sidekick-docker 0.1.4 → 0.1.5

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.
@@ -39518,22 +39518,32 @@ var require_DockerClient = __commonJS({
39518
39518
  }
39519
39519
  async listContainers(all = true) {
39520
39520
  const containers = await this.docker.listContainers({ all });
39521
- return containers.map((c) => ({
39522
- id: c.Id,
39523
- name: (c.Names[0] || "").replace(/^\//, ""),
39524
- image: c.Image,
39525
- state: c.State,
39526
- status: c.Status,
39527
- ports: (c.Ports || []).map((p) => ({
39528
- hostIp: p.IP || "0.0.0.0",
39529
- hostPort: p.PublicPort || 0,
39530
- containerPort: p.PrivatePort,
39531
- protocol: p.Type || "tcp"
39532
- })),
39533
- created: new Date(c.Created * 1e3),
39534
- composeProject: c.Labels?.["com.docker.compose.project"],
39535
- composeService: c.Labels?.["com.docker.compose.service"]
39536
- }));
39521
+ return containers.map((c) => {
39522
+ let healthStatus;
39523
+ if (/\(healthy\)/.test(c.Status))
39524
+ healthStatus = "healthy";
39525
+ else if (/\(unhealthy\)/.test(c.Status))
39526
+ healthStatus = "unhealthy";
39527
+ else if (/\(health: starting\)/.test(c.Status))
39528
+ healthStatus = "starting";
39529
+ return {
39530
+ id: c.Id,
39531
+ name: (c.Names[0] || "").replace(/^\//, ""),
39532
+ image: c.Image,
39533
+ state: c.State,
39534
+ status: c.Status,
39535
+ ports: (c.Ports || []).map((p) => ({
39536
+ hostIp: p.IP || "0.0.0.0",
39537
+ hostPort: p.PublicPort || 0,
39538
+ containerPort: p.PrivatePort,
39539
+ protocol: p.Type || "tcp"
39540
+ })),
39541
+ created: new Date(c.Created * 1e3),
39542
+ composeProject: c.Labels?.["com.docker.compose.project"],
39543
+ composeService: c.Labels?.["com.docker.compose.service"],
39544
+ healthStatus
39545
+ };
39546
+ });
39537
39547
  }
39538
39548
  async startContainer(id) {
39539
39549
  await this.docker.getContainer(id).start();
@@ -39544,6 +39554,12 @@ var require_DockerClient = __commonJS({
39544
39554
  async restartContainer(id) {
39545
39555
  await this.docker.getContainer(id).restart();
39546
39556
  }
39557
+ async pauseContainer(id) {
39558
+ await this.docker.getContainer(id).pause();
39559
+ }
39560
+ async unpauseContainer(id) {
39561
+ await this.docker.getContainer(id).unpause();
39562
+ }
39547
39563
  async removeContainer(id, force = false) {
39548
39564
  await this.docker.getContainer(id).remove({ force });
39549
39565
  }
@@ -39605,6 +39621,7 @@ var require_DockerClient = __commonJS({
39605
39621
  const memStats = raw.memory_stats;
39606
39622
  const netStats = raw.networks;
39607
39623
  const pidsStats = raw.pids_stats;
39624
+ const blkioStats = raw.blkio_stats;
39608
39625
  const cpuUsage = cpuStats?.cpu_usage?.total_usage ?? 0;
39609
39626
  const systemUsage = cpuStats?.system_cpu_usage ?? 0;
39610
39627
  const numCpus = cpuStats?.cpu_usage?.percpu_usage?.length ?? cpuStats?.online_cpus ?? 1;
@@ -39622,6 +39639,18 @@ var require_DockerClient = __commonJS({
39622
39639
  netTx += iface.tx_bytes ?? 0;
39623
39640
  }
39624
39641
  }
39642
+ let blockRead = 0;
39643
+ let blockWrite = 0;
39644
+ const ioServiceBytes = blkioStats?.io_service_bytes_recursive;
39645
+ if (ioServiceBytes) {
39646
+ for (const entry of ioServiceBytes) {
39647
+ const op = (entry.op || "").toLowerCase();
39648
+ if (op === "read")
39649
+ blockRead += entry.value ?? 0;
39650
+ else if (op === "write")
39651
+ blockWrite += entry.value ?? 0;
39652
+ }
39653
+ }
39625
39654
  return {
39626
39655
  stats: {
39627
39656
  cpuPercent: Math.round(cpuPercent * 100) / 100,
@@ -39630,6 +39659,8 @@ var require_DockerClient = __commonJS({
39630
39659
  memoryPercent: Math.round(memPercent * 100) / 100,
39631
39660
  networkRx: netRx,
39632
39661
  networkTx: netTx,
39662
+ blockRead,
39663
+ blockWrite,
39633
39664
  pids: pidsStats?.current ?? 0,
39634
39665
  timestamp: /* @__PURE__ */ new Date()
39635
39666
  },
@@ -40131,6 +40162,36 @@ var require_StatsCollector = __commonJS({
40131
40162
  return void 0;
40132
40163
  return history.samples[history.samples.length - 1];
40133
40164
  }
40165
+ getNetworkRxRateSeries(containerId) {
40166
+ return this.computeRateSeries(containerId, (s) => s.networkRx);
40167
+ }
40168
+ getNetworkTxRateSeries(containerId) {
40169
+ return this.computeRateSeries(containerId, (s) => s.networkTx);
40170
+ }
40171
+ getBlockReadRateSeries(containerId) {
40172
+ return this.computeRateSeries(containerId, (s) => s.blockRead);
40173
+ }
40174
+ getBlockWriteRateSeries(containerId) {
40175
+ return this.computeRateSeries(containerId, (s) => s.blockWrite);
40176
+ }
40177
+ computeRateSeries(containerId, extractor) {
40178
+ const history = this.histories.get(containerId);
40179
+ if (!history || history.samples.length < 2)
40180
+ return [];
40181
+ const rates = [];
40182
+ for (let i = 1; i < history.samples.length; i++) {
40183
+ const prev = history.samples[i - 1];
40184
+ const curr = history.samples[i];
40185
+ const dt = (curr.timestamp.getTime() - prev.timestamp.getTime()) / 1e3;
40186
+ if (dt > 0) {
40187
+ const delta = extractor(curr) - extractor(prev);
40188
+ rates.push(Math.max(0, delta / dt));
40189
+ } else {
40190
+ rates.push(0);
40191
+ }
40192
+ }
40193
+ return rates;
40194
+ }
40134
40195
  remove(containerId) {
40135
40196
  this.histories.delete(containerId);
40136
40197
  }
@@ -78294,6 +78355,16 @@ function colorizeDetailKey(line) {
78294
78355
  if (!match) return line;
78295
78356
  return ansi.brand(match[1]) + line.substring(match[1].length);
78296
78357
  }
78358
+ function colorizeHealth(status) {
78359
+ switch (status) {
78360
+ case "healthy":
78361
+ return ansi.green(status);
78362
+ case "unhealthy":
78363
+ return ansi.red(status);
78364
+ case "starting":
78365
+ return ansi.yellow(status);
78366
+ }
78367
+ }
78297
78368
  function colorizeState(state) {
78298
78369
  switch (state) {
78299
78370
  case "running":
@@ -78417,7 +78488,22 @@ var ContainersPanel = class {
78417
78488
  lines.push(` ${coloredSparkline(memSeries, "memory")}`);
78418
78489
  }
78419
78490
  lines.push(
78420
- colorizeDetailKey(`Net: \u25BC ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkRx)} \u25B2 ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkTx)}`),
78491
+ colorizeDetailKey(`Net: \u25BC ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkRx)} \u25B2 ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkTx)}`)
78492
+ );
78493
+ const rxRates = metrics.statsCollector.getNetworkRxRateSeries(c.id);
78494
+ const txRates = metrics.statsCollector.getNetworkTxRateSeries(c.id);
78495
+ if (rxRates.length > 1) {
78496
+ lines.push(` \u25BC ${coloredSparkline(rxRates, "cpu")} \u25B2 ${coloredSparkline(txRates, "memory")}`);
78497
+ }
78498
+ lines.push(
78499
+ colorizeDetailKey(`IO: R ${(0, import_sidekick_docker_shared3.formatBytes)(latest.blockRead)} W ${(0, import_sidekick_docker_shared3.formatBytes)(latest.blockWrite)}`)
78500
+ );
78501
+ const brRates = metrics.statsCollector.getBlockReadRateSeries(c.id);
78502
+ const bwRates = metrics.statsCollector.getBlockWriteRateSeries(c.id);
78503
+ if (brRates.length > 1) {
78504
+ lines.push(` R ${coloredSparkline(brRates, "cpu")} W ${coloredSparkline(bwRates, "memory")}`);
78505
+ }
78506
+ lines.push(
78421
78507
  colorizeDetailKey(`PIDs: ${latest.pids}`)
78422
78508
  );
78423
78509
  if (metrics.logSeverityTimeSeries.length > 1) {
@@ -78451,6 +78537,7 @@ var ContainersPanel = class {
78451
78537
  sectionHeader("Status"),
78452
78538
  colorizeDetailKey(` State: ${colorizeState(c.state)}`),
78453
78539
  colorizeDetailKey(` Status: ${c.status}`),
78540
+ ...c.healthStatus ? [colorizeDetailKey(` Health: ${colorizeHealth(c.healthStatus)}`)] : [],
78454
78541
  colorizeDetailKey(` Created: ${c.created.toLocaleString()}`),
78455
78542
  "",
78456
78543
  sectionHeader("Network"),
@@ -78485,10 +78572,11 @@ var ContainersPanel = class {
78485
78572
  return metrics.containers.map((c) => {
78486
78573
  const uptime = compactUptime(c.status);
78487
78574
  const portHint = c.state === "running" && c.ports.length > 0 ? `:${c.ports[0].hostPort || c.ports[0].containerPort}` : "";
78575
+ const healthBadge = c.healthStatus ? ` ${colorizeHealth(c.healthStatus)}` : "";
78488
78576
  const namePart = portHint ? `${(0, import_sidekick_docker_shared3.truncate)(c.name, 34)} ${portHint}` : (0, import_sidekick_docker_shared3.truncate)(c.name, 38);
78489
78577
  return {
78490
78578
  id: c.id,
78491
- label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}`,
78579
+ label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}${healthBadge}`,
78492
78580
  sortKey: c.state === "running" ? 0 : 1,
78493
78581
  data: c,
78494
78582
  iconColor: (0, import_sidekick_docker_shared3.stateColor)(c.state),
@@ -78526,6 +78614,24 @@ var ContainersPanel = class {
78526
78614
  },
78527
78615
  condition: (item) => item.data.state === "running"
78528
78616
  },
78617
+ {
78618
+ key: "p",
78619
+ label: "Pause",
78620
+ handler: (item) => {
78621
+ const c = item.data;
78622
+ this.client.pauseContainer(c.id).then(() => this.onAction()).catch((e) => this.onError(String(e)));
78623
+ },
78624
+ condition: (item) => item.data.state === "running"
78625
+ },
78626
+ {
78627
+ key: "u",
78628
+ label: "Unpause",
78629
+ handler: (item) => {
78630
+ const c = item.data;
78631
+ this.client.unpauseContainer(c.id).then(() => this.onAction()).catch((e) => this.onError(String(e)));
78632
+ },
78633
+ condition: (item) => item.data.state === "paused"
78634
+ },
78529
78635
  {
78530
78636
  key: "d",
78531
78637
  label: "Remove",
@@ -79253,6 +79359,7 @@ function useWindowedScroll({ totalItems, viewportHeight }) {
79253
79359
 
79254
79360
  // src/dashboard/ink/useKeyboardHandler.ts
79255
79361
  await init_build2();
79362
+ var SORT_FIELDS = ["state", "name", "cpu", "mem", "net", "io", "pids"];
79256
79363
  function executeAction(action, item, dispatch, addToast) {
79257
79364
  if (action.confirm) {
79258
79365
  dispatch({ type: "SET_CONFIRM", action: () => {
@@ -79376,6 +79483,32 @@ function useKeyboardHandler(ctx) {
79376
79483
  }
79377
79484
  return;
79378
79485
  }
79486
+ if (state.overlay === "sort") {
79487
+ if (key.escape) {
79488
+ dispatch({ type: "SET_OVERLAY", overlay: null });
79489
+ return;
79490
+ }
79491
+ if (input === "j" || key.downArrow) {
79492
+ dispatch({ type: "SORT_MENU_NAV", delta: 1 });
79493
+ return;
79494
+ }
79495
+ if (input === "k" || key.upArrow) {
79496
+ dispatch({ type: "SORT_MENU_NAV", delta: -1 });
79497
+ return;
79498
+ }
79499
+ if (input === "R") {
79500
+ dispatch({ type: "TOGGLE_SORT_REVERSE" });
79501
+ addToast(`Sort: ${state.sortReversed ? "ascending" : "descending"}`, "info");
79502
+ return;
79503
+ }
79504
+ if (key.return) {
79505
+ const field = SORT_FIELDS[state.sortMenuIndex];
79506
+ dispatch({ type: "SET_SORT_FIELD", field });
79507
+ addToast(`Sort: ${field}`, "info");
79508
+ return;
79509
+ }
79510
+ return;
79511
+ }
79379
79512
  if (key.escape) {
79380
79513
  if (state.filterString) {
79381
79514
  dispatch({ type: "SET_FILTER", value: "" });
@@ -79422,6 +79555,20 @@ function useKeyboardHandler(ctx) {
79422
79555
  return;
79423
79556
  }
79424
79557
  }
79558
+ if (input === "a" && panel.id === "containers") {
79559
+ dispatch({ type: "TOGGLE_SHOW_ALL" });
79560
+ addToast(state.showAllContainers ? "Running only" : "Show all", "info");
79561
+ return;
79562
+ }
79563
+ if (input === "o" && panel.id === "containers") {
79564
+ dispatch({ type: "SET_OVERLAY", overlay: "sort" });
79565
+ return;
79566
+ }
79567
+ if (input === "R" && panel.id === "containers") {
79568
+ dispatch({ type: "TOGGLE_SORT_REVERSE" });
79569
+ addToast(`Sort: ${state.sortReversed ? "ascending" : "descending"}`, "info");
79570
+ return;
79571
+ }
79425
79572
  if (input === "x") {
79426
79573
  if (selectedItem && panelActions.length > 0) {
79427
79574
  dispatch({ type: "SET_OVERLAY", overlay: "context-menu" });
@@ -79796,6 +79943,9 @@ var GLOBAL_BINDINGS = [
79796
79943
  { key: "z", label: "Cycle layout (Normal/Wide/Expanded)" },
79797
79944
  { key: "/", label: "Filter items" },
79798
79945
  { key: "x", label: "Actions menu" },
79946
+ { key: "a", label: "Toggle all/running (Containers)" },
79947
+ { key: "o", label: "Sort menu (Containers)" },
79948
+ { key: "R", label: "Reverse sort (Containers)" },
79799
79949
  { key: "V", label: "Version info" },
79800
79950
  { key: "?", label: "This help" },
79801
79951
  { key: "q", label: "Quit" }
@@ -80134,6 +80284,52 @@ function VersionOverlay({ version: version2 }) {
80134
80284
  ] });
80135
80285
  }
80136
80286
 
80287
+ // src/dashboard/ink/SortOverlay.tsx
80288
+ await init_build2();
80289
+ var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
80290
+ var SORT_OPTIONS = [
80291
+ { field: "state", label: "State (running first)" },
80292
+ { field: "name", label: "Name" },
80293
+ { field: "cpu", label: "CPU %" },
80294
+ { field: "mem", label: "Memory %" },
80295
+ { field: "net", label: "Network I/O" },
80296
+ { field: "io", label: "Block I/O" },
80297
+ { field: "pids", label: "PIDs" }
80298
+ ];
80299
+ function SortOverlay({ selectedIndex, currentField, reversed }) {
80300
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
80301
+ Box_default,
80302
+ {
80303
+ position: "absolute",
80304
+ marginTop: 2,
80305
+ marginLeft: 2,
80306
+ flexDirection: "column",
80307
+ borderStyle: "single",
80308
+ borderColor: "#2B4C7E",
80309
+ paddingX: 1,
80310
+ children: [
80311
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { bold: true, color: "#2B4C7E", children: "\u2195 Sort by" }),
80312
+ SORT_OPTIONS.map((opt, i) => {
80313
+ const isSelected = i === selectedIndex;
80314
+ const isCurrent = opt.field === currentField;
80315
+ const indicator = isCurrent ? reversed ? " \u25B2" : " \u25BC" : "";
80316
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80317
+ Text,
80318
+ {
80319
+ color: isSelected ? "#2B4C7E" : isCurrent ? "yellow" : "white",
80320
+ bold: isSelected,
80321
+ inverse: isSelected,
80322
+ children: ` ${opt.label}${indicator} `
80323
+ }
80324
+ ) }, opt.field);
80325
+ }),
80326
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: "" }),
80327
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "gray", dimColor: true, children: "j/k select Enter apply R reverse Esc close" })
80328
+ ]
80329
+ }
80330
+ );
80331
+ }
80332
+
80137
80333
  // src/dashboard/ink/Dashboard.tsx
80138
80334
  var import_sidekick_docker_shared12 = __toESM(require_dist(), 1);
80139
80335
 
@@ -80192,7 +80388,8 @@ var ExecManager = class {
80192
80388
  };
80193
80389
 
80194
80390
  // src/dashboard/ink/Dashboard.tsx
80195
- var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
80391
+ var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
80392
+ var SORT_FIELDS2 = ["state", "name", "cpu", "mem", "net", "io", "pids"];
80196
80393
  var SIDE_PANEL_WIDTH = 28;
80197
80394
  var SIDE_PANEL_WIDTH_WIDE = 42;
80198
80395
  var MIN_SCREEN_WIDTH = 60;
@@ -80279,6 +80476,16 @@ function reducer(state, action) {
80279
80476
  return { ...state, logFilterString: action.value };
80280
80477
  case "TOGGLE_LOG_FILTER_MODE":
80281
80478
  return { ...state, logFilterMode: state.logFilterMode === "exact" ? "fuzzy" : "exact" };
80479
+ case "TOGGLE_SHOW_ALL":
80480
+ return { ...state, showAllContainers: !state.showAllContainers, selectedItemIndex: 0 };
80481
+ case "SET_SORT_FIELD":
80482
+ return { ...state, sortField: action.field, overlay: null };
80483
+ case "TOGGLE_SORT_REVERSE":
80484
+ return { ...state, sortReversed: !state.sortReversed };
80485
+ case "SORT_MENU_NAV": {
80486
+ const next = (state.sortMenuIndex + action.delta + SORT_FIELDS2.length) % SORT_FIELDS2.length;
80487
+ return { ...state, sortMenuIndex: next };
80488
+ }
80282
80489
  default:
80283
80490
  return state;
80284
80491
  }
@@ -80300,7 +80507,11 @@ var initialState = {
80300
80507
  execContainerId: null,
80301
80508
  execContainerName: "",
80302
80509
  logFilterString: "",
80303
- logFilterMode: "exact"
80510
+ logFilterMode: "exact",
80511
+ showAllContainers: true,
80512
+ sortField: "state",
80513
+ sortReversed: false,
80514
+ sortMenuIndex: 0
80304
80515
  };
80305
80516
  function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecFallback }) {
80306
80517
  const [state, dispatch] = (0, import_react36.useReducer)(reducer, initialState);
@@ -80391,6 +80602,12 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80391
80602
  const totalItemCount = allItems.length;
80392
80603
  const currentItems = (() => {
80393
80604
  let items = allItems;
80605
+ if (panel.id === "containers" && !state.showAllContainers) {
80606
+ items = items.filter((it) => {
80607
+ const c = it.data;
80608
+ return c.state === "running" || c.state === "paused";
80609
+ });
80610
+ }
80394
80611
  if (state.filterString) {
80395
80612
  const f = state.filterString.toLowerCase();
80396
80613
  items = items.filter((it) => {
@@ -80398,7 +80615,47 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80398
80615
  return text.toLowerCase().includes(f);
80399
80616
  });
80400
80617
  }
80401
- items.sort((a, b) => a.sortKey - b.sortKey);
80618
+ if (panel.id === "containers" && state.sortField !== "state") {
80619
+ const dir = state.sortReversed ? -1 : 1;
80620
+ items.sort((a, b) => {
80621
+ const ca = a.data;
80622
+ const cb = b.data;
80623
+ switch (state.sortField) {
80624
+ case "name":
80625
+ return dir * ca.name.localeCompare(cb.name);
80626
+ case "cpu": {
80627
+ const sa = metrics.statsCollector.getLatest(ca.id)?.cpuPercent ?? 0;
80628
+ const sb = metrics.statsCollector.getLatest(cb.id)?.cpuPercent ?? 0;
80629
+ return dir * (sb - sa);
80630
+ }
80631
+ case "mem": {
80632
+ const sa = metrics.statsCollector.getLatest(ca.id)?.memoryPercent ?? 0;
80633
+ const sb = metrics.statsCollector.getLatest(cb.id)?.memoryPercent ?? 0;
80634
+ return dir * (sb - sa);
80635
+ }
80636
+ case "net": {
80637
+ const sa = metrics.statsCollector.getLatest(ca.id);
80638
+ const sb = metrics.statsCollector.getLatest(cb.id);
80639
+ return dir * ((sb?.networkRx ?? 0) + (sb?.networkTx ?? 0) - ((sa?.networkRx ?? 0) + (sa?.networkTx ?? 0)));
80640
+ }
80641
+ case "io": {
80642
+ const sa = metrics.statsCollector.getLatest(ca.id);
80643
+ const sb = metrics.statsCollector.getLatest(cb.id);
80644
+ return dir * ((sb?.blockRead ?? 0) + (sb?.blockWrite ?? 0) - ((sa?.blockRead ?? 0) + (sa?.blockWrite ?? 0)));
80645
+ }
80646
+ case "pids": {
80647
+ const sa = metrics.statsCollector.getLatest(ca.id)?.pids ?? 0;
80648
+ const sb = metrics.statsCollector.getLatest(cb.id)?.pids ?? 0;
80649
+ return dir * (sb - sa);
80650
+ }
80651
+ default:
80652
+ return a.sortKey - b.sortKey;
80653
+ }
80654
+ });
80655
+ } else {
80656
+ const dir = state.sortReversed ? -1 : 1;
80657
+ items.sort((a, b) => dir * (a.sortKey - b.sortKey));
80658
+ }
80402
80659
  return items;
80403
80660
  })();
80404
80661
  const clampedSelection = Math.min(state.selectedItemIndex, Math.max(0, currentItems.length - 1));
@@ -80487,14 +80744,14 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80487
80744
  rotatePhrase
80488
80745
  });
80489
80746
  if (tooSmall) {
80490
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooSmallOverlay, { columns, rows });
80747
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooSmallOverlay, { columns, rows });
80491
80748
  }
80492
80749
  const showNormalLayout = state.overlay !== "help" && state.overlay !== "exec" && state.overlay !== "version";
80493
80750
  const panelActionHints = applicableActions.map((a) => ({ key: a.key, label: a.label, destructive: !!a.confirm }));
80494
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MouseProvider, { onMouse: handleMouse, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", height: rows, width: columns, children: [
80495
- showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TabBar, { panels, activeIndex: state.activePanelIndex, layoutMode: state.layoutMode, phrase, panelCounts }),
80496
- showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexGrow: 1, flexDirection: "row", children: [
80497
- sideWidth > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80751
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MouseProvider, { onMouse: handleMouse, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "column", height: rows, width: columns, children: [
80752
+ showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TabBar, { panels, activeIndex: state.activePanelIndex, layoutMode: state.layoutMode, phrase, panelCounts }),
80753
+ showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexGrow: 1, flexDirection: "row", children: [
80754
+ sideWidth > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80498
80755
  SideList,
80499
80756
  {
80500
80757
  items: currentItems,
@@ -80510,9 +80767,9 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80510
80767
  runningCount: panel.id === "containers" ? runningCount : void 0
80511
80768
  }
80512
80769
  ),
80513
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
80514
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DetailTabBar, { tabs: detailTabs, activeIndex: state.detailTabIndex }),
80515
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80770
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
80771
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DetailTabBar, { tabs: detailTabs, activeIndex: state.detailTabIndex }),
80772
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80516
80773
  DetailPane,
80517
80774
  {
80518
80775
  content: detailContent,
@@ -80523,16 +80780,16 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80523
80780
  )
80524
80781
  ] })
80525
80782
  ] }),
80526
- state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.1.4" }),
80527
- state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VersionOverlay, { version: "0.1.4" }),
80528
- state.overlay === "exec" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80783
+ state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.1.5" }),
80784
+ state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VersionOverlay, { version: "0.1.5" }),
80785
+ state.overlay === "exec" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80529
80786
  ExecOverlay,
80530
80787
  {
80531
80788
  containerName: state.execContainerName,
80532
80789
  outputLines: state.execOutputLines
80533
80790
  }
80534
80791
  ),
80535
- state.overlay !== "exec" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80792
+ state.overlay !== "exec" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80536
80793
  StatusBar,
80537
80794
  {
80538
80795
  daemonConnected: metrics.daemonConnected,
@@ -80541,14 +80798,14 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80541
80798
  filterString: state.filterString,
80542
80799
  containerCount: metrics.containers.length,
80543
80800
  runningCount,
80544
- version: "0.1.4",
80801
+ version: "0.1.5",
80545
80802
  matchCount: state.filterString ? currentItems.length : void 0,
80546
80803
  totalCount: state.filterString ? totalItemCount : void 0,
80547
80804
  lastRefresh: metrics.lastRefresh
80548
80805
  }
80549
80806
  ),
80550
- state.overlay === "context-menu" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ContextMenuOverlay, { actions: contextActions, selectedIndex: state.contextMenuIndex }),
80551
- state.overlay === "filter" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80807
+ state.overlay === "context-menu" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ContextMenuOverlay, { actions: contextActions, selectedIndex: state.contextMenuIndex }),
80808
+ state.overlay === "filter" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80552
80809
  FilterOverlay,
