@flanksource/clicky-ui 0.3.48 → 0.3.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/DataTable.cjs +18 -8
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +4 -0
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +18 -8
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/TaskManager.cjs +183 -159
- package/dist/data/TaskManager.cjs.map +1 -1
- package/dist/data/TaskManager.d.ts +3 -1
- package/dist/data/TaskManager.d.ts.map +1 -1
- package/dist/data/TaskManager.js +185 -161
- package/dist/data/TaskManager.js.map +1 -1
- package/dist/data/TaskManagerButton.cjs +1 -0
- package/dist/data/TaskManagerButton.cjs.map +1 -1
- package/dist/data/TaskManagerButton.js +1 -0
- package/dist/data/TaskManagerButton.js.map +1 -1
- package/dist/data/TaskProgress.cjs +13 -7
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts +3 -1
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +13 -7
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/traces/ProcessTraceTree.cjs +93 -0
- package/dist/data/traces/ProcessTraceTree.cjs.map +1 -0
- package/dist/data/traces/ProcessTraceTree.d.ts +24 -0
- package/dist/data/traces/ProcessTraceTree.d.ts.map +1 -0
- package/dist/data/traces/ProcessTraceTree.js +93 -0
- package/dist/data/traces/ProcessTraceTree.js.map +1 -0
- package/dist/data/traces/Sparkline.cjs +23 -0
- package/dist/data/traces/Sparkline.cjs.map +1 -0
- package/dist/data/traces/Sparkline.d.ts +13 -0
- package/dist/data/traces/Sparkline.d.ts.map +1 -0
- package/dist/data/traces/Sparkline.js +23 -0
- package/dist/data/traces/Sparkline.js.map +1 -0
- package/dist/data/traces/SqlTraceTable.cjs +104 -0
- package/dist/data/traces/SqlTraceTable.cjs.map +1 -0
- package/dist/data/traces/SqlTraceTable.d.ts +19 -0
- package/dist/data/traces/SqlTraceTable.d.ts.map +1 -0
- package/dist/data/traces/SqlTraceTable.js +104 -0
- package/dist/data/traces/SqlTraceTable.js.map +1 -0
- package/dist/data/traces/TerminalCastPlayer.cjs +162 -0
- package/dist/data/traces/TerminalCastPlayer.cjs.map +1 -0
- package/dist/data/traces/TerminalCastPlayer.js +162 -0
- package/dist/data/traces/TerminalCastPlayer.js.map +1 -0
- package/dist/data/traces/TraceHarView.cjs +15 -0
- package/dist/data/traces/TraceHarView.cjs.map +1 -0
- package/dist/data/traces/TraceHarView.js +15 -0
- package/dist/data/traces/TraceHarView.js.map +1 -0
- package/dist/data/traces/TraceView.cjs +54 -0
- package/dist/data/traces/TraceView.cjs.map +1 -0
- package/dist/data/traces/TraceView.d.ts +18 -0
- package/dist/data/traces/TraceView.d.ts.map +1 -0
- package/dist/data/traces/TraceView.js +54 -0
- package/dist/data/traces/TraceView.js.map +1 -0
- package/dist/data/traces/cast.cjs +81 -0
- package/dist/data/traces/cast.cjs.map +1 -0
- package/dist/data/traces/cast.js +81 -0
- package/dist/data/traces/cast.js.map +1 -0
- package/dist/data/traces/har-adapter.cjs +83 -0
- package/dist/data/traces/har-adapter.cjs.map +1 -0
- package/dist/data/traces/har-adapter.js +83 -0
- package/dist/data/traces/har-adapter.js.map +1 -0
- package/dist/data/traces/index.d.ts +12 -0
- package/dist/data/traces/index.d.ts.map +1 -0
- package/dist/data/traces/process-tree.cjs +53 -0
- package/dist/data/traces/process-tree.cjs.map +1 -0
- package/dist/data/traces/process-tree.d.ts +21 -0
- package/dist/data/traces/process-tree.d.ts.map +1 -0
- package/dist/data/traces/process-tree.js +53 -0
- package/dist/data/traces/process-tree.js.map +1 -0
- package/dist/data/traces/sql-trace.cjs +39 -0
- package/dist/data/traces/sql-trace.cjs.map +1 -0
- package/dist/data/traces/sql-trace.d.ts +31 -0
- package/dist/data/traces/sql-trace.d.ts.map +1 -0
- package/dist/data/traces/sql-trace.js +39 -0
- package/dist/data/traces/sql-trace.js.map +1 -0
- package/dist/data/traces/terminal-screen.cjs +270 -0
- package/dist/data/traces/terminal-screen.cjs.map +1 -0
- package/dist/data/traces/terminal-screen.js +270 -0
- package/dist/data/traces/terminal-screen.js.map +1 -0
- package/dist/data/traces/terminal-timeline.cjs +48 -0
- package/dist/data/traces/terminal-timeline.cjs.map +1 -0
- package/dist/data/traces/terminal-timeline.js +48 -0
- package/dist/data/traces/terminal-timeline.js.map +1 -0
- package/dist/data/traces/types.d.ts +1 -3
- package/dist/data/traces/types.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.cjs.map +1 -1
- package/dist/data/version-info.js +3 -3
- package/dist/data/version-info.js.map +1 -1
- package/dist/data.cjs +22 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +1 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +22 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +22 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskManagerButton.js","sources":["../../src/data/TaskManagerButton.tsx"],"sourcesContent":["import { resourceSummary, taskTransportConnected, type ResourceSummary } from \"./task-resource-summary\";\nimport { useResourceClock } from \"../hooks/use-resource-clock\";\nimport { Button } from \"../components/button\";\nimport { UiActivity, UiListChecks, UiMemoryStick } from \"../icons\";\nimport { useTaskRun, useTaskRuns } from \"../hooks/use-task-run\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { formatBytes } from \"../lib/format\";\nimport { TaskManager } from \"./TaskManager\";\nimport { taskStatusIcon } from \"./task-status\";\n\nexport interface TaskManagerButtonProps {\n basePath?: string;\n tasksHref?: string;\n latest?: number;\n onNavigate?: (href: string) => void;\n panel?: boolean;\n kind?: string;\n labels?: Record<string, string>;\n selectedId?: string;\n onSelectRun?: (id: string | null) => void;\n}\n\nexport function TaskManagerButton({\n basePath,\n tasksHref = \"/tasks\",\n latest = 5,\n onNavigate,\n panel,\n kind,\n labels,\n selectedId,\n onSelectRun,\n}: TaskManagerButtonProps) {\n const { runs, status: runsStatus } = useTaskRuns({ basePath, kind, labels });\n const activeRuns = runs.filter((run) => run.status === \"running\" || run.status === \"pending\");\n const { snapshots, status: snapshotStatus } = useTaskRun({\n ...(basePath ? { basePath } : {}),\n ids: activeRuns.map((run) => run.id),\n enabled: activeRuns.length > 0,\n });\n const now = useResourceClock(activeRuns.length > 0);\n const resources = resourceSummary(snapshots, { now, connected: taskTransportConnected(runsStatus) && taskTransportConnected(snapshotStatus) });\n const trigger = <TaskTrigger active={activeRuns.length} {...(activeRuns.length ? { resources } : {})} />;\n\n return panel ? (\n <TaskPanelDropdown\n {...(basePath ? { basePath } : {})}\n {...(kind ? { kind } : {})}\n {...(labels ? { labels } : {})}\n {...(onSelectRun ? { onSelectRun } : {})}\n {...(selectedId ? { selectedId } : {})}\n trigger={trigger}\n />\n ) : (\n <RecentTasksDropdown\n latest={latest}\n {...(onNavigate ? { onNavigate } : {})}\n runs={runs}\n tasksHref={tasksHref}\n trigger={trigger}\n />\n );\n}\n\nfunction TaskPanelDropdown({ basePath, kind, labels, onSelectRun, selectedId, trigger }: TaskManagerButtonProps & { trigger: React.ReactNode }) {\n return (\n <DropdownMenu\n align=\"right\"\n header={<span className=\"text-xs font-semibold\">Activity</span>}\n menuClassName=\"w-[min(42rem,calc(100vw-1rem))] max-w-none p-0\"\n menuLabel=\"Task activity\"\n trigger={trigger}\n >\n {() => (\n <div className=\"max-h-[min(42rem,calc(100vh-5rem))] overflow-auto p-3\">\n <TaskManager\n {...(basePath ? { basePath } : {})}\n {...(kind ? { kind } : {})}\n {...(labels ? { labels } : {})}\n {...(onSelectRun ? { onSelectRun } : {})}\n {...(selectedId ? { selectedId } : {})}\n />\n </div>\n )}\n </DropdownMenu>\n );\n}\n\ntype TaskRuns = ReturnType<typeof useTaskRuns>[\"runs\"];\n\nfunction RecentTasksDropdown({\n latest,\n onNavigate,\n runs,\n tasksHref,\n trigger,\n}: {\n latest: number;\n onNavigate?: (href: string) => void;\n runs: TaskRuns;\n tasksHref: string;\n trigger: React.ReactNode;\n}) {\n const navigate = (href: string) => {\n if (onNavigate) onNavigate(href);\n else window.location.assign(href);\n };\n const items: DropdownMenuItem[] = runs.slice(0, latest).map((run) => ({\n label: (\n <span className=\"flex min-w-0 items-center justify-between gap-3\">\n <span className=\"truncate\">{run.name}</span>\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">{run.status}</span>\n </span>\n ),\n icon: taskStatusIcon(run.status),\n onSelect: () => navigate(run.href ?? `${tasksHref}/${encodeURIComponent(run.id)}`),\n }));\n if (items.length === 0) {\n items.push({ label: \"No tasks yet\", disabled: true, onSelect: () => {} });\n }\n\n return (\n <DropdownMenu\n items={items}\n align=\"right\"\n menuLabel=\"Recent tasks\"\n trigger={trigger}\n footer={(\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" className=\"w-full justify-start\" onClick={() => navigate(tasksHref)}>\n View all tasks\n </Button>\n )}\n />\n );\n}\n\nfunction TaskTrigger({ active, resources }: { active: number; resources?: ResourceSummary }) {\n const label = `Tasks (${active} active)`;\n return (\n <Button type=\"button\" variant=\"ghost\" size={resources ? \"sm\" : \"icon\"} aria-label={label} title={label} className=\"relative gap-1.5\">\n <UiListChecks className={active > 0 ? \"animate-pulse\" : undefined} />\n {resources?.state === \"unavailable\" ? <span className=\"text-xs text-muted-foreground\">Resources unavailable</span> : resources ? (\n <span className=\"flex items-center gap-1.5 text-xs\" title={`Sampled ${new Date(resources.sampledAt).toLocaleTimeString()}; CPU 100% equals one core`}>\n <UiActivity /><span>{resources.cpu.toFixed(1)}%</span>\n <UiMemoryStick /><span>{formatBytes(resources.rss)}</span>\n {resources.state === \"stale\" && <span className=\"text-muted-foreground\">Stale</span>}\n </span>\n ) : null}\n </Button>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAsBO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,EAAE,MAAM,QAAQ,WAAA,IAAe,YAAY,EAAE,UAAU,MAAM,QAAQ;AAC3E,QAAM,aAAa,KAAK,OAAO,CAAC,QAAQ,IAAI,WAAW,aAAa,IAAI,WAAW,SAAS;AAC5F,QAAM,EAAE,WAAW,QAAQ,eAAA,IAAmB,WAAW;AAAA,IACvD,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,IAC9B,KAAK,WAAW,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,IACnC,SAAS,WAAW,SAAS;AAAA,EAAA,CAC9B;AACD,QAAM,MAAM,iBAAiB,WAAW,SAAS,CAAC;AAClD,QAAM,YAAY,gBAAgB,WAAW,EAAE,KAAK,WAAW,uBAAuB,UAAU,KAAK,uBAAuB,cAAc,EAAA,CAAG;AAC7I,QAAM,UAAU,oBAAC,aAAA,EAAY,QAAQ,WAAW,QAAS,GAAI,WAAW,SAAS,EAAE,UAAA,IAAc,CAAA,EAAC,CAAI;AAEtG,SAAO,QACL;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,MAC9B,GAAI,OAAO,EAAE,KAAA,IAAS,CAAA;AAAA,MACtB,GAAI,SAAS,EAAE,OAAA,IAAW,CAAA;AAAA,MAC1B,GAAI,cAAc,EAAE,YAAA,IAAgB,CAAA;AAAA,MACpC,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MACnC;AAAA,IAAA;AAAA,EAAA,IAGF;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,kBAAkB,EAAE,UAAU,MAAM,QAAQ,aAAa,YAAY,WAAkE;AAC9I,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAQ,oBAAC,QAAA,EAAK,WAAU,yBAAwB,UAAA,YAAQ;AAAA,MACxD,eAAc;AAAA,MACd,WAAU;AAAA,MACV;AAAA,MAEC,UAAA,MACC,oBAAC,OAAA,EAAI,WAAU,yDACb,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"TaskManagerButton.js","sources":["../../src/data/TaskManagerButton.tsx"],"sourcesContent":["import { resourceSummary, taskTransportConnected, type ResourceSummary } from \"./task-resource-summary\";\nimport { useResourceClock } from \"../hooks/use-resource-clock\";\nimport { Button } from \"../components/button\";\nimport { UiActivity, UiListChecks, UiMemoryStick } from \"../icons\";\nimport { useTaskRun, useTaskRuns } from \"../hooks/use-task-run\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { formatBytes } from \"../lib/format\";\nimport { TaskManager } from \"./TaskManager\";\nimport { taskStatusIcon } from \"./task-status\";\n\nexport interface TaskManagerButtonProps {\n basePath?: string;\n tasksHref?: string;\n latest?: number;\n onNavigate?: (href: string) => void;\n panel?: boolean;\n kind?: string;\n labels?: Record<string, string>;\n selectedId?: string;\n onSelectRun?: (id: string | null) => void;\n}\n\nexport function TaskManagerButton({\n basePath,\n tasksHref = \"/tasks\",\n latest = 5,\n onNavigate,\n panel,\n kind,\n labels,\n selectedId,\n onSelectRun,\n}: TaskManagerButtonProps) {\n const { runs, status: runsStatus } = useTaskRuns({ basePath, kind, labels });\n const activeRuns = runs.filter((run) => run.status === \"running\" || run.status === \"pending\");\n const { snapshots, status: snapshotStatus } = useTaskRun({\n ...(basePath ? { basePath } : {}),\n ids: activeRuns.map((run) => run.id),\n enabled: activeRuns.length > 0,\n });\n const now = useResourceClock(activeRuns.length > 0);\n const resources = resourceSummary(snapshots, { now, connected: taskTransportConnected(runsStatus) && taskTransportConnected(snapshotStatus) });\n const trigger = <TaskTrigger active={activeRuns.length} {...(activeRuns.length ? { resources } : {})} />;\n\n return panel ? (\n <TaskPanelDropdown\n {...(basePath ? { basePath } : {})}\n {...(kind ? { kind } : {})}\n {...(labels ? { labels } : {})}\n {...(onSelectRun ? { onSelectRun } : {})}\n {...(selectedId ? { selectedId } : {})}\n trigger={trigger}\n />\n ) : (\n <RecentTasksDropdown\n latest={latest}\n {...(onNavigate ? { onNavigate } : {})}\n runs={runs}\n tasksHref={tasksHref}\n trigger={trigger}\n />\n );\n}\n\nfunction TaskPanelDropdown({ basePath, kind, labels, onSelectRun, selectedId, trigger }: TaskManagerButtonProps & { trigger: React.ReactNode }) {\n return (\n <DropdownMenu\n align=\"right\"\n header={<span className=\"text-xs font-semibold\">Activity</span>}\n menuClassName=\"w-[min(42rem,calc(100vw-1rem))] max-w-none p-0\"\n menuLabel=\"Task activity\"\n trigger={trigger}\n >\n {() => (\n <div className=\"max-h-[min(42rem,calc(100vh-5rem))] overflow-auto p-3\">\n <TaskManager\n compact\n {...(basePath ? { basePath } : {})}\n {...(kind ? { kind } : {})}\n {...(labels ? { labels } : {})}\n {...(onSelectRun ? { onSelectRun } : {})}\n {...(selectedId ? { selectedId } : {})}\n />\n </div>\n )}\n </DropdownMenu>\n );\n}\n\ntype TaskRuns = ReturnType<typeof useTaskRuns>[\"runs\"];\n\nfunction RecentTasksDropdown({\n latest,\n onNavigate,\n runs,\n tasksHref,\n trigger,\n}: {\n latest: number;\n onNavigate?: (href: string) => void;\n runs: TaskRuns;\n tasksHref: string;\n trigger: React.ReactNode;\n}) {\n const navigate = (href: string) => {\n if (onNavigate) onNavigate(href);\n else window.location.assign(href);\n };\n const items: DropdownMenuItem[] = runs.slice(0, latest).map((run) => ({\n label: (\n <span className=\"flex min-w-0 items-center justify-between gap-3\">\n <span className=\"truncate\">{run.name}</span>\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">{run.status}</span>\n </span>\n ),\n icon: taskStatusIcon(run.status),\n onSelect: () => navigate(run.href ?? `${tasksHref}/${encodeURIComponent(run.id)}`),\n }));\n if (items.length === 0) {\n items.push({ label: \"No tasks yet\", disabled: true, onSelect: () => {} });\n }\n\n return (\n <DropdownMenu\n items={items}\n align=\"right\"\n menuLabel=\"Recent tasks\"\n trigger={trigger}\n footer={(\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" className=\"w-full justify-start\" onClick={() => navigate(tasksHref)}>\n View all tasks\n </Button>\n )}\n />\n );\n}\n\nfunction TaskTrigger({ active, resources }: { active: number; resources?: ResourceSummary }) {\n const label = `Tasks (${active} active)`;\n return (\n <Button type=\"button\" variant=\"ghost\" size={resources ? \"sm\" : \"icon\"} aria-label={label} title={label} className=\"relative gap-1.5\">\n <UiListChecks className={active > 0 ? \"animate-pulse\" : undefined} />\n {resources?.state === \"unavailable\" ? <span className=\"text-xs text-muted-foreground\">Resources unavailable</span> : resources ? (\n <span className=\"flex items-center gap-1.5 text-xs\" title={`Sampled ${new Date(resources.sampledAt).toLocaleTimeString()}; CPU 100% equals one core`}>\n <UiActivity /><span>{resources.cpu.toFixed(1)}%</span>\n <UiMemoryStick /><span>{formatBytes(resources.rss)}</span>\n {resources.state === \"stale\" && <span className=\"text-muted-foreground\">Stale</span>}\n </span>\n ) : null}\n </Button>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAsBO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,EAAE,MAAM,QAAQ,WAAA,IAAe,YAAY,EAAE,UAAU,MAAM,QAAQ;AAC3E,QAAM,aAAa,KAAK,OAAO,CAAC,QAAQ,IAAI,WAAW,aAAa,IAAI,WAAW,SAAS;AAC5F,QAAM,EAAE,WAAW,QAAQ,eAAA,IAAmB,WAAW;AAAA,IACvD,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,IAC9B,KAAK,WAAW,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,IACnC,SAAS,WAAW,SAAS;AAAA,EAAA,CAC9B;AACD,QAAM,MAAM,iBAAiB,WAAW,SAAS,CAAC;AAClD,QAAM,YAAY,gBAAgB,WAAW,EAAE,KAAK,WAAW,uBAAuB,UAAU,KAAK,uBAAuB,cAAc,EAAA,CAAG;AAC7I,QAAM,UAAU,oBAAC,aAAA,EAAY,QAAQ,WAAW,QAAS,GAAI,WAAW,SAAS,EAAE,UAAA,IAAc,CAAA,EAAC,CAAI;AAEtG,SAAO,QACL;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,MAC9B,GAAI,OAAO,EAAE,KAAA,IAAS,CAAA;AAAA,MACtB,GAAI,SAAS,EAAE,OAAA,IAAW,CAAA;AAAA,MAC1B,GAAI,cAAc,EAAE,YAAA,IAAgB,CAAA;AAAA,MACpC,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MACnC;AAAA,IAAA;AAAA,EAAA,IAGF;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,kBAAkB,EAAE,UAAU,MAAM,QAAQ,aAAa,YAAY,WAAkE;AAC9I,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAQ,oBAAC,QAAA,EAAK,WAAU,yBAAwB,UAAA,YAAQ;AAAA,MACxD,eAAc;AAAA,MACd,WAAU;AAAA,MACV;AAAA,MAEC,UAAA,MACC,oBAAC,OAAA,EAAI,WAAU,yDACb,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAO;AAAA,UACN,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,UAC9B,GAAI,OAAO,EAAE,KAAA,IAAS,CAAA;AAAA,UACtB,GAAI,SAAS,EAAE,OAAA,IAAW,CAAA;AAAA,UAC1B,GAAI,cAAc,EAAE,YAAA,IAAgB,CAAA;AAAA,UACpC,GAAI,aAAa,EAAE,eAAe,CAAA;AAAA,QAAC;AAAA,MAAA,EACtC,CACF;AAAA,IAAA;AAAA,EAAA;AAIR;AAIA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,WAAW,CAAC,SAAiB;AACjC,QAAI,uBAAuB,IAAI;AAAA,QAC1B,QAAO,SAAS,OAAO,IAAI;AAAA,EAClC;AACA,QAAM,QAA4B,KAAK,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,SAAS;AAAA,IACpE,OACE,qBAAC,QAAA,EAAK,WAAU,mDACd,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,YAAY,UAAA,IAAI,MAAK;AAAA,MACrC,oBAAC,QAAA,EAAK,WAAU,8CAA8C,cAAI,OAAA,CAAO;AAAA,IAAA,GAC3E;AAAA,IAEF,MAAM,eAAe,IAAI,MAAM;AAAA,IAC/B,UAAU,MAAM,SAAS,IAAI,QAAQ,GAAG,SAAS,IAAI,mBAAmB,IAAI,EAAE,CAAC,EAAE;AAAA,EAAA,EACjF;AACF,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,KAAK,EAAE,OAAO,gBAAgB,UAAU,MAAM,UAAU,MAAM;AAAA,IAAC,GAAG;AAAA,EAC1E;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAM;AAAA,MACN,WAAU;AAAA,MACV;AAAA,MACA,QACE,oBAAC,QAAA,EAAO,MAAK,UAAS,SAAQ,SAAQ,MAAK,MAAK,WAAU,wBAAuB,SAAS,MAAM,SAAS,SAAS,GAAG,UAAA,iBAAA,CAErH;AAAA,IAAA;AAAA,EAAA;AAIR;AAEA,SAAS,YAAY,EAAE,QAAQ,aAA8D;AAC3F,QAAM,QAAQ,UAAU,MAAM;AAC9B,SACE,qBAAC,QAAA,EAAO,MAAK,UAAS,SAAQ,SAAQ,MAAM,YAAY,OAAO,QAAQ,cAAY,OAAO,OAAO,OAAO,WAAU,oBAChH,UAAA;AAAA,IAAA,oBAAC,cAAA,EAAa,WAAW,SAAS,IAAI,kBAAkB,QAAW;AAAA,KAClE,uCAAW,WAAU,gBAAgB,oBAAC,UAAK,WAAU,iCAAgC,UAAA,wBAAA,CAAqB,IAAU,YACnH,qBAAC,UAAK,WAAU,qCAAoC,OAAO,WAAW,IAAI,KAAK,UAAU,SAAS,EAAE,mBAAA,CAAoB,8BACtH,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW;AAAA,2BAAG,QAAA,EAAM,UAAA;AAAA,QAAA,UAAU,IAAI,QAAQ,CAAC;AAAA,QAAE;AAAA,MAAA,GAAC;AAAA,0BAC9C,eAAA,EAAc;AAAA,MAAE,oBAAC,QAAA,EAAM,UAAA,YAAY,UAAU,GAAG,GAAE;AAAA,MAClD,UAAU,UAAU,+BAAY,QAAA,EAAK,WAAU,yBAAwB,UAAA,QAAA,CAAK;AAAA,IAAA,EAAA,CAC/E,IACE;AAAA,EAAA,GACN;AAEJ;"}
|
|
@@ -32,6 +32,7 @@ function TaskProgress({
|
|
|
32
32
|
snapshots,
|
|
33
33
|
title,
|
|
34
34
|
compact,
|
|
35
|
+
initialShowAllTasks,
|
|
35
36
|
className,
|
|
36
37
|
onControl,
|
|
37
38
|
onTaskControl,
|
|
@@ -56,6 +57,7 @@ function TaskProgress({
|
|
|
56
57
|
group: g,
|
|
57
58
|
tasks: tasks.filter((t) => g.groupId ? t.groupId === g.groupId : t.group === g.id),
|
|
58
59
|
compact,
|
|
60
|
+
initialShowAllTasks,
|
|
59
61
|
...onControl ? { onControl } : {},
|
|
60
62
|
...onTaskControl ? { onTaskControl } : {},
|
|
61
63
|
...metricsBaseUrl ? { metricsBaseUrl } : {},
|
|
@@ -71,6 +73,7 @@ function TaskGroupCard({
|
|
|
71
73
|
group: g,
|
|
72
74
|
tasks,
|
|
73
75
|
compact,
|
|
76
|
+
initialShowAllTasks,
|
|
74
77
|
onControl,
|
|
75
78
|
onTaskControl,
|
|
76
79
|
metricsBaseUrl,
|
|
@@ -78,7 +81,7 @@ function TaskGroupCard({
|
|
|
78
81
|
extraTabs,
|
|
79
82
|
headerExtra
|
|
80
83
|
}) {
|
|
81
|
-
const [showAll, setShowAll] = react.useState(false);
|
|
84
|
+
const [showAll, setShowAll] = react.useState(initialShowAllTasks ?? false);
|
|
82
85
|
const { state: copyState, copy } = clipboard.useCopyFlash();
|
|
83
86
|
const work = taskWorkProgress.taskWorkProgress(g);
|
|
84
87
|
const total = g.work ? work.total : g.total ?? tasks.length;
|
|
@@ -110,8 +113,8 @@ function TaskGroupCard({
|
|
|
110
113
|
onSelect: () => copy(taskCopy.taskGroupErrors(g, tasks))
|
|
111
114
|
}
|
|
112
115
|
];
|
|
113
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("rounded-lg border bg-card", compact ? "p-
|
|
114
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
116
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("rounded-lg border bg-card", compact ? "p-2" : "p-4"), children: [
|
|
117
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex items-center justify-between gap-3", compact ? "mb-2" : "mb-3"), children: [
|
|
115
118
|
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "flex min-w-0 items-center gap-1.5 text-sm font-semibold", children: [
|
|
116
119
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
117
120
|
Icon.Icon,
|
|
@@ -155,7 +158,7 @@ function TaskGroupCard({
|
|
|
155
158
|
onControl && /* @__PURE__ */ jsxRuntime.jsx(TaskControls, { target: g, onControl })
|
|
156
159
|
] })
|
|
157
160
|
] }),
|
|
158
|
-
total > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsxRuntime.jsx(ProgressBar.ProgressBar, { segments: taskStatus.taskSegments(counts), total, height: "h-1.5" }) }),
|
|
161
|
+
total > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: compact ? "mb-2" : "mb-3", children: /* @__PURE__ */ jsxRuntime.jsx(ProgressBar.ProgressBar, { segments: taskStatus.taskSegments(counts), total, height: "h-1.5" }) }),
|
|
159
162
|
taskProcessDetails.isTaskProcessDetails(g.details) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
160
163
|
TaskProcessDetails.TaskProcessDetailsView,
|
|
161
164
|
{
|
|
@@ -169,7 +172,7 @@ function TaskGroupCard({
|
|
|
169
172
|
"button",
|
|
170
173
|
{
|
|
171
174
|
type: "button",
|
|
172
|
-
className: "border-b
|
|
175
|
+
className: utils.cn("border-b text-xs text-muted-foreground hover:text-foreground", compact ? "py-1" : "py-1.5"),
|
|
173
176
|
onClick: () => setShowAll((v) => !v),
|
|
174
177
|
children: showAll ? "▲ collapse" : `... ${(collapseCompleted ? hiddenCompleted : 0) + (collapsePending ? hiddenPending : 0)} more tasks`
|
|
175
178
|
}
|
|
@@ -179,6 +182,7 @@ function TaskGroupCard({
|
|
|
179
182
|
{
|
|
180
183
|
task: t,
|
|
181
184
|
group: g,
|
|
185
|
+
compact,
|
|
182
186
|
...onTaskControl ? { onTaskControl } : {},
|
|
183
187
|
...metricsBaseUrl ? { metricsBaseUrl } : {},
|
|
184
188
|
...connectionStatus ? { connectionStatus } : {},
|
|
@@ -192,6 +196,7 @@ function TaskGroupCard({
|
|
|
192
196
|
function TaskRow({
|
|
193
197
|
task: t,
|
|
194
198
|
group,
|
|
199
|
+
compact,
|
|
195
200
|
onTaskControl,
|
|
196
201
|
metricsBaseUrl,
|
|
197
202
|
connectionStatus,
|
|
@@ -215,7 +220,8 @@ function TaskRow({
|
|
|
215
220
|
"div",
|
|
216
221
|
{
|
|
217
222
|
className: utils.cn(
|
|
218
|
-
"group flex items-start
|
|
223
|
+
"group flex items-start border-b last:border-0",
|
|
224
|
+
compact ? "gap-2 py-1" : "gap-3 py-2",
|
|
219
225
|
expandable && "-mx-1 cursor-pointer rounded px-1 hover:bg-muted/50"
|
|
220
226
|
),
|
|
221
227
|
onClick: expandable ? () => setExpanded((v) => !v) : void 0,
|
|
@@ -224,7 +230,7 @@ function TaskRow({
|
|
|
224
230
|
Icon.Icon,
|
|
225
231
|
{
|
|
226
232
|
icon: taskStatus.taskStatusIcon(t.status),
|
|
227
|
-
className: utils.cn(taskStatus.taskStatusColor(t.status), "mt-0.5 text-lg", t.status === "running" && "animate-spin")
|
|
233
|
+
className: utils.cn(taskStatus.taskStatusColor(t.status), "mt-0.5", compact ? "text-base" : "text-lg", t.status === "running" && "animate-spin")
|
|
228
234
|
}
|
|
229
235
|
),
|
|
230
236
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskProgress.cjs","sources":["../../src/data/TaskProgress.tsx"],"sourcesContent":["import { taskWorkProgress } from \"./task-work-progress\";\nimport { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { CopyButton } from \"../components/CopyButton\";\nimport { SplitButton } from \"../components/SplitButton\";\nimport { useCopyFlash } from \"../components/clipboard\";\nimport { UiCheck, UiCopy, UiJson, UiPlay, UiRefresh, UiRestart, UiStop, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { Icon } from \"./Icon\";\nimport { ProgressBar } from \"./ProgressBar\";\nimport { TaskProcessDetailsView } from \"./TaskProcessDetails\";\nimport { TaskExecDetailsView } from \"./TaskExecDetails\";\nimport type { LogEntry, TaskControlAction, TaskSnapshot } from \"./TaskSnapshot\";\nimport { type TaskHeaderExtra, TaskMetadataChips } from \"./TaskHeaderExtras\";\nimport { type TaskExtraTabs, TaskStreamTabs } from \"./TaskStreamTabs\";\nimport {\n isFailedOrWarn,\n taskGroupErrorCount,\n taskGroupErrors,\n taskGroupJson,\n taskGroupMarkdown,\n taskMarkdown,\n} from \"./task-copy\";\nimport { isTaskExecDetails } from \"./task-exec-details\";\nimport { isTaskProcessDetails } from \"./task-process-details\";\nimport {\n bucketTasks,\n logLevelColor,\n taskSegments,\n taskStatusBg,\n taskStatusColor,\n taskStatusIcon,\n} from \"./task-status\";\n\n// TaskProgress renders one or more clicky task runs (groups) and their child\n// tasks: a segmented progress bar per group plus collapsible per-task rows with\n// status icon, duration, error, and expandable logs. Presentational only —\n// callers feed it snapshots from useTaskRun (SSE) or any other source.\n\nconst MAX_COMPLETED = 5;\nconst MAX_PENDING = 3;\n\nexport interface TaskProgressProps {\n snapshots: TaskSnapshot[];\n title?: string;\n /** Tighter spacing for embedding in a panel. */\n compact?: boolean;\n className?: string;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n /**\n * Contributes host-owned output panes alongside a task's own stdout/stderr —\n * an agent's session transcript, say, which this module has no way to fetch.\n */\n extraTabs?: TaskExtraTabs;\n /**\n * Replaces the content beside a task's name in its header row. Returning null\n * for a task falls back to the default, which chips the scalar values of its\n * process metadata.\n */\n headerExtra?: TaskHeaderExtra;\n}\n\nexport function TaskProgress({\n snapshots,\n title,\n compact,\n className,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: TaskProgressProps) {\n const groups = snapshots.filter((s) => s.type === \"group\");\n const tasks = snapshots.filter((s) => s.type === \"task\");\n\n if (groups.length === 0) {\n return (\n <div className={cn(\"text-sm text-muted-foreground\", className)}>\n {title ? `${title}: ` : \"\"}No tasks yet.\n </div>\n );\n }\n\n return (\n <div className={cn(compact ? \"space-y-2\" : \"space-y-3\", className)}>\n {title && <h2 className=\"text-sm font-semibold\">{title}</h2>}\n {groups.map((g) => (\n <TaskGroupCard\n key={g.groupId || g.id}\n group={g}\n tasks={tasks.filter((t) => g.groupId ? t.groupId === g.groupId : t.group === g.id)}\n compact={compact}\n {...(onControl ? { onControl } : {})}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskGroupCard({\n group: g,\n tasks,\n compact,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: {\n group: TaskSnapshot;\n tasks: TaskSnapshot[];\n compact: boolean | undefined;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const [showAll, setShowAll] = useState(false);\n const { state: copyState, copy } = useCopyFlash();\n const work = taskWorkProgress(g);\n const total = g.work ? work.total : g.total ?? tasks.length;\n const counts = g.work ? work.counts : bucketTasks(tasks);\n const done = counts.ok + counts.warn + counts.fail + counts.canceled;\n const progress = g.work ? work.label : total > 0 ? `${done}/${total}` : \"\";\n\n const running = tasks.filter((t) => t.status === \"running\");\n const pending = tasks.filter((t) => t.status === \"pending\");\n const completed = tasks.filter((t) => t.status !== \"running\" && t.status !== \"pending\");\n const alwaysShow = completed.filter(isFailedOrWarn);\n const collapsible = completed.filter((t) => !isFailedOrWarn(t));\n\n const hiddenCompleted = collapsible.length - MAX_COMPLETED;\n const collapseCompleted = !showAll && hiddenCompleted > 0;\n const visibleSuccess = collapseCompleted ? collapsible.slice(-MAX_COMPLETED) : collapsible;\n\n const hiddenPending = pending.length - MAX_PENDING;\n const collapsePending = !showAll && hiddenPending > 0;\n const visiblePending = collapsePending ? pending.slice(0, MAX_PENDING) : pending;\n\n const isTerminal = g.status !== \"running\" && g.status !== \"pending\";\n\n const copyItems: DropdownMenuItem[] = [\n {\n label: \"Copy as JSON\",\n icon: UiJson,\n onSelect: () => copy(taskGroupJson(g, tasks)),\n },\n {\n label: \"Copy errors only\",\n icon: UiWarningTriangle,\n disabled: taskGroupErrorCount(tasks) === 0,\n onSelect: () => copy(taskGroupErrors(g, tasks)),\n },\n ];\n\n return (\n <div className={cn(\"rounded-lg border bg-card\", compact ? \"p-3\" : \"p-4\")}>\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <h3 className=\"flex min-w-0 items-center gap-1.5 text-sm font-semibold\">\n <Icon\n icon={taskStatusIcon(g.status)}\n className={cn(\n \"shrink-0\",\n taskStatusColor(g.status),\n g.status === \"running\" && \"animate-spin\",\n )}\n />\n <span className=\"truncate\">{g.name}</span>\n {progress && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{progress}</span>\n )}\n {g.kind && (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0 text-[10px] text-muted-foreground\">\n {g.kind}\n </span>\n )}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n {isTerminal && (\n <span\n className={cn(\n \"rounded-full px-2 py-0.5 text-xs\",\n taskStatusColor(g.status),\n taskStatusBg(g.status),\n )}\n >\n {g.status}\n </span>\n )}\n <SplitButton\n label={copyState === \"copied\" ? \"Copied\" : copyState === \"error\" ? \"Copy failed\" : \"Copy\"}\n icon={copyState === \"copied\" ? UiCheck : UiCopy}\n variant=\"ghost\"\n size=\"sm\"\n title=\"More copy options\"\n onClick={() => copy(taskGroupMarkdown(g, tasks))}\n items={copyItems}\n />\n {onControl && <TaskControls target={g} onControl={onControl} />}\n </div>\n </div>\n\n {total > 0 && (\n <div className=\"mb-3\">\n <ProgressBar segments={taskSegments(counts)} total={total} height=\"h-1.5\" />\n </div>\n )}\n\n {isTaskProcessDetails(g.details) && (\n <TaskProcessDetailsView\n details={g.details}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n\n {!isTaskProcessDetails(g.details) && isTaskExecDetails(g.details) && (\n <TaskExecDetailsView details={g.details} />\n )}\n\n {hiddenCompleted > 0 || hiddenPending > 0 ? (\n <button\n type=\"button\"\n className=\"border-b py-1.5 text-xs text-muted-foreground hover:text-foreground\"\n onClick={() => setShowAll((v) => !v)}\n >\n {showAll\n ? \"▲ collapse\"\n : `... ${(collapseCompleted ? hiddenCompleted : 0) + (collapsePending ? hiddenPending : 0)} more tasks`}\n </button>\n ) : null}\n\n {[...visibleSuccess, ...alwaysShow, ...running, ...visiblePending].map((t) => (\n <TaskRow\n key={t.id}\n task={t}\n group={g}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskRow({\n task: t,\n group,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs: contributeTabs,\n headerExtra,\n}: {\n task: TaskSnapshot;\n group: TaskSnapshot;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n}) {\n const [expanded, setExpanded] = useState(false);\n const logs: LogEntry[] = t.logs ?? [];\n const hasLogs = logs.length > 0;\n const extraTabs = contributeTabs?.(t, group) ?? [];\n // A host that has nothing to add for this task returns null, and the default\n // metadata chips take over — so enriching one kind of task never costs the\n // rest their header.\n const header = headerExtra?.(t, group) ?? <TaskMetadataChips task={t} />;\n const hasOutput = !!t.stdout || !!t.stderr || extraTabs.length > 0;\n const execDetails = isTaskExecDetails(t.details) ? t.details : undefined;\n const processDetails = isTaskProcessDetails(t.details) ? t.details : undefined;\n const expandable = hasLogs || hasOutput || execDetails !== undefined || processDetails !== undefined;\n // Promote the latest warning message inline so a `warning` row shows its\n // reason without expanding. Suppressed when an error is already shown.\n const latestWarn = t.error ? undefined : logs.filter((l) => l.level === \"warn\").at(-1);\n // Bounded per-task progress (e.g. records emitted in a phase): render an x/y\n // count, a percentage, and a thin bar while the task runs.\n const done = t.progress ?? 0;\n // Only surface bounded progress once work has actually started — an untouched\n // task should not render a \"0/100 · 0%\" placeholder.\n const hasProgress = typeof t.maxValue === \"number\" && t.maxValue > 0 && done > 0;\n const pct = hasProgress ? Math.round((done / (t.maxValue as number)) * 100) : 0;\n\n return (\n <div\n className={cn(\n \"group flex items-start gap-3 border-b py-2 last:border-0\",\n expandable && \"-mx-1 cursor-pointer rounded px-1 hover:bg-muted/50\",\n )}\n onClick={expandable ? () => setExpanded((v) => !v) : undefined}\n >\n <Icon\n icon={taskStatusIcon(t.status)}\n className={cn(taskStatusColor(t.status), \"mt-0.5 text-lg\", t.status === \"running\" && \"animate-spin\")}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-sm font-medium\">\n <span className=\"truncate\">{t.name}</span>\n {t.error && <span className=\"truncate text-xs font-normal text-red-500\">{t.error}</span>}\n {latestWarn && (\n <span className={cn(\"truncate text-xs font-normal\", logLevelColor(\"warn\"))}>\n {latestWarn.message}\n </span>\n )}\n {expandable && (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 text-[10px] font-medium text-muted-foreground\">\n {logs.length + (t.stdout ? 1 : 0) + (t.stderr ? 1 : 0) + (execDetails || processDetails ? 1 : 0)}\n </span>\n )}\n </span>\n {header}\n <div className=\"flex shrink-0 items-center gap-1\">\n {t.duration && <span className=\"text-xs text-muted-foreground\">{t.duration}</span>}\n <CopyButton\n value={() => taskMarkdown(t)}\n label={`Copy ${t.name}`}\n className=\"opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100\"\n iconClassName=\"text-xs\"\n />\n {onTaskControl && (\n <TaskControls\n target={t}\n labelSuffix={t.name}\n stopPropagation\n onControl={(action) => onTaskControl(action, t, group)}\n />\n )}\n </div>\n </div>\n {(t.description || hasProgress) && (\n <div className=\"mt-0.5 flex items-center gap-2\">\n {t.description && (\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">{t.description}</span>\n )}\n {hasProgress && (\n <span className=\"shrink-0 text-xs tabular-nums text-muted-foreground\">\n {done}/{t.maxValue} · {pct}%\n </span>\n )}\n </div>\n )}\n {hasProgress && t.status === \"running\" && (\n <div className=\"mt-1\">\n <ProgressBar\n segments={[{ count: done, color: \"bg-blue-500\", label: \"done\" }]}\n total={t.maxValue as number}\n height=\"h-1\"\n />\n </div>\n )}\n {expanded && execDetails && <TaskExecDetailsView details={execDetails} />}\n {expanded && processDetails && (\n <TaskProcessDetailsView\n details={processDetails}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n {expanded && hasLogs && (\n <div className=\"mt-1 ml-1 max-h-48 space-y-0.5 overflow-y-auto border-l-2 pl-2\">\n {logs.map((l, i) => (\n <div key={i} className={cn(\"text-xs\", logLevelColor(l.level))}>\n <span className=\"mr-1 font-mono text-muted-foreground\">{l.level.substring(0, 3)}</span>\n {l.message}\n </div>\n ))}\n </div>\n )}\n {expanded && <TaskStreamTabs task={t} {...(extraTabs.length > 0 ? { extraTabs } : {})} />}\n </div>\n </div>\n );\n}\n\nfunction TaskControls({\n target,\n onControl,\n labelSuffix,\n stopPropagation,\n}: {\n target: TaskSnapshot;\n onControl: (action: TaskControlAction, target: TaskSnapshot) => void | Promise<void>;\n labelSuffix?: string;\n stopPropagation?: boolean;\n}) {\n const [busy, setBusy] = useState<TaskControlAction | null>(null);\n const [error, setError] = useState(\"\");\n const icons: Record<TaskControlAction, typeof UiPlay> = {\n start: UiPlay,\n stop: UiStop,\n restart: UiRestart,\n drain: UiStop,\n retry: UiRefresh,\n };\n const invoke = async (action: TaskControlAction) => {\n setBusy(action);\n setError(\"\");\n try {\n await onControl(action, target);\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : `Failed to ${action} task`);\n } finally {\n setBusy(null);\n }\n };\n return (\n <>\n {(target.controls ?? []).map((action) => {\n const ControlIcon = icons[action];\n const actionLabel = action === \"drain\" ? \"Stop after current\" : action[0]?.toUpperCase() + action.slice(1);\n const label = labelSuffix ? `${actionLabel} ${labelSuffix}` : actionLabel;\n return (\n <Button\n key={action}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={label}\n title={label}\n disabled={busy !== null}\n onClick={(event) => {\n if (stopPropagation) event.stopPropagation();\n void invoke(action);\n }}\n >\n <ControlIcon />\n </Button>\n );\n })}\n {error && <span role=\"alert\" className=\"text-xs text-red-600\">{error}</span>}\n </>\n );\n}\n"],"names":["cn","jsxs","jsx","useState","useCopyFlash","taskWorkProgress","bucketTasks","isFailedOrWarn","UiJson","taskGroupJson","UiWarningTriangle","taskGroupErrorCount","taskGroupErrors","Icon","taskStatusIcon","taskStatusColor","taskStatusBg","SplitButton","UiCheck","UiCopy","taskGroupMarkdown","ProgressBar","taskSegments","isTaskProcessDetails","TaskProcessDetailsView","isTaskExecDetails","TaskExecDetailsView","TaskMetadataChips","logLevelColor","CopyButton","taskMarkdown","TaskStreamTabs","UiPlay","UiStop","UiRestart","UiRefresh","Fragment","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TaskProgress.cjs","sources":["../../src/data/TaskProgress.tsx"],"sourcesContent":["import { taskWorkProgress } from \"./task-work-progress\";\nimport { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { CopyButton } from \"../components/CopyButton\";\nimport { SplitButton } from \"../components/SplitButton\";\nimport { useCopyFlash } from \"../components/clipboard\";\nimport { UiCheck, UiCopy, UiJson, UiPlay, UiRefresh, UiRestart, UiStop, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { Icon } from \"./Icon\";\nimport { ProgressBar } from \"./ProgressBar\";\nimport { TaskProcessDetailsView } from \"./TaskProcessDetails\";\nimport { TaskExecDetailsView } from \"./TaskExecDetails\";\nimport type { LogEntry, TaskControlAction, TaskSnapshot } from \"./TaskSnapshot\";\nimport { type TaskHeaderExtra, TaskMetadataChips } from \"./TaskHeaderExtras\";\nimport { type TaskExtraTabs, TaskStreamTabs } from \"./TaskStreamTabs\";\nimport {\n isFailedOrWarn,\n taskGroupErrorCount,\n taskGroupErrors,\n taskGroupJson,\n taskGroupMarkdown,\n taskMarkdown,\n} from \"./task-copy\";\nimport { isTaskExecDetails } from \"./task-exec-details\";\nimport { isTaskProcessDetails } from \"./task-process-details\";\nimport {\n bucketTasks,\n logLevelColor,\n taskSegments,\n taskStatusBg,\n taskStatusColor,\n taskStatusIcon,\n} from \"./task-status\";\n\n// TaskProgress renders one or more clicky task runs (groups) and their child\n// tasks: a segmented progress bar per group plus collapsible per-task rows with\n// status icon, duration, error, and expandable logs. Presentational only —\n// callers feed it snapshots from useTaskRun (SSE) or any other source.\n\nconst MAX_COMPLETED = 5;\nconst MAX_PENDING = 3;\n\nexport interface TaskProgressProps {\n snapshots: TaskSnapshot[];\n title?: string;\n /** Tighter spacing for embedding in a panel. */\n compact?: boolean;\n /** Show every child task when the group first opens. */\n initialShowAllTasks?: boolean;\n className?: string;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n /**\n * Contributes host-owned output panes alongside a task's own stdout/stderr —\n * an agent's session transcript, say, which this module has no way to fetch.\n */\n extraTabs?: TaskExtraTabs;\n /**\n * Replaces the content beside a task's name in its header row. Returning null\n * for a task falls back to the default, which chips the scalar values of its\n * process metadata.\n */\n headerExtra?: TaskHeaderExtra;\n}\n\nexport function TaskProgress({\n snapshots,\n title,\n compact,\n initialShowAllTasks,\n className,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: TaskProgressProps) {\n const groups = snapshots.filter((s) => s.type === \"group\");\n const tasks = snapshots.filter((s) => s.type === \"task\");\n\n if (groups.length === 0) {\n return (\n <div className={cn(\"text-sm text-muted-foreground\", className)}>\n {title ? `${title}: ` : \"\"}No tasks yet.\n </div>\n );\n }\n\n return (\n <div className={cn(compact ? \"space-y-2\" : \"space-y-3\", className)}>\n {title && <h2 className=\"text-sm font-semibold\">{title}</h2>}\n {groups.map((g) => (\n <TaskGroupCard\n key={g.groupId || g.id}\n group={g}\n tasks={tasks.filter((t) => g.groupId ? t.groupId === g.groupId : t.group === g.id)}\n compact={compact}\n initialShowAllTasks={initialShowAllTasks}\n {...(onControl ? { onControl } : {})}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskGroupCard({\n group: g,\n tasks,\n compact,\n initialShowAllTasks,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: {\n group: TaskSnapshot;\n tasks: TaskSnapshot[];\n compact: boolean | undefined;\n initialShowAllTasks: boolean | undefined;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const [showAll, setShowAll] = useState(initialShowAllTasks ?? false);\n const { state: copyState, copy } = useCopyFlash();\n const work = taskWorkProgress(g);\n const total = g.work ? work.total : g.total ?? tasks.length;\n const counts = g.work ? work.counts : bucketTasks(tasks);\n const done = counts.ok + counts.warn + counts.fail + counts.canceled;\n const progress = g.work ? work.label : total > 0 ? `${done}/${total}` : \"\";\n\n const running = tasks.filter((t) => t.status === \"running\");\n const pending = tasks.filter((t) => t.status === \"pending\");\n const completed = tasks.filter((t) => t.status !== \"running\" && t.status !== \"pending\");\n const alwaysShow = completed.filter(isFailedOrWarn);\n const collapsible = completed.filter((t) => !isFailedOrWarn(t));\n\n const hiddenCompleted = collapsible.length - MAX_COMPLETED;\n const collapseCompleted = !showAll && hiddenCompleted > 0;\n const visibleSuccess = collapseCompleted ? collapsible.slice(-MAX_COMPLETED) : collapsible;\n\n const hiddenPending = pending.length - MAX_PENDING;\n const collapsePending = !showAll && hiddenPending > 0;\n const visiblePending = collapsePending ? pending.slice(0, MAX_PENDING) : pending;\n\n const isTerminal = g.status !== \"running\" && g.status !== \"pending\";\n\n const copyItems: DropdownMenuItem[] = [\n {\n label: \"Copy as JSON\",\n icon: UiJson,\n onSelect: () => copy(taskGroupJson(g, tasks)),\n },\n {\n label: \"Copy errors only\",\n icon: UiWarningTriangle,\n disabled: taskGroupErrorCount(tasks) === 0,\n onSelect: () => copy(taskGroupErrors(g, tasks)),\n },\n ];\n\n return (\n <div className={cn(\"rounded-lg border bg-card\", compact ? \"p-2\" : \"p-4\")}>\n <div className={cn(\"flex items-center justify-between gap-3\", compact ? \"mb-2\" : \"mb-3\")}>\n <h3 className=\"flex min-w-0 items-center gap-1.5 text-sm font-semibold\">\n <Icon\n icon={taskStatusIcon(g.status)}\n className={cn(\n \"shrink-0\",\n taskStatusColor(g.status),\n g.status === \"running\" && \"animate-spin\",\n )}\n />\n <span className=\"truncate\">{g.name}</span>\n {progress && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{progress}</span>\n )}\n {g.kind && (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0 text-[10px] text-muted-foreground\">\n {g.kind}\n </span>\n )}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n {isTerminal && (\n <span\n className={cn(\n \"rounded-full px-2 py-0.5 text-xs\",\n taskStatusColor(g.status),\n taskStatusBg(g.status),\n )}\n >\n {g.status}\n </span>\n )}\n <SplitButton\n label={copyState === \"copied\" ? \"Copied\" : copyState === \"error\" ? \"Copy failed\" : \"Copy\"}\n icon={copyState === \"copied\" ? UiCheck : UiCopy}\n variant=\"ghost\"\n size=\"sm\"\n title=\"More copy options\"\n onClick={() => copy(taskGroupMarkdown(g, tasks))}\n items={copyItems}\n />\n {onControl && <TaskControls target={g} onControl={onControl} />}\n </div>\n </div>\n\n {total > 0 && (\n <div className={compact ? \"mb-2\" : \"mb-3\"}>\n <ProgressBar segments={taskSegments(counts)} total={total} height=\"h-1.5\" />\n </div>\n )}\n\n {isTaskProcessDetails(g.details) && (\n <TaskProcessDetailsView\n details={g.details}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n\n {!isTaskProcessDetails(g.details) && isTaskExecDetails(g.details) && (\n <TaskExecDetailsView details={g.details} />\n )}\n\n {hiddenCompleted > 0 || hiddenPending > 0 ? (\n <button\n type=\"button\"\n className={cn(\"border-b text-xs text-muted-foreground hover:text-foreground\", compact ? \"py-1\" : \"py-1.5\")}\n onClick={() => setShowAll((v) => !v)}\n >\n {showAll\n ? \"▲ collapse\"\n : `... ${(collapseCompleted ? hiddenCompleted : 0) + (collapsePending ? hiddenPending : 0)} more tasks`}\n </button>\n ) : null}\n\n {[...visibleSuccess, ...alwaysShow, ...running, ...visiblePending].map((t) => (\n <TaskRow\n key={t.id}\n task={t}\n group={g}\n compact={compact}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskRow({\n task: t,\n group,\n compact,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs: contributeTabs,\n headerExtra,\n}: {\n task: TaskSnapshot;\n group: TaskSnapshot;\n compact: boolean | undefined;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n}) {\n const [expanded, setExpanded] = useState(false);\n const logs: LogEntry[] = t.logs ?? [];\n const hasLogs = logs.length > 0;\n const extraTabs = contributeTabs?.(t, group) ?? [];\n // A host that has nothing to add for this task returns null, and the default\n // metadata chips take over — so enriching one kind of task never costs the\n // rest their header.\n const header = headerExtra?.(t, group) ?? <TaskMetadataChips task={t} />;\n const hasOutput = !!t.stdout || !!t.stderr || extraTabs.length > 0;\n const execDetails = isTaskExecDetails(t.details) ? t.details : undefined;\n const processDetails = isTaskProcessDetails(t.details) ? t.details : undefined;\n const expandable = hasLogs || hasOutput || execDetails !== undefined || processDetails !== undefined;\n // Promote the latest warning message inline so a `warning` row shows its\n // reason without expanding. Suppressed when an error is already shown.\n const latestWarn = t.error ? undefined : logs.filter((l) => l.level === \"warn\").at(-1);\n // Bounded per-task progress (e.g. records emitted in a phase): render an x/y\n // count, a percentage, and a thin bar while the task runs.\n const done = t.progress ?? 0;\n // Only surface bounded progress once work has actually started — an untouched\n // task should not render a \"0/100 · 0%\" placeholder.\n const hasProgress = typeof t.maxValue === \"number\" && t.maxValue > 0 && done > 0;\n const pct = hasProgress ? Math.round((done / (t.maxValue as number)) * 100) : 0;\n\n return (\n <div\n className={cn(\n \"group flex items-start border-b last:border-0\",\n compact ? \"gap-2 py-1\" : \"gap-3 py-2\",\n expandable && \"-mx-1 cursor-pointer rounded px-1 hover:bg-muted/50\",\n )}\n onClick={expandable ? () => setExpanded((v) => !v) : undefined}\n >\n <Icon\n icon={taskStatusIcon(t.status)}\n className={cn(taskStatusColor(t.status), \"mt-0.5\", compact ? \"text-base\" : \"text-lg\", t.status === \"running\" && \"animate-spin\")}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-sm font-medium\">\n <span className=\"truncate\">{t.name}</span>\n {t.error && <span className=\"truncate text-xs font-normal text-red-500\">{t.error}</span>}\n {latestWarn && (\n <span className={cn(\"truncate text-xs font-normal\", logLevelColor(\"warn\"))}>\n {latestWarn.message}\n </span>\n )}\n {expandable && (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 text-[10px] font-medium text-muted-foreground\">\n {logs.length + (t.stdout ? 1 : 0) + (t.stderr ? 1 : 0) + (execDetails || processDetails ? 1 : 0)}\n </span>\n )}\n </span>\n {header}\n <div className=\"flex shrink-0 items-center gap-1\">\n {t.duration && <span className=\"text-xs text-muted-foreground\">{t.duration}</span>}\n <CopyButton\n value={() => taskMarkdown(t)}\n label={`Copy ${t.name}`}\n className=\"opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100\"\n iconClassName=\"text-xs\"\n />\n {onTaskControl && (\n <TaskControls\n target={t}\n labelSuffix={t.name}\n stopPropagation\n onControl={(action) => onTaskControl(action, t, group)}\n />\n )}\n </div>\n </div>\n {(t.description || hasProgress) && (\n <div className=\"mt-0.5 flex items-center gap-2\">\n {t.description && (\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">{t.description}</span>\n )}\n {hasProgress && (\n <span className=\"shrink-0 text-xs tabular-nums text-muted-foreground\">\n {done}/{t.maxValue} · {pct}%\n </span>\n )}\n </div>\n )}\n {hasProgress && t.status === \"running\" && (\n <div className=\"mt-1\">\n <ProgressBar\n segments={[{ count: done, color: \"bg-blue-500\", label: \"done\" }]}\n total={t.maxValue as number}\n height=\"h-1\"\n />\n </div>\n )}\n {expanded && execDetails && <TaskExecDetailsView details={execDetails} />}\n {expanded && processDetails && (\n <TaskProcessDetailsView\n details={processDetails}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n {expanded && hasLogs && (\n <div className=\"mt-1 ml-1 max-h-48 space-y-0.5 overflow-y-auto border-l-2 pl-2\">\n {logs.map((l, i) => (\n <div key={i} className={cn(\"text-xs\", logLevelColor(l.level))}>\n <span className=\"mr-1 font-mono text-muted-foreground\">{l.level.substring(0, 3)}</span>\n {l.message}\n </div>\n ))}\n </div>\n )}\n {expanded && <TaskStreamTabs task={t} {...(extraTabs.length > 0 ? { extraTabs } : {})} />}\n </div>\n </div>\n );\n}\n\nfunction TaskControls({\n target,\n onControl,\n labelSuffix,\n stopPropagation,\n}: {\n target: TaskSnapshot;\n onControl: (action: TaskControlAction, target: TaskSnapshot) => void | Promise<void>;\n labelSuffix?: string;\n stopPropagation?: boolean;\n}) {\n const [busy, setBusy] = useState<TaskControlAction | null>(null);\n const [error, setError] = useState(\"\");\n const icons: Record<TaskControlAction, typeof UiPlay> = {\n start: UiPlay,\n stop: UiStop,\n restart: UiRestart,\n drain: UiStop,\n retry: UiRefresh,\n };\n const invoke = async (action: TaskControlAction) => {\n setBusy(action);\n setError(\"\");\n try {\n await onControl(action, target);\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : `Failed to ${action} task`);\n } finally {\n setBusy(null);\n }\n };\n return (\n <>\n {(target.controls ?? []).map((action) => {\n const ControlIcon = icons[action];\n const actionLabel = action === \"drain\" ? \"Stop after current\" : action[0]?.toUpperCase() + action.slice(1);\n const label = labelSuffix ? `${actionLabel} ${labelSuffix}` : actionLabel;\n return (\n <Button\n key={action}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={label}\n title={label}\n disabled={busy !== null}\n onClick={(event) => {\n if (stopPropagation) event.stopPropagation();\n void invoke(action);\n }}\n >\n <ControlIcon />\n </Button>\n );\n })}\n {error && <span role=\"alert\" className=\"text-xs text-red-600\">{error}</span>}\n </>\n );\n}\n"],"names":["cn","jsxs","jsx","useState","useCopyFlash","taskWorkProgress","bucketTasks","isFailedOrWarn","UiJson","taskGroupJson","UiWarningTriangle","taskGroupErrorCount","taskGroupErrors","Icon","taskStatusIcon","taskStatusColor","taskStatusBg","SplitButton","UiCheck","UiCopy","taskGroupMarkdown","ProgressBar","taskSegments","isTaskProcessDetails","TaskProcessDetailsView","isTaskExecDetails","TaskExecDetailsView","TaskMetadataChips","logLevelColor","CopyButton","taskMarkdown","TaskStreamTabs","UiPlay","UiStop","UiRestart","UiRefresh","Fragment","Button"],"mappings":"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"}
|
|
@@ -6,6 +6,8 @@ export interface TaskProgressProps {
|
|
|
6
6
|
title?: string;
|
|
7
7
|
/** Tighter spacing for embedding in a panel. */
|
|
8
8
|
compact?: boolean;
|
|
9
|
+
/** Show every child task when the group first opens. */
|
|
10
|
+
initialShowAllTasks?: boolean;
|
|
9
11
|
className?: string;
|
|
10
12
|
onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;
|
|
11
13
|
onTaskControl?: (action: TaskControlAction, task: TaskSnapshot, group: TaskSnapshot) => void | Promise<void>;
|
|
@@ -23,5 +25,5 @@ export interface TaskProgressProps {
|
|
|
23
25
|
*/
|
|
24
26
|
headerExtra?: TaskHeaderExtra;
|
|
25
27
|
}
|
|
26
|
-
export declare function TaskProgress({ snapshots, title, compact, className, onControl, onTaskControl, metricsBaseUrl, connectionStatus, extraTabs, headerExtra, }: TaskProgressProps): import("react").JSX.Element;
|
|
28
|
+
export declare function TaskProgress({ snapshots, title, compact, initialShowAllTasks, className, onControl, onTaskControl, metricsBaseUrl, connectionStatus, extraTabs, headerExtra, }: TaskProgressProps): import("react").JSX.Element;
|
|
27
29
|
//# sourceMappingURL=TaskProgress.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskProgress.d.ts","sourceRoot":"","sources":["../../src/data/TaskProgress.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAY,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,KAAK,eAAe,EAAqB,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AA4BtE,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,aAAa,CAAC,EAAE,CACd,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,YAAY,KAChB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,WAAW,GACZ,EAAE,iBAAiB,+
|
|
1
|
+
{"version":3,"file":"TaskProgress.d.ts","sourceRoot":"","sources":["../../src/data/TaskProgress.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAY,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,KAAK,eAAe,EAAqB,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AA4BtE,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,aAAa,CAAC,EAAE,CACd,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,YAAY,KAChB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,KAAK,EACL,OAAO,EACP,mBAAmB,EACnB,SAAS,EACT,SAAS,EACT,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,WAAW,GACZ,EAAE,iBAAiB,+BAgCnB"}
|
|
@@ -30,6 +30,7 @@ function TaskProgress({
|
|
|
30
30
|
snapshots,
|
|
31
31
|
title,
|
|
32
32
|
compact,
|
|
33
|
+
initialShowAllTasks,
|
|
33
34
|
className,
|
|
34
35
|
onControl,
|
|
35
36
|
onTaskControl,
|
|
@@ -54,6 +55,7 @@ function TaskProgress({
|
|
|
54
55
|
group: g,
|
|
55
56
|
tasks: tasks.filter((t) => g.groupId ? t.groupId === g.groupId : t.group === g.id),
|
|
56
57
|
compact,
|
|
58
|
+
initialShowAllTasks,
|
|
57
59
|
...onControl ? { onControl } : {},
|
|
58
60
|
...onTaskControl ? { onTaskControl } : {},
|
|
59
61
|
...metricsBaseUrl ? { metricsBaseUrl } : {},
|
|
@@ -69,6 +71,7 @@ function TaskGroupCard({
|
|
|
69
71
|
group: g,
|
|
70
72
|
tasks,
|
|
71
73
|
compact,
|
|
74
|
+
initialShowAllTasks,
|
|
72
75
|
onControl,
|
|
73
76
|
onTaskControl,
|
|
74
77
|
metricsBaseUrl,
|
|
@@ -76,7 +79,7 @@ function TaskGroupCard({
|
|
|
76
79
|
extraTabs,
|
|
77
80
|
headerExtra
|
|
78
81
|
}) {
|
|
79
|
-
const [showAll, setShowAll] = useState(false);
|
|
82
|
+
const [showAll, setShowAll] = useState(initialShowAllTasks ?? false);
|
|
80
83
|
const { state: copyState, copy } = useCopyFlash();
|
|
81
84
|
const work = taskWorkProgress(g);
|
|
82
85
|
const total = g.work ? work.total : g.total ?? tasks.length;
|
|
@@ -108,8 +111,8 @@ function TaskGroupCard({
|
|
|
108
111
|
onSelect: () => copy(taskGroupErrors(g, tasks))
|
|
109
112
|
}
|
|
110
113
|
];
|
|
111
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("rounded-lg border bg-card", compact ? "p-
|
|
112
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
114
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("rounded-lg border bg-card", compact ? "p-2" : "p-4"), children: [
|
|
115
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-3", compact ? "mb-2" : "mb-3"), children: [
|
|
113
116
|
/* @__PURE__ */ jsxs("h3", { className: "flex min-w-0 items-center gap-1.5 text-sm font-semibold", children: [
|
|
114
117
|
/* @__PURE__ */ jsx(
|
|
115
118
|
Icon,
|
|
@@ -153,7 +156,7 @@ function TaskGroupCard({
|
|
|
153
156
|
onControl && /* @__PURE__ */ jsx(TaskControls, { target: g, onControl })
|
|
154
157
|
] })
|
|
155
158
|
] }),
|
|
156
|
-
total > 0 && /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(ProgressBar, { segments: taskSegments(counts), total, height: "h-1.5" }) }),
|
|
159
|
+
total > 0 && /* @__PURE__ */ jsx("div", { className: compact ? "mb-2" : "mb-3", children: /* @__PURE__ */ jsx(ProgressBar, { segments: taskSegments(counts), total, height: "h-1.5" }) }),
|
|
157
160
|
isTaskProcessDetails(g.details) && /* @__PURE__ */ jsx(
|
|
158
161
|
TaskProcessDetailsView,
|
|
159
162
|
{
|
|
@@ -167,7 +170,7 @@ function TaskGroupCard({
|
|
|
167
170
|
"button",
|
|
168
171
|
{
|
|
169
172
|
type: "button",
|
|
170
|
-
className: "border-b
|
|
173
|
+
className: cn("border-b text-xs text-muted-foreground hover:text-foreground", compact ? "py-1" : "py-1.5"),
|
|
171
174
|
onClick: () => setShowAll((v) => !v),
|
|
172
175
|
children: showAll ? "▲ collapse" : `... ${(collapseCompleted ? hiddenCompleted : 0) + (collapsePending ? hiddenPending : 0)} more tasks`
|
|
173
176
|
}
|
|
@@ -177,6 +180,7 @@ function TaskGroupCard({
|
|
|
177
180
|
{
|
|
178
181
|
task: t,
|
|
179
182
|
group: g,
|
|
183
|
+
compact,
|
|
180
184
|
...onTaskControl ? { onTaskControl } : {},
|
|
181
185
|
...metricsBaseUrl ? { metricsBaseUrl } : {},
|
|
182
186
|
...connectionStatus ? { connectionStatus } : {},
|
|
@@ -190,6 +194,7 @@ function TaskGroupCard({
|
|
|
190
194
|
function TaskRow({
|
|
191
195
|
task: t,
|
|
192
196
|
group,
|
|
197
|
+
compact,
|
|
193
198
|
onTaskControl,
|
|
194
199
|
metricsBaseUrl,
|
|
195
200
|
connectionStatus,
|
|
@@ -213,7 +218,8 @@ function TaskRow({
|
|
|
213
218
|
"div",
|
|
214
219
|
{
|
|
215
220
|
className: cn(
|
|
216
|
-
"group flex items-start
|
|
221
|
+
"group flex items-start border-b last:border-0",
|
|
222
|
+
compact ? "gap-2 py-1" : "gap-3 py-2",
|
|
217
223
|
expandable && "-mx-1 cursor-pointer rounded px-1 hover:bg-muted/50"
|
|
218
224
|
),
|
|
219
225
|
onClick: expandable ? () => setExpanded((v) => !v) : void 0,
|
|
@@ -222,7 +228,7 @@ function TaskRow({
|
|
|
222
228
|
Icon,
|
|
223
229
|
{
|
|
224
230
|
icon: taskStatusIcon(t.status),
|
|
225
|
-
className: cn(taskStatusColor(t.status), "mt-0.5 text-lg", t.status === "running" && "animate-spin")
|
|
231
|
+
className: cn(taskStatusColor(t.status), "mt-0.5", compact ? "text-base" : "text-lg", t.status === "running" && "animate-spin")
|
|
226
232
|
}
|
|
227
233
|
),
|
|
228
234
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskProgress.js","sources":["../../src/data/TaskProgress.tsx"],"sourcesContent":["import { taskWorkProgress } from \"./task-work-progress\";\nimport { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { CopyButton } from \"../components/CopyButton\";\nimport { SplitButton } from \"../components/SplitButton\";\nimport { useCopyFlash } from \"../components/clipboard\";\nimport { UiCheck, UiCopy, UiJson, UiPlay, UiRefresh, UiRestart, UiStop, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { Icon } from \"./Icon\";\nimport { ProgressBar } from \"./ProgressBar\";\nimport { TaskProcessDetailsView } from \"./TaskProcessDetails\";\nimport { TaskExecDetailsView } from \"./TaskExecDetails\";\nimport type { LogEntry, TaskControlAction, TaskSnapshot } from \"./TaskSnapshot\";\nimport { type TaskHeaderExtra, TaskMetadataChips } from \"./TaskHeaderExtras\";\nimport { type TaskExtraTabs, TaskStreamTabs } from \"./TaskStreamTabs\";\nimport {\n isFailedOrWarn,\n taskGroupErrorCount,\n taskGroupErrors,\n taskGroupJson,\n taskGroupMarkdown,\n taskMarkdown,\n} from \"./task-copy\";\nimport { isTaskExecDetails } from \"./task-exec-details\";\nimport { isTaskProcessDetails } from \"./task-process-details\";\nimport {\n bucketTasks,\n logLevelColor,\n taskSegments,\n taskStatusBg,\n taskStatusColor,\n taskStatusIcon,\n} from \"./task-status\";\n\n// TaskProgress renders one or more clicky task runs (groups) and their child\n// tasks: a segmented progress bar per group plus collapsible per-task rows with\n// status icon, duration, error, and expandable logs. Presentational only —\n// callers feed it snapshots from useTaskRun (SSE) or any other source.\n\nconst MAX_COMPLETED = 5;\nconst MAX_PENDING = 3;\n\nexport interface TaskProgressProps {\n snapshots: TaskSnapshot[];\n title?: string;\n /** Tighter spacing for embedding in a panel. */\n compact?: boolean;\n className?: string;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n /**\n * Contributes host-owned output panes alongside a task's own stdout/stderr —\n * an agent's session transcript, say, which this module has no way to fetch.\n */\n extraTabs?: TaskExtraTabs;\n /**\n * Replaces the content beside a task's name in its header row. Returning null\n * for a task falls back to the default, which chips the scalar values of its\n * process metadata.\n */\n headerExtra?: TaskHeaderExtra;\n}\n\nexport function TaskProgress({\n snapshots,\n title,\n compact,\n className,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: TaskProgressProps) {\n const groups = snapshots.filter((s) => s.type === \"group\");\n const tasks = snapshots.filter((s) => s.type === \"task\");\n\n if (groups.length === 0) {\n return (\n <div className={cn(\"text-sm text-muted-foreground\", className)}>\n {title ? `${title}: ` : \"\"}No tasks yet.\n </div>\n );\n }\n\n return (\n <div className={cn(compact ? \"space-y-2\" : \"space-y-3\", className)}>\n {title && <h2 className=\"text-sm font-semibold\">{title}</h2>}\n {groups.map((g) => (\n <TaskGroupCard\n key={g.groupId || g.id}\n group={g}\n tasks={tasks.filter((t) => g.groupId ? t.groupId === g.groupId : t.group === g.id)}\n compact={compact}\n {...(onControl ? { onControl } : {})}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskGroupCard({\n group: g,\n tasks,\n compact,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: {\n group: TaskSnapshot;\n tasks: TaskSnapshot[];\n compact: boolean | undefined;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const [showAll, setShowAll] = useState(false);\n const { state: copyState, copy } = useCopyFlash();\n const work = taskWorkProgress(g);\n const total = g.work ? work.total : g.total ?? tasks.length;\n const counts = g.work ? work.counts : bucketTasks(tasks);\n const done = counts.ok + counts.warn + counts.fail + counts.canceled;\n const progress = g.work ? work.label : total > 0 ? `${done}/${total}` : \"\";\n\n const running = tasks.filter((t) => t.status === \"running\");\n const pending = tasks.filter((t) => t.status === \"pending\");\n const completed = tasks.filter((t) => t.status !== \"running\" && t.status !== \"pending\");\n const alwaysShow = completed.filter(isFailedOrWarn);\n const collapsible = completed.filter((t) => !isFailedOrWarn(t));\n\n const hiddenCompleted = collapsible.length - MAX_COMPLETED;\n const collapseCompleted = !showAll && hiddenCompleted > 0;\n const visibleSuccess = collapseCompleted ? collapsible.slice(-MAX_COMPLETED) : collapsible;\n\n const hiddenPending = pending.length - MAX_PENDING;\n const collapsePending = !showAll && hiddenPending > 0;\n const visiblePending = collapsePending ? pending.slice(0, MAX_PENDING) : pending;\n\n const isTerminal = g.status !== \"running\" && g.status !== \"pending\";\n\n const copyItems: DropdownMenuItem[] = [\n {\n label: \"Copy as JSON\",\n icon: UiJson,\n onSelect: () => copy(taskGroupJson(g, tasks)),\n },\n {\n label: \"Copy errors only\",\n icon: UiWarningTriangle,\n disabled: taskGroupErrorCount(tasks) === 0,\n onSelect: () => copy(taskGroupErrors(g, tasks)),\n },\n ];\n\n return (\n <div className={cn(\"rounded-lg border bg-card\", compact ? \"p-3\" : \"p-4\")}>\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <h3 className=\"flex min-w-0 items-center gap-1.5 text-sm font-semibold\">\n <Icon\n icon={taskStatusIcon(g.status)}\n className={cn(\n \"shrink-0\",\n taskStatusColor(g.status),\n g.status === \"running\" && \"animate-spin\",\n )}\n />\n <span className=\"truncate\">{g.name}</span>\n {progress && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{progress}</span>\n )}\n {g.kind && (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0 text-[10px] text-muted-foreground\">\n {g.kind}\n </span>\n )}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n {isTerminal && (\n <span\n className={cn(\n \"rounded-full px-2 py-0.5 text-xs\",\n taskStatusColor(g.status),\n taskStatusBg(g.status),\n )}\n >\n {g.status}\n </span>\n )}\n <SplitButton\n label={copyState === \"copied\" ? \"Copied\" : copyState === \"error\" ? \"Copy failed\" : \"Copy\"}\n icon={copyState === \"copied\" ? UiCheck : UiCopy}\n variant=\"ghost\"\n size=\"sm\"\n title=\"More copy options\"\n onClick={() => copy(taskGroupMarkdown(g, tasks))}\n items={copyItems}\n />\n {onControl && <TaskControls target={g} onControl={onControl} />}\n </div>\n </div>\n\n {total > 0 && (\n <div className=\"mb-3\">\n <ProgressBar segments={taskSegments(counts)} total={total} height=\"h-1.5\" />\n </div>\n )}\n\n {isTaskProcessDetails(g.details) && (\n <TaskProcessDetailsView\n details={g.details}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n\n {!isTaskProcessDetails(g.details) && isTaskExecDetails(g.details) && (\n <TaskExecDetailsView details={g.details} />\n )}\n\n {hiddenCompleted > 0 || hiddenPending > 0 ? (\n <button\n type=\"button\"\n className=\"border-b py-1.5 text-xs text-muted-foreground hover:text-foreground\"\n onClick={() => setShowAll((v) => !v)}\n >\n {showAll\n ? \"▲ collapse\"\n : `... ${(collapseCompleted ? hiddenCompleted : 0) + (collapsePending ? hiddenPending : 0)} more tasks`}\n </button>\n ) : null}\n\n {[...visibleSuccess, ...alwaysShow, ...running, ...visiblePending].map((t) => (\n <TaskRow\n key={t.id}\n task={t}\n group={g}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskRow({\n task: t,\n group,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs: contributeTabs,\n headerExtra,\n}: {\n task: TaskSnapshot;\n group: TaskSnapshot;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n}) {\n const [expanded, setExpanded] = useState(false);\n const logs: LogEntry[] = t.logs ?? [];\n const hasLogs = logs.length > 0;\n const extraTabs = contributeTabs?.(t, group) ?? [];\n // A host that has nothing to add for this task returns null, and the default\n // metadata chips take over — so enriching one kind of task never costs the\n // rest their header.\n const header = headerExtra?.(t, group) ?? <TaskMetadataChips task={t} />;\n const hasOutput = !!t.stdout || !!t.stderr || extraTabs.length > 0;\n const execDetails = isTaskExecDetails(t.details) ? t.details : undefined;\n const processDetails = isTaskProcessDetails(t.details) ? t.details : undefined;\n const expandable = hasLogs || hasOutput || execDetails !== undefined || processDetails !== undefined;\n // Promote the latest warning message inline so a `warning` row shows its\n // reason without expanding. Suppressed when an error is already shown.\n const latestWarn = t.error ? undefined : logs.filter((l) => l.level === \"warn\").at(-1);\n // Bounded per-task progress (e.g. records emitted in a phase): render an x/y\n // count, a percentage, and a thin bar while the task runs.\n const done = t.progress ?? 0;\n // Only surface bounded progress once work has actually started — an untouched\n // task should not render a \"0/100 · 0%\" placeholder.\n const hasProgress = typeof t.maxValue === \"number\" && t.maxValue > 0 && done > 0;\n const pct = hasProgress ? Math.round((done / (t.maxValue as number)) * 100) : 0;\n\n return (\n <div\n className={cn(\n \"group flex items-start gap-3 border-b py-2 last:border-0\",\n expandable && \"-mx-1 cursor-pointer rounded px-1 hover:bg-muted/50\",\n )}\n onClick={expandable ? () => setExpanded((v) => !v) : undefined}\n >\n <Icon\n icon={taskStatusIcon(t.status)}\n className={cn(taskStatusColor(t.status), \"mt-0.5 text-lg\", t.status === \"running\" && \"animate-spin\")}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-sm font-medium\">\n <span className=\"truncate\">{t.name}</span>\n {t.error && <span className=\"truncate text-xs font-normal text-red-500\">{t.error}</span>}\n {latestWarn && (\n <span className={cn(\"truncate text-xs font-normal\", logLevelColor(\"warn\"))}>\n {latestWarn.message}\n </span>\n )}\n {expandable && (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 text-[10px] font-medium text-muted-foreground\">\n {logs.length + (t.stdout ? 1 : 0) + (t.stderr ? 1 : 0) + (execDetails || processDetails ? 1 : 0)}\n </span>\n )}\n </span>\n {header}\n <div className=\"flex shrink-0 items-center gap-1\">\n {t.duration && <span className=\"text-xs text-muted-foreground\">{t.duration}</span>}\n <CopyButton\n value={() => taskMarkdown(t)}\n label={`Copy ${t.name}`}\n className=\"opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100\"\n iconClassName=\"text-xs\"\n />\n {onTaskControl && (\n <TaskControls\n target={t}\n labelSuffix={t.name}\n stopPropagation\n onControl={(action) => onTaskControl(action, t, group)}\n />\n )}\n </div>\n </div>\n {(t.description || hasProgress) && (\n <div className=\"mt-0.5 flex items-center gap-2\">\n {t.description && (\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">{t.description}</span>\n )}\n {hasProgress && (\n <span className=\"shrink-0 text-xs tabular-nums text-muted-foreground\">\n {done}/{t.maxValue} · {pct}%\n </span>\n )}\n </div>\n )}\n {hasProgress && t.status === \"running\" && (\n <div className=\"mt-1\">\n <ProgressBar\n segments={[{ count: done, color: \"bg-blue-500\", label: \"done\" }]}\n total={t.maxValue as number}\n height=\"h-1\"\n />\n </div>\n )}\n {expanded && execDetails && <TaskExecDetailsView details={execDetails} />}\n {expanded && processDetails && (\n <TaskProcessDetailsView\n details={processDetails}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n {expanded && hasLogs && (\n <div className=\"mt-1 ml-1 max-h-48 space-y-0.5 overflow-y-auto border-l-2 pl-2\">\n {logs.map((l, i) => (\n <div key={i} className={cn(\"text-xs\", logLevelColor(l.level))}>\n <span className=\"mr-1 font-mono text-muted-foreground\">{l.level.substring(0, 3)}</span>\n {l.message}\n </div>\n ))}\n </div>\n )}\n {expanded && <TaskStreamTabs task={t} {...(extraTabs.length > 0 ? { extraTabs } : {})} />}\n </div>\n </div>\n );\n}\n\nfunction TaskControls({\n target,\n onControl,\n labelSuffix,\n stopPropagation,\n}: {\n target: TaskSnapshot;\n onControl: (action: TaskControlAction, target: TaskSnapshot) => void | Promise<void>;\n labelSuffix?: string;\n stopPropagation?: boolean;\n}) {\n const [busy, setBusy] = useState<TaskControlAction | null>(null);\n const [error, setError] = useState(\"\");\n const icons: Record<TaskControlAction, typeof UiPlay> = {\n start: UiPlay,\n stop: UiStop,\n restart: UiRestart,\n drain: UiStop,\n retry: UiRefresh,\n };\n const invoke = async (action: TaskControlAction) => {\n setBusy(action);\n setError(\"\");\n try {\n await onControl(action, target);\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : `Failed to ${action} task`);\n } finally {\n setBusy(null);\n }\n };\n return (\n <>\n {(target.controls ?? []).map((action) => {\n const ControlIcon = icons[action];\n const actionLabel = action === \"drain\" ? \"Stop after current\" : action[0]?.toUpperCase() + action.slice(1);\n const label = labelSuffix ? `${actionLabel} ${labelSuffix}` : actionLabel;\n return (\n <Button\n key={action}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={label}\n title={label}\n disabled={busy !== null}\n onClick={(event) => {\n if (stopPropagation) event.stopPropagation();\n void invoke(action);\n }}\n >\n <ControlIcon />\n </Button>\n );\n })}\n {error && <span role=\"alert\" className=\"text-xs text-red-600\">{error}</span>}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TaskProgress.js","sources":["../../src/data/TaskProgress.tsx"],"sourcesContent":["import { taskWorkProgress } from \"./task-work-progress\";\nimport { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { CopyButton } from \"../components/CopyButton\";\nimport { SplitButton } from \"../components/SplitButton\";\nimport { useCopyFlash } from \"../components/clipboard\";\nimport { UiCheck, UiCopy, UiJson, UiPlay, UiRefresh, UiRestart, UiStop, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { Icon } from \"./Icon\";\nimport { ProgressBar } from \"./ProgressBar\";\nimport { TaskProcessDetailsView } from \"./TaskProcessDetails\";\nimport { TaskExecDetailsView } from \"./TaskExecDetails\";\nimport type { LogEntry, TaskControlAction, TaskSnapshot } from \"./TaskSnapshot\";\nimport { type TaskHeaderExtra, TaskMetadataChips } from \"./TaskHeaderExtras\";\nimport { type TaskExtraTabs, TaskStreamTabs } from \"./TaskStreamTabs\";\nimport {\n isFailedOrWarn,\n taskGroupErrorCount,\n taskGroupErrors,\n taskGroupJson,\n taskGroupMarkdown,\n taskMarkdown,\n} from \"./task-copy\";\nimport { isTaskExecDetails } from \"./task-exec-details\";\nimport { isTaskProcessDetails } from \"./task-process-details\";\nimport {\n bucketTasks,\n logLevelColor,\n taskSegments,\n taskStatusBg,\n taskStatusColor,\n taskStatusIcon,\n} from \"./task-status\";\n\n// TaskProgress renders one or more clicky task runs (groups) and their child\n// tasks: a segmented progress bar per group plus collapsible per-task rows with\n// status icon, duration, error, and expandable logs. Presentational only —\n// callers feed it snapshots from useTaskRun (SSE) or any other source.\n\nconst MAX_COMPLETED = 5;\nconst MAX_PENDING = 3;\n\nexport interface TaskProgressProps {\n snapshots: TaskSnapshot[];\n title?: string;\n /** Tighter spacing for embedding in a panel. */\n compact?: boolean;\n /** Show every child task when the group first opens. */\n initialShowAllTasks?: boolean;\n className?: string;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n /**\n * Contributes host-owned output panes alongside a task's own stdout/stderr —\n * an agent's session transcript, say, which this module has no way to fetch.\n */\n extraTabs?: TaskExtraTabs;\n /**\n * Replaces the content beside a task's name in its header row. Returning null\n * for a task falls back to the default, which chips the scalar values of its\n * process metadata.\n */\n headerExtra?: TaskHeaderExtra;\n}\n\nexport function TaskProgress({\n snapshots,\n title,\n compact,\n initialShowAllTasks,\n className,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: TaskProgressProps) {\n const groups = snapshots.filter((s) => s.type === \"group\");\n const tasks = snapshots.filter((s) => s.type === \"task\");\n\n if (groups.length === 0) {\n return (\n <div className={cn(\"text-sm text-muted-foreground\", className)}>\n {title ? `${title}: ` : \"\"}No tasks yet.\n </div>\n );\n }\n\n return (\n <div className={cn(compact ? \"space-y-2\" : \"space-y-3\", className)}>\n {title && <h2 className=\"text-sm font-semibold\">{title}</h2>}\n {groups.map((g) => (\n <TaskGroupCard\n key={g.groupId || g.id}\n group={g}\n tasks={tasks.filter((t) => g.groupId ? t.groupId === g.groupId : t.group === g.id)}\n compact={compact}\n initialShowAllTasks={initialShowAllTasks}\n {...(onControl ? { onControl } : {})}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskGroupCard({\n group: g,\n tasks,\n compact,\n initialShowAllTasks,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs,\n headerExtra,\n}: {\n group: TaskSnapshot;\n tasks: TaskSnapshot[];\n compact: boolean | undefined;\n initialShowAllTasks: boolean | undefined;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onControl?: (action: TaskControlAction, group: TaskSnapshot) => void | Promise<void>;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const [showAll, setShowAll] = useState(initialShowAllTasks ?? false);\n const { state: copyState, copy } = useCopyFlash();\n const work = taskWorkProgress(g);\n const total = g.work ? work.total : g.total ?? tasks.length;\n const counts = g.work ? work.counts : bucketTasks(tasks);\n const done = counts.ok + counts.warn + counts.fail + counts.canceled;\n const progress = g.work ? work.label : total > 0 ? `${done}/${total}` : \"\";\n\n const running = tasks.filter((t) => t.status === \"running\");\n const pending = tasks.filter((t) => t.status === \"pending\");\n const completed = tasks.filter((t) => t.status !== \"running\" && t.status !== \"pending\");\n const alwaysShow = completed.filter(isFailedOrWarn);\n const collapsible = completed.filter((t) => !isFailedOrWarn(t));\n\n const hiddenCompleted = collapsible.length - MAX_COMPLETED;\n const collapseCompleted = !showAll && hiddenCompleted > 0;\n const visibleSuccess = collapseCompleted ? collapsible.slice(-MAX_COMPLETED) : collapsible;\n\n const hiddenPending = pending.length - MAX_PENDING;\n const collapsePending = !showAll && hiddenPending > 0;\n const visiblePending = collapsePending ? pending.slice(0, MAX_PENDING) : pending;\n\n const isTerminal = g.status !== \"running\" && g.status !== \"pending\";\n\n const copyItems: DropdownMenuItem[] = [\n {\n label: \"Copy as JSON\",\n icon: UiJson,\n onSelect: () => copy(taskGroupJson(g, tasks)),\n },\n {\n label: \"Copy errors only\",\n icon: UiWarningTriangle,\n disabled: taskGroupErrorCount(tasks) === 0,\n onSelect: () => copy(taskGroupErrors(g, tasks)),\n },\n ];\n\n return (\n <div className={cn(\"rounded-lg border bg-card\", compact ? \"p-2\" : \"p-4\")}>\n <div className={cn(\"flex items-center justify-between gap-3\", compact ? \"mb-2\" : \"mb-3\")}>\n <h3 className=\"flex min-w-0 items-center gap-1.5 text-sm font-semibold\">\n <Icon\n icon={taskStatusIcon(g.status)}\n className={cn(\n \"shrink-0\",\n taskStatusColor(g.status),\n g.status === \"running\" && \"animate-spin\",\n )}\n />\n <span className=\"truncate\">{g.name}</span>\n {progress && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{progress}</span>\n )}\n {g.kind && (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0 text-[10px] text-muted-foreground\">\n {g.kind}\n </span>\n )}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n {isTerminal && (\n <span\n className={cn(\n \"rounded-full px-2 py-0.5 text-xs\",\n taskStatusColor(g.status),\n taskStatusBg(g.status),\n )}\n >\n {g.status}\n </span>\n )}\n <SplitButton\n label={copyState === \"copied\" ? \"Copied\" : copyState === \"error\" ? \"Copy failed\" : \"Copy\"}\n icon={copyState === \"copied\" ? UiCheck : UiCopy}\n variant=\"ghost\"\n size=\"sm\"\n title=\"More copy options\"\n onClick={() => copy(taskGroupMarkdown(g, tasks))}\n items={copyItems}\n />\n {onControl && <TaskControls target={g} onControl={onControl} />}\n </div>\n </div>\n\n {total > 0 && (\n <div className={compact ? \"mb-2\" : \"mb-3\"}>\n <ProgressBar segments={taskSegments(counts)} total={total} height=\"h-1.5\" />\n </div>\n )}\n\n {isTaskProcessDetails(g.details) && (\n <TaskProcessDetailsView\n details={g.details}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n\n {!isTaskProcessDetails(g.details) && isTaskExecDetails(g.details) && (\n <TaskExecDetailsView details={g.details} />\n )}\n\n {hiddenCompleted > 0 || hiddenPending > 0 ? (\n <button\n type=\"button\"\n className={cn(\"border-b text-xs text-muted-foreground hover:text-foreground\", compact ? \"py-1\" : \"py-1.5\")}\n onClick={() => setShowAll((v) => !v)}\n >\n {showAll\n ? \"▲ collapse\"\n : `... ${(collapseCompleted ? hiddenCompleted : 0) + (collapsePending ? hiddenPending : 0)} more tasks`}\n </button>\n ) : null}\n\n {[...visibleSuccess, ...alwaysShow, ...running, ...visiblePending].map((t) => (\n <TaskRow\n key={t.id}\n task={t}\n group={g}\n compact={compact}\n {...(onTaskControl ? { onTaskControl } : {})}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n {...(extraTabs ? { extraTabs } : {})}\n {...(headerExtra ? { headerExtra } : {})}\n />\n ))}\n </div>\n );\n}\n\nfunction TaskRow({\n task: t,\n group,\n compact,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n extraTabs: contributeTabs,\n headerExtra,\n}: {\n task: TaskSnapshot;\n group: TaskSnapshot;\n compact: boolean | undefined;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n extraTabs?: TaskExtraTabs;\n headerExtra?: TaskHeaderExtra;\n onTaskControl?: (\n action: TaskControlAction,\n task: TaskSnapshot,\n group: TaskSnapshot,\n ) => void | Promise<void>;\n}) {\n const [expanded, setExpanded] = useState(false);\n const logs: LogEntry[] = t.logs ?? [];\n const hasLogs = logs.length > 0;\n const extraTabs = contributeTabs?.(t, group) ?? [];\n // A host that has nothing to add for this task returns null, and the default\n // metadata chips take over — so enriching one kind of task never costs the\n // rest their header.\n const header = headerExtra?.(t, group) ?? <TaskMetadataChips task={t} />;\n const hasOutput = !!t.stdout || !!t.stderr || extraTabs.length > 0;\n const execDetails = isTaskExecDetails(t.details) ? t.details : undefined;\n const processDetails = isTaskProcessDetails(t.details) ? t.details : undefined;\n const expandable = hasLogs || hasOutput || execDetails !== undefined || processDetails !== undefined;\n // Promote the latest warning message inline so a `warning` row shows its\n // reason without expanding. Suppressed when an error is already shown.\n const latestWarn = t.error ? undefined : logs.filter((l) => l.level === \"warn\").at(-1);\n // Bounded per-task progress (e.g. records emitted in a phase): render an x/y\n // count, a percentage, and a thin bar while the task runs.\n const done = t.progress ?? 0;\n // Only surface bounded progress once work has actually started — an untouched\n // task should not render a \"0/100 · 0%\" placeholder.\n const hasProgress = typeof t.maxValue === \"number\" && t.maxValue > 0 && done > 0;\n const pct = hasProgress ? Math.round((done / (t.maxValue as number)) * 100) : 0;\n\n return (\n <div\n className={cn(\n \"group flex items-start border-b last:border-0\",\n compact ? \"gap-2 py-1\" : \"gap-3 py-2\",\n expandable && \"-mx-1 cursor-pointer rounded px-1 hover:bg-muted/50\",\n )}\n onClick={expandable ? () => setExpanded((v) => !v) : undefined}\n >\n <Icon\n icon={taskStatusIcon(t.status)}\n className={cn(taskStatusColor(t.status), \"mt-0.5\", compact ? \"text-base\" : \"text-lg\", t.status === \"running\" && \"animate-spin\")}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-sm font-medium\">\n <span className=\"truncate\">{t.name}</span>\n {t.error && <span className=\"truncate text-xs font-normal text-red-500\">{t.error}</span>}\n {latestWarn && (\n <span className={cn(\"truncate text-xs font-normal\", logLevelColor(\"warn\"))}>\n {latestWarn.message}\n </span>\n )}\n {expandable && (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 text-[10px] font-medium text-muted-foreground\">\n {logs.length + (t.stdout ? 1 : 0) + (t.stderr ? 1 : 0) + (execDetails || processDetails ? 1 : 0)}\n </span>\n )}\n </span>\n {header}\n <div className=\"flex shrink-0 items-center gap-1\">\n {t.duration && <span className=\"text-xs text-muted-foreground\">{t.duration}</span>}\n <CopyButton\n value={() => taskMarkdown(t)}\n label={`Copy ${t.name}`}\n className=\"opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100\"\n iconClassName=\"text-xs\"\n />\n {onTaskControl && (\n <TaskControls\n target={t}\n labelSuffix={t.name}\n stopPropagation\n onControl={(action) => onTaskControl(action, t, group)}\n />\n )}\n </div>\n </div>\n {(t.description || hasProgress) && (\n <div className=\"mt-0.5 flex items-center gap-2\">\n {t.description && (\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">{t.description}</span>\n )}\n {hasProgress && (\n <span className=\"shrink-0 text-xs tabular-nums text-muted-foreground\">\n {done}/{t.maxValue} · {pct}%\n </span>\n )}\n </div>\n )}\n {hasProgress && t.status === \"running\" && (\n <div className=\"mt-1\">\n <ProgressBar\n segments={[{ count: done, color: \"bg-blue-500\", label: \"done\" }]}\n total={t.maxValue as number}\n height=\"h-1\"\n />\n </div>\n )}\n {expanded && execDetails && <TaskExecDetailsView details={execDetails} />}\n {expanded && processDetails && (\n <TaskProcessDetailsView\n details={processDetails}\n {...(metricsBaseUrl ? { metricsBaseUrl } : {})}\n {...(connectionStatus ? { connectionStatus } : {})}\n />\n )}\n {expanded && hasLogs && (\n <div className=\"mt-1 ml-1 max-h-48 space-y-0.5 overflow-y-auto border-l-2 pl-2\">\n {logs.map((l, i) => (\n <div key={i} className={cn(\"text-xs\", logLevelColor(l.level))}>\n <span className=\"mr-1 font-mono text-muted-foreground\">{l.level.substring(0, 3)}</span>\n {l.message}\n </div>\n ))}\n </div>\n )}\n {expanded && <TaskStreamTabs task={t} {...(extraTabs.length > 0 ? { extraTabs } : {})} />}\n </div>\n </div>\n );\n}\n\nfunction TaskControls({\n target,\n onControl,\n labelSuffix,\n stopPropagation,\n}: {\n target: TaskSnapshot;\n onControl: (action: TaskControlAction, target: TaskSnapshot) => void | Promise<void>;\n labelSuffix?: string;\n stopPropagation?: boolean;\n}) {\n const [busy, setBusy] = useState<TaskControlAction | null>(null);\n const [error, setError] = useState(\"\");\n const icons: Record<TaskControlAction, typeof UiPlay> = {\n start: UiPlay,\n stop: UiStop,\n restart: UiRestart,\n drain: UiStop,\n retry: UiRefresh,\n };\n const invoke = async (action: TaskControlAction) => {\n setBusy(action);\n setError(\"\");\n try {\n await onControl(action, target);\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : `Failed to ${action} task`);\n } finally {\n setBusy(null);\n }\n };\n return (\n <>\n {(target.controls ?? []).map((action) => {\n const ControlIcon = icons[action];\n const actionLabel = action === \"drain\" ? \"Stop after current\" : action[0]?.toUpperCase() + action.slice(1);\n const label = labelSuffix ? `${actionLabel} ${labelSuffix}` : actionLabel;\n return (\n <Button\n key={action}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={label}\n title={label}\n disabled={busy !== null}\n onClick={(event) => {\n if (stopPropagation) event.stopPropagation();\n void invoke(action);\n }}\n >\n <ControlIcon />\n </Button>\n );\n })}\n {error && <span role=\"alert\" className=\"text-xs text-red-600\">{error}</span>}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|