dsh-plugin-container 0.4.6 → 0.5.0

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/lib/client.js CHANGED
@@ -109,7 +109,7 @@ function cacheClear(prefix = "") {
109
109
 
110
110
  // src/client/icons.jsx
111
111
  var import_jsx_runtime = require("react/jsx-runtime");
112
- function Svg({ size = 18, className, children, viewBox = "0 0 24 24", fill = "none" }) {
112
+ function Svg({ size = 18, className, children, viewBox = "0 0 24 24", fill: fill2 = "none" }) {
113
113
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
114
114
  "svg",
115
115
  {
@@ -117,8 +117,8 @@ function Svg({ size = 18, className, children, viewBox = "0 0 24 24", fill = "no
117
117
  width: size,
118
118
  height: size,
119
119
  viewBox,
120
- fill,
121
- stroke: fill === "none" ? "currentColor" : "none",
120
+ fill: fill2,
121
+ stroke: fill2 === "none" ? "currentColor" : "none",
122
122
  strokeWidth: "1.6",
123
123
  strokeLinecap: "round",
124
124
  strokeLinejoin: "round",
@@ -213,6 +213,8 @@ var IconInfo = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { ..
213
213
  ] });
214
214
  var IconX = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Svg, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6.5 6.5 11 11M17.5 6.5l-11 11" }) });
215
215
  var IconDownload = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Svg, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 4.5v10.2M7.8 10.6 12 14.8l4.2-4.2M5 18.8h14" }) });
216
+ var IconUpload = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Svg, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 15.5V5.3M7.8 9.4 12 5.2l4.2 4.2M5 18.8h14" }) });
217
+ var IconHammer = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Svg, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m13.2 8.4 2.4 2.4M10.6 11 4.8 16.8a1.7 1.7 0 0 0 2.4 2.4L13 13.4M12.4 5.6l3-3 5.6 5.6-3 3z" }) });
216
218
  var IconSparkles = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { ...props, children: [
217
219
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 4.5l1.2 3.3L16.5 9l-3.3 1.2L12 13.5l-1.2-3.3L7.5 9l3.3-1.2L12 4.5Z" }),
218
220
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 14l.7 1.8 1.8.7-1.8.7L18 19l-.7-1.8-1.8-.7 1.8-.7L18 14Z" }),
@@ -223,14 +225,6 @@ var IconExec = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { ..
223
225
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m7.2 9.2 3 2.8-3 2.8M12.5 15h4" }),
224
226
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 9.2h.01" })
225
227
  ] });
226
- var IconUpload = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { ...props, children: [
227
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 16V4M7.5 8.5 12 4l4.5 4.5" }),
228
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 15v3.5A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5V15" })
229
- ] });
230
- var IconBuild = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { ...props, children: [
231
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14.5 5.5 18.5 9.5M4 20l4.2-1 10.9-10.9a2.1 2.1 0 0 0-3-3L5.2 16 4 20Z" }),
232
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m13.2 6.8 4 4" })
233
- ] });
234
228
  var IconAttach = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { ...props, children: [
235
229
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9.5 14.5 14.5 9.5" }),
236
230
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 7.5 12.6 5.9a3.2 3.2 0 0 1 4.5 4.5L15.4 12" }),
@@ -350,17 +344,6 @@ var zh = {
350
344
  removeNetwork: "\u5220\u9664\u7F51\u7EDC",
351
345
  pull: "\u62C9\u53D6",
352
346
  pullPlaceholder: "nginx:latest",
353
- pushImage: "\u63A8\u9001\u955C\u50CF",
354
- buildImage: "\u6784\u5EFA\u955C\u50CF",
355
- buildImageTitle: "\u6784\u5EFA\u955C\u50CF",
356
- buildTag: "\u955C\u50CF\u6807\u7B7E",
357
- buildContext: "\u6784\u5EFA\u4E0A\u4E0B\u6587\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09",
358
- buildContextHint: "\u4F8B\u5982 /Users/me/project\uFF0C\u5FC5\u987B\u5305\u542B Dockerfile\u3002",
359
- buildDockerfile: "Dockerfile",
360
- buildNoCache: "\u4E0D\u4F7F\u7528\u6784\u5EFA\u7F13\u5B58",
361
- buildStart: "\u5F00\u59CB\u6784\u5EFA",
362
- buildInvalidTag: "\u8BF7\u8F93\u5165\u5408\u6CD5\u7684\u955C\u50CF\u6807\u7B7E\uFF0C\u4F8B\u5982 my-app:latest",
363
- buildInvalidContext: "\u6784\u5EFA\u4E0A\u4E0B\u6587\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84",
364
347
  pullAction: "\u62C9\u53D6\u955C\u50CF",
365
348
  emptyContainers: "\u6CA1\u6709\u5BB9\u5668",
366
349
  emptyImages: "\u6CA1\u6709\u955C\u50CF",
@@ -496,7 +479,57 @@ var zh = {
496
479
  viewRuntime: "\u8FD0\u884C\u65F6\u8BE6\u60C5",
497
480
  restartToApply: "\u9700\u8981\u91CD\u542F DSH \u624D\u80FD\u5E94\u7528 host \u53D8\u66F4",
498
481
  notInstalled: "\u672A\u5B89\u88C5",
499
- unknown: "\u672A\u77E5"
482
+ unknown: "\u672A\u77E5",
483
+ imgPush: "\u63A8\u9001",
484
+ imgPushTitle: "\u63A8\u9001\u955C\u50CF",
485
+ imgPushSource: "\u672C\u5730\u955C\u50CF",
486
+ imgPushTarget: "\u63A8\u9001\u5230",
487
+ imgPushTargetHint: "\u683C\u5F0F\uFF1A[\u4ED3\u5E93\u5730\u5740/]\u7528\u6237\u540D/\u955C\u50CF\u540D:\u6807\u7B7E\u3002\u63A8\u9001\u5230 Docker Hub \u5FC5\u987B\u5E26\u7528\u6237\u540D\u524D\u7F00\u3002",
488
+ imgPushNeedsNamespace: "\u8FD9\u4E2A\u540D\u5B57\u6CA1\u6709\u7528\u6237\u540D\u524D\u7F00\uFF0C\u63A8\u9001\u5230 Docker Hub \u901A\u5E38\u4F1A\u88AB\u62D2\u7EDD\u3002\u4F8B\u5982\uFF1Amyname/{name}",
489
+ imgPushRetag: "\u76EE\u6807\u540D\u548C\u672C\u5730\u540D\u4E0D\u540C\uFF0C\u4F1A\u5148\u6253\u6807\u7B7E\uFF08tag\uFF09\u518D\u63A8\u9001\uFF1B\u672C\u5730\u955C\u50CF\u4E0D\u4F1A\u88AB\u6539\u540D\u3002",
490
+ imgPushLoginDocker: "\u63A8\u9001\u524D\u9700\u8981\u5148\u767B\u5F55\u4ED3\u5E93\uFF1A\u5728\u7EC8\u7AEF\u8FD0\u884C docker login\uFF08\u79C1\u6709\u4ED3\u5E93\u52A0\u4E0A\u5730\u5740\uFF0C\u4F8B\u5982 docker login ghcr.io\uFF09\u3002",
491
+ imgPushLoginApple: "\u63A8\u9001\u524D\u9700\u8981\u5148\u767B\u5F55\u4ED3\u5E93\uFF1A\u5728\u7EC8\u7AEF\u8FD0\u884C container registry login <\u4ED3\u5E93\u5730\u5740>\u3002",
492
+ imgPushPresets: "\u5E38\u7528\u4ED3\u5E93",
493
+ imgPushStart: "\u5F00\u59CB\u63A8\u9001",
494
+ imgPushing: "\u63A8\u9001\u4E2D\u2026",
495
+ imgPushDone: "\u955C\u50CF\u5DF2\u63A8\u9001\uFF1A{name}",
496
+ imgPushFailed: "\u63A8\u9001\u5931\u8D25\uFF0C\u8BE6\u60C5\u89C1\u63A7\u5236\u53F0",
497
+ imgPushAuthFailed: "\u63A8\u9001\u88AB\u62D2\u7EDD\uFF1A\u8BF7\u5148\u767B\u5F55\u4ED3\u5E93\uFF0C\u5E76\u786E\u8BA4\u955C\u50CF\u540D\u5E26\u6709\u4F60\u7684\u7528\u6237\u540D\u524D\u7F00\u3002",
498
+ imgCommandPreview: "\u5C06\u6267\u884C",
499
+ imgBuild: "\u6784\u5EFA\u955C\u50CF",
500
+ imgBuildTitle: "\u6784\u5EFA\u955C\u50CF",
501
+ imgBuildDir: "\u6784\u5EFA\u76EE\u5F55",
502
+ imgBuildDirPlaceholder: "/Users/\u4F60/\u9879\u76EE\u76EE\u5F55\uFF08\u5305\u542B Dockerfile\uFF09",
503
+ imgBuildDirHint: "\u9009\u62E9\u5305\u542B Dockerfile \u7684\u9879\u76EE\u6587\u4EF6\u5939\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u63A7\u5236\u53F0\u7684\u5DE5\u4F5C\u76EE\u5F55\u3002",
504
+ imgBuildDirChecking: "\u6B63\u5728\u68C0\u67E5\u76EE\u5F55\u2026",
505
+ imgBuildDirMissing: "\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84\u3002",
506
+ imgBuildDirNotDir: "\u8FD9\u4E0D\u662F\u4E00\u4E2A\u76EE\u5F55\u3002",
507
+ imgBuildDirNoFile: "\u76EE\u5F55\u91CC\u6CA1\u6709 Dockerfile \u6216 Containerfile\u3002",
508
+ imgBuildDirOk: "\u627E\u5230 {count} \u4E2A\u6784\u5EFA\u6587\u4EF6",
509
+ imgBuildFile: "\u6784\u5EFA\u6587\u4EF6",
510
+ imgBuildTag: "\u955C\u50CF\u540D:\u6807\u7B7E",
511
+ imgBuildTagPlaceholder: "myapp:latest",
512
+ imgBuildTagHint: "\u4ED3\u5E93\u90E8\u5206\u5FC5\u987B\u5C0F\u5199\u3002\u8981\u63A8\u9001\u5230 Docker Hub\uFF0C\u8BF7\u5199\u6210 \u7528\u6237\u540D/\u955C\u50CF\u540D:\u6807\u7B7E\u3002",
513
+ imgBuildTagRequired: "\u8BF7\u586B\u5199\u955C\u50CF\u540D\uFF0C\u4F8B\u5982 myapp:latest",
514
+ imgBuildAdvanced: "\u9AD8\u7EA7\u9009\u9879",
515
+ imgBuildPlatform: "\u76EE\u6807\u5E73\u53F0",
516
+ imgBuildPlatformAuto: "\u9ED8\u8BA4\uFF08\u5F53\u524D\u67B6\u6784\uFF09",
517
+ imgBuildNoCache: "\u4E0D\u4F7F\u7528\u7F13\u5B58\uFF08--no-cache\uFF09",
518
+ imgBuildArgs: "\u6784\u5EFA\u53C2\u6570\uFF08\u6BCF\u884C\u4E00\u4E2A\uFF09",
519
+ imgBuildArgsPlaceholder: "KEY=VALUE",
520
+ imgBuildStart: "\u5F00\u59CB\u6784\u5EFA",
521
+ imgBuilding: "\u6784\u5EFA\u4E2D\u2026",
522
+ imgBuildDone: "\u955C\u50CF\u6784\u5EFA\u5B8C\u6210\uFF1A{name}",
523
+ imgBuildFailed: "\u6784\u5EFA\u5931\u8D25\uFF0C\u8BE6\u60C5\u89C1\u63A7\u5236\u53F0",
524
+ imgBuildHint: "\u6784\u5EFA\u53EF\u80FD\u9700\u8981\u51E0\u5206\u949F\uFF0C\u8FDB\u5EA6\u5728\u201C\u63A7\u5236\u53F0\u201D\u6807\u7B7E\u67E5\u770B\u3002",
525
+ imgPullDone: "\u955C\u50CF\u5DF2\u62C9\u53D6\uFF1A{name}",
526
+ imgPullFailed: "\u62C9\u53D6\u5931\u8D25\uFF0C\u8BE6\u60C5\u89C1\u63A7\u5236\u53F0",
527
+ imgPullHint: "\u8F93\u5165\u955C\u50CF\u540D\uFF0C\u4F8B\u5982 nginx:latest\uFF1B\u6CA1\u5199\u6807\u7B7E\u65F6\u9ED8\u8BA4 latest\u3002",
528
+ imgJobBusy: "\u5DF2\u6709\u547D\u4EE4\u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5B83\u7ED3\u675F\u6216\u5148\u53D6\u6D88\u3002",
529
+ imgPullPlatform: "\u955C\u50CF\u67B6\u6784",
530
+ imgBuildDirChoose: "\u9009\u62E9\u6587\u4EF6\u5939\u2026",
531
+ imgBuildDirChange: "\u66F4\u6362",
532
+ imgBuildDirPickFailed: "\u65E0\u6CD5\u6253\u5F00\u6587\u4EF6\u5939\u9009\u62E9\u5668\uFF0C\u8BF7\u91CD\u8BD5\u3002"
500
533
  };
501
534
  var en = {
502
535
  panel: "Containers",
@@ -606,17 +639,6 @@ var en = {
606
639
  removeNetwork: "Remove network",
607
640
  pull: "Pull",
608
641
  pullPlaceholder: "nginx:latest",
609
- pushImage: "Push image",
610
- buildImage: "Build image",
611
- buildImageTitle: "Build image",
612
- buildTag: "Image tag",
613
- buildContext: "Build context (absolute path)",
614
- buildContextHint: "For example /Users/me/project; it must contain the Dockerfile.",
615
- buildDockerfile: "Dockerfile",
616
- buildNoCache: "Disable build cache",
617
- buildStart: "Build",
618
- buildInvalidTag: "Enter a valid image tag, for example my-app:latest",
619
- buildInvalidContext: "Build context must be an absolute path",
620
642
  pullAction: "Pull image",
621
643
  emptyContainers: "No containers",
622
644
  emptyImages: "No images",
@@ -752,11 +774,61 @@ var en = {
752
774
  viewRuntime: "Runtime details",
753
775
  restartToApply: "Restart DSH to apply host-side changes",
754
776
  notInstalled: "Not installed",
755
- unknown: "Unknown"
777
+ unknown: "Unknown",
778
+ imgPush: "Push",
779
+ imgPushTitle: "Push image",
780
+ imgPushSource: "Local image",
781
+ imgPushTarget: "Push to",
782
+ imgPushTargetHint: "Format: [registry/]username/image:tag. Docker Hub requires a username prefix.",
783
+ imgPushNeedsNamespace: "This name has no username prefix, so Docker Hub will usually reject the push. For example: myname/{name}",
784
+ imgPushRetag: "The target differs from the local name, so the image is tagged first and then pushed. The local image is not renamed.",
785
+ imgPushLoginDocker: "Log in to the registry first: run docker login in a terminal (add the address for private registries, e.g. docker login ghcr.io).",
786
+ imgPushLoginApple: "Log in to the registry first: run container registry login <registry> in a terminal.",
787
+ imgPushPresets: "Common registries",
788
+ imgPushStart: "Start push",
789
+ imgPushing: "Pushing\u2026",
790
+ imgPushDone: "Image pushed: {name}",
791
+ imgPushFailed: "Push failed, see the console for details",
792
+ imgPushAuthFailed: "Push was denied: log in to the registry first and make sure the image name has your username prefix.",
793
+ imgCommandPreview: "Will run",
794
+ imgBuild: "Build image",
795
+ imgBuildTitle: "Build image",
796
+ imgBuildDir: "Build directory",
797
+ imgBuildDirPlaceholder: "/Users/you/project (contains a Dockerfile)",
798
+ imgBuildDirHint: "Choose the project folder that contains a Dockerfile. Defaults to the console working directory.",
799
+ imgBuildDirChecking: "Checking directory\u2026",
800
+ imgBuildDirMissing: "Directory not found. Check the path.",
801
+ imgBuildDirNotDir: "This is not a directory.",
802
+ imgBuildDirNoFile: "No Dockerfile or Containerfile in this directory.",
803
+ imgBuildDirOk: "Found {count} build file(s)",
804
+ imgBuildFile: "Build file",
805
+ imgBuildTag: "Image name:tag",
806
+ imgBuildTagPlaceholder: "myapp:latest",
807
+ imgBuildTagHint: "The repository part must be lowercase. To push to Docker Hub, use username/image:tag.",
808
+ imgBuildTagRequired: "Enter an image name, for example myapp:latest",
809
+ imgBuildAdvanced: "Advanced options",
810
+ imgBuildPlatform: "Target platform",
811
+ imgBuildPlatformAuto: "Default (this machine)",
812
+ imgBuildNoCache: "Do not use cache (--no-cache)",
813
+ imgBuildArgs: "Build arguments (one per line)",
814
+ imgBuildArgsPlaceholder: "KEY=VALUE",
815
+ imgBuildStart: "Start build",
816
+ imgBuilding: "Building\u2026",
817
+ imgBuildDone: "Image built: {name}",
818
+ imgBuildFailed: "Build failed, see the console for details",
819
+ imgBuildHint: "A build can take a few minutes. Follow the progress in the Console tab.",
820
+ imgPullDone: "Image pulled: {name}",
821
+ imgPullFailed: "Pull failed, see the console for details",
822
+ imgPullHint: "Enter an image name such as nginx:latest. Without a tag, latest is used.",
823
+ imgJobBusy: "Another command is running. Wait for it to finish or cancel it first.",
824
+ imgPullPlatform: "Image architecture",
825
+ imgBuildDirChoose: "Choose folder\u2026",
826
+ imgBuildDirChange: "Change",
827
+ imgBuildDirPickFailed: "Could not open the folder picker. Try again."
756
828
  };
757
829
 
758
830
  // src/client/page.jsx
759
- var import_react14 = require("react");
831
+ var import_react15 = require("react");
760
832
 
761
833
  // src/client/attach.jsx
762
834
  var import_react3 = require("react");
@@ -1012,6 +1084,9 @@ function displayValue(value) {
1012
1084
  if (typeof value === "boolean") return value ? "true" : "false";
1013
1085
  return String(value);
1014
1086
  }
1087
+ function fill(text, values = {}) {
1088
+ return String(text).replace(/\{(\w+)\}/gu, (match, key) => values[key] === void 0 ? match : String(values[key]));
1089
+ }
1015
1090
  function errorMessage(error) {
1016
1091
  if (error === void 0 || error === null) return "";
1017
1092
  if (error instanceof Error) return error.message;
@@ -1149,25 +1224,338 @@ function AttachDialog({ open, t, mode = "attach", session, output, loading, erro
1149
1224
  );
1150
1225
  }
1151
1226
 
1152
- // src/client/run-container.jsx
1227
+ // src/client/build-image.jsx
1228
+ var import_react4 = require("react");
1229
+
1230
+ // src/client/platforms.js
1231
+ var PLATFORMS = ["linux/amd64", "linux/arm64"];
1232
+
1233
+ // src/client/build-image.jsx
1234
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1235
+ var IMAGE_REF = /^[A-Za-z0-9][A-Za-z0-9_.:/@-]*$/u;
1236
+ function BuildImageDialog({ open, t, api, provider, defaultDir = "", pickDirectory, onClose, onSubmit }) {
1237
+ const [dir, setDir] = (0, import_react4.useState)("");
1238
+ const [info, setInfo] = (0, import_react4.useState)(null);
1239
+ const [file, setFile] = (0, import_react4.useState)("");
1240
+ const [tag, setTag] = (0, import_react4.useState)("");
1241
+ const [tagEdited, setTagEdited] = (0, import_react4.useState)(false);
1242
+ const [platform, setPlatform] = (0, import_react4.useState)("");
1243
+ const [noCache, setNoCache] = (0, import_react4.useState)(false);
1244
+ const [buildArgs, setBuildArgs] = (0, import_react4.useState)("");
1245
+ const [error, setError] = (0, import_react4.useState)(null);
1246
+ const [busy, setBusy] = (0, import_react4.useState)(false);
1247
+ const requestId = (0, import_react4.useRef)(0);
1248
+ const canPick = typeof pickDirectory === "function" && (pickDirectory.available?.() ?? true);
1249
+ const choose = async () => {
1250
+ try {
1251
+ const picked = await pickDirectory();
1252
+ if (typeof picked === "string" && picked !== "") {
1253
+ setDir(picked);
1254
+ setError(null);
1255
+ }
1256
+ } catch (pickError) {
1257
+ setError(pickError instanceof Error && pickError.message !== "unsupported" ? pickError.message : t("imgBuildDirPickFailed"));
1258
+ }
1259
+ };
1260
+ (0, import_react4.useEffect)(() => {
1261
+ if (!open) return;
1262
+ setDir(defaultDir);
1263
+ setInfo(null);
1264
+ setFile("");
1265
+ setTag("");
1266
+ setTagEdited(false);
1267
+ setPlatform("");
1268
+ setNoCache(false);
1269
+ setBuildArgs("");
1270
+ setError(null);
1271
+ setBusy(false);
1272
+ }, [open, defaultDir]);
1273
+ (0, import_react4.useEffect)(() => {
1274
+ if (!open) return void 0;
1275
+ const path = dir.trim();
1276
+ if (path === "") {
1277
+ setInfo(null);
1278
+ return void 0;
1279
+ }
1280
+ const id = ++requestId.current;
1281
+ const timer = setTimeout(async () => {
1282
+ try {
1283
+ const value = await api.call("buildContext", { path });
1284
+ if (id !== requestId.current) return;
1285
+ setInfo(value);
1286
+ setFile((current) => value.dockerfiles.includes(current) ? current : value.dockerfiles[0] ?? "");
1287
+ if (value.suggestedTag !== "") setTag((current) => tagEdited || current !== "" ? current : value.suggestedTag);
1288
+ } catch {
1289
+ if (id === requestId.current) setInfo(null);
1290
+ }
1291
+ }, 300);
1292
+ return () => clearTimeout(timer);
1293
+ }, [api, dir, open, tagEdited]);
1294
+ const args = (0, import_react4.useMemo)(() => buildArgs.split(/\n/u).map((line) => line.trim()).filter(Boolean), [buildArgs]);
1295
+ const tagValid = IMAGE_REF.test(tag.trim());
1296
+ const dirOk = info !== null && info.isDirectory && info.dockerfiles.length > 0;
1297
+ const trimmedDir = dir.trim();
1298
+ const dirChecked = info !== null && info.path === trimmedDir;
1299
+ let dirLine = null;
1300
+ if (trimmedDir !== "" && !dirChecked) dirLine = { tone: "hint", text: t("imgBuildDirChecking") };
1301
+ else if (dirChecked && !info.exists) dirLine = { tone: "err", text: t("imgBuildDirMissing") };
1302
+ else if (dirChecked && !info.isDirectory) dirLine = { tone: "err", text: t("imgBuildDirNotDir") };
1303
+ else if (dirChecked && info.dockerfiles.length === 0) dirLine = { tone: "err", text: t("imgBuildDirNoFile") };
1304
+ else if (dirChecked) dirLine = { tone: "ok", text: fill(t("imgBuildDirOk"), { count: info.dockerfiles.length }) };
1305
+ const command = (0, import_react4.useMemo)(() => {
1306
+ const cli = provider === "apple-container" ? "container" : "docker";
1307
+ const parts = [cli, "build", "-t", tag.trim() || "<name:tag>"];
1308
+ if (file !== "" && file !== "Dockerfile") parts.push("-f", file);
1309
+ if (platform !== "") parts.push("--platform", platform);
1310
+ if (noCache) parts.push("--no-cache");
1311
+ for (const arg of args) parts.push("--build-arg", arg);
1312
+ parts.push(".");
1313
+ return `cd ${trimmedDir || "<dir>"}
1314
+ ${parts.join(" ")}`;
1315
+ }, [args, file, noCache, platform, provider, tag, trimmedDir]);
1316
+ const submit = async (event) => {
1317
+ event?.preventDefault();
1318
+ if (!dirOk) {
1319
+ setError(dirLine?.tone === "err" ? dirLine.text : t("imgBuildDirPlaceholder"));
1320
+ return;
1321
+ }
1322
+ if (!tagValid) {
1323
+ setError(t("imgBuildTagRequired"));
1324
+ return;
1325
+ }
1326
+ setBusy(true);
1327
+ setError(null);
1328
+ try {
1329
+ await onSubmit({
1330
+ kind: "image",
1331
+ action: "build",
1332
+ tag: tag.trim(),
1333
+ name: tag.trim(),
1334
+ contextDir: trimmedDir,
1335
+ file: file === "" ? void 0 : file,
1336
+ platform: platform === "" ? void 0 : platform,
1337
+ noCache,
1338
+ buildArgs: args
1339
+ });
1340
+ onClose();
1341
+ } catch (submitError) {
1342
+ setError(submitError instanceof Error ? submitError.message : String(submitError));
1343
+ setBusy(false);
1344
+ }
1345
+ };
1346
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1347
+ Modal,
1348
+ {
1349
+ open,
1350
+ title: t("imgBuildTitle"),
1351
+ subtitle: provider === "apple-container" ? t("providerApple") : t("providerDocker"),
1352
+ onClose,
1353
+ closeLabel: t("close"),
1354
+ footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1355
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { size: "sm", variant: "ghost", onClick: onClose, disabled: busy, children: t("modalCancel") }),
1356
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { size: "sm", variant: "primary", onClick: submit, disabled: busy || !dirOk || !tagValid, children: busy ? t("imgBuilding") : t("imgBuildStart") })
1357
+ ] }),
1358
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { className: "dsh-docker-run-form", onSubmit: submit, children: [
1359
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1360
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgBuildDir") }),
1361
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-docker-image-picker", children: [
1362
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1363
+ "input",
1364
+ {
1365
+ className: "dsh-docker-input dsh-docker-mono",
1366
+ style: { flex: 1, minWidth: 0 },
1367
+ value: dir,
1368
+ onChange: (event) => setDir(event.target.value),
1369
+ onClick: canPick ? choose : void 0,
1370
+ readOnly: canPick,
1371
+ placeholder: canPick ? t("imgBuildDirChoose") : t("imgBuildDirPlaceholder"),
1372
+ spellCheck: "false",
1373
+ autoFocus: !canPick
1374
+ }
1375
+ ),
1376
+ canPick && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { size: "sm", onClick: choose, children: dir.trim() === "" ? t("imgBuildDirChoose") : t("imgBuildDirChange") })
1377
+ ] }),
1378
+ dirLine === null || dirLine.tone === "hint" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-docker-hint", children: dirLine?.text ?? t("imgBuildDirHint") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: dirLine.tone === "ok" ? "dsh-docker-line-ok" : "dsh-docker-line-err", children: dirLine.text })
1379
+ ] }),
1380
+ dirOk && info.dockerfiles.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1381
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgBuildFile") }),
1382
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { className: "dsh-docker-select", value: file, onChange: (event) => setFile(event.target.value), children: info.dockerfiles.map((name) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: name, children: name }, name)) })
1383
+ ] }),
1384
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1385
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgBuildTag") }),
1386
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1387
+ "input",
1388
+ {
1389
+ className: "dsh-docker-input dsh-docker-mono",
1390
+ value: tag,
1391
+ onChange: (event) => {
1392
+ setTag(event.target.value);
1393
+ setTagEdited(true);
1394
+ },
1395
+ placeholder: t("imgBuildTagPlaceholder"),
1396
+ spellCheck: "false"
1397
+ }
1398
+ ),
1399
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-docker-hint", children: t("imgBuildTagHint") })
1400
+ ] }),
1401
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("details", { className: "dsh-docker-advanced", children: [
1402
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("summary", { children: t("imgBuildAdvanced") }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-docker-advanced-body", children: [
1404
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1405
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgBuildPlatform") }),
1406
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { className: "dsh-docker-select", value: platform, onChange: (event) => setPlatform(event.target.value), children: [
1407
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: t("imgBuildPlatformAuto") }),
1408
+ PLATFORMS.map((name) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: name, children: name }, name))
1409
+ ] })
1410
+ ] }),
1411
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-check", children: [
1412
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: noCache, onChange: (event) => setNoCache(event.target.checked) }),
1413
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgBuildNoCache") })
1414
+ ] }),
1415
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1416
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgBuildArgs") }),
1417
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1418
+ "textarea",
1419
+ {
1420
+ className: "dsh-docker-input dsh-docker-textarea",
1421
+ value: buildArgs,
1422
+ onChange: (event) => setBuildArgs(event.target.value),
1423
+ placeholder: t("imgBuildArgsPlaceholder"),
1424
+ spellCheck: "false",
1425
+ rows: 3
1426
+ }
1427
+ )
1428
+ ] })
1429
+ ] })
1430
+ ] }),
1431
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1432
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("imgCommandPreview") }),
1433
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: "dsh-docker-preview", children: command })
1434
+ ] }),
1435
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-docker-hint", children: t("imgBuildHint") }),
1436
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-docker-form-error", children: error })
1437
+ ] })
1438
+ }
1439
+ );
1440
+ }
1441
+
1442
+ // src/client/push-image.jsx
1153
1443
  var import_react5 = require("react");
