@exagone313/dsh-podman 0.2.0-rc.2
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/LICENSE +21 -0
- package/README.md +41 -0
- package/README.zh.md +41 -0
- package/cordis.patch.yml +17 -0
- package/dist/approval-reasons.d.ts +129 -0
- package/dist/approval-reasons.js +253 -0
- package/dist/approval-reasons.test.d.ts +1 -0
- package/dist/approval-reasons.test.js +115 -0
- package/dist/approval.d.ts +29 -0
- package/dist/approval.js +412 -0
- package/dist/approval.test.d.ts +1 -0
- package/dist/approval.test.js +462 -0
- package/dist/card-route.d.ts +15 -0
- package/dist/card-route.js +478 -0
- package/dist/card-route.test.d.ts +1 -0
- package/dist/card-route.test.js +181 -0
- package/dist/card-test-support.d.ts +15 -0
- package/dist/card-test-support.js +160 -0
- package/dist/client/ContainerCard.d.ts +6 -0
- package/dist/client/ContainerCard.js +79 -0
- package/dist/client/card-client.d.ts +6 -0
- package/dist/client/card-client.js +47 -0
- package/dist/client/card-protocol.d.ts +101 -0
- package/dist/client/card-protocol.js +10 -0
- package/dist/client/container-card-caches.d.ts +10 -0
- package/dist/client/container-card-caches.js +31 -0
- package/dist/client/container-card-controller.d.ts +107 -0
- package/dist/client/container-card-controller.js +207 -0
- package/dist/client/container-card-create-modal.d.ts +24 -0
- package/dist/client/container-card-create-modal.js +109 -0
- package/dist/client/container-card-directory-styles.d.ts +5 -0
- package/dist/client/container-card-directory-styles.js +246 -0
- package/dist/client/container-card-directory.d.ts +12 -0
- package/dist/client/container-card-directory.js +144 -0
- package/dist/client/container-card-editors.d.ts +30 -0
- package/dist/client/container-card-editors.js +116 -0
- package/dist/client/container-card-images.d.ts +37 -0
- package/dist/client/container-card-images.js +35 -0
- package/dist/client/container-card-paths.d.ts +20 -0
- package/dist/client/container-card-paths.js +88 -0
- package/dist/client/container-card-row.d.ts +30 -0
- package/dist/client/container-card-row.js +54 -0
- package/dist/client/container-card-secrets.d.ts +21 -0
- package/dist/client/container-card-secrets.js +71 -0
- package/dist/client/container-card-shared.d.ts +55 -0
- package/dist/client/container-card-shared.js +152 -0
- package/dist/client/container-card-styles.d.ts +21 -0
- package/dist/client/container-card-styles.js +143 -0
- package/dist/client/container-card-volumes.d.ts +12 -0
- package/dist/client/container-card-volumes.js +37 -0
- package/dist/client/container-card-workspace.d.ts +31 -0
- package/dist/client/container-card-workspace.js +24 -0
- package/dist/client/directory-picker.d.ts +12 -0
- package/dist/client/directory-picker.js +30 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js +4419 -0
- package/dist/client/locales.d.ts +9 -0
- package/dist/client/locales.js +370 -0
- package/dist/client/read-only-approval.d.ts +8 -0
- package/dist/client/read-only-approval.js +63 -0
- package/dist/client/slot-contract.d.ts +12 -0
- package/dist/client/slot-contract.js +4 -0
- package/dist/client/terminal-styles.d.ts +5 -0
- package/dist/client/terminal-styles.js +31 -0
- package/dist/client/tool-views.d.ts +8 -0
- package/dist/client/tool-views.js +241 -0
- package/dist/containers.test.d.ts +1 -0
- package/dist/containers.test.js +443 -0
- package/dist/daemons.test.d.ts +1 -0
- package/dist/daemons.test.js +153 -0
- package/dist/fs-provider.d.ts +23 -0
- package/dist/fs-provider.js +184 -0
- package/dist/fs-provider.test.d.ts +1 -0
- package/dist/fs-provider.test.js +260 -0
- package/dist/generated/version.d.ts +2 -0
- package/dist/generated/version.js +6 -0
- package/dist/grpc/proto/dshctl/v1/control.proto +133 -0
- package/dist/grpc/proto/dshguest/v1/guest.proto +79 -0
- package/dist/grpc/runtime-client.d.ts +5 -0
- package/dist/grpc/runtime-client.js +43 -0
- package/dist/guest-rpc.d.ts +62 -0
- package/dist/guest-rpc.js +391 -0
- package/dist/images.test.d.ts +1 -0
- package/dist/images.test.js +79 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +140 -0
- package/dist/misc.test.d.ts +1 -0
- package/dist/misc.test.js +141 -0
- package/dist/mount-enums.d.ts +22 -0
- package/dist/mount-enums.js +81 -0
- package/dist/mount-input.d.ts +14 -0
- package/dist/mount-input.js +64 -0
- package/dist/mounts.test.d.ts +1 -0
- package/dist/mounts.test.js +408 -0
- package/dist/output-reader.d.ts +34 -0
- package/dist/output-reader.js +87 -0
- package/dist/paths.test.d.ts +1 -0
- package/dist/paths.test.js +74 -0
- package/dist/preferences.d.ts +6 -0
- package/dist/preferences.js +27 -0
- package/dist/project-path.d.ts +6 -0
- package/dist/project-path.js +73 -0
- package/dist/project-path.test.d.ts +1 -0
- package/dist/project-path.test.js +52 -0
- package/dist/prompts.d.ts +13 -0
- package/dist/prompts.js +149 -0
- package/dist/public.d.ts +4 -0
- package/dist/public.js +63 -0
- package/dist/read-only-shell.d.ts +14 -0
- package/dist/read-only-shell.js +150 -0
- package/dist/read-only-shell.test.d.ts +1 -0
- package/dist/read-only-shell.test.js +127 -0
- package/dist/secrets.test.d.ts +1 -0
- package/dist/secrets.test.js +181 -0
- package/dist/settings-commands.test.d.ts +1 -0
- package/dist/settings-commands.test.js +549 -0
- package/dist/settings-create.test.d.ts +1 -0
- package/dist/settings-create.test.js +394 -0
- package/dist/settings-mounts.test.d.ts +1 -0
- package/dist/settings-mounts.test.js +467 -0
- package/dist/settings-paths.test.d.ts +1 -0
- package/dist/settings-paths.test.js +65 -0
- package/dist/settings-schema.d.ts +14 -0
- package/dist/settings-schema.js +14 -0
- package/dist/settings-workspaces.test.d.ts +1 -0
- package/dist/settings-workspaces.test.js +265 -0
- package/dist/spill-store.d.ts +17 -0
- package/dist/spill-store.js +54 -0
- package/dist/spill-store.test.d.ts +1 -0
- package/dist/spill-store.test.js +59 -0
- package/dist/subprocess.d.ts +9 -0
- package/dist/subprocess.js +369 -0
- package/dist/subprocess.test.d.ts +1 -0
- package/dist/subprocess.test.js +234 -0
- package/dist/test-support.d.ts +328 -0
- package/dist/test-support.js +437 -0
- package/dist/tool-defs.d.ts +26 -0
- package/dist/tool-defs.js +188 -0
- package/dist/tool-handlers.d.ts +2 -0
- package/dist/tool-handlers.js +546 -0
- package/dist/tool-params.d.ts +803 -0
- package/dist/tool-params.js +494 -0
- package/dist/tool-schemas.d.ts +2 -0
- package/dist/tool-schemas.js +5 -0
- package/dist/tool-views.d.ts +2 -0
- package/dist/tool-views.js +56 -0
- package/dist/views.test.d.ts +1 -0
- package/dist/views.test.js +23 -0
- package/dist/volumes.test.d.ts +1 -0
- package/dist/volumes.test.js +40 -0
- package/dist/workspace-binding.d.ts +40 -0
- package/dist/workspace-binding.js +275 -0
- package/dist/workspace-binding.test.d.ts +1 -0
- package/dist/workspace-binding.test.js +337 -0
- package/docs/architecture.md +173 -0
- package/docs/architecture.zh.md +129 -0
- package/docs/configuration.md +160 -0
- package/docs/configuration.zh.md +147 -0
- package/docs/development.md +142 -0
- package/docs/development.zh.md +135 -0
- package/docs/install-dsh-and-dsh-podman.md +165 -0
- package/docs/install-dsh-and-dsh-podman.zh.md +145 -0
- package/docs/usage.md +393 -0
- package/docs/usage.zh.md +315 -0
- package/package.json +119 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Development
|
|
8
|
+
|
|
9
|
+
This page is for **contributors** building the plugin from this repository.
|
|
10
|
+
|
|
11
|
+
## Repository layout
|
|
12
|
+
|
|
13
|
+
- `src/` — the Cordis plugin (host half + browser client).
|
|
14
|
+
- `cmd/dsh-podman-orchestrator/` and `cmd/dsh-podman-guest-agent/` — the two Go
|
|
15
|
+
binaries.
|
|
16
|
+
- `internal/` — Go implementation of the orchestrator, guest agent, and protobuf
|
|
17
|
+
bindings.
|
|
18
|
+
- `proto/` — the gRPC definitions.
|
|
19
|
+
- `.github/workflows/` — CI and release automation.
|
|
20
|
+
|
|
21
|
+
## Building
|
|
22
|
+
|
|
23
|
+
Prerequisites: Go 1.27, Node ≥ 22, pnpm 12, and (for the browser half) the
|
|
24
|
+
`@deepseek-ai/dsh-client-*` packages published on npm.
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pnpm install
|
|
28
|
+
pnpm run build # tsc host + tsc client -> dist/, copies proto/ -> dist/grpc/proto/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The Go build tags skip the btrfs and devicemapper storage drivers, which need
|
|
32
|
+
host C headers; `make` applies the same tags automatically.
|
|
33
|
+
|
|
34
|
+
The `Makefile` wraps the common workflows:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
make build-go # build both Go binaries into bin/<os>-<arch>/
|
|
38
|
+
make build # build-go + pnpm-build
|
|
39
|
+
make vet # go vet with the build tags
|
|
40
|
+
make test-go # go test with the build tags
|
|
41
|
+
make test # test-go + pnpm test (JS tests, which run against dist/)
|
|
42
|
+
make download-licenses # generate LICENSE.pkg from the project and third-party Go licenses
|
|
43
|
+
make image # build the orchestrator and guest-agent container images
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`make image` depends on `LICENSE.pkg`: the `download-licenses` target runs the
|
|
47
|
+
Go collector in `scripts/download-licenses`, which shells out to
|
|
48
|
+
`go-licenses save` and gathers the project's MIT license plus every third-party
|
|
49
|
+
Go license and Apache `NOTICE` into `LICENSE.pkg`. That file is gitignored
|
|
50
|
+
(never committed) and is baked into the orchestrator and guest-agent images at
|
|
51
|
+
`/usr/share/licenses/dsh-podman/LICENSE`; because workspace containers mount the
|
|
52
|
+
guest-agent image, it also rides along into every workspace container.
|
|
53
|
+
|
|
54
|
+
`pnpm test` runs `node --test dist/*.test.js`, so it requires `pnpm build` to
|
|
55
|
+
have run first (the `test` target handles this).
|
|
56
|
+
|
|
57
|
+
## Protobuf
|
|
58
|
+
|
|
59
|
+
The `.proto` sources live in `proto/`; the generated Go bindings in
|
|
60
|
+
`internal/genproto/` are committed. After changing a `.proto`, regenerate them
|
|
61
|
+
with Buf (`buf generate`), which must be installed separately (it has no `make`
|
|
62
|
+
target) — pin it with `go install github.com/bufbuild/buf/cmd/buf@v1.73.0`.
|
|
63
|
+
Commit the `.proto` change together with the regenerated Go bindings.
|
|
64
|
+
|
|
65
|
+
The JS side loads the raw `.proto` files at runtime via `@grpc/proto-loader`
|
|
66
|
+
(copied to `dist/grpc/proto/` at build time); no TypeScript bindings are
|
|
67
|
+
generated. Optionally validate the schema with `buf lint` and `buf breaking`.
|
|
68
|
+
|
|
69
|
+
## Install development builds
|
|
70
|
+
|
|
71
|
+
### Build
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
make # builds plugin and go binaries
|
|
75
|
+
make image # build images
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Recreate containers
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
systemctl --user restart dsh dsh-podman-orchestrator
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Update plugin
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm pack
|
|
88
|
+
v="$(jq -r .version package.json)"
|
|
89
|
+
podman cp ./exagone313-dsh-podman-"${v}".tgz dsh:/tmp/
|
|
90
|
+
podman exec -it dsh dsh plugin --profile web remove @exagone313/dsh-podman # necessary, to force reinstall if the same version
|
|
91
|
+
podman exec -it dsh dsh plugin --profile web add /tmp/exagone313-dsh-podman-"${v}".tgz --allow-build=protobufjs
|
|
92
|
+
systemctl --user restart dsh
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Continuous integration
|
|
96
|
+
|
|
97
|
+
CI (`.github/workflows/ci.yml`) runs on every branch push and pull request:
|
|
98
|
+
|
|
99
|
+
- **actions-lint** — zizmor scans the workflows for insecure practices.
|
|
100
|
+
- **go** — build, vet, tests, and govulncheck (Go vulnerabilities). Unfixed
|
|
101
|
+
findings don't fail the job; fixable ones do.
|
|
102
|
+
- **js** — install, typecheck, build, tests, and `pnpm audit`.
|
|
103
|
+
- **images** — builds the orchestrator and guest-agent images (runs only after
|
|
104
|
+
the test jobs pass).
|
|
105
|
+
- **trivy** — filesystem vulnerability scan (unfixed ignored) and container
|
|
106
|
+
misconfiguration scan (DS-0002 excluded via `.trivyignore.yaml`).
|
|
107
|
+
|
|
108
|
+
All third-party actions are pinned to full commit SHAs and checked by zizmor.
|
|
109
|
+
|
|
110
|
+
## Releasing
|
|
111
|
+
|
|
112
|
+
Releases are triggered by pushing a **bare semver tag** (`x.y.z`, no `v`;
|
|
113
|
+
pre-releases like `1.0.0-rc.1` also work). The release workflow
|
|
114
|
+
(`.github/workflows/release.yml`):
|
|
115
|
+
|
|
116
|
+
1. Runs the tests, then builds both binaries for `linux/amd64` and
|
|
117
|
+
`linux/arm64`.
|
|
118
|
+
2. Pushes the **orchestrator** and **guest-agent** images to GHCR
|
|
119
|
+
(`ghcr.io/exagone313/dsh-podman/{orchestrator,guest-agent}`), tagged with the
|
|
120
|
+
version plus `latest` for stable releases (pre-releases never get `latest`).
|
|
121
|
+
3. Publishes the plugin to **npm** (`@exagone313/dsh-podman`) with provenance;
|
|
122
|
+
pre-releases are published under the `next` dist-tag.
|
|
123
|
+
4. Creates a **GitHub release** with auto-generated notes and attaches the
|
|
124
|
+
binaries and the npm tarball.
|
|
125
|
+
|
|
126
|
+
The tag must match `package.json`'s version — the workflow fails otherwise — so
|
|
127
|
+
bump both with the version script:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
pnpm bump-version 0.1.1 # add --dry-run to validate only
|
|
131
|
+
git push origin master 0.1.1
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`scripts/bump-version.mjs` checks that the version is a semver release or
|
|
135
|
+
pre-release that increases the current one, writes it to `package.json`, commits
|
|
136
|
+
`chore: bump version to X`, and creates the tag; it pushes nothing, and it
|
|
137
|
+
requires the `master` branch with a clean working tree. The tag is also what the
|
|
138
|
+
built plugin and binaries report, since `scripts/generate-version.mjs` derives
|
|
139
|
+
the embedded version from `git describe --tags`. Pre-releases (`1.0.0-rc.1`) are
|
|
140
|
+
bumped the same way.
|
|
141
|
+
|
|
142
|
+
The `NPM_TOKEN` secret must be configured on the repository for the npm step.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# 开发
|
|
8
|
+
|
|
9
|
+
本页面向从本仓库构建插件的**贡献者**。
|
|
10
|
+
|
|
11
|
+
## 仓库结构
|
|
12
|
+
|
|
13
|
+
- `src/` — Cordis 插件(宿主端 + 浏览器客户端)。
|
|
14
|
+
- `cmd/dsh-podman-orchestrator/` 和 `cmd/dsh-podman-guest-agent/` — 两个 Go
|
|
15
|
+
二进制文件。
|
|
16
|
+
- `internal/` — orchestrator、guest agent 和 protobuf 绑定的 Go 实现。
|
|
17
|
+
- `proto/` — gRPC 定义。
|
|
18
|
+
- `.github/workflows/` — CI 和发布自动化。
|
|
19
|
+
|
|
20
|
+
## 构建
|
|
21
|
+
|
|
22
|
+
前置要求:Go 1.27、Node ≥ 22、pnpm 12,以及(浏览器端所需的)发布在 npm 上的
|
|
23
|
+
`@deepseek-ai/dsh-client-*` 包。
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pnpm install
|
|
27
|
+
pnpm run build # tsc host + tsc client -> dist/, copies proto/ -> dist/grpc/proto/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Go 构建标签会跳过 btrfs 和 devicemapper 存储驱动,它们需要宿主机的 C
|
|
31
|
+
头文件;`make` 会自动应用相同的标签。
|
|
32
|
+
|
|
33
|
+
`Makefile` 封装了常见的工作流:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
make build-go # build both Go binaries into bin/<os>-<arch>/
|
|
37
|
+
make build # build-go + pnpm-build
|
|
38
|
+
make vet # go vet with the build tags
|
|
39
|
+
make test-go # go test with the build tags
|
|
40
|
+
make test # test-go + pnpm test (JS tests, which run against dist/)
|
|
41
|
+
make download-licenses # generate LICENSE.pkg from the project and third-party Go licenses
|
|
42
|
+
make image # build the orchestrator and guest-agent container images
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`make image` 依赖 `LICENSE.pkg`:`download-licenses` 目标会运行
|
|
46
|
+
`scripts/download-licenses` 中的 Go 收集器,它调用 `go-licenses save` 并将项目的
|
|
47
|
+
MIT 许可证以及所有第三方 Go 许可证和 Apache `NOTICE` 汇总到 `LICENSE.pkg`
|
|
48
|
+
中。该文件被 gitignore (从不提交),并被烘焙进 orchestrator 和 guest-agent
|
|
49
|
+
镜像,位于 `/usr/share/licenses/dsh-podman/LICENSE`;由于工作区容器会挂载
|
|
50
|
+
guest-agent 镜像,因此它也会随之进入每个工作区容器。
|
|
51
|
+
|
|
52
|
+
`pnpm test` 运行 `node --test dist/*.test.js`,因此它要求先运行 `pnpm build`
|
|
53
|
+
(`test` 目标会处理这一点)。
|
|
54
|
+
|
|
55
|
+
## Protobuf
|
|
56
|
+
|
|
57
|
+
`.proto` 源文件位于 `proto/`;生成的 Go 绑定位于
|
|
58
|
+
`internal/genproto/`,会被提交。修改 `.proto` 后,需要使用单独安装的
|
|
59
|
+
Buf(`buf generate`)重新生成(没有对应的 `make` 目标)——请用
|
|
60
|
+
`go install github.com/bufbuild/buf/cmd/buf@v1.73.0` 固定版本。请将 `.proto`
|
|
61
|
+
改动与重新生成的 Go 绑定一起提交。
|
|
62
|
+
|
|
63
|
+
JS 端在运行时通过 `@grpc/proto-loader` 加载原始 `.proto` 文件(构建时复制到
|
|
64
|
+
`dist/grpc/proto/`);不生成 TypeScript 绑定。也可以使用 `buf lint` 和
|
|
65
|
+
`buf breaking` 校验 schema。
|
|
66
|
+
|
|
67
|
+
## 安装开发构建
|
|
68
|
+
|
|
69
|
+
### 构建
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
make # builds plugin and go binaries
|
|
73
|
+
make image # build images
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 重建容器
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
systemctl --user restart dsh dsh-podman-orchestrator
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 更新插件
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm pack
|
|
86
|
+
v="$(jq -r .version package.json)"
|
|
87
|
+
podman cp ./exagone313-dsh-podman-"${v}".tgz dsh:/tmp/
|
|
88
|
+
podman exec -it dsh dsh plugin --profile web remove @exagone313/dsh-podman # necessary, to force reinstall if the same version
|
|
89
|
+
podman exec -it dsh dsh plugin --profile web add /tmp/exagone313-dsh-podman-"${v}".tgz --allow-build=protobufjs
|
|
90
|
+
systemctl --user restart dsh
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 持续集成
|
|
94
|
+
|
|
95
|
+
CI(`.github/workflows/ci.yml`)在每次分支推送和拉取请求时运行:
|
|
96
|
+
|
|
97
|
+
- **actions-lint** — zizmor 扫描工作流是否存在不安全实践。
|
|
98
|
+
- **go** — 构建、vet、测试和 govulncheck(Go 漏洞)。未修复的
|
|
99
|
+
发现不会导致任务失败;可修复的会导致失败。
|
|
100
|
+
- **js** — 安装、类型检查、构建、测试和 `pnpm audit`。
|
|
101
|
+
- **images** — 构建 orchestrator 和 guest-agent 镜像(仅在测试任务通过后运行)。
|
|
102
|
+
- **trivy** — 文件系统漏洞扫描(未修复的被忽略)和容器 错误配置扫描(DS-0002
|
|
103
|
+
通过 `.trivyignore.yaml` 排除)。
|
|
104
|
+
|
|
105
|
+
所有第三方 actions 都锁定到完整的提交 SHA,并由 zizmor 检查。
|
|
106
|
+
|
|
107
|
+
## 发布
|
|
108
|
+
|
|
109
|
+
发布由推送**纯 Semver 标签**(`x.y.z`,不带 `v`; 像 `1.0.0-rc.1`
|
|
110
|
+
这样的预发布同样有效)触发。发布工作流 (`.github/workflows/release.yml`):
|
|
111
|
+
|
|
112
|
+
1. 运行测试,然后为 `linux/amd64` 和 `linux/arm64` 构建两个二进制文件。
|
|
113
|
+
2. 将 **orchestrator** 和 **guest-agent** 镜像推送到 GHCR
|
|
114
|
+
(`ghcr.io/exagone313/dsh-podman/{orchestrator,guest-agent}`),并打上
|
|
115
|
+
版本号以及稳定版的 `latest` 标签(预发布永远不会获得 `latest`)。
|
|
116
|
+
3. 将插件发布到 **npm**(`@exagone313/dsh-podman`),附带来源证明; 预发布在
|
|
117
|
+
`next` dist-tag 下发布。
|
|
118
|
+
4. 创建带有自动生成说明的 **GitHub release**,并附上 二进制文件和 npm tarball。
|
|
119
|
+
|
|
120
|
+
标签必须与 `package.json`
|
|
121
|
+
中的版本一致——否则工作流会失败——因此请用版本脚本同时更新两者:
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
pnpm bump-version 0.1.1 # 加上 --dry-run 则仅校验
|
|
125
|
+
git push origin master 0.1.1
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`scripts/bump-version.mjs` 会检查版本是否为递增的 Semver
|
|
129
|
+
正式版或预发布版,将其写入 `package.json`,提交
|
|
130
|
+
`chore: bump version to X`,并创建标签;它不会推送,且要求处于 `master`
|
|
131
|
+
分支且工作区干净。标签同时也是构建出的插件与二进制文件所报告的版本,因为
|
|
132
|
+
`scripts/generate-version.mjs` 从 `git describe --tags`
|
|
133
|
+
推导嵌入的版本。预发布版(`1.0.0-rc.1`)也用同样的方式递增。
|
|
134
|
+
|
|
135
|
+
npm 步骤要求仓库配置 `NPM_TOKEN` 密钥。
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Install DeepSeek Harness & dsh-podman with rootless Podman
|
|
8
|
+
|
|
9
|
+
## Goals
|
|
10
|
+
|
|
11
|
+
The goal of this guide is to install:
|
|
12
|
+
|
|
13
|
+
- [DeepSeek Harness](https://deepseek.com/harness), referred to later as _dsh_
|
|
14
|
+
- the dsh-podman plugin in dsh, which replaces host filesystem and shell access
|
|
15
|
+
- the dsh-podman orchestrator, a separate Podman container that integrates with
|
|
16
|
+
Podman
|
|
17
|
+
|
|
18
|
+
Having the dsh plugin and the orchestrator running as separate containers is an
|
|
19
|
+
important part of the security design of dsh-podman: dsh itself doesn't have
|
|
20
|
+
direct access to Podman, only the orchestrator does, with limitations. dsh
|
|
21
|
+
shouldn't be able to escalate privileges using this path, as the capabilities
|
|
22
|
+
provided to dsh are constrained:
|
|
23
|
+
|
|
24
|
+
- the names of pods, containers, volumes and secrets are prefixed with
|
|
25
|
+
`dsh-podman-`
|
|
26
|
+
- mounted paths are limited to bind-mounted project directories and managed
|
|
27
|
+
volumes
|
|
28
|
+
- containers are dealt with separately for each dsh workspace.
|
|
29
|
+
|
|
30
|
+
Nevertheless, it is recommended to run dsh as a dedicated user instead of your
|
|
31
|
+
main user.
|
|
32
|
+
|
|
33
|
+
Note that, for now, network access is not constrained, but support for this
|
|
34
|
+
could be added in the future.
|
|
35
|
+
|
|
36
|
+
## Terminology
|
|
37
|
+
|
|
38
|
+
- **dsh**: DeepSeek Harness, a plugin-oriented AI agent harness developed by
|
|
39
|
+
DeepSeek
|
|
40
|
+
- **dsh-podman**: this project
|
|
41
|
+
- **dsh-podman plugin**: the plugin installed in dsh, which provides tools to
|
|
42
|
+
agents and a UI for manual settings, and connects to the orchestrator;
|
|
43
|
+
referred to later as _plugin_
|
|
44
|
+
- **dsh-podman orchestrator**: the daemon that receives connections from the
|
|
45
|
+
dsh-podman plugin, has access to the Podman socket and manages containers and
|
|
46
|
+
other resources; it runs in a container; referred to later as _orchestrator_
|
|
47
|
+
- **Podman socket**: while the Podman client can be used without a daemon, it is
|
|
48
|
+
still possible to enable management through a socket, which is required by the
|
|
49
|
+
orchestrator to work as if it were running on the host system
|
|
50
|
+
- **guest container**: a container created by the dsh-podman orchestrator, in
|
|
51
|
+
relation to a dsh workspace
|
|
52
|
+
- **dsh workspace**: in dsh, a project uses the name _workspace_, with its own
|
|
53
|
+
dedicated directory
|
|
54
|
+
|
|
55
|
+
## Requirements
|
|
56
|
+
|
|
57
|
+
- A user to run dsh as (not root)
|
|
58
|
+
- A Linux distribution powered by systemd
|
|
59
|
+
- Podman 5 or later; Podman 6 is recommended
|
|
60
|
+
- A systemd session as your dsh user (**`sudo -iu` will not work**):
|
|
61
|
+
- by using machinectl (recommended; on some distributions, this command is
|
|
62
|
+
part of the `systemd-container` package; it needs to be run as root or as
|
|
63
|
+
part of the _wheel_ group):
|
|
64
|
+
```bash
|
|
65
|
+
machinectl shell --uid=your-username
|
|
66
|
+
```
|
|
67
|
+
- by connecting via SSH
|
|
68
|
+
- by connecting on a tty
|
|
69
|
+
|
|
70
|
+
## Recommendations
|
|
71
|
+
|
|
72
|
+
- If you want to start dsh at boot,
|
|
73
|
+
[enable _user lingering_ for your user](https://www.freedesktop.org/software/systemd/man/loginctl.html#enable-linger%20USER%E2%80%A6)
|
|
74
|
+
as root:
|
|
75
|
+
```bash
|
|
76
|
+
loginctl enable-linger your-username
|
|
77
|
+
```
|
|
78
|
+
- Ensure that Podman is working correctly as your dsh user (⚠️ the first command
|
|
79
|
+
may stop existing containers!):
|
|
80
|
+
```bash
|
|
81
|
+
podman system migrate
|
|
82
|
+
podman run --rm quay.io/podman/hello
|
|
83
|
+
podman rmi quay.io/podman/hello
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Preparation
|
|
87
|
+
|
|
88
|
+
- You need to choose a project directory. This directory will be mounted
|
|
89
|
+
read-only in dsh (necessary for the integrated project manager) and read-write
|
|
90
|
+
in guest containers. In this guide we will use `${HOME}/project`
|
|
91
|
+
(`%h/project`) but you are free to choose another path, as long as your user
|
|
92
|
+
has read-write access to it.
|
|
93
|
+
- Create a project inside the chosen directory. This will be useful to create a
|
|
94
|
+
workspace in dsh to validate the setup.
|
|
95
|
+
|
|
96
|
+
## Installation
|
|
97
|
+
|
|
98
|
+
### dsh setup
|
|
99
|
+
|
|
100
|
+
This installation uses
|
|
101
|
+
[Podman Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html),
|
|
102
|
+
which adds Podman integration into systemd.
|
|
103
|
+
|
|
104
|
+
1. Create the Quadlet directory for your user:
|
|
105
|
+
```bash
|
|
106
|
+
mkdir -p ~/.config/containers/systemd
|
|
107
|
+
```
|
|
108
|
+
2. Copy the files [dsh.container](../quadlet/dsh.container) and
|
|
109
|
+
[dsh-podman-orchestrator.container](../quadlet/dsh-podman-orchestrator.container)
|
|
110
|
+
to `~/.config/containers/systemd/`.
|
|
111
|
+
- Adapt the files to your desired project directory if you wish to change it.
|
|
112
|
+
3. Reload systemd session configuration:
|
|
113
|
+
```bash
|
|
114
|
+
systemctl --user daemon-reload
|
|
115
|
+
```
|
|
116
|
+
4. Check if there are errors in the configuration:
|
|
117
|
+
```bash
|
|
118
|
+
journalctl --user -e
|
|
119
|
+
```
|
|
120
|
+
5. Start dsh and dsh-podman-orchestrator:
|
|
121
|
+
```bash
|
|
122
|
+
systemctl --user start dsh dsh-podman-orchestrator
|
|
123
|
+
```
|
|
124
|
+
6. Check if there are startup errors from either container:
|
|
125
|
+
```bash
|
|
126
|
+
journalctl --user -eu dsh
|
|
127
|
+
```
|
|
128
|
+
```bash
|
|
129
|
+
journalctl --user -eu dsh-podman-orchestrator
|
|
130
|
+
```
|
|
131
|
+
7. View the dsh container logs:
|
|
132
|
+
```bash
|
|
133
|
+
podman logs dsh
|
|
134
|
+
```
|
|
135
|
+
8. Visit the given URL in the form `http://127.0.0.1:3080/?token=xxx` to access
|
|
136
|
+
dsh.
|
|
137
|
+
9. Once your web browser has saved this token, you'll be able to access dsh with
|
|
138
|
+
the URL [http://127.0.0.1:3080/](http://127.0.0.1:3080/).
|
|
139
|
+
|
|
140
|
+
### dsh-podman plugin installation
|
|
141
|
+
|
|
142
|
+
1. Run this command to install the dsh-podman plugin:
|
|
143
|
+
```bash
|
|
144
|
+
podman exec dsh dsh plugin --profile web add @exagone313/dsh-podman --allow-build=protobufjs
|
|
145
|
+
```
|
|
146
|
+
2. Restart dsh to complete the installation:
|
|
147
|
+
```bash
|
|
148
|
+
systemctl --user restart dsh
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Verification
|
|
152
|
+
|
|
153
|
+
- Open **Settings → Plugins → dsh-podman**: the card should list the base images
|
|
154
|
+
and, for a workspace, offer to create its default container.
|
|
155
|
+
- In a dsh session, run a shell command. It should execute inside a Podman
|
|
156
|
+
container for the current workspace (the plugin auto-creates the workspace's
|
|
157
|
+
default container on first use).
|
|
158
|
+
|
|
159
|
+
## Enable daily auto-updates (optional)
|
|
160
|
+
|
|
161
|
+
This requires enabling lingering for your user.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
systemctl --user enable --now podman-auto-update.timer
|
|
165
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# 使用 rootless Podman 安装 DeepSeek Harness 与 dsh-podman
|
|
8
|
+
|
|
9
|
+
## 目标
|
|
10
|
+
|
|
11
|
+
本指南的目标是安装:
|
|
12
|
+
|
|
13
|
+
- [DeepSeek Harness](https://deepseek.com/harness),下文简称 _dsh_
|
|
14
|
+
- dsh 中的 dsh-podman 插件,它取代了宿主的文件系统和 shell 访问
|
|
15
|
+
- dsh-podman 编排器,一个与 Podman 集成的独立 Podman 容器
|
|
16
|
+
|
|
17
|
+
将 dsh 插件和编排器作为独立的容器运行,是 dsh-podman 安全设计的重要一环: dsh
|
|
18
|
+
本身不能直接访问 Podman,只有编排器可以,并且受到限制。dsh
|
|
19
|
+
不应能通过这条路径提权,因为提供给 dsh 的权限能力是受限的:
|
|
20
|
+
|
|
21
|
+
- pod、容器、卷和 secret 的名称都以 `dsh-podman-` 为前缀
|
|
22
|
+
- 挂载路径仅限于绑定挂载的项目目录和受管理的卷
|
|
23
|
+
- 每个 dsh 工作区分别管理各自的容器。
|
|
24
|
+
|
|
25
|
+
尽管如此,仍建议使用专用用户运行 dsh,而不是你的主用户。
|
|
26
|
+
|
|
27
|
+
请注意,目前网络访问不受限制,但未来可能会添加对此的支持。
|
|
28
|
+
|
|
29
|
+
## 术语
|
|
30
|
+
|
|
31
|
+
- **dsh**:DeepSeek Harness,由 DeepSeek 开发的面向插件的 AI agent harness
|
|
32
|
+
- **dsh-podman**:本项目
|
|
33
|
+
- **dsh-podman 插件**:安装在 dsh 中的插件,它为 agent 提供工具、提供手动设置
|
|
34
|
+
UI,并连接编排器;下文简称 _plugin_
|
|
35
|
+
- **dsh-podman 编排器**:接收来自 dsh-podman 插件连接的守护进程,可访问 Podman
|
|
36
|
+
套接字并管理容器和其他资源;它在容器中运行;下文简称 _orchestrator_
|
|
37
|
+
- **Podman 套接字**:虽然 Podman
|
|
38
|
+
客户端可以在没有守护进程的情况下使用,但仍然可以通过套接字启用管理,这是编排器以仿佛在主机系统上运行的方式工作所必需的
|
|
39
|
+
- **guest 容器**:由 dsh-podman 编排器创建的容器,与 dsh 工作区相关联
|
|
40
|
+
- **dsh 工作区**:在 dsh 中,项目使用 _workspace_ 这一名称,并有自己的专用目录
|
|
41
|
+
|
|
42
|
+
## 要求
|
|
43
|
+
|
|
44
|
+
- 一个用于运行 dsh 的用户(不能是 root)
|
|
45
|
+
- 基于 systemd 的 Linux 发行版
|
|
46
|
+
- Podman 5 或更高版本;推荐使用 Podman 6
|
|
47
|
+
- 以你的 dsh 用户身份存在的 systemd 会话(**`sudo -iu` 无法工作**):
|
|
48
|
+
- 通过 machinectl(推荐;在某些发行版上,此命令属于 `systemd-container`
|
|
49
|
+
包;需要以 root 身份或作为 _wheel_ 组的成员运行):
|
|
50
|
+
```bash
|
|
51
|
+
machinectl shell --uid=your-username
|
|
52
|
+
```
|
|
53
|
+
- 通过 SSH 连接
|
|
54
|
+
- 通过 tty 连接
|
|
55
|
+
|
|
56
|
+
## 建议
|
|
57
|
+
|
|
58
|
+
- 如果你想在开机时启动 dsh,请以 root 身份
|
|
59
|
+
[为你的用户启用 _user lingering_(常驻)](https://www.freedesktop.org/software/systemd/man/loginctl.html#enable-linger%20USER%E2%80%A6):
|
|
60
|
+
```bash
|
|
61
|
+
loginctl enable-linger your-username
|
|
62
|
+
```
|
|
63
|
+
- 确保 Podman 在你的 dsh 用户下能正常工作(⚠️ 第一条命令可能会停止现有容器!):
|
|
64
|
+
```bash
|
|
65
|
+
podman system migrate
|
|
66
|
+
podman run --rm quay.io/podman/hello
|
|
67
|
+
podman rmi quay.io/podman/hello
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 准备工作
|
|
71
|
+
|
|
72
|
+
- 你需要选择一个项目目录。该目录在 dsh
|
|
73
|
+
中以只读方式挂载(对于内置的项目管理器是必需的),在 guest
|
|
74
|
+
容器中以读写方式挂载。在本指南中,我们将使用
|
|
75
|
+
`${HOME}/project`(`%h/project`),但你可以自由选择其他路径,只要你的用户对该路径具有读写访问权限即可。
|
|
76
|
+
- 在所选目录中创建一个项目。这将有助于在 dsh 中创建工作区以验证安装是否成功。
|
|
77
|
+
|
|
78
|
+
## 安装
|
|
79
|
+
|
|
80
|
+
### dsh 配置
|
|
81
|
+
|
|
82
|
+
本次安装使用
|
|
83
|
+
[Podman Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html),
|
|
84
|
+
它为 systemd 增加了 Podman 集成。
|
|
85
|
+
|
|
86
|
+
1. 为你的用户创建 Quadlet 目录:
|
|
87
|
+
```bash
|
|
88
|
+
mkdir -p ~/.config/containers/systemd
|
|
89
|
+
```
|
|
90
|
+
2. 将文件 [dsh.container](../quadlet/dsh.container) 和
|
|
91
|
+
[dsh-podman-orchestrator.container](../quadlet/dsh-podman-orchestrator.container)
|
|
92
|
+
复制到 `~/.config/containers/systemd/`。
|
|
93
|
+
- 如果你希望更改项目目录,可相应调整这些文件。
|
|
94
|
+
3. 重新加载 systemd 会话配置:
|
|
95
|
+
```bash
|
|
96
|
+
systemctl --user daemon-reload
|
|
97
|
+
```
|
|
98
|
+
4. 检查配置中是否有错误:
|
|
99
|
+
```bash
|
|
100
|
+
journalctl --user -e
|
|
101
|
+
```
|
|
102
|
+
5. 启动 dsh 和 dsh-podman-orchestrator:
|
|
103
|
+
```bash
|
|
104
|
+
systemctl --user start dsh dsh-podman-orchestrator
|
|
105
|
+
```
|
|
106
|
+
6. 检查任一容器是否有启动错误:
|
|
107
|
+
```bash
|
|
108
|
+
journalctl --user -eu dsh
|
|
109
|
+
```
|
|
110
|
+
```bash
|
|
111
|
+
journalctl --user -eu dsh-podman-orchestrator
|
|
112
|
+
```
|
|
113
|
+
7. 查看 dsh 容器日志:
|
|
114
|
+
```bash
|
|
115
|
+
podman logs dsh
|
|
116
|
+
```
|
|
117
|
+
8. 访问形如 `http://127.0.0.1:3080/?token=xxx` 的给定 URL 以使用 dsh。
|
|
118
|
+
9. 浏览器保存该令牌后,即可通过 [http://127.0.0.1:3080/](http://127.0.0.1:3080/)
|
|
119
|
+
访问 dsh。
|
|
120
|
+
|
|
121
|
+
### dsh-podman 插件安装
|
|
122
|
+
|
|
123
|
+
1. 运行以下命令安装 dsh-podman 插件:
|
|
124
|
+
```bash
|
|
125
|
+
podman exec dsh dsh plugin --profile web add @exagone313/dsh-podman --allow-build=protobufjs
|
|
126
|
+
```
|
|
127
|
+
2. 重启 dsh 以完成安装:
|
|
128
|
+
```bash
|
|
129
|
+
systemctl --user restart dsh
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 验证
|
|
133
|
+
|
|
134
|
+
- 打开 **Settings → Plugins →
|
|
135
|
+
dsh-podman**:卡片应列出基础镜像,并针对工作区提供创建其默认容器的选项。
|
|
136
|
+
- 在 dsh 会话中运行一条 shell 命令。它应在当前工作区的 Podman
|
|
137
|
+
容器内执行(插件会在首次使用时自动创建工作区的默认容器)。
|
|
138
|
+
|
|
139
|
+
## 启用每日自动更新(可选)
|
|
140
|
+
|
|
141
|
+
这需要为你的用户启用 lingering。
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
systemctl --user enable --now podman-auto-update.timer
|
|
145
|
+
```
|