@flanksource/clicky-ui 0.3.35 → 0.3.36
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/ai.cjs +2 -1
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +2 -1
- package/dist/ai.js.map +1 -1
- package/dist/data/TaskHeaderExtras.cjs +35 -0
- package/dist/data/TaskHeaderExtras.cjs.map +1 -0
- package/dist/data/TaskHeaderExtras.d.ts +27 -0
- package/dist/data/TaskHeaderExtras.d.ts.map +1 -0
- package/dist/data/TaskHeaderExtras.js +35 -0
- package/dist/data/TaskHeaderExtras.js.map +1 -0
- package/dist/data/TaskManager.cjs +18 -6
- package/dist/data/TaskManager.cjs.map +1 -1
- package/dist/data/TaskManager.d.ts +13 -1
- package/dist/data/TaskManager.d.ts.map +1 -1
- package/dist/data/TaskManager.js +18 -6
- package/dist/data/TaskManager.js.map +1 -1
- package/dist/data/TaskProcessDetails.cjs +4 -1
- package/dist/data/TaskProcessDetails.cjs.map +1 -1
- package/dist/data/TaskProcessDetails.d.ts.map +1 -1
- package/dist/data/TaskProcessDetails.js +4 -1
- package/dist/data/TaskProcessDetails.js.map +1 -1
- package/dist/data/TaskProcessMetadata.cjs +50 -0
- package/dist/data/TaskProcessMetadata.cjs.map +1 -0
- package/dist/data/TaskProcessMetadata.d.ts +20 -0
- package/dist/data/TaskProcessMetadata.d.ts.map +1 -0
- package/dist/data/TaskProcessMetadata.js +50 -0
- package/dist/data/TaskProcessMetadata.js.map +1 -0
- package/dist/data/TaskProgress.cjs +22 -31
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts +14 -1
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +22 -31
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/TaskSnapshot.cjs.map +1 -1
- package/dist/data/TaskSnapshot.d.ts +22 -0
- package/dist/data/TaskSnapshot.d.ts.map +1 -1
- package/dist/data/TaskSnapshot.js.map +1 -1
- package/dist/data/TaskStreamTabs.cjs +78 -0
- package/dist/data/TaskStreamTabs.cjs.map +1 -0
- package/dist/data/TaskStreamTabs.d.ts +35 -0
- package/dist/data/TaskStreamTabs.d.ts.map +1 -0
- package/dist/data/TaskStreamTabs.js +78 -0
- package/dist/data/TaskStreamTabs.js.map +1 -0
- package/dist/data/ai/SessionInspector.approvals-model.cjs +9 -0
- package/dist/data/ai/SessionInspector.approvals-model.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.approvals-model.d.ts +17 -0
- package/dist/data/ai/SessionInspector.approvals-model.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.approvals-model.js +9 -0
- package/dist/data/ai/SessionInspector.approvals-model.js.map +1 -0
- package/dist/data/ai/SessionInspector.approvals.cjs +7 -11
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.d.ts +2 -10
- package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +4 -8
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionInspector.cjs +2 -2
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.d.ts +1 -1
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.js +1 -1
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.panel-parts.cjs +0 -13
- package/dist/data/ai/SessionInspector.panel-parts.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.panel-parts.d.ts +4 -5
- package/dist/data/ai/SessionInspector.panel-parts.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.panel-parts.js +1 -14
- package/dist/data/ai/SessionInspector.panel-parts.js.map +1 -1
- package/dist/data/ai/SessionInspector.panel-values.cjs +18 -0
- package/dist/data/ai/SessionInspector.panel-values.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.panel-values.d.ts +13 -0
- package/dist/data/ai/SessionInspector.panel-values.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.panel-values.js +18 -0
- package/dist/data/ai/SessionInspector.panel-values.js.map +1 -0
- package/dist/data/ai/SessionInspector.panels.cjs +27 -26
- package/dist/data/ai/SessionInspector.panels.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.panels.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.panels.js +2 -1
- package/dist/data/ai/SessionInspector.panels.js.map +1 -1
- package/dist/data/ai/index.d.ts +2 -1
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/task-metadata.cjs +36 -0
- package/dist/data/task-metadata.cjs.map +1 -0
- package/dist/data/task-metadata.d.ts +39 -0
- package/dist/data/task-metadata.d.ts.map +1 -0
- package/dist/data/task-metadata.js +36 -0
- package/dist/data/task-metadata.js.map +1 -0
- package/dist/data/task-streams.cjs +39 -0
- package/dist/data/task-streams.cjs.map +1 -0
- package/dist/data/task-streams.d.ts +60 -0
- package/dist/data/task-streams.d.ts.map +1 -0
- package/dist/data/task-streams.js +39 -0
- package/dist/data/task-streams.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +14 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +6 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +14 -0
- package/dist/data.js.map +1 -1
- package/dist/hooks/use-task-run.cjs +13 -15
- package/dist/hooks/use-task-run.cjs.map +1 -1
- package/dist/hooks/use-task-run.d.ts.map +1 -1
- package/dist/hooks/use-task-run.js +14 -16
- package/dist/hooks/use-task-run.js.map +1 -1
- package/dist/index.cjs +14 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +14 -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":"TaskProcessDetails.cjs","sources":["../../src/data/TaskProcessDetails.tsx"],"sourcesContent":["import { UiActivity, UiDatabase, UiFile } from \"../icons\";\nimport { TimeseriesGauge } from \"./TimeseriesGauge\";\nimport { DiagnosticsTree } from \"./diagnostics/DiagnosticsTree\";\nimport { TaskResourceReadings } from \"./TaskResourceReadings\";\nimport { buildTaskProcessForest } from \"./task-process-details\";\nimport { TaskCommandLine } from \"./TaskExecDetails\";\nimport type { TaskProcessDetails } from \"./TaskSnapshot\";\n\nexport function TaskProcessDetailsView({\n details,\n metricsBaseUrl,\n connectionStatus,\n}: {\n details: TaskProcessDetails;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const forest = buildTaskProcessForest(details.tree ?? []);\n const metricBase = metricsBaseUrl ?? \"/api/v1/tasks/metrics/\";\n const restartLabel = `${details.restarts} ${details.restarts === 1 ? \"restart\" : \"restarts\"}`;\n\n return (\n <section className=\"mb-3 space-y-3 rounded-md border bg-muted/20 p-3\">\n <TaskCommandLine command={details.command} {...(details.args ? { args: details.args } : {})} />\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"font-mono text-foreground\">pid {details.pid ?? \"—\"}</span>\n <span>{details.status}</span>\n <TaskResourceReadings details={details} {...(connectionStatus ? { connectionStatus } : {})} />\n <span>{restartLabel}</span>\n <span>{details.restartPolicy}</span>\n </div>\n\n {Object.keys(details.metrics).length > 0 && (\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4\">\n {details.metrics.cpu && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.cpu) }}\n title=\"CPU\"\n icon={UiActivity}\n unit=\"percent\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.rss && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.rss) }}\n title=\"RSS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.vms && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.vms) }}\n title=\"VMS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.openFiles && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.openFiles) }}\n title=\"Open files\"\n icon={UiFile}\n unit=\"short\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n </div>\n )}\n\n {forest.length > 0 && (\n <div className=\"space-y-1\">\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Process tree\n </div>\n <div className=\"overflow-hidden rounded-md border bg-background\">\n {forest.map((root) => (\n <DiagnosticsTree key={root.pid} root={root} expandAll onSelect={() => {}} />\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n"],"names":["buildTaskProcessForest","jsxs","jsx","TaskCommandLine","TaskResourceReadings","TimeseriesGauge","UiActivity","UiDatabase","UiFile","DiagnosticsTree"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TaskProcessDetails.cjs","sources":["../../src/data/TaskProcessDetails.tsx"],"sourcesContent":["import { UiActivity, UiDatabase, UiFile } from \"../icons\";\nimport { TimeseriesGauge } from \"./TimeseriesGauge\";\nimport { DiagnosticsTree } from \"./diagnostics/DiagnosticsTree\";\nimport { TaskResourceReadings } from \"./TaskResourceReadings\";\nimport { buildTaskProcessForest } from \"./task-process-details\";\nimport { TaskCommandLine } from \"./TaskExecDetails\";\nimport { TaskMetadata, TaskProcessFacts } from \"./TaskProcessMetadata\";\nimport type { TaskProcessDetails } from \"./TaskSnapshot\";\n\nexport function TaskProcessDetailsView({\n details,\n metricsBaseUrl,\n connectionStatus,\n}: {\n details: TaskProcessDetails;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const forest = buildTaskProcessForest(details.tree ?? []);\n const metricBase = metricsBaseUrl ?? \"/api/v1/tasks/metrics/\";\n const restartLabel = `${details.restarts} ${details.restarts === 1 ? \"restart\" : \"restarts\"}`;\n\n return (\n <section className=\"mb-3 space-y-3 rounded-md border bg-muted/20 p-3\">\n <TaskMetadata {...(details.metadata !== undefined ? { metadata: details.metadata } : {})} />\n <TaskCommandLine command={details.command} {...(details.args ? { args: details.args } : {})} />\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"font-mono text-foreground\">pid {details.pid ?? \"—\"}</span>\n <span>{details.status}</span>\n <TaskResourceReadings details={details} {...(connectionStatus ? { connectionStatus } : {})} />\n <span>{restartLabel}</span>\n <span>{details.restartPolicy}</span>\n <TaskProcessFacts details={details} />\n </div>\n\n {Object.keys(details.metrics).length > 0 && (\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4\">\n {details.metrics.cpu && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.cpu) }}\n title=\"CPU\"\n icon={UiActivity}\n unit=\"percent\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.rss && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.rss) }}\n title=\"RSS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.vms && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.vms) }}\n title=\"VMS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.openFiles && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.openFiles) }}\n title=\"Open files\"\n icon={UiFile}\n unit=\"short\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n </div>\n )}\n\n {forest.length > 0 && (\n <div className=\"space-y-1\">\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Process tree\n </div>\n <div className=\"overflow-hidden rounded-md border bg-background\">\n {forest.map((root) => (\n <DiagnosticsTree key={root.pid} root={root} expandAll onSelect={() => {}} />\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n"],"names":["buildTaskProcessForest","jsxs","jsx","TaskMetadata","TaskCommandLine","TaskResourceReadings","TaskProcessFacts","TimeseriesGauge","UiActivity","UiDatabase","UiFile","DiagnosticsTree"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskProcessDetails.d.ts","sourceRoot":"","sources":["../../src/data/TaskProcessDetails.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TaskProcessDetails.d.ts","sourceRoot":"","sources":["../../src/data/TaskProcessDetails.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,cAAc,EACd,gBAAgB,GACjB,EAAE;IACD,OAAO,EAAE,kBAAkB,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,+BAqFA"}
|
|
@@ -4,6 +4,7 @@ import { DiagnosticsTree } from "./diagnostics/DiagnosticsTree.js";
|
|
|
4
4
|
import { TaskResourceReadings } from "./TaskResourceReadings.js";
|
|
5
5
|
import { buildTaskProcessForest } from "./task-process-details.js";
|
|
6
6
|
import { TaskCommandLine } from "./TaskExecDetails.js";
|
|
7
|
+
import { TaskMetadata, TaskProcessFacts } from "./TaskProcessMetadata.js";
|
|
7
8
|
import { UiActivity } from "../icons/components/UiActivity.js";
|
|
8
9
|
import { UiDatabase } from "../icons/components/UiDatabase.js";
|
|
9
10
|
import { UiFile } from "../icons/components/UiFile.js";
|
|
@@ -16,6 +17,7 @@ function TaskProcessDetailsView({
|
|
|
16
17
|
const metricBase = metricsBaseUrl ?? "/api/v1/tasks/metrics/";
|
|
17
18
|
const restartLabel = `${details.restarts} ${details.restarts === 1 ? "restart" : "restarts"}`;
|
|
18
19
|
return /* @__PURE__ */ jsxs("section", { className: "mb-3 space-y-3 rounded-md border bg-muted/20 p-3", children: [
|
|
20
|
+
/* @__PURE__ */ jsx(TaskMetadata, { ...details.metadata !== void 0 ? { metadata: details.metadata } : {} }),
|
|
19
21
|
/* @__PURE__ */ jsx(TaskCommandLine, { command: details.command, ...details.args ? { args: details.args } : {} }),
|
|
20
22
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground", children: [
|
|
21
23
|
/* @__PURE__ */ jsxs("span", { className: "font-mono text-foreground", children: [
|
|
@@ -25,7 +27,8 @@ function TaskProcessDetailsView({
|
|
|
25
27
|
/* @__PURE__ */ jsx("span", { children: details.status }),
|
|
26
28
|
/* @__PURE__ */ jsx(TaskResourceReadings, { details, ...connectionStatus ? { connectionStatus } : {} }),
|
|
27
29
|
/* @__PURE__ */ jsx("span", { children: restartLabel }),
|
|
28
|
-
/* @__PURE__ */ jsx("span", { children: details.restartPolicy })
|
|
30
|
+
/* @__PURE__ */ jsx("span", { children: details.restartPolicy }),
|
|
31
|
+
/* @__PURE__ */ jsx(TaskProcessFacts, { details })
|
|
29
32
|
] }),
|
|
30
33
|
Object.keys(details.metrics).length > 0 && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4", children: [
|
|
31
34
|
details.metrics.cpu && /* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskProcessDetails.js","sources":["../../src/data/TaskProcessDetails.tsx"],"sourcesContent":["import { UiActivity, UiDatabase, UiFile } from \"../icons\";\nimport { TimeseriesGauge } from \"./TimeseriesGauge\";\nimport { DiagnosticsTree } from \"./diagnostics/DiagnosticsTree\";\nimport { TaskResourceReadings } from \"./TaskResourceReadings\";\nimport { buildTaskProcessForest } from \"./task-process-details\";\nimport { TaskCommandLine } from \"./TaskExecDetails\";\nimport type { TaskProcessDetails } from \"./TaskSnapshot\";\n\nexport function TaskProcessDetailsView({\n details,\n metricsBaseUrl,\n connectionStatus,\n}: {\n details: TaskProcessDetails;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const forest = buildTaskProcessForest(details.tree ?? []);\n const metricBase = metricsBaseUrl ?? \"/api/v1/tasks/metrics/\";\n const restartLabel = `${details.restarts} ${details.restarts === 1 ? \"restart\" : \"restarts\"}`;\n\n return (\n <section className=\"mb-3 space-y-3 rounded-md border bg-muted/20 p-3\">\n <TaskCommandLine command={details.command} {...(details.args ? { args: details.args } : {})} />\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"font-mono text-foreground\">pid {details.pid ?? \"—\"}</span>\n <span>{details.status}</span>\n <TaskResourceReadings details={details} {...(connectionStatus ? { connectionStatus } : {})} />\n <span>{restartLabel}</span>\n <span>{details.restartPolicy}</span>\n </div>\n\n {Object.keys(details.metrics).length > 0 && (\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4\">\n {details.metrics.cpu && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.cpu) }}\n title=\"CPU\"\n icon={UiActivity}\n unit=\"percent\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.rss && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.rss) }}\n title=\"RSS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.vms && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.vms) }}\n title=\"VMS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.openFiles && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.openFiles) }}\n title=\"Open files\"\n icon={UiFile}\n unit=\"short\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n </div>\n )}\n\n {forest.length > 0 && (\n <div className=\"space-y-1\">\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Process tree\n </div>\n <div className=\"overflow-hidden rounded-md border bg-background\">\n {forest.map((root) => (\n <DiagnosticsTree key={root.pid} root={root} expandAll onSelect={() => {}} />\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TaskProcessDetails.js","sources":["../../src/data/TaskProcessDetails.tsx"],"sourcesContent":["import { UiActivity, UiDatabase, UiFile } from \"../icons\";\nimport { TimeseriesGauge } from \"./TimeseriesGauge\";\nimport { DiagnosticsTree } from \"./diagnostics/DiagnosticsTree\";\nimport { TaskResourceReadings } from \"./TaskResourceReadings\";\nimport { buildTaskProcessForest } from \"./task-process-details\";\nimport { TaskCommandLine } from \"./TaskExecDetails\";\nimport { TaskMetadata, TaskProcessFacts } from \"./TaskProcessMetadata\";\nimport type { TaskProcessDetails } from \"./TaskSnapshot\";\n\nexport function TaskProcessDetailsView({\n details,\n metricsBaseUrl,\n connectionStatus,\n}: {\n details: TaskProcessDetails;\n metricsBaseUrl?: string;\n connectionStatus?: string;\n}) {\n const forest = buildTaskProcessForest(details.tree ?? []);\n const metricBase = metricsBaseUrl ?? \"/api/v1/tasks/metrics/\";\n const restartLabel = `${details.restarts} ${details.restarts === 1 ? \"restart\" : \"restarts\"}`;\n\n return (\n <section className=\"mb-3 space-y-3 rounded-md border bg-muted/20 p-3\">\n <TaskMetadata {...(details.metadata !== undefined ? { metadata: details.metadata } : {})} />\n <TaskCommandLine command={details.command} {...(details.args ? { args: details.args } : {})} />\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"font-mono text-foreground\">pid {details.pid ?? \"—\"}</span>\n <span>{details.status}</span>\n <TaskResourceReadings details={details} {...(connectionStatus ? { connectionStatus } : {})} />\n <span>{restartLabel}</span>\n <span>{details.restartPolicy}</span>\n <TaskProcessFacts details={details} />\n </div>\n\n {Object.keys(details.metrics).length > 0 && (\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4\">\n {details.metrics.cpu && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.cpu) }}\n title=\"CPU\"\n icon={UiActivity}\n unit=\"percent\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.rss && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.rss) }}\n title=\"RSS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.vms && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.vms) }}\n title=\"VMS\"\n icon={UiDatabase}\n unit=\"bytes\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n {details.metrics.openFiles && (\n <TimeseriesGauge\n baseUrl={metricBase}\n value={{ id: encodeURIComponent(details.metrics.openFiles) }}\n title=\"Open files\"\n icon={UiFile}\n unit=\"short\"\n variant=\"cell\"\n range=\"15m\"\n refreshMs={2000}\n />\n )}\n </div>\n )}\n\n {forest.length > 0 && (\n <div className=\"space-y-1\">\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Process tree\n </div>\n <div className=\"overflow-hidden rounded-md border bg-background\">\n {forest.map((root) => (\n <DiagnosticsTree key={root.pid} root={root} expandAll onSelect={() => {}} />\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const JsonView = require("./JsonView.cjs");
|
|
5
|
+
const taskMetadata = require("./task-metadata.cjs");
|
|
6
|
+
const format = require("../lib/format.cjs");
|
|
7
|
+
function TaskMetadata({ metadata }) {
|
|
8
|
+
const entries = taskMetadata.metadataEntries(metadata);
|
|
9
|
+
if (taskMetadata.isFlatMetadata(metadata)) {
|
|
10
|
+
if (entries.length === 0) return null;
|
|
11
|
+
return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "flex flex-wrap items-baseline gap-x-4 gap-y-1 text-xs", children: entries.map(({ key, text }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5", children: [
|
|
12
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground", children: key }),
|
|
13
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "font-medium text-foreground", children: taskMetadata.isMetadataLink(key, text) ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: text, className: "text-primary hover:underline", children: text }) : text })
|
|
14
|
+
] }, key)) });
|
|
15
|
+
}
|
|
16
|
+
if (metadata === void 0 || metadata === null) return null;
|
|
17
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { data: metadata }) });
|
|
18
|
+
}
|
|
19
|
+
function limitEntries(limits) {
|
|
20
|
+
const parts = [];
|
|
21
|
+
if (limits.maxRssBytes) parts.push(`max ${format.formatBytes(limits.maxRssBytes)} RSS`);
|
|
22
|
+
if (limits.maxCpuPercent) parts.push(`max ${limits.maxCpuPercent}% CPU`);
|
|
23
|
+
if (limits.cpuSampleCount) parts.push(`over ${limits.cpuSampleCount} samples`);
|
|
24
|
+
if (limits.interval) parts.push(`every ${limits.interval}`);
|
|
25
|
+
return parts;
|
|
26
|
+
}
|
|
27
|
+
function TaskProcessFacts({ details }) {
|
|
28
|
+
const limits = details.limits ? limitEntries(details.limits) : [];
|
|
29
|
+
const started = details.started ? Date.parse(details.started) : NaN;
|
|
30
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
31
|
+
Number.isFinite(started) && started > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { title: new Date(started).toISOString(), children: [
|
|
32
|
+
"started ",
|
|
33
|
+
new Date(started).toLocaleTimeString()
|
|
34
|
+
] }),
|
|
35
|
+
details.ports && details.ports.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { children: details.ports.map((port) => `:${port}`).join(" ") }),
|
|
36
|
+
details.exitCode !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
37
|
+
"exit ",
|
|
38
|
+
details.exitCode
|
|
39
|
+
] }),
|
|
40
|
+
details.maxRestarts ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
41
|
+
"max ",
|
|
42
|
+
details.maxRestarts,
|
|
43
|
+
" restarts"
|
|
44
|
+
] }) : null,
|
|
45
|
+
limits.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { title: "Exceeding a limit kills the whole process tree", children: limits.join(" · ") })
|
|
46
|
+
] });
|
|
47
|
+
}
|
|
48
|
+
exports.TaskMetadata = TaskMetadata;
|
|
49
|
+
exports.TaskProcessFacts = TaskProcessFacts;
|
|
50
|
+
//# sourceMappingURL=TaskProcessMetadata.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TaskProcessMetadata.cjs","sources":["../../src/data/TaskProcessMetadata.tsx"],"sourcesContent":["import { formatBytes } from \"./diagnostics/utils\";\nimport { JsonView } from \"./JsonView\";\nimport { isFlatMetadata, isMetadataLink, metadataEntries } from \"./task-metadata\";\nimport type { TaskProcessDetails, TaskResourceLimits } from \"./TaskSnapshot\";\n\n/**\n * TaskMetadata renders the caller's own context for a process — which run it is\n * working, which model, which phase, which turn. The producer chooses both the\n * keys and the shape, so this reads the shape rather than assuming one: a flat\n * object is a definition list, where a value that points somewhere becomes a\n * link; anything structured keeps its structure in a JSON view rather than being\n * flattened into something that only looks like a label.\n */\nexport function TaskMetadata({ metadata }: { metadata?: unknown }) {\n const entries = metadataEntries(metadata);\n if (isFlatMetadata(metadata)) {\n if (entries.length === 0) return null;\n return (\n <dl className=\"flex flex-wrap items-baseline gap-x-4 gap-y-1 text-xs\">\n {entries.map(({ key, text }) => (\n <div key={key} className=\"flex items-baseline gap-1.5\">\n <dt className=\"text-muted-foreground\">{key}</dt>\n <dd className=\"font-medium text-foreground\">\n {isMetadataLink(key, text) ? (\n <a href={text} className=\"text-primary hover:underline\">\n {text}\n </a>\n ) : (\n text\n )}\n </dd>\n </div>\n ))}\n </dl>\n );\n }\n if (metadata === undefined || metadata === null) return null;\n return (\n <div className=\"overflow-x-auto text-xs\">\n <JsonView data={metadata} />\n </div>\n );\n}\n\nfunction limitEntries(limits: TaskResourceLimits): string[] {\n const parts: string[] = [];\n if (limits.maxRssBytes) parts.push(`max ${formatBytes(limits.maxRssBytes)} RSS`);\n if (limits.maxCpuPercent) parts.push(`max ${limits.maxCpuPercent}% CPU`);\n if (limits.cpuSampleCount) parts.push(`over ${limits.cpuSampleCount} samples`);\n if (limits.interval) parts.push(`every ${limits.interval}`);\n return parts;\n}\n\n/**\n * TaskProcessFacts is the line of things that are true about the process but\n * are not resource readings: where it listens, what killed it, what would.\n */\nexport function TaskProcessFacts({ details }: { details: TaskProcessDetails }) {\n const limits = details.limits ? limitEntries(details.limits) : [];\n const started = details.started ? Date.parse(details.started) : NaN;\n return (\n <>\n {Number.isFinite(started) && started > 0 && (\n <span title={new Date(started).toISOString()}>started {new Date(started).toLocaleTimeString()}</span>\n )}\n {details.ports && details.ports.length > 0 && <span>{details.ports.map((port) => `:${port}`).join(\" \")}</span>}\n {details.exitCode !== undefined && <span>exit {details.exitCode}</span>}\n {details.maxRestarts ? <span>max {details.maxRestarts} restarts</span> : null}\n {limits.length > 0 && <span title=\"Exceeding a limit kills the whole process tree\">{limits.join(\" · \")}</span>}\n </>\n );\n}\n"],"names":["metadataEntries","isFlatMetadata","jsx","jsxs","isMetadataLink","JsonView","formatBytes","Fragment"],"mappings":";;;;;;AAaO,SAAS,aAAa,EAAE,YAAoC;AACjE,QAAM,UAAUA,aAAAA,gBAAgB,QAAQ;AACxC,MAAIC,aAAAA,eAAe,QAAQ,GAAG;AAC5B,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WACEC,2BAAAA,IAAC,MAAA,EAAG,WAAU,yDACX,kBAAQ,IAAI,CAAC,EAAE,KAAK,KAAA,MACnBC,2BAAAA,KAAC,OAAA,EAAc,WAAU,+BACvB,UAAA;AAAA,MAAAD,2BAAAA,IAAC,MAAA,EAAG,WAAU,yBAAyB,UAAA,KAAI;AAAA,qCAC1C,MAAA,EAAG,WAAU,+BACX,UAAAE,aAAAA,eAAe,KAAK,IAAI,IACvBF,2BAAAA,IAAC,KAAA,EAAE,MAAM,MAAM,WAAU,gCACtB,UAAA,MACH,IAEA,KAAA,CAEJ;AAAA,IAAA,KAVQ,GAWV,CACD,GACH;AAAA,EAEJ;AACA,MAAI,aAAa,UAAa,aAAa,KAAM,QAAO;AACxD,SACEA,+BAAC,SAAI,WAAU,2BACb,yCAACG,SAAAA,UAAA,EAAS,MAAM,UAAU,EAAA,CAC5B;AAEJ;AAEA,SAAS,aAAa,QAAsC;AAC1D,QAAM,QAAkB,CAAA;AACxB,MAAI,OAAO,YAAa,OAAM,KAAK,OAAOC,OAAAA,YAAY,OAAO,WAAW,CAAC,MAAM;AAC/E,MAAI,OAAO,cAAe,OAAM,KAAK,OAAO,OAAO,aAAa,OAAO;AACvE,MAAI,OAAO,eAAgB,OAAM,KAAK,QAAQ,OAAO,cAAc,UAAU;AAC7E,MAAI,OAAO,SAAU,OAAM,KAAK,SAAS,OAAO,QAAQ,EAAE;AAC1D,SAAO;AACT;AAMO,SAAS,iBAAiB,EAAE,WAA4C;AAC7E,QAAM,SAAS,QAAQ,SAAS,aAAa,QAAQ,MAAM,IAAI,CAAA;AAC/D,QAAM,UAAU,QAAQ,UAAU,KAAK,MAAM,QAAQ,OAAO,IAAI;AAChE,SACEH,2BAAAA,KAAAI,qBAAA,EACG,UAAA;AAAA,IAAA,OAAO,SAAS,OAAO,KAAK,UAAU,KACrCJ,2BAAAA,KAAC,QAAA,EAAK,OAAO,IAAI,KAAK,OAAO,EAAE,eAAe,UAAA;AAAA,MAAA;AAAA,MAAS,IAAI,KAAK,OAAO,EAAE,mBAAA;AAAA,IAAmB,GAAE;AAAA,IAE/F,QAAQ,SAAS,QAAQ,MAAM,SAAS,oCAAM,QAAA,EAAM,UAAA,QAAQ,MAAM,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,EAAE,KAAK,GAAG,GAAE;AAAA,IACtG,QAAQ,aAAa,UAAaA,2BAAAA,KAAC,QAAA,EAAK,UAAA;AAAA,MAAA;AAAA,MAAM,QAAQ;AAAA,IAAA,GAAS;AAAA,IAC/D,QAAQ,cAAcA,2BAAAA,KAAC,QAAA,EAAK,UAAA;AAAA,MAAA;AAAA,MAAK,QAAQ;AAAA,MAAY;AAAA,IAAA,EAAA,CAAS,IAAU;AAAA,IACxE,OAAO,SAAS,KAAKD,2BAAAA,IAAC,QAAA,EAAK,OAAM,kDAAkD,UAAA,OAAO,KAAK,KAAK,EAAA,CAAE;AAAA,EAAA,GACzG;AAEJ;;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TaskProcessDetails } from './TaskSnapshot';
|
|
2
|
+
/**
|
|
3
|
+
* TaskMetadata renders the caller's own context for a process — which run it is
|
|
4
|
+
* working, which model, which phase, which turn. The producer chooses both the
|
|
5
|
+
* keys and the shape, so this reads the shape rather than assuming one: a flat
|
|
6
|
+
* object is a definition list, where a value that points somewhere becomes a
|
|
7
|
+
* link; anything structured keeps its structure in a JSON view rather than being
|
|
8
|
+
* flattened into something that only looks like a label.
|
|
9
|
+
*/
|
|
10
|
+
export declare function TaskMetadata({ metadata }: {
|
|
11
|
+
metadata?: unknown;
|
|
12
|
+
}): import("react").JSX.Element | null;
|
|
13
|
+
/**
|
|
14
|
+
* TaskProcessFacts is the line of things that are true about the process but
|
|
15
|
+
* are not resource readings: where it listens, what killed it, what would.
|
|
16
|
+
*/
|
|
17
|
+
export declare function TaskProcessFacts({ details }: {
|
|
18
|
+
details: TaskProcessDetails;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=TaskProcessMetadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TaskProcessMetadata.d.ts","sourceRoot":"","sources":["../../src/data/TaskProcessMetadata.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,gBAAgB,CAAC;AAE7E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,sCA6BhE;AAWD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,kBAAkB,CAAA;CAAE,+BAc5E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { JsonView } from "./JsonView.js";
|
|
3
|
+
import { metadataEntries, isFlatMetadata, isMetadataLink } from "./task-metadata.js";
|
|
4
|
+
import { formatBytes } from "../lib/format.js";
|
|
5
|
+
function TaskMetadata({ metadata }) {
|
|
6
|
+
const entries = metadataEntries(metadata);
|
|
7
|
+
if (isFlatMetadata(metadata)) {
|
|
8
|
+
if (entries.length === 0) return null;
|
|
9
|
+
return /* @__PURE__ */ jsx("dl", { className: "flex flex-wrap items-baseline gap-x-4 gap-y-1 text-xs", children: entries.map(({ key, text }) => /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1.5", children: [
|
|
10
|
+
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: key }),
|
|
11
|
+
/* @__PURE__ */ jsx("dd", { className: "font-medium text-foreground", children: isMetadataLink(key, text) ? /* @__PURE__ */ jsx("a", { href: text, className: "text-primary hover:underline", children: text }) : text })
|
|
12
|
+
] }, key)) });
|
|
13
|
+
}
|
|
14
|
+
if (metadata === void 0 || metadata === null) return null;
|
|
15
|
+
return /* @__PURE__ */ jsx("div", { className: "overflow-x-auto text-xs", children: /* @__PURE__ */ jsx(JsonView, { data: metadata }) });
|
|
16
|
+
}
|
|
17
|
+
function limitEntries(limits) {
|
|
18
|
+
const parts = [];
|
|
19
|
+
if (limits.maxRssBytes) parts.push(`max ${formatBytes(limits.maxRssBytes)} RSS`);
|
|
20
|
+
if (limits.maxCpuPercent) parts.push(`max ${limits.maxCpuPercent}% CPU`);
|
|
21
|
+
if (limits.cpuSampleCount) parts.push(`over ${limits.cpuSampleCount} samples`);
|
|
22
|
+
if (limits.interval) parts.push(`every ${limits.interval}`);
|
|
23
|
+
return parts;
|
|
24
|
+
}
|
|
25
|
+
function TaskProcessFacts({ details }) {
|
|
26
|
+
const limits = details.limits ? limitEntries(details.limits) : [];
|
|
27
|
+
const started = details.started ? Date.parse(details.started) : NaN;
|
|
28
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29
|
+
Number.isFinite(started) && started > 0 && /* @__PURE__ */ jsxs("span", { title: new Date(started).toISOString(), children: [
|
|
30
|
+
"started ",
|
|
31
|
+
new Date(started).toLocaleTimeString()
|
|
32
|
+
] }),
|
|
33
|
+
details.ports && details.ports.length > 0 && /* @__PURE__ */ jsx("span", { children: details.ports.map((port) => `:${port}`).join(" ") }),
|
|
34
|
+
details.exitCode !== void 0 && /* @__PURE__ */ jsxs("span", { children: [
|
|
35
|
+
"exit ",
|
|
36
|
+
details.exitCode
|
|
37
|
+
] }),
|
|
38
|
+
details.maxRestarts ? /* @__PURE__ */ jsxs("span", { children: [
|
|
39
|
+
"max ",
|
|
40
|
+
details.maxRestarts,
|
|
41
|
+
" restarts"
|
|
42
|
+
] }) : null,
|
|
43
|
+
limits.length > 0 && /* @__PURE__ */ jsx("span", { title: "Exceeding a limit kills the whole process tree", children: limits.join(" · ") })
|
|
44
|
+
] });
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
TaskMetadata,
|
|
48
|
+
TaskProcessFacts
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=TaskProcessMetadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TaskProcessMetadata.js","sources":["../../src/data/TaskProcessMetadata.tsx"],"sourcesContent":["import { formatBytes } from \"./diagnostics/utils\";\nimport { JsonView } from \"./JsonView\";\nimport { isFlatMetadata, isMetadataLink, metadataEntries } from \"./task-metadata\";\nimport type { TaskProcessDetails, TaskResourceLimits } from \"./TaskSnapshot\";\n\n/**\n * TaskMetadata renders the caller's own context for a process — which run it is\n * working, which model, which phase, which turn. The producer chooses both the\n * keys and the shape, so this reads the shape rather than assuming one: a flat\n * object is a definition list, where a value that points somewhere becomes a\n * link; anything structured keeps its structure in a JSON view rather than being\n * flattened into something that only looks like a label.\n */\nexport function TaskMetadata({ metadata }: { metadata?: unknown }) {\n const entries = metadataEntries(metadata);\n if (isFlatMetadata(metadata)) {\n if (entries.length === 0) return null;\n return (\n <dl className=\"flex flex-wrap items-baseline gap-x-4 gap-y-1 text-xs\">\n {entries.map(({ key, text }) => (\n <div key={key} className=\"flex items-baseline gap-1.5\">\n <dt className=\"text-muted-foreground\">{key}</dt>\n <dd className=\"font-medium text-foreground\">\n {isMetadataLink(key, text) ? (\n <a href={text} className=\"text-primary hover:underline\">\n {text}\n </a>\n ) : (\n text\n )}\n </dd>\n </div>\n ))}\n </dl>\n );\n }\n if (metadata === undefined || metadata === null) return null;\n return (\n <div className=\"overflow-x-auto text-xs\">\n <JsonView data={metadata} />\n </div>\n );\n}\n\nfunction limitEntries(limits: TaskResourceLimits): string[] {\n const parts: string[] = [];\n if (limits.maxRssBytes) parts.push(`max ${formatBytes(limits.maxRssBytes)} RSS`);\n if (limits.maxCpuPercent) parts.push(`max ${limits.maxCpuPercent}% CPU`);\n if (limits.cpuSampleCount) parts.push(`over ${limits.cpuSampleCount} samples`);\n if (limits.interval) parts.push(`every ${limits.interval}`);\n return parts;\n}\n\n/**\n * TaskProcessFacts is the line of things that are true about the process but\n * are not resource readings: where it listens, what killed it, what would.\n */\nexport function TaskProcessFacts({ details }: { details: TaskProcessDetails }) {\n const limits = details.limits ? limitEntries(details.limits) : [];\n const started = details.started ? Date.parse(details.started) : NaN;\n return (\n <>\n {Number.isFinite(started) && started > 0 && (\n <span title={new Date(started).toISOString()}>started {new Date(started).toLocaleTimeString()}</span>\n )}\n {details.ports && details.ports.length > 0 && <span>{details.ports.map((port) => `:${port}`).join(\" \")}</span>}\n {details.exitCode !== undefined && <span>exit {details.exitCode}</span>}\n {details.maxRestarts ? <span>max {details.maxRestarts} restarts</span> : null}\n {limits.length > 0 && <span title=\"Exceeding a limit kills the whole process tree\">{limits.join(\" · \")}</span>}\n </>\n );\n}\n"],"names":[],"mappings":";;;;AAaO,SAAS,aAAa,EAAE,YAAoC;AACjE,QAAM,UAAU,gBAAgB,QAAQ;AACxC,MAAI,eAAe,QAAQ,GAAG;AAC5B,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WACE,oBAAC,MAAA,EAAG,WAAU,yDACX,kBAAQ,IAAI,CAAC,EAAE,KAAK,KAAA,MACnB,qBAAC,OAAA,EAAc,WAAU,+BACvB,UAAA;AAAA,MAAA,oBAAC,MAAA,EAAG,WAAU,yBAAyB,UAAA,KAAI;AAAA,0BAC1C,MAAA,EAAG,WAAU,+BACX,UAAA,eAAe,KAAK,IAAI,IACvB,oBAAC,KAAA,EAAE,MAAM,MAAM,WAAU,gCACtB,UAAA,MACH,IAEA,KAAA,CAEJ;AAAA,IAAA,KAVQ,GAWV,CACD,GACH;AAAA,EAEJ;AACA,MAAI,aAAa,UAAa,aAAa,KAAM,QAAO;AACxD,SACE,oBAAC,SAAI,WAAU,2BACb,8BAAC,UAAA,EAAS,MAAM,UAAU,EAAA,CAC5B;AAEJ;AAEA,SAAS,aAAa,QAAsC;AAC1D,QAAM,QAAkB,CAAA;AACxB,MAAI,OAAO,YAAa,OAAM,KAAK,OAAO,YAAY,OAAO,WAAW,CAAC,MAAM;AAC/E,MAAI,OAAO,cAAe,OAAM,KAAK,OAAO,OAAO,aAAa,OAAO;AACvE,MAAI,OAAO,eAAgB,OAAM,KAAK,QAAQ,OAAO,cAAc,UAAU;AAC7E,MAAI,OAAO,SAAU,OAAM,KAAK,SAAS,OAAO,QAAQ,EAAE;AAC1D,SAAO;AACT;AAMO,SAAS,iBAAiB,EAAE,WAA4C;AAC7E,QAAM,SAAS,QAAQ,SAAS,aAAa,QAAQ,MAAM,IAAI,CAAA;AAC/D,QAAM,UAAU,QAAQ,UAAU,KAAK,MAAM,QAAQ,OAAO,IAAI;AAChE,SACE,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA,OAAO,SAAS,OAAO,KAAK,UAAU,KACrC,qBAAC,QAAA,EAAK,OAAO,IAAI,KAAK,OAAO,EAAE,eAAe,UAAA;AAAA,MAAA;AAAA,MAAS,IAAI,KAAK,OAAO,EAAE,mBAAA;AAAA,IAAmB,GAAE;AAAA,IAE/F,QAAQ,SAAS,QAAQ,MAAM,SAAS,yBAAM,QAAA,EAAM,UAAA,QAAQ,MAAM,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,EAAE,KAAK,GAAG,GAAE;AAAA,IACtG,QAAQ,aAAa,UAAa,qBAAC,QAAA,EAAK,UAAA;AAAA,MAAA;AAAA,MAAM,QAAQ;AAAA,IAAA,GAAS;AAAA,IAC/D,QAAQ,cAAc,qBAAC,QAAA,EAAK,UAAA;AAAA,MAAA;AAAA,MAAK,QAAQ;AAAA,MAAY;AAAA,IAAA,EAAA,CAAS,IAAU;AAAA,IACxE,OAAO,SAAS,KAAK,oBAAC,QAAA,EAAK,OAAM,kDAAkD,UAAA,OAAO,KAAK,KAAK,EAAA,CAAE;AAAA,EAAA,GACzG;AAEJ;"}
|
|
@@ -8,11 +8,12 @@ const CopyButton = require("../components/CopyButton.cjs");
|
|
|
8
8
|
const SplitButton = require("../components/SplitButton.cjs");
|
|
9
9
|
const clipboard = require("../components/clipboard.cjs");
|
|
10
10
|
const utils = require("../lib/utils.cjs");
|
|
11
|
-
const AnsiHtml = require("./AnsiHtml.cjs");
|
|
12
11
|
const Icon = require("./Icon.cjs");
|
|
13
12
|
const ProgressBar = require("./ProgressBar.cjs");
|
|
14
13
|
const TaskProcessDetails = require("./TaskProcessDetails.cjs");
|
|
15
14
|
const TaskExecDetails = require("./TaskExecDetails.cjs");
|
|
15
|
+
const TaskHeaderExtras = require("./TaskHeaderExtras.cjs");
|
|
16
|
+
const TaskStreamTabs = require("./TaskStreamTabs.cjs");
|
|
16
17
|
const taskCopy = require("./task-copy.cjs");
|
|
17
18
|
const taskExecDetails = require("./task-exec-details.cjs");
|
|
18
19
|
const taskProcessDetails = require("./task-process-details.cjs");
|
|
@@ -34,7 +35,9 @@ function TaskProgress({
|
|
|
34
35
|
onControl,
|
|
35
36
|
onTaskControl,
|
|
36
37
|
metricsBaseUrl,
|
|
37
|
-
connectionStatus
|
|
38
|
+
connectionStatus,
|
|
39
|
+
extraTabs,
|
|
40
|
+
headerExtra
|
|
38
41
|
}) {
|
|
39
42
|
const groups = snapshots.filter((s) => s.type === "group");
|
|
40
43
|
const tasks = snapshots.filter((s) => s.type === "task");
|
|
@@ -55,7 +58,9 @@ function TaskProgress({
|
|
|
55
58
|
...onControl ? { onControl } : {},
|
|
56
59
|
...onTaskControl ? { onTaskControl } : {},
|
|
57
60
|
...metricsBaseUrl ? { metricsBaseUrl } : {},
|
|
58
|
-
...connectionStatus ? { connectionStatus } : {}
|
|
61
|
+
...connectionStatus ? { connectionStatus } : {},
|
|
62
|
+
...extraTabs ? { extraTabs } : {},
|
|
63
|
+
...headerExtra ? { headerExtra } : {}
|
|
59
64
|
},
|
|
60
65
|
g.groupId || g.id
|
|
61
66
|
))
|
|
@@ -68,7 +73,9 @@ function TaskGroupCard({
|
|
|
68
73
|
onControl,
|
|
69
74
|
onTaskControl,
|
|
70
75
|
metricsBaseUrl,
|
|
71
|
-
connectionStatus
|
|
76
|
+
connectionStatus,
|
|
77
|
+
extraTabs,
|
|
78
|
+
headerExtra
|
|
72
79
|
}) {
|
|
73
80
|
const [showAll, setShowAll] = react.useState(false);
|
|
74
81
|
const { state: copyState, copy } = clipboard.useCopyFlash();
|
|
@@ -173,7 +180,9 @@ function TaskGroupCard({
|
|
|
173
180
|
group: g,
|
|
174
181
|
...onTaskControl ? { onTaskControl } : {},
|
|
175
182
|
...metricsBaseUrl ? { metricsBaseUrl } : {},
|
|
176
|
-
...connectionStatus ? { connectionStatus } : {}
|
|
183
|
+
...connectionStatus ? { connectionStatus } : {},
|
|
184
|
+
...extraTabs ? { extraTabs } : {},
|
|
185
|
+
...headerExtra ? { headerExtra } : {}
|
|
177
186
|
},
|
|
178
187
|
t.id
|
|
179
188
|
))
|
|
@@ -184,12 +193,16 @@ function TaskRow({
|
|
|
184
193
|
group,
|
|
185
194
|
onTaskControl,
|
|
186
195
|
metricsBaseUrl,
|
|
187
|
-
connectionStatus
|
|
196
|
+
connectionStatus,
|
|
197
|
+
extraTabs: contributeTabs,
|
|
198
|
+
headerExtra
|
|
188
199
|
}) {
|
|
189
200
|
const [expanded, setExpanded] = react.useState(false);
|
|
190
201
|
const logs = t.logs ?? [];
|
|
191
202
|
const hasLogs = logs.length > 0;
|
|
192
|
-
const
|
|
203
|
+
const extraTabs = (contributeTabs == null ? void 0 : contributeTabs(t, group)) ?? [];
|
|
204
|
+
const header = (headerExtra == null ? void 0 : headerExtra(t, group)) ?? /* @__PURE__ */ jsxRuntime.jsx(TaskHeaderExtras.TaskMetadataChips, { task: t });
|
|
205
|
+
const hasOutput = !!t.stdout || !!t.stderr || extraTabs.length > 0;
|
|
193
206
|
const execDetails = taskExecDetails.isTaskExecDetails(t.details) ? t.details : void 0;
|
|
194
207
|
const processDetails = taskProcessDetails.isTaskProcessDetails(t.details) ? t.details : void 0;
|
|
195
208
|
const expandable = hasLogs || hasOutput || execDetails !== void 0 || processDetails !== void 0;
|
|
@@ -221,6 +234,7 @@ function TaskRow({
|
|
|
221
234
|
latestWarn && /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils.cn("truncate text-xs font-normal", taskStatus.logLevelColor("warn")), children: latestWarn.message }),
|
|
222
235
|
expandable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 text-[10px] font-medium text-muted-foreground", children: logs.length + (t.stdout ? 1 : 0) + (t.stderr ? 1 : 0) + (execDetails || processDetails ? 1 : 0) })
|
|
223
236
|
] }),
|
|
237
|
+
header,
|
|
224
238
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
225
239
|
t.duration && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: t.duration }),
|
|
226
240
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -275,35 +289,12 @@ function TaskRow({
|
|
|
275
289
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1 font-mono text-muted-foreground", children: l.level.substring(0, 3) }),
|
|
276
290
|
l.message
|
|
277
291
|
] }, i)) }),
|
|
278
|
-
expanded &&
|
|
279
|
-
t.stdout && /* @__PURE__ */ jsxRuntime.jsx(TaskStream, { label: "stdout", text: t.stdout, ...t.stdoutTruncated ? { truncated: true } : {} }),
|
|
280
|
-
t.stderr && /* @__PURE__ */ jsxRuntime.jsx(TaskStream, { label: "stderr", text: t.stderr, ...t.stderrTruncated ? { truncated: true } : {}, error: true })
|
|
281
|
-
] })
|
|
292
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsx(TaskStreamTabs.TaskStreamTabs, { task: t, ...extraTabs.length > 0 ? { extraTabs } : {} })
|
|
282
293
|
] })
|
|
283
294
|
]
|
|
284
295
|
}
|
|
285
296
|
);
|
|
286
297
|
}
|
|
287
|
-
function TaskStream({
|
|
288
|
-
label,
|
|
289
|
-
text,
|
|
290
|
-
truncated,
|
|
291
|
-
error
|
|
292
|
-
}) {
|
|
293
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded border bg-black", children: [
|
|
294
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-b border-white/10 px-2 py-1 text-[10px] text-gray-400", children: [
|
|
295
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
|
|
296
|
-
truncated && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "showing latest 1 MiB" })
|
|
297
|
-
] }),
|
|
298
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
299
|
-
AnsiHtml.AnsiHtml,
|
|
300
|
-
{
|
|
301
|
-
text,
|
|
302
|
-
className: utils.cn("max-h-64 overflow-auto whitespace-pre-wrap p-2 text-xs text-gray-100", error && "text-red-300")
|
|
303
|
-
}
|
|
304
|
-
)
|
|
305
|
-
] });
|
|
306
|
-
}
|
|
307
298
|
function TaskControls({
|
|
308
299
|
target,
|
|
309
300
|
onControl,
|
|
@@ -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, UiRestart, UiStop, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { AnsiHtml } from \"./AnsiHtml\";\nimport { Icon } from \"./Icon\";\nimport { ProgressBar } from \"./ProgressBar\";\nimport { TaskProcessDetailsView } from \"./TaskProcessDetails\";\nimport { TaskExecDetailsView } from \"./TaskExecDetails\";\nimport type { LogEntry, TaskControlAction, TaskSnapshot } from \"./TaskSnapshot\";\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\nexport function TaskProgress({\n snapshots,\n title,\n compact,\n className,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\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 />\n ))}\n </div>\n );\n}\n\nfunction TaskGroupCard({\n group: g,\n tasks,\n compact,\n onControl,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n}: {\n group: TaskSnapshot;\n tasks: TaskSnapshot[];\n compact: boolean | undefined;\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 />\n ))}\n </div>\n );\n}\n\nfunction TaskRow({\n task: t,\n group,\n onTaskControl,\n metricsBaseUrl,\n connectionStatus,\n}: {\n task: TaskSnapshot;\n group: TaskSnapshot;\n metricsBaseUrl?: string;\n connectionStatus?: string;\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 hasOutput = !!t.stdout || !!t.stderr;\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 <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 && hasOutput && (\n <div className=\"mt-2 space-y-2\">\n {t.stdout && <TaskStream label=\"stdout\" text={t.stdout} {...(t.stdoutTruncated ? { truncated: true } : {})} />}\n {t.stderr && <TaskStream label=\"stderr\" text={t.stderr} {...(t.stderrTruncated ? { truncated: true } : {})} error />}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction TaskStream({\n label,\n text,\n truncated,\n error,\n}: {\n label: string;\n text: string;\n truncated?: boolean;\n error?: boolean;\n}) {\n return (\n <div className=\"overflow-hidden rounded border bg-black\">\n <div className=\"flex items-center justify-between border-b border-white/10 px-2 py-1 text-[10px] text-gray-400\">\n <span>{label}</span>\n {truncated && <span>showing latest 1 MiB</span>}\n </div>\n <AnsiHtml\n text={text}\n className={cn(\"max-h-64 overflow-auto whitespace-pre-wrap p-2 text-xs text-gray-100\", error && \"text-red-300\")}\n />\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 = { start: UiPlay, stop: UiStop, restart: UiRestart, drain: UiStop };\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","logLevelColor","CopyButton","taskMarkdown","AnsiHtml","UiPlay","UiStop","UiRestart","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, 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 = { start: UiPlay, stop: UiStop, restart: UiRestart, drain: UiStop };\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","Fragment","Button"],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { TaskControlAction, TaskSnapshot } from './TaskSnapshot';
|
|
2
|
+
import { TaskHeaderExtra } from './TaskHeaderExtras';
|
|
3
|
+
import { TaskExtraTabs } from './TaskStreamTabs';
|
|
2
4
|
export interface TaskProgressProps {
|
|
3
5
|
snapshots: TaskSnapshot[];
|
|
4
6
|
title?: string;
|
|
@@ -9,6 +11,17 @@ export interface TaskProgressProps {
|
|
|
9
11
|
onTaskControl?: (action: TaskControlAction, task: TaskSnapshot, group: TaskSnapshot) => void | Promise<void>;
|
|
10
12
|
metricsBaseUrl?: string;
|
|
11
13
|
connectionStatus?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Contributes host-owned output panes alongside a task's own stdout/stderr —
|
|
16
|
+
* an agent's session transcript, say, which this module has no way to fetch.
|
|
17
|
+
*/
|
|
18
|
+
extraTabs?: TaskExtraTabs;
|
|
19
|
+
/**
|
|
20
|
+
* Replaces the content beside a task's name in its header row. Returning null
|
|
21
|
+
* for a task falls back to the default, which chips the scalar values of its
|
|
22
|
+
* process metadata.
|
|
23
|
+
*/
|
|
24
|
+
headerExtra?: TaskHeaderExtra;
|
|
12
25
|
}
|
|
13
|
-
export declare function TaskProgress({ snapshots, title, compact, className, onControl, onTaskControl, metricsBaseUrl, connectionStatus, }: TaskProgressProps): import("react").JSX.Element;
|
|
26
|
+
export declare function TaskProgress({ snapshots, title, compact, className, onControl, onTaskControl, metricsBaseUrl, connectionStatus, extraTabs, headerExtra, }: TaskProgressProps): import("react").JSX.Element;
|
|
14
27
|
//# sourceMappingURL=TaskProgress.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskProgress.d.ts","sourceRoot":"","sources":["../../src/data/TaskProgress.tsx"],"names":[],"mappings":"
|
|
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,+BA+BnB"}
|