1444
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1445
+ var IMAGE_REF2 = /^[A-Za-z0-9][A-Za-z0-9_.:/@-]*$/u;
1446
+ var PRESETS = [
1447
+ { label: "Docker Hub", prefix: "myname/" },
1448
+ { label: "GHCR", prefix: "ghcr.io/myname/" },
1449
+ { label: "Quay", prefix: "quay.io/myname/" }
1450
+ ];
1451
+ function lastSegment(reference) {
1452
+ const withoutDigest = reference.split("@")[0];
1453
+ return withoutDigest.slice(withoutDigest.lastIndexOf("/") + 1);
1454
+ }
1455
+ function PushImageDialog({ open, t, provider, image, onClose, onSubmit }) {
1456
+ const [target, setTarget] = (0, import_react5.useState)("");
1457
+ const [error, setError] = (0, import_react5.useState)(null);
1458
+ const [busy, setBusy] = (0, import_react5.useState)(false);
1459
+ (0, import_react5.useEffect)(() => {
1460
+ if (!open) return;
1461
+ setTarget(image);
1462
+ setError(null);
1463
+ setBusy(false);
1464
+ }, [open, image]);
1465
+ const trimmed = target.trim();
1466
+ const valid = IMAGE_REF2.test(trimmed);
1467
+ const needsNamespace = valid && !trimmed.split("@")[0].includes("/");
1468
+ const retag = valid && trimmed !== image;
1469
+ const command = (0, import_react5.useMemo)(() => {
1470
+ const cli = provider === "apple-container" ? "container image" : "docker";
1471
+ const lines = [];
1472
+ if (retag) lines.push(`${cli} tag ${image} ${trimmed}`);
1473
+ lines.push(`${cli} push ${valid ? trimmed : "\u2026"}`);
1474
+ return lines.join("\n");
1475
+ }, [image, provider, retag, trimmed, valid]);
1476
+ const submit = async (event) => {
1477
+ event?.preventDefault();
1478
+ if (!valid) {
1479
+ setError(t("pullInvalid"));
1480
+ return;
1481
+ }
1482
+ setBusy(true);
1483
+ setError(null);
1484
+ try {
1485
+ await onSubmit({ kind: "image", action: "push", id: image, target: trimmed, name: trimmed });
1486
+ onClose();
1487
+ } catch (submitError) {
1488
+ setError(submitError instanceof Error ? submitError.message : String(submitError));
1489
+ setBusy(false);
1490
+ }
1491
+ };
1492
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1493
+ Modal,
1494
+ {
1495
+ open,
1496
+ title: t("imgPushTitle"),
1497
+ subtitle: provider === "apple-container" ? t("providerApple") : t("providerDocker"),
1498
+ onClose,
1499
+ closeLabel: t("close"),
1500
+ footer: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1501
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { size: "sm", variant: "ghost", onClick: onClose, disabled: busy, children: t("modalCancel") }),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { size: "sm", variant: "primary", onClick: submit, disabled: busy || !valid, children: busy ? t("imgPushing") : t("imgPushStart") })
1503
+ ] }),
1504
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { className: "dsh-docker-run-form", onSubmit: submit, children: [
1505
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dsh-docker-field", children: [
1506
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: t("imgPushSource") }),
1507
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { className: "dsh-docker-input dsh-docker-mono", value: image, readOnly: true })
1508
+ ] }),
1509
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dsh-docker-field", children: [
1510
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: t("imgPushTarget") }),
1511
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1512
+ "input",
1513
+ {
1514
+ className: "dsh-docker-input dsh-docker-mono",
1515
+ value: target,
1516
+ onChange: (event) => setTarget(event.target.value),
1517
+ spellCheck: "false",
1518
+ autoFocus: true
1519
+ }
1520
+ ),
1521
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-docker-hint", children: t("imgPushTargetHint") })
1522
+ ] }),
1523
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-docker-chip-row", children: [
1524
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-docker-hint", children: t("imgPushPresets") }),
1525
+ PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => setTarget(`${preset.prefix}${lastSegment(image)}`), children: preset.label }, preset.label))
1526
+ ] }),
1527
+ needsNamespace && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-docker-hint dsh-docker-hint-warn", children: fill(t("imgPushNeedsNamespace"), { name: lastSegment(trimmed) }) }),
1528
+ retag && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-docker-hint", children: t("imgPushRetag") }),
1529
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dsh-docker-field", children: [
1530
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: t("imgCommandPreview") }),
1531
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { className: "dsh-docker-preview", children: command })
1532
+ ] }),
1533
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-docker-hint", children: provider === "apple-container" ? t("imgPushLoginApple") : t("imgPushLoginDocker") }),
1534
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-docker-form-error", children: error })
1535
+ ] })
1536
+ }
1537
+ );
1538
+ }
1539
+
1540
+ // src/client/run-container.jsx
1541
+ var import_react7 = require("react");
1154
1542
 
1155
1543
  // src/client/hooks.js
1156
- var import_react4 = require("react");
1544
+ var import_react6 = require("react");
1157
1545
  var LIST_TTL = 2e3;
1158
1546
  var STATUS_INTERVAL = 1e4;
