opencode-docker-panel 0.5.0 → 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.
- package/CHANGELOG.md +77 -70
- package/README.md +86 -87
- package/README.ru.md +76 -77
- package/dist/commands.js +5 -5
- package/dist/compose.js +18 -18
- package/dist/panel.js +74 -73
- package/dist/poll.js +17 -17
- package/package.json +79 -76
package/CHANGELOG.md
CHANGED
|
@@ -1,70 +1,77 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this plugin, by version and date. The version is the one in `package.json` at
|
|
4
|
-
that commit.
|
|
5
|
-
|
|
6
|
-
## 0.5.
|
|
7
|
-
|
|
8
|
-
- The
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- The
|
|
16
|
-
Docker is
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
`
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
## 0.
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this plugin, by version and date. The version is the one in `package.json` at
|
|
4
|
+
that commit.
|
|
5
|
+
|
|
6
|
+
## 0.5.1 - 2026-10-08
|
|
7
|
+
|
|
8
|
+
- The repository is formatted with prettier, with a config that matches the existing style: no semicolons,
|
|
9
|
+
a 120 column width, trailing commas everywhere
|
|
10
|
+
- `npm run format` writes, `npm run format:check` only reports
|
|
11
|
+
- Version is bumped because the formatting changes every module and the rebuilt `dist` differs from 0.5.0
|
|
12
|
+
|
|
13
|
+
## 0.5.0 - 2026-10-07
|
|
14
|
+
|
|
15
|
+
- The panel can start and stop Docker Desktop: `Start Docker Desktop` is a clickable line in the
|
|
16
|
+
sidebar, `Stop Docker Desktop` is the last entry of the container list and is available even with no
|
|
17
|
+
containers at all
|
|
18
|
+
- `Stop` confirms first and names the running containers it can see, because an app-level stop ends
|
|
19
|
+
every container of every project
|
|
20
|
+
- Engine state comes from a `docker desktop status` probe rather than from `docker ps`, which reports a
|
|
21
|
+
stopped engine as an unavailable socket and cannot tell it apart from a missing CLI
|
|
22
|
+
- The probe waits up to nine seconds: measured, the CLI plugin takes 3.5 to 4.5 seconds to answer when
|
|
23
|
+
Docker is stopped, and a shorter timeout turned a provable `stopped` into an unknown state with no
|
|
24
|
+
buttons at all
|
|
25
|
+
- Log polling stops while the engine is down instead of spawning a doomed `docker logs` every two
|
|
26
|
+
seconds; the window keeps its last lines and does not resume by itself
|
|
27
|
+
- Readme trimmed to install and verification, with the behaviour, the demos and the limits moved to
|
|
28
|
+
`docs/features.md` and `docs/features.ru.md`
|
|
29
|
+
- Compose project names derived from a directory are normalized the way compose normalizes them, so an
|
|
30
|
+
uppercase directory like `CarManufacturersMVC` starts as `carmanufacturersmvc` instead of being
|
|
31
|
+
rejected as an invalid project name
|
|
32
|
+
- A compose project name that compose would reject, or one that normalizes to nothing, no longer
|
|
33
|
+
offers a button at all
|
|
34
|
+
- A stopped engine is read from `docker ps` failing on a missing `dockerDesktopLinuxEngine` pipe, which
|
|
35
|
+
takes a quarter of a second instead of the four seconds `docker desktop status` needs, so the
|
|
36
|
+
`Start Docker Desktop` line shows up right away
|
|
37
|
+
|
|
38
|
+
## 0.4.8 - 2026-10-04
|
|
39
|
+
|
|
40
|
+
- The package now ships precompiled ESM: `npm run build` transpiles the sources with the same
|
|
41
|
+
Solid options OpenTUI's own transform uses, and `exports["./tui"]` points at `dist/tui.js`
|
|
42
|
+
- `react` dropped: the panel never imported it, and the host rewrites `@opentui/solid` and
|
|
43
|
+
`solid-js` to its own runtime when a package under `node_modules` ships JavaScript
|
|
44
|
+
- Peer dependencies stay optional, so npm never writes a second Solid or OpenTUI copy next to
|
|
45
|
+
the plugin
|
|
46
|
+
- `check-build` verifies the built entry imports, claims `sidebar.content`, and releases it on
|
|
47
|
+
cleanup
|
|
48
|
+
|
|
49
|
+
## 0.4.1 — 2026-10-04
|
|
50
|
+
|
|
51
|
+
- `react` added to peer dependencies, so the panel loads from npm
|
|
52
|
+
|
|
53
|
+
## 0.4.0 — 2026-10-04
|
|
54
|
+
|
|
55
|
+
- Sidebar draws running containers only, at most five, with the header opening the full list
|
|
56
|
+
- `Pin` and `Unpin` per container, stored by the host and surviving a TUI restart
|
|
57
|
+
- `Up stack` starts a compose project from the agent directory, only when the file provably declares
|
|
58
|
+
the clicked container's project
|
|
59
|
+
- An unstarted stack in the agent directory gets its own line under the rows
|
|
60
|
+
- Packaged for npm: `files` allowlist, peer dependencies, repository metadata, npm install docs
|
|
61
|
+
- Readme trimmed to what a user needs, with the working install path first
|
|
62
|
+
|
|
63
|
+
## 0.3.0 — 2026-09-30
|
|
64
|
+
|
|
65
|
+
- `Start`, `Restart`, `Stop` and `Down compose project` per container, with `Down` confirming first
|
|
66
|
+
- Log view in the same dialog, `docker logs --timestamps --tail 200`, streams merged by timestamp
|
|
67
|
+
- Terminal recording added to the readme
|
|
68
|
+
- CI running typecheck and parser checks on both Linux and Windows
|
|
69
|
+
|
|
70
|
+
## 0.2.0 — 2026-09-29
|
|
71
|
+
|
|
72
|
+
- Loads as a CLI-only plugin, no `@opencode/plugin` import at runtime
|
|
73
|
+
- A poll that reports no containers clears the panel instead of keeping stale rows
|
|
74
|
+
|
|
75
|
+
## 0.1.0 — 2026-09-29
|
|
76
|
+
|
|
77
|
+
- First version: Docker containers in the `sidebar.content` slot, polled from `docker ps`
|
package/README.md
CHANGED
|
@@ -1,87 +1,86 @@
|
|
|
1
|
-
# opencode-docker-panel
|
|
2
|
-
|
|
3
|
-
[](https://github.com/victor-ochenin/opencodeDockerPlugin/actions/workflows/ci.yml)
|
|
4
|
-
[](https://www.npmjs.com/package/opencode-docker-panel)
|
|
5
|
-
|
|
6
|
-
A Docker container panel for the OpenCode 2 TUI sidebar, with Docker Desktop control.
|
|
7
|
-
|
|
8
|
-

|
|
9
|
-
|
|
10
|
-
What it does, with demos: [docs/features.md](docs/features.md). Русская версия этого файла:
|
|
11
|
-
[README.ru.md](README.ru.md), демонстрации на русском — [docs/features.ru.md](docs/features.ru.md).
|
|
12
|
-
|
|
13
|
-
## Requirements
|
|
14
|
-
|
|
15
|
-
- OpenCode 2 runtime with plugin slots (`opencode2`)
|
|
16
|
-
- `docker` on `PATH`. Starting and stopping Docker Desktop needs its `docker desktop` CLI plugin
|
|
17
|
-
and works on Windows only
|
|
18
|
-
|
|
19
|
-
## Install
|
|
20
|
-
|
|
21
|
-
### Option A: let an LLM do it
|
|
22
|
-
|
|
23
|
-
Paste this into any agent (Claude Code, OpenCode, Cursor, and so on):
|
|
24
|
-
|
|
25
|
-
```text
|
|
26
|
-
Install the opencode-docker-panel Docker sidebar plugin by following
|
|
27
|
-
https://github.com/victor-ochenin/opencodeDockerPlugin#installation
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Option B: manual setup
|
|
31
|
-
|
|
32
|
-
Add the plugin to `~/.config/opencode/cli.json`. Create the file if it does not exist and keep
|
|
33
|
-
whatever is already in it.
|
|
34
|
-
|
|
35
|
-
```jsonc
|
|
36
|
-
{
|
|
37
|
-
"$schema": "https://opencode.ai/v2/cli.json",
|
|
38
|
-
"plugins": [{ "package": "opencode-docker-panel", "options": { "intervalMs": 3000 } }]
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Two things trip people up here, so they are worth stating plainly:
|
|
43
|
-
|
|
44
|
-
- **It goes in `cli.json`, not `opencode.json`.** This is a terminal-only plugin: it draws in the
|
|
45
|
-
sidebar, and `cli.json` is the file the terminal client reads.
|
|
46
|
-
- **There is no login step and no provider to configure.** It talks to the local `docker` CLI and
|
|
47
|
-
nothing else.
|
|
48
|
-
|
|
49
|
-
Restart the TUI afterwards. The host installs the package on the next start; nothing to copy and
|
|
50
|
-
nothing to build.
|
|
51
|
-
|
|
52
|
-
Pin a version when you want a known state: `{ "package": "opencode-docker-panel@0.5.0" }`.
|
|
53
|
-
|
|
54
|
-
### Verification
|
|
55
|
-
|
|
56
|
-
There is no CLI check for this one: the plugin draws in the terminal UI, so `opencode run` will
|
|
57
|
-
never show it. Verify in the TUI.
|
|
58
|
-
|
|
59
|
-
1. `docker ps` returns at least one container. If it fails, the panel has nothing to draw and says
|
|
60
|
-
so.
|
|
61
|
-
2. Restart the TUI and open a session.
|
|
62
|
-
3. The sidebar gets a `Docker` header with a container count. Running containers appear as rows, at
|
|
63
|
-
most five of them, with a `N more, click for all` line under them when something is still hidden.
|
|
64
|
-
4. Click `Docker` to collapse the list, then click it again to open the full list. Pick a container
|
|
65
|
-
to get its actions menu, and the last entry there is `Stop Docker Desktop`.
|
|
66
|
-
|
|
67
|
-
Stop Docker Desktop and the sidebar gets a clickable `Start Docker Desktop` line instead of a line of text.
|
|
68
|
-
|
|
69
|
-
If the header never appears, the plugin did not load: check that the entry is in `cli.json` under
|
|
70
|
-
`plugins`, and check `~/.local/share/opencode/log/opencode.log` for a load error.
|
|
71
|
-
|
|
72
|
-
## Options
|
|
73
|
-
|
|
74
|
-
| Option
|
|
75
|
-
|
|
76
|
-
| `intervalMs` | `3000`
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
MIT
|
|
1
|
+
# opencode-docker-panel
|
|
2
|
+
|
|
3
|
+
[](https://github.com/victor-ochenin/opencodeDockerPlugin/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/opencode-docker-panel)
|
|
5
|
+
|
|
6
|
+
A Docker container panel for the OpenCode 2 TUI sidebar, with Docker Desktop control.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
What it does, with demos: [docs/features.md](docs/features.md). Русская версия этого файла:
|
|
11
|
+
[README.ru.md](README.ru.md), демонстрации на русском — [docs/features.ru.md](docs/features.ru.md).
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- OpenCode 2 runtime with plugin slots (`opencode2`)
|
|
16
|
+
- `docker` on `PATH`. Starting and stopping Docker Desktop needs its `docker desktop` CLI plugin
|
|
17
|
+
and works on Windows only
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
### Option A: let an LLM do it
|
|
22
|
+
|
|
23
|
+
Paste this into any agent (Claude Code, OpenCode, Cursor, and so on):
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
Install the opencode-docker-panel Docker sidebar plugin by following
|
|
27
|
+
https://github.com/victor-ochenin/opencodeDockerPlugin#installation
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Option B: manual setup
|
|
31
|
+
|
|
32
|
+
Add the plugin to `~/.config/opencode/cli.json`. Create the file if it does not exist and keep
|
|
33
|
+
whatever is already in it.
|
|
34
|
+
|
|
35
|
+
```jsonc
|
|
36
|
+
{
|
|
37
|
+
"$schema": "https://opencode.ai/v2/cli.json",
|
|
38
|
+
"plugins": [{ "package": "opencode-docker-panel", "options": { "intervalMs": 3000 } }],
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Two things trip people up here, so they are worth stating plainly:
|
|
43
|
+
|
|
44
|
+
- **It goes in `cli.json`, not `opencode.json`.** This is a terminal-only plugin: it draws in the
|
|
45
|
+
sidebar, and `cli.json` is the file the terminal client reads.
|
|
46
|
+
- **There is no login step and no provider to configure.** It talks to the local `docker` CLI and
|
|
47
|
+
nothing else.
|
|
48
|
+
|
|
49
|
+
Restart the TUI afterwards. The host installs the package on the next start; nothing to copy and
|
|
50
|
+
nothing to build.
|
|
51
|
+
|
|
52
|
+
Pin a version when you want a known state: `{ "package": "opencode-docker-panel@0.5.0" }`.
|
|
53
|
+
|
|
54
|
+
### Verification
|
|
55
|
+
|
|
56
|
+
There is no CLI check for this one: the plugin draws in the terminal UI, so `opencode run` will
|
|
57
|
+
never show it. Verify in the TUI.
|
|
58
|
+
|
|
59
|
+
1. `docker ps` returns at least one container. If it fails, the panel has nothing to draw and says
|
|
60
|
+
so.
|
|
61
|
+
2. Restart the TUI and open a session.
|
|
62
|
+
3. The sidebar gets a `Docker` header with a container count. Running containers appear as rows, at
|
|
63
|
+
most five of them, with a `N more, click for all` line under them when something is still hidden.
|
|
64
|
+
4. Click `Docker` to collapse the list, then click it again to open the full list. Pick a container
|
|
65
|
+
to get its actions menu, and the last entry there is `Stop Docker Desktop`.
|
|
66
|
+
|
|
67
|
+
Stop Docker Desktop and the sidebar gets a clickable `Start Docker Desktop` line instead of a line of text.
|
|
68
|
+
|
|
69
|
+
If the header never appears, the plugin did not load: check that the entry is in `cli.json` under
|
|
70
|
+
`plugins`, and check `~/.local/share/opencode/log/opencode.log` for a load error.
|
|
71
|
+
|
|
72
|
+
## Options
|
|
73
|
+
|
|
74
|
+
| Option | Default | Notes |
|
|
75
|
+
| ------------ | ------- | ------------------------------------- |
|
|
76
|
+
| `intervalMs` | `3000` | Poll interval, clamped to 1000..60000 |
|
|
77
|
+
|
|
78
|
+
Everything else lives in [docs/features.md](docs/features.md).
|
|
79
|
+
|
|
80
|
+
## Changelog
|
|
81
|
+
|
|
82
|
+
Versions and dates are in [CHANGELOG.md](CHANGELOG.md).
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
package/README.ru.md
CHANGED
|
@@ -1,77 +1,76 @@
|
|
|
1
|
-
# opencode-docker-panel
|
|
2
|
-
|
|
3
|
-
[](https://github.com/victor-ochenin/opencodeDockerPlugin/actions/workflows/ci.yml)
|
|
4
|
-
[](https://www.npmjs.com/package/opencode-docker-panel)
|
|
5
|
-
|
|
6
|
-
Панель контейнеров Docker для бокового сайдбара OpenCode 2, с управлением Docker Desktop.
|
|
7
|
-
|
|
8
|
-

|
|
9
|
-
|
|
10
|
-
Что она умеет, с демонстрациями: [docs/features.ru.md](docs/features.ru.md). English version of this file:
|
|
11
|
-
[README.md](README.md), demos in English — [docs/features.md](docs/features.md).
|
|
12
|
-
|
|
13
|
-
## Требования
|
|
14
|
-
|
|
15
|
-
- Рантайм OpenCode 2 со слотами плагинов (`opencode2`)
|
|
16
|
-
- `docker` в `PATH`. Запуск и остановка Docker Desktop требуют CLI-плагина `docker desktop` и работают только на Windows
|
|
17
|
-
|
|
18
|
-
## Установка
|
|
19
|
-
|
|
20
|
-
### Вариант A: пусть сделает LLM
|
|
21
|
-
|
|
22
|
-
Вставь это в любого агента (Claude Code, OpenCode, Cursor и так далее):
|
|
23
|
-
|
|
24
|
-
```text
|
|
25
|
-
Установи плагин панели Docker opencode-docker-panel по инструкции
|
|
26
|
-
https://github.com/victor-ochenin/opencodeDockerPlugin#installation
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### Вариант B: вручную
|
|
30
|
-
|
|
31
|
-
Добавь плагин в `~/.config/opencode/cli.json`. Если файла нет, создай его, и всё, что в нём уже есть, сохрани.
|
|
32
|
-
|
|
33
|
-
```jsonc
|
|
34
|
-
{
|
|
35
|
-
"$schema": "https://opencode.ai/v2/cli.json",
|
|
36
|
-
"plugins": [{ "package": "opencode-docker-panel", "options": { "intervalMs": 3000 } }]
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Два места, на которых обычно спотыкаются, поэтому скажу прямо:
|
|
41
|
-
|
|
42
|
-
- **Запись идёт в `cli.json`, а не в `opencode.json`.** Плагин только терминальный: он рисуется в сайдбаре, а `cli.json` читает терминальный клиент.
|
|
43
|
-
- **Логиниться не нужно, провайдера настраивать не нужно.** Плагин говорит только с локальным `docker` и больше ни с чем.
|
|
44
|
-
|
|
45
|
-
После этого перезапусти TUI: хост сам поставит пакет при следующем старте, копировать и собирать ничего не нужно.
|
|
46
|
-
|
|
47
|
-
Если нужна зафиксированная версия, укажи её явно: `{ "package": "opencode-docker-panel@0.5.0" }`.
|
|
48
|
-
|
|
49
|
-
### Проверка
|
|
50
|
-
|
|
51
|
-
CLI-проверки у этого плагина нет: он рисуется в терминальном интерфейсе, поэтому `opencode run` его не покажет никогда. Проверяй в TUI.
|
|
52
|
-
|
|
53
|
-
1. `docker ps` возвращает хотя бы один контейнер. Если команда падает, панели нечего рисовать, и она так и скажет.
|
|
54
|
-
2. Перезапусти TUI и открой сессию.
|
|
55
|
-
3. В сайдбаре появится заголовок `Docker` со счётчиком контейнеров. Запущенные контейнеры станут строками, не больше пяти, а под ними — строка `N more, click for all`, если что-то ещё скрыто. Если Docker остановлен, под заголовком будет кликабельная строка `Start Docker Desktop` вместо текста.
|
|
56
|
-
4. Кликни по `Docker`, чтобы свернуть список, и ещё раз, чтобы открыть полный. Выбери контейнер — откроется меню его действий, а последней позицией в том же списке будет `Stop Docker Desktop`.
|
|
57
|
-
|
|
58
|
-
Останови Docker Desktop — вместо текста в сайдбаре появится кликабельная строка `Start Docker Desktop`.
|
|
59
|
-
|
|
60
|
-
Если заголовок так и не появился, плагин не загрузился: проверь, что запись лежит в `cli.json` в секции `plugins`, и посмотри `~/.local/share/opencode/log/opencode.log` на предмет ошибки загрузки.
|
|
61
|
-
|
|
62
|
-
## Опции
|
|
63
|
-
|
|
64
|
-
| Опция
|
|
65
|
-
|
|
66
|
-
| `intervalMs` | `3000`
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
MIT
|
|
1
|
+
# opencode-docker-panel
|
|
2
|
+
|
|
3
|
+
[](https://github.com/victor-ochenin/opencodeDockerPlugin/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/opencode-docker-panel)
|
|
5
|
+
|
|
6
|
+
Панель контейнеров Docker для бокового сайдбара OpenCode 2, с управлением Docker Desktop.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
Что она умеет, с демонстрациями: [docs/features.ru.md](docs/features.ru.md). English version of this file:
|
|
11
|
+
[README.md](README.md), demos in English — [docs/features.md](docs/features.md).
|
|
12
|
+
|
|
13
|
+
## Требования
|
|
14
|
+
|
|
15
|
+
- Рантайм OpenCode 2 со слотами плагинов (`opencode2`)
|
|
16
|
+
- `docker` в `PATH`. Запуск и остановка Docker Desktop требуют CLI-плагина `docker desktop` и работают только на Windows
|
|
17
|
+
|
|
18
|
+
## Установка
|
|
19
|
+
|
|
20
|
+
### Вариант A: пусть сделает LLM
|
|
21
|
+
|
|
22
|
+
Вставь это в любого агента (Claude Code, OpenCode, Cursor и так далее):
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
Установи плагин панели Docker opencode-docker-panel по инструкции
|
|
26
|
+
https://github.com/victor-ochenin/opencodeDockerPlugin#installation
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Вариант B: вручную
|
|
30
|
+
|
|
31
|
+
Добавь плагин в `~/.config/opencode/cli.json`. Если файла нет, создай его, и всё, что в нём уже есть, сохрани.
|
|
32
|
+
|
|
33
|
+
```jsonc
|
|
34
|
+
{
|
|
35
|
+
"$schema": "https://opencode.ai/v2/cli.json",
|
|
36
|
+
"plugins": [{ "package": "opencode-docker-panel", "options": { "intervalMs": 3000 } }],
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Два места, на которых обычно спотыкаются, поэтому скажу прямо:
|
|
41
|
+
|
|
42
|
+
- **Запись идёт в `cli.json`, а не в `opencode.json`.** Плагин только терминальный: он рисуется в сайдбаре, а `cli.json` читает терминальный клиент.
|
|
43
|
+
- **Логиниться не нужно, провайдера настраивать не нужно.** Плагин говорит только с локальным `docker` и больше ни с чем.
|
|
44
|
+
|
|
45
|
+
После этого перезапусти TUI: хост сам поставит пакет при следующем старте, копировать и собирать ничего не нужно.
|
|
46
|
+
|
|
47
|
+
Если нужна зафиксированная версия, укажи её явно: `{ "package": "opencode-docker-panel@0.5.0" }`.
|
|
48
|
+
|
|
49
|
+
### Проверка
|
|
50
|
+
|
|
51
|
+
CLI-проверки у этого плагина нет: он рисуется в терминальном интерфейсе, поэтому `opencode run` его не покажет никогда. Проверяй в TUI.
|
|
52
|
+
|
|
53
|
+
1. `docker ps` возвращает хотя бы один контейнер. Если команда падает, панели нечего рисовать, и она так и скажет.
|
|
54
|
+
2. Перезапусти TUI и открой сессию.
|
|
55
|
+
3. В сайдбаре появится заголовок `Docker` со счётчиком контейнеров. Запущенные контейнеры станут строками, не больше пяти, а под ними — строка `N more, click for all`, если что-то ещё скрыто. Если Docker остановлен, под заголовком будет кликабельная строка `Start Docker Desktop` вместо текста.
|
|
56
|
+
4. Кликни по `Docker`, чтобы свернуть список, и ещё раз, чтобы открыть полный. Выбери контейнер — откроется меню его действий, а последней позицией в том же списке будет `Stop Docker Desktop`.
|
|
57
|
+
|
|
58
|
+
Останови Docker Desktop — вместо текста в сайдбаре появится кликабельная строка `Start Docker Desktop`.
|
|
59
|
+
|
|
60
|
+
Если заголовок так и не появился, плагин не загрузился: проверь, что запись лежит в `cli.json` в секции `plugins`, и посмотри `~/.local/share/opencode/log/opencode.log` на предмет ошибки загрузки.
|
|
61
|
+
|
|
62
|
+
## Опции
|
|
63
|
+
|
|
64
|
+
| Опция | По умолчанию | Примечания |
|
|
65
|
+
| ------------ | ------------ | ------------------------------------------------------ |
|
|
66
|
+
| `intervalMs` | `3000` | Интервал опроса, ограничивается диапазоном 1000..60000 |
|
|
67
|
+
|
|
68
|
+
Всё остальное — в [docs/features.ru.md](docs/features.ru.md).
|
|
69
|
+
|
|
70
|
+
## Изменения
|
|
71
|
+
|
|
72
|
+
Версии и даты в [CHANGELOG.md](CHANGELOG.md).
|
|
73
|
+
|
|
74
|
+
## Лицензия
|
|
75
|
+
|
|
76
|
+
MIT
|
package/dist/commands.js
CHANGED
|
@@ -48,11 +48,11 @@ function firstLine(text) {
|
|
|
48
48
|
if (!line) return "";
|
|
49
49
|
return line.length > 80 ? `${line.slice(0, 77)}...` : line;
|
|
50
50
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Runs an already-built argument list.
|
|
53
|
-
*
|
|
54
|
-
* `up` has no container behind it, so the boundary takes the argv rather than a container the caller
|
|
55
|
-
* would have to invent to satisfy the type.
|
|
51
|
+
/**
|
|
52
|
+
* Runs an already-built argument list.
|
|
53
|
+
*
|
|
54
|
+
* `up` has no container behind it, so the boundary takes the argv rather than a container the caller
|
|
55
|
+
* would have to invent to satisfy the type.
|
|
56
56
|
*/
|
|
57
57
|
export function runDockerArgs(args) {
|
|
58
58
|
return new Promise(resolve => {
|
package/dist/compose.js
CHANGED
|
@@ -4,14 +4,14 @@ import { basename, dirname, join } from "node:path";
|
|
|
4
4
|
/** compose v2's own search order, so the resolver sees the file the CLI would pick */
|
|
5
5
|
const CANDIDATES = ["compose.yaml", "compose.yml", "docker-compose.yaml", "docker-compose.yml"];
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Compose derives a project name from the directory by lowercasing it, dropping everything outside
|
|
9
|
-
* `[a-z0-9_-]` and then dropping whatever is left before the first alphanumeric. Measured against
|
|
10
|
-
* compose v2: `My.Stack 2` becomes `mystack2`, `A+B` becomes `ab`, `--Lead` becomes `lead`,
|
|
11
|
-
* `Ünïcode` becomes `ncode`, and a directory named `---` fails with "project name must not be empty".
|
|
12
|
-
*
|
|
13
|
-
* The panel passes the name explicitly as `-p`, which replaces that derivation, so the same
|
|
14
|
-
* normalization has to happen here or compose rejects what it would have accepted on its own.
|
|
7
|
+
/**
|
|
8
|
+
* Compose derives a project name from the directory by lowercasing it, dropping everything outside
|
|
9
|
+
* `[a-z0-9_-]` and then dropping whatever is left before the first alphanumeric. Measured against
|
|
10
|
+
* compose v2: `My.Stack 2` becomes `mystack2`, `A+B` becomes `ab`, `--Lead` becomes `lead`,
|
|
11
|
+
* `Ünïcode` becomes `ncode`, and a directory named `---` fails with "project name must not be empty".
|
|
12
|
+
*
|
|
13
|
+
* The panel passes the name explicitly as `-p`, which replaces that derivation, so the same
|
|
14
|
+
* normalization has to happen here or compose rejects what it would have accepted on its own.
|
|
15
15
|
*/
|
|
16
16
|
export function normalizeProject(name) {
|
|
17
17
|
return name.toLowerCase().replace(/[^a-z0-9_-]/g, "").replace(/^[^a-z0-9]+/, "");
|
|
@@ -25,10 +25,10 @@ function declaredProject(body) {
|
|
|
25
25
|
return match?.[1]?.replace(/^["']|["']$/g, "") ?? "";
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Finds the agent directory's compose file and reports the project it declares, if any.
|
|
30
|
-
*
|
|
31
|
-
* Read on every call because the caller opens a menu, not the poll loop.
|
|
28
|
+
/**
|
|
29
|
+
* Finds the agent directory's compose file and reports the project it declares, if any.
|
|
30
|
+
*
|
|
31
|
+
* Read on every call because the caller opens a menu, not the poll loop.
|
|
32
32
|
*/
|
|
33
33
|
export function findComposeFile(agentDir) {
|
|
34
34
|
if (!agentDir) return null;
|
|
@@ -56,12 +56,12 @@ export function findComposeFile(agentDir) {
|
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
/**
|
|
60
|
-
* The compose target for a container already part of the project, or null when the agent directory's
|
|
61
|
-
* file belongs to somebody else.
|
|
62
|
-
*
|
|
63
|
-
* `up` runs build and command lines from that file, so an uncertain match has to hide the button
|
|
64
|
-
* rather than point it at the wrong stack.
|
|
59
|
+
/**
|
|
60
|
+
* The compose target for a container already part of the project, or null when the agent directory's
|
|
61
|
+
* file belongs to somebody else.
|
|
62
|
+
*
|
|
63
|
+
* `up` runs build and command lines from that file, so an uncertain match has to hide the button
|
|
64
|
+
* rather than point it at the wrong stack.
|
|
65
65
|
*/
|
|
66
66
|
export function resolveComposeTarget(agentDir, project) {
|
|
67
67
|
const target = findComposeFile(agentDir);
|
package/dist/panel.js
CHANGED
|
@@ -275,12 +275,12 @@ export function DockerPanel(props) {
|
|
|
275
275
|
});
|
|
276
276
|
await polling.refreshAfterAction();
|
|
277
277
|
};
|
|
278
|
-
/**
|
|
279
|
-
* Opens the same actions for a container the sidebar does not show, and carries the one engine
|
|
280
|
-
* action last.
|
|
281
|
-
*
|
|
282
|
-
* The engine entry stays available with no containers at all, because that is exactly when Docker is
|
|
283
|
-
* down and it is the only way to turn it back on.
|
|
278
|
+
/**
|
|
279
|
+
* Opens the same actions for a container the sidebar does not show, and carries the one engine
|
|
280
|
+
* action last.
|
|
281
|
+
*
|
|
282
|
+
* The engine entry stays available with no containers at all, because that is exactly when Docker is
|
|
283
|
+
* down and it is the only way to turn it back on.
|
|
284
284
|
*/
|
|
285
285
|
const pickContainer = async all => {
|
|
286
286
|
const action = engine.state() === "running" ? "engine-stop" : undefined;
|
|
@@ -325,11 +325,11 @@ export function DockerPanel(props) {
|
|
|
325
325
|
await pickContainer(polling.state().containers);
|
|
326
326
|
};
|
|
327
327
|
|
|
328
|
-
/**
|
|
329
|
-
* Both engine actions ask first, and Stop names what it is about to end.
|
|
330
|
-
*
|
|
331
|
-
* Start confirms too: it brings up a virtual machine and starts consuming memory, so a misclick is
|
|
332
|
-
* not free even though nothing is running that it would interrupt.
|
|
328
|
+
/**
|
|
329
|
+
* Both engine actions ask first, and Stop names what it is about to end.
|
|
330
|
+
*
|
|
331
|
+
* Start confirms too: it brings up a virtual machine and starts consuming memory, so a misclick is
|
|
332
|
+
* not free even though nothing is running that it would interrupt.
|
|
333
333
|
*/
|
|
334
334
|
const runRuntime = async action => {
|
|
335
335
|
if (busy()) return;
|
|
@@ -536,8 +536,9 @@ export function DockerPanel(props) {
|
|
|
536
536
|
return _$memo(() => !!(!stopping() && !hasRows()))() && polling.state().containers.length > 0;
|
|
537
537
|
},
|
|
538
538
|
get children() {
|
|
539
|
-
var _el$30 = _$createElement("text")
|
|
540
|
-
|
|
539
|
+
var _el$30 = _$createElement("text"),
|
|
540
|
+
_el$31 = _$createTextNode(` click for the list`);
|
|
541
|
+
_$insertNode(_el$30, _el$31);
|
|
541
542
|
_$setProp(_el$30, "onMouseUp", event => arm(openBrowse, event));
|
|
542
543
|
_$effect(_$p => _$setProp(_el$30, "fg", theme().text.muted, _$p));
|
|
543
544
|
return _el$30;
|
|
@@ -548,27 +549,27 @@ export function DockerPanel(props) {
|
|
|
548
549
|
return _$memo(() => !!engineDown())() && !busy();
|
|
549
550
|
},
|
|
550
551
|
get children() {
|
|
551
|
-
var _el$
|
|
552
|
-
_el$
|
|
553
|
-
_el$
|
|
554
|
-
_$insertNode(_el$
|
|
555
|
-
_$insertNode(_el$
|
|
556
|
-
_$setProp(_el$
|
|
557
|
-
_$insertNode(_el$
|
|
558
|
-
_$insertNode(_el$
|
|
552
|
+
var _el$33 = _$createElement("text"),
|
|
553
|
+
_el$34 = _$createElement("b"),
|
|
554
|
+
_el$36 = _$createElement("span");
|
|
555
|
+
_$insertNode(_el$33, _el$34);
|
|
556
|
+
_$insertNode(_el$33, _el$36);
|
|
557
|
+
_$setProp(_el$33, "onMouseUp", event => arm(() => void runRuntime("engine-start"), event));
|
|
558
|
+
_$insertNode(_el$34, _$createTextNode(`Start Docker Desktop`));
|
|
559
|
+
_$insertNode(_el$36, _$createTextNode(` · click to start`));
|
|
559
560
|
_$effect(_p$ => {
|
|
560
561
|
var _v$6 = theme().text.base,
|
|
561
562
|
_v$7 = {
|
|
562
563
|
fg: theme().text.muted
|
|
563
564
|
};
|
|
564
|
-
_v$6 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
565
|
-
_v$7 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
565
|
+
_v$6 !== _p$.e && (_p$.e = _$setProp(_el$33, "fg", _v$6, _p$.e));
|
|
566
|
+
_v$7 !== _p$.t && (_p$.t = _$setProp(_el$36, "style", _v$7, _p$.t));
|
|
566
567
|
return _p$;
|
|
567
568
|
}, {
|
|
568
569
|
e: undefined,
|
|
569
570
|
t: undefined
|
|
570
571
|
});
|
|
571
|
-
return _el$
|
|
572
|
+
return _el$33;
|
|
572
573
|
}
|
|
573
574
|
}), null);
|
|
574
575
|
_$insert(_el$18, _$createComponent(Show, {
|
|
@@ -576,12 +577,12 @@ export function DockerPanel(props) {
|
|
|
576
577
|
return _$memo(() => !!(!engineDown() && polling.state().containers.length === 0))() && polling.state().detail.length > 0;
|
|
577
578
|
},
|
|
578
579
|
get children() {
|
|
579
|
-
var _el$
|
|
580
|
-
_el$
|
|
581
|
-
_$insertNode(_el$
|
|
582
|
-
_$insert(_el$
|
|
583
|
-
_$effect(_$p => _$setProp(_el$
|
|
584
|
-
return _el$
|
|
580
|
+
var _el$38 = _$createElement("text"),
|
|
581
|
+
_el$39 = _$createTextNode(` `);
|
|
582
|
+
_$insertNode(_el$38, _el$39);
|
|
583
|
+
_$insert(_el$38, () => polling.state().detail, null);
|
|
584
|
+
_$effect(_$p => _$setProp(_el$38, "fg", theme().text.muted, _$p));
|
|
585
|
+
return _el$38;
|
|
585
586
|
}
|
|
586
587
|
}), null);
|
|
587
588
|
_$insert(_el$18, _$createComponent(Show, {
|
|
@@ -594,52 +595,52 @@ export function DockerPanel(props) {
|
|
|
594
595
|
return visible();
|
|
595
596
|
},
|
|
596
597
|
children: container => (() => {
|
|
597
|
-
var _el$
|
|
598
|
-
_el$
|
|
599
|
-
_el$
|
|
600
|
-
_el$
|
|
601
|
-
_el$
|
|
602
|
-
_$insertNode(_el$
|
|
603
|
-
_$insertNode(_el$
|
|
604
|
-
_$setProp(_el$
|
|
605
|
-
_$setProp(_el$
|
|
606
|
-
_$setProp(_el$
|
|
607
|
-
_$insertNode(_el$
|
|
608
|
-
_$setProp(_el$
|
|
609
|
-
_$insertNode(_el$
|
|
610
|
-
_$insertNode(_el$
|
|
611
|
-
_$setProp(_el$
|
|
612
|
-
_$insert(_el$
|
|
613
|
-
_$insert(_el$
|
|
598
|
+
var _el$48 = _$createElement("box"),
|
|
599
|
+
_el$49 = _$createElement("text"),
|
|
600
|
+
_el$51 = _$createElement("text"),
|
|
601
|
+
_el$52 = _$createTextNode(` `),
|
|
602
|
+
_el$53 = _$createElement("span");
|
|
603
|
+
_$insertNode(_el$48, _el$49);
|
|
604
|
+
_$insertNode(_el$48, _el$51);
|
|
605
|
+
_$setProp(_el$48, "flexDirection", "row");
|
|
606
|
+
_$setProp(_el$48, "gap", 1);
|
|
607
|
+
_$setProp(_el$48, "onMouseUp", event => arm(() => openMenu(container()), event));
|
|
608
|
+
_$insertNode(_el$49, _$createTextNode(`•`));
|
|
609
|
+
_$setProp(_el$49, "flexShrink", 0);
|
|
610
|
+
_$insertNode(_el$51, _el$52);
|
|
611
|
+
_$insertNode(_el$51, _el$53);
|
|
612
|
+
_$setProp(_el$51, "wrapMode", "word");
|
|
613
|
+
_$insert(_el$51, () => container().name, _el$52);
|
|
614
|
+
_$insert(_el$53, () => detailLabel(container(), props.pinned));
|
|
614
615
|
_$effect(_p$ => {
|
|
615
616
|
var _v$0 = dotColor(theme(), container().state),
|
|
616
617
|
_v$1 = theme().text.base,
|
|
617
618
|
_v$10 = {
|
|
618
619
|
fg: theme().text.muted
|
|
619
620
|
};
|
|
620
|
-
_v$0 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
621
|
-
_v$1 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
622
|
-
_v$10 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
621
|
+
_v$0 !== _p$.e && (_p$.e = _$setProp(_el$49, "fg", _v$0, _p$.e));
|
|
622
|
+
_v$1 !== _p$.t && (_p$.t = _$setProp(_el$51, "fg", _v$1, _p$.t));
|
|
623
|
+
_v$10 !== _p$.a && (_p$.a = _$setProp(_el$53, "style", _v$10, _p$.a));
|
|
623
624
|
return _p$;
|
|
624
625
|
}, {
|
|
625
626
|
e: undefined,
|
|
626
627
|
t: undefined,
|
|
627
628
|
a: undefined
|
|
628
629
|
});
|
|
629
|
-
return _el$
|
|
630
|
+
return _el$48;
|
|
630
631
|
})()
|
|
631
632
|
}), _$createComponent(Show, {
|
|
632
633
|
get when() {
|
|
633
634
|
return hasRows();
|
|
634
635
|
},
|
|
635
636
|
get children() {
|
|
636
|
-
var _el$
|
|
637
|
-
_el$
|
|
638
|
-
_$insertNode(_el$
|
|
639
|
-
_$setProp(_el$
|
|
640
|
-
_$insert(_el$
|
|
641
|
-
_$effect(_$p => _$setProp(_el$
|
|
642
|
-
return _el$
|
|
637
|
+
var _el$40 = _$createElement("text"),
|
|
638
|
+
_el$41 = _$createTextNode(` `);
|
|
639
|
+
_$insertNode(_el$40, _el$41);
|
|
640
|
+
_$setProp(_el$40, "onMouseUp", event => arm(openBrowse, event));
|
|
641
|
+
_$insert(_el$40, browseLabel, null);
|
|
642
|
+
_$effect(_$p => _$setProp(_el$40, "fg", theme().text.muted, _$p));
|
|
643
|
+
return _el$40;
|
|
643
644
|
}
|
|
644
645
|
})];
|
|
645
646
|
}
|
|
@@ -649,31 +650,31 @@ export function DockerPanel(props) {
|
|
|
649
650
|
return _$memo(() => !!pendingStack())() && !engineDown();
|
|
650
651
|
},
|
|
651
652
|
get children() {
|
|
652
|
-
var _el$
|
|
653
|
-
_el$
|
|
654
|
-
_el$
|
|
655
|
-
_el$
|
|
656
|
-
_el$
|
|
657
|
-
_$insertNode(_el$
|
|
658
|
-
_$insertNode(_el$
|
|
659
|
-
_$setProp(_el$
|
|
660
|
-
_$insertNode(_el$
|
|
661
|
-
_$insertNode(_el$
|
|
662
|
-
_$insertNode(_el$
|
|
663
|
-
_$insert(_el$
|
|
653
|
+
var _el$42 = _$createElement("text"),
|
|
654
|
+
_el$43 = _$createElement("b"),
|
|
655
|
+
_el$45 = _$createElement("span"),
|
|
656
|
+
_el$46 = _$createTextNode(` · `),
|
|
657
|
+
_el$47 = _$createTextNode(` is not running here`);
|
|
658
|
+
_$insertNode(_el$42, _el$43);
|
|
659
|
+
_$insertNode(_el$42, _el$45);
|
|
660
|
+
_$setProp(_el$42, "onMouseUp", event => arm(() => void openStack(), event));
|
|
661
|
+
_$insertNode(_el$43, _$createTextNode(`Up stack`));
|
|
662
|
+
_$insertNode(_el$45, _el$46);
|
|
663
|
+
_$insertNode(_el$45, _el$47);
|
|
664
|
+
_$insert(_el$45, () => pendingStack()?.project, _el$47);
|
|
664
665
|
_$effect(_p$ => {
|
|
665
666
|
var _v$8 = theme().text.base,
|
|
666
667
|
_v$9 = {
|
|
667
668
|
fg: theme().text.muted
|
|
668
669
|
};
|
|
669
|
-
_v$8 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
670
|
-
_v$9 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
670
|
+
_v$8 !== _p$.e && (_p$.e = _$setProp(_el$42, "fg", _v$8, _p$.e));
|
|
671
|
+
_v$9 !== _p$.t && (_p$.t = _$setProp(_el$45, "style", _v$9, _p$.t));
|
|
671
672
|
return _p$;
|
|
672
673
|
}, {
|
|
673
674
|
e: undefined,
|
|
674
675
|
t: undefined
|
|
675
676
|
});
|
|
676
|
-
return _el$
|
|
677
|
+
return _el$42;
|
|
677
678
|
}
|
|
678
679
|
}), null);
|
|
679
680
|
_$effect(_$p => _$setProp(_el$20, "fg", theme().text.base, _$p));
|
package/dist/poll.js
CHANGED
|
@@ -10,10 +10,10 @@ const INITIAL = {
|
|
|
10
10
|
/** docker reports the old state for a moment after start or stop, so an action is polled twice */
|
|
11
11
|
const SETTLE_MS = 1200;
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* A Docker Desktop cold start boots a virtual machine, which takes a minute and answers `unknown` while
|
|
15
|
-
* it goes. Polling faster than the container loop is what makes the panel notice it came up at all,
|
|
16
|
-
* and the deadline is what stops a dead engine from holding `working` forever.
|
|
13
|
+
/**
|
|
14
|
+
* A Docker Desktop cold start boots a virtual machine, which takes a minute and answers `unknown` while
|
|
15
|
+
* it goes. Polling faster than the container loop is what makes the panel notice it came up at all,
|
|
16
|
+
* and the deadline is what stops a dead engine from holding `working` forever.
|
|
17
17
|
*/
|
|
18
18
|
export const ENGINE_TRANSITION_MS = 2000;
|
|
19
19
|
export const ENGINE_DEADLINE_MS = 120000;
|
|
@@ -27,11 +27,11 @@ export function keepContainers(previous, next) {
|
|
|
27
27
|
/** The sidebar belongs to what runs right now, not to every container that exists */
|
|
28
28
|
export const MAX_RUNNING = 5;
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* A pinned container is shown whatever its state and spends the running budget when it happens to
|
|
32
|
-
* run, so pinning everything shows everything.
|
|
33
|
-
*
|
|
34
|
-
* Stopped containers get no row, the dialog is their only door.
|
|
30
|
+
/**
|
|
31
|
+
* A pinned container is shown whatever its state and spends the running budget when it happens to
|
|
32
|
+
* run, so pinning everything shows everything.
|
|
33
|
+
*
|
|
34
|
+
* Stopped containers get no row, the dialog is their only door.
|
|
35
35
|
*/
|
|
36
36
|
export function selectRows(all, pinned) {
|
|
37
37
|
const isPinned = item => pinned.includes(item.name);
|
|
@@ -39,20 +39,20 @@ export function selectRows(all, pinned) {
|
|
|
39
39
|
const running = all.filter(item => !isPinned(item) && item.state === "running");
|
|
40
40
|
return [...fixed, ...running.slice(0, Math.max(0, MAX_RUNNING - fixed.length))];
|
|
41
41
|
}
|
|
42
|
-
/**
|
|
43
|
-
* The engine has its own probe because `docker ps` cannot report it: on a stopped engine the ps call
|
|
44
|
-
* fails to connect and says only `unavailable`, which is also what a missing CLI or a locked socket
|
|
45
|
-
* produces. `docker desktop status` is the only thing that tells those apart.
|
|
42
|
+
/**
|
|
43
|
+
* The engine has its own probe because `docker ps` cannot report it: on a stopped engine the ps call
|
|
44
|
+
* fails to connect and says only `unavailable`, which is also what a missing CLI or a locked socket
|
|
45
|
+
* produces. `docker desktop status` is the only thing that tells those apart.
|
|
46
46
|
*/
|
|
47
47
|
export function createEngineProbe() {
|
|
48
48
|
const [state, setState] = createSignal("unknown");
|
|
49
49
|
let disposed = false;
|
|
50
50
|
let probing = false;
|
|
51
51
|
|
|
52
|
-
/**
|
|
53
|
-
* A stopped engine takes over four seconds to answer, which is longer than the container poll, so a
|
|
54
|
-
* probe per poll would leave several of them waiting on the same pipe at once. One at a time is the
|
|
55
|
-
* whole guard: a call that arrives while one is in flight reads the last known state instead.
|
|
52
|
+
/**
|
|
53
|
+
* A stopped engine takes over four seconds to answer, which is longer than the container poll, so a
|
|
54
|
+
* probe per poll would leave several of them waiting on the same pipe at once. One at a time is the
|
|
55
|
+
* whole guard: a call that arrives while one is in flight reads the last known state instead.
|
|
56
56
|
*/
|
|
57
57
|
const refresh = async () => {
|
|
58
58
|
if (probing) return state();
|
package/package.json
CHANGED
|
@@ -1,76 +1,79 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "opencode-docker-panel",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Docker container panel for the OpenCode 2 TUI sidebar",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"opencode",
|
|
7
|
-
"opencode-plugin",
|
|
8
|
-
"opencode-tui",
|
|
9
|
-
"docker",
|
|
10
|
-
"docker-compose",
|
|
11
|
-
"sidebar",
|
|
12
|
-
"tui"
|
|
13
|
-
],
|
|
14
|
-
"homepage": "https://github.com/victor-ochenin/opencodeDockerPlugin#readme",
|
|
15
|
-
"bugs": {
|
|
16
|
-
"url": "https://github.com/victor-ochenin/opencodeDockerPlugin/issues"
|
|
17
|
-
},
|
|
18
|
-
"repository": {
|
|
19
|
-
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/victor-ochenin/opencodeDockerPlugin.git",
|
|
21
|
-
"directory": "."
|
|
22
|
-
},
|
|
23
|
-
"type": "module",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"exports": {
|
|
26
|
-
"./tui": "./dist/tui.js"
|
|
27
|
-
},
|
|
28
|
-
"files": [
|
|
29
|
-
"dist",
|
|
30
|
-
"README.md",
|
|
31
|
-
"CHANGELOG.md",
|
|
32
|
-
"LICENSE"
|
|
33
|
-
],
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "node --experimental-strip-types scripts/build.ts",
|
|
36
|
-
"check": "node --experimental-strip-types scripts/check-parser.ts",
|
|
37
|
-
"typecheck": "tsc --noEmit",
|
|
38
|
-
"check-build": "node --experimental-strip-types scripts/check-build.ts"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"@
|
|
44
|
-
"@
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"@
|
|
68
|
-
"@
|
|
69
|
-
"@
|
|
70
|
-
"@
|
|
71
|
-
"@
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-docker-panel",
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "Docker container panel for the OpenCode 2 TUI sidebar",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"opencode",
|
|
7
|
+
"opencode-plugin",
|
|
8
|
+
"opencode-tui",
|
|
9
|
+
"docker",
|
|
10
|
+
"docker-compose",
|
|
11
|
+
"sidebar",
|
|
12
|
+
"tui"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/victor-ochenin/opencodeDockerPlugin#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/victor-ochenin/opencodeDockerPlugin/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/victor-ochenin/opencodeDockerPlugin.git",
|
|
21
|
+
"directory": "."
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"exports": {
|
|
26
|
+
"./tui": "./dist/tui.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"CHANGELOG.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "node --experimental-strip-types scripts/build.ts",
|
|
36
|
+
"check": "node --experimental-strip-types scripts/check-parser.ts",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"check-build": "node --experimental-strip-types scripts/check-build.ts",
|
|
39
|
+
"format": "prettier --write .",
|
|
40
|
+
"format:check": "prettier --check ."
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@opencode/plugin": "^2.0.20",
|
|
44
|
+
"@opencode/theme": "^2.0.20",
|
|
45
|
+
"@opentui/core": ">=0.5.8",
|
|
46
|
+
"@opentui/solid": ">=0.5.8",
|
|
47
|
+
"solid-js": "^1.9.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"@opencode/plugin": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"@opencode/theme": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"@opentui/core": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@opentui/solid": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"solid-js": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@babel/core": "^7.28.0",
|
|
68
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
69
|
+
"@opencode/plugin": "^2.0.20",
|
|
70
|
+
"@opencode/theme": "^2.0.20",
|
|
71
|
+
"@opentui/core": "0.5.12",
|
|
72
|
+
"@opentui/solid": "0.5.12",
|
|
73
|
+
"@types/babel__core": "^7.20.5",
|
|
74
|
+
"babel-preset-solid": "^1.9.12",
|
|
75
|
+
"prettier": "^3.9.9",
|
|
76
|
+
"solid-js": "1.9.12",
|
|
77
|
+
"typescript": "^5.9.2"
|
|
78
|
+
}
|
|
79
|
+
}
|