80553
80810
  {
80554
80811
  filterString: state.filterString,
@@ -80557,14 +80814,15 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80557
80814
  panelTitle: panel.title
80558
80815
  }
80559
80816
  ),
80560
- state.overlay === "log-filter" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80817
+ state.overlay === "log-filter" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80561
80818
  LogFilterOverlay,
80562
80819
  {
80563
80820
  filterString: state.logFilterString,
80564
80821
  filterMode: state.logFilterMode
80565
80822
  }
80566
80823
  ),
80567
- state.overlay === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
80824
+ state.overlay === "sort" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SortOverlay, { selectedIndex: state.sortMenuIndex, currentField: state.sortField, reversed: state.sortReversed }),
80825
+ state.overlay === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
80568
80826
  ConfirmOverlay,
80569
80827
  {
80570
80828
  message: state.confirmMessage,
@@ -80575,7 +80833,7 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
80575
80833
  onCancel: () => dispatch({ type: "SET_CONFIRM", action: null, message: "" })
80576
80834
  }
80577
80835
  ),
80578
- state.toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToastNotification, { toast: state.toasts[state.toasts.length - 1] })
80836
+ state.toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ToastNotification, { toast: state.toasts[state.toasts.length - 1] })
80579
80837
  ] }) });
80580
80838
  }
80581
80839
 
@@ -80826,7 +81084,7 @@ async function logsAction(container, opts) {
80826
81084
 
80827
81085
  // src/cli.ts
80828
81086
  var program2 = new Command();
80829
- program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.1.4").option("--socket <path>", "Docker socket path").action(async (_opts, cmd) => {
81087
+ program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.1.5").option("--socket <path>", "Docker socket path").action(async (_opts, cmd) => {
80830
81088
  await dashboardAction(_opts, cmd);
80831
81089
  });
80832
81090
  program2.command("ps").description("List containers").option("-a, --all", "Show all containers (default: running only)", false).action(async (opts) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sidekick-docker",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Docker management TUI dashboard",
5
5
  "author": "Cesar Andres Lopez <cesarandreslopez@gmail.com>",
6
6
  "repository": {