1159
1547
  function useDockerList(api, provider, resource, context, { all = true, refreshToken = 0, enabled = true } = {}) {
1160
1548
  const key = `list:${provider}:${resource}:${context ?? ""}:${all ? "all" : "running"}`;
1161
- const [state, setState] = (0, import_react4.useState)(() => {
1549
+ const [state, setState] = (0, import_react6.useState)(() => {
1162
1550
  const cached = cacheGet(key);
1163
1551
  return { data: cached ?? null, error: null, loading: cached === void 0 };
1164
1552
  });
1165
- const [localVersion, setLocalVersion] = (0, import_react4.useState)(0);
1166
- const [reloadSignal, setReloadSignal] = (0, import_react4.useState)(0);
1167
- (0, import_react4.useEffect)(() => {
1553
+ const [localVersion, setLocalVersion] = (0, import_react6.useState)(0);
1554
+ const [reloadSignal, setReloadSignal] = (0, import_react6.useState)(0);
1555
+ (0, import_react6.useEffect)(() => {
1168
1556
  setState({ data: null, error: null, loading: enabled });
1169
1557
  }, [enabled, key]);
1170
- (0, import_react4.useEffect)(() => {
1558
+ (0, import_react6.useEffect)(() => {
1171
1559
  if (!enabled) {
1172
1560
  setState((current) => current.data === null && !current.loading && current.error === null ? current : { data: null, error: null, loading: false });
1173
1561
  return void 0;
@@ -1196,17 +1584,17 @@ function useDockerList(api, provider, resource, context, { all = true, refreshTo
1196
1584
  controller.abort();
1197
1585
  };
1198
1586
  }, [api, provider, key, resource, context, all, enabled, refreshToken, reloadSignal, localVersion]);
1199
- const reload = (0, import_react4.useCallback)(() => {
1587
+ const reload = (0, import_react6.useCallback)(() => {
1200
1588
  cacheClear(key);
1201
1589
  setReloadSignal((value) => value + 1);
1202
1590
  }, [key]);
1203
1591
  return { ...state, reload };
1204
1592
  }
1205
1593
  function useDockerStatus(api, provider, context, refreshToken = 0) {
1206
- const [state, setState] = (0, import_react4.useState)({ data: null, error: null, loading: true, updatedAt: null });
1207
- const [localVersion, setLocalVersion] = (0, import_react4.useState)(0);
1208
- const mounted = (0, import_react4.useRef)(true);
1209
- const load = (0, import_react4.useCallback)(
1594
+ const [state, setState] = (0, import_react6.useState)({ data: null, error: null, loading: true, updatedAt: null });
1595
+ const [localVersion, setLocalVersion] = (0, import_react6.useState)(0);
1596
+ const mounted = (0, import_react6.useRef)(true);
1597
+ const load = (0, import_react6.useCallback)(
1210
1598
  async (signal) => {
1211
1599
  try {
1212
1600
  const value = await api.call("status", { provider, context: context ?? void 0 }, signal);
@@ -1219,16 +1607,16 @@ function useDockerStatus(api, provider, context, refreshToken = 0) {
1219
1607
  },
1220
1608
  [api, provider, context]
1221
1609
  );
1222
- (0, import_react4.useEffect)(() => {
1610
+ (0, import_react6.useEffect)(() => {
1223
1611
  mounted.current = true;
1224
1612
  return () => {
1225
1613
  mounted.current = false;
1226
1614
  };
1227
1615
  }, []);
1228
- (0, import_react4.useEffect)(() => {
1616
+ (0, import_react6.useEffect)(() => {
1229
1617
  setState({ data: null, error: null, loading: true, updatedAt: null });
1230
1618
  }, [api, provider, context]);
1231
- (0, import_react4.useEffect)(() => {
1619
+ (0, import_react6.useEffect)(() => {
1232
1620
  let controller = new AbortController();
1233
1621
  let timer;
1234
1622
  const tick = () => {
@@ -1256,16 +1644,16 @@ function useDockerStatus(api, provider, context, refreshToken = 0) {
1256
1644
  document.removeEventListener("visibilitychange", onVisibility);
1257
1645
  };
1258
1646
  }, [load, refreshToken, localVersion]);
1259
- const refresh = (0, import_react4.useCallback)(() => {
1647
+ const refresh = (0, import_react6.useCallback)(() => {
1260
1648
  cacheClear("list:");
1261
1649
  setLocalVersion((value) => value + 1);
1262
1650
  }, []);
1263
1651
  return { ...state, refresh };
1264
1652
  }
1265
1653
  function useProviders(api, refreshToken = 0) {
1266
- const [state, setState] = (0, import_react4.useState)({ data: null, error: null, loading: true });
1267
- const [localVersion, setLocalVersion] = (0, import_react4.useState)(0);
1268
- (0, import_react4.useEffect)(() => {
1654
+ const [state, setState] = (0, import_react6.useState)({ data: null, error: null, loading: true });
1655
+ const [localVersion, setLocalVersion] = (0, import_react6.useState)(0);
1656
+ (0, import_react6.useEffect)(() => {
1269
1657
  const controller = new AbortController();
1270
1658
  let active = true;
1271
1659
  setState((current) => ({ ...current, loading: current.data === null, error: null }));
@@ -1284,12 +1672,12 @@ function useProviders(api, refreshToken = 0) {
1284
1672
  controller.abort();
1285
1673
  };
1286
1674
  }, [api, refreshToken, localVersion]);
1287
- const reload = (0, import_react4.useCallback)(() => setLocalVersion((value) => value + 1), []);
1675
+ const reload = (0, import_react6.useCallback)(() => setLocalVersion((value) => value + 1), []);
1288
1676
  return { ...state, reload };
1289
1677
  }
1290
1678
 
1291
1679
  // src/client/run-container.jsx
1292
- var import_jsx_runtime4 = require("react/jsx-runtime");
1680
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1293
1681
  function RunContainerDialog({
1294
1682
  open,
1295
1683
  t,
@@ -1303,20 +1691,20 @@ function RunContainerDialog({
1303
1691
  onClose,
1304
1692
  onSubmit
1305
1693
  }) {
1306
- const [image, setImage] = (0, import_react5.useState)("");
1307
- const [manual, setManual] = (0, import_react5.useState)(false);
1308
- const [customImage, setCustomImage] = (0, import_react5.useState)("");
1309
- const [name, setName] = (0, import_react5.useState)("");
1310
- const [command, setCommand] = (0, import_react5.useState)("");
1311
- const [ports, setPorts] = (0, import_react5.useState)("");
1312
- const [env, setEnv] = (0, import_react5.useState)("");
1313
- const [error, setError] = (0, import_react5.useState)(null);
1314
- const [busy, setBusy] = (0, import_react5.useState)(false);
1694
+ const [image, setImage] = (0, import_react7.useState)("");
1695
+ const [manual, setManual] = (0, import_react7.useState)(false);
1696
+ const [customImage, setCustomImage] = (0, import_react7.useState)("");
1697
+ const [name, setName] = (0, import_react7.useState)("");
1698
+ const [command, setCommand] = (0, import_react7.useState)("");
1699
+ const [ports, setPorts] = (0, import_react7.useState)("");
1700
+ const [env, setEnv] = (0, import_react7.useState)("");
1701
+ const [error, setError] = (0, import_react7.useState)(null);
1702
+ const [busy, setBusy] = (0, import_react7.useState)(false);
1315
1703
  const images = useDockerList(api, provider, "images", context, {
1316
1704
  refreshToken,
1317
1705
  enabled: open && features.includes("run") && status?.daemon?.state === "running"
1318
1706
  });
1319
- const options = (0, import_react5.useMemo)(() => {
1707
+ const options = (0, import_react7.useMemo)(() => {
1320
1708
  const names = [];
1321
1709
  for (const item of images.data?.items ?? []) {
1322
1710
  if (typeof item.name === "string" && item.name !== "" && item.name !== "<none>" && !names.includes(item.name)) names.push(item.name);
@@ -1324,7 +1712,7 @@ function RunContainerDialog({
1324
1712
  if (initialImage !== "" && !names.includes(initialImage)) names.unshift(initialImage);
1325
1713
  return names;
1326
1714
  }, [images.data, initialImage]);
1327
- (0, import_react5.useEffect)(() => {
1715
+ (0, import_react7.useEffect)(() => {
1328
1716
  if (!open) return;
1329
1717
  setImage(initialImage);
1330
1718
  setManual(false);
@@ -1336,7 +1724,7 @@ function RunContainerDialog({
1336
1724
  setError(null);
1337
1725
  setBusy(false);
1338
1726
  }, [open, initialImage]);
1339
- (0, import_react5.useEffect)(() => {
1727
+ (0, import_react7.useEffect)(() => {
1340
1728
  if (!open || manual) return;
1341
1729
  if (initialImage !== "" && options.includes(initialImage)) {
1342
1730
  setImage(initialImage);
@@ -1387,7 +1775,7 @@ function RunContainerDialog({
1387
1775
  setBusy(false);
1388
1776
  }
1389
1777
  };
1390
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1778
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1391
1779
  Modal,
1392
1780
  {
1393
1781
  open,
@@ -1395,15 +1783,15 @@ function RunContainerDialog({
1395
1783
  subtitle: provider === "apple-container" ? t("providerApple") : t("providerDocker"),
1396
1784
  onClose: close,
1397
1785
  closeLabel: t("close"),
1398
- footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1399
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { size: "sm", variant: "ghost", onClick: close, disabled: busy, children: t("modalCancel") }),
1400
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { size: "sm", variant: "primary", onClick: submit, disabled: busy, children: busy ? t("starting") : t("runStart") })
1786
+ footer: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1787
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "sm", variant: "ghost", onClick: close, disabled: busy, children: t("modalCancel") }),
1788
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "sm", variant: "primary", onClick: submit, disabled: busy, children: busy ? t("starting") : t("runStart") })
1401
1789
  ] }),
1402
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { className: "dsh-docker-run-form", onSubmit: submit, children: [
1403
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1404
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("runImage") }),
1405
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-docker-image-picker", children: [
1406
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1790
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { className: "dsh-docker-run-form", onSubmit: submit, children: [
1791
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dsh-docker-field", children: [
1792
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("runImage") }),
1793
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-image-picker", children: [
1794
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1407
1795
  "select",
1408
1796
  {
1409
1797
  className: "dsh-docker-select",
@@ -1419,15 +1807,15 @@ function RunContainerDialog({
1419
1807
  },
1420
1808
  autoFocus: true,
1421
1809
  children: [
1422
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: t("runImageSelect") }),
1423
- options.map((name2) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: name2, children: name2 }, name2)),
1424
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "__custom__", children: t("runImageCustom") })
1810
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: t("runImageSelect") }),
1811
+ options.map((name2) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: name2, children: name2 }, name2)),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "__custom__", children: t("runImageCustom") })
1425
1813
  ]
1426
1814
  }
1427
1815
  ),
1428
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { size: "sm", variant: "ghost", onClick: images.reload, disabled: images.loading, children: t("refresh") })
1816
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "sm", variant: "ghost", onClick: images.reload, disabled: images.loading, children: t("refresh") })
1429
1817
  ] }),
1430
- manual && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1818
+ manual && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1431
1819
  "input",
1432
1820
  {
1433
1821
  className: "dsh-docker-input",
@@ -1437,36 +1825,36 @@ function RunContainerDialog({
1437
1825
  spellCheck: "false"
1438
1826
  }
1439
1827
  ),
1440
- images.data !== null && options.length === 0 && !manual && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-docker-muted", children: t("runImageListEmpty") })
1828
+ images.data !== null && options.length === 0 && !manual && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-muted", children: t("runImageListEmpty") })
1441
1829
  ] }),
1442
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-docker-run-grid", children: [
1443
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1444
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("runName") }),
1445
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { className: "dsh-docker-input", value: name, onChange: (event) => setName(event.target.value), placeholder: t("runNamePlaceholder"), spellCheck: "false" })
1830
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-run-grid", children: [
1831
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dsh-docker-field", children: [
1832
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("runName") }),
1833
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "dsh-docker-input", value: name, onChange: (event) => setName(event.target.value), placeholder: t("runNamePlaceholder"), spellCheck: "false" })
1446
1834
  ] }),
1447
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1448
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("runPorts") }),
1449
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { className: "dsh-docker-input", value: ports, onChange: (event) => setPorts(event.target.value), placeholder: t("runPortsPlaceholder"), spellCheck: "false" })
1835
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dsh-docker-field", children: [
1836
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("runPorts") }),
1837
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "dsh-docker-input", value: ports, onChange: (event) => setPorts(event.target.value), placeholder: t("runPortsPlaceholder"), spellCheck: "false" })
1450
1838
  ] })
1451
1839
  ] }),
1452
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1453
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("runCommand") }),
1454
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { className: "dsh-docker-input", value: command, onChange: (event) => setCommand(event.target.value), placeholder: t("runCommandPlaceholder"), spellCheck: "false" })
1840
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dsh-docker-field", children: [
1841
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("runCommand") }),
1842
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "dsh-docker-input", value: command, onChange: (event) => setCommand(event.target.value), placeholder: t("runCommandPlaceholder"), spellCheck: "false" })
1455
1843
  ] }),
1456
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-docker-field", children: [
1457
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("runEnv") }),
1458
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("textarea", { className: "dsh-docker-input dsh-docker-textarea", value: env, onChange: (event) => setEnv(event.target.value), placeholder: t("runEnvPlaceholder"), spellCheck: "false", rows: 3 })
1844
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dsh-docker-field", children: [
1845
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("runEnv") }),
1846
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("textarea", { className: "dsh-docker-input dsh-docker-textarea", value: env, onChange: (event) => setEnv(event.target.value), placeholder: t("runEnvPlaceholder"), spellCheck: "false", rows: 3 })
1459
1847
  ] }),
1460
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-docker-muted", children: t("runDetachedHint") }),
1461
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-docker-form-error", children: error })
1848
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-docker-muted", children: t("runDetachedHint") }),
1849
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-docker-form-error", children: error })
1462
1850
  ] })
1463
1851
  }
1464
1852
  );
1465
1853
  }
1466
1854
 
1467
1855
  // src/client/tabs/compose.jsx
1468
- var import_react6 = require("react");
1469
- var import_jsx_runtime5 = require("react/jsx-runtime");
1856
+ var import_react8 = require("react");
1857
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1470
1858
  function configList(value) {
1471
1859
  if (typeof value !== "string" || value.trim() === "") return [];
1472
1860
  return value.split(",").map((entry) => entry.trim()).filter(Boolean);
@@ -1476,46 +1864,46 @@ function composeCommand(project) {
1476
1864
  return files.length === 0 ? null : `docker compose -f ${JSON.stringify(files[0])}`;
1477
1865
  }
1478
1866
  function ComposeTab({ t, api, provider, context, status, refreshToken }) {
1479
- const [search, setSearch] = (0, import_react6.useState)("");
1867
+ const [search, setSearch] = (0, import_react8.useState)("");
1480
1868
  const enabled = status?.daemon?.state === "running";
1481
1869
  const list = useDockerList(api, provider, "compose", context, { refreshToken, enabled });
1482
1870
  const items = list.data?.items ?? [];
1483
- const filtered = (0, import_react6.useMemo)(() => {
1871
+ const filtered = (0, import_react8.useMemo)(() => {
1484
1872
  const needle = search.trim().toLowerCase();
1485
1873
  return needle === "" ? items : items.filter((item) => `${item.name} ${item.status} ${item.configFiles}`.toLowerCase().includes(needle));
1486
1874
  }, [items, search]);
1487
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-docker-stack", children: [
1488
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-docker-toolbar", children: [
1489
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-docker-toolbar-left", children: [
1490
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }),
1491
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-docker-muted", children: t("composeReadOnly") })
1875
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-stack", children: [
1876
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-toolbar", children: [
1877
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-toolbar-left", children: [
1878
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }),
1879
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-docker-muted", children: t("composeReadOnly") })
1492
1880
  ] }),
1493
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
1494
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "dsh-docker-muted", children: [
1881
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
1882
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "dsh-docker-muted", children: [
1495
1883
  filtered.length,
1496
1884
  " / ",
1497
1885
  items.length
1498
1886
  ] }),
1499
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
1887
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
1500
1888
  ] })
1501
1889
  ] }),
1502
- !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconAlert, { size: 20 }), title: t("daemonStopped"), text: t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LoadingSkeleton, { rows: 5 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconCompose, { size: 20 }), title: search === "" ? t("emptyCompose") : t("emptySearch"), text: search === "" ? t("composeReadOnly") : search }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "dsh-docker-table", children: [
1503
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
1504
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { children: t("project") }),
1505
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { children: t("status") }),
1506
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { children: t("configFiles") }),
1507
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
1890
+ !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconAlert, { size: 20 }), title: t("daemonStopped"), text: t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LoadingSkeleton, { rows: 5 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconCompose, { size: 20 }), title: search === "" ? t("emptyCompose") : t("emptySearch"), text: search === "" ? t("composeReadOnly") : search }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "dsh-docker-table", children: [
1891
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("tr", { children: [
1892
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("project") }),
1893
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("status") }),
1894
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("configFiles") }),
1895
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
1508
1896
  ] }) }),
1509
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: filtered.map((item) => {
1897
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { children: filtered.map((item) => {
1510
1898
  const base = composeCommand(item);
1511
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
1512
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "dsh-docker-row-title", children: item.name }),
1513
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { children: displayValue(item.status) }),
1514
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-docker-chips", children: configList(item.configFiles).map((file) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-docker-chip dsh-docker-chip-code", title: file, children: file }, file)) }) }),
1515
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "dsh-docker-col-actions", children: base !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "dsh-docker-row-actions", children: [
1516
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CopyButton, { text: `${base} up -d`, label: "up -d", copiedLabel: t("copied"), className: "dsh-docker-btn dsh-docker-sm" }),
1517
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CopyButton, { text: `${base} down`, label: "down", copiedLabel: t("copied"), className: "dsh-docker-btn dsh-docker-sm" })
1518
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-docker-muted", children: "\u2014" }) })
1899
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("tr", { children: [
1900
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "dsh-docker-row-title", children: item.name }),
1901
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { children: displayValue(item.status) }),
1902
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-docker-chips", children: configList(item.configFiles).map((file) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-docker-chip dsh-docker-chip-code", title: file, children: file }, file)) }) }),
1903
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "dsh-docker-col-actions", children: base !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "dsh-docker-row-actions", children: [
1904
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CopyButton, { text: `${base} up -d`, label: "up -d", copiedLabel: t("copied"), className: "dsh-docker-btn dsh-docker-sm" }),
1905
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CopyButton, { text: `${base} down`, label: "down", copiedLabel: t("copied"), className: "dsh-docker-btn dsh-docker-sm" })
1906
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-docker-muted", children: "\u2014" }) })
1519
1907
  ] }, item.name);
1520
1908
  }) })
1521
1909
  ] }) }) })
@@ -1523,7 +1911,7 @@ function ComposeTab({ t, api, provider, context, status, refreshToken }) {
1523
1911
  }
1524
1912
 
1525
1913
  // src/client/tabs/console.jsx
1526
- var import_react7 = require("react");
1914
+ var import_react9 = require("react");
1527
1915
 
1528
1916
  // src/client/store.js
1529
1917
  var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
@@ -1607,7 +1995,7 @@ function createDockerStore() {
1607
1995
  }
1608
1996
 
1609
1997
  // src/client/tabs/console.jsx
1610
- var import_jsx_runtime6 = require("react/jsx-runtime");
1998
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1611
1999
  var QUICK_DOCKER = ["ps -a", "images", "volume ls", "network ls", "compose ls", "system df", "info", "version"];
1612
2000
  var QUICK_APPLE = ["ls -a", "image ls", "volume ls", "network ls", "system df", "system version"];
1613
2001
  var SENSITIVE = /(?:^|\s)(login|logout|--password(?:-stdin)?|--token|--registry-token)(?:\s|=|$)/u;
@@ -1620,11 +2008,11 @@ function statusLabel2(t, status) {
1620
2008
  return t("commandFinished");
1621
2009
  }
