opencode-docker-panel 0.4.8 → 0.5.1

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.
@@ -0,0 +1,67 @@
1
+ import { execFile } from "node:child_process";
2
+ const COMMAND = "docker";
3
+ /**
4
+ * Measured with Docker Desktop stopped on this machine: three runs took 3497, 4439 and 4453 ms.
5
+ * The CLI plugin spends those seconds waiting on a named pipe that is not answering, so a four second
6
+ * timeout like the `docker ps` one kills the call and turns a provable `stopped` into `unknown`,
7
+ * which hides the Start button. Nine seconds clears the measured worst case with room to spare.
8
+ */
9
+ const TIMEOUT_MS = 9000;
10
+ const MAX_BUFFER = 1024 * 1024;
11
+ /**
12
+ * `docker desktop status` has no output contract for the stopped case: it exits 1 and writes the
13
+ * reason to stderr, so the state comes from the exit code plus the wording rather than from a value.
14
+ *
15
+ * Measured on Docker Desktop CLI plugin v0.2.0, stopped: exit 1, stderr
16
+ * `Could not retrieve status. Is Docker Desktop running?`, stdout `You can start Docker Desktop by
17
+ * running 'docker desktop start'.`. The stdout half is the independent half: it asserts the engine is
18
+ * down and names the command, where the stderr half only asks a question.
19
+ * Measured with an unknown flag on the same build: exit 125, which is docker's own code for a command
20
+ * or flag it does not know, so the code alone cannot tell stopped from missing. `docker desktop engine ls`
21
+ * also exits 1 when the engine is down, but says `unable to retrieve the engine list`, so exit 1 alone
22
+ * would be wrong and the wording is what makes the state provable.
23
+ */
24
+ export function parseDesktopStatus(code, stdout, stderr) {
25
+ const text = `${stdout}\n${stderr}`.toLowerCase();
26
+ // Both wordings are real: older docker says `is not a docker command`, this build says `unknown command`
27
+ if (text.includes("is not a docker command") || text.includes("unknown command")) return "absent";
28
+ if (code === 0) return "running";
29
+ // Exit 1 alone is not enough, `docker desktop engine ls` shares it. Both wordings name the engine as
30
+ // down, so either one plus the code makes the state provable rather than inferred
31
+ if (code === 1 && (text.includes("is docker desktop running") || text.includes("you can start docker desktop"))) {
32
+ return "stopped";
33
+ }
34
+ return "unknown";
35
+ }
36
+ export const ENGINE_TIMEOUT_MS = TIMEOUT_MS;
37
+ export function runDesktopStatus(timeoutMs = TIMEOUT_MS) {
38
+ return new Promise(resolve => {
39
+ execFile(COMMAND, ["desktop", "status"], {
40
+ timeout: timeoutMs,
41
+ windowsHide: true,
42
+ maxBuffer: MAX_BUFFER
43
+ }, (error, stdout, stderr) => {
44
+ if (!error) {
45
+ resolve("running");
46
+ return;
47
+ }
48
+ const killed = error.killed === true;
49
+ if (killed) {
50
+ resolve("unknown");
51
+ return;
52
+ }
53
+ const failure = error;
54
+ const code = failure.code === "ENOENT" ? null : failure.code ?? null;
55
+ resolve(parseDesktopStatus(typeof code === "number" ? code : null, String(stdout), String(stderr)));
56
+ });
57
+ });
58
+ }
59
+
60
+ /** An app-level stop kills every container of every project, so it needs a confirmation the container actions do not */
61
+ export function buildRuntimeArgs(action) {
62
+ return ["desktop", action === "engine-start" ? "start" : "stop"];
63
+ }
64
+ export const ENGINE_ACTION_LABEL = {
65
+ "engine-start": "Start Docker Desktop",
66
+ "engine-stop": "Stop Docker Desktop"
67
+ };
package/dist/tui.js CHANGED
@@ -15,7 +15,7 @@ const plugin = {
15
15
  });
16
16
  let dispose;
17
17
 
18
- /** Durable storage is the host's own, so a pin outlives the TUI without this plugin owning any user file. */
18
+ /** Durable storage is the host's own, so a pin outlives the TUI without this plugin owning a user file */
19
19
  async function togglePin(name) {
20
20
  await setPinned(draft => {
21
21
  const index = draft.names.indexOf(name);
@@ -23,7 +23,7 @@ const plugin = {
23
23
  });
24
24
  }
25
25
 
26
- /** Drops the current claim and registers it again, which is the only way to make the host paint the slot anew. */
26
+ /** Drops the claim and registers it again, the only way to make the host paint the slot anew */
27
27
  function reload() {
28
28
  queueMicrotask(() => {
29
29
  dispose?.();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-docker-panel",
3
- "version": "0.4.8",
3
+ "version": "0.5.1",
4
4
  "description": "Docker container panel for the OpenCode 2 TUI sidebar",
5
5
  "keywords": [
6
6
  "opencode",
@@ -35,7 +35,9 @@
35
35
  "build": "node --experimental-strip-types scripts/build.ts",
36
36
  "check": "node --experimental-strip-types scripts/check-parser.ts",
37
37
  "typecheck": "tsc --noEmit",
38
- "check-build": "node --experimental-strip-types scripts/check-build.ts"
38
+ "check-build": "node --experimental-strip-types scripts/check-build.ts",
39
+ "format": "prettier --write .",
40
+ "format:check": "prettier --check ."
39
41
  },
40
42
  "peerDependencies": {
41
43
  "@opencode/plugin": "^2.0.20",
@@ -70,6 +72,7 @@
70
72
  "@opentui/solid": "0.5.12",
71
73
  "@types/babel__core": "^7.20.5",
72
74
  "babel-preset-solid": "^1.9.12",
75
+ "prettier": "^3.9.9",
73
76
  "solid-js": "1.9.12",
74
77
  "typescript": "^5.9.2"
75
78
  }