1622
2010
  function ConsoleTab({ t, provider, runs, runState, context, status, cwd, onCwdChange, draft, setDraft, onRun }) {
1623
- const [history, setHistory] = (0, import_react7.useState)(() => readHistory());
1624
- const [historyIndex, setHistoryIndex] = (0, import_react7.useState)(-1);
1625
- const [now, setNow] = (0, import_react7.useState)(() => Date.now());
1626
- const [stick, setStick] = (0, import_react7.useState)(true);
1627
- const preRef = (0, import_react7.useRef)(null);
2011
+ const [history, setHistory] = (0, import_react9.useState)(() => readHistory());
2012
+ const [historyIndex, setHistoryIndex] = (0, import_react9.useState)(-1);
2013
+ const [now, setNow] = (0, import_react9.useState)(() => Date.now());
2014
+ const [stick, setStick] = (0, import_react9.useState)(true);
2015
+ const preRef = (0, import_react9.useRef)(null);
1628
2016
  const run = runState?.run ?? null;
1629
2017
  const active = run !== null && (run.status === "running" || run.status === "cancelling");
1630
2018
  const output = runState?.stdout ?? "";
@@ -1634,15 +2022,15 @@ function ConsoleTab({ t, provider, runs, runState, context, status, cwd, onCwdCh
1634
2022
  ${stderr}`;
1635
2023
  const hasOutput = combined.trim() !== "";
1636
2024
  const runId = run?.id;
1637
- (0, import_react7.useEffect)(() => {
2025
+ (0, import_react9.useEffect)(() => {
1638
2026
  if (!active) return void 0;
1639
2027
  const timer = setInterval(() => setNow(Date.now()), 1e3);
1640
2028
  return () => clearInterval(timer);
1641
2029
  }, [active]);
1642
- (0, import_react7.useEffect)(() => {
2030
+ (0, import_react9.useEffect)(() => {
1643
2031
  if (runId !== void 0) setStick(true);
1644
2032
  }, [runId]);
1645
- (0, import_react7.useEffect)(() => {
2033
+ (0, import_react9.useEffect)(() => {
1646
2034
  if (!stick) return;
1647
2035
  const element = preRef.current;
1648
2036
  if (element !== null) element.scrollTop = element.scrollHeight;
@@ -1690,12 +2078,12 @@ ${stderr}`;
1690
2078
  const elapsed = run?.startedAt !== void 0 ? (run.endedAt ?? (active ? now : run.endedAt)) - run.startedAt : void 0;
1691
2079
  const isApple = provider === "apple-container";
1692
2080
  const commandPrefix = isApple ? "container" : "docker";
1693
- const quick = (0, import_react7.useMemo)(() => isApple ? QUICK_APPLE : QUICK_DOCKER, [isApple]);
1694
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-console", children: [
1695
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { className: "dsh-docker-console-form", onSubmit: submit, children: [
1696
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-console-row", children: [
1697
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-console-prompt", children: "$" }),
1698
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2081
+ const quick = (0, import_react9.useMemo)(() => isApple ? QUICK_APPLE : QUICK_DOCKER, [isApple]);
2082
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-console", children: [
2083
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { className: "dsh-docker-console-form", onSubmit: submit, children: [
2084
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-console-row", children: [
2085
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-console-prompt", children: "$" }),
2086
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1699
2087
  "input",
1700
2088
  {
1701
2089
  className: "dsh-docker-input dsh-docker-console-input",
@@ -1712,25 +2100,25 @@ ${stderr}`;
1712
2100
  autoCorrect: "off"
1713
2101
  }
1714
2102
  ),
1715
- active ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Button, { type: "button", variant: "danger", onClick: () => runs.cancel(), children: [
1716
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconX, { size: 13 }),
2103
+ active ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Button, { type: "button", variant: "danger", onClick: () => runs.cancel(), children: [
2104
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconX, { size: 13 }),
1717
2105
  " ",
1718
2106
  t("cancel")
1719
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Button, { type: "submit", variant: "primary", disabled: draft.trim() === "", children: [
1720
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconTerminal, { size: 13 }),
2107
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Button, { type: "submit", variant: "primary", disabled: draft.trim() === "", children: [
2108
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconTerminal, { size: 13 }),
1721
2109
  " ",
1722
2110
  t("run")
1723
2111
  ] })
1724
2112
  ] }),
1725
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-console-meta", children: [
1726
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-docker-console-hint", children: [
2113
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-console-meta", children: [
2114
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "dsh-docker-console-hint", children: [
1727
2115
  isApple ? t("providerLabel") : t("contextLabel"),
1728
2116
  ": ",
1729
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-mono", children: isApple ? t("providerApple") : context ?? t("noContext") })
2117
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-mono", children: isApple ? t("providerApple") : context ?? t("noContext") })
1730
2118
  ] }),
1731
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-console-hint", children: "\xB7" }),
1732
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-console-hint", children: t("cwd") }),
1733
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2119
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-console-hint", children: "\xB7" }),
2120
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-console-hint", children: t("cwd") }),
2121
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1734
2122
  "input",
1735
2123
  {
1736
2124
  className: "dsh-docker-input dsh-docker-console-cwd",
@@ -1741,34 +2129,34 @@ ${stderr}`;
1741
2129
  spellCheck: "false"
1742
2130
  }
1743
2131
  ),
1744
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-console-hint dsh-docker-truncate", children: t("shellHint") })
2132
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-console-hint dsh-docker-truncate", children: t("shellHint") })
1745
2133
  ] }),
1746
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-chip-row", style: { alignItems: "center" }, children: [
1747
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-console-hint", children: t("quickCommands") }),
1748
- quick.map((command) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "dsh-docker-quick", onClick: () => setDraft(`${commandPrefix} ${command}`), children: command }, command)),
1749
- history.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1750
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-console-hint", style: { marginLeft: 4 }, children: t("history") }),
1751
- history.slice(0, 4).map((command, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "dsh-docker-quick", title: command, onClick: () => setDraft(command), children: command.length > 28 ? `${command.slice(0, 28)}\u2026` : command }, `${command}-${index}`)),
1752
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => {
2134
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-chip-row", style: { alignItems: "center" }, children: [
2135
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-console-hint", children: t("quickCommands") }),
2136
+ quick.map((command) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "dsh-docker-quick", onClick: () => setDraft(`${commandPrefix} ${command}`), children: command }, command)),
2137
+ history.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2138
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-console-hint", style: { marginLeft: 4 }, children: t("history") }),
2139
+ history.slice(0, 4).map((command, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "dsh-docker-quick", title: command, onClick: () => setDraft(command), children: command.length > 28 ? `${command.slice(0, 28)}\u2026` : command }, `${command}-${index}`)),
2140
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => {
1753
2141
  setHistory([]);
1754
2142
  writeHistory([]);
1755
2143
  }, children: t("resetHistory") })
1756
2144
  ] })
1757
2145
  ] })
1758
2146
  ] }),
1759
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-console-output", children: [
1760
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-output-head", children: [
1761
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-output-title", children: [
1762
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconTerminal, { size: 14 }),
1763
- run !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-output-cmd", title: run.displayCommand, children: run.displayCommand }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("terminal") })
2147
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-console-output", children: [
2148
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-output-head", children: [
2149
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-output-title", children: [
2150
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconTerminal, { size: 14 }),
2151
+ run !== null ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-output-cmd", title: run.displayCommand, children: run.displayCommand }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("terminal") })
1764
2152
  ] }),
1765
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-output-actions", children: [
1766
- runState?.truncated === true && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-chip", children: t("truncation") }),
1767
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CopyButton, { text: combined, label: t("copy"), copiedLabel: t("copied"), className: "dsh-docker-btn dsh-docker-sm" }),
1768
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "sm", onClick: () => runs.reset(), disabled: run === null && !hasOutput, children: t("clear") })
2153
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-output-actions", children: [
2154
+ runState?.truncated === true && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-chip", children: t("truncation") }),
2155
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CopyButton, { text: combined, label: t("copy"), copiedLabel: t("copied"), className: "dsh-docker-btn dsh-docker-sm" }),
2156
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { size: "sm", onClick: () => runs.reset(), disabled: run === null && !hasOutput, children: t("clear") })
1769
2157
  ] })
1770
2158
  ] }),
1771
- runState?.error !== void 0 && runState?.error !== null && runState.error !== "" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { className: "dsh-docker-output-pre", style: { color: "var(--dsw-alias-label-error)" }, children: runState.error }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2159
+ runState?.error !== void 0 && runState?.error !== null && runState.error !== "" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "dsh-docker-output-pre", style: { color: "var(--dsw-alias-label-error)" }, children: runState.error }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1772
2160
  "pre",
1773
2161
  {
1774
2162
  ref: preRef,
@@ -1781,45 +2169,45 @@ ${stderr}`;
1781
2169
  children: hasOutput ? combined : t("noOutput")
1782
2170
  }
1783
2171
  ),
1784
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-docker-run-status", "data-status": run?.status ?? "idle", children: [
1785
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-dot" }),
1786
- run === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t("noActiveRun") }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1787
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: statusLabel2(t, run.status) }),
1788
- run.exitCode !== null && run.exitCode !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2172
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dsh-docker-run-status", "data-status": run?.status ?? "idle", children: [
2173
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-dot" }),
2174
+ run === null ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("noActiveRun") }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2175
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: statusLabel2(t, run.status) }),
2176
+ run.exitCode !== null && run.exitCode !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
1789
2177
  t("exitCode"),
1790
2178
  ": ",
1791
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-mono", children: run.exitCode })
2179
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-mono", children: run.exitCode })
1792
2180
  ] }),
1793
- elapsed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2181
+ elapsed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
1794
2182
  t("elapsed"),
1795
2183
  ": ",
1796
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-mono", children: formatDuration(Math.max(0, elapsed)) })
2184
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-mono", children: formatDuration(Math.max(0, elapsed)) })
1797
2185
  ] }),
1798
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2186
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
1799
2187
  isApple ? t("providerLabel") : t("contextLabel"),
1800
2188
  ": ",
1801
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-mono", children: isApple ? t("providerApple") : run.context ?? context ?? "\u2014" })
2189
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-mono", children: isApple ? t("providerApple") : run.context ?? context ?? "\u2014" })
1802
2190
  ] }),
1803
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-muted", children: formatTime(run.startedAt) }),
1804
- active && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Spinner, { size: 12 })
2191
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-muted", children: formatTime(run.startedAt) }),
2192
+ active && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Spinner, { size: 12 })
1805
2193
  ] }),
1806
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { flex: 1 } }),
1807
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-docker-muted dsh-docker-mono", children: isApple ? status?.runtime?.details?.status ?? "" : status?.context?.endpoint ?? "" })
2194
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { flex: 1 } }),
2195
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-docker-muted dsh-docker-mono", children: isApple ? status?.runtime?.details?.status ?? "" : status?.context?.endpoint ?? "" })
1808
2196
  ] })
1809
2197
  ] })
1810
2198
  ] });
1811
2199
  }
1812
2200
 
1813
2201
  // src/client/tabs/containers.jsx
1814
- var import_react8 = require("react");
1815
- var import_jsx_runtime7 = require("react/jsx-runtime");
2202
+ var import_react10 = require("react");
2203
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1816
2204
  function ContainersTab({ t, api, provider, context, status, refreshToken, features, onAction, onAttach, onRunContainer, onAskAI, canAskAI, onInspect }) {
1817
- const [all, setAll] = (0, import_react8.useState)(true);
1818
- const [search, setSearch] = (0, import_react8.useState)("");
2205
+ const [all, setAll] = (0, import_react10.useState)(true);
2206
+ const [search, setSearch] = (0, import_react10.useState)("");
1819
2207
  const enabled = status?.daemon?.state === "running";
1820
2208
  const list = useDockerList(api, provider, "containers", context, { all, refreshToken, enabled });
1821
2209
  const items = list.data?.items ?? [];
1822
- const filtered = (0, import_react8.useMemo)(() => {
2210
+ const filtered = (0, import_react10.useMemo)(() => {
1823
2211
  const needle = search.trim().toLowerCase();
1824
2212
  if (needle === "") return items;
1825
2213
  return items.filter(
@@ -1829,61 +2217,61 @@ function ContainersTab({ t, api, provider, context, status, refreshToken, featur
1829
2217
  const act = (action, item, focusConsole = false, follow = false) => {
1830
2218
  onAction({ kind: "container", action, id: item.id, follow }, { focusConsole });
1831
2219
  };
1832
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-stack", children: [
1833
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-toolbar", children: [
1834
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-toolbar-left", children: [
1835
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }),
1836
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-seg", role: "group", "aria-label": t("status"), children: [
1837
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "aria-pressed": all, onClick: () => setAll(true), children: t("all") }),
1838
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "aria-pressed": !all, onClick: () => setAll(false), children: t("running") })
2220
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-stack", children: [
2221
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2222
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-toolbar-left", children: [
2223
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }),
2224
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-seg", role: "group", "aria-label": t("status"), children: [
2225
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": all, onClick: () => setAll(true), children: t("all") }),
2226
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": !all, onClick: () => setAll(false), children: t("running") })
1839
2227
  ] })
1840
2228
  ] }),
1841
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
1842
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "dsh-docker-muted", children: [
2229
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2230
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "dsh-docker-muted", children: [
1843
2231
  filtered.length,
1844
2232
  " / ",
1845
2233
  items.length
1846
2234
  ] }),
1847
- features.includes("run") ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { size: "sm", variant: "primary", onClick: () => onRunContainer(), children: t("runContainer") }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-docker-muted", children: t("restartFeatures") }),
1848
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2235
+ features.includes("run") ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { size: "sm", variant: "primary", onClick: () => onRunContainer(), children: t("runContainer") }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dsh-docker-muted", children: t("restartFeatures") }),
2236
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
1849
2237
  ] })
1850
2238
  ] }),
1851
- !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LoadingSkeleton, { rows: 6 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconBox, { size: 20 }), title: search === "" ? t("emptyContainers") : t("emptySearch"), text: search === "" ? void 0 : search }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "dsh-docker-table", children: [
1852
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("tr", { children: [
1853
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("name") }),
1854
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("image") }),
1855
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("status") }),
1856
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("ports") }),
1857
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { children: t("created") }),
1858
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2239
+ !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LoadingSkeleton, { rows: 6 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconBox, { size: 20 }), title: search === "" ? t("emptyContainers") : t("emptySearch"), text: search === "" ? void 0 : search }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "dsh-docker-table", children: [
2240
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { children: [
2241
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("name") }),
2242
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("image") }),
2243
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("status") }),
2244
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("ports") }),
2245
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("created") }),
2246
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
1859
2247
  ] }) }),
1860
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("tr", { children: [
1861
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("td", { children: [
1862
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "dsh-docker-row-title", style: { border: 0, padding: 0, background: "none", cursor: "pointer", textAlign: "left" }, onClick: () => onInspect("container", item.id), children: item.name || item.id }),
1863
- item.id !== item.name && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-docker-mono dsh-docker-muted", children: item.id })
2248
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tbody", { children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { children: [
2249
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("td", { children: [
2250
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "dsh-docker-row-title", style: { border: 0, padding: 0, background: "none", cursor: "pointer", textAlign: "left" }, onClick: () => onInspect("container", item.id), children: item.name || item.id }),
2251
+ item.id !== item.name && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "dsh-docker-mono dsh-docker-muted", children: item.id })
1864
2252
  ] }),
1865
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "dsh-docker-mono dsh-docker-truncate", title: item.image, children: item.image }),
1866
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StateLabel, { state: item.state, t }) }),
1867
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Chips, { values: item.ports.slice(0, 2), mono: true }) }),
1868
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "dsh-docker-muted", children: item.runningFor || item.createdAt || "\u2014" }),
1869
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "dsh-docker-row-actions", children: [
1870
- item.state === "running" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("stopContainer"), onClick: () => act("stop", item), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconStop, { size: 14 }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("startContainer"), onClick: () => act("start", item), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconPlay, { size: 14 }) }),
1871
- provider === "docker" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("restartContainer"), onClick: () => act("restart", item), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconRestart, { size: 14 }) }),
1872
- canAskAI && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2253
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-mono dsh-docker-truncate", title: item.image, children: item.image }),
2254
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StateLabel, { state: item.state, t }) }),
2255
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Chips, { values: item.ports.slice(0, 2), mono: true }) }),
2256
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-muted", children: item.runningFor || item.createdAt || "\u2014" }),
2257
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2258
+ item.state === "running" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("stopContainer"), onClick: () => act("stop", item), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconStop, { size: 14 }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("startContainer"), onClick: () => act("start", item), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconPlay, { size: 14 }) }),
2259
+ provider === "docker" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("restartContainer"), onClick: () => act("restart", item), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconRestart, { size: 14 }) }),
2260
+ canAskAI && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1873
2261
  IconButton,
1874
2262
  {
1875
2263
  size: "sm",
1876
2264
  label: item.state === "running" ? t("askAi") : t("diagnose"),
1877
2265
  onClick: () => onAskAI(item, item.state === "running" ? "ask" : "diagnose"),
1878
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSparkles, { size: 14 })
2266
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSparkles, { size: 14 })
1879
2267
  }
1880
2268
  ),
1881
- features.includes("exec") && item.state === "running" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("exec"), onClick: () => onAttach(item, "exec"), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconExec, { size: 14 }) }),
1882
- features.includes("attach") && item.state === "running" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("attach"), onClick: () => onAttach(item), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconAttach, { size: 14 }) }),
1883
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("logs"), onClick: () => act("logs", item, true), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconTerminal, { size: 14 }) }),
1884
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("followLogs"), onClick: () => act("logs", item, true, true), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconTerminal, { size: 14, style: { transform: "scaleX(-1)" } }) }),
1885
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("container", item.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconInfo, { size: 14 }) }),
1886
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconButton, { size: "sm", label: t("remove"), onClick: () => act("delete", item), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconTrash, { size: 14 }) })
2269
+ features.includes("exec") && item.state === "running" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("exec"), onClick: () => onAttach(item, "exec"), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconExec, { size: 14 }) }),
2270
+ features.includes("attach") && item.state === "running" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("attach"), onClick: () => onAttach(item), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconAttach, { size: 14 }) }),
2271
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("logs"), onClick: () => act("logs", item, true), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconTerminal, { size: 14 }) }),
2272
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("followLogs"), onClick: () => act("logs", item, true, true), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconTerminal, { size: 14, style: { transform: "scaleX(-1)" } }) }),
2273
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("container", item.id), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconInfo, { size: 14 }) }),
2274
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("remove"), onClick: () => act("delete", item), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconTrash, { size: 14 }) })
1887
2275
  ] }) })
1888
2276
  ] }, item.id)) })
1889
2277
  ] }) }) })
@@ -1891,158 +2279,41 @@ function ContainersTab({ t, api, provider, context, status, refreshToken, featur
1891
2279
  }
1892
2280
 
1893
2281
  // src/client/tabs/images.jsx
1894
- var import_react10 = require("react");
1895
-
1896
- // src/client/build-image.jsx
1897
- var import_react9 = require("react");
1898
- var import_jsx_runtime8 = require("react/jsx-runtime");
1899
- var IMAGE_REF = /^[A-Za-z0-9][A-Za-z0-9_.:/@-]*$/u;
1900
- function BuildImageDialog({ open, t, provider, cwd, onClose, onSubmit }) {
1901
- const [tag, setTag] = (0, import_react9.useState)("");
1902
- const [contextPath, setContextPath] = (0, import_react9.useState)("");
1903
- const [dockerfile, setDockerfile] = (0, import_react9.useState)("Dockerfile");
1904
- const [noCache, setNoCache] = (0, import_react9.useState)(false);
1905
- const [error, setError] = (0, import_react9.useState)(null);
1906
- const [busy, setBusy] = (0, import_react9.useState)(false);
1907
- (0, import_react9.useEffect)(() => {
1908
- if (!open) return;
1909
- setTag("");
1910
- setContextPath(cwd || "");
1911
- setDockerfile("Dockerfile");
1912
- setNoCache(false);
1913
- setError(null);
1914
- setBusy(false);
1915
- }, [open, cwd]);
1916
- const close = () => {
1917
- if (busy) return;
1918
- onClose();
1919
- };
1920
- const submit = async (event) => {
1921
- event?.preventDefault();
1922
- const imageTag = tag.trim();
1923
- const context = contextPath.trim();
1924
- if (!IMAGE_REF.test(imageTag)) {
1925
- setError(t("buildInvalidTag"));
1926
- return;
1927
- }
1928
- if (!context.startsWith("/")) {
1929
- setError(t("buildInvalidContext"));
1930
- return;
1931
- }
1932
- setBusy(true);
1933
- setError(null);
1934
- try {
1935
- await onSubmit({
1936
- kind: "image",
1937
- action: "build",
1938
- tag: imageTag,
1939
- contextPath: context,
1940
- dockerfile: dockerfile.trim() === "" ? void 0 : dockerfile.trim(),
1941
- noCache
1942
- });
1943
- setBusy(false);
1944
- onClose();
1945
- } catch (submitError) {
1946
- setError(submitError instanceof Error ? submitError.message : String(submitError));
1947
- setBusy(false);
1948
- }
1949
- };
1950
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1951
- Modal,
1952
- {
1953
- open,
1954
- title: t("buildImageTitle"),
1955
- subtitle: provider === "apple-container" ? t("providerApple") : t("providerDocker"),
1956
- onClose: close,
1957
- closeLabel: t("close"),
1958
- footer: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1959
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { size: "sm", variant: "ghost", onClick: close, disabled: busy, children: t("modalCancel") }),
1960
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { size: "sm", variant: "primary", onClick: submit, disabled: busy, children: busy ? t("starting") : t("buildStart") })
1961
- ] }),
1962
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { className: "dsh-docker-run-form", onSubmit: submit, children: [
1963
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "dsh-docker-field", children: [
1964
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("buildTag") }),
1965
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1966
- "input",
1967
- {
1968
- className: "dsh-docker-input",
1969
- value: tag,
1970
- onChange: (event) => setTag(event.target.value),
1971
- placeholder: "my-app:latest",
1972
- spellCheck: "false",
1973
- autoFocus: true
1974
- }
1975
- )
1976
- ] }),
1977
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "dsh-docker-field", children: [
1978
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("buildContext") }),
1979
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1980
- "input",
1981
- {
1982
- className: "dsh-docker-input",
1983
- value: contextPath,
1984
- onChange: (event) => setContextPath(event.target.value),
1985
- placeholder: "/Users/me/project",
1986
- spellCheck: "false"
1987
- }
1988
- ),
1989
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { className: "dsh-docker-muted", children: t("buildContextHint") })
1990
- ] }),
1991
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "dsh-docker-field", children: [
1992
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("buildDockerfile") }),
1993
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1994
- "input",
1995
- {
1996
- className: "dsh-docker-input",
1997
- value: dockerfile,
1998
- onChange: (event) => setDockerfile(event.target.value),
1999
- placeholder: "Dockerfile",
2000
- spellCheck: "false"
2001
- }
2002
- )
2003
- ] }),
2004
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "dsh-docker-check", children: [
2005
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked: noCache, onChange: (event) => setNoCache(event.target.checked) }),
2006
- t("buildNoCache")
2007
- ] }),
2008
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "dsh-docker-form-error", children: error })
2009
- ] })
2010
- }
2011
- );
2282
+ var import_react11 = require("react");
2283
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2284
+ var IMAGE_REF3 = /^[A-Za-z0-9][A-Za-z0-9_.:/@-]*$/u;
2285
+ function normalizePullInput(value) {
2286
+ return value.trim().replace(/^(?:docker\s+(?:image\s+)?|container\s+image\s+)pull\s+/iu, "").trim();
2012
2287
  }
2013
-
2014
- // src/client/tabs/images.jsx
2015
- var import_jsx_runtime9 = require("react/jsx-runtime");
2016
- var IMAGE_REF2 = /^[A-Za-z0-9][A-Za-z0-9_.:/@-]*$/u;
2017
- function ImagesTab({ t, api, provider, context, status, refreshToken, features = [], cwd, onAction, onRunContainer, onInspect, onNotify }) {
2288
+ function ImagesTab({ t, api, provider, context, status, refreshToken, features = [], onAction, onRunContainer, onInspect, onNotify, onPullImage, onPushImage, onBuildImage }) {
2018
2289
  const showArchitecture = features.includes("image-architecture");
2019
- const [search, setSearch] = (0, import_react10.useState)("");
2020
- const [pull, setPull] = (0, import_react10.useState)("");
2021
- const [buildOpen, setBuildOpen] = (0, import_react10.useState)(false);
2290
+ const [search, setSearch] = (0, import_react11.useState)("");
2291
+ const [pull, setPull] = (0, import_react11.useState)("");
2292
+ const [pullPlatform, setPullPlatform] = (0, import_react11.useState)("");
2022
2293
  const enabled = status?.daemon?.state === "running";
2023
2294
  const list = useDockerList(api, provider, "images", context, { refreshToken, enabled });
2024
2295
  const items = list.data?.items ?? [];
2025
- const filtered = (0, import_react10.useMemo)(() => {
2296
+ const filtered = (0, import_react11.useMemo)(() => {
2026
2297
  const needle = search.trim().toLowerCase();
2027
2298
  if (needle === "") return items;
2028
2299
  return items.filter((item) => `${item.name} ${item.id} ${item.repository} ${item.tag}`.toLowerCase().includes(needle));
2029
2300
  }, [items, search]);
2030
2301
  const submitPull = (event) => {
2031
2302
  event.preventDefault();
2032
- const reference = pull.trim();
2033
- if (!IMAGE_REF2.test(reference)) {
2303
+ const reference = normalizePullInput(pull);
2304
+ if (!IMAGE_REF3.test(reference)) {
2034
2305
  onNotify("error", t("pullInvalid"));
2035
2306
  return;
2036
2307
  }
2037
2308
  setPull("");
2038
- onAction({ kind: "image", action: "pull", id: reference }, { focusConsole: true });
2309
+ onPullImage(reference, pullPlatform === "" ? void 0 : pullPlatform);
2039
2310
  };
2040
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-stack", children: [
2041
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2042
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-toolbar-left", children: [
2043
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }),
2044
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: submitPull, className: "dsh-docker-toolbar-left", style: { gap: 6 }, children: [
2045
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2311
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-stack", children: [
2312
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2313
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-toolbar-left", children: [
2314
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }),
2315
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: submitPull, className: "dsh-docker-toolbar-left", style: { gap: 6 }, children: [
2316
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2046
2317
  "input",
2047
2318
  {
2048
2319
  className: "dsh-docker-input",
@@ -2050,132 +2321,135 @@ function ImagesTab({ t, api, provider, context, status, refreshToken, features =
2050
2321
  value: pull,
2051
2322
  onChange: (event) => setPull(event.target.value),
2052
2323
  placeholder: t("pullPlaceholder"),
2053
- "aria-label": t("pullPlaceholder"),
2324
+ "aria-label": t("imgPullHint"),
2325
+ title: t("imgPullHint"),
2054
2326
  spellCheck: "false"
2055
2327
  }
2056
2328
  ),
2057
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Button, { size: "sm", type: "submit", disabled: pull.trim() === "", children: [
2058
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconDownload, { size: 13 }),
2329
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2330
+ "select",
2331
+ {
2332
+ className: "dsh-docker-select",
2333
+ style: { width: 150 },
2334
+ value: pullPlatform,
2335
+ onChange: (event) => setPullPlatform(event.target.value),
2336
+ "aria-label": t("imgPullPlatform"),
2337
+ title: t("imgPullPlatform"),
2338
+ children: [
2339
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: t("imgBuildPlatformAuto") }),
2340
+ PLATFORMS.map((name) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: name, children: name }, name))
2341
+ ]
2342
+ }
2343
+ ),
2344
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Button, { size: "sm", type: "submit", disabled: pull.trim() === "", children: [
2345
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconDownload, { size: 13 }),
2059
2346
  " ",
2060
2347
  t("pull")
2061
2348
  ] })
2062
2349
  ] })
2063
2350
  ] }),
2064
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2065
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "dsh-docker-muted", children: [
2351
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2352
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dsh-docker-muted", children: [
2066
2353
  filtered.length,
2067
2354
  " / ",
2068
2355
  items.length
2069
2356
  ] }),
2070
- !showArchitecture && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dsh-docker-muted", children: t("restartForArchitecture") }),
2071
- features.includes("image-build") && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Button, { size: "sm", onClick: () => setBuildOpen(true), children: [
2072
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconBuild, { size: 13 }),
2357
+ !showArchitecture && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "dsh-docker-muted", children: t("restartForArchitecture") }),
2358
+ features.includes("image-build") && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Button, { size: "sm", onClick: onBuildImage, children: [
2359
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconHammer, { size: 13 }),
2073
2360
  " ",
2074
- t("buildImage")
2361
+ t("imgBuild")
2075
2362
  ] }),
2076
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2363
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2077
2364
  ] })
2078
2365
  ] }),
2079
- !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LoadingSkeleton, { rows: 6 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconImage, { size: 20 }), title: search === "" ? t("emptyImages") : t("emptySearch"), text: search === "" ? t("pullPlaceholder") : search }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "dsh-docker-table", children: [
2080
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { children: [
2081
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("repository") }),
2082
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("tag") }),
2083
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("id") }),
2084
- showArchitecture && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("architecture") }),
2085
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "dsh-docker-col-num", children: t("size") }),
2086
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { children: t("createdSince") }),
2087
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2366
+ !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LoadingSkeleton, { rows: 6 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconImage, { size: 20 }), title: search === "" ? t("emptyImages") : t("emptySearch"), text: search === "" ? t("pullPlaceholder") : search }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { className: "dsh-docker-table", children: [
2367
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
2368
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("repository") }),
2369
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("tag") }),
2370
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("id") }),
2371
+ showArchitecture && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("architecture") }),
2372
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "dsh-docker-col-num", children: t("size") }),
2373
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("createdSince") }),
2374
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2088
2375
  ] }) }),
2089
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tbody", { children: filtered.map((item) => {
2376
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tbody", { children: filtered.map((item) => {
2090
2377
  const inspectId = provider === "apple-container" ? item.name : item.id;
2091
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { children: [
2092
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-mono dsh-docker-truncate", title: item.repository, children: item.repository }),
2093
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-mono", children: displayValue(item.tag) }),
2094
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-mono dsh-docker-muted", title: item.id, children: shortId(item.id) }),
2095
- showArchitecture && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-mono", children: displayValue(item.architecture) }),
2096
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-col-num", children: displayValue(item.size) }),
2097
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-muted", children: displayValue(item.createdSince) }),
2098
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2099
- features.includes("run") && item.name !== "<none>" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("runFromImage"), onClick: () => onRunContainer(item.name), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconPlay, { size: 14 }) }),
2100
- features.includes("image-push") && item.name !== "<none>" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("pushImage"), onClick: () => onAction({ kind: "image", action: "push", id: item.name }, { focusConsole: true }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconUpload, { size: 14 }) }),
2101
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("image", inspectId), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconInfo, { size: 14 }) }),
2102
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconButton, { size: "sm", label: t("removeImage"), onClick: () => onAction({ kind: "image", action: "delete", id: inspectId }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconTrash, { size: 14 }) })
2378
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
2379
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-mono dsh-docker-truncate", title: item.repository, children: item.repository }),
2380
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-mono", children: displayValue(item.tag) }),
2381
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-mono dsh-docker-muted", title: item.id, children: shortId(item.id) }),
2382
+ showArchitecture && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-mono", children: displayValue(item.architecture) }),
2383
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-col-num", children: displayValue(item.size) }),
2384
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-muted", children: displayValue(item.createdSince) }),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2386
+ features.includes("run") && item.name !== "<none>" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconButton, { size: "sm", label: t("runFromImage"), onClick: () => onRunContainer(item.name), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconPlay, { size: 14 }) }),
2387
+ features.includes("image-push") && item.name !== "<none>" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconButton, { size: "sm", label: t("imgPush"), onClick: () => onPushImage(item.name), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconUpload, { size: 14 }) }),
2388
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("image", inspectId), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconInfo, { size: 14 }) }),
2389
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconButton, { size: "sm", label: t("removeImage"), onClick: () => onAction({ kind: "image", action: "delete", id: inspectId }), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconTrash, { size: 14 }) })
2103
2390
  ] }) })
2104
2391
  ] }, `${item.id}-${item.name}`);
2105
2392
  }) })
2106
- ] }) }) }),
2107
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2108
- BuildImageDialog,
2109
- {
2110
- open: buildOpen,
2111
- t,
2112
- provider,
2113
- cwd,
2114
- onClose: () => setBuildOpen(false),
2115
- onSubmit: async (input) => {
2116
- await onAction(input, { focusConsole: true });
2117
- }
2118
- }
2119
- )
2393
+ ] }) }) })
2120
2394
  ] });
2121
2395
  }
2122
2396
 
2123
2397
  // src/client/tabs/networks.jsx
2124
- var import_react11 = require("react");
2125
- var import_jsx_runtime10 = require("react/jsx-runtime");
2398
+ var import_react12 = require("react");
2399
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2126
2400
  var BUILTIN = /* @__PURE__ */ new Set(["bridge", "host", "none"]);
2127
2401
  function NetworksTab({ t, api, provider, context, status, refreshToken, onAction, onInspect }) {
2128
- const [search, setSearch] = (0, import_react11.useState)("");
2402
+ const [search, setSearch] = (0, import_react12.useState)("");
2129
2403
  const enabled = status?.daemon?.state === "running";
2130
2404
  const list = useDockerList(api, provider, "networks", context, { refreshToken, enabled });
2131
2405
  const items = list.data?.items ?? [];
2132
2406
  const builtin = provider === "apple-container" ? /* @__PURE__ */ new Set(["default"]) : BUILTIN;
2133
- const filtered = (0, import_react11.useMemo)(() => {
2407
+ const filtered = (0, import_react12.useMemo)(() => {
2134
2408
  const needle = search.trim().toLowerCase();
2135
2409
  return needle === "" ? items : items.filter((item) => `${item.name} ${item.driver} ${item.scope} ${item.id}`.toLowerCase().includes(needle));
2136
2410
  }, [items, search]);
2137
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-stack", children: [
2138
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2139
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "dsh-docker-toolbar-left", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }) }),
2140
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2141
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dsh-docker-muted", children: [
2411
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-stack", children: [
2412
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2413
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-toolbar-left", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }) }),
2414
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2415
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "dsh-docker-muted", children: [
2142
2416
  filtered.length,
2143
2417
  " / ",
2144
2418
  items.length
2145
2419
  ] }),
2146
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2420
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2147
2421
  ] })
2148
2422
  ] }),
2149
- !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LoadingSkeleton, { rows: 5 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconNetwork, { size: 20 }), title: search === "" ? t("emptyNetworks") : t("emptySearch"), text: search === "" ? void 0 : search }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { className: "dsh-docker-table", children: [
2150
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
2151
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("name") }),
2152
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("driver") }),
2153
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("scope") }),
2154
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: "IPv4" }),
2155
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: "IPv6" }),
2156
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { children: t("internal") }),
2157
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2423
+ !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LoadingSkeleton, { rows: 5 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconNetwork, { size: 20 }), title: search === "" ? t("emptyNetworks") : t("emptySearch"), text: search === "" ? void 0 : search }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { className: "dsh-docker-table", children: [
2424
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
2425
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("name") }),
2426
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("driver") }),
2427
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("scope") }),
2428
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: "IPv4" }),
2429
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: "IPv6" }),
2430
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("internal") }),
2431
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2158
2432
  ] }) }),
2159
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tbody", { children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
2160
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("td", { children: [
2161
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "dsh-docker-row-title", children: item.name }),
2162
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "dsh-docker-mono dsh-docker-muted", children: item.id })
2433
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
2434
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("td", { children: [
2435
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-row-title", children: item.name }),
2436
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-mono dsh-docker-muted", children: item.id })
2163
2437
  ] }),
2164
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { children: displayValue(item.driver) }),
2165
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { children: displayValue(item.scope) }),
2166
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { children: displayValue(item.ipv4) }),
2167
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { children: displayValue(item.ipv6) }),
2168
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { children: displayValue(item.internal) }),
2169
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2170
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("network", item.id), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconInfo, { size: 14 }) }),
2171
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2438
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: displayValue(item.driver) }),
2439
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: displayValue(item.scope) }),
2440
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: displayValue(item.ipv4) }),
2441
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: displayValue(item.ipv6) }),
2442
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: displayValue(item.internal) }),
2443
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2444
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("network", item.id), children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconInfo, { size: 14 }) }),
2445
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2172
2446
  IconButton,
2173
2447
  {
2174
2448
  size: "sm",
2175
2449
  label: t("removeNetwork"),
2176
2450
  disabled: builtin.has(item.name),
2177
2451
  onClick: () => onAction({ kind: "network", action: "delete", id: item.name }),
2178
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconTrash, { size: 14 })
2452
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconTrash, { size: 14 })
2179
2453
  }
2180
2454
  )
2181
2455
  ] }) })
@@ -2185,13 +2459,13 @@ function NetworksTab({ t, api, provider, context, status, refreshToken, onAction
2185
2459
  }
2186
2460
 
2187
2461
  // src/client/tabs/overview.jsx
2188
- var import_react12 = require("react");
2189
- var import_jsx_runtime11 = require("react/jsx-runtime");
2462
+ var import_react13 = require("react");
2463
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2190
2464
  function Stat({ label, value, detail }) {
2191
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-stat", children: [
2192
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-stat-label", children: label }),
2193
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-stat-value", children: value }),
2194
- detail !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-stat-detail", children: detail })
2465
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-stat", children: [
2466
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-stat-label", children: label }),
2467
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-stat-value", children: value }),
2468
+ detail !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-stat-detail", children: detail })
2195
2469
  ] });
2196
2470
  }
2197
2471
  function RuntimeCard({ t, provider, status, imageCount, volumeCount, networkCount, onRuntime, busy }) {
@@ -2220,92 +2494,92 @@ function RuntimeCard({ t, provider, status, imageCount, volumeCount, networkCoun
2220
2494
  [t("memory"), runtime?.memory !== void 0 ? formatBytes(runtime.memory) : void 0],
2221
2495
  [t("disk"), runtime?.disk !== void 0 ? formatBytes(runtime.disk) : void 0]
2222
2496
  ]).filter(([, value]) => value !== void 0 && value !== null && value !== "");
2223
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "dsh-docker-card", children: [
2224
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-card-head", children: [
2225
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2226
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "dsh-docker-card-title", children: t("runtime") }),
2227
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "dsh-docker-card-sub", children: runtime?.kind ?? "" })
2497
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "dsh-docker-card", children: [
2498
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-card-head", children: [
2499
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
2500
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { className: "dsh-docker-card-title", children: t("runtime") }),
2501
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "dsh-docker-card-sub", children: runtime?.kind ?? "" })
2228
2502
  ] }),
2229
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "dsh-docker-status", "data-state": runtime?.running ? "running" : "stopped", children: [
2230
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dsh-docker-dot" }),
2503
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "dsh-docker-status", "data-state": runtime?.running ? "running" : "stopped", children: [
2504
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-docker-dot" }),
2231
2505
  runtime?.running ? t("statusRunning") : t("statusStopped")
2232
2506
  ] })
2233
2507
  ] }),
2234
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-card-body", children: [
2235
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-runtime-head", children: [
2236
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dsh-docker-mark", style: { width: 34, height: 34 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconBox, { size: 19 }) }),
2237
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2238
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-runtime-name", children: runtime?.label ?? t("unknownRuntime") }),
2239
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-muted", children: isApple ? "container \xB7 per-container VM" : runtime?.kind === "colima" ? `colima \xB7 profile ${runtime.profile ?? "default"}` : runtime?.kind ?? "" })
2508
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-card-body", children: [
2509
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-runtime-head", children: [
2510
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-docker-mark", style: { width: 34, height: 34 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconBox, { size: 19 }) }),
2511
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
2512
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-runtime-name", children: runtime?.label ?? t("unknownRuntime") }),
2513
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-muted", children: isApple ? "container \xB7 per-container VM" : runtime?.kind === "colima" ? `colima \xB7 profile ${runtime.profile ?? "default"}` : runtime?.kind ?? "" })
2240
2514
  ] })
2241
2515
  ] }),
2242
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv", children: rows.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-kv-row", style: { display: "contents" }, children: [
2243
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-key", children: key }),
2244
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-value", children: displayValue(value) })
2516
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv", children: rows.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-kv-row", style: { display: "contents" }, children: [
2517
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-key", children: key }),
2518
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-value", children: displayValue(value) })
2245
2519
  ] }, key)) }),
2246
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-middle", style: { marginTop: 14 }, children: [
2247
- runtime?.canStart === true && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Button, { size: "sm", variant: "primary", onClick: () => onRuntime("start"), disabled: busy, children: [
2248
- busy ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Spinner, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconPlay, { size: 13 }),
2520
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-middle", style: { marginTop: 14 }, children: [
2521
+ runtime?.canStart === true && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Button, { size: "sm", variant: "primary", onClick: () => onRuntime("start"), disabled: busy, children: [
2522
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Spinner, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconPlay, { size: 13 }),
2249
2523
  " ",
2250
2524
  t("start")
2251
2525
  ] }),
2252
- runtime?.canStop === true && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Button, { size: "sm", onClick: () => onRuntime("stop"), disabled: busy, children: [
2253
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconStop, { size: 13 }),
2526
+ runtime?.canStop === true && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Button, { size: "sm", onClick: () => onRuntime("stop"), disabled: busy, children: [
2527
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconStop, { size: 13 }),
2254
2528
  " ",
2255
2529
  t("stop")
2256
2530
  ] }),
2257
- runtime?.canRestart === true && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Button, { size: "sm", onClick: () => onRuntime("restart"), disabled: busy, children: [
2258
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconRestart, { size: 13 }),
2531
+ runtime?.canRestart === true && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Button, { size: "sm", onClick: () => onRuntime("restart"), disabled: busy, children: [
2532
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconRestart, { size: 13 }),
2259
2533
  " ",
2260
2534
  t("restart")
2261
2535
  ] }),
2262
- runtime?.canStart !== true && runtime?.canStop !== true && runtime?.canRestart !== true && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dsh-docker-muted", children: status.capabilities?.enableRuntimeControl === false ? t("runtimeControlDisabled") : runtime?.error ?? t("remoteHint") })
2536
+ runtime?.canStart !== true && runtime?.canStop !== true && runtime?.canRestart !== true && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-docker-muted", children: status.capabilities?.enableRuntimeControl === false ? t("runtimeControlDisabled") : runtime?.error ?? t("remoteHint") })
2263
2537
  ] })
2264
2538
  ] })
2265
2539
  ] });
2266
2540
  }
2267
2541
  function RecentContainers({ t, list, onOpenTab, onInspect }) {
2268
- if (list.loading && list.data === null) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LoadingSkeleton, { rows: 4 });
2542
+ if (list.loading && list.data === null) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LoadingSkeleton, { rows: 4 });
2269
2543
  if (list.error !== null && list.data === null) {
2270
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload });
2544
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload });
2271
2545
  }
2272
2546
  const items = (list.data?.items ?? []).slice(0, 5);
2273
2547
  if (items.length === 0) {
2274
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconBox, { size: 19 }), title: t("emptyContainers") });
2548
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconBox, { size: 19 }), title: t("emptyContainers") });
2275
2549
  }
2276
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-table-wrap", children: [
2277
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { className: "dsh-docker-table", children: [
2278
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
2279
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("name") }),
2280
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("image") }),
2281
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("status") }),
2282
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("ports") })
2550
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-table-wrap", children: [
2551
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "dsh-docker-table", children: [
2552
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
2553
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("name") }),
2554
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("image") }),
2555
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("status") }),
2556
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("ports") })
2283
2557
  ] }) }),
2284
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { onClick: () => onInspect("container", item.id), style: { cursor: "pointer" }, children: [
2285
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dsh-docker-row-title", children: item.name || item.id }) }),
2286
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "dsh-docker-mono dsh-docker-truncate", children: item.image }),
2287
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StateLabel, { state: item.state, t }) }),
2288
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Chips, { values: item.ports.slice(0, 2), mono: true }) })
2558
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { onClick: () => onInspect("container", item.id), style: { cursor: "pointer" }, children: [
2559
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-docker-row-title", children: item.name || item.id }) }),
2560
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "dsh-docker-mono dsh-docker-truncate", children: item.image }),
2561
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(StateLabel, { state: item.state, t }) }),
2562
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Chips, { values: item.ports.slice(0, 2), mono: true }) })
2289
2563
  ] }, item.id)) })
2290
2564
  ] }),
2291
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", padding: "8px 12px" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => onOpenTab("containers"), children: t("viewAll") }) })
2565
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", padding: "8px 12px" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => onOpenTab("containers"), children: t("viewAll") }) })
2292
2566
  ] });
2293
2567
  }
2294
2568
  function DiskCard({ t, list }) {
2295
- if (list.loading && list.data === null) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LoadingSkeleton, { rows: 3 });
2296
- if (list.error !== null && list.data === null) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-muted", style: { padding: 16 }, children: list.error.message });
2569
+ if (list.loading && list.data === null) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LoadingSkeleton, { rows: 3 });
2570
+ if (list.error !== null && list.data === null) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-muted", style: { padding: 16 }, children: list.error.message });
2297
2571
  const items = list.data?.items ?? [];
2298
- if (items.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-muted", style: { padding: 16 }, children: t("noDiskData") });
2299
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { className: "dsh-docker-table", children: [
2300
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
2301
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: t("status") }),
2302
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { className: "dsh-docker-col-num", children: t("size") }),
2303
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { className: "dsh-docker-col-num", children: "Reclaimable" })
2572
+ if (items.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-muted", style: { padding: 16 }, children: t("noDiskData") });
2573
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "dsh-docker-table", children: [
2574
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
2575
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("status") }),
2576
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "dsh-docker-col-num", children: t("size") }),
2577
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "dsh-docker-col-num", children: "Reclaimable" })
2304
2578
  ] }) }),
2305
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
2306
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: item.type }),
2307
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "dsh-docker-col-num", children: displayValue(item.size) }),
2308
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "dsh-docker-col-num", children: displayValue(item.reclaimable) })
2579
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
2580
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { children: item.type }),
2581
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "dsh-docker-col-num", children: displayValue(item.size) }),
2582
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "dsh-docker-col-num", children: displayValue(item.reclaimable) })
2309
2583
  ] }, item.type)) })
2310
2584
  ] }) });
2311
2585
  }
@@ -2321,18 +2595,18 @@ function OverviewTab({ t, api, provider, context, status, refreshToken, onRuntim
2321
2595
  const isApple = provider === "apple-container";
2322
2596
  const quick = isApple ? ["ls -a", "image ls", "volume ls", "network ls", "system df", "system version"] : ["ps -a", "images", "volume ls", "network ls", "compose ls", "system df", "info", "version"];
2323
2597
  const commandPrefix = isApple ? "container" : "docker";
2324
- const recent = (0, import_react12.useMemo)(() => (containers.data?.items ?? []).slice(0, 5), [containers.data]);
2598
+ const recent = (0, import_react13.useMemo)(() => (containers.data?.items ?? []).slice(0, 5), [containers.data]);
2325
2599
  const volumeCount = volumes.data?.items?.length;
2326
2600
  const networkCount = networks.data?.items?.length;
2327
2601
  const imageCount = images.data?.items?.length ?? server?.images;
2328
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-stack", children: [
2329
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-stats", children: [
2330
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Stat, { label: t("runningContainers"), value: server?.containersRunning ?? "\u2014", detail: isApple ? t("providerApple") : context ?? t("noContext") }),
2331
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Stat, { label: t("stoppedContainers"), value: server?.containersStopped ?? "\u2014" }),
2332
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Stat, { label: t("imageCount"), value: imageCount ?? "\u2014" }),
2333
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Stat, { label: t("volumeCount"), value: volumeCount ?? "\u2014" }),
2334
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Stat, { label: t("networkCount"), value: networkCount ?? "\u2014" }),
2335
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2602
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-stack", children: [
2603
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-stats", children: [
2604
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Stat, { label: t("runningContainers"), value: server?.containersRunning ?? "\u2014", detail: isApple ? t("providerApple") : context ?? t("noContext") }),
2605
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Stat, { label: t("stoppedContainers"), value: server?.containersStopped ?? "\u2014" }),
2606
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Stat, { label: t("imageCount"), value: imageCount ?? "\u2014" }),
2607
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Stat, { label: t("volumeCount"), value: volumeCount ?? "\u2014" }),
2608
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Stat, { label: t("networkCount"), value: networkCount ?? "\u2014" }),
2609
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2336
2610
  Stat,
2337
2611
  {
2338
2612
  label: t("server"),
@@ -2341,102 +2615,102 @@ function OverviewTab({ t, api, provider, context, status, refreshToken, onRuntim
2341
2615
  }
2342
2616
  )
2343
2617
  ] }),
2344
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-grid-2", children: [
2345
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RuntimeCard, { t, provider, status, imageCount, volumeCount, networkCount, onRuntime, busy }),
2346
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "dsh-docker-card", children: [
2347
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-card-head", children: [
2348
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2349
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "dsh-docker-card-title", children: t("quickCommands") }),
2350
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "dsh-docker-card-sub", children: t("terminal") })
2618
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-grid-2", children: [
2619
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RuntimeCard, { t, provider, status, imageCount, volumeCount, networkCount, onRuntime, busy }),
2620
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "dsh-docker-card", children: [
2621
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-card-head", children: [
2622
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
2623
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { className: "dsh-docker-card-title", children: t("quickCommands") }),
2624
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "dsh-docker-card-sub", children: t("terminal") })
2351
2625
  ] }),
2352
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconTerminal, { size: 16, className: "dsh-docker-muted" })
2626
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconTerminal, { size: 16, className: "dsh-docker-muted" })
2353
2627
  ] }),
2354
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-card-body", children: [
2355
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-chip-row", children: quick.map((command) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "dsh-docker-quick", onClick: () => onQuickCommand(`${commandPrefix} ${command}`), children: command }, command)) }),
2356
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-divider" }),
2357
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-kv", children: [
2358
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-key", children: t("client") }),
2359
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-kv-value", children: [
2628
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-card-body", children: [
2629
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-chip-row", children: quick.map((command) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "dsh-docker-quick", onClick: () => onQuickCommand(`${commandPrefix} ${command}`), children: command }, command)) }),
2630
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-divider" }),
2631
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-kv", children: [
2632
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-key", children: t("client") }),
2633
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-kv-value", children: [
2360
2634
  status?.client?.version ?? "\u2014",
2361
2635
  " ",
2362
- status?.cli?.path ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "dsh-docker-mono dsh-docker-muted", children: [
2636
+ status?.cli?.path ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "dsh-docker-mono dsh-docker-muted", children: [
2363
2637
  " \xB7 ",
2364
2638
  status.cli.path
2365
2639
  ] }) : null
2366
2640
  ] }),
2367
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-key", children: isApple ? t("providerLabel") : t("context") }),
2368
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-value", children: isApple ? t("providerApple") : context ?? status?.context?.selected ?? status?.context?.current ?? t("noContext") }),
2369
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-key", children: t("lastUpdated") }),
2370
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-kv-value", children: formatTime(status?.fetchedAt) })
2641
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-key", children: isApple ? t("providerLabel") : t("context") }),
2642
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-value", children: isApple ? t("providerApple") : context ?? status?.context?.selected ?? status?.context?.current ?? t("noContext") }),
2643
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-key", children: t("lastUpdated") }),
2644
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-kv-value", children: formatTime(status?.fetchedAt) })
2371
2645
  ] })
2372
2646
  ] })
2373
2647
  ] })
2374
2648
  ] }),
2375
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-grid-2", children: [
2376
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "dsh-docker-card", children: [
2377
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-card-head", children: [
2378
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "dsh-docker-card-title", children: t("recentContainers") }) }),
2379
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => onOpenTab("containers"), children: t("viewAll") })
2649
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-grid-2", children: [
2650
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "dsh-docker-card", children: [
2651
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-card-head", children: [
2652
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { className: "dsh-docker-card-title", children: t("recentContainers") }) }),
2653
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button, { size: "sm", variant: "ghost", onClick: () => onOpenTab("containers"), children: t("viewAll") })
2380
2654
  ] }),
2381
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-card-body dsh-docker-flush", style: { paddingTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RecentContainers, { t, list: { ...containers, data: containers.data ?? { items: recent } }, onOpenTab, onInspect }) })
2655
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-card-body dsh-docker-flush", style: { paddingTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RecentContainers, { t, list: { ...containers, data: containers.data ?? { items: recent } }, onOpenTab, onInspect }) })
2382
2656
  ] }),
2383
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "dsh-docker-card", children: [
2384
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-docker-card-head", children: [
2385
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2386
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "dsh-docker-card-title", children: t("disk") }),
2387
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "dsh-docker-card-sub", children: [
2657
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "dsh-docker-card", children: [
2658
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-card-head", children: [
2659
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
2660
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { className: "dsh-docker-card-title", children: t("disk") }),
2661
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "dsh-docker-card-sub", children: [
2388
2662
  commandPrefix,
2389
2663
  " system df"
2390
2664
  ] })
2391
2665
  ] }),
2392
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconImage, { size: 16, className: "dsh-docker-muted" })
2666
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconImage, { size: 16, className: "dsh-docker-muted" })
2393
2667
  ] }),
2394
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dsh-docker-card-body dsh-docker-flush", style: { paddingTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DiskCard, { t, list: disk }) })
2668
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-card-body dsh-docker-flush", style: { paddingTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DiskCard, { t, list: disk }) })
2395
2669
  ] })
2396
2670
  ] })
2397
2671
  ] });
2398
2672
  }
2399
2673
 
2400
2674
  // src/client/tabs/volumes.jsx
2401
- var import_react13 = require("react");
2402
- var import_jsx_runtime12 = require("react/jsx-runtime");
2675
+ var import_react14 = require("react");
2676
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2403
2677
  function VolumesTab({ t, api, provider, context, status, refreshToken, onAction, onInspect }) {
2404
- const [search, setSearch] = (0, import_react13.useState)("");
2678
+ const [search, setSearch] = (0, import_react14.useState)("");
2405
2679
  const enabled = status?.daemon?.state === "running";
2406
2680
  const list = useDockerList(api, provider, "volumes", context, { refreshToken, enabled });
2407
2681
  const items = list.data?.items ?? [];
2408
- const filtered = (0, import_react13.useMemo)(() => {
2682
+ const filtered = (0, import_react14.useMemo)(() => {
2409
2683
  const needle = search.trim().toLowerCase();
2410
2684
  return needle === "" ? items : items.filter((item) => `${item.name} ${item.driver} ${item.mountpoint}`.toLowerCase().includes(needle));
2411
2685
  }, [items, search]);
2412
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-stack", children: [
2413
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2414
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-toolbar-left", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }) }),
2415
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2416
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "dsh-docker-muted", children: [
2686
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-stack", children: [
2687
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-toolbar", children: [
2688
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-toolbar-left", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SearchInput, { value: search, onChange: setSearch, placeholder: t("search"), label: t("search") }) }),
2689
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-toolbar-right", children: [
2690
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "dsh-docker-muted", children: [
2417
2691
  filtered.length,
2418
2692
  " / ",
2419
2693
  items.length
2420
2694
  ] }),
2421
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2695
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "sm", onClick: list.reload, disabled: list.loading, children: t("refresh") })
2422
2696
  ] })
2423
2697
  ] }),
2424
- !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LoadingSkeleton, { rows: 5 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconVolume, { size: 20 }), title: search === "" ? t("emptyVolumes") : t("emptySearch"), text: search === "" ? void 0 : search }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "dsh-docker-table", children: [
2425
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
2426
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("name") }),
2427
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("driver") }),
2428
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("scope") }),
2429
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { children: t("mountpoint") }),
2430
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2698
+ !enabled && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconAlert, { size: 20 }), title: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped"), text: provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody") }) : list.loading && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LoadingSkeleton, { rows: 5 }) : list.error !== null && list.data === null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ErrorState, { title: t("listFailed"), text: list.error.message, retryLabel: t("retry"), onRetry: list.reload }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EmptyState, { icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconVolume, { size: 20 }), title: search === "" ? t("emptyVolumes") : t("emptySearch"), text: search === "" ? void 0 : search }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("section", { className: "dsh-docker-card", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("table", { className: "dsh-docker-table", children: [
2699
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { children: [
2700
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { children: t("name") }),
2701
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { children: t("driver") }),
2702
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { children: t("scope") }),
2703
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { children: t("mountpoint") }),
2704
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "dsh-docker-col-actions", children: t("actions") })
2431
2705
  ] }) }),
2432
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
2433
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "dsh-docker-mono dsh-docker-row-title", children: item.name }),
2434
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { children: displayValue(item.driver) }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { children: displayValue(item.scope) }),
2436
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "dsh-docker-mono dsh-docker-muted dsh-docker-truncate", title: item.mountpoint, children: displayValue(item.mountpoint) }),
2437
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2438
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("volume", item.name), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconInfo, { size: 14 }) }),
2439
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { size: "sm", label: t("removeVolume"), onClick: () => onAction({ kind: "volume", action: "delete", id: item.name }), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconTrash, { size: 14 }) })
2706
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { children: [
2707
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "dsh-docker-mono dsh-docker-row-title", children: item.name }),
2708
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { children: displayValue(item.driver) }),
2709
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { children: displayValue(item.scope) }),
2710
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "dsh-docker-mono dsh-docker-muted dsh-docker-truncate", title: item.mountpoint, children: displayValue(item.mountpoint) }),
2711
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "dsh-docker-col-actions", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "dsh-docker-row-actions", children: [
2712
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconButton, { size: "sm", label: t("inspect"), onClick: () => onInspect("volume", item.name), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconInfo, { size: 14 }) }),
2713
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconButton, { size: "sm", label: t("removeVolume"), onClick: () => onAction({ kind: "volume", action: "delete", id: item.name }), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconTrash, { size: 14 }) })
2440
2714
  ] }) })
2441
2715
  ] }, item.name)) })
2442
2716
  ] }) }) })
@@ -2444,7 +2718,7 @@ function VolumesTab({ t, api, provider, context, status, refreshToken, onAction,
2444
2718
  }
2445
2719
 
2446
2720
  // src/client/page.jsx
2447
- var import_jsx_runtime13 = require("react/jsx-runtime");
2721
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2448
2722
  var TABS = [
2449
2723
  ["overview", "overview"],
2450
2724
  ["containers", "containers"],
@@ -2454,7 +2728,7 @@ var TABS = [
2454
2728
  ["compose", "compose"],
2455
2729
  ["console", "console"]
2456
2730
  ];
2457
- var DockerErrorBoundary = class extends import_react14.Component {
2731
+ var DockerErrorBoundary = class extends import_react15.Component {
2458
2732
  constructor(props) {
2459
2733
  super(props);
2460
2734
  this.state = { error: null };
@@ -2464,7 +2738,7 @@ var DockerErrorBoundary = class extends import_react14.Component {
2464
2738
  }
2465
2739
  render() {
2466
2740
  if (this.state.error !== null) {
2467
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-body", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2741
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-body", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2468
2742
  ErrorState,
2469
2743
  {
2470
2744
  title: this.props.t("errorTitle"),
@@ -2494,35 +2768,38 @@ function tabCount(tab, status, counts) {
2494
2768
  return void 0;
2495
2769
  }
2496
2770
  function DockerPage(props) {
2497
- const { t, api, runs, useStore, actions, startDiagnosis } = props;
2771
+ const { t, api, runs, useStore, actions, startDiagnosis, pickDirectory } = props;
2498
2772
  const store = useStore((snapshot) => snapshot);
2499
2773
  const tab = store.tab;
2500
2774
  const provider = store.provider;
2501
2775
  const context = store.context;
2502
2776
  const cwd = store.cwd;
2503
- const [refreshToken, setRefreshToken] = (0, import_react14.useState)(0);
2504
- const [draft, setDraft] = (0, import_react14.useState)("");
2505
- const [startingAt, setStartingAt] = (0, import_react14.useState)(null);
2506
- const [runtimeBusy, setRuntimeBusy] = (0, import_react14.useState)(null);
2507
- const [inspect, setInspect] = (0, import_react14.useState)({ open: false, loading: false, kind: null, id: null, value: null, raw: "", error: null });
2508
- const [confirm, setConfirm] = (0, import_react14.useState)(null);
2509
- const [attach, setAttach] = (0, import_react14.useState)({ open: false, loading: false, mode: "attach", session: null, output: "", error: null });
2510
- const [runDialog, setRunDialog] = (0, import_react14.useState)({ open: false, image: "" });
2511
- const attachRef = (0, import_react14.useRef)(null);
2512
- const attachRequest = (0, import_react14.useRef)(0);
2513
- const [toasts, setToasts] = (0, import_react14.useState)([]);
2514
- const toastTimers = (0, import_react14.useRef)(/* @__PURE__ */ new Map());
2777
+ const [refreshToken, setRefreshToken] = (0, import_react15.useState)(0);
2778
+ const [draft, setDraft] = (0, import_react15.useState)("");
2779
+ const [startingAt, setStartingAt] = (0, import_react15.useState)(null);
2780
+ const [runtimeBusy, setRuntimeBusy] = (0, import_react15.useState)(null);
2781
+ const [inspect, setInspect] = (0, import_react15.useState)({ open: false, loading: false, kind: null, id: null, value: null, raw: "", error: null });
2782
+ const [confirm, setConfirm] = (0, import_react15.useState)(null);
2783
+ const [attach, setAttach] = (0, import_react15.useState)({ open: false, loading: false, mode: "attach", session: null, output: "", error: null });
2784
+ const [runDialog, setRunDialog] = (0, import_react15.useState)({ open: false, image: "" });
2785
+ const [pushDialog, setPushDialog] = (0, import_react15.useState)({ open: false, image: "" });
2786
+ const [buildDialog, setBuildDialog] = (0, import_react15.useState)(false);
2787
+ const watchedJob = (0, import_react15.useRef)(null);
2788
+ const attachRef = (0, import_react15.useRef)(null);
2789
+ const attachRequest = (0, import_react15.useRef)(0);
2790
+ const [toasts, setToasts] = (0, import_react15.useState)([]);
2791
+ const toastTimers = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
2515
2792
  const providersState = useProviders(api);
2516
- const providerOptions = (0, import_react14.useMemo)(() => (providersState.data?.providers ?? []).filter((item) => item.available), [providersState.data]);
2517
- const features = (0, import_react14.useMemo)(() => providersState.data?.features ?? [], [providersState.data]);
2793
+ const providerOptions = (0, import_react15.useMemo)(() => (providersState.data?.providers ?? []).filter((item) => item.available), [providersState.data]);
2794
+ const features = (0, import_react15.useMemo)(() => providersState.data?.features ?? [], [providersState.data]);
2518
2795
  const canAskAI = features.includes("ai-tools") && typeof startDiagnosis === "function";
2519
2796
  const statusState = useDockerStatus(api, provider, provider === "docker" ? context : null, refreshToken);
2520
2797
  const status = statusState.data;
2521
- const runState = (0, import_react14.useSyncExternalStore)(runs.subscribe, runs.getSnapshot);
2798
+ const runState = (0, import_react15.useSyncExternalStore)(runs.subscribe, runs.getSnapshot);
2522
2799
  const selectedContext = provider === "docker" ? context ?? status?.context?.selected ?? null : null;
2523
2800
  const contexts = provider === "docker" ? status?.context?.contexts ?? [] : [];
2524
2801
  const pill = runtimeStatus(status, t);
2525
- const notify = (0, import_react14.useCallback)((tone, message) => {
2802
+ const notify = (0, import_react15.useCallback)((tone, message) => {
2526
2803
  const id = `${Date.now()}_${Math.random().toString(16).slice(2)}`;
2527
2804
  setToasts((current) => [...current.slice(-3), { id, tone, message }]);
2528
2805
  const timer = setTimeout(() => {
@@ -2531,27 +2808,27 @@ function DockerPage(props) {
2531
2808
  }, tone === "error" ? 7e3 : 4e3);
2532
2809
  toastTimers.current.set(id, timer);
2533
2810
  }, []);
2534
- (0, import_react14.useEffect)(() => () => {
2811
+ (0, import_react15.useEffect)(() => () => {
2535
2812
  for (const timer of toastTimers.current.values()) clearTimeout(timer);
2536
2813
  toastTimers.current.clear();
2537
2814
  }, []);
2538
- (0, import_react14.useEffect)(() => {
2815
+ (0, import_react15.useEffect)(() => {
2539
2816
  if (providersState.data === null || providerOptions.length === 0) return;
2540
2817
  if (!providerOptions.some((item) => item.id === provider)) {
2541
2818
  const next = providersState.data.defaultProvider ?? providerOptions[0].id;
2542
2819
  if (next !== provider) actions.setProvider(next);
2543
2820
  }
2544
2821
  }, [actions, provider, providerOptions, providersState.data]);
2545
- (0, import_react14.useEffect)(() => {
2822
+ (0, import_react15.useEffect)(() => {
2546
2823
  if (provider === "apple-container" && tab === "compose") actions.setTab("overview");
2547
2824
  }, [actions, provider, tab]);
2548
- (0, import_react14.useEffect)(() => {
2825
+ (0, import_react15.useEffect)(() => {
2549
2826
  if (provider !== "docker") return;
2550
2827
  if (context !== null && status !== null && contexts.length > 0 && !contexts.some((item) => item.name === context)) {
2551
2828
  actions.setContext(null);
2552
2829
  }
2553
2830
  }, [actions, context, contexts, provider, status]);
2554
- (0, import_react14.useEffect)(() => {
2831
+ (0, import_react15.useEffect)(() => {
2555
2832
  runs.onFinished = (finished) => {
2556
2833
  setRefreshToken((value) => value + 1);
2557
2834
  statusState.refresh();
@@ -2565,7 +2842,7 @@ function DockerPage(props) {
2565
2842
  runs.onFinished = void 0;
2566
2843
  };
2567
2844
  }, [notify, runs, startingAt, statusState.refresh, t]);
2568
- (0, import_react14.useEffect)(() => {
2845
+ (0, import_react15.useEffect)(() => {
2569
2846
  if (startingAt === null) return void 0;
2570
2847
  if (runtimeBusy === "stop" ? status?.daemon?.state !== "running" : status?.daemon?.state === "running") {
2571
2848
  setStartingAt(null);
@@ -2580,13 +2857,13 @@ function DockerPage(props) {
2580
2857
  }, provider === "apple-container" ? 45e3 : 13e4);
2581
2858
  return () => clearTimeout(timer);
2582
2859
  }, [notify, provider, runtimeBusy, startingAt, status?.daemon?.state, status?.runtime?.label, t]);
2583
- const refreshAll = (0, import_react14.useCallback)(() => {
2860
+ const refreshAll = (0, import_react15.useCallback)(() => {
2584
2861
  cacheClear();
2585
2862
  setRefreshToken((value) => value + 1);
2586
2863
  statusState.refresh();
2587
2864
  }, [statusState.refresh]);
2588
- const lastRun = (0, import_react14.useRef)(null);
2589
- (0, import_react14.useEffect)(() => {
2865
+ const lastRun = (0, import_react15.useRef)(null);
2866
+ (0, import_react15.useEffect)(() => {
2590
2867
  const run = runState.run;
2591
2868
  if (run === null || run === void 0) {
2592
2869
  lastRun.current = null;
@@ -2598,7 +2875,7 @@ function DockerPage(props) {
2598
2875
  lastRun.current = signature;
2599
2876
  refreshAll();
2600
2877
  }, [refreshAll, runState.run?.id, runState.run?.status]);
2601
- const confirmThen = (0, import_react14.useCallback)((config, execute) => {
2878
+ const confirmThen = (0, import_react15.useCallback)((config, execute) => {
2602
2879
  setConfirm({
2603
2880
  ...config,
2604
2881
  busy: false,
@@ -2615,7 +2892,7 @@ function DockerPage(props) {
2615
2892
  }
2616
2893
  });
2617
2894
  }, [notify, refreshAll]);
2618
- const startRun = (0, import_react14.useCallback)(async (input, { focusConsole = false } = {}) => {
2895
+ const startRun = (0, import_react15.useCallback)(async (input, { focusConsole = false } = {}) => {
2619
2896
  const payload = { provider, ...input };
2620
2897
  if (runs.active) {
2621
2898
  notify("info", t("commandRunning"));
@@ -2645,7 +2922,7 @@ function DockerPage(props) {
2645
2922
  return null;
2646
2923
  }
2647
2924
  }, [actions, confirmThen, notify, provider, runs, t]);
2648
- const runRuntime = (0, import_react14.useCallback)(async (action) => {
2925
+ const runRuntime = (0, import_react15.useCallback)(async (action) => {
2649
2926
  const execute = async (confirmed) => {
2650
2927
  if (runs.active) {
2651
2928
  notify("info", t("commandRunning"));
@@ -2683,7 +2960,7 @@ function DockerPage(props) {
2683
2960
  };
2684
2961
  await execute(false);
2685
2962
  }, [confirmThen, notify, provider, refreshAll, runs, selectedContext, t]);
2686
- const openInspect = (0, import_react14.useCallback)(async (kind, id) => {
2963
+ const openInspect = (0, import_react15.useCallback)(async (kind, id) => {
2687
2964
  setInspect({ open: true, loading: true, kind, id, value: null, raw: "", error: null });
2688
2965
  try {
2689
2966
  const value = await api.call("inspect", { provider, kind, id, context: selectedContext ?? void 0 });
@@ -2692,7 +2969,7 @@ function DockerPage(props) {
2692
2969
  setInspect({ open: true, loading: false, kind, id, value: null, raw: "", error });
2693
2970
  }
2694
2971
  }, [api, provider, selectedContext]);
2695
- const closeAttach = (0, import_react14.useCallback)(() => {
2972
+ const closeAttach = (0, import_react15.useCallback)(() => {
2696
2973
  attachRequest.current += 1;
2697
2974
  const session = attachRef.current;
2698
2975
  attachRef.current = null;
@@ -2700,7 +2977,7 @@ function DockerPage(props) {
2700
2977
  if (session !== null && session?.id !== void 0) api.call("attachClose", { attachId: session.id }).catch(() => {
2701
2978
  });
2702
2979
  }, [api]);
2703
- const openAttach = (0, import_react14.useCallback)(async (container, mode = "attach") => {
2980
+ const openAttach = (0, import_react15.useCallback)(async (container, mode = "attach") => {
2704
2981
  if (container?.state !== "running") {
2705
2982
  notify("info", t("attachNotRunning"));
2706
2983
  return;
@@ -2735,7 +3012,7 @@ function DockerPage(props) {
2735
3012
  setAttach({ open: true, loading: false, mode, session: null, output: "", error });
2736
3013
  }
2737
3014
  }, [api, notify, provider, selectedContext, t]);
2738
- const attachInput = (0, import_react14.useCallback)(async (data) => {
3015
+ const attachInput = (0, import_react15.useCallback)(async (data) => {
2739
3016
  const session = attachRef.current;
2740
3017
  if (session === null || session.status !== "running") return;
2741
3018
  try {
@@ -2744,7 +3021,7 @@ function DockerPage(props) {
2744
3021
  setAttach((current) => ({ ...current, error }));
2745
3022
  }
2746
3023
  }, [api]);
2747
- (0, import_react14.useEffect)(() => {
3024
+ (0, import_react15.useEffect)(() => {
2748
3025
  if (!attach.open || attach.session === null || attach.session.status !== "running") return void 0;
2749
3026
  const attachId = attach.session.id;
2750
3027
  let cancelled = false;
@@ -2778,12 +3055,12 @@ function DockerPage(props) {
2778
3055
  clearTimeout(timer);
2779
3056
  };
2780
3057
  }, [api, attach.open, attach.session?.id]);
2781
- (0, import_react14.useEffect)(() => () => {
3058
+ (0, import_react15.useEffect)(() => () => {
2782
3059
  const session = attachRef.current;
2783
3060
  if (session !== null) api.call("attachClose", { attachId: session.id }).catch(() => {
2784
3061
  });
2785
3062
  }, [api]);
2786
- const askAI = (0, import_react14.useCallback)(async (item, mode = "ask") => {
3063
+ const askAI = (0, import_react15.useCallback)(async (item, mode = "ask") => {
2787
3064
  if (!canAskAI) {
2788
3065
  notify("error", t("askAiUnavailable"));
2789
3066
  return;
@@ -2808,13 +3085,13 @@ function DockerPage(props) {
2808
3085
  notify("error", errorMessage(error));
2809
3086
  }
2810
3087
  }, [canAskAI, notify, provider, selectedContext, startDiagnosis, t]);
2811
- const openRun = (0, import_react14.useCallback)((image = "") => setRunDialog({ open: true, image }), []);
2812
- const closeRun = (0, import_react14.useCallback)(() => setRunDialog({ open: false, image: "" }), []);
2813
- const scheduleListRefresh = (0, import_react14.useCallback)(() => {
3088
+ const openRun = (0, import_react15.useCallback)((image = "") => setRunDialog({ open: true, image }), []);
3089
+ const closeRun = (0, import_react15.useCallback)(() => setRunDialog({ open: false, image: "" }), []);
3090
+ const scheduleListRefresh = (0, import_react15.useCallback)(() => {
2814
3091
  window.setTimeout(() => refreshAll(), 900);
2815
3092
  window.setTimeout(() => refreshAll(), 2600);
2816
3093
  }, [refreshAll]);
2817
- const runAction = (0, import_react14.useCallback)(async (input, { focusConsole = false } = {}) => {
3094
+ const runAction = (0, import_react15.useCallback)(async (input, { focusConsole = false } = {}) => {
2818
3095
  if (runs.active) {
2819
3096
  notify("info", t("commandRunning"));
2820
3097
  return null;
@@ -2847,7 +3124,44 @@ function DockerPage(props) {
2847
3124
  return null;
2848
3125
  }
2849
3126
  }, [actions, confirmThen, notify, provider, runs, scheduleListRefresh, t]);
2850
- const openTab = (0, import_react14.useCallback)((next) => actions.setTab(next), [actions]);
3127
+ const openPush = (0, import_react15.useCallback)((image) => setPushDialog({ open: true, image }), []);
3128
+ const closePush = (0, import_react15.useCallback)(() => setPushDialog({ open: false, image: "" }), []);
3129
+ const openBuild = (0, import_react15.useCallback)(() => setBuildDialog(true), []);
3130
+ const closeBuild = (0, import_react15.useCallback)(() => setBuildDialog(false), []);
3131
+ const startImageJob = (0, import_react15.useCallback)(async ({ name, ...input }) => {
3132
+ if (runs.active) throw new Error(t("imgJobBusy"));
3133
+ const run = await runs.startAction({ provider, context: provider === "docker" ? selectedContext : void 0, ...input });
3134
+ if (run !== null) {
3135
+ watchedJob.current = { id: run.id, action: input.action, name: name ?? input.id ?? input.tag };
3136
+ actions.setTab("console");
3137
+ scheduleListRefresh();
3138
+ }
3139
+ return run;
3140
+ }, [actions, provider, runs, scheduleListRefresh, selectedContext, t]);
3141
+ const pullImage = (0, import_react15.useCallback)(async (reference, platform) => {
3142
+ try {
3143
+ await startImageJob({ kind: "image", action: "pull", id: reference, platform, name: platform === void 0 ? reference : `${reference} (${platform})` });
3144
+ } catch (error) {
3145
+ notify("error", errorMessage(error));
3146
+ }
3147
+ }, [notify, startImageJob]);
3148
+ (0, import_react15.useEffect)(() => {
3149
+ const watched = watchedJob.current;
3150
+ const run = runState.run;
3151
+ if (watched === null || run === null || run === void 0 || run.id !== watched.id) return;
3152
+ if (run.status === "running" || run.status === "cancelling") return;
3153
+ watchedJob.current = null;
3154
+ if (run.status === "cancelled") return;
3155
+ const key = watched.action === "push" ? "imgPush" : watched.action === "build" ? "imgBuild" : "imgPull";
3156
+ if (run.status === "exited") {
3157
+ notify("success", fill(t(`${key}Done`), { name: watched.name }));
3158
+ } else if (key === "imgPush" && /denied|unauthorized|authentication required|access forbidden/iu.test(`${runState.stderr}${runState.stdout}`)) {
3159
+ notify("error", t("imgPushAuthFailed"));
3160
+ } else {
3161
+ notify("error", t(`${key}Failed`));
3162
+ }
3163
+ }, [notify, runState.run, runState.stderr, runState.stdout, t]);
3164
+ const openTab = (0, import_react15.useCallback)((next) => actions.setTab(next), [actions]);
2851
3165
  const tabProps = {
2852
3166
  t,
2853
3167
  api,
@@ -2861,6 +3175,9 @@ function DockerPage(props) {
2861
3175
  onAction: runAction,
2862
3176
  onAttach: openAttach,
2863
3177
  onRunContainer: openRun,
3178
+ onPullImage: pullImage,
3179
+ onPushImage: openPush,
3180
+ onBuildImage: openBuild,
2864
3181
  onAskAI: askAI,
2865
3182
  canAskAI,
2866
3183
  onRuntime: runRuntime,
@@ -2885,21 +3202,21 @@ function DockerPage(props) {
2885
3202
  networks: void 0,
2886
3203
  compose: void 0
2887
3204
  };
2888
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LocaleContext.Provider, { value: t, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-page", "data-dsh-docker-page": "true", "data-docker-provider": provider, "data-docker-daemon": status?.daemon?.state ?? "unknown", children: [
2889
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("header", { className: "dsh-docker-header", children: [
2890
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-brand", children: [
2891
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-mark", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DockerMark, { size: 23 }) }),
2892
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-heading", children: [
2893
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { className: "dsh-docker-title", children: t("title") }),
2894
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "dsh-docker-subtitle", children: t("subtitle") })
3205
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LocaleContext.Provider, { value: t, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-page", "data-dsh-docker-page": "true", "data-docker-provider": provider, "data-docker-daemon": status?.daemon?.state ?? "unknown", children: [
3206
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { className: "dsh-docker-header", children: [
3207
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-brand", children: [
3208
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-mark", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DockerMark, { size: 23 }) }),
3209
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-heading", children: [
3210
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h1", { className: "dsh-docker-title", children: t("title") }),
3211
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "dsh-docker-subtitle", children: t("subtitle") })
2895
3212
  ] })
2896
3213
  ] }),
2897
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-header-actions", children: [
2898
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "dsh-docker-status", "data-state": startingAt === null ? pill.state : "starting", title: status?.runtime?.label, children: [
2899
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-dot" }),
3214
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-header-actions", children: [
3215
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "dsh-docker-status", "data-state": startingAt === null ? pill.state : "starting", title: status?.runtime?.label, children: [
3216
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-dot" }),
2900
3217
  startingAt === null ? pill.label : runtimeBusy === "stop" ? t("stopping") : t("statusStarting")
2901
3218
  ] }),
2902
- providerOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-seg dsh-docker-provider-switch", role: "group", "aria-label": t("providerLabel"), children: providerOptions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3219
+ providerOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-seg dsh-docker-provider-switch", role: "group", "aria-label": t("providerLabel"), children: providerOptions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2903
3220
  "button",
2904
3221
  {
2905
3222
  type: "button",
@@ -2919,7 +3236,7 @@ function DockerPage(props) {
2919
3236
  },
2920
3237
  item.id
2921
3238
  )) }),
2922
- contexts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3239
+ contexts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2923
3240
  "select",
2924
3241
  {
2925
3242
  className: "dsh-docker-select",
@@ -2927,16 +3244,16 @@ function DockerPage(props) {
2927
3244
  onChange: (event) => actions.setContext(event.target.value === "" ? null : event.target.value),
2928
3245
  "aria-label": t("contextLabel"),
2929
3246
  title: status?.context?.endpoint ?? "",
2930
- children: contexts.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("option", { value: item.name, children: [
3247
+ children: contexts.map((item) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("option", { value: item.name, children: [
2931
3248
  item.name,
2932
3249
  item.current ? ` \xB7 ${t("currentSuffix")}` : ""
2933
3250
  ] }, item.name))
2934
3251
  }
2935
3252
  ),
2936
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconButton, { label: t("refresh"), onClick: refreshAll, disabled: statusState.loading, children: statusState.loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Spinner, { size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconRefresh, { size: 16 }) })
3253
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconButton, { label: t("refresh"), onClick: refreshAll, disabled: statusState.loading, children: statusState.loading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Spinner, { size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconRefresh, { size: 16 }) })
2937
3254
  ] })
2938
3255
  ] }),
2939
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3256
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2940
3257
  DockerBanner,
2941
3258
  {
2942
3259
  t,
@@ -2949,7 +3266,7 @@ function DockerPage(props) {
2949
3266
  onRetry: refreshAll
2950
3267
  }
2951
3268
  ),
2952
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("nav", { className: "dsh-docker-tabs", role: "tablist", "aria-label": t("title"), children: TABS.filter(([id]) => id !== "compose" || provider === "docker").map(([id, labelKey]) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3269
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("nav", { className: "dsh-docker-tabs", role: "tablist", "aria-label": t("title"), children: TABS.filter(([id]) => id !== "compose" || provider === "docker").map(([id, labelKey]) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2953
3270
  "button",
2954
3271
  {
2955
3272
  type: "button",
@@ -2959,12 +3276,12 @@ function DockerPage(props) {
2959
3276
  onClick: () => actions.setTab(id),
2960
3277
  children: [
2961
3278
  t(labelKey),
2962
- tabCount(id, status, counts) !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-tab-count", children: tabCount(id, status, counts) })
3279
+ tabCount(id, status, counts) !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-tab-count", children: tabCount(id, status, counts) })
2963
3280
  ]
2964
3281
  },
2965
3282
  id
2966
3283
  )) }),
2967
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DockerErrorBoundary, { t, children: statusState.loading && status === null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-body", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LoadingSkeleton, { rows: 6 }) }) : statusState.error !== null && status === null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-body", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3284
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DockerErrorBoundary, { t, children: statusState.loading && status === null ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-body", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LoadingSkeleton, { rows: 6 }) }) : statusState.error !== null && status === null ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-body", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2968
3285
  ErrorState,
2969
3286
  {
2970
3287
  title: t("statusFailed"),
@@ -2973,16 +3290,16 @@ ${t("statusErrorHint")}`,
2973
3290
  retryLabel: t("retry"),
2974
3291
  onRetry: refreshAll
2975
3292
  }
2976
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: cx("dsh-docker-body", tab === "console" && "dsh-docker-body-fill"), children: [
2977
- tab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OverviewTab, { ...tabProps }),
2978
- tab === "containers" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ContainersTab, { ...tabProps }),
2979
- tab === "images" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ImagesTab, { ...tabProps }),
2980
- tab === "volumes" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VolumesTab, { ...tabProps }),
2981
- tab === "networks" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NetworksTab, { ...tabProps }),
2982
- tab === "compose" && provider === "docker" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ComposeTab, { ...tabProps }),
2983
- tab === "console" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ConsoleTab, { ...tabProps })
3293
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cx("dsh-docker-body", tab === "console" && "dsh-docker-body-fill"), children: [
3294
+ tab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(OverviewTab, { ...tabProps }),
3295
+ tab === "containers" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContainersTab, { ...tabProps }),
3296
+ tab === "images" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ImagesTab, { ...tabProps }),
3297
+ tab === "volumes" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(VolumesTab, { ...tabProps }),
3298
+ tab === "networks" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(NetworksTab, { ...tabProps }),
3299
+ tab === "compose" && provider === "docker" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ComposeTab, { ...tabProps }),
3300
+ tab === "console" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ConsoleTab, { ...tabProps })
2984
3301
  ] }) }),
2985
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3302
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2986
3303
  Modal,
2987
3304
  {
2988
3305
  open: inspect.open,
@@ -2991,14 +3308,14 @@ ${t("statusErrorHint")}`,
2991
3308
  wide: true,
2992
3309
  onClose: () => setInspect((current) => ({ ...current, open: false })),
2993
3310
  closeLabel: t("close"),
2994
- footer: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2995
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CopyButton, { text: inspect.raw, label: t("copy"), copiedLabel: t("copied") }),
2996
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { variant: "primary", onClick: () => setInspect((current) => ({ ...current, open: false })), children: t("close") })
3311
+ footer: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3312
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CopyButton, { text: inspect.raw, label: t("copy"), copiedLabel: t("copied") }),
3313
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { variant: "primary", onClick: () => setInspect((current) => ({ ...current, open: false })), children: t("close") })
2997
3314
  ] }),
2998
- children: inspect.loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LoadingSkeleton, { rows: 5 }) : inspect.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ErrorState, { title: t("errorTitle"), text: errorMessage(inspect.error), retryLabel: t("retry") }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("pre", { className: "dsh-docker-json", children: inspect.value === null ? inspect.raw : JSON.stringify(inspect.value, null, 2) })
3315
+ children: inspect.loading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LoadingSkeleton, { rows: 5 }) : inspect.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ErrorState, { title: t("errorTitle"), text: errorMessage(inspect.error), retryLabel: t("retry") }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { className: "dsh-docker-json", children: inspect.value === null ? inspect.raw : JSON.stringify(inspect.value, null, 2) })
2999
3316
  }
3000
3317
  ),
3001
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3318
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3002
3319
  RunContainerDialog,
3003
3320
  {
3004
3321
  open: runDialog.open,
@@ -3016,7 +3333,31 @@ ${t("statusErrorHint")}`,
3016
3333
  }
3017
3334
  }
3018
3335
  ),
3019
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3336
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3337
+ PushImageDialog,
3338
+ {
3339
+ open: pushDialog.open,
3340
+ t,
3341
+ provider,
3342
+ image: pushDialog.image,
3343
+ onClose: closePush,
3344
+ onSubmit: startImageJob
3345
+ }
3346
+ ),
3347
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3348
+ BuildImageDialog,
3349
+ {
3350
+ open: buildDialog,
3351
+ t,
3352
+ api,
3353
+ provider,
3354
+ defaultDir: cwd,
3355
+ pickDirectory,
3356
+ onClose: closeBuild,
3357
+ onSubmit: startImageJob
3358
+ }
3359
+ ),
3360
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3020
3361
  AttachDialog,
3021
3362
  {
3022
3363
  open: attach.open,
@@ -3030,7 +3371,7 @@ ${t("statusErrorHint")}`,
3030
3371
  onClose: closeAttach
3031
3372
  }
3032
3373
  ),
3033
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3374
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3034
3375
  ConfirmDialog,
3035
3376
  {
3036
3377
  open: confirm !== null,
@@ -3046,7 +3387,7 @@ ${t("statusErrorHint")}`,
3046
3387
  onCancel: () => setConfirm(null)
3047
3388
  }
3048
3389
  ),
3049
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ToastStack, { toasts, onDismiss: (id) => setToasts((current) => current.filter((toast) => toast.id !== id)) })
3390
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToastStack, { toasts, onDismiss: (id) => setToasts((current) => current.filter((toast) => toast.id !== id)) })
3050
3391
  ] }) });
3051
3392
  }
3052
3393
  function DockerBanner({ t, provider, status, statusError, startingAt, runtimeBusy, onRuntime, onRetry }) {
@@ -3056,11 +3397,11 @@ function DockerBanner({ t, provider, status, statusError, startingAt, runtimeBus
3056
3397
  const daemonStopped = status.daemon?.state === "stopped" || status.daemon?.state === "unreachable";
3057
3398
  const cliMissing = status.cli?.installed === false;
3058
3399
  if (startingAt !== null) {
3059
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "info", children: [
3060
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconSpinner, { size: 15 }) }),
3061
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3062
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-title", children: runtimeBusy === "stop" ? t("stopping") : t("starting") }),
3063
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-text", children: [
3400
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "info", children: [
3401
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconSpinner, { size: 15 }) }),
3402
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3403
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-title", children: runtimeBusy === "stop" ? t("stopping") : t("starting") }),
3404
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-text", children: [
3064
3405
  runtime?.label ?? "Docker",
3065
3406
  provider === "docker" ? ` \xB7 ${status.context?.endpoint ?? ""}` : ` \xB7 ${status.runtime?.details?.status ?? ""}`
3066
3407
  ] })
@@ -3068,34 +3409,34 @@ function DockerBanner({ t, provider, status, statusError, startingAt, runtimeBus
3068
3409
  ] });
3069
3410
  }
3070
3411
  if (cliMissing) {
3071
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "error", children: [
3072
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconAlert, { size: 16 }) }),
3073
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3074
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-title", children: provider === "apple-container" ? t("appleCliMissing") : t("cliMissing") }),
3075
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-text", children: status.cli.error ?? t("cliMissingBody") })
3412
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "error", children: [
3413
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconAlert, { size: 16 }) }),
3414
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3415
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-title", children: provider === "apple-container" ? t("appleCliMissing") : t("cliMissing") }),
3416
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-text", children: status.cli.error ?? t("cliMissingBody") })
3076
3417
  ] }),
3077
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-actions", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "sm", onClick: onRetry, children: t("retry") }) })
3418
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-actions", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { size: "sm", onClick: onRetry, children: t("retry") }) })
3078
3419
  ] });
3079
3420
  }
3080
3421
  if (daemonStopped) {
3081
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "warn", children: [
3082
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconAlert, { size: 16 }) }),
3083
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3084
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-title", children: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped") }),
3085
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-text", children: status.daemon?.error ?? (provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody")) })
3422
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "warn", children: [
3423
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconAlert, { size: 16 }) }),
3424
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3425
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-title", children: provider === "apple-container" ? t("appleSystemStopped") : t("daemonStopped") }),
3426
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-text", children: status.daemon?.error ?? (provider === "apple-container" ? t("appleSystemStoppedBody") : t("daemonStoppedBody")) })
3086
3427
  ] }),
3087
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-actions", children: [
3088
- runtime?.canStart === true && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "sm", variant: "primary", onClick: () => onRuntime("start"), children: t("runtimeStart") }),
3089
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "sm", onClick: onRetry, children: t("refresh") })
3428
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-actions", children: [
3429
+ runtime?.canStart === true && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { size: "sm", variant: "primary", onClick: () => onRuntime("start"), children: t("runtimeStart") }),
3430
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { size: "sm", onClick: onRetry, children: t("refresh") })
3090
3431
  ] })
3091
3432
  ] });
3092
3433
  }
3093
3434
  if (runtime?.kind === "remote") {
3094
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "info", children: [
3095
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconInfo, { size: 16 }) }),
3096
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3097
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-title", children: t("remote") }),
3098
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-text", children: [
3435
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "info", children: [
3436
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconInfo, { size: 16 }) }),
3437
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3438
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-title", children: t("remote") }),
3439
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-text", children: [
3099
3440
  t("remoteHint"),
3100
3441
  " \xB7 ",
3101
3442
  status.context?.endpoint ?? ""
@@ -3104,20 +3445,20 @@ function DockerBanner({ t, provider, status, statusError, startingAt, runtimeBus
3104
3445
  ] });
3105
3446
  }
3106
3447
  if (statusError !== null) {
3107
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "error", children: [
3108
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconAlert, { size: 16 }) }),
3109
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3110
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-title", children: t("refreshFailed") }),
3111
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-text", children: errorMessage(statusError) })
3448
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "error", children: [
3449
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconAlert, { size: 16 }) }),
3450
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner-main", children: [
3451
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-title", children: t("refreshFailed") }),
3452
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-text", children: errorMessage(statusError) })
3112
3453
  ] }),
3113
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-actions", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "sm", onClick: onRetry, children: t("retry") }) })
3454
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-actions", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { size: "sm", onClick: onRetry, children: t("retry") }) })
3114
3455
  ] });
3115
3456
  }
3116
3457
  if (status.warnings?.length > 0) {
3117
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "info", children: [
3118
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconInfo, { size: 16 }) }),
3119
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-main", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-text", children: status.warnings.join(" \xB7 ") }) }),
3120
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-docker-banner-actions", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "dsh-docker-muted", children: [
3458
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-docker-banner", "data-tone": "info", children: [
3459
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-docker-banner-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconInfo, { size: 16 }) }),
3460
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-main", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-text", children: status.warnings.join(" \xB7 ") }) }),
3461
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-docker-banner-actions", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "dsh-docker-muted", children: [
3121
3462
  t("lastUpdated"),
3122
3463
  " ",
3123
3464
  formatTime(status.fetchedAt)
@@ -3514,7 +3855,6 @@ var CSS = `
3514
3855
  .dsh-docker-field > span { font-size: 11.5px; color: var(--dsw-alias-label-secondary, #60636c); }
3515
3856
  .dsh-docker-textarea { height: auto; min-height: 72px; padding: 8px 10px; resize: vertical; font-family: var(--dsw-font-markdown-code-font-family, ui-monospace, Menlo, monospace); line-height: 1.5; }
3516
3857
  .dsh-docker-form-error { color: var(--dsw-alias-label-error, #d33c3c); font-size: 12px; }
3517
- .dsh-docker-check { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--dsw-alias-label-secondary, #60636c); }
3518
3858
 
3519
3859
 
3520
3860
  .dsh-docker-table-wrap { overflow: auto; border-radius: 0 0 11px 11px; }
@@ -3653,6 +3993,18 @@ var CSS = `
3653
3993
  @media (prefers-reduced-motion: reduce) {
3654
3994
  .dsh-docker-spinner, .dsh-docker-skel-line, .dsh-docker-toast { animation: none; }
3655
3995
  }
3996
+ .dsh-docker-hint { font-size: 12px; line-height: 1.5; color: var(--dsw-alias-label-tertiary, #8a8d96); }
3997
+ .dsh-docker-hint-warn { color: var(--dsw-alias-label-warning, #b7791f); }
3998
+ .dsh-docker-line-ok { font-size: 12px; color: var(--dsw-alias-label-success, #2f855a); }
3999
+ .dsh-docker-line-err { font-size: 12px; color: var(--dsw-alias-label-error, #d33c3c); }
4000
+ .dsh-docker-preview { margin: 0; padding: 8px 10px; border-radius: 8px; white-space: pre-wrap; word-break: break-all; font-family: var(--dsw-font-markdown-code-font-family, ui-monospace, Menlo, monospace); font-size: 11.5px; line-height: 1.55; background: var(--dsw-alias-markdown-code-block, #f6f7f9); border: .5px solid var(--dsw-alias-border-l3, rgba(0,0,0,.08)); }
4001
+ .dsh-docker-chip-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
4002
+ .dsh-docker-advanced { border-top: .5px solid var(--dsw-alias-border-l3, rgba(0,0,0,.08)); padding-top: 10px; }
4003
+ .dsh-docker-advanced > summary { cursor: pointer; font-size: 12px; color: var(--dsw-alias-label-secondary, #60636c); user-select: none; }
4004
+ .dsh-docker-advanced[open] > summary { margin-bottom: 10px; }
4005
+ .dsh-docker-advanced-body { display: flex; flex-direction: column; gap: 12px; }
4006
+ .dsh-docker-check { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
4007
+
3656
4008
  `;
3657
4009
  function injectStyles() {
3658
4010
  if (typeof document === "undefined") return;
@@ -3665,7 +4017,7 @@ function injectStyles() {
3665
4017
  }
3666
4018
 
3667
4019
  // src/client/index.jsx
3668
- var import_jsx_runtime14 = require("react/jsx-runtime");
4020
+ var import_jsx_runtime15 = require("react/jsx-runtime");
3669
4021
  injectStyles();
3670
4022
  var inject = ["slots", "layout", "locale", "connection", "sessions"];
3671
4023
  function apply(ctx) {
@@ -3692,6 +4044,15 @@ function apply(ctx) {
3692
4044
  if (!result.ok) throw new Error(`\u53D1\u9001\u5230\u8BCA\u65AD\u4F1A\u8BDD\u5931\u8D25: ${result.error?.message ?? "unknown"}`);
3693
4045
  return sessionId;
3694
4046
  };
4047
+ const pickDirectory = async () => {
4048
+ const desktop = globalThis.__DSH_DIRECTORY_PICKER__;
4049
+ if (desktop !== void 0 && typeof desktop.pick === "function") return desktop.pick();
4050
+ const workspace = ctx.get("uiWorkspace");
4051
+ if (typeof workspace?.pickDirectory === "function") return workspace.pickDirectory();
4052
+ throw new Error("unsupported");
4053
+ };
4054
+ const canPickDirectory = () => globalThis.__DSH_DIRECTORY_PICKER__ !== void 0 && typeof globalThis.__DSH_DIRECTORY_PICKER__.pick === "function" || typeof ctx.get("uiWorkspace")?.pickDirectory === "function";
4055
+ pickDirectory.available = canPickDirectory;
3695
4056
  const handle = createDockerStore();
3696
4057
  const instance = handle.create();
3697
4058
  const store = { ...handle, create: () => instance };
@@ -3703,7 +4064,7 @@ function apply(ctx) {
3703
4064
  key: "docker",
3704
4065
  locale: NS,
3705
4066
  store,
3706
- inject: () => ({ api, runs, startDiagnosis })
4067
+ inject: () => ({ api, runs, startDiagnosis, pickDirectory })
3707
4068
  },
3708
4069
  DockerPage
3709
4070
  );
@@ -3723,7 +4084,7 @@ function apply(ctx) {
3723
4084
  );
3724
4085
  }
3725
4086
  function DockerIcon({ size = 18 }) {
3726
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DockerMark, { size });
4087
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DockerMark, { size });
3727
4088
  }
3728
4089
 
3729
4090
  return module.exports;