🛟 Updated.Unverified
ddc354c parent: 11a9590 modified
.vscode/settings.json +1 -1 | @@ -1,6 +1,6 @@ | ||
| 1 | 1 | { |
| 2 | 2 | "workbench.iconTheme": "material-icon-theme", |
| 3 | - "workbench.colorTheme": "GitHub Light Colorblind (Beta)", | |
| 3 | + "workbench.colorTheme": "Light Modern", | |
| 4 | 4 | "editor.fontSize": 14, |
| 5 | 5 | "terminal.integrated.fontSize": 16, |
| 6 | 6 | "editor.insertSpaces": true, |
| @@ -1,6 +1,6 @@ | |||
| 1 | { | 1 | { |
| 2 | "workbench.iconTheme": "material-icon-theme", | 2 | "workbench.iconTheme": "material-icon-theme", |
| 3 | - "workbench.colorTheme": "GitHub Light Colorblind (Beta)", | 3 | + "workbench.colorTheme": "Light Modern", |
| 4 | "editor.fontSize": 14, | 4 | "editor.fontSize": 14, |
| 5 | "terminal.integrated.fontSize": 16, | 5 | "terminal.integrated.fontSize": 16, |
| 6 | "editor.insertSpaces": true, | 6 | "editor.insertSpaces": true, |
deleted
docker-sbx-v3/README.md +0 -154 | deleted file mode 100644 | ||
| @@ -1,154 +0,0 @@ | ||
| 1 | -# mm in a Docker Sandbox — kits v3 | |
| 2 | - | |
| 3 | -The same two kits as [`../docker-sbx`](../docker-sbx/README.md), rewritten for the [kit specification v3](https://github.com/docker/sandbox-kit-spec) (`schemaVersion: "3"`). `docker-sbx/` (v2) is left untouched and keeps working: sbx still loads `spec.yaml` kits. | |
| 4 | - | |
| 5 | -- **mm-tui** — `sbx run` opens mm's window mode (`mm -tui`) on the workspace. | |
| 6 | -- **mm-acp** — `sbx create` once, then an editor that speaks the Agent Client Protocol runs `sbx exec -i … mm -acp`. | |
| 7 | - | |
| 8 | -``` | |
| 9 | -docker-sbx-v3/ | |
| 10 | -├── publish.sh build + push the image, then build + push the kits — the one command to release | |
| 11 | -├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) | |
| 12 | -├── sync-kits.sh points the kits at one image: owner + version | |
| 13 | -├── check-kits.sh builds the kits locally (no push, no sbx) and checks them with kit-tck if present | |
| 14 | -├── push-kits.sh builds and pushes the kits with buildx: <owner>/sbx-kit-mm-tui, <owner>/sbx-kit-mm-acp | |
| 15 | -├── template/ | |
| 16 | -│ ├── Dockerfile docker/sandbox-templates:shell + mm (built from this checkout) — same image as v2 | |
| 17 | -│ ├── mm-tui entry point of the mm-tui kit: `mm -tui "$@"` | |
| 18 | -│ └── mm-acp-info entry point of the mm-acp kit: prints the editor wiring, opens a shell | |
| 19 | -└── kits/ | |
| 20 | - ├── mm-tui/ | |
| 21 | - │ ├── mm-tui.yaml the descriptor: kind: workload, args, capabilities | |
| 22 | - │ └── mm-tui.dockerfile the content: FROM <image>:<tag>, ENV, ENTRYPOINT ["mm-tui"] | |
| 23 | - └── mm-acp/ | |
| 24 | - ├── mm-acp.yaml | |
| 25 | - └── mm-acp.dockerfile … ENTRYPOINT ["mm-acp-info"] | |
| 26 | -``` | |
| 27 | - | |
| 28 | -## What changed from the v2 kits | |
| 29 | - | |
| 30 | -| | v2 (`docker-sbx/kits/*/spec.yaml`) | v3 (`docker-sbx-v3/kits/*/`) | | |
| 31 | -|---|---|---| | |
| 32 | -| Files | one `spec.yaml` | `<kit>.yaml` (descriptor) + `<kit>.dockerfile` (content) | | |
| 33 | -| Kind | `kind: sandbox` | `kind: workload` | | |
| 34 | -| Name | `name: mm-tui` | none: a kit's identity is the reference it is consumed by | | |
| 35 | -| Image, entry point, env | `sandbox.image`, `sandbox.entrypoint`, `environment.variables` | `FROM`, `ENTRYPOINT`, `ENV` in the Dockerfile — the descriptor restates nothing the image config carries | | |
| 36 | -| Network | `permissions.network.allow` | `capabilities: - type: com.docker.sandbox/network-policy@1` (`runtime.allow`) | | |
| 37 | -| Agent launch | implicit | `capabilities: - type: com.docker.sandbox/sbx@1`: the host runs the ENTRYPOINT under bash, as the image's user (`agent`) | | |
| 38 | -| `tag` arg | substituted into `sandbox.image` at create | **build-phase** (`buildArg: MM_TAG`): baked in when the kit is built; also the kit's `version` and its `provides: mm@<tag>` | | |
| 39 | -| `config` arg | substituted into `environment.variables` | **create-phase** (`env: AGENT_CONFIG`): exported to the container at `sbx run` / `sbx create` | | |
| 40 | -| Owner of the image | rewritten in `sandbox.image` | its own build-phase arg, `image` (`k33g/mm-sandbox`) | | |
| 41 | -| Published as | `sbx kit push` → `k33g/mm-tui`, `k33g/mm-acp` | `docker buildx build --push` → `k33g/sbx-kit-mm-tui`, `k33g/sbx-kit-mm-acp` (an ordinary multi-arch image, with SBOM and provenance) | | |
| 42 | - | |
| 43 | -The repositories differ on purpose: pushing a v3 kit to `k33g/mm-tui:<version>` would replace the v2 kit published under that tag. `sbx-kit-<name>` is the naming Docker's own kits use. | |
| 44 | - | |
| 45 | -## Two things behave differently | |
| 46 | - | |
| 47 | -**The workspace is `/home/agent/workspace`.** The template's base image declares that `WORKDIR`, and `sbx@1` requires the host to mount the workspace at the image's working directory when it is absolute. A relative configuration path (`config=agent.dmr.yaml`) works as before. An absolute **host** path in `AGENT_CONFIG` (`/Users/…/agent.dmr.yaml`) does not: use the path relative to the workspace, or `/home/agent/workspace/…`. (Stated by the specification; not yet observed with sbx.) | |
| 48 | - | |
| 49 | -**The template image must be on a registry to run the kits from source.** A v3 kit is built on top of the template (`FROM k33g/mm-sandbox:<tag>`), and `sbx run ./docker-sbx-v3/kits/…` builds it in sbx's builder sandbox, whose own Docker engine pulls that image from the registry. `--pull never` and `sbx template load` no longer help. Push the image (`PUSH=1 ./docker-sbx-v3/build.sh`) before running a kit from source, or check the kits without sbx with `check-kits.sh`. | |
| 50 | - | |
| 51 | -## 0. Use the published kits (no build) | |
| 52 | - | |
| 53 | -Once `publish.sh` has run for a version: | |
| 54 | - | |
| 55 | -```bash | |
| 56 | -sbx kit inspect k33g/sbx-kit-mm-tui:0.2.1 # look before you run | |
| 57 | - | |
| 58 | -cd /path/to/your/project | |
| 59 | -sbx run k33g/sbx-kit-mm-tui:0.2.1 . -- agent.dmr.yaml | |
| 60 | -sbx run k33g/sbx-kit-mm-tui:0.2.1 . --kit-arg config=agent.dmr.yaml | |
| 61 | -``` | |
| 62 | - | |
| 63 | -What follows `--` is mm's own command line. Without it, mm reads the `config` argument, then `./agent.yaml` in the workspace, then its built-in defaults. | |
| 64 | - | |
| 65 | -From an editor, create the sandbox once, from the project the editor will open: | |
| 66 | - | |
| 67 | -```bash | |
| 68 | -cd /path/to/your/project | |
| 69 | -sbx create --name mm-acp k33g/sbx-kit-mm-acp:0.2.1 . --kit-arg config=agent.dmr.yaml | |
| 70 | -``` | |
| 71 | - | |
| 72 | -then register it — in Zed's `settings.json`: | |
| 73 | - | |
| 74 | -```json | |
| 75 | -{ | |
| 76 | - "agent_servers": { | |
| 77 | - "mini-me (sandbox)": { | |
| 78 | - "type": "custom", | |
| 79 | - "command": "sbx", | |
| 80 | - "args": ["exec", "-i", "mm-acp", "mm", "-acp"] | |
| 81 | - } | |
| 82 | - } | |
| 83 | -} | |
| 84 | -``` | |
| 85 | - | |
| 86 | -**Kit arguments.** On a published kit only `config` can be set: `image` and `tag` are build-phase and were fixed when the kit was built, so a published kit always names the image it was built on. To use another mm version, take the kit of that version. | |
| 87 | - | |
| 88 | -| `--kit-arg` | Default | Phase | Effect | | |
| 89 | -|---|---|---|---| | |
| 90 | -| `config=<path>` | empty | create | The file mm reads (its `AGENT_CONFIG`): relative to the workspace, or absolute inside the sandbox. Empty: `./agent.yaml`, then the built-in defaults. | | |
| 91 | -| `tag=<version>` | mm's version (`0.2.1`) | build | Which `<image>:<tag>` the kit is built FROM; also the kit's version. No `v`. | | |
| 92 | -| `image=<repo>` | `k33g/mm-sandbox` | build | Which repository the kit is built FROM. | | |
| 93 | - | |
| 94 | -## 1. Build the template | |
| 95 | - | |
| 96 | -From the repository root: | |
| 97 | - | |
| 98 | -```bash | |
| 99 | -./docker-sbx-v3/build.sh # TAG from release.env: v0.2.1 → k33g/mm-sandbox:0.2.1, local store | |
| 100 | -PUSH=1 ./docker-sbx-v3/build.sh # multi-arch, pushed — needed before running a kit from source | |
| 101 | -``` | |
| 102 | - | |
| 103 | -Same image, same rules as v2's `build.sh`; it then rewrites the kits' `image` and `tag` defaults (`sync-kits.sh`), so the kits always name the image just built. | |
| 104 | - | |
| 105 | -## 2. Check the kits without sbx | |
| 106 | - | |
| 107 | -```bash | |
| 108 | -./docker-sbx-v3/check-kits.sh # both kits | |
| 109 | -./docker-sbx-v3/check-kits.sh mm-tui # one | |
| 110 | -``` | |
| 111 | - | |
| 112 | -Each kit is built with `docker buildx build -f <kit>.yaml`: the descriptor's first line, `# syntax=docker/sandbox-kit:3`, makes BuildKit pull the kit frontend, which validates the descriptor (unknown keys and arg patterns included), builds the companion Dockerfile and writes the published form to `tmp/kits-v3/<kit>/`. With [`kit-tck`](https://github.com/docker/sandbox-kit-spec) on the `PATH` (or `KIT_TCK=/path/to/kit-tck`), the result is also checked against the specification: | |
| 113 | - | |
| 114 | -```bash | |
| 115 | -git clone https://github.com/docker/sandbox-kit-spec && cd sandbox-kit-spec | |
| 116 | -go build -o ~/.local/bin/kit-tck ./cmd/kit-tck | |
| 117 | -``` | |
| 118 | - | |
| 119 | -## 3. Run the kits from source | |
| 120 | - | |
| 121 | -With the template pushed (section 1): | |
| 122 | - | |
| 123 | -```bash | |
| 124 | -cd /path/to/your/project | |
| 125 | -sbx run /path/to/mini-me/docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | |
| 126 | -sbx create --name mm-acp /path/to/mini-me/docker-sbx-v3/kits/mm-acp . --kit-arg config=agent.dmr.yaml | |
| 127 | -``` | |
| 128 | - | |
| 129 | -sbx recognizes a v3 kit directory by its single `*.yaml` declaring `schemaVersion: "3"` (and no `spec.yaml`), builds it in its builder sandbox (`sbx kit builder status`), and caches the result by the directory's content. From source, the build-phase args can be set too: `--kit-arg tag=0.2.2`. | |
| 130 | - | |
| 131 | -## 4. Publishing a version | |
| 132 | - | |
| 133 | -```bash | |
| 134 | -export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner | |
| 135 | -export DOCKER_PAT=dckr_pat_… # an access token with read/write scope | |
| 136 | -./docker-sbx-v3/publish.sh # TAG from release.env: k33g/mm-sandbox:0.2.1, k33g/sbx-kit-mm-tui:0.2.1, k33g/sbx-kit-mm-acp:0.2.1 | |
| 137 | -``` | |
| 138 | - | |
| 139 | -It is two steps you can also run alone: | |
| 140 | - | |
| 141 | -```bash | |
| 142 | -PUSH=1 ./docker-sbx-v3/build.sh v0.2.1 # the image, multi-arch, pushed | |
| 143 | -./docker-sbx-v3/push-kits.sh v0.2.1 # the kits: buildx build --push, linux/amd64 + linux/arm64 | |
| 144 | -``` | |
| 145 | - | |
| 146 | -`push-kits.sh` refuses to start when the image is not on the registry yet, runs `sync-kits.sh`, then builds each kit with the `mm-sandbox-builder` buildx instance (created by `build.sh` if needed) with SBOM and provenance attestations, and validates the pushed kits with `kit-tck` when it is available. No `sbx` is needed to publish. `IMAGE_OWNER`, `REGISTRY`, `KIT_PREFIX` and `PLATFORMS` override the defaults. The descriptors end up naming the new version — commit them. | |
| 147 | - | |
| 148 | -## The model server stays on the host | |
| 149 | - | |
| 150 | -Unchanged from v2: inside a sandbox `localhost` is the sandbox itself, and Docker Model Runner or llama-server are reached through `host.docker.internal`. Both kits allow ports 12434 (Docker Model Runner) and 8080 (llama-server) on the host. Another port: `sbx policy allow network host.docker.internal:<port>`. | |
| 151 | - | |
| 152 | -## Status | |
| 153 | - | |
| 154 | -Checked here: both kits build with the `docker/sandbox-kit:3` frontend (3.0.0-m.6), single- and multi-arch with attestations, and pass `kit-tck validate` (18/18); the published config is `User: agent`, `Entrypoint: [mm-tui]` (or `[mm-acp-info]`), no `Cmd`, `WorkingDir: /home/agent/workspace`. Not yet checked: running them with `sbx` (`sbx run`, `sbx create`, `sbx exec -i … mm -acp`), and pushing to Docker Hub. The kit specification itself is still marked experimental. | |
| deleted file mode 100644 | |||
| @@ -1,154 +0,0 @@ | |||
| 1 | -# mm in a Docker Sandbox — kits v3 | ||
| 2 | - | ||
| 3 | -The same two kits as [`../docker-sbx`](../docker-sbx/README.md), rewritten for the [kit specification v3](https://github.com/docker/sandbox-kit-spec) (`schemaVersion: "3"`). `docker-sbx/` (v2) is left untouched and keeps working: sbx still loads `spec.yaml` kits. | ||
| 4 | - | ||
| 5 | -- **mm-tui** — `sbx run` opens mm's window mode (`mm -tui`) on the workspace. | ||
| 6 | -- **mm-acp** — `sbx create` once, then an editor that speaks the Agent Client Protocol runs `sbx exec -i … mm -acp`. | ||
| 7 | - | ||
| 8 | -``` | ||
| 9 | -docker-sbx-v3/ | ||
| 10 | -├── publish.sh build + push the image, then build + push the kits — the one command to release | ||
| 11 | -├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) | ||
| 12 | -├── sync-kits.sh points the kits at one image: owner + version | ||
| 13 | -├── check-kits.sh builds the kits locally (no push, no sbx) and checks them with kit-tck if present | ||
| 14 | -├── push-kits.sh builds and pushes the kits with buildx: <owner>/sbx-kit-mm-tui, <owner>/sbx-kit-mm-acp | ||
| 15 | -├── template/ | ||
| 16 | -│ ├── Dockerfile docker/sandbox-templates:shell + mm (built from this checkout) — same image as v2 | ||
| 17 | -│ ├── mm-tui entry point of the mm-tui kit: `mm -tui "$@"` | ||
| 18 | -│ └── mm-acp-info entry point of the mm-acp kit: prints the editor wiring, opens a shell | ||
| 19 | -└── kits/ | ||
| 20 | - ├── mm-tui/ | ||
| 21 | - │ ├── mm-tui.yaml the descriptor: kind: workload, args, capabilities | ||
| 22 | - │ └── mm-tui.dockerfile the content: FROM <image>:<tag>, ENV, ENTRYPOINT ["mm-tui"] | ||
| 23 | - └── mm-acp/ | ||
| 24 | - ├── mm-acp.yaml | ||
| 25 | - └── mm-acp.dockerfile … ENTRYPOINT ["mm-acp-info"] | ||
| 26 | -``` | ||
| 27 | - | ||
| 28 | -## What changed from the v2 kits | ||
| 29 | - | ||
| 30 | -| | v2 (`docker-sbx/kits/*/spec.yaml`) | v3 (`docker-sbx-v3/kits/*/`) | | ||
| 31 | -|---|---|---| | ||
| 32 | -| Files | one `spec.yaml` | `<kit>.yaml` (descriptor) + `<kit>.dockerfile` (content) | | ||
| 33 | -| Kind | `kind: sandbox` | `kind: workload` | | ||
| 34 | -| Name | `name: mm-tui` | none: a kit's identity is the reference it is consumed by | | ||
| 35 | -| Image, entry point, env | `sandbox.image`, `sandbox.entrypoint`, `environment.variables` | `FROM`, `ENTRYPOINT`, `ENV` in the Dockerfile — the descriptor restates nothing the image config carries | | ||
| 36 | -| Network | `permissions.network.allow` | `capabilities: - type: com.docker.sandbox/network-policy@1` (`runtime.allow`) | | ||
| 37 | -| Agent launch | implicit | `capabilities: - type: com.docker.sandbox/sbx@1`: the host runs the ENTRYPOINT under bash, as the image's user (`agent`) | | ||
| 38 | -| `tag` arg | substituted into `sandbox.image` at create | **build-phase** (`buildArg: MM_TAG`): baked in when the kit is built; also the kit's `version` and its `provides: mm@<tag>` | | ||
| 39 | -| `config` arg | substituted into `environment.variables` | **create-phase** (`env: AGENT_CONFIG`): exported to the container at `sbx run` / `sbx create` | | ||
| 40 | -| Owner of the image | rewritten in `sandbox.image` | its own build-phase arg, `image` (`k33g/mm-sandbox`) | | ||
| 41 | -| Published as | `sbx kit push` → `k33g/mm-tui`, `k33g/mm-acp` | `docker buildx build --push` → `k33g/sbx-kit-mm-tui`, `k33g/sbx-kit-mm-acp` (an ordinary multi-arch image, with SBOM and provenance) | | ||
| 42 | - | ||
| 43 | -The repositories differ on purpose: pushing a v3 kit to `k33g/mm-tui:<version>` would replace the v2 kit published under that tag. `sbx-kit-<name>` is the naming Docker's own kits use. | ||
| 44 | - | ||
| 45 | -## Two things behave differently | ||
| 46 | - | ||
| 47 | -**The workspace is `/home/agent/workspace`.** The template's base image declares that `WORKDIR`, and `sbx@1` requires the host to mount the workspace at the image's working directory when it is absolute. A relative configuration path (`config=agent.dmr.yaml`) works as before. An absolute **host** path in `AGENT_CONFIG` (`/Users/…/agent.dmr.yaml`) does not: use the path relative to the workspace, or `/home/agent/workspace/…`. (Stated by the specification; not yet observed with sbx.) | ||
| 48 | - | ||
| 49 | -**The template image must be on a registry to run the kits from source.** A v3 kit is built on top of the template (`FROM k33g/mm-sandbox:<tag>`), and `sbx run ./docker-sbx-v3/kits/…` builds it in sbx's builder sandbox, whose own Docker engine pulls that image from the registry. `--pull never` and `sbx template load` no longer help. Push the image (`PUSH=1 ./docker-sbx-v3/build.sh`) before running a kit from source, or check the kits without sbx with `check-kits.sh`. | ||
| 50 | - | ||
| 51 | -## 0. Use the published kits (no build) | ||
| 52 | - | ||
| 53 | -Once `publish.sh` has run for a version: | ||
| 54 | - | ||
| 55 | -```bash | ||
| 56 | -sbx kit inspect k33g/sbx-kit-mm-tui:0.2.1 # look before you run | ||
| 57 | - | ||
| 58 | -cd /path/to/your/project | ||
| 59 | -sbx run k33g/sbx-kit-mm-tui:0.2.1 . -- agent.dmr.yaml | ||
| 60 | -sbx run k33g/sbx-kit-mm-tui:0.2.1 . --kit-arg config=agent.dmr.yaml | ||
| 61 | -``` | ||
| 62 | - | ||
| 63 | -What follows `--` is mm's own command line. Without it, mm reads the `config` argument, then `./agent.yaml` in the workspace, then its built-in defaults. | ||
| 64 | - | ||
| 65 | -From an editor, create the sandbox once, from the project the editor will open: | ||
| 66 | - | ||
| 67 | -```bash | ||
| 68 | -cd /path/to/your/project | ||
| 69 | -sbx create --name mm-acp k33g/sbx-kit-mm-acp:0.2.1 . --kit-arg config=agent.dmr.yaml | ||
| 70 | -``` | ||
| 71 | - | ||
| 72 | -then register it — in Zed's `settings.json`: | ||
| 73 | - | ||
| 74 | -```json | ||
| 75 | -{ | ||
| 76 | - "agent_servers": { | ||
| 77 | - "mini-me (sandbox)": { | ||
| 78 | - "type": "custom", | ||
| 79 | - "command": "sbx", | ||
| 80 | - "args": ["exec", "-i", "mm-acp", "mm", "-acp"] | ||
| 81 | - } | ||
| 82 | - } | ||
| 83 | -} | ||
| 84 | -``` | ||
| 85 | - | ||
| 86 | -**Kit arguments.** On a published kit only `config` can be set: `image` and `tag` are build-phase and were fixed when the kit was built, so a published kit always names the image it was built on. To use another mm version, take the kit of that version. | ||
| 87 | - | ||
| 88 | -| `--kit-arg` | Default | Phase | Effect | | ||
| 89 | -|---|---|---|---| | ||
| 90 | -| `config=<path>` | empty | create | The file mm reads (its `AGENT_CONFIG`): relative to the workspace, or absolute inside the sandbox. Empty: `./agent.yaml`, then the built-in defaults. | | ||
| 91 | -| `tag=<version>` | mm's version (`0.2.1`) | build | Which `<image>:<tag>` the kit is built FROM; also the kit's version. No `v`. | | ||
| 92 | -| `image=<repo>` | `k33g/mm-sandbox` | build | Which repository the kit is built FROM. | | ||
| 93 | - | ||
| 94 | -## 1. Build the template | ||
| 95 | - | ||
| 96 | -From the repository root: | ||
| 97 | - | ||
| 98 | -```bash | ||
| 99 | -./docker-sbx-v3/build.sh # TAG from release.env: v0.2.1 → k33g/mm-sandbox:0.2.1, local store | ||
| 100 | -PUSH=1 ./docker-sbx-v3/build.sh # multi-arch, pushed — needed before running a kit from source | ||
| 101 | -``` | ||
| 102 | - | ||
| 103 | -Same image, same rules as v2's `build.sh`; it then rewrites the kits' `image` and `tag` defaults (`sync-kits.sh`), so the kits always name the image just built. | ||
| 104 | - | ||
| 105 | -## 2. Check the kits without sbx | ||
| 106 | - | ||
| 107 | -```bash | ||
| 108 | -./docker-sbx-v3/check-kits.sh # both kits | ||
| 109 | -./docker-sbx-v3/check-kits.sh mm-tui # one | ||
| 110 | -``` | ||
| 111 | - | ||
| 112 | -Each kit is built with `docker buildx build -f <kit>.yaml`: the descriptor's first line, `# syntax=docker/sandbox-kit:3`, makes BuildKit pull the kit frontend, which validates the descriptor (unknown keys and arg patterns included), builds the companion Dockerfile and writes the published form to `tmp/kits-v3/<kit>/`. With [`kit-tck`](https://github.com/docker/sandbox-kit-spec) on the `PATH` (or `KIT_TCK=/path/to/kit-tck`), the result is also checked against the specification: | ||
| 113 | - | ||
| 114 | -```bash | ||
| 115 | -git clone https://github.com/docker/sandbox-kit-spec && cd sandbox-kit-spec | ||
| 116 | -go build -o ~/.local/bin/kit-tck ./cmd/kit-tck | ||
| 117 | -``` | ||
| 118 | - | ||
| 119 | -## 3. Run the kits from source | ||
| 120 | - | ||
| 121 | -With the template pushed (section 1): | ||
| 122 | - | ||
| 123 | -```bash | ||
| 124 | -cd /path/to/your/project | ||
| 125 | -sbx run /path/to/mini-me/docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | ||
| 126 | -sbx create --name mm-acp /path/to/mini-me/docker-sbx-v3/kits/mm-acp . --kit-arg config=agent.dmr.yaml | ||
| 127 | -``` | ||
| 128 | - | ||
| 129 | -sbx recognizes a v3 kit directory by its single `*.yaml` declaring `schemaVersion: "3"` (and no `spec.yaml`), builds it in its builder sandbox (`sbx kit builder status`), and caches the result by the directory's content. From source, the build-phase args can be set too: `--kit-arg tag=0.2.2`. | ||
| 130 | - | ||
| 131 | -## 4. Publishing a version | ||
| 132 | - | ||
| 133 | -```bash | ||
| 134 | -export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner | ||
| 135 | -export DOCKER_PAT=dckr_pat_… # an access token with read/write scope | ||
| 136 | -./docker-sbx-v3/publish.sh # TAG from release.env: k33g/mm-sandbox:0.2.1, k33g/sbx-kit-mm-tui:0.2.1, k33g/sbx-kit-mm-acp:0.2.1 | ||
| 137 | -``` | ||
| 138 | - | ||
| 139 | -It is two steps you can also run alone: | ||
| 140 | - | ||
| 141 | -```bash | ||
| 142 | -PUSH=1 ./docker-sbx-v3/build.sh v0.2.1 # the image, multi-arch, pushed | ||
| 143 | -./docker-sbx-v3/push-kits.sh v0.2.1 # the kits: buildx build --push, linux/amd64 + linux/arm64 | ||
| 144 | -``` | ||
| 145 | - | ||
| 146 | -`push-kits.sh` refuses to start when the image is not on the registry yet, runs `sync-kits.sh`, then builds each kit with the `mm-sandbox-builder` buildx instance (created by `build.sh` if needed) with SBOM and provenance attestations, and validates the pushed kits with `kit-tck` when it is available. No `sbx` is needed to publish. `IMAGE_OWNER`, `REGISTRY`, `KIT_PREFIX` and `PLATFORMS` override the defaults. The descriptors end up naming the new version — commit them. | ||
| 147 | - | ||
| 148 | -## The model server stays on the host | ||
| 149 | - | ||
| 150 | -Unchanged from v2: inside a sandbox `localhost` is the sandbox itself, and Docker Model Runner or llama-server are reached through `host.docker.internal`. Both kits allow ports 12434 (Docker Model Runner) and 8080 (llama-server) on the host. Another port: `sbx policy allow network host.docker.internal:<port>`. | ||
| 151 | - | ||
| 152 | -## Status | ||
| 153 | - | ||
| 154 | -Checked here: both kits build with the `docker/sandbox-kit:3` frontend (3.0.0-m.6), single- and multi-arch with attestations, and pass `kit-tck validate` (18/18); the published config is `User: agent`, `Entrypoint: [mm-tui]` (or `[mm-acp-info]`), no `Cmd`, `WorkingDir: /home/agent/workspace`. Not yet checked: running them with `sbx` (`sbx run`, `sbx create`, `sbx exec -i … mm -acp`), and pushing to Docker Hub. The kit specification itself is still marked experimental. | ||
deleted
docker-sbx-v3/build.sh +0 -105 | deleted file mode 100644 | ||
| @@ -1,105 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Build the mm sandbox template image, <owner>/mm-sandbox:<version>, from this | |
| 3 | -# checkout — the image both v3 kits are built FROM. The image tag follows mm's | |
| 4 | -# own tag, minus the "v": release.env says TAG="v0.2.1", the image is | |
| 5 | -# k33g/mm-sandbox:0.2.1 and `mm --version` inside it reports v0.2.1 — the | |
| 6 | -# same rule as the release assets. | |
| 7 | -# | |
| 8 | -# Usage: | |
| 9 | -# ./docker-sbx-v3/build.sh # TAG from release.env, image for this machine | |
| 10 | -# ./docker-sbx-v3/build.sh v0.2.2 # override the tag for this run | |
| 11 | -# PUSH=1 ./docker-sbx-v3/build.sh # multi-arch (linux/amd64 + linux/arm64) built | |
| 12 | -# # with buildx and PUSHED to the registry — | |
| 13 | -# # needs `docker login`; publish.sh does this | |
| 14 | -# IMAGE_OWNER=someone ./docker-sbx-v3/build.sh # another image owner (default k33g) | |
| 15 | -# PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set | |
| 16 | -# SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx-v3/build.sh | |
| 17 | -# # base it on the Docker-in-Docker shell | |
| 18 | -# | |
| 19 | -# Whatever the mode, the two kits under docker-sbx-v3/kits/ are then pointed | |
| 20 | -# at the image just built (docker-sbx-v3/sync-kits.sh), so kits and image move | |
| 21 | -# together. Publishing the kits themselves is docker-sbx-v3/push-kits.sh, and | |
| 22 | -# docker-sbx-v3/publish.sh chains the two. | |
| 23 | -# | |
| 24 | -# Unlike v2, a v3 kit is BUILT on top of this image (FROM), and sbx builds a | |
| 25 | -# source-form kit in its builder sandbox, whose Docker engine pulls from a | |
| 26 | -# registry: an image that is only in the local store is not enough for | |
| 27 | -# `sbx run ./docker-sbx-v3/kits/…`. Push it (PUSH=1) first. | |
| 28 | -set -euo pipefail | |
| 29 | - | |
| 30 | -cd "$(dirname "$0")/.." | |
| 31 | - | |
| 32 | -# release.env carries TAG ("v0.2.1"). It is git-ignored, so a checkout without | |
| 33 | -# it names the tag on the command line. A tag given on the command line wins. | |
| 34 | -if [ -f release.env ]; then | |
| 35 | - # shellcheck source=/dev/null | |
| 36 | - source release.env | |
| 37 | -fi | |
| 38 | -TAG="${1:-${TAG:-}}" | |
| 39 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 40 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx-v3/build.sh v1.2.3)" | |
| 41 | - exit 1 | |
| 42 | -fi | |
| 43 | - | |
| 44 | -# Not OWNER: release.env uses that name for the git owner (bots-garden), and | |
| 45 | -# the image owner is a different thing — the Docker Hub account, k33g. | |
| 46 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | |
| 47 | -VERSION="${TAG#v}" | |
| 48 | -IMAGE="${IMAGE_OWNER}/mm-sandbox:${VERSION}" | |
| 49 | -PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | |
| 50 | - | |
| 51 | -build_args=(--build-arg "MM_VERSION=${TAG}") | |
| 52 | -if [ -n "${SHELL_TEMPLATE:-}" ]; then | |
| 53 | - build_args+=(--build-arg "SHELL_TEMPLATE=${SHELL_TEMPLATE}") | |
| 54 | -fi | |
| 55 | - | |
| 56 | -if [ -n "${PUSH:-}" ]; then | |
| 57 | - # Multi-arch needs buildx's container driver: the classic builder can | |
| 58 | - # neither assemble a manifest list nor build for a foreign platform. The | |
| 59 | - # Go stage cross-compiles on the build platform; only the final stage's | |
| 60 | - # `RUN mm --version` runs under emulation (Docker Desktop ships QEMU). | |
| 61 | - echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | |
| 62 | - if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | |
| 63 | - docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | |
| 64 | - fi | |
| 65 | - docker buildx build --builder mm-sandbox-builder \ | |
| 66 | - --platform "${PLATFORMS}" \ | |
| 67 | - -f docker-sbx-v3/template/Dockerfile "${build_args[@]}" \ | |
| 68 | - -t "${IMAGE}" --push . | |
| 69 | - # The proof that ships: the registry holds one manifest per platform. | |
| 70 | - docker buildx imagetools inspect "${IMAGE}" | grep -E '^Name:|Platform:' | sed 's/^/ /' | |
| 71 | -else | |
| 72 | - echo "🐳 Building ${IMAGE} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | |
| 73 | - docker build -f docker-sbx-v3/template/Dockerfile "${build_args[@]}" -t "${IMAGE}" . | |
| 74 | - | |
| 75 | - # The one proof that what was built starts: --version needs no config and | |
| 76 | - # no model server. It also confirms the stamp reached the binary. | |
| 77 | - reported="$(docker run --rm "${IMAGE}" mm --version)" | |
| 78 | - if ! grep -q -- "${TAG}" <<<"${reported}"; then | |
| 79 | - echo "❌ the image does not report ${TAG}: ${reported}" | |
| 80 | - exit 1 | |
| 81 | - fi | |
| 82 | - echo "✅ ${reported}" | |
| 83 | -fi | |
| 84 | - | |
| 85 | -./docker-sbx-v3/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | |
| 86 | - | |
| 87 | -if [ -n "${PUSH:-}" ]; then | |
| 88 | - cat <<NEXT | |
| 89 | - | |
| 90 | -Image on the registry. Next: | |
| 91 | - | |
| 92 | - try the kits from source sbx run ./docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | |
| 93 | - publish them ./docker-sbx-v3/push-kits.sh ${TAG} | |
| 94 | -NEXT | |
| 95 | -else | |
| 96 | - cat <<NEXT | |
| 97 | - | |
| 98 | -${IMAGE} is in the local image store only. That is enough for | |
| 99 | -./docker-sbx-v3/check-kits.sh (which builds the kits with your docker), not | |
| 100 | -for sbx: its builder sandbox pulls the FROM image from the registry. To run | |
| 101 | -the kits from source with sbx, push the image first: | |
| 102 | - | |
| 103 | - PUSH=1 ./docker-sbx-v3/build.sh ${TAG} | |
| 104 | -NEXT | |
| 105 | -fi | |
| deleted file mode 100644 | |||
| @@ -1,105 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Build the mm sandbox template image, <owner>/mm-sandbox:<version>, from this | ||
| 3 | -# checkout — the image both v3 kits are built FROM. The image tag follows mm's | ||
| 4 | -# own tag, minus the "v": release.env says TAG="v0.2.1", the image is | ||
| 5 | -# k33g/mm-sandbox:0.2.1 and `mm --version` inside it reports v0.2.1 — the | ||
| 6 | -# same rule as the release assets. | ||
| 7 | -# | ||
| 8 | -# Usage: | ||
| 9 | -# ./docker-sbx-v3/build.sh # TAG from release.env, image for this machine | ||
| 10 | -# ./docker-sbx-v3/build.sh v0.2.2 # override the tag for this run | ||
| 11 | -# PUSH=1 ./docker-sbx-v3/build.sh # multi-arch (linux/amd64 + linux/arm64) built | ||
| 12 | -# # with buildx and PUSHED to the registry — | ||
| 13 | -# # needs `docker login`; publish.sh does this | ||
| 14 | -# IMAGE_OWNER=someone ./docker-sbx-v3/build.sh # another image owner (default k33g) | ||
| 15 | -# PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set | ||
| 16 | -# SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx-v3/build.sh | ||
| 17 | -# # base it on the Docker-in-Docker shell | ||
| 18 | -# | ||
| 19 | -# Whatever the mode, the two kits under docker-sbx-v3/kits/ are then pointed | ||
| 20 | -# at the image just built (docker-sbx-v3/sync-kits.sh), so kits and image move | ||
| 21 | -# together. Publishing the kits themselves is docker-sbx-v3/push-kits.sh, and | ||
| 22 | -# docker-sbx-v3/publish.sh chains the two. | ||
| 23 | -# | ||
| 24 | -# Unlike v2, a v3 kit is BUILT on top of this image (FROM), and sbx builds a | ||
| 25 | -# source-form kit in its builder sandbox, whose Docker engine pulls from a | ||
| 26 | -# registry: an image that is only in the local store is not enough for | ||
| 27 | -# `sbx run ./docker-sbx-v3/kits/…`. Push it (PUSH=1) first. | ||
| 28 | -set -euo pipefail | ||
| 29 | - | ||
| 30 | -cd "$(dirname "$0")/.." | ||
| 31 | - | ||
| 32 | -# release.env carries TAG ("v0.2.1"). It is git-ignored, so a checkout without | ||
| 33 | -# it names the tag on the command line. A tag given on the command line wins. | ||
| 34 | -if [ -f release.env ]; then | ||
| 35 | - # shellcheck source=/dev/null | ||
| 36 | - source release.env | ||
| 37 | -fi | ||
| 38 | -TAG="${1:-${TAG:-}}" | ||
| 39 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 40 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx-v3/build.sh v1.2.3)" | ||
| 41 | - exit 1 | ||
| 42 | -fi | ||
| 43 | - | ||
| 44 | -# Not OWNER: release.env uses that name for the git owner (bots-garden), and | ||
| 45 | -# the image owner is a different thing — the Docker Hub account, k33g. | ||
| 46 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | ||
| 47 | -VERSION="${TAG#v}" | ||
| 48 | -IMAGE="${IMAGE_OWNER}/mm-sandbox:${VERSION}" | ||
| 49 | -PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | ||
| 50 | - | ||
| 51 | -build_args=(--build-arg "MM_VERSION=${TAG}") | ||
| 52 | -if [ -n "${SHELL_TEMPLATE:-}" ]; then | ||
| 53 | - build_args+=(--build-arg "SHELL_TEMPLATE=${SHELL_TEMPLATE}") | ||
| 54 | -fi | ||
| 55 | - | ||
| 56 | -if [ -n "${PUSH:-}" ]; then | ||
| 57 | - # Multi-arch needs buildx's container driver: the classic builder can | ||
| 58 | - # neither assemble a manifest list nor build for a foreign platform. The | ||
| 59 | - # Go stage cross-compiles on the build platform; only the final stage's | ||
| 60 | - # `RUN mm --version` runs under emulation (Docker Desktop ships QEMU). | ||
| 61 | - echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | ||
| 62 | - if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | ||
| 63 | - docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | ||
| 64 | - fi | ||
| 65 | - docker buildx build --builder mm-sandbox-builder \ | ||
| 66 | - --platform "${PLATFORMS}" \ | ||
| 67 | - -f docker-sbx-v3/template/Dockerfile "${build_args[@]}" \ | ||
| 68 | - -t "${IMAGE}" --push . | ||
| 69 | - # The proof that ships: the registry holds one manifest per platform. | ||
| 70 | - docker buildx imagetools inspect "${IMAGE}" | grep -E '^Name:|Platform:' | sed 's/^/ /' | ||
| 71 | -else | ||
| 72 | - echo "🐳 Building ${IMAGE} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | ||
| 73 | - docker build -f docker-sbx-v3/template/Dockerfile "${build_args[@]}" -t "${IMAGE}" . | ||
| 74 | - | ||
| 75 | - # The one proof that what was built starts: --version needs no config and | ||
| 76 | - # no model server. It also confirms the stamp reached the binary. | ||
| 77 | - reported="$(docker run --rm "${IMAGE}" mm --version)" | ||
| 78 | - if ! grep -q -- "${TAG}" <<<"${reported}"; then | ||
| 79 | - echo "❌ the image does not report ${TAG}: ${reported}" | ||
| 80 | - exit 1 | ||
| 81 | - fi | ||
| 82 | - echo "✅ ${reported}" | ||
| 83 | -fi | ||
| 84 | - | ||
| 85 | -./docker-sbx-v3/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | ||
| 86 | - | ||
| 87 | -if [ -n "${PUSH:-}" ]; then | ||
| 88 | - cat <<NEXT | ||
| 89 | - | ||
| 90 | -Image on the registry. Next: | ||
| 91 | - | ||
| 92 | - try the kits from source sbx run ./docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | ||
| 93 | - publish them ./docker-sbx-v3/push-kits.sh ${TAG} | ||
| 94 | -NEXT | ||
| 95 | -else | ||
| 96 | - cat <<NEXT | ||
| 97 | - | ||
| 98 | -${IMAGE} is in the local image store only. That is enough for | ||
| 99 | -./docker-sbx-v3/check-kits.sh (which builds the kits with your docker), not | ||
| 100 | -for sbx: its builder sandbox pulls the FROM image from the registry. To run | ||
| 101 | -the kits from source with sbx, push the image first: | ||
| 102 | - | ||
| 103 | - PUSH=1 ./docker-sbx-v3/build.sh ${TAG} | ||
| 104 | -NEXT | ||
| 105 | -fi | ||
deleted
docker-sbx-v3/check-kits.sh +0 -60 | deleted file mode 100644 | ||
| @@ -1,60 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Build the two v3 kits locally, without pushing and without sbx, and check | |
| 3 | -# them against the kit specification when kit-tck is available. | |
| 4 | -# | |
| 5 | -# Usage: | |
| 6 | -# ./docker-sbx-v3/check-kits.sh # every kit under docker-sbx-v3/kits/ | |
| 7 | -# ./docker-sbx-v3/check-kits.sh mm-tui # one kit | |
| 8 | -# KIT_TCK=/path/to/kit-tck … # the conformance tool, if not on the PATH | |
| 9 | -# | |
| 10 | -# Each kit is built with `docker buildx build -f <kit>.yaml`: the descriptor's | |
| 11 | -# first line, `# syntax=docker/sandbox-kit:3`, makes BuildKit pull the kit | |
| 12 | -# frontend, which validates the descriptor (arg patterns included), builds | |
| 13 | -# <kit>.dockerfile and writes the published form — an OCI image whose | |
| 14 | -# manifest annotation carries the descriptor. The result lands in | |
| 15 | -# tmp/kits-v3/<kit>/ as an OCI layout, for the host platform only. | |
| 16 | -# | |
| 17 | -# The args are the descriptors' defaults, so run build.sh (or sync-kits.sh) | |
| 18 | -# first to point them at the image you want. That image is resolved by your | |
| 19 | -# BuildKit: from the local store with Docker Desktop's default builder, | |
| 20 | -# otherwise from the registry. | |
| 21 | -# | |
| 22 | -# kit-tck is the specification's conformance tool | |
| 23 | -# (github.com/docker/sandbox-kit-spec, `go build ./cmd/kit-tck`). Without it | |
| 24 | -# the build itself is the check: the frontend refuses a descriptor that does | |
| 25 | -# not validate. | |
| 26 | -set -euo pipefail | |
| 27 | - | |
| 28 | -cd "$(dirname "$0")/.." | |
| 29 | - | |
| 30 | -KIT_TCK="${KIT_TCK:-kit-tck}" | |
| 31 | -if [ $# -gt 0 ]; then | |
| 32 | - kits=("$@") | |
| 33 | -else | |
| 34 | - kits=() | |
| 35 | - for dir in docker-sbx-v3/kits/*/; do | |
| 36 | - kits+=("$(basename "${dir}")") | |
| 37 | - done | |
| 38 | -fi | |
| 39 | - | |
| 40 | -for kit in "${kits[@]}"; do | |
| 41 | - dir="docker-sbx-v3/kits/${kit}" | |
| 42 | - if [ ! -f "${dir}/${kit}.yaml" ]; then | |
| 43 | - echo "❌ no kit named '${kit}': expected ${dir}/${kit}.yaml" >&2 | |
| 44 | - exit 1 | |
| 45 | - fi | |
| 46 | - out="tmp/kits-v3/${kit}" | |
| 47 | - rm -rf "${out}" | |
| 48 | - mkdir -p "$(dirname "${out}")" | |
| 49 | - | |
| 50 | - echo "🧰 ${kit}: building ${dir}/${kit}.yaml" | |
| 51 | - docker buildx build "${dir}" -f "${dir}/${kit}.yaml" \ | |
| 52 | - --output "type=oci,dest=${out},tar=false,name=${kit}:check" | |
| 53 | - | |
| 54 | - if command -v "${KIT_TCK}" >/dev/null 2>&1; then | |
| 55 | - "${KIT_TCK}" validate --layout "${out}" check | |
| 56 | - else | |
| 57 | - echo " (kit-tck not found: built and validated by the frontend only)" | |
| 58 | - fi | |
| 59 | - echo "✅ ${kit} → ${out}" | |
| 60 | -done | |
| deleted file mode 100644 | |||
| @@ -1,60 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Build the two v3 kits locally, without pushing and without sbx, and check | ||
| 3 | -# them against the kit specification when kit-tck is available. | ||
| 4 | -# | ||
| 5 | -# Usage: | ||
| 6 | -# ./docker-sbx-v3/check-kits.sh # every kit under docker-sbx-v3/kits/ | ||
| 7 | -# ./docker-sbx-v3/check-kits.sh mm-tui # one kit | ||
| 8 | -# KIT_TCK=/path/to/kit-tck … # the conformance tool, if not on the PATH | ||
| 9 | -# | ||
| 10 | -# Each kit is built with `docker buildx build -f <kit>.yaml`: the descriptor's | ||
| 11 | -# first line, `# syntax=docker/sandbox-kit:3`, makes BuildKit pull the kit | ||
| 12 | -# frontend, which validates the descriptor (arg patterns included), builds | ||
| 13 | -# <kit>.dockerfile and writes the published form — an OCI image whose | ||
| 14 | -# manifest annotation carries the descriptor. The result lands in | ||
| 15 | -# tmp/kits-v3/<kit>/ as an OCI layout, for the host platform only. | ||
| 16 | -# | ||
| 17 | -# The args are the descriptors' defaults, so run build.sh (or sync-kits.sh) | ||
| 18 | -# first to point them at the image you want. That image is resolved by your | ||
| 19 | -# BuildKit: from the local store with Docker Desktop's default builder, | ||
| 20 | -# otherwise from the registry. | ||
| 21 | -# | ||
| 22 | -# kit-tck is the specification's conformance tool | ||
| 23 | -# (github.com/docker/sandbox-kit-spec, `go build ./cmd/kit-tck`). Without it | ||
| 24 | -# the build itself is the check: the frontend refuses a descriptor that does | ||
| 25 | -# not validate. | ||
| 26 | -set -euo pipefail | ||
| 27 | - | ||
| 28 | -cd "$(dirname "$0")/.." | ||
| 29 | - | ||
| 30 | -KIT_TCK="${KIT_TCK:-kit-tck}" | ||
| 31 | -if [ $# -gt 0 ]; then | ||
| 32 | - kits=("$@") | ||
| 33 | -else | ||
| 34 | - kits=() | ||
| 35 | - for dir in docker-sbx-v3/kits/*/; do | ||
| 36 | - kits+=("$(basename "${dir}")") | ||
| 37 | - done | ||
| 38 | -fi | ||
| 39 | - | ||
| 40 | -for kit in "${kits[@]}"; do | ||
| 41 | - dir="docker-sbx-v3/kits/${kit}" | ||
| 42 | - if [ ! -f "${dir}/${kit}.yaml" ]; then | ||
| 43 | - echo "❌ no kit named '${kit}': expected ${dir}/${kit}.yaml" >&2 | ||
| 44 | - exit 1 | ||
| 45 | - fi | ||
| 46 | - out="tmp/kits-v3/${kit}" | ||
| 47 | - rm -rf "${out}" | ||
| 48 | - mkdir -p "$(dirname "${out}")" | ||
| 49 | - | ||
| 50 | - echo "🧰 ${kit}: building ${dir}/${kit}.yaml" | ||
| 51 | - docker buildx build "${dir}" -f "${dir}/${kit}.yaml" \ | ||
| 52 | - --output "type=oci,dest=${out},tar=false,name=${kit}:check" | ||
| 53 | - | ||
| 54 | - if command -v "${KIT_TCK}" >/dev/null 2>&1; then | ||
| 55 | - "${KIT_TCK}" validate --layout "${out}" check | ||
| 56 | - else | ||
| 57 | - echo " (kit-tck not found: built and validated by the frontend only)" | ||
| 58 | - fi | ||
| 59 | - echo "✅ ${kit} → ${out}" | ||
| 60 | -done | ||
deleted
docker-sbx-v3/kits/mm-acp/mm-acp.dockerfile +0 -20 | deleted file mode 100644 | ||
| @@ -1,20 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | -# check=skip=InvalidDefaultArgInFrom | |
| 3 | -# Content of the mm-acp kit (descriptor: mm-acp.yaml). Same template image as | |
| 4 | -# mm-tui; only the launch contract differs. No default on purpose (hence the | |
| 5 | -# skipped check above): the frontend always passes the kit's `image` and `tag` | |
| 6 | -# args — see kits/mm-tui/mm-tui.dockerfile. | |
| 7 | -ARG MM_IMAGE | |
| 8 | -ARG MM_TAG | |
| 9 | -FROM ${MM_IMAGE}:${MM_TAG} | |
| 10 | - | |
| 11 | -# v2's environment.variables. `sbx exec` inherits the image environment, so | |
| 12 | -# the editor's settings need not repeat them. AGENT_CONFIG comes from the kit's | |
| 13 | -# `config` arg (env:). | |
| 14 | -ENV LANG=C.UTF-8 | |
| 15 | - | |
| 16 | -# v2's sandbox.entrypoint. Not `mm -acp`: nothing useful comes of speaking | |
| 17 | -# JSON-RPC to a terminal. Attaching with `sbx run` prints the editor wiring | |
| 18 | -# with this sandbox's real name, then opens a shell; the editor itself runs | |
| 19 | -# `sbx exec -i <sandbox> mm -acp`. | |
| 20 | -ENTRYPOINT ["mm-acp-info"] | |
| deleted file mode 100644 | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | -# check=skip=InvalidDefaultArgInFrom | ||
| 3 | -# Content of the mm-acp kit (descriptor: mm-acp.yaml). Same template image as | ||
| 4 | -# mm-tui; only the launch contract differs. No default on purpose (hence the | ||
| 5 | -# skipped check above): the frontend always passes the kit's `image` and `tag` | ||
| 6 | -# args — see kits/mm-tui/mm-tui.dockerfile. | ||
| 7 | -ARG MM_IMAGE | ||
| 8 | -ARG MM_TAG | ||
| 9 | -FROM ${MM_IMAGE}:${MM_TAG} | ||
| 10 | - | ||
| 11 | -# v2's environment.variables. `sbx exec` inherits the image environment, so | ||
| 12 | -# the editor's settings need not repeat them. AGENT_CONFIG comes from the kit's | ||
| 13 | -# `config` arg (env:). | ||
| 14 | -ENV LANG=C.UTF-8 | ||
| 15 | - | ||
| 16 | -# v2's sandbox.entrypoint. Not `mm -acp`: nothing useful comes of speaking | ||
| 17 | -# JSON-RPC to a terminal. Attaching with `sbx run` prints the editor wiring | ||
| 18 | -# with this sandbox's real name, then opens a shell; the editor itself runs | ||
| 19 | -# `sbx exec -i <sandbox> mm -acp`. | ||
| 20 | -ENTRYPOINT ["mm-acp-info"] | ||
deleted
docker-sbx-v3/kits/mm-acp/mm-acp.yaml +0 -82 | deleted file mode 100644 | ||
| @@ -1,82 +0,0 @@ | ||
| 1 | -# syntax=docker/sandbox-kit:3 | |
| 2 | -# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/sandbox-kit-spec/main/schema/kit.schema.json | |
| 3 | -# | |
| 4 | -# Docker Sandboxes kit (spec v3): mm as an editor's agent (Agent Client | |
| 5 | -# Protocol), on the mm sandbox template. The v2 twin is | |
| 6 | -# docker-sbx/kits/mm-acp/spec.yaml. | |
| 7 | -# | |
| 8 | -# sbx create --name mm-acp ./docker-sbx-v3/kits/mm-acp . \ | |
| 9 | -# --kit-arg config=agent.dmr.yaml | |
| 10 | -# | |
| 11 | -# then, in the editor (Zed settings.json): | |
| 12 | -# | |
| 13 | -# "agent_servers": { "mini-me (sandbox)": { "type": "custom", | |
| 14 | -# "command": "sbx", "args": ["exec", "-i", "mm-acp", "mm", "-acp"] } } | |
| 15 | -# | |
| 16 | -# Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the | |
| 17 | -# agent's raw stdin/stdout, and `sbx run` always allocates a terminal. So the | |
| 18 | -# sandbox is created without attaching, and the editor starts `mm -acp` inside | |
| 19 | -# it for every conversation (sbx starts a stopped sandbox first). Attaching | |
| 20 | -# with `sbx run` runs the entry point (mm-acp.dockerfile), which prints this | |
| 21 | -# wiring with the sandbox's real name and opens a shell. | |
| 22 | -# | |
| 23 | -# sbx builds this source form in its builder sandbox, whose own Docker engine | |
| 24 | -# PULLS the FROM image: <image>:<tag> must be on a registry, not only in the | |
| 25 | -# local image store (see docker-sbx-v3/README.md). | |
| 26 | -schemaVersion: "3" | |
| 27 | -kind: workload | |
| 28 | -displayName: Mini Me (editor, ACP) | |
| 29 | -description: > | |
| 30 | - Holds mm, a minimal coding agent for local LLMs, for an editor that speaks | |
| 31 | - the Agent Client Protocol (Zed, …). The editor runs `sbx exec -i <sandbox> | |
| 32 | - mm -acp`; every command and file edit the model asks for happens inside the | |
| 33 | - sandbox, on the mounted workspace. The model server stays on the host, | |
| 34 | - reached through host.docker.internal. | |
| 35 | -sourceUrl: https://git.rickub.com/bots-garden/mini-me | |
| 36 | -# The kit's version is mm's: the image tag it is built on. A published kit is | |
| 37 | -# versioned by its OCI tag anyway, which wins over this field. | |
| 38 | -version: "${{ kit.args.tag }}" | |
| 39 | -provides: ["mm@${{ kit.args.tag }}"] | |
| 40 | - | |
| 41 | -args: | |
| 42 | - # Build-phase (buildArg): see kits/mm-tui/mm-tui.yaml. | |
| 43 | - image: | |
| 44 | - default: "k33g/mm-sandbox" | |
| 45 | - description: >- | |
| 46 | - Repository of the mm sandbox template image, without the tag. Kept equal | |
| 47 | - to <owner>/mm-sandbox by docker-sbx-v3/sync-kits.sh. | |
| 48 | - pattern: '^[a-z0-9][a-z0-9._/:-]*$' | |
| 49 | - buildArg: MM_IMAGE | |
| 50 | - tag: | |
| 51 | - default: "0.2.6" | |
| 52 | - description: >- | |
| 53 | - Tag of the template image: mm's version without the "v", as | |
| 54 | - docker-sbx-v3/build.sh tags it (and rewrites this default to). Also the | |
| 55 | - kit's version, hence version-shaped. | |
| 56 | - pattern: '^[0-9]+(\.[0-9A-Za-z-]+)*$' | |
| 57 | - buildArg: MM_TAG | |
| 58 | - # Create-phase (env): baked into the container at `sbx create`, so | |
| 59 | - # `sbx exec` inherits it and the editor's settings need not repeat the path. | |
| 60 | - # `sbx exec -e AGENT_CONFIG=…` overrides it for one session. | |
| 61 | - config: | |
| 62 | - default: "" | |
| 63 | - description: >- | |
| 64 | - Configuration file mm reads (its AGENT_CONFIG): a path relative to the | |
| 65 | - workspace, which is where `sbx exec` starts mm, or an absolute path | |
| 66 | - inside the sandbox. Empty: ./agent.yaml in the workspace, then the | |
| 67 | - built-in defaults. | |
| 68 | - env: AGENT_CONFIG | |
| 69 | - | |
| 70 | -capabilities: | |
| 71 | - # A sandbox-agent workload — see kits/mm-tui/mm-tui.yaml. | |
| 72 | - - type: com.docker.sandbox/sbx@1 | |
| 73 | - | |
| 74 | - # The model server on the host — see kits/mm-tui/mm-tui.yaml. | |
| 75 | - - type: com.docker.sandbox/network-policy@1 | |
| 76 | - config: | |
| 77 | - runtime: | |
| 78 | - allow: | |
| 79 | - - "host.docker.internal:12434" | |
| 80 | - - "localhost:12434" | |
| 81 | - - "host.docker.internal:8080" | |
| 82 | - - "localhost:8080" | |
| deleted file mode 100644 | |||
| @@ -1,82 +0,0 @@ | |||
| 1 | -# syntax=docker/sandbox-kit:3 | ||
| 2 | -# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/sandbox-kit-spec/main/schema/kit.schema.json | ||
| 3 | -# | ||
| 4 | -# Docker Sandboxes kit (spec v3): mm as an editor's agent (Agent Client | ||
| 5 | -# Protocol), on the mm sandbox template. The v2 twin is | ||
| 6 | -# docker-sbx/kits/mm-acp/spec.yaml. | ||
| 7 | -# | ||
| 8 | -# sbx create --name mm-acp ./docker-sbx-v3/kits/mm-acp . \ | ||
| 9 | -# --kit-arg config=agent.dmr.yaml | ||
| 10 | -# | ||
| 11 | -# then, in the editor (Zed settings.json): | ||
| 12 | -# | ||
| 13 | -# "agent_servers": { "mini-me (sandbox)": { "type": "custom", | ||
| 14 | -# "command": "sbx", "args": ["exec", "-i", "mm-acp", "mm", "-acp"] } } | ||
| 15 | -# | ||
| 16 | -# Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the | ||
| 17 | -# agent's raw stdin/stdout, and `sbx run` always allocates a terminal. So the | ||
| 18 | -# sandbox is created without attaching, and the editor starts `mm -acp` inside | ||
| 19 | -# it for every conversation (sbx starts a stopped sandbox first). Attaching | ||
| 20 | -# with `sbx run` runs the entry point (mm-acp.dockerfile), which prints this | ||
| 21 | -# wiring with the sandbox's real name and opens a shell. | ||
| 22 | -# | ||
| 23 | -# sbx builds this source form in its builder sandbox, whose own Docker engine | ||
| 24 | -# PULLS the FROM image: <image>:<tag> must be on a registry, not only in the | ||
| 25 | -# local image store (see docker-sbx-v3/README.md). | ||
| 26 | -schemaVersion: "3" | ||
| 27 | -kind: workload | ||
| 28 | -displayName: Mini Me (editor, ACP) | ||
| 29 | -description: > | ||
| 30 | - Holds mm, a minimal coding agent for local LLMs, for an editor that speaks | ||
| 31 | - the Agent Client Protocol (Zed, …). The editor runs `sbx exec -i <sandbox> | ||
| 32 | - mm -acp`; every command and file edit the model asks for happens inside the | ||
| 33 | - sandbox, on the mounted workspace. The model server stays on the host, | ||
| 34 | - reached through host.docker.internal. | ||
| 35 | -sourceUrl: https://git.rickub.com/bots-garden/mini-me | ||
| 36 | -# The kit's version is mm's: the image tag it is built on. A published kit is | ||
| 37 | -# versioned by its OCI tag anyway, which wins over this field. | ||
| 38 | -version: "${{ kit.args.tag }}" | ||
| 39 | -provides: ["mm@${{ kit.args.tag }}"] | ||
| 40 | - | ||
| 41 | -args: | ||
| 42 | - # Build-phase (buildArg): see kits/mm-tui/mm-tui.yaml. | ||
| 43 | - image: | ||
| 44 | - default: "k33g/mm-sandbox" | ||
| 45 | - description: >- | ||
| 46 | - Repository of the mm sandbox template image, without the tag. Kept equal | ||
| 47 | - to <owner>/mm-sandbox by docker-sbx-v3/sync-kits.sh. | ||
| 48 | - pattern: '^[a-z0-9][a-z0-9._/:-]*$' | ||
| 49 | - buildArg: MM_IMAGE | ||
| 50 | - tag: | ||
| 51 | - default: "0.2.6" | ||
| 52 | - description: >- | ||
| 53 | - Tag of the template image: mm's version without the "v", as | ||
| 54 | - docker-sbx-v3/build.sh tags it (and rewrites this default to). Also the | ||
| 55 | - kit's version, hence version-shaped. | ||
| 56 | - pattern: '^[0-9]+(\.[0-9A-Za-z-]+)*$' | ||
| 57 | - buildArg: MM_TAG | ||
| 58 | - # Create-phase (env): baked into the container at `sbx create`, so | ||
| 59 | - # `sbx exec` inherits it and the editor's settings need not repeat the path. | ||
| 60 | - # `sbx exec -e AGENT_CONFIG=…` overrides it for one session. | ||
| 61 | - config: | ||
| 62 | - default: "" | ||
| 63 | - description: >- | ||
| 64 | - Configuration file mm reads (its AGENT_CONFIG): a path relative to the | ||
| 65 | - workspace, which is where `sbx exec` starts mm, or an absolute path | ||
| 66 | - inside the sandbox. Empty: ./agent.yaml in the workspace, then the | ||
| 67 | - built-in defaults. | ||
| 68 | - env: AGENT_CONFIG | ||
| 69 | - | ||
| 70 | -capabilities: | ||
| 71 | - # A sandbox-agent workload — see kits/mm-tui/mm-tui.yaml. | ||
| 72 | - - type: com.docker.sandbox/sbx@1 | ||
| 73 | - | ||
| 74 | - # The model server on the host — see kits/mm-tui/mm-tui.yaml. | ||
| 75 | - - type: com.docker.sandbox/network-policy@1 | ||
| 76 | - config: | ||
| 77 | - runtime: | ||
| 78 | - allow: | ||
| 79 | - - "host.docker.internal:12434" | ||
| 80 | - - "localhost:12434" | ||
| 81 | - - "host.docker.internal:8080" | ||
| 82 | - - "localhost:8080" | ||
deleted
docker-sbx-v3/kits/mm-tui/mm-tui.dockerfile +0 -25 | deleted file mode 100644 | ||
| @@ -1,25 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | -# check=skip=InvalidDefaultArgInFrom | |
| 3 | -# Content of the mm-tui kit (descriptor: mm-tui.yaml). The kit's build context | |
| 4 | -# is this directory, so mm itself cannot be built here: the template image | |
| 5 | -# (docker-sbx-v3/template/Dockerfile, built from the repository root) carries | |
| 6 | -# mm, its wrappers and the toolchains, and this layer only sets the launch | |
| 7 | -# contract. No default on purpose (hence the skipped check above): the frontend | |
| 8 | -# always passes the kit's `image` and `tag` args, and a default here would be a | |
| 9 | -# second copy of the descriptor's to keep in sync. | |
| 10 | -ARG MM_IMAGE | |
| 11 | -ARG MM_TAG | |
| 12 | -FROM ${MM_IMAGE}:${MM_TAG} | |
| 13 | - | |
| 14 | -# v2's environment.variables. tcell needs a terminal type and a UTF-8 locale | |
| 15 | -# to draw the window. AGENT_CONFIG comes from the kit's `config` arg (env:). | |
| 16 | -ENV TERM=xterm-256color \ | |
| 17 | - COLORTERM=truecolor \ | |
| 18 | - LANG=C.UTF-8 | |
| 19 | - | |
| 20 | -# v2's sandbox.entrypoint. A wrapper, not `mm -tui` directly: it always adds | |
| 21 | -# -tui, whatever the user passes after "--". Setting ENTRYPOINT also drops the | |
| 22 | -# base template's CMD, so the launch argv is exactly mm-tui + the user's args. | |
| 23 | -# USER (agent) and WORKDIR (/home/agent/workspace) are inherited from the | |
| 24 | -# template, which is what sbx@1 reads. | |
| 25 | -ENTRYPOINT ["mm-tui"] | |
| deleted file mode 100644 | |||
| @@ -1,25 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | -# check=skip=InvalidDefaultArgInFrom | ||
| 3 | -# Content of the mm-tui kit (descriptor: mm-tui.yaml). The kit's build context | ||
| 4 | -# is this directory, so mm itself cannot be built here: the template image | ||
| 5 | -# (docker-sbx-v3/template/Dockerfile, built from the repository root) carries | ||
| 6 | -# mm, its wrappers and the toolchains, and this layer only sets the launch | ||
| 7 | -# contract. No default on purpose (hence the skipped check above): the frontend | ||
| 8 | -# always passes the kit's `image` and `tag` args, and a default here would be a | ||
| 9 | -# second copy of the descriptor's to keep in sync. | ||
| 10 | -ARG MM_IMAGE | ||
| 11 | -ARG MM_TAG | ||
| 12 | -FROM ${MM_IMAGE}:${MM_TAG} | ||
| 13 | - | ||
| 14 | -# v2's environment.variables. tcell needs a terminal type and a UTF-8 locale | ||
| 15 | -# to draw the window. AGENT_CONFIG comes from the kit's `config` arg (env:). | ||
| 16 | -ENV TERM=xterm-256color \ | ||
| 17 | - COLORTERM=truecolor \ | ||
| 18 | - LANG=C.UTF-8 | ||
| 19 | - | ||
| 20 | -# v2's sandbox.entrypoint. A wrapper, not `mm -tui` directly: it always adds | ||
| 21 | -# -tui, whatever the user passes after "--". Setting ENTRYPOINT also drops the | ||
| 22 | -# base template's CMD, so the launch argv is exactly mm-tui + the user's args. | ||
| 23 | -# USER (agent) and WORKDIR (/home/agent/workspace) are inherited from the | ||
| 24 | -# template, which is what sbx@1 reads. | ||
| 25 | -ENTRYPOINT ["mm-tui"] | ||
deleted
docker-sbx-v3/kits/mm-tui/mm-tui.yaml +0 -86 | deleted file mode 100644 | ||
| @@ -1,86 +0,0 @@ | ||
| 1 | -# syntax=docker/sandbox-kit:3 | |
| 2 | -# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/sandbox-kit-spec/main/schema/kit.schema.json | |
| 3 | -# | |
| 4 | -# Docker Sandboxes kit (spec v3): mm in its window mode, on the mm sandbox | |
| 5 | -# template. The v2 twin is docker-sbx/kits/mm-tui/spec.yaml. | |
| 6 | -# | |
| 7 | -# sbx run ./docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | |
| 8 | -# | |
| 9 | -# What follows "--" reaches mm as its own arguments (here the configuration | |
| 10 | -# file, relative to the workspace). Without it, the `config` argument below is | |
| 11 | -# read, then ./agent.yaml, then the built-in defaults: | |
| 12 | -# | |
| 13 | -# sbx run ./docker-sbx-v3/kits/mm-tui . --kit-arg config=agent.dmr.yaml | |
| 14 | -# | |
| 15 | -# v3 layout: this file is the descriptor (declarations only), mm-tui.dockerfile | |
| 16 | -# beside it is the content. What v2 wrote in `sandbox.image`, | |
| 17 | -# `sandbox.entrypoint` and `environment.variables` is now in that Dockerfile's | |
| 18 | -# FROM, ENTRYPOINT and ENV — the descriptor restates nothing the image config | |
| 19 | -# already carries. | |
| 20 | -# | |
| 21 | -# sbx builds this source form in its builder sandbox, whose own Docker engine | |
| 22 | -# PULLS the FROM image: <image>:<tag> must be on a registry, not only in the | |
| 23 | -# local image store (see docker-sbx-v3/README.md). | |
| 24 | -schemaVersion: "3" | |
| 25 | -kind: workload | |
| 26 | -displayName: Mini Me (window mode) | |
| 27 | -description: > | |
| 28 | - Runs mm, a minimal coding agent for local LLMs, in its single-window terminal | |
| 29 | - mode (`mm -tui`) on the workspace. The model server (Docker Model Runner or | |
| 30 | - llama-server) stays on the host: inside the sandbox `localhost` is the sandbox | |
| 31 | - itself, so the configuration file must reach the host through | |
| 32 | - host.docker.internal — agent.dmr.yaml already falls back to it. | |
| 33 | -sourceUrl: https://git.rickub.com/bots-garden/mini-me | |
| 34 | -# The kit's version is mm's: the image tag it is built on. A published kit is | |
| 35 | -# versioned by its OCI tag anyway, which wins over this field. | |
| 36 | -version: "${{ kit.args.tag }}" | |
| 37 | -provides: ["mm@${{ kit.args.tag }}"] | |
| 38 | - | |
| 39 | -args: | |
| 40 | - # Build-phase (buildArg): resolved when the kit is built, handed to | |
| 41 | - # mm-tui.dockerfile as --build-arg, and baked into the published descriptor. | |
| 42 | - # A published kit therefore always names the image it was built on. | |
| 43 | - image: | |
| 44 | - default: "k33g/mm-sandbox" | |
| 45 | - description: >- | |
| 46 | - Repository of the mm sandbox template image, without the tag. Kept equal | |
| 47 | - to <owner>/mm-sandbox by docker-sbx-v3/sync-kits.sh. | |
| 48 | - pattern: '^[a-z0-9][a-z0-9._/:-]*$' | |
| 49 | - buildArg: MM_IMAGE | |
| 50 | - tag: | |
| 51 | - default: "0.2.6" | |
| 52 | - description: >- | |
| 53 | - Tag of the template image: mm's version without the "v", as | |
| 54 | - docker-sbx-v3/build.sh tags it (and rewrites this default to). Also the | |
| 55 | - kit's version, hence version-shaped. | |
| 56 | - pattern: '^[0-9]+(\.[0-9A-Za-z-]+)*$' | |
| 57 | - buildArg: MM_TAG | |
| 58 | - # Create-phase (env): resolved at `sbx run` / `sbx create`, exported to the | |
| 59 | - # container. Private otherwise — an arg without env: never reaches it. | |
| 60 | - config: | |
| 61 | - default: "" | |
| 62 | - description: >- | |
| 63 | - Configuration file mm reads (its AGENT_CONFIG): a path relative to the | |
| 64 | - workspace, or an absolute path inside the sandbox. Empty: ./agent.yaml in | |
| 65 | - the workspace, then the built-in defaults. | |
| 66 | - env: AGENT_CONFIG | |
| 67 | - | |
| 68 | -capabilities: | |
| 69 | - # A sandbox-agent workload: the host launches the image ENTRYPOINT (mm-tui) | |
| 70 | - # under bash as the image's user (agent), and mounts the workspace at the | |
| 71 | - # image's WORKDIR, /home/agent/workspace. | |
| 72 | - - type: com.docker.sandbox/sbx@1 | |
| 73 | - | |
| 74 | - # The model server on the host. Requests leave the sandbox through its proxy, | |
| 75 | - # which maps host.docker.internal to the host's localhost; both spellings are | |
| 76 | - # listed so the rule matches whichever one the policy is checked against. | |
| 77 | - # 12434 is Docker Model Runner, 8080 is llama-server's default. Add your own | |
| 78 | - # port with `sbx policy allow network host.docker.internal:<port>`. | |
| 79 | - - type: com.docker.sandbox/network-policy@1 | |
| 80 | - config: | |
| 81 | - runtime: | |
| 82 | - allow: | |
| 83 | - - "host.docker.internal:12434" | |
| 84 | - - "localhost:12434" | |
| 85 | - - "host.docker.internal:8080" | |
| 86 | - - "localhost:8080" | |
| deleted file mode 100644 | |||
| @@ -1,86 +0,0 @@ | |||
| 1 | -# syntax=docker/sandbox-kit:3 | ||
| 2 | -# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/sandbox-kit-spec/main/schema/kit.schema.json | ||
| 3 | -# | ||
| 4 | -# Docker Sandboxes kit (spec v3): mm in its window mode, on the mm sandbox | ||
| 5 | -# template. The v2 twin is docker-sbx/kits/mm-tui/spec.yaml. | ||
| 6 | -# | ||
| 7 | -# sbx run ./docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | ||
| 8 | -# | ||
| 9 | -# What follows "--" reaches mm as its own arguments (here the configuration | ||
| 10 | -# file, relative to the workspace). Without it, the `config` argument below is | ||
| 11 | -# read, then ./agent.yaml, then the built-in defaults: | ||
| 12 | -# | ||
| 13 | -# sbx run ./docker-sbx-v3/kits/mm-tui . --kit-arg config=agent.dmr.yaml | ||
| 14 | -# | ||
| 15 | -# v3 layout: this file is the descriptor (declarations only), mm-tui.dockerfile | ||
| 16 | -# beside it is the content. What v2 wrote in `sandbox.image`, | ||
| 17 | -# `sandbox.entrypoint` and `environment.variables` is now in that Dockerfile's | ||
| 18 | -# FROM, ENTRYPOINT and ENV — the descriptor restates nothing the image config | ||
| 19 | -# already carries. | ||
| 20 | -# | ||
| 21 | -# sbx builds this source form in its builder sandbox, whose own Docker engine | ||
| 22 | -# PULLS the FROM image: <image>:<tag> must be on a registry, not only in the | ||
| 23 | -# local image store (see docker-sbx-v3/README.md). | ||
| 24 | -schemaVersion: "3" | ||
| 25 | -kind: workload | ||
| 26 | -displayName: Mini Me (window mode) | ||
| 27 | -description: > | ||
| 28 | - Runs mm, a minimal coding agent for local LLMs, in its single-window terminal | ||
| 29 | - mode (`mm -tui`) on the workspace. The model server (Docker Model Runner or | ||
| 30 | - llama-server) stays on the host: inside the sandbox `localhost` is the sandbox | ||
| 31 | - itself, so the configuration file must reach the host through | ||
| 32 | - host.docker.internal — agent.dmr.yaml already falls back to it. | ||
| 33 | -sourceUrl: https://git.rickub.com/bots-garden/mini-me | ||
| 34 | -# The kit's version is mm's: the image tag it is built on. A published kit is | ||
| 35 | -# versioned by its OCI tag anyway, which wins over this field. | ||
| 36 | -version: "${{ kit.args.tag }}" | ||
| 37 | -provides: ["mm@${{ kit.args.tag }}"] | ||
| 38 | - | ||
| 39 | -args: | ||
| 40 | - # Build-phase (buildArg): resolved when the kit is built, handed to | ||
| 41 | - # mm-tui.dockerfile as --build-arg, and baked into the published descriptor. | ||
| 42 | - # A published kit therefore always names the image it was built on. | ||
| 43 | - image: | ||
| 44 | - default: "k33g/mm-sandbox" | ||
| 45 | - description: >- | ||
| 46 | - Repository of the mm sandbox template image, without the tag. Kept equal | ||
| 47 | - to <owner>/mm-sandbox by docker-sbx-v3/sync-kits.sh. | ||
| 48 | - pattern: '^[a-z0-9][a-z0-9._/:-]*$' | ||
| 49 | - buildArg: MM_IMAGE | ||
| 50 | - tag: | ||
| 51 | - default: "0.2.6" | ||
| 52 | - description: >- | ||
| 53 | - Tag of the template image: mm's version without the "v", as | ||
| 54 | - docker-sbx-v3/build.sh tags it (and rewrites this default to). Also the | ||
| 55 | - kit's version, hence version-shaped. | ||
| 56 | - pattern: '^[0-9]+(\.[0-9A-Za-z-]+)*$' | ||
| 57 | - buildArg: MM_TAG | ||
| 58 | - # Create-phase (env): resolved at `sbx run` / `sbx create`, exported to the | ||
| 59 | - # container. Private otherwise — an arg without env: never reaches it. | ||
| 60 | - config: | ||
| 61 | - default: "" | ||
| 62 | - description: >- | ||
| 63 | - Configuration file mm reads (its AGENT_CONFIG): a path relative to the | ||
| 64 | - workspace, or an absolute path inside the sandbox. Empty: ./agent.yaml in | ||
| 65 | - the workspace, then the built-in defaults. | ||
| 66 | - env: AGENT_CONFIG | ||
| 67 | - | ||
| 68 | -capabilities: | ||
| 69 | - # A sandbox-agent workload: the host launches the image ENTRYPOINT (mm-tui) | ||
| 70 | - # under bash as the image's user (agent), and mounts the workspace at the | ||
| 71 | - # image's WORKDIR, /home/agent/workspace. | ||
| 72 | - - type: com.docker.sandbox/sbx@1 | ||
| 73 | - | ||
| 74 | - # The model server on the host. Requests leave the sandbox through its proxy, | ||
| 75 | - # which maps host.docker.internal to the host's localhost; both spellings are | ||
| 76 | - # listed so the rule matches whichever one the policy is checked against. | ||
| 77 | - # 12434 is Docker Model Runner, 8080 is llama-server's default. Add your own | ||
| 78 | - # port with `sbx policy allow network host.docker.internal:<port>`. | ||
| 79 | - - type: com.docker.sandbox/network-policy@1 | ||
| 80 | - config: | ||
| 81 | - runtime: | ||
| 82 | - allow: | ||
| 83 | - - "host.docker.internal:12434" | ||
| 84 | - - "localhost:12434" | ||
| 85 | - - "host.docker.internal:8080" | ||
| 86 | - - "localhost:8080" | ||
deleted
docker-sbx-v3/publish.sh +0 -75 | deleted file mode 100644 | ||
| @@ -1,75 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Build and publish everything to Docker Hub, by hand, in one go: | |
| 3 | -# <owner>/mm-sandbox:<version> the template image, linux/amd64 + linux/arm64 | |
| 4 | -# <owner>/sbx-kit-mm-tui:<version> the window-mode kit (v3) | |
| 5 | -# <owner>/sbx-kit-mm-acp:<version> the editor (ACP) kit (v3) | |
| 6 | -# | |
| 7 | -# Usage: | |
| 8 | -# ./docker-sbx-v3/publish.sh # TAG from release.env (v0.2.1 → 0.2.1) | |
| 9 | -# ./docker-sbx-v3/publish.sh v0.2.2 # another tag | |
| 10 | -# | |
| 11 | -# Credentials, two environment variables: | |
| 12 | -# DOCKER_HANDLE the Docker Hub account — also the image owner (default k33g) | |
| 13 | -# DOCKER_PAT an access token with read/write scope | |
| 14 | -# With both set, the script logs in with them (and out at the end). With | |
| 15 | -# neither, it uses the login you already have (`docker login` done earlier). | |
| 16 | -# | |
| 17 | -# Needs: docker with buildx (Docker Desktop has it). No sbx: v3 kits are | |
| 18 | -# published with buildx. Pieces, runnable alone: | |
| 19 | -# PUSH=1 ./docker-sbx-v3/build.sh TAG image only | |
| 20 | -# ./docker-sbx-v3/push-kits.sh TAG kits only | |
| 21 | -set -euo pipefail | |
| 22 | - | |
| 23 | -cd "$(dirname "$0")/.." | |
| 24 | - | |
| 25 | -if [ -f release.env ]; then | |
| 26 | - # shellcheck source=/dev/null | |
| 27 | - source release.env | |
| 28 | -fi | |
| 29 | -TAG="${1:-${TAG:-}}" | |
| 30 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 31 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx-v3/publish.sh v1.2.3)" | |
| 32 | - exit 1 | |
| 33 | -fi | |
| 34 | - | |
| 35 | -# Secrets pasted with a trailing newline or stray spaces are a classic. | |
| 36 | -DOCKER_HANDLE="$(printf '%s' "${DOCKER_HANDLE:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 37 | -DOCKER_PAT="$(printf '%s' "${DOCKER_PAT:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 38 | -case "${DOCKER_HANDLE}" in | |
| 39 | -*@* | *:*) | |
| 40 | - echo "❌ DOCKER_HANDLE must be the Docker ID (username), not an e-mail: access tokens only pair with the username" | |
| 41 | - exit 1 | |
| 42 | - ;; | |
| 43 | -esac | |
| 44 | -export IMAGE_OWNER="${IMAGE_OWNER:-${DOCKER_HANDLE:-k33g}}" | |
| 45 | -VERSION="${TAG#v}" | |
| 46 | - | |
| 47 | -logged_in_here="" | |
| 48 | -if [ -n "${DOCKER_HANDLE}" ] && [ -n "${DOCKER_PAT}" ]; then | |
| 49 | - echo "🔐 docker login as ${DOCKER_HANDLE}" | |
| 50 | - printf '%s' "${DOCKER_PAT}" | docker login --username "${DOCKER_HANDLE}" --password-stdin | |
| 51 | - logged_in_here=1 | |
| 52 | -elif [ -n "${DOCKER_HANDLE}${DOCKER_PAT}" ]; then | |
| 53 | - echo "❌ set both DOCKER_HANDLE and DOCKER_PAT, or neither (to reuse an existing docker login)" | |
| 54 | - exit 1 | |
| 55 | -else | |
| 56 | - echo "🔐 no DOCKER_HANDLE/DOCKER_PAT: using the existing docker login, publishing under ${IMAGE_OWNER}" | |
| 57 | -fi | |
| 58 | -# Whatever happens below, a login made here does not outlive the script. | |
| 59 | -cleanup() { | |
| 60 | - if [ -n "${logged_in_here}" ]; then | |
| 61 | - docker logout >/dev/null 2>&1 || true | |
| 62 | - fi | |
| 63 | -} | |
| 64 | -trap cleanup EXIT | |
| 65 | - | |
| 66 | -echo | |
| 67 | -echo "═══ 1/2 image ${IMAGE_OWNER}/mm-sandbox:${VERSION}" | |
| 68 | -PUSH=1 ./docker-sbx-v3/build.sh "${TAG}" | |
| 69 | - | |
| 70 | -echo | |
| 71 | -echo "═══ 2/2 kits ${IMAGE_OWNER}/${KIT_PREFIX:-sbx-kit-}mm-tui:${VERSION} and ${IMAGE_OWNER}/${KIT_PREFIX:-sbx-kit-}mm-acp:${VERSION}" | |
| 72 | -./docker-sbx-v3/push-kits.sh "${TAG}" | |
| 73 | - | |
| 74 | -echo | |
| 75 | -echo "✨ Published ${TAG}. The kits' descriptors now name version ${VERSION} — commit them." | |
| deleted file mode 100644 | |||
| @@ -1,75 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Build and publish everything to Docker Hub, by hand, in one go: | ||
| 3 | -# <owner>/mm-sandbox:<version> the template image, linux/amd64 + linux/arm64 | ||
| 4 | -# <owner>/sbx-kit-mm-tui:<version> the window-mode kit (v3) | ||
| 5 | -# <owner>/sbx-kit-mm-acp:<version> the editor (ACP) kit (v3) | ||
| 6 | -# | ||
| 7 | -# Usage: | ||
| 8 | -# ./docker-sbx-v3/publish.sh # TAG from release.env (v0.2.1 → 0.2.1) | ||
| 9 | -# ./docker-sbx-v3/publish.sh v0.2.2 # another tag | ||
| 10 | -# | ||
| 11 | -# Credentials, two environment variables: | ||
| 12 | -# DOCKER_HANDLE the Docker Hub account — also the image owner (default k33g) | ||
| 13 | -# DOCKER_PAT an access token with read/write scope | ||
| 14 | -# With both set, the script logs in with them (and out at the end). With | ||
| 15 | -# neither, it uses the login you already have (`docker login` done earlier). | ||
| 16 | -# | ||
| 17 | -# Needs: docker with buildx (Docker Desktop has it). No sbx: v3 kits are | ||
| 18 | -# published with buildx. Pieces, runnable alone: | ||
| 19 | -# PUSH=1 ./docker-sbx-v3/build.sh TAG image only | ||
| 20 | -# ./docker-sbx-v3/push-kits.sh TAG kits only | ||
| 21 | -set -euo pipefail | ||
| 22 | - | ||
| 23 | -cd "$(dirname "$0")/.." | ||
| 24 | - | ||
| 25 | -if [ -f release.env ]; then | ||
| 26 | - # shellcheck source=/dev/null | ||
| 27 | - source release.env | ||
| 28 | -fi | ||
| 29 | -TAG="${1:-${TAG:-}}" | ||
| 30 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 31 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx-v3/publish.sh v1.2.3)" | ||
| 32 | - exit 1 | ||
| 33 | -fi | ||
| 34 | - | ||
| 35 | -# Secrets pasted with a trailing newline or stray spaces are a classic. | ||
| 36 | -DOCKER_HANDLE="$(printf '%s' "${DOCKER_HANDLE:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 37 | -DOCKER_PAT="$(printf '%s' "${DOCKER_PAT:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 38 | -case "${DOCKER_HANDLE}" in | ||
| 39 | -*@* | *:*) | ||
| 40 | - echo "❌ DOCKER_HANDLE must be the Docker ID (username), not an e-mail: access tokens only pair with the username" | ||
| 41 | - exit 1 | ||
| 42 | - ;; | ||
| 43 | -esac | ||
| 44 | -export IMAGE_OWNER="${IMAGE_OWNER:-${DOCKER_HANDLE:-k33g}}" | ||
| 45 | -VERSION="${TAG#v}" | ||
| 46 | - | ||
| 47 | -logged_in_here="" | ||
| 48 | -if [ -n "${DOCKER_HANDLE}" ] && [ -n "${DOCKER_PAT}" ]; then | ||
| 49 | - echo "🔐 docker login as ${DOCKER_HANDLE}" | ||
| 50 | - printf '%s' "${DOCKER_PAT}" | docker login --username "${DOCKER_HANDLE}" --password-stdin | ||
| 51 | - logged_in_here=1 | ||
| 52 | -elif [ -n "${DOCKER_HANDLE}${DOCKER_PAT}" ]; then | ||
| 53 | - echo "❌ set both DOCKER_HANDLE and DOCKER_PAT, or neither (to reuse an existing docker login)" | ||
| 54 | - exit 1 | ||
| 55 | -else | ||
| 56 | - echo "🔐 no DOCKER_HANDLE/DOCKER_PAT: using the existing docker login, publishing under ${IMAGE_OWNER}" | ||
| 57 | -fi | ||
| 58 | -# Whatever happens below, a login made here does not outlive the script. | ||
| 59 | -cleanup() { | ||
| 60 | - if [ -n "${logged_in_here}" ]; then | ||
| 61 | - docker logout >/dev/null 2>&1 || true | ||
| 62 | - fi | ||
| 63 | -} | ||
| 64 | -trap cleanup EXIT | ||
| 65 | - | ||
| 66 | -echo | ||
| 67 | -echo "═══ 1/2 image ${IMAGE_OWNER}/mm-sandbox:${VERSION}" | ||
| 68 | -PUSH=1 ./docker-sbx-v3/build.sh "${TAG}" | ||
| 69 | - | ||
| 70 | -echo | ||
| 71 | -echo "═══ 2/2 kits ${IMAGE_OWNER}/${KIT_PREFIX:-sbx-kit-}mm-tui:${VERSION} and ${IMAGE_OWNER}/${KIT_PREFIX:-sbx-kit-}mm-acp:${VERSION}" | ||
| 72 | -./docker-sbx-v3/push-kits.sh "${TAG}" | ||
| 73 | - | ||
| 74 | -echo | ||
| 75 | -echo "✨ Published ${TAG}. The kits' descriptors now name version ${VERSION} — commit them." | ||
deleted
docker-sbx-v3/push-kits.sh +0 -94 | deleted file mode 100644 | ||
| @@ -1,94 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Build and publish the two v3 kits to Docker Hub: | |
| 3 | -# <owner>/sbx-kit-mm-tui:<version> and <owner>/sbx-kit-mm-acp:<version> | |
| 4 | -# | |
| 5 | -# Usage: | |
| 6 | -# ./docker-sbx-v3/push-kits.sh # TAG from release.env | |
| 7 | -# ./docker-sbx-v3/push-kits.sh v0.2.2 # override the tag | |
| 8 | -# IMAGE_OWNER=someone … # another owner (default k33g); the kits | |
| 9 | -# # are re-pointed at someone/mm-sandbox too | |
| 10 | -# REGISTRY=localhost:5000 … # another registry (default docker.io) | |
| 11 | -# KIT_PREFIX=mm-v3- … # repository prefix (default sbx-kit-) | |
| 12 | -# PLATFORMS=linux/amd64 … # narrower multi-arch set | |
| 13 | -# | |
| 14 | -# A v3 kit is an ordinary OCI image, so publishing is a buildx build: the | |
| 15 | -# descriptor's `# syntax=docker/sandbox-kit:3` line makes BuildKit run the kit | |
| 16 | -# frontend, which validates the descriptor, builds the companion Dockerfile | |
| 17 | -# FROM <owner>/mm-sandbox:<version> and pushes one image per platform with the | |
| 18 | -# descriptor in its manifest annotations. No sbx needed (v2 used | |
| 19 | -# `sbx kit push`, which only knows spec.yaml). | |
| 20 | -# | |
| 21 | -# The repositories are sbx-kit-<kit>, the naming Docker's own kits use, and | |
| 22 | -# NOT the v2 ones (<owner>/mm-tui, <owner>/mm-acp): pushing a v3 kit there at | |
| 23 | -# the same version would replace the published v2 kit. | |
| 24 | -# | |
| 25 | -# Needs a login: `docker login -u <handle>` with a Docker Hub access token. | |
| 26 | -# publish.sh runs this after the image. Push the image first: the kits are | |
| 27 | -# built FROM <owner>/mm-sandbox:<version>, pulled from the registry. | |
| 28 | -set -euo pipefail | |
| 29 | - | |
| 30 | -cd "$(dirname "$0")/.." | |
| 31 | - | |
| 32 | -if [ -f release.env ]; then | |
| 33 | - # shellcheck source=/dev/null | |
| 34 | - source release.env | |
| 35 | -fi | |
| 36 | -TAG="${1:-${TAG:-}}" | |
| 37 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 38 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx-v3/push-kits.sh v1.2.3)" | |
| 39 | - exit 1 | |
| 40 | -fi | |
| 41 | - | |
| 42 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | |
| 43 | -REGISTRY="${REGISTRY:-docker.io}" | |
| 44 | -KIT_PREFIX="${KIT_PREFIX:-sbx-kit-}" | |
| 45 | -PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | |
| 46 | -VERSION="${TAG#v}" | |
| 47 | -IMAGE="${IMAGE_OWNER}/mm-sandbox:${VERSION}" | |
| 48 | - | |
| 49 | -# Fail here rather than in the middle of a multi-arch build. | |
| 50 | -if ! docker buildx imagetools inspect "${IMAGE}" >/dev/null 2>&1; then | |
| 51 | - echo "❌ ${IMAGE} is not on the registry: the kits are built FROM it. Push it first: PUSH=1 ./docker-sbx-v3/build.sh ${TAG}" | |
| 52 | - exit 1 | |
| 53 | -fi | |
| 54 | - | |
| 55 | -./docker-sbx-v3/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | |
| 56 | - | |
| 57 | -# Same builder as build.sh: multi-arch needs the container driver. | |
| 58 | -if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | |
| 59 | - docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | |
| 60 | -fi | |
| 61 | - | |
| 62 | -refs=() | |
| 63 | -for dir in docker-sbx-v3/kits/*/; do | |
| 64 | - kit="$(basename "${dir}")" | |
| 65 | - ref="${REGISTRY}/${IMAGE_OWNER}/${KIT_PREFIX}${kit}:${VERSION}" | |
| 66 | - echo "🧰 ${kit} → ${ref}" | |
| 67 | - # The build args are the kit's own arg names; the frontend validates them | |
| 68 | - # against the descriptor and hands the Dockerfile the declared buildArg. | |
| 69 | - # They repeat what sync-kits.sh just wrote, so the file and the push agree. | |
| 70 | - docker buildx build --builder mm-sandbox-builder "${dir}" -f "${dir}${kit}.yaml" \ | |
| 71 | - --build-arg "image=${IMAGE_OWNER}/mm-sandbox" \ | |
| 72 | - --build-arg "tag=${VERSION}" \ | |
| 73 | - --platform "${PLATFORMS}" \ | |
| 74 | - --provenance=true --sbom=true \ | |
| 75 | - -t "${ref}" --push | |
| 76 | - docker buildx imagetools inspect "${ref}" | grep -E '^Name:|Platform:' | sed 's/^/ /' | |
| 77 | - refs+=("${ref}") | |
| 78 | -done | |
| 79 | - | |
| 80 | -# The specification's own check of what was pushed, when available. | |
| 81 | -if command -v "${KIT_TCK:-kit-tck}" >/dev/null 2>&1; then | |
| 82 | - for ref in "${refs[@]}"; do | |
| 83 | - "${KIT_TCK:-kit-tck}" validate "${ref}" | |
| 84 | - done | |
| 85 | -fi | |
| 86 | - | |
| 87 | -cat <<NEXT | |
| 88 | - | |
| 89 | -Published. From any machine with Docker Sandboxes (docker.io is an allowed kit source by default): | |
| 90 | - | |
| 91 | - window mode sbx run ${IMAGE_OWNER}/${KIT_PREFIX}mm-tui:${VERSION} . -- agent.dmr.yaml | |
| 92 | - editor (ACP) sbx create --name mm-acp ${IMAGE_OWNER}/${KIT_PREFIX}mm-acp:${VERSION} . --kit-arg config=agent.dmr.yaml | |
| 93 | - then register sbx exec -i mm-acp mm -acp in the editor | |
| 94 | -NEXT | |
| deleted file mode 100644 | |||
| @@ -1,94 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Build and publish the two v3 kits to Docker Hub: | ||
| 3 | -# <owner>/sbx-kit-mm-tui:<version> and <owner>/sbx-kit-mm-acp:<version> | ||
| 4 | -# | ||
| 5 | -# Usage: | ||
| 6 | -# ./docker-sbx-v3/push-kits.sh # TAG from release.env | ||
| 7 | -# ./docker-sbx-v3/push-kits.sh v0.2.2 # override the tag | ||
| 8 | -# IMAGE_OWNER=someone … # another owner (default k33g); the kits | ||
| 9 | -# # are re-pointed at someone/mm-sandbox too | ||
| 10 | -# REGISTRY=localhost:5000 … # another registry (default docker.io) | ||
| 11 | -# KIT_PREFIX=mm-v3- … # repository prefix (default sbx-kit-) | ||
| 12 | -# PLATFORMS=linux/amd64 … # narrower multi-arch set | ||
| 13 | -# | ||
| 14 | -# A v3 kit is an ordinary OCI image, so publishing is a buildx build: the | ||
| 15 | -# descriptor's `# syntax=docker/sandbox-kit:3` line makes BuildKit run the kit | ||
| 16 | -# frontend, which validates the descriptor, builds the companion Dockerfile | ||
| 17 | -# FROM <owner>/mm-sandbox:<version> and pushes one image per platform with the | ||
| 18 | -# descriptor in its manifest annotations. No sbx needed (v2 used | ||
| 19 | -# `sbx kit push`, which only knows spec.yaml). | ||
| 20 | -# | ||
| 21 | -# The repositories are sbx-kit-<kit>, the naming Docker's own kits use, and | ||
| 22 | -# NOT the v2 ones (<owner>/mm-tui, <owner>/mm-acp): pushing a v3 kit there at | ||
| 23 | -# the same version would replace the published v2 kit. | ||
| 24 | -# | ||
| 25 | -# Needs a login: `docker login -u <handle>` with a Docker Hub access token. | ||
| 26 | -# publish.sh runs this after the image. Push the image first: the kits are | ||
| 27 | -# built FROM <owner>/mm-sandbox:<version>, pulled from the registry. | ||
| 28 | -set -euo pipefail | ||
| 29 | - | ||
| 30 | -cd "$(dirname "$0")/.." | ||
| 31 | - | ||
| 32 | -if [ -f release.env ]; then | ||
| 33 | - # shellcheck source=/dev/null | ||
| 34 | - source release.env | ||
| 35 | -fi | ||
| 36 | -TAG="${1:-${TAG:-}}" | ||
| 37 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 38 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx-v3/push-kits.sh v1.2.3)" | ||
| 39 | - exit 1 | ||
| 40 | -fi | ||
| 41 | - | ||
| 42 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | ||
| 43 | -REGISTRY="${REGISTRY:-docker.io}" | ||
| 44 | -KIT_PREFIX="${KIT_PREFIX:-sbx-kit-}" | ||
| 45 | -PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | ||
| 46 | -VERSION="${TAG#v}" | ||
| 47 | -IMAGE="${IMAGE_OWNER}/mm-sandbox:${VERSION}" | ||
| 48 | - | ||
| 49 | -# Fail here rather than in the middle of a multi-arch build. | ||
| 50 | -if ! docker buildx imagetools inspect "${IMAGE}" >/dev/null 2>&1; then | ||
| 51 | - echo "❌ ${IMAGE} is not on the registry: the kits are built FROM it. Push it first: PUSH=1 ./docker-sbx-v3/build.sh ${TAG}" | ||
| 52 | - exit 1 | ||
| 53 | -fi | ||
| 54 | - | ||
| 55 | -./docker-sbx-v3/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | ||
| 56 | - | ||
| 57 | -# Same builder as build.sh: multi-arch needs the container driver. | ||
| 58 | -if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | ||
| 59 | - docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | ||
| 60 | -fi | ||
| 61 | - | ||
| 62 | -refs=() | ||
| 63 | -for dir in docker-sbx-v3/kits/*/; do | ||
| 64 | - kit="$(basename "${dir}")" | ||
| 65 | - ref="${REGISTRY}/${IMAGE_OWNER}/${KIT_PREFIX}${kit}:${VERSION}" | ||
| 66 | - echo "🧰 ${kit} → ${ref}" | ||
| 67 | - # The build args are the kit's own arg names; the frontend validates them | ||
| 68 | - # against the descriptor and hands the Dockerfile the declared buildArg. | ||
| 69 | - # They repeat what sync-kits.sh just wrote, so the file and the push agree. | ||
| 70 | - docker buildx build --builder mm-sandbox-builder "${dir}" -f "${dir}${kit}.yaml" \ | ||
| 71 | - --build-arg "image=${IMAGE_OWNER}/mm-sandbox" \ | ||
| 72 | - --build-arg "tag=${VERSION}" \ | ||
| 73 | - --platform "${PLATFORMS}" \ | ||
| 74 | - --provenance=true --sbom=true \ | ||
| 75 | - -t "${ref}" --push | ||
| 76 | - docker buildx imagetools inspect "${ref}" | grep -E '^Name:|Platform:' | sed 's/^/ /' | ||
| 77 | - refs+=("${ref}") | ||
| 78 | -done | ||
| 79 | - | ||
| 80 | -# The specification's own check of what was pushed, when available. | ||
| 81 | -if command -v "${KIT_TCK:-kit-tck}" >/dev/null 2>&1; then | ||
| 82 | - for ref in "${refs[@]}"; do | ||
| 83 | - "${KIT_TCK:-kit-tck}" validate "${ref}" | ||
| 84 | - done | ||
| 85 | -fi | ||
| 86 | - | ||
| 87 | -cat <<NEXT | ||
| 88 | - | ||
| 89 | -Published. From any machine with Docker Sandboxes (docker.io is an allowed kit source by default): | ||
| 90 | - | ||
| 91 | - window mode sbx run ${IMAGE_OWNER}/${KIT_PREFIX}mm-tui:${VERSION} . -- agent.dmr.yaml | ||
| 92 | - editor (ACP) sbx create --name mm-acp ${IMAGE_OWNER}/${KIT_PREFIX}mm-acp:${VERSION} . --kit-arg config=agent.dmr.yaml | ||
| 93 | - then register sbx exec -i mm-acp mm -acp in the editor | ||
| 94 | -NEXT | ||
deleted
docker-sbx-v3/sync-kits.sh +0 -44 | deleted file mode 100644 | ||
| @@ -1,44 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Point the two v3 kits at one image: <owner>/mm-sandbox:<version>. | |
| 3 | -# | |
| 4 | -# Usage: ./docker-sbx-v3/sync-kits.sh OWNER VERSION (e.g. k33g 0.2.1) | |
| 5 | -# | |
| 6 | -# Rewrites, in docker-sbx-v3/kits/*/*.yaml (the descriptors), only two values: | |
| 7 | -# args.image.default: "<owner>/mm-sandbox" which repository the kit is built FROM | |
| 8 | -# args.tag.default: "<version>" which tag — and the kit's version, | |
| 9 | -# since `version:` and `provides:` | |
| 10 | -# reference ${{ kit.args.tag }} | |
| 11 | -# Everything else — comments included — is left byte-for-byte alone, so a | |
| 12 | -# kit that already matches is not changed at all. build.sh and push-kits.sh | |
| 13 | -# call this, so the kits always name the image just built or pushed. | |
| 14 | -set -euo pipefail | |
| 15 | - | |
| 16 | -if [ $# -ne 2 ]; then | |
| 17 | - echo "usage: $0 OWNER VERSION" >&2 | |
| 18 | - exit 2 | |
| 19 | -fi | |
| 20 | -OWNER="$1" | |
| 21 | -VERSION="$2" | |
| 22 | - | |
| 23 | -# The kits' `tag` arg is also their version, so it carries the spec's version | |
| 24 | -# grammar: dotted segments, no "v" (the frontend refuses anything else). | |
| 25 | -if ! [[ "${VERSION}" =~ ^[0-9]+(\.[0-9A-Za-z-]+)*$ ]]; then | |
| 26 | - echo "❌ VERSION must be version-shaped without a \"v\" (0.2.1, 0.2.2-rc.1), got '${VERSION}'" >&2 | |
| 27 | - exit 2 | |
| 28 | -fi | |
| 29 | - | |
| 30 | -cd "$(dirname "$0")/.." | |
| 31 | - | |
| 32 | -for kit in docker-sbx-v3/kits/*/*.yaml; do | |
| 33 | - if ! grep -q '^ image:$' "${kit}" || ! grep -q '^ tag:$' "${kit}"; then | |
| 34 | - echo "❌ ${kit}: expected an 'args.image' and an 'args.tag' — not updated" >&2 | |
| 35 | - exit 1 | |
| 36 | - fi | |
| 37 | - # sed -i.bak works on both GNU and BSD sed; the backup is removed at once. | |
| 38 | - sed -i.bak -E \ | |
| 39 | - -e "/^ image:\$/,/^ default:/ s|^( default: )\"[^\"/]*(/mm-sandbox)\"|\1\"${OWNER}\2\"|" \ | |
| 40 | - -e "/^ tag:\$/,/^ default:/ s|^( default: )\"[^\"]*\"|\1\"${VERSION}\"|" \ | |
| 41 | - "${kit}" | |
| 42 | - rm -f "${kit}.bak" | |
| 43 | - echo "✅ ${kit} → image ${OWNER}/mm-sandbox, tag (and version) \"${VERSION}\"" | |
| 44 | -done | |
| deleted file mode 100644 | |||
| @@ -1,44 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Point the two v3 kits at one image: <owner>/mm-sandbox:<version>. | ||
| 3 | -# | ||
| 4 | -# Usage: ./docker-sbx-v3/sync-kits.sh OWNER VERSION (e.g. k33g 0.2.1) | ||
| 5 | -# | ||
| 6 | -# Rewrites, in docker-sbx-v3/kits/*/*.yaml (the descriptors), only two values: | ||
| 7 | -# args.image.default: "<owner>/mm-sandbox" which repository the kit is built FROM | ||
| 8 | -# args.tag.default: "<version>" which tag — and the kit's version, | ||
| 9 | -# since `version:` and `provides:` | ||
| 10 | -# reference ${{ kit.args.tag }} | ||
| 11 | -# Everything else — comments included — is left byte-for-byte alone, so a | ||
| 12 | -# kit that already matches is not changed at all. build.sh and push-kits.sh | ||
| 13 | -# call this, so the kits always name the image just built or pushed. | ||
| 14 | -set -euo pipefail | ||
| 15 | - | ||
| 16 | -if [ $# -ne 2 ]; then | ||
| 17 | - echo "usage: $0 OWNER VERSION" >&2 | ||
| 18 | - exit 2 | ||
| 19 | -fi | ||
| 20 | -OWNER="$1" | ||
| 21 | -VERSION="$2" | ||
| 22 | - | ||
| 23 | -# The kits' `tag` arg is also their version, so it carries the spec's version | ||
| 24 | -# grammar: dotted segments, no "v" (the frontend refuses anything else). | ||
| 25 | -if ! [[ "${VERSION}" =~ ^[0-9]+(\.[0-9A-Za-z-]+)*$ ]]; then | ||
| 26 | - echo "❌ VERSION must be version-shaped without a \"v\" (0.2.1, 0.2.2-rc.1), got '${VERSION}'" >&2 | ||
| 27 | - exit 2 | ||
| 28 | -fi | ||
| 29 | - | ||
| 30 | -cd "$(dirname "$0")/.." | ||
| 31 | - | ||
| 32 | -for kit in docker-sbx-v3/kits/*/*.yaml; do | ||
| 33 | - if ! grep -q '^ image:$' "${kit}" || ! grep -q '^ tag:$' "${kit}"; then | ||
| 34 | - echo "❌ ${kit}: expected an 'args.image' and an 'args.tag' — not updated" >&2 | ||
| 35 | - exit 1 | ||
| 36 | - fi | ||
| 37 | - # sed -i.bak works on both GNU and BSD sed; the backup is removed at once. | ||
| 38 | - sed -i.bak -E \ | ||
| 39 | - -e "/^ image:\$/,/^ default:/ s|^( default: )\"[^\"/]*(/mm-sandbox)\"|\1\"${OWNER}\2\"|" \ | ||
| 40 | - -e "/^ tag:\$/,/^ default:/ s|^( default: )\"[^\"]*\"|\1\"${VERSION}\"|" \ | ||
| 41 | - "${kit}" | ||
| 42 | - rm -f "${kit}.bak" | ||
| 43 | - echo "✅ ${kit} → image ${OWNER}/mm-sandbox, tag (and version) \"${VERSION}\"" | ||
| 44 | -done | ||
deleted
docker-sbx-v3/template/Dockerfile +0 -143 | deleted file mode 100644 | ||
| @@ -1,143 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | -# | |
| 3 | -# The mm sandbox template: Docker Sandboxes' `shell` image with mm installed. | |
| 4 | -# | |
| 5 | -# Build it from the REPOSITORY ROOT (the context is the mm sources), or run | |
| 6 | -# docker-sbx-v3/build.sh, which does exactly that and stamps mm's tag — the | |
| 7 | -# image tag is that tag without the "v", k33g/mm-sandbox:0.0.2 for v0.0.2: | |
| 8 | -# | |
| 9 | -# docker build -f docker-sbx-v3/template/Dockerfile \ | |
| 10 | -# --build-arg MM_VERSION=v0.0.2 -t k33g/mm-sandbox:0.0.2 . | |
| 11 | -# | |
| 12 | -# The two v3 kits under docker-sbx-v3/kits/ are thin workloads built FROM this | |
| 13 | -# image: each one sets its own ENTRYPOINT (mm-tui, mm-acp-info), which the | |
| 14 | -# sandbox runtime reads as the agent's launch command (sbx@1). ENTRYPOINT and | |
| 15 | -# CMD are therefore deliberately not set here: the template stays agnostic. | |
| 16 | - | |
| 17 | -ARG GO_VERSION=1.26 | |
| 18 | -ARG SHELL_TEMPLATE=docker/sandbox-templates:shell | |
| 19 | - | |
| 20 | -# ---- build stage: cross-compile mm for the target platform ----------------- | |
| 21 | -FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build | |
| 22 | -ARG TARGETOS | |
| 23 | -ARG TARGETARCH | |
| 24 | -# What `mm --version` reports: the tag, as 02-build-releases.sh stamps it. | |
| 25 | -ARG MM_VERSION=dev | |
| 26 | - | |
| 27 | -WORKDIR /src | |
| 28 | -COPY go.mod go.sum ./ | |
| 29 | -RUN --mount=type=cache,target=/go/pkg/mod go mod download | |
| 30 | -COPY . . | |
| 31 | -# Same flags as 02-build-releases.sh: no C, no local paths, no symbols, the | |
| 32 | -# version stamped into internal/version. | |
| 33 | -RUN --mount=type=cache,target=/go/pkg/mod \ | |
| 34 | - --mount=type=cache,target=/root/.cache/go-build \ | |
| 35 | - CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ | |
| 36 | - go build -trimpath -ldflags "-s -w -X mm/internal/version.stamped=${MM_VERSION}" -o /out/mm . | |
| 37 | - | |
| 38 | -# ---- template: the shell sandbox plus mm ----------------------------------- | |
| 39 | -FROM ${SHELL_TEMPLATE} | |
| 40 | - | |
| 41 | -COPY --from=build --chmod=0755 /out/mm /usr/local/bin/mm | |
| 42 | -# The two kit entry points. mm-tui runs `mm -tui "$@"`; mm-acp-info prints how | |
| 43 | -# an editor reaches this sandbox and opens a shell (see docker-sbx-v3/README.md). | |
| 44 | -COPY --chmod=0755 docker-sbx-v3/template/mm-tui docker-sbx-v3/template/mm-acp-info /usr/local/bin/ | |
| 45 | - | |
| 46 | -# tcell (the window mode) needs a terminal type and a UTF-8 locale; the kits | |
| 47 | -# set them too, this is the fallback for a plain `docker run`. | |
| 48 | -ENV TERM=xterm-256color \ | |
| 49 | - COLORTERM=truecolor \ | |
| 50 | - LANG=C.UTF-8 | |
| 51 | - | |
| 52 | -# The pinned toolchains (/usr/local/go/bin, /usr/local/node/bin) must come | |
| 53 | -# before /usr/bin so they win over any Go or Node the base image ships. | |
| 54 | -ENV PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH | |
| 55 | - | |
| 56 | -# Without this, a go.mod whose `go` directive is newer than GO_VERSION makes the | |
| 57 | -# toolchain download and run a different Go, silently defeating the pin. | |
| 58 | -ENV GOTOOLCHAIN=local | |
| 59 | - | |
| 60 | -# ------------------------------------ | |
| 61 | -# Shared curl options for every download below. | |
| 62 | -# | |
| 63 | -# ARG, not ENV: this is build-time only and must not leak into the image. | |
| 64 | -# ------------------------------------ | |
| 65 | -ARG CURL_RETRY="--retry 5 --retry-all-errors --retry-delay 3 --connect-timeout 15" | |
| 66 | - | |
| 67 | -USER root | |
| 68 | - | |
| 69 | -# ------------------------------------ | |
| 70 | -# Install Go toolchain and Node.js | |
| 71 | -# ------------------------------------ | |
| 72 | -ARG GO_VERSION=1.26.0 | |
| 73 | -ARG NODE_VERSION=24.21.0 | |
| 74 | -ARG TARGETARCH | |
| 75 | - | |
| 76 | -RUN <<EOF | |
| 77 | -set -eux | |
| 78 | -apt-get update | |
| 79 | -apt-get install -y curl build-essential xz-utils | |
| 80 | -rm -rf /var/lib/apt/lists/* | |
| 81 | -EOF | |
| 82 | - | |
| 83 | -RUN <<EOF | |
| 84 | -set -eux | |
| 85 | -apt-get remove -y golang-go golang-doc | |
| 86 | -apt-get autoremove -y | |
| 87 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/go.tgz "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" | |
| 88 | -rm -rf /usr/local/go | |
| 89 | -tar -C /usr/local -xzf /tmp/go.tgz | |
| 90 | -rm /tmp/go.tgz | |
| 91 | -/usr/local/go/bin/go version | |
| 92 | -EOF | |
| 93 | - | |
| 94 | -RUN <<EOF | |
| 95 | -set -eux | |
| 96 | -case "${TARGETARCH}" in | |
| 97 | - amd64) node_arch=x64 ;; | |
| 98 | - arm64) node_arch=arm64 ;; | |
| 99 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | |
| 100 | -esac | |
| 101 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/node.tar.xz "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_arch}.tar.xz" | |
| 102 | -rm -rf /usr/local/node | |
| 103 | -mkdir -p /usr/local/node | |
| 104 | -tar -C /usr/local/node --strip-components=1 -xJf /tmp/node.tar.xz | |
| 105 | -rm /tmp/node.tar.xz | |
| 106 | -/usr/local/node/bin/node --version | |
| 107 | -/usr/local/node/bin/npm --version | |
| 108 | -EOF | |
| 109 | - | |
| 110 | -# ------------------------------------ | |
| 111 | -# Persist the Go and Node environment for sandbox shells. | |
| 112 | -# /etc/sandbox-persistent.sh is sourced before every bash command in the sbx. | |
| 113 | -# ------------------------------------ | |
| 114 | -RUN <<EOF | |
| 115 | -{ | |
| 116 | - echo 'export PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH' | |
| 117 | - echo 'export GOTOOLCHAIN=local' | |
| 118 | -} >> /etc/sandbox-persistent.sh | |
| 119 | -EOF | |
| 120 | - | |
| 121 | -# Switch to agent user for Go tools installation (they go to /home/agent/go/bin) | |
| 122 | -USER agent | |
| 123 | - | |
| 124 | -# ------------------------------------ | |
| 125 | -# Install Go developer tools | |
| 126 | -# ------------------------------------ | |
| 127 | -ARG GOPLS_VERSION=v0.23.0 | |
| 128 | -ARG X_TOOLS_VERSION=v0.49.0 | |
| 129 | -ARG STATICCHECK_VERSION=v0.7.0 | |
| 130 | - | |
| 131 | -# Retried: parallel multi-arch builds occasionally hit DNS timeouts on | |
| 132 | -# Docker Desktop's resolver. The module cache survives within this RUN, | |
| 133 | -# so a retry only fetches what's still missing. | |
| 134 | -RUN for i in 1 2 3 4 5; do \ | |
| 135 | - go install golang.org/x/tools/gopls@${GOPLS_VERSION} \ | |
| 136 | - && go install golang.org/x/tools/cmd/goimports@${X_TOOLS_VERSION} \ | |
| 137 | - && go install honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION} \ | |
| 138 | - && exit 0; \ | |
| 139 | - echo "go install failed (attempt $i), retrying..." >&2; sleep $((i * 5)); \ | |
| 140 | - done; exit 1 | |
| 141 | - | |
| 142 | -# Prove the binary runs on this platform before the image is tagged. | |
| 143 | -RUN mm --version && mm-tui --version | |
| deleted file mode 100644 | |||
| @@ -1,143 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | -# | ||
| 3 | -# The mm sandbox template: Docker Sandboxes' `shell` image with mm installed. | ||
| 4 | -# | ||
| 5 | -# Build it from the REPOSITORY ROOT (the context is the mm sources), or run | ||
| 6 | -# docker-sbx-v3/build.sh, which does exactly that and stamps mm's tag — the | ||
| 7 | -# image tag is that tag without the "v", k33g/mm-sandbox:0.0.2 for v0.0.2: | ||
| 8 | -# | ||
| 9 | -# docker build -f docker-sbx-v3/template/Dockerfile \ | ||
| 10 | -# --build-arg MM_VERSION=v0.0.2 -t k33g/mm-sandbox:0.0.2 . | ||
| 11 | -# | ||
| 12 | -# The two v3 kits under docker-sbx-v3/kits/ are thin workloads built FROM this | ||
| 13 | -# image: each one sets its own ENTRYPOINT (mm-tui, mm-acp-info), which the | ||
| 14 | -# sandbox runtime reads as the agent's launch command (sbx@1). ENTRYPOINT and | ||
| 15 | -# CMD are therefore deliberately not set here: the template stays agnostic. | ||
| 16 | - | ||
| 17 | -ARG GO_VERSION=1.26 | ||
| 18 | -ARG SHELL_TEMPLATE=docker/sandbox-templates:shell | ||
| 19 | - | ||
| 20 | -# ---- build stage: cross-compile mm for the target platform ----------------- | ||
| 21 | -FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build | ||
| 22 | -ARG TARGETOS | ||
| 23 | -ARG TARGETARCH | ||
| 24 | -# What `mm --version` reports: the tag, as 02-build-releases.sh stamps it. | ||
| 25 | -ARG MM_VERSION=dev | ||
| 26 | - | ||
| 27 | -WORKDIR /src | ||
| 28 | -COPY go.mod go.sum ./ | ||
| 29 | -RUN --mount=type=cache,target=/go/pkg/mod go mod download | ||
| 30 | -COPY . . | ||
| 31 | -# Same flags as 02-build-releases.sh: no C, no local paths, no symbols, the | ||
| 32 | -# version stamped into internal/version. | ||
| 33 | -RUN --mount=type=cache,target=/go/pkg/mod \ | ||
| 34 | - --mount=type=cache,target=/root/.cache/go-build \ | ||
| 35 | - CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ | ||
| 36 | - go build -trimpath -ldflags "-s -w -X mm/internal/version.stamped=${MM_VERSION}" -o /out/mm . | ||
| 37 | - | ||
| 38 | -# ---- template: the shell sandbox plus mm ----------------------------------- | ||
| 39 | -FROM ${SHELL_TEMPLATE} | ||
| 40 | - | ||
| 41 | -COPY --from=build --chmod=0755 /out/mm /usr/local/bin/mm | ||
| 42 | -# The two kit entry points. mm-tui runs `mm -tui "$@"`; mm-acp-info prints how | ||
| 43 | -# an editor reaches this sandbox and opens a shell (see docker-sbx-v3/README.md). | ||
| 44 | -COPY --chmod=0755 docker-sbx-v3/template/mm-tui docker-sbx-v3/template/mm-acp-info /usr/local/bin/ | ||
| 45 | - | ||
| 46 | -# tcell (the window mode) needs a terminal type and a UTF-8 locale; the kits | ||
| 47 | -# set them too, this is the fallback for a plain `docker run`. | ||
| 48 | -ENV TERM=xterm-256color \ | ||
| 49 | - COLORTERM=truecolor \ | ||
| 50 | - LANG=C.UTF-8 | ||
| 51 | - | ||
| 52 | -# The pinned toolchains (/usr/local/go/bin, /usr/local/node/bin) must come | ||
| 53 | -# before /usr/bin so they win over any Go or Node the base image ships. | ||
| 54 | -ENV PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH | ||
| 55 | - | ||
| 56 | -# Without this, a go.mod whose `go` directive is newer than GO_VERSION makes the | ||
| 57 | -# toolchain download and run a different Go, silently defeating the pin. | ||
| 58 | -ENV GOTOOLCHAIN=local | ||
| 59 | - | ||
| 60 | -# ------------------------------------ | ||
| 61 | -# Shared curl options for every download below. | ||
| 62 | -# | ||
| 63 | -# ARG, not ENV: this is build-time only and must not leak into the image. | ||
| 64 | -# ------------------------------------ | ||
| 65 | -ARG CURL_RETRY="--retry 5 --retry-all-errors --retry-delay 3 --connect-timeout 15" | ||
| 66 | - | ||
| 67 | -USER root | ||
| 68 | - | ||
| 69 | -# ------------------------------------ | ||
| 70 | -# Install Go toolchain and Node.js | ||
| 71 | -# ------------------------------------ | ||
| 72 | -ARG GO_VERSION=1.26.0 | ||
| 73 | -ARG NODE_VERSION=24.21.0 | ||
| 74 | -ARG TARGETARCH | ||
| 75 | - | ||
| 76 | -RUN <<EOF | ||
| 77 | -set -eux | ||
| 78 | -apt-get update | ||
| 79 | -apt-get install -y curl build-essential xz-utils | ||
| 80 | -rm -rf /var/lib/apt/lists/* | ||
| 81 | -EOF | ||
| 82 | - | ||
| 83 | -RUN <<EOF | ||
| 84 | -set -eux | ||
| 85 | -apt-get remove -y golang-go golang-doc | ||
| 86 | -apt-get autoremove -y | ||
| 87 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/go.tgz "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" | ||
| 88 | -rm -rf /usr/local/go | ||
| 89 | -tar -C /usr/local -xzf /tmp/go.tgz | ||
| 90 | -rm /tmp/go.tgz | ||
| 91 | -/usr/local/go/bin/go version | ||
| 92 | -EOF | ||
| 93 | - | ||
| 94 | -RUN <<EOF | ||
| 95 | -set -eux | ||
| 96 | -case "${TARGETARCH}" in | ||
| 97 | - amd64) node_arch=x64 ;; | ||
| 98 | - arm64) node_arch=arm64 ;; | ||
| 99 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | ||
| 100 | -esac | ||
| 101 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/node.tar.xz "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_arch}.tar.xz" | ||
| 102 | -rm -rf /usr/local/node | ||
| 103 | -mkdir -p /usr/local/node | ||
| 104 | -tar -C /usr/local/node --strip-components=1 -xJf /tmp/node.tar.xz | ||
| 105 | -rm /tmp/node.tar.xz | ||
| 106 | -/usr/local/node/bin/node --version | ||
| 107 | -/usr/local/node/bin/npm --version | ||
| 108 | -EOF | ||
| 109 | - | ||
| 110 | -# ------------------------------------ | ||
| 111 | -# Persist the Go and Node environment for sandbox shells. | ||
| 112 | -# /etc/sandbox-persistent.sh is sourced before every bash command in the sbx. | ||
| 113 | -# ------------------------------------ | ||
| 114 | -RUN <<EOF | ||
| 115 | -{ | ||
| 116 | - echo 'export PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH' | ||
| 117 | - echo 'export GOTOOLCHAIN=local' | ||
| 118 | -} >> /etc/sandbox-persistent.sh | ||
| 119 | -EOF | ||
| 120 | - | ||
| 121 | -# Switch to agent user for Go tools installation (they go to /home/agent/go/bin) | ||
| 122 | -USER agent | ||
| 123 | - | ||
| 124 | -# ------------------------------------ | ||
| 125 | -# Install Go developer tools | ||
| 126 | -# ------------------------------------ | ||
| 127 | -ARG GOPLS_VERSION=v0.23.0 | ||
| 128 | -ARG X_TOOLS_VERSION=v0.49.0 | ||
| 129 | -ARG STATICCHECK_VERSION=v0.7.0 | ||
| 130 | - | ||
| 131 | -# Retried: parallel multi-arch builds occasionally hit DNS timeouts on | ||
| 132 | -# Docker Desktop's resolver. The module cache survives within this RUN, | ||
| 133 | -# so a retry only fetches what's still missing. | ||
| 134 | -RUN for i in 1 2 3 4 5; do \ | ||
| 135 | - go install golang.org/x/tools/gopls@${GOPLS_VERSION} \ | ||
| 136 | - && go install golang.org/x/tools/cmd/goimports@${X_TOOLS_VERSION} \ | ||
| 137 | - && go install honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION} \ | ||
| 138 | - && exit 0; \ | ||
| 139 | - echo "go install failed (attempt $i), retrying..." >&2; sleep $((i * 5)); \ | ||
| 140 | - done; exit 1 | ||
| 141 | - | ||
| 142 | -# Prove the binary runs on this platform before the image is tagged. | ||
| 143 | -RUN mm --version && mm-tui --version | ||
deleted
docker-sbx-v3/template/mm-acp-info +0 -52 | deleted file mode 100644 | ||
| @@ -1,52 +0,0 @@ | ||
| 1 | -#!/bin/bash | |
| 2 | -# Entry point of the mm-acp sandbox kit (docker-sbx-v3/kits/mm-acp). | |
| 3 | -# | |
| 4 | -# An editor never runs this script. It reaches mm with | |
| 5 | -# | |
| 6 | -# sbx exec -i <sandbox> mm -acp | |
| 7 | -# | |
| 8 | -# because an ACP client needs raw stdin/stdout and `sbx run` always allocates | |
| 9 | -# a terminal. So attaching to this sandbox with `sbx run` prints the wiring | |
| 10 | -# for the editor, with this sandbox's real name and paths, then opens a shell. | |
| 11 | -set -u | |
| 12 | - | |
| 13 | -name="${SANDBOX_NAME:-$(hostname)}" | |
| 14 | -workspace="${WORKSPACE_DIR:-$PWD}" | |
| 15 | -config="${AGENT_CONFIG:-}" | |
| 16 | -if [ -z "$config" ]; then | |
| 17 | - config_note="none set — mm reads ./agent.yaml in the workspace, then its built-in defaults" | |
| 18 | -elif [ "${config#/}" = "$config" ]; then | |
| 19 | - config_note="$config (relative to the workspace: ${workspace%/}/$config)" | |
| 20 | -else | |
| 21 | - config_note="$config" | |
| 22 | -fi | |
| 23 | - | |
| 24 | -cat <<INFO | |
| 25 | - | |
| 26 | - mm $(mm --version 2>/dev/null | awk '{print $2}') in sandbox "$name" | |
| 27 | - workspace : $workspace | |
| 28 | - config : $config_note | |
| 29 | - | |
| 30 | - This sandbox is meant for an editor (Agent Client Protocol). Register it in | |
| 31 | - Zed's settings.json — the editor starts mm inside the sandbox on every | |
| 32 | - conversation, and sbx starts the sandbox first when it is stopped: | |
| 33 | - | |
| 34 | - { | |
| 35 | - "agent_servers": { | |
| 36 | - "mini-me (sandbox)": { | |
| 37 | - "type": "custom", | |
| 38 | - "command": "sbx", | |
| 39 | - "args": ["exec", "-i", "$name", "mm", "-acp"] | |
| 40 | - } | |
| 41 | - } | |
| 42 | - } | |
| 43 | - | |
| 44 | - Use the absolute path of sbx as "command" if the editor cannot find it | |
| 45 | - (\`which sbx\` on the host). To change the configuration file for one | |
| 46 | - session, add "-e", "AGENT_CONFIG=/path/in/workspace/agent.yaml" before | |
| 47 | - "$name" in "args". Full guide: docker-sbx-v3/README.md | |
| 48 | - | |
| 49 | - You are now in a shell inside the sandbox. \`mm agent.yaml\` works here too. | |
| 50 | - | |
| 51 | -INFO | |
| 52 | -exec bash -l | |
| deleted file mode 100644 | |||
| @@ -1,52 +0,0 @@ | |||
| 1 | -#!/bin/bash | ||
| 2 | -# Entry point of the mm-acp sandbox kit (docker-sbx-v3/kits/mm-acp). | ||
| 3 | -# | ||
| 4 | -# An editor never runs this script. It reaches mm with | ||
| 5 | -# | ||
| 6 | -# sbx exec -i <sandbox> mm -acp | ||
| 7 | -# | ||
| 8 | -# because an ACP client needs raw stdin/stdout and `sbx run` always allocates | ||
| 9 | -# a terminal. So attaching to this sandbox with `sbx run` prints the wiring | ||
| 10 | -# for the editor, with this sandbox's real name and paths, then opens a shell. | ||
| 11 | -set -u | ||
| 12 | - | ||
| 13 | -name="${SANDBOX_NAME:-$(hostname)}" | ||
| 14 | -workspace="${WORKSPACE_DIR:-$PWD}" | ||
| 15 | -config="${AGENT_CONFIG:-}" | ||
| 16 | -if [ -z "$config" ]; then | ||
| 17 | - config_note="none set — mm reads ./agent.yaml in the workspace, then its built-in defaults" | ||
| 18 | -elif [ "${config#/}" = "$config" ]; then | ||
| 19 | - config_note="$config (relative to the workspace: ${workspace%/}/$config)" | ||
| 20 | -else | ||
| 21 | - config_note="$config" | ||
| 22 | -fi | ||
| 23 | - | ||
| 24 | -cat <<INFO | ||
| 25 | - | ||
| 26 | - mm $(mm --version 2>/dev/null | awk '{print $2}') in sandbox "$name" | ||
| 27 | - workspace : $workspace | ||
| 28 | - config : $config_note | ||
| 29 | - | ||
| 30 | - This sandbox is meant for an editor (Agent Client Protocol). Register it in | ||
| 31 | - Zed's settings.json — the editor starts mm inside the sandbox on every | ||
| 32 | - conversation, and sbx starts the sandbox first when it is stopped: | ||
| 33 | - | ||
| 34 | - { | ||
| 35 | - "agent_servers": { | ||
| 36 | - "mini-me (sandbox)": { | ||
| 37 | - "type": "custom", | ||
| 38 | - "command": "sbx", | ||
| 39 | - "args": ["exec", "-i", "$name", "mm", "-acp"] | ||
| 40 | - } | ||
| 41 | - } | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - Use the absolute path of sbx as "command" if the editor cannot find it | ||
| 45 | - (\`which sbx\` on the host). To change the configuration file for one | ||
| 46 | - session, add "-e", "AGENT_CONFIG=/path/in/workspace/agent.yaml" before | ||
| 47 | - "$name" in "args". Full guide: docker-sbx-v3/README.md | ||
| 48 | - | ||
| 49 | - You are now in a shell inside the sandbox. \`mm agent.yaml\` works here too. | ||
| 50 | - | ||
| 51 | -INFO | ||
| 52 | -exec bash -l | ||
deleted
docker-sbx-v3/template/mm-tui +0 -11 | deleted file mode 100644 | ||
| @@ -1,11 +0,0 @@ | ||
| 1 | -#!/bin/bash | |
| 2 | -# Entry point of the mm-tui sandbox kit (docker-sbx-v3/kits/mm-tui). | |
| 3 | -# | |
| 4 | -# `sbx run` forwards whatever follows "--" as this script's arguments, so | |
| 5 | -# | |
| 6 | -# sbx run ./docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | |
| 7 | -# | |
| 8 | -# runs `mm -tui agent.dmr.yaml` in the workspace. Without an argument mm reads | |
| 9 | -# $AGENT_CONFIG (the kit's `config` argument), then ./agent.yaml, then its | |
| 10 | -# built-in defaults. Flags pass through too: `-- -config other.yaml`. | |
| 11 | -exec mm -tui "$@" | |
| deleted file mode 100644 | |||
| @@ -1,11 +0,0 @@ | |||
| 1 | -#!/bin/bash | ||
| 2 | -# Entry point of the mm-tui sandbox kit (docker-sbx-v3/kits/mm-tui). | ||
| 3 | -# | ||
| 4 | -# `sbx run` forwards whatever follows "--" as this script's arguments, so | ||
| 5 | -# | ||
| 6 | -# sbx run ./docker-sbx-v3/kits/mm-tui . -- agent.dmr.yaml | ||
| 7 | -# | ||
| 8 | -# runs `mm -tui agent.dmr.yaml` in the workspace. Without an argument mm reads | ||
| 9 | -# $AGENT_CONFIG (the kit's `config` argument), then ./agent.yaml, then its | ||
| 10 | -# built-in defaults. Flags pass through too: `-- -config other.yaml`. | ||
| 11 | -exec mm -tui "$@" | ||
deleted
docker-sbx/README.md +0 -208 | deleted file mode 100644 | ||
| @@ -1,208 +0,0 @@ | ||
| 1 | -# mm in a Docker Sandbox | |
| 2 | - | |
| 3 | -Everything needed to run `mm` inside a [Docker Sandbox](https://docs.docker.com/ai/sandboxes/): a **template** (the `shell` sandbox image with `mm` installed) and two **kits** that start it — one for the window mode in your terminal, one for an editor that speaks the Agent Client Protocol. | |
| 4 | - | |
| 5 | -The full guide, with the reasoning, is in [`docs/en/how-to/run-in-a-docker-sandbox.md`](../docs/en/how-to/run-in-a-docker-sandbox.md) ([français](../docs/fr/how-to/run-in-a-docker-sandbox.md)). This page is the short version. | |
| 6 | - | |
| 7 | -``` | |
| 8 | -docker-sbx/ | |
| 9 | -├── publish.sh build + push the image, then publish the kits — the one command to release | |
| 10 | -├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) | |
| 11 | -├── sync-kits.sh points the kits at one image: owner + version | |
| 12 | -├── push-kits.sh publishes the kits to Docker Hub as OCI artifacts (sbx kit push) | |
| 13 | -├── template/ | |
| 14 | -│ ├── Dockerfile docker/sandbox-templates:shell + mm (built from this checkout) | |
| 15 | -│ ├── mm-tui entry point of the mm-tui kit: `mm -tui "$@"` | |
| 16 | -│ └── mm-acp-info entry point of the mm-acp kit: prints the editor wiring, opens a shell | |
| 17 | -└── kits/ | |
| 18 | - ├── mm-tui/spec.yaml kind: sandbox — `sbx run` opens mm's window on the workspace | |
| 19 | - └── mm-acp/spec.yaml kind: sandbox — `sbx create` once, the editor runs `sbx exec -i … mm -acp` | |
| 20 | -``` | |
| 21 | - | |
| 22 | -## 0. Use the published kits (no build) | |
| 23 | - | |
| 24 | -Every release publishes the image and the two kits to Docker Hub at mm's version: | |
| 25 | - | |
| 26 | -| On Docker Hub | What it is | | |
| 27 | -|---|---| | |
| 28 | -| `k33g/mm-sandbox:0.1.7` | The template image. You never name it yourself: each kit pulls it. | | |
| 29 | -| `k33g/mm-tui:0.1.7` | The window-mode kit, for `sbx run`. | | |
| 30 | -| `k33g/mm-acp:0.1.7` | The editor kit, for `sbx create` + `sbx exec -i … mm -acp`. | | |
| 31 | - | |
| 32 | -Nothing to build, no `--pull never`, and no setting to change: Docker Hub is an allowed kit source out of the box (`sbx settings get kit.allowedSources` shows `docker.io/`), and a reference with a `/` but no registry host is read as `docker.io/…`. Only Docker Desktop with the `sbx` command, and a model server on your machine, are needed. | |
| 33 | - | |
| 34 | -**Look before you run.** `sbx kit inspect` reads the kit from the Hub without creating anything: its image, its entry point, its arguments and their defaults, the ports it allows. | |
| 35 | - | |
| 36 | -```bash | |
| 37 | -sbx kit inspect k33g/mm-tui:0.1.7 | |
| 38 | -``` | |
| 39 | - | |
| 40 | -**Window mode.** From the project you want mm to work on: | |
| 41 | - | |
| 42 | -```bash | |
| 43 | -cd /path/to/your/project | |
| 44 | -sbx run k33g/mm-tui:0.1.7 . -- agent.dmr.yaml | |
| 45 | -``` | |
| 46 | - | |
| 47 | -The first run pulls the kit and the image, creates the sandbox `mm-tui-<directory>`, mounts the current directory as its workspace and opens `mm -tui agent.dmr.yaml` in it. What follows `--` is mm's own command line, so `-- -config other.yaml` works too. Without anything after `--`, mm reads the kit's `config` argument, then `./agent.yaml` in the workspace: | |
| 48 | - | |
| 49 | -```bash | |
| 50 | -sbx run k33g/mm-tui:0.1.7 . --kit-arg config=agent.dmr.yaml | |
| 51 | -``` | |
| 52 | - | |
| 53 | -Later, `sbx run --name mm-tui-<directory>` re-attaches to that sandbox; `sbx ls` lists them. | |
| 54 | - | |
| 55 | -**From an editor.** Create the sandbox once, from the project the editor will open, with the configuration file baked in: | |
| 56 | - | |
| 57 | -```bash | |
| 58 | -cd /path/to/your/project | |
| 59 | -sbx create --name mm-acp k33g/mm-acp:0.1.7 . --kit-arg config=agent.dmr.yaml | |
| 60 | - | |
| 61 | -#sbx create k33g/mm-acp:0.1.7 . --name sbx-mm-acp | |
| 62 | -``` | |
| 63 | - | |
| 64 | -then register it in the editor — in Zed's `settings.json`: | |
| 65 | - | |
| 66 | -```json | |
| 67 | -{ | |
| 68 | - "agent_servers": { | |
| 69 | - "mini-me (sandbox)": { | |
| 70 | - "type": "custom", | |
| 71 | - "command": "sbx", | |
| 72 | - "args": ["exec", "-i", "mm-acp", "mm", "-acp"] | |
| 73 | - } | |
| 74 | - } | |
| 75 | -} | |
| 76 | -``` | |
| 77 | - | |
| 78 | -The editor starts `mm -acp` inside the sandbox for every conversation; `sbx exec` starts the sandbox first when it is stopped, and runs mm in the workspace with the baked-in `AGENT_CONFIG`. One sandbox per project, each with its own `--name` and its own editor entry. Section 3 has the details (another config for one session, where the logs are, why `sbx exec -i` and not `sbx run`). | |
| 79 | - | |
| 80 | -**Kit arguments.** Both kits take the same two, passed with `--kit-arg name=value` (repeatable) to `sbx run` or `sbx create`: | |
| 81 | - | |
| 82 | -| `--kit-arg` | Default | Effect | | |
| 83 | -|---|---|---| | |
| 84 | -| `config=<path>` | empty | The file mm reads (its `AGENT_CONFIG`): relative to the workspace, or absolute inside the sandbox. Empty: `./agent.yaml`, then the built-in defaults. | | |
| 85 | -| `tag=<version>` | the kit's own version (`0.1.7`) | Which `k33g/mm-sandbox:<version>` image to use. Normally left alone: a kit and its image share a version. | | |
| 86 | - | |
| 87 | -**Other versions.** Replace `0.1.7` with the release you want, in the kit reference only — the kit brings the matching image. A kit can also be pinned by digest, `k33g/mm-tui@sha256:…`, the digest being what `sbx kit inspect` or the Hub page shows. | |
| 88 | - | |
| 89 | -**If sbx refuses the source.** A message like `its source is not in your allowlist` means `kit.allowedSources` was narrowed on this machine; `sbx settings set kit.allowedSources '["docker.io/"]'` restores the default, or add `docker.io/k33g/` to your list. | |
| 90 | - | |
| 91 | -Sections 1–3 are the same flow with a template and kits built locally, for a work-in-progress mm. | |
| 92 | - | |
| 93 | -## 1. Build the template | |
| 94 | - | |
| 95 | -From the repository root: | |
| 96 | - | |
| 97 | -```bash | |
| 98 | -./docker-sbx/build.sh # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7 | |
| 99 | -./docker-sbx/build.sh v0.1.5 # → k33g/mm-sandbox:0.1.5 | |
| 100 | -``` | |
| 101 | - | |
| 102 | -The image tag is mm's tag without the `v`, the same rule as the release assets, and the script rewrites the kits' default `tag` argument to the version it built, so the kits always name the image just built. The image lands in the local Docker image store: every `sbx run` / `sbx create` below carries `--pull never` until you `docker push k33g/mm-sandbox:0.1.7`. If `sbx` runs on another machine, `EXPORT=1 ./docker-sbx/build.sh` also writes `tmp/mm-sandbox-<version>.tar`; load it there with `sbx template load`. | |
| 103 | - | |
| 104 | -## 2. Window mode in the terminal — kit `mm-tui` | |
| 105 | - | |
| 106 | -From the project you want `mm` to work on: | |
| 107 | - | |
| 108 | -```bash | |
| 109 | -sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | |
| 110 | -``` | |
| 111 | - | |
| 112 | -What follows `--` reaches `mm` as its own arguments, so this runs `mm -tui agent.dmr.yaml` in the workspace. Any `mm` flag passes through the same way (`-- -config other.yaml`). Two kit arguments exist as well: | |
| 113 | - | |
| 114 | -| `--kit-arg` | Default | Effect | | |
| 115 | -|---|---|---| | |
| 116 | -| `config=<path>` | empty | The file `mm` reads when nothing follows `--` (its `AGENT_CONFIG`). Relative to the workspace, or absolute. Empty: `./agent.yaml`, then the built-in defaults. | | |
| 117 | -| `tag=<version>` | the version last built (`0.1.7`) | Which `k33g/mm-sandbox:<version>` image to use. | | |
| 118 | - | |
| 119 | -`sbx run --name <name>` re-attaches to a sandbox that already exists. Sessions, when enabled in the YAML, are written under the workspace's `.mm/sessions`, which is your host directory. | |
| 120 | - | |
| 121 | -## 3. From an editor (ACP) — kit `mm-acp` | |
| 122 | - | |
| 123 | -Create the sandbox once, without attaching, **from the project the editor will open**. `.` is the workspace; sbx makes it absolute. A path that does not exist on your machine makes sbx ask "The selected workspace does not exist. Would you like to create it?" — answer `N` and fix the path. The kit path must be explicit: `./`, `../` or absolute. | |
| 124 | - | |
| 125 | -```bash | |
| 126 | -cd /path/to/your/project | |
| 127 | -sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . \ | |
| 128 | - --kit-arg config=agent.dmr.yaml | |
| 129 | - | |
| 130 | -# once the image is pushed (docker push k33g/mm-sandbox:0.1.7), --pull never is not needed: | |
| 131 | -sbx create --name mm-acp ./docker-sbx/kits/mm-acp . \ | |
| 132 | - --kit-arg config=agent.dmr.yaml | |
| 133 | -``` | |
| 134 | - | |
| 135 | -Then register it in the editor. In Zed's `settings.json`: | |
| 136 | - | |
| 137 | -```json | |
| 138 | -{ | |
| 139 | - "agent_servers": { | |
| 140 | - "📦 mini-me (dmr sbx)": { | |
| 141 | - "type": "custom", | |
| 142 | - "command": "sbx", | |
| 143 | - "args": ["exec", "-i", "mm-acp", "mm", "-acp"], | |
| 144 | - }, | |
| 145 | - } | |
| 146 | -} | |
| 147 | -``` | |
| 148 | - | |
| 149 | -Or: | |
| 150 | - | |
| 151 | -```bash | |
| 152 | -sbx create --pull never --name mm-acp-2 ./docker-sbx/kits/mm-acp . | |
| 153 | -``` | |
| 154 | - | |
| 155 | -And: | |
| 156 | - | |
| 157 | -```json | |
| 158 | -{ | |
| 159 | - "agent_servers": { | |
| 160 | - "😄 mini-me (dmr sbx)": { | |
| 161 | - "type": "custom", | |
| 162 | - "command": "sbx", | |
| 163 | - "args": ["exec", "-i", "mm-acp-2", "mm", "-acp"], | |
| 164 | - "env": { "AGENT_CONFIG": "/Users/k33g/kDrive/Rickub/bots-garden/mini-me/demo/agent.dmr.yaml" } | |
| 165 | - }, | |
| 166 | - } | |
| 167 | -} | |
| 168 | -``` | |
| 169 | - | |
| 170 | - | |
| 171 | - | |
| 172 | -The editor starts `mm -acp` inside the sandbox for every conversation; `sbx exec` starts the sandbox first when it is stopped, and runs `mm` in the workspace with the `AGENT_CONFIG` baked in by `--kit-arg config`. Everything the model does — commands, file edits — happens inside the sandbox, on the mounted project. | |
| 173 | - | |
| 174 | -Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the agent's raw stdin/stdout, and `sbx run` always allocates a terminal. Attaching to this sandbox with `sbx run --name mm-acp` is still useful: its entry point prints the wiring above with the sandbox's real name, then opens a shell. | |
| 175 | - | |
| 176 | -- One sandbox per project: the workspace is fixed at creation. Give each one its own `--name` and its own entry in the editor. | |
| 177 | -- Another configuration file for one session: `"args": ["exec", "-i", "-e", "AGENT_CONFIG=agent.lsp.yaml", "mm-acp", "mm", "-acp"]`. | |
| 178 | -- `sbx` not found by the editor: use the absolute path printed by `which sbx` as `"command"`. | |
| 179 | -- Logs: in Zed, `dev: open acp logs` shows `mm`'s banner, warnings and `[acp] …` trail. | |
| 180 | - | |
| 181 | -## 4. Publishing a version | |
| 182 | - | |
| 183 | -Publishing is done by hand, from a laptop with Docker Desktop (buildx and the `sbx` CLI). One command builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag: | |
| 184 | - | |
| 185 | -```bash | |
| 186 | -export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner | |
| 187 | -export DOCKER_PAT=dckr_pat_… # an access token with read/write scope | |
| 188 | -./docker-sbx/publish.sh # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7 | |
| 189 | -./docker-sbx/publish.sh v0.1.5 # another tag | |
| 190 | -``` | |
| 191 | - | |
| 192 | -With the two variables set, the script logs in with them and logs out at the end; with neither, it reuses the `docker login` you already have. It is two steps you can also run alone: | |
| 193 | - | |
| 194 | -```bash | |
| 195 | -PUSH=1 ./docker-sbx/build.sh v0.2.3 # buildx multi-arch, pushed; proof: `imagetools inspect` lists both platforms | |
| 196 | -./docker-sbx/push-kits.sh v0.1.7 # sbx kit validate + sbx kit push, for each kit | |
| 197 | -``` | |
| 198 | - | |
| 199 | -Both call `sync-kits.sh` first, so the published kits always name the image just pushed, and the kits' `spec.yaml` end up saying the new version — commit them. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store; no sandbox daemon is involved. `IMAGE_OWNER=<handle>` publishes under another account. Nothing in CI publishes to the Hub: the Release workflow only builds the binaries. | |
| 200 | - | |
| 201 | -## The model server stays on the host | |
| 202 | - | |
| 203 | -Inside a sandbox `localhost` is the sandbox itself. Docker Model Runner and llama-server keep running on your machine and are reached through `host.docker.internal`, which the sandbox proxy maps to your host's `localhost`: | |
| 204 | - | |
| 205 | -- `agent.dmr.yaml` already has `fallback: http://host.docker.internal:12434/engines/v1` — nothing to change. | |
| 206 | -- `agent.llamacpp.yaml` has no fallback: pass `--env AGENT_BASE_URL=http://host.docker.internal:8080/v1` to `sbx run` / `sbx create`, or edit its `baseUrl`. | |
| 207 | - | |
| 208 | -Both kits allow ports 12434 (Docker Model Runner) and 8080 (llama-server) on the host. Another port: `sbx policy allow network host.docker.internal:<port>`. | |
| deleted file mode 100644 | |||
| @@ -1,208 +0,0 @@ | |||
| 1 | -# mm in a Docker Sandbox | ||
| 2 | - | ||
| 3 | -Everything needed to run `mm` inside a [Docker Sandbox](https://docs.docker.com/ai/sandboxes/): a **template** (the `shell` sandbox image with `mm` installed) and two **kits** that start it — one for the window mode in your terminal, one for an editor that speaks the Agent Client Protocol. | ||
| 4 | - | ||
| 5 | -The full guide, with the reasoning, is in [`docs/en/how-to/run-in-a-docker-sandbox.md`](../docs/en/how-to/run-in-a-docker-sandbox.md) ([français](../docs/fr/how-to/run-in-a-docker-sandbox.md)). This page is the short version. | ||
| 6 | - | ||
| 7 | -``` | ||
| 8 | -docker-sbx/ | ||
| 9 | -├── publish.sh build + push the image, then publish the kits — the one command to release | ||
| 10 | -├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) | ||
| 11 | -├── sync-kits.sh points the kits at one image: owner + version | ||
| 12 | -├── push-kits.sh publishes the kits to Docker Hub as OCI artifacts (sbx kit push) | ||
| 13 | -├── template/ | ||
| 14 | -│ ├── Dockerfile docker/sandbox-templates:shell + mm (built from this checkout) | ||
| 15 | -│ ├── mm-tui entry point of the mm-tui kit: `mm -tui "$@"` | ||
| 16 | -│ └── mm-acp-info entry point of the mm-acp kit: prints the editor wiring, opens a shell | ||
| 17 | -└── kits/ | ||
| 18 | - ├── mm-tui/spec.yaml kind: sandbox — `sbx run` opens mm's window on the workspace | ||
| 19 | - └── mm-acp/spec.yaml kind: sandbox — `sbx create` once, the editor runs `sbx exec -i … mm -acp` | ||
| 20 | -``` | ||
| 21 | - | ||
| 22 | -## 0. Use the published kits (no build) | ||
| 23 | - | ||
| 24 | -Every release publishes the image and the two kits to Docker Hub at mm's version: | ||
| 25 | - | ||
| 26 | -| On Docker Hub | What it is | | ||
| 27 | -|---|---| | ||
| 28 | -| `k33g/mm-sandbox:0.1.7` | The template image. You never name it yourself: each kit pulls it. | | ||
| 29 | -| `k33g/mm-tui:0.1.7` | The window-mode kit, for `sbx run`. | | ||
| 30 | -| `k33g/mm-acp:0.1.7` | The editor kit, for `sbx create` + `sbx exec -i … mm -acp`. | | ||
| 31 | - | ||
| 32 | -Nothing to build, no `--pull never`, and no setting to change: Docker Hub is an allowed kit source out of the box (`sbx settings get kit.allowedSources` shows `docker.io/`), and a reference with a `/` but no registry host is read as `docker.io/…`. Only Docker Desktop with the `sbx` command, and a model server on your machine, are needed. | ||
| 33 | - | ||
| 34 | -**Look before you run.** `sbx kit inspect` reads the kit from the Hub without creating anything: its image, its entry point, its arguments and their defaults, the ports it allows. | ||
| 35 | - | ||
| 36 | -```bash | ||
| 37 | -sbx kit inspect k33g/mm-tui:0.1.7 | ||
| 38 | -``` | ||
| 39 | - | ||
| 40 | -**Window mode.** From the project you want mm to work on: | ||
| 41 | - | ||
| 42 | -```bash | ||
| 43 | -cd /path/to/your/project | ||
| 44 | -sbx run k33g/mm-tui:0.1.7 . -- agent.dmr.yaml | ||
| 45 | -``` | ||
| 46 | - | ||
| 47 | -The first run pulls the kit and the image, creates the sandbox `mm-tui-<directory>`, mounts the current directory as its workspace and opens `mm -tui agent.dmr.yaml` in it. What follows `--` is mm's own command line, so `-- -config other.yaml` works too. Without anything after `--`, mm reads the kit's `config` argument, then `./agent.yaml` in the workspace: | ||
| 48 | - | ||
| 49 | -```bash | ||
| 50 | -sbx run k33g/mm-tui:0.1.7 . --kit-arg config=agent.dmr.yaml | ||
| 51 | -``` | ||
| 52 | - | ||
| 53 | -Later, `sbx run --name mm-tui-<directory>` re-attaches to that sandbox; `sbx ls` lists them. | ||
| 54 | - | ||
| 55 | -**From an editor.** Create the sandbox once, from the project the editor will open, with the configuration file baked in: | ||
| 56 | - | ||
| 57 | -```bash | ||
| 58 | -cd /path/to/your/project | ||
| 59 | -sbx create --name mm-acp k33g/mm-acp:0.1.7 . --kit-arg config=agent.dmr.yaml | ||
| 60 | - | ||
| 61 | -#sbx create k33g/mm-acp:0.1.7 . --name sbx-mm-acp | ||
| 62 | -``` | ||
| 63 | - | ||
| 64 | -then register it in the editor — in Zed's `settings.json`: | ||
| 65 | - | ||
| 66 | -```json | ||
| 67 | -{ | ||
| 68 | - "agent_servers": { | ||
| 69 | - "mini-me (sandbox)": { | ||
| 70 | - "type": "custom", | ||
| 71 | - "command": "sbx", | ||
| 72 | - "args": ["exec", "-i", "mm-acp", "mm", "-acp"] | ||
| 73 | - } | ||
| 74 | - } | ||
| 75 | -} | ||
| 76 | -``` | ||
| 77 | - | ||
| 78 | -The editor starts `mm -acp` inside the sandbox for every conversation; `sbx exec` starts the sandbox first when it is stopped, and runs mm in the workspace with the baked-in `AGENT_CONFIG`. One sandbox per project, each with its own `--name` and its own editor entry. Section 3 has the details (another config for one session, where the logs are, why `sbx exec -i` and not `sbx run`). | ||
| 79 | - | ||
| 80 | -**Kit arguments.** Both kits take the same two, passed with `--kit-arg name=value` (repeatable) to `sbx run` or `sbx create`: | ||
| 81 | - | ||
| 82 | -| `--kit-arg` | Default | Effect | | ||
| 83 | -|---|---|---| | ||
| 84 | -| `config=<path>` | empty | The file mm reads (its `AGENT_CONFIG`): relative to the workspace, or absolute inside the sandbox. Empty: `./agent.yaml`, then the built-in defaults. | | ||
| 85 | -| `tag=<version>` | the kit's own version (`0.1.7`) | Which `k33g/mm-sandbox:<version>` image to use. Normally left alone: a kit and its image share a version. | | ||
| 86 | - | ||
| 87 | -**Other versions.** Replace `0.1.7` with the release you want, in the kit reference only — the kit brings the matching image. A kit can also be pinned by digest, `k33g/mm-tui@sha256:…`, the digest being what `sbx kit inspect` or the Hub page shows. | ||
| 88 | - | ||
| 89 | -**If sbx refuses the source.** A message like `its source is not in your allowlist` means `kit.allowedSources` was narrowed on this machine; `sbx settings set kit.allowedSources '["docker.io/"]'` restores the default, or add `docker.io/k33g/` to your list. | ||
| 90 | - | ||
| 91 | -Sections 1–3 are the same flow with a template and kits built locally, for a work-in-progress mm. | ||
| 92 | - | ||
| 93 | -## 1. Build the template | ||
| 94 | - | ||
| 95 | -From the repository root: | ||
| 96 | - | ||
| 97 | -```bash | ||
| 98 | -./docker-sbx/build.sh # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7 | ||
| 99 | -./docker-sbx/build.sh v0.1.5 # → k33g/mm-sandbox:0.1.5 | ||
| 100 | -``` | ||
| 101 | - | ||
| 102 | -The image tag is mm's tag without the `v`, the same rule as the release assets, and the script rewrites the kits' default `tag` argument to the version it built, so the kits always name the image just built. The image lands in the local Docker image store: every `sbx run` / `sbx create` below carries `--pull never` until you `docker push k33g/mm-sandbox:0.1.7`. If `sbx` runs on another machine, `EXPORT=1 ./docker-sbx/build.sh` also writes `tmp/mm-sandbox-<version>.tar`; load it there with `sbx template load`. | ||
| 103 | - | ||
| 104 | -## 2. Window mode in the terminal — kit `mm-tui` | ||
| 105 | - | ||
| 106 | -From the project you want `mm` to work on: | ||
| 107 | - | ||
| 108 | -```bash | ||
| 109 | -sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | ||
| 110 | -``` | ||
| 111 | - | ||
| 112 | -What follows `--` reaches `mm` as its own arguments, so this runs `mm -tui agent.dmr.yaml` in the workspace. Any `mm` flag passes through the same way (`-- -config other.yaml`). Two kit arguments exist as well: | ||
| 113 | - | ||
| 114 | -| `--kit-arg` | Default | Effect | | ||
| 115 | -|---|---|---| | ||
| 116 | -| `config=<path>` | empty | The file `mm` reads when nothing follows `--` (its `AGENT_CONFIG`). Relative to the workspace, or absolute. Empty: `./agent.yaml`, then the built-in defaults. | | ||
| 117 | -| `tag=<version>` | the version last built (`0.1.7`) | Which `k33g/mm-sandbox:<version>` image to use. | | ||
| 118 | - | ||
| 119 | -`sbx run --name <name>` re-attaches to a sandbox that already exists. Sessions, when enabled in the YAML, are written under the workspace's `.mm/sessions`, which is your host directory. | ||
| 120 | - | ||
| 121 | -## 3. From an editor (ACP) — kit `mm-acp` | ||
| 122 | - | ||
| 123 | -Create the sandbox once, without attaching, **from the project the editor will open**. `.` is the workspace; sbx makes it absolute. A path that does not exist on your machine makes sbx ask "The selected workspace does not exist. Would you like to create it?" — answer `N` and fix the path. The kit path must be explicit: `./`, `../` or absolute. | ||
| 124 | - | ||
| 125 | -```bash | ||
| 126 | -cd /path/to/your/project | ||
| 127 | -sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . \ | ||
| 128 | - --kit-arg config=agent.dmr.yaml | ||
| 129 | - | ||
| 130 | -# once the image is pushed (docker push k33g/mm-sandbox:0.1.7), --pull never is not needed: | ||
| 131 | -sbx create --name mm-acp ./docker-sbx/kits/mm-acp . \ | ||
| 132 | - --kit-arg config=agent.dmr.yaml | ||
| 133 | -``` | ||
| 134 | - | ||
| 135 | -Then register it in the editor. In Zed's `settings.json`: | ||
| 136 | - | ||
| 137 | -```json | ||
| 138 | -{ | ||
| 139 | - "agent_servers": { | ||
| 140 | - "📦 mini-me (dmr sbx)": { | ||
| 141 | - "type": "custom", | ||
| 142 | - "command": "sbx", | ||
| 143 | - "args": ["exec", "-i", "mm-acp", "mm", "-acp"], | ||
| 144 | - }, | ||
| 145 | - } | ||
| 146 | -} | ||
| 147 | -``` | ||
| 148 | - | ||
| 149 | -Or: | ||
| 150 | - | ||
| 151 | -```bash | ||
| 152 | -sbx create --pull never --name mm-acp-2 ./docker-sbx/kits/mm-acp . | ||
| 153 | -``` | ||
| 154 | - | ||
| 155 | -And: | ||
| 156 | - | ||
| 157 | -```json | ||
| 158 | -{ | ||
| 159 | - "agent_servers": { | ||
| 160 | - "😄 mini-me (dmr sbx)": { | ||
| 161 | - "type": "custom", | ||
| 162 | - "command": "sbx", | ||
| 163 | - "args": ["exec", "-i", "mm-acp-2", "mm", "-acp"], | ||
| 164 | - "env": { "AGENT_CONFIG": "/Users/k33g/kDrive/Rickub/bots-garden/mini-me/demo/agent.dmr.yaml" } | ||
| 165 | - }, | ||
| 166 | - } | ||
| 167 | -} | ||
| 168 | -``` | ||
| 169 | - | ||
| 170 | - | ||
| 171 | - | ||
| 172 | -The editor starts `mm -acp` inside the sandbox for every conversation; `sbx exec` starts the sandbox first when it is stopped, and runs `mm` in the workspace with the `AGENT_CONFIG` baked in by `--kit-arg config`. Everything the model does — commands, file edits — happens inside the sandbox, on the mounted project. | ||
| 173 | - | ||
| 174 | -Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the agent's raw stdin/stdout, and `sbx run` always allocates a terminal. Attaching to this sandbox with `sbx run --name mm-acp` is still useful: its entry point prints the wiring above with the sandbox's real name, then opens a shell. | ||
| 175 | - | ||
| 176 | -- One sandbox per project: the workspace is fixed at creation. Give each one its own `--name` and its own entry in the editor. | ||
| 177 | -- Another configuration file for one session: `"args": ["exec", "-i", "-e", "AGENT_CONFIG=agent.lsp.yaml", "mm-acp", "mm", "-acp"]`. | ||
| 178 | -- `sbx` not found by the editor: use the absolute path printed by `which sbx` as `"command"`. | ||
| 179 | -- Logs: in Zed, `dev: open acp logs` shows `mm`'s banner, warnings and `[acp] …` trail. | ||
| 180 | - | ||
| 181 | -## 4. Publishing a version | ||
| 182 | - | ||
| 183 | -Publishing is done by hand, from a laptop with Docker Desktop (buildx and the `sbx` CLI). One command builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag: | ||
| 184 | - | ||
| 185 | -```bash | ||
| 186 | -export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner | ||
| 187 | -export DOCKER_PAT=dckr_pat_… # an access token with read/write scope | ||
| 188 | -./docker-sbx/publish.sh # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7 | ||
| 189 | -./docker-sbx/publish.sh v0.1.5 # another tag | ||
| 190 | -``` | ||
| 191 | - | ||
| 192 | -With the two variables set, the script logs in with them and logs out at the end; with neither, it reuses the `docker login` you already have. It is two steps you can also run alone: | ||
| 193 | - | ||
| 194 | -```bash | ||
| 195 | -PUSH=1 ./docker-sbx/build.sh v0.2.3 # buildx multi-arch, pushed; proof: `imagetools inspect` lists both platforms | ||
| 196 | -./docker-sbx/push-kits.sh v0.1.7 # sbx kit validate + sbx kit push, for each kit | ||
| 197 | -``` | ||
| 198 | - | ||
| 199 | -Both call `sync-kits.sh` first, so the published kits always name the image just pushed, and the kits' `spec.yaml` end up saying the new version — commit them. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store; no sandbox daemon is involved. `IMAGE_OWNER=<handle>` publishes under another account. Nothing in CI publishes to the Hub: the Release workflow only builds the binaries. | ||
| 200 | - | ||
| 201 | -## The model server stays on the host | ||
| 202 | - | ||
| 203 | -Inside a sandbox `localhost` is the sandbox itself. Docker Model Runner and llama-server keep running on your machine and are reached through `host.docker.internal`, which the sandbox proxy maps to your host's `localhost`: | ||
| 204 | - | ||
| 205 | -- `agent.dmr.yaml` already has `fallback: http://host.docker.internal:12434/engines/v1` — nothing to change. | ||
| 206 | -- `agent.llamacpp.yaml` has no fallback: pass `--env AGENT_BASE_URL=http://host.docker.internal:8080/v1` to `sbx run` / `sbx create`, or edit its `baseUrl`. | ||
| 207 | - | ||
| 208 | -Both kits allow ports 12434 (Docker Model Runner) and 8080 (llama-server) on the host. Another port: `sbx policy allow network host.docker.internal:<port>`. | ||
deleted
docker-sbx/USE.MM.SBX-WITH.TURBO.EDITORS.md +0 -16 | deleted file mode 100644 | ||
| @@ -1,16 +0,0 @@ | ||
| 1 | - | |
| 2 | - | |
| 3 | -Start `sbx` in your project directory: | |
| 4 | -```bash | |
| 5 | -sbx create k33g/mm-acp:0.1.7 . --name turbo-acp --kit-arg config=.turbo-go/agent.mm-dmr-gemma.yaml | |
| 6 | -``` | |
| 7 | - | |
| 8 | -`acp.toml`: | |
| 9 | - | |
| 10 | -```toml | |
| 11 | -[[agent]] | |
| 12 | -name = "📦 Riker (sbx mm-dmr-gemma)" | |
| 13 | -command = "sbx" | |
| 14 | -args = ["exec", "-i", "turbo-acp", "mm", "-acp"] | |
| 15 | - | |
| 16 | -``` | |
| \ No newline at end of file | ||
| deleted file mode 100644 | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | - | ||
| 2 | - | ||
| 3 | -Start `sbx` in your project directory: | ||
| 4 | -```bash | ||
| 5 | -sbx create k33g/mm-acp:0.1.7 . --name turbo-acp --kit-arg config=.turbo-go/agent.mm-dmr-gemma.yaml | ||
| 6 | -``` | ||
| 7 | - | ||
| 8 | -`acp.toml`: | ||
| 9 | - | ||
| 10 | -```toml | ||
| 11 | -[[agent]] | ||
| 12 | -name = "📦 Riker (sbx mm-dmr-gemma)" | ||
| 13 | -command = "sbx" | ||
| 14 | -args = ["exec", "-i", "turbo-acp", "mm", "-acp"] | ||
| 15 | - | ||
| 16 | -``` | ||
| \ No newline at end of file | \ No newline at end of file | ||
deleted
docker-sbx/USE.MM.SBX-WITH.ZED.EDITOR.md +0 -18 | deleted file mode 100644 | ||
| @@ -1,18 +0,0 @@ | ||
| 1 | - | |
| 2 | - | |
| 3 | -Start `sbx` in your project directory: | |
| 4 | -```bash | |
| 5 | -sbx create k33g/mm-acp:0.1.7 . --name zed-acp --kit-arg config=agent.dmr.yaml | |
| 6 | -``` | |
| 7 | - | |
| 8 | -Zed settings: | |
| 9 | - | |
| 10 | -```json | |
| 11 | - "agent_servers": { | |
| 12 | - "😄 mini-me (dmr sbx)": { | |
| 13 | - "type": "custom", | |
| 14 | - "command": "sbx", | |
| 15 | - "args": ["exec", "-i", "zed-acp-3", "mm", "-acp"], | |
| 16 | - }, | |
| 17 | - } | |
| 18 | -``` | |
| \ No newline at end of file | ||
| deleted file mode 100644 | |||
| @@ -1,18 +0,0 @@ | |||
| 1 | - | ||
| 2 | - | ||
| 3 | -Start `sbx` in your project directory: | ||
| 4 | -```bash | ||
| 5 | -sbx create k33g/mm-acp:0.1.7 . --name zed-acp --kit-arg config=agent.dmr.yaml | ||
| 6 | -``` | ||
| 7 | - | ||
| 8 | -Zed settings: | ||
| 9 | - | ||
| 10 | -```json | ||
| 11 | - "agent_servers": { | ||
| 12 | - "😄 mini-me (dmr sbx)": { | ||
| 13 | - "type": "custom", | ||
| 14 | - "command": "sbx", | ||
| 15 | - "args": ["exec", "-i", "zed-acp-3", "mm", "-acp"], | ||
| 16 | - }, | ||
| 17 | - } | ||
| 18 | -``` | ||
| \ No newline at end of file | \ No newline at end of file | ||
deleted
docker-sbx/build.sh +0 -106 | deleted file mode 100644 | ||
| @@ -1,106 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Build the mm sandbox template image, <owner>/mm-sandbox:<version>, from this | |
| 3 | -# checkout. The image tag follows mm's own tag, minus the "v": release.env | |
| 4 | -# says TAG="v0.0.2", the image is k33g/mm-sandbox:0.0.2 and `mm --version` | |
| 5 | -# inside it reports v0.0.2 — the same rule as the release assets. | |
| 6 | -# | |
| 7 | -# Usage: | |
| 8 | -# ./docker-sbx/build.sh # TAG from release.env, image for this machine | |
| 9 | -# ./docker-sbx/build.sh v0.0.3 # override the tag for this run | |
| 10 | -# PUSH=1 ./docker-sbx/build.sh # multi-arch (linux/amd64 + linux/arm64) built | |
| 11 | -# # with buildx and PUSHED to the registry — | |
| 12 | -# # needs `docker login`; publish.sh does this | |
| 13 | -# IMAGE_OWNER=someone ./docker-sbx/build.sh # another image owner (default k33g) | |
| 14 | -# PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set | |
| 15 | -# SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh | |
| 16 | -# # base it on the Docker-in-Docker shell | |
| 17 | -# EXPORT=1 ./docker-sbx/build.sh # also `docker save` to tmp/, for | |
| 18 | -# # `sbx template load` on another host | |
| 19 | -# | |
| 20 | -# Whatever the mode, the two kits under docker-sbx/kits/ are then pointed at | |
| 21 | -# the image just built (docker-sbx/sync-kits.sh), so kits and image move | |
| 22 | -# together. Publishing the kits themselves is docker-sbx/push-kits.sh, and | |
| 23 | -# docker-sbx/publish.sh chains the two. | |
| 24 | -set -euo pipefail | |
| 25 | - | |
| 26 | -cd "$(dirname "$0")/.." | |
| 27 | - | |
| 28 | -# release.env carries TAG ("v0.0.2"). It is git-ignored, so a checkout without | |
| 29 | -# it names the tag on the command line. A tag given on the command line wins. | |
| 30 | -if [ -f release.env ]; then | |
| 31 | - # shellcheck source=/dev/null | |
| 32 | - source release.env | |
| 33 | -fi | |
| 34 | -TAG="${1:-${TAG:-}}" | |
| 35 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 36 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/build.sh v1.2.3)" | |
| 37 | - exit 1 | |
| 38 | -fi | |
| 39 | - | |
| 40 | -# Not OWNER: release.env uses that name for the git owner (bots-garden), and | |
| 41 | -# the image owner is a different thing — the Docker Hub account, k33g. | |
| 42 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | |
| 43 | -VERSION="${TAG#v}" | |
| 44 | -IMAGE="${IMAGE_OWNER}/mm-sandbox:${VERSION}" | |
| 45 | -PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | |
| 46 | - | |
| 47 | -build_args=(--build-arg "MM_VERSION=${TAG}") | |
| 48 | -if [ -n "${SHELL_TEMPLATE:-}" ]; then | |
| 49 | - build_args+=(--build-arg "SHELL_TEMPLATE=${SHELL_TEMPLATE}") | |
| 50 | -fi | |
| 51 | - | |
| 52 | -if [ -n "${PUSH:-}" ]; then | |
| 53 | - # Multi-arch needs buildx's container driver: the classic builder can | |
| 54 | - # neither assemble a manifest list nor build for a foreign platform. The | |
| 55 | - # Go stage cross-compiles on the build platform; only the final stage's | |
| 56 | - # `RUN mm --version` runs under emulation (Docker Desktop ships QEMU). | |
| 57 | - echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | |
| 58 | - if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | |
| 59 | - docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | |
| 60 | - fi | |
| 61 | - docker buildx build --builder mm-sandbox-builder \ | |
| 62 | - --platform "${PLATFORMS}" \ | |
| 63 | - -f docker-sbx/template/Dockerfile "${build_args[@]}" \ | |
| 64 | - -t "${IMAGE}" --push . | |
| 65 | - # The proof that ships: the registry holds one manifest per platform. | |
| 66 | - docker buildx imagetools inspect "${IMAGE}" | grep -E '^Name:|Platform:' | sed 's/^/ /' | |
| 67 | -else | |
| 68 | - echo "🐳 Building ${IMAGE} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | |
| 69 | - docker build -f docker-sbx/template/Dockerfile "${build_args[@]}" -t "${IMAGE}" . | |
| 70 | - | |
| 71 | - # The one proof that what was built starts: --version needs no config and | |
| 72 | - # no model server. It also confirms the stamp reached the binary. | |
| 73 | - reported="$(docker run --rm "${IMAGE}" mm --version)" | |
| 74 | - if ! grep -q -- "${TAG}" <<<"${reported}"; then | |
| 75 | - echo "❌ the image does not report ${TAG}: ${reported}" | |
| 76 | - exit 1 | |
| 77 | - fi | |
| 78 | - echo "✅ ${reported}" | |
| 79 | -fi | |
| 80 | - | |
| 81 | -./docker-sbx/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | |
| 82 | - | |
| 83 | -if [ -n "${EXPORT:-}" ]; then | |
| 84 | - mkdir -p tmp | |
| 85 | - docker save -o "tmp/mm-sandbox-${VERSION}.tar" "${IMAGE}" | |
| 86 | - echo "📦 tmp/mm-sandbox-${VERSION}.tar — load it where sbx runs with: sbx template load tmp/mm-sandbox-${VERSION}.tar" | |
| 87 | -fi | |
| 88 | - | |
| 89 | -if [ -n "${PUSH:-}" ]; then | |
| 90 | - cat <<NEXT | |
| 91 | - | |
| 92 | -Image on the registry. Publish the kits next: ./docker-sbx/push-kits.sh ${TAG} | |
| 93 | -NEXT | |
| 94 | -else | |
| 95 | - cat <<NEXT | |
| 96 | - | |
| 97 | -Next, from the project you want mm to work on: | |
| 98 | - | |
| 99 | - window mode sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | |
| 100 | - editor (ACP) sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . --kit-arg config=agent.dmr.yaml | |
| 101 | - then register sbx exec -i mm-acp mm -acp in the editor (docker-sbx/README.md) | |
| 102 | - | |
| 103 | - --pull never because ${IMAGE} exists only in the local image store; | |
| 104 | - after \`docker push ${IMAGE}\` (or PUSH=1) it is no longer needed. | |
| 105 | -NEXT | |
| 106 | -fi | |
| deleted file mode 100644 | |||
| @@ -1,106 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Build the mm sandbox template image, <owner>/mm-sandbox:<version>, from this | ||
| 3 | -# checkout. The image tag follows mm's own tag, minus the "v": release.env | ||
| 4 | -# says TAG="v0.0.2", the image is k33g/mm-sandbox:0.0.2 and `mm --version` | ||
| 5 | -# inside it reports v0.0.2 — the same rule as the release assets. | ||
| 6 | -# | ||
| 7 | -# Usage: | ||
| 8 | -# ./docker-sbx/build.sh # TAG from release.env, image for this machine | ||
| 9 | -# ./docker-sbx/build.sh v0.0.3 # override the tag for this run | ||
| 10 | -# PUSH=1 ./docker-sbx/build.sh # multi-arch (linux/amd64 + linux/arm64) built | ||
| 11 | -# # with buildx and PUSHED to the registry — | ||
| 12 | -# # needs `docker login`; publish.sh does this | ||
| 13 | -# IMAGE_OWNER=someone ./docker-sbx/build.sh # another image owner (default k33g) | ||
| 14 | -# PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set | ||
| 15 | -# SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh | ||
| 16 | -# # base it on the Docker-in-Docker shell | ||
| 17 | -# EXPORT=1 ./docker-sbx/build.sh # also `docker save` to tmp/, for | ||
| 18 | -# # `sbx template load` on another host | ||
| 19 | -# | ||
| 20 | -# Whatever the mode, the two kits under docker-sbx/kits/ are then pointed at | ||
| 21 | -# the image just built (docker-sbx/sync-kits.sh), so kits and image move | ||
| 22 | -# together. Publishing the kits themselves is docker-sbx/push-kits.sh, and | ||
| 23 | -# docker-sbx/publish.sh chains the two. | ||
| 24 | -set -euo pipefail | ||
| 25 | - | ||
| 26 | -cd "$(dirname "$0")/.." | ||
| 27 | - | ||
| 28 | -# release.env carries TAG ("v0.0.2"). It is git-ignored, so a checkout without | ||
| 29 | -# it names the tag on the command line. A tag given on the command line wins. | ||
| 30 | -if [ -f release.env ]; then | ||
| 31 | - # shellcheck source=/dev/null | ||
| 32 | - source release.env | ||
| 33 | -fi | ||
| 34 | -TAG="${1:-${TAG:-}}" | ||
| 35 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 36 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/build.sh v1.2.3)" | ||
| 37 | - exit 1 | ||
| 38 | -fi | ||
| 39 | - | ||
| 40 | -# Not OWNER: release.env uses that name for the git owner (bots-garden), and | ||
| 41 | -# the image owner is a different thing — the Docker Hub account, k33g. | ||
| 42 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | ||
| 43 | -VERSION="${TAG#v}" | ||
| 44 | -IMAGE="${IMAGE_OWNER}/mm-sandbox:${VERSION}" | ||
| 45 | -PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | ||
| 46 | - | ||
| 47 | -build_args=(--build-arg "MM_VERSION=${TAG}") | ||
| 48 | -if [ -n "${SHELL_TEMPLATE:-}" ]; then | ||
| 49 | - build_args+=(--build-arg "SHELL_TEMPLATE=${SHELL_TEMPLATE}") | ||
| 50 | -fi | ||
| 51 | - | ||
| 52 | -if [ -n "${PUSH:-}" ]; then | ||
| 53 | - # Multi-arch needs buildx's container driver: the classic builder can | ||
| 54 | - # neither assemble a manifest list nor build for a foreign platform. The | ||
| 55 | - # Go stage cross-compiles on the build platform; only the final stage's | ||
| 56 | - # `RUN mm --version` runs under emulation (Docker Desktop ships QEMU). | ||
| 57 | - echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | ||
| 58 | - if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | ||
| 59 | - docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | ||
| 60 | - fi | ||
| 61 | - docker buildx build --builder mm-sandbox-builder \ | ||
| 62 | - --platform "${PLATFORMS}" \ | ||
| 63 | - -f docker-sbx/template/Dockerfile "${build_args[@]}" \ | ||
| 64 | - -t "${IMAGE}" --push . | ||
| 65 | - # The proof that ships: the registry holds one manifest per platform. | ||
| 66 | - docker buildx imagetools inspect "${IMAGE}" | grep -E '^Name:|Platform:' | sed 's/^/ /' | ||
| 67 | -else | ||
| 68 | - echo "🐳 Building ${IMAGE} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | ||
| 69 | - docker build -f docker-sbx/template/Dockerfile "${build_args[@]}" -t "${IMAGE}" . | ||
| 70 | - | ||
| 71 | - # The one proof that what was built starts: --version needs no config and | ||
| 72 | - # no model server. It also confirms the stamp reached the binary. | ||
| 73 | - reported="$(docker run --rm "${IMAGE}" mm --version)" | ||
| 74 | - if ! grep -q -- "${TAG}" <<<"${reported}"; then | ||
| 75 | - echo "❌ the image does not report ${TAG}: ${reported}" | ||
| 76 | - exit 1 | ||
| 77 | - fi | ||
| 78 | - echo "✅ ${reported}" | ||
| 79 | -fi | ||
| 80 | - | ||
| 81 | -./docker-sbx/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | ||
| 82 | - | ||
| 83 | -if [ -n "${EXPORT:-}" ]; then | ||
| 84 | - mkdir -p tmp | ||
| 85 | - docker save -o "tmp/mm-sandbox-${VERSION}.tar" "${IMAGE}" | ||
| 86 | - echo "📦 tmp/mm-sandbox-${VERSION}.tar — load it where sbx runs with: sbx template load tmp/mm-sandbox-${VERSION}.tar" | ||
| 87 | -fi | ||
| 88 | - | ||
| 89 | -if [ -n "${PUSH:-}" ]; then | ||
| 90 | - cat <<NEXT | ||
| 91 | - | ||
| 92 | -Image on the registry. Publish the kits next: ./docker-sbx/push-kits.sh ${TAG} | ||
| 93 | -NEXT | ||
| 94 | -else | ||
| 95 | - cat <<NEXT | ||
| 96 | - | ||
| 97 | -Next, from the project you want mm to work on: | ||
| 98 | - | ||
| 99 | - window mode sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | ||
| 100 | - editor (ACP) sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . --kit-arg config=agent.dmr.yaml | ||
| 101 | - then register sbx exec -i mm-acp mm -acp in the editor (docker-sbx/README.md) | ||
| 102 | - | ||
| 103 | - --pull never because ${IMAGE} exists only in the local image store; | ||
| 104 | - after \`docker push ${IMAGE}\` (or PUSH=1) it is no longer needed. | ||
| 105 | -NEXT | ||
| 106 | -fi | ||
deleted
docker-sbx/kits/mm-acp/spec.yaml +0 -69 | deleted file mode 100644 | ||
| @@ -1,69 +0,0 @@ | ||
| 1 | -# Docker Sandboxes kit: mm as an editor's agent (Agent Client Protocol), inside | |
| 2 | -# the mm sandbox template. | |
| 3 | -# | |
| 4 | -# ./docker-sbx/build.sh # once: k33g/mm-sandbox:<version> | |
| 5 | -# sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . \ | |
| 6 | -# --kit-arg config=agent.dmr.yaml | |
| 7 | -# | |
| 8 | -# then, in the editor (Zed settings.json): | |
| 9 | -# | |
| 10 | -# "agent_servers": { "mini-me (sandbox)": { "type": "custom", | |
| 11 | -# "command": "sbx", "args": ["exec", "-i", "mm-acp", "mm", "-acp"] } } | |
| 12 | -# | |
| 13 | -# Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the | |
| 14 | -# agent's raw stdin/stdout, and `sbx run` always allocates a terminal. So the | |
| 15 | -# sandbox is created without attaching, and the editor starts `mm -acp` inside | |
| 16 | -# it for every conversation (sbx starts a stopped sandbox first). Attaching | |
| 17 | -# with `sbx run` runs the entry point below, which prints this wiring with the | |
| 18 | -# sandbox's real name and opens a shell. | |
| 19 | -schemaVersion: "2" | |
| 20 | -kind: sandbox | |
| 21 | -name: mm-acp | |
| 22 | -displayName: Mini Me (editor, ACP) | |
| 23 | -description: > | |
| 24 | - Holds mm, a minimal coding agent for local LLMs, for an editor that speaks | |
| 25 | - the Agent Client Protocol (Zed, …). The editor runs `sbx exec -i <sandbox> | |
| 26 | - mm -acp`; every command and file edit the model asks for happens inside the | |
| 27 | - sandbox, on the mounted workspace. The model server stays on the host, | |
| 28 | - reached through host.docker.internal. | |
| 29 | -# Kept equal to the image tag by docker-sbx/sync-kits.sh; becomes the | |
| 30 | -# vnd.docker.sandbox.kit.version annotation of the published kit. | |
| 31 | -version: "0.2.1" | |
| 32 | -sourceURL: https://git.rickub.com/bots-garden/mini-me | |
| 33 | - | |
| 34 | -args: | |
| 35 | - tag: | |
| 36 | - default: "0.2.1" | |
| 37 | - description: >- | |
| 38 | - Tag of the k33g/mm-sandbox image: mm's version without the "v", as | |
| 39 | - docker-sbx/build.sh tags it (and rewrites this default to). | |
| 40 | - pattern: '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$' | |
| 41 | - config: | |
| 42 | - default: "" | |
| 43 | - description: >- | |
| 44 | - Configuration file mm reads (its AGENT_CONFIG): an absolute path inside | |
| 45 | - the sandbox, or a path relative to the workspace, which is where | |
| 46 | - `sbx exec` starts mm. Empty: ./agent.yaml in the workspace, then the | |
| 47 | - built-in defaults. | |
| 48 | - | |
| 49 | -sandbox: | |
| 50 | - image: "k33g/mm-sandbox:${{ kit.args.tag }}" | |
| 51 | - # Not `mm -acp`: nothing useful comes of speaking JSON-RPC to a terminal. | |
| 52 | - entrypoint: [mm-acp-info] | |
| 53 | - | |
| 54 | -environment: | |
| 55 | - variables: | |
| 56 | - # Baked into the container, so `sbx exec` inherits it and the editor's | |
| 57 | - # settings need not repeat the path. `sbx exec -e AGENT_CONFIG=…` overrides | |
| 58 | - # it for one session. | |
| 59 | - AGENT_CONFIG: "${{ kit.args.config }}" | |
| 60 | - LANG: C.UTF-8 | |
| 61 | - | |
| 62 | -# The model server on the host — see docker-sbx/kits/mm-tui/spec.yaml. | |
| 63 | -permissions: | |
| 64 | - network: | |
| 65 | - allow: | |
| 66 | - - "host.docker.internal:12434" | |
| 67 | - - "localhost:12434" | |
| 68 | - - "host.docker.internal:8080" | |
| 69 | - - "localhost:8080" | |
| deleted file mode 100644 | |||
| @@ -1,69 +0,0 @@ | |||
| 1 | -# Docker Sandboxes kit: mm as an editor's agent (Agent Client Protocol), inside | ||
| 2 | -# the mm sandbox template. | ||
| 3 | -# | ||
| 4 | -# ./docker-sbx/build.sh # once: k33g/mm-sandbox:<version> | ||
| 5 | -# sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . \ | ||
| 6 | -# --kit-arg config=agent.dmr.yaml | ||
| 7 | -# | ||
| 8 | -# then, in the editor (Zed settings.json): | ||
| 9 | -# | ||
| 10 | -# "agent_servers": { "mini-me (sandbox)": { "type": "custom", | ||
| 11 | -# "command": "sbx", "args": ["exec", "-i", "mm-acp", "mm", "-acp"] } } | ||
| 12 | -# | ||
| 13 | -# Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the | ||
| 14 | -# agent's raw stdin/stdout, and `sbx run` always allocates a terminal. So the | ||
| 15 | -# sandbox is created without attaching, and the editor starts `mm -acp` inside | ||
| 16 | -# it for every conversation (sbx starts a stopped sandbox first). Attaching | ||
| 17 | -# with `sbx run` runs the entry point below, which prints this wiring with the | ||
| 18 | -# sandbox's real name and opens a shell. | ||
| 19 | -schemaVersion: "2" | ||
| 20 | -kind: sandbox | ||
| 21 | -name: mm-acp | ||
| 22 | -displayName: Mini Me (editor, ACP) | ||
| 23 | -description: > | ||
| 24 | - Holds mm, a minimal coding agent for local LLMs, for an editor that speaks | ||
| 25 | - the Agent Client Protocol (Zed, …). The editor runs `sbx exec -i <sandbox> | ||
| 26 | - mm -acp`; every command and file edit the model asks for happens inside the | ||
| 27 | - sandbox, on the mounted workspace. The model server stays on the host, | ||
| 28 | - reached through host.docker.internal. | ||
| 29 | -# Kept equal to the image tag by docker-sbx/sync-kits.sh; becomes the | ||
| 30 | -# vnd.docker.sandbox.kit.version annotation of the published kit. | ||
| 31 | -version: "0.2.1" | ||
| 32 | -sourceURL: https://git.rickub.com/bots-garden/mini-me | ||
| 33 | - | ||
| 34 | -args: | ||
| 35 | - tag: | ||
| 36 | - default: "0.2.1" | ||
| 37 | - description: >- | ||
| 38 | - Tag of the k33g/mm-sandbox image: mm's version without the "v", as | ||
| 39 | - docker-sbx/build.sh tags it (and rewrites this default to). | ||
| 40 | - pattern: '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$' | ||
| 41 | - config: | ||
| 42 | - default: "" | ||
| 43 | - description: >- | ||
| 44 | - Configuration file mm reads (its AGENT_CONFIG): an absolute path inside | ||
| 45 | - the sandbox, or a path relative to the workspace, which is where | ||
| 46 | - `sbx exec` starts mm. Empty: ./agent.yaml in the workspace, then the | ||
| 47 | - built-in defaults. | ||
| 48 | - | ||
| 49 | -sandbox: | ||
| 50 | - image: "k33g/mm-sandbox:${{ kit.args.tag }}" | ||
| 51 | - # Not `mm -acp`: nothing useful comes of speaking JSON-RPC to a terminal. | ||
| 52 | - entrypoint: [mm-acp-info] | ||
| 53 | - | ||
| 54 | -environment: | ||
| 55 | - variables: | ||
| 56 | - # Baked into the container, so `sbx exec` inherits it and the editor's | ||
| 57 | - # settings need not repeat the path. `sbx exec -e AGENT_CONFIG=…` overrides | ||
| 58 | - # it for one session. | ||
| 59 | - AGENT_CONFIG: "${{ kit.args.config }}" | ||
| 60 | - LANG: C.UTF-8 | ||
| 61 | - | ||
| 62 | -# The model server on the host — see docker-sbx/kits/mm-tui/spec.yaml. | ||
| 63 | -permissions: | ||
| 64 | - network: | ||
| 65 | - allow: | ||
| 66 | - - "host.docker.internal:12434" | ||
| 67 | - - "localhost:12434" | ||
| 68 | - - "host.docker.internal:8080" | ||
| 69 | - - "localhost:8080" | ||
deleted
docker-sbx/kits/mm-tui/spec.yaml +0 -68 | deleted file mode 100644 | ||
| @@ -1,68 +0,0 @@ | ||
| 1 | -# Docker Sandboxes kit: mm in its window mode, inside the mm sandbox template. | |
| 2 | -# | |
| 3 | -# ./docker-sbx/build.sh # once: k33g/mm-sandbox:<version> | |
| 4 | -# sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | |
| 5 | -# | |
| 6 | -# What follows "--" reaches mm as its own arguments (here the configuration | |
| 7 | -# file, relative to the workspace). Without it, the `config` argument below is | |
| 8 | -# read, then ./agent.yaml, then the built-in defaults: | |
| 9 | -# | |
| 10 | -# sbx run --pull never ./docker-sbx/kits/mm-tui . --kit-arg config=agent.dmr.yaml | |
| 11 | -# | |
| 12 | -# --pull never: the image is built locally; drop it once it is pushed. | |
| 13 | -schemaVersion: "2" | |
| 14 | -kind: sandbox | |
| 15 | -name: mm-tui | |
| 16 | -displayName: Mini Me (window mode) | |
| 17 | -description: > | |
| 18 | - Runs mm, a minimal coding agent for local LLMs, in its single-window terminal | |
| 19 | - mode (`mm -tui`) on the workspace. The model server (Docker Model Runner or | |
| 20 | - llama-server) stays on the host: inside the sandbox `localhost` is the sandbox | |
| 21 | - itself, so the configuration file must reach the host through | |
| 22 | - host.docker.internal — agent.dmr.yaml already falls back to it. | |
| 23 | -# Kept equal to the image tag by docker-sbx/sync-kits.sh; becomes the | |
| 24 | -# vnd.docker.sandbox.kit.version annotation of the published kit. | |
| 25 | -version: "0.2.1" | |
| 26 | -sourceURL: https://git.rickub.com/bots-garden/mini-me | |
| 27 | - | |
| 28 | -args: | |
| 29 | - tag: | |
| 30 | - default: "0.2.1" | |
| 31 | - description: >- | |
| 32 | - Tag of the k33g/mm-sandbox image: mm's version without the "v", as | |
| 33 | - docker-sbx/build.sh tags it (and rewrites this default to). | |
| 34 | - pattern: '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$' | |
| 35 | - config: | |
| 36 | - default: "" | |
| 37 | - description: >- | |
| 38 | - Configuration file mm reads (its AGENT_CONFIG): an absolute path inside | |
| 39 | - the sandbox, or a path relative to the workspace. Empty: ./agent.yaml in | |
| 40 | - the workspace, then the built-in defaults. | |
| 41 | - | |
| 42 | -sandbox: | |
| 43 | - image: "k33g/mm-sandbox:${{ kit.args.tag }}" | |
| 44 | - # A wrapper, not `mm -tui` directly: the start script drops the fixed | |
| 45 | - # options when the first user argument is not a flag, so `-- agent.yaml` | |
| 46 | - # would otherwise lose -tui. The wrapper always adds it. | |
| 47 | - entrypoint: [mm-tui] | |
| 48 | - | |
| 49 | -environment: | |
| 50 | - variables: | |
| 51 | - AGENT_CONFIG: "${{ kit.args.config }}" | |
| 52 | - # tcell needs a terminal type and a UTF-8 locale to draw the window. | |
| 53 | - TERM: xterm-256color | |
| 54 | - COLORTERM: truecolor | |
| 55 | - LANG: C.UTF-8 | |
| 56 | - | |
| 57 | -# The model server on the host. Requests leave the sandbox through its proxy, | |
| 58 | -# which maps host.docker.internal to the host's localhost; both spellings are | |
| 59 | -# listed so the rule matches whichever one the policy is checked against. | |
| 60 | -# 12434 is Docker Model Runner, 8080 is llama-server's default. Add your own | |
| 61 | -# port with `sbx policy allow network host.docker.internal:<port>`. | |
| 62 | -permissions: | |
| 63 | - network: | |
| 64 | - allow: | |
| 65 | - - "host.docker.internal:12434" | |
| 66 | - - "localhost:12434" | |
| 67 | - - "host.docker.internal:8080" | |
| 68 | - - "localhost:8080" | |
| deleted file mode 100644 | |||
| @@ -1,68 +0,0 @@ | |||
| 1 | -# Docker Sandboxes kit: mm in its window mode, inside the mm sandbox template. | ||
| 2 | -# | ||
| 3 | -# ./docker-sbx/build.sh # once: k33g/mm-sandbox:<version> | ||
| 4 | -# sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | ||
| 5 | -# | ||
| 6 | -# What follows "--" reaches mm as its own arguments (here the configuration | ||
| 7 | -# file, relative to the workspace). Without it, the `config` argument below is | ||
| 8 | -# read, then ./agent.yaml, then the built-in defaults: | ||
| 9 | -# | ||
| 10 | -# sbx run --pull never ./docker-sbx/kits/mm-tui . --kit-arg config=agent.dmr.yaml | ||
| 11 | -# | ||
| 12 | -# --pull never: the image is built locally; drop it once it is pushed. | ||
| 13 | -schemaVersion: "2" | ||
| 14 | -kind: sandbox | ||
| 15 | -name: mm-tui | ||
| 16 | -displayName: Mini Me (window mode) | ||
| 17 | -description: > | ||
| 18 | - Runs mm, a minimal coding agent for local LLMs, in its single-window terminal | ||
| 19 | - mode (`mm -tui`) on the workspace. The model server (Docker Model Runner or | ||
| 20 | - llama-server) stays on the host: inside the sandbox `localhost` is the sandbox | ||
| 21 | - itself, so the configuration file must reach the host through | ||
| 22 | - host.docker.internal — agent.dmr.yaml already falls back to it. | ||
| 23 | -# Kept equal to the image tag by docker-sbx/sync-kits.sh; becomes the | ||
| 24 | -# vnd.docker.sandbox.kit.version annotation of the published kit. | ||
| 25 | -version: "0.2.1" | ||
| 26 | -sourceURL: https://git.rickub.com/bots-garden/mini-me | ||
| 27 | - | ||
| 28 | -args: | ||
| 29 | - tag: | ||
| 30 | - default: "0.2.1" | ||
| 31 | - description: >- | ||
| 32 | - Tag of the k33g/mm-sandbox image: mm's version without the "v", as | ||
| 33 | - docker-sbx/build.sh tags it (and rewrites this default to). | ||
| 34 | - pattern: '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$' | ||
| 35 | - config: | ||
| 36 | - default: "" | ||
| 37 | - description: >- | ||
| 38 | - Configuration file mm reads (its AGENT_CONFIG): an absolute path inside | ||
| 39 | - the sandbox, or a path relative to the workspace. Empty: ./agent.yaml in | ||
| 40 | - the workspace, then the built-in defaults. | ||
| 41 | - | ||
| 42 | -sandbox: | ||
| 43 | - image: "k33g/mm-sandbox:${{ kit.args.tag }}" | ||
| 44 | - # A wrapper, not `mm -tui` directly: the start script drops the fixed | ||
| 45 | - # options when the first user argument is not a flag, so `-- agent.yaml` | ||
| 46 | - # would otherwise lose -tui. The wrapper always adds it. | ||
| 47 | - entrypoint: [mm-tui] | ||
| 48 | - | ||
| 49 | -environment: | ||
| 50 | - variables: | ||
| 51 | - AGENT_CONFIG: "${{ kit.args.config }}" | ||
| 52 | - # tcell needs a terminal type and a UTF-8 locale to draw the window. | ||
| 53 | - TERM: xterm-256color | ||
| 54 | - COLORTERM: truecolor | ||
| 55 | - LANG: C.UTF-8 | ||
| 56 | - | ||
| 57 | -# The model server on the host. Requests leave the sandbox through its proxy, | ||
| 58 | -# which maps host.docker.internal to the host's localhost; both spellings are | ||
| 59 | -# listed so the rule matches whichever one the policy is checked against. | ||
| 60 | -# 12434 is Docker Model Runner, 8080 is llama-server's default. Add your own | ||
| 61 | -# port with `sbx policy allow network host.docker.internal:<port>`. | ||
| 62 | -permissions: | ||
| 63 | - network: | ||
| 64 | - allow: | ||
| 65 | - - "host.docker.internal:12434" | ||
| 66 | - - "localhost:12434" | ||
| 67 | - - "host.docker.internal:8080" | ||
| 68 | - - "localhost:8080" | ||
deleted
docker-sbx/mcp/github-mcp.sh +0 -51 | deleted file mode 100644 | ||
| @@ -1,51 +0,0 @@ | ||
| 1 | -#!/bin/sh | |
| 2 | -# GitHub's official MCP server (github/github-mcp-server) over stdio, for the | |
| 3 | -# sbx MCP gateway: | |
| 4 | -# | |
| 5 | -# sbx mcp add github-mm --command "$PWD/docker-sbx/mcp/github-mcp.sh" | |
| 6 | -# | |
| 7 | -# sbx runs this ON THE HOST, as a child of sandboxd, never inside the sandbox: | |
| 8 | -# the token stays on your machine and the sandbox only sees the gateway. | |
| 9 | -# | |
| 10 | -# Why a script: in sbx's local mode a catalog image is started as a bare | |
| 11 | -# `docker run -i --rm <image>`, with no environment, so the catalog's | |
| 12 | -# github-official entry would start without a token, and `sbx mcp add` has no | |
| 13 | -# --env flag. A --command server inherits sandboxd's environment instead, and | |
| 14 | -# this script adds the token to it. | |
| 15 | -# | |
| 16 | -# Token, first found: $GITHUB_PERSONAL_ACCESS_TOKEN, $GITHUB_OAUTH_TOKEN, the | |
| 17 | -# macOS keychain item "github-mcp", `gh auth token`. | |
| 18 | -# Tools: read-only and four toolsets by default (25 tools) — a small local | |
| 19 | -# model copes badly with 40+. Override with GITHUB_TOOLSETS / GITHUB_READ_ONLY. | |
| 20 | -set -eu | |
| 21 | - | |
| 22 | -# sandboxd may start with a minimal PATH: add the usual macOS locations of | |
| 23 | -# docker and gh. | |
| 24 | -PATH="/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH" | |
| 25 | -export PATH | |
| 26 | - | |
| 27 | -# sandboxd does NOT see the variables of your interactive shell, so on macOS | |
| 28 | -# the reliable place for the token is the login keychain, stored once with: | |
| 29 | -# security add-generic-password -U -a "$USER" -s github-mcp -w | |
| 30 | -# (it prompts for the token; `-w "$GITHUB_OAUTH_TOKEN"` works too). | |
| 31 | -service="${GITHUB_MCP_KEYCHAIN_SERVICE:-github-mcp}" | |
| 32 | -token="${GITHUB_PERSONAL_ACCESS_TOKEN:-${GITHUB_OAUTH_TOKEN:-}}" | |
| 33 | -if [ -z "$token" ] && command -v security >/dev/null 2>&1; then | |
| 34 | - token="$(security find-generic-password -s "$service" -w 2>/dev/null || true)" | |
| 35 | -fi | |
| 36 | -if [ -z "$token" ] && command -v gh >/dev/null 2>&1; then | |
| 37 | - token="$(gh auth token 2>/dev/null || true)" | |
| 38 | -fi | |
| 39 | -if [ -z "$token" ]; then | |
| 40 | - echo "github-mcp: no token: store it with 'security add-generic-password -U -a \"\$USER\" -s $service -w', or run 'gh auth login'" >&2 | |
| 41 | - exit 1 | |
| 42 | -fi | |
| 43 | -GITHUB_PERSONAL_ACCESS_TOKEN="$token" | |
| 44 | -export GITHUB_PERSONAL_ACCESS_TOKEN | |
| 45 | - | |
| 46 | -# stdout is the MCP channel: nothing but the server may write to it. | |
| 47 | -exec docker run -i --rm \ | |
| 48 | - -e GITHUB_PERSONAL_ACCESS_TOKEN \ | |
| 49 | - -e GITHUB_TOOLSETS="${GITHUB_TOOLSETS:-context,repos,issues,pull_requests}" \ | |
| 50 | - -e GITHUB_READ_ONLY="${GITHUB_READ_ONLY:-1}" \ | |
| 51 | - "${GITHUB_MCP_IMAGE:-ghcr.io/github/github-mcp-server}" stdio | |
| deleted file mode 100644 | |||
| @@ -1,51 +0,0 @@ | |||
| 1 | -#!/bin/sh | ||
| 2 | -# GitHub's official MCP server (github/github-mcp-server) over stdio, for the | ||
| 3 | -# sbx MCP gateway: | ||
| 4 | -# | ||
| 5 | -# sbx mcp add github-mm --command "$PWD/docker-sbx/mcp/github-mcp.sh" | ||
| 6 | -# | ||
| 7 | -# sbx runs this ON THE HOST, as a child of sandboxd, never inside the sandbox: | ||
| 8 | -# the token stays on your machine and the sandbox only sees the gateway. | ||
| 9 | -# | ||
| 10 | -# Why a script: in sbx's local mode a catalog image is started as a bare | ||
| 11 | -# `docker run -i --rm <image>`, with no environment, so the catalog's | ||
| 12 | -# github-official entry would start without a token, and `sbx mcp add` has no | ||
| 13 | -# --env flag. A --command server inherits sandboxd's environment instead, and | ||
| 14 | -# this script adds the token to it. | ||
| 15 | -# | ||
| 16 | -# Token, first found: $GITHUB_PERSONAL_ACCESS_TOKEN, $GITHUB_OAUTH_TOKEN, the | ||
| 17 | -# macOS keychain item "github-mcp", `gh auth token`. | ||
| 18 | -# Tools: read-only and four toolsets by default (25 tools) — a small local | ||
| 19 | -# model copes badly with 40+. Override with GITHUB_TOOLSETS / GITHUB_READ_ONLY. | ||
| 20 | -set -eu | ||
| 21 | - | ||
| 22 | -# sandboxd may start with a minimal PATH: add the usual macOS locations of | ||
| 23 | -# docker and gh. | ||
| 24 | -PATH="/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH" | ||
| 25 | -export PATH | ||
| 26 | - | ||
| 27 | -# sandboxd does NOT see the variables of your interactive shell, so on macOS | ||
| 28 | -# the reliable place for the token is the login keychain, stored once with: | ||
| 29 | -# security add-generic-password -U -a "$USER" -s github-mcp -w | ||
| 30 | -# (it prompts for the token; `-w "$GITHUB_OAUTH_TOKEN"` works too). | ||
| 31 | -service="${GITHUB_MCP_KEYCHAIN_SERVICE:-github-mcp}" | ||
| 32 | -token="${GITHUB_PERSONAL_ACCESS_TOKEN:-${GITHUB_OAUTH_TOKEN:-}}" | ||
| 33 | -if [ -z "$token" ] && command -v security >/dev/null 2>&1; then | ||
| 34 | - token="$(security find-generic-password -s "$service" -w 2>/dev/null || true)" | ||
| 35 | -fi | ||
| 36 | -if [ -z "$token" ] && command -v gh >/dev/null 2>&1; then | ||
| 37 | - token="$(gh auth token 2>/dev/null || true)" | ||
| 38 | -fi | ||
| 39 | -if [ -z "$token" ]; then | ||
| 40 | - echo "github-mcp: no token: store it with 'security add-generic-password -U -a \"\$USER\" -s $service -w', or run 'gh auth login'" >&2 | ||
| 41 | - exit 1 | ||
| 42 | -fi | ||
| 43 | -GITHUB_PERSONAL_ACCESS_TOKEN="$token" | ||
| 44 | -export GITHUB_PERSONAL_ACCESS_TOKEN | ||
| 45 | - | ||
| 46 | -# stdout is the MCP channel: nothing but the server may write to it. | ||
| 47 | -exec docker run -i --rm \ | ||
| 48 | - -e GITHUB_PERSONAL_ACCESS_TOKEN \ | ||
| 49 | - -e GITHUB_TOOLSETS="${GITHUB_TOOLSETS:-context,repos,issues,pull_requests}" \ | ||
| 50 | - -e GITHUB_READ_ONLY="${GITHUB_READ_ONLY:-1}" \ | ||
| 51 | - "${GITHUB_MCP_IMAGE:-ghcr.io/github/github-mcp-server}" stdio | ||
deleted
docker-sbx/publish.sh +0 -82 | deleted file mode 100644 | ||
| @@ -1,82 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Build and publish everything to Docker Hub, by hand, in one go: | |
| 3 | -# <owner>/mm-sandbox:<version> the template image, linux/amd64 + linux/arm64 | |
| 4 | -# <owner>/mm-tui:<version> the window-mode kit | |
| 5 | -# <owner>/mm-acp:<version> the editor (ACP) kit | |
| 6 | -# | |
| 7 | -# Usage: | |
| 8 | -# ./docker-sbx/publish.sh # TAG from release.env (v0.0.3 → 0.0.3) | |
| 9 | -# ./docker-sbx/publish.sh v0.0.4 # another tag | |
| 10 | -# | |
| 11 | -# Credentials, two environment variables: | |
| 12 | -# DOCKER_HANDLE the Docker Hub account — also the image owner (default k33g) | |
| 13 | -# DOCKER_PAT an access token with read/write scope | |
| 14 | -# With both set, the script logs in with them (and out at the end). With | |
| 15 | -# neither, it uses the login you already have (`docker login` done earlier). | |
| 16 | -# | |
| 17 | -# Needs: docker with buildx (Docker Desktop has it), and the sbx CLI for the | |
| 18 | -# kits (`SBX=/path/to/sbx` if it is not on the PATH). Pieces, runnable alone: | |
| 19 | -# PUSH=1 ./docker-sbx/build.sh TAG image only | |
| 20 | -# ./docker-sbx/push-kits.sh TAG kits only | |
| 21 | -set -euo pipefail | |
| 22 | - | |
| 23 | -cd "$(dirname "$0")/.." | |
| 24 | - | |
| 25 | -if [ -f release.env ]; then | |
| 26 | - # shellcheck source=/dev/null | |
| 27 | - source release.env | |
| 28 | -fi | |
| 29 | -TAG="${1:-${TAG:-}}" | |
| 30 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 31 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/publish.sh v1.2.3)" | |
| 32 | - exit 1 | |
| 33 | -fi | |
| 34 | - | |
| 35 | -# Secrets pasted with a trailing newline or stray spaces are a classic. | |
| 36 | -DOCKER_HANDLE="$(printf '%s' "${DOCKER_HANDLE:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 37 | -DOCKER_PAT="$(printf '%s' "${DOCKER_PAT:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 38 | -case "${DOCKER_HANDLE}" in | |
| 39 | -*@* | *:*) | |
| 40 | - echo "❌ DOCKER_HANDLE must be the Docker ID (username), not an e-mail: access tokens only pair with the username" | |
| 41 | - exit 1 | |
| 42 | - ;; | |
| 43 | -esac | |
| 44 | -export IMAGE_OWNER="${IMAGE_OWNER:-${DOCKER_HANDLE:-k33g}}" | |
| 45 | -VERSION="${TAG#v}" | |
| 46 | - | |
| 47 | -SBX="${SBX:-sbx}" | |
| 48 | -if ! command -v "${SBX}" >/dev/null 2>&1; then | |
| 49 | - echo "❌ sbx not found (${SBX}): install Docker Sandboxes, or SBX=/path/to/sbx" | |
| 50 | - exit 1 | |
| 51 | -fi | |
| 52 | -export SBX | |
| 53 | - | |
| 54 | -logged_in_here="" | |
| 55 | -if [ -n "${DOCKER_HANDLE}" ] && [ -n "${DOCKER_PAT}" ]; then | |
| 56 | - echo "🔐 docker login as ${DOCKER_HANDLE}" | |
| 57 | - printf '%s' "${DOCKER_PAT}" | docker login --username "${DOCKER_HANDLE}" --password-stdin | |
| 58 | - logged_in_here=1 | |
| 59 | -elif [ -n "${DOCKER_HANDLE}${DOCKER_PAT}" ]; then | |
| 60 | - echo "❌ set both DOCKER_HANDLE and DOCKER_PAT, or neither (to reuse an existing docker login)" | |
| 61 | - exit 1 | |
| 62 | -else | |
| 63 | - echo "🔐 no DOCKER_HANDLE/DOCKER_PAT: using the existing docker login, publishing under ${IMAGE_OWNER}" | |
| 64 | -fi | |
| 65 | -# Whatever happens below, a login made here does not outlive the script. | |
| 66 | -cleanup() { | |
| 67 | - if [ -n "${logged_in_here}" ]; then | |
| 68 | - docker logout >/dev/null 2>&1 || true | |
| 69 | - fi | |
| 70 | -} | |
| 71 | -trap cleanup EXIT | |
| 72 | - | |
| 73 | -echo | |
| 74 | -echo "═══ 1/2 image ${IMAGE_OWNER}/mm-sandbox:${VERSION}" | |
| 75 | -PUSH=1 ./docker-sbx/build.sh "${TAG}" | |
| 76 | - | |
| 77 | -echo | |
| 78 | -echo "═══ 2/2 kits ${IMAGE_OWNER}/mm-tui:${VERSION} and ${IMAGE_OWNER}/mm-acp:${VERSION}" | |
| 79 | -./docker-sbx/push-kits.sh "${TAG}" | |
| 80 | - | |
| 81 | -echo | |
| 82 | -echo "✨ Published ${TAG}. The kits' spec.yaml now name version ${VERSION} — commit them." | |
| deleted file mode 100644 | |||
| @@ -1,82 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Build and publish everything to Docker Hub, by hand, in one go: | ||
| 3 | -# <owner>/mm-sandbox:<version> the template image, linux/amd64 + linux/arm64 | ||
| 4 | -# <owner>/mm-tui:<version> the window-mode kit | ||
| 5 | -# <owner>/mm-acp:<version> the editor (ACP) kit | ||
| 6 | -# | ||
| 7 | -# Usage: | ||
| 8 | -# ./docker-sbx/publish.sh # TAG from release.env (v0.0.3 → 0.0.3) | ||
| 9 | -# ./docker-sbx/publish.sh v0.0.4 # another tag | ||
| 10 | -# | ||
| 11 | -# Credentials, two environment variables: | ||
| 12 | -# DOCKER_HANDLE the Docker Hub account — also the image owner (default k33g) | ||
| 13 | -# DOCKER_PAT an access token with read/write scope | ||
| 14 | -# With both set, the script logs in with them (and out at the end). With | ||
| 15 | -# neither, it uses the login you already have (`docker login` done earlier). | ||
| 16 | -# | ||
| 17 | -# Needs: docker with buildx (Docker Desktop has it), and the sbx CLI for the | ||
| 18 | -# kits (`SBX=/path/to/sbx` if it is not on the PATH). Pieces, runnable alone: | ||
| 19 | -# PUSH=1 ./docker-sbx/build.sh TAG image only | ||
| 20 | -# ./docker-sbx/push-kits.sh TAG kits only | ||
| 21 | -set -euo pipefail | ||
| 22 | - | ||
| 23 | -cd "$(dirname "$0")/.." | ||
| 24 | - | ||
| 25 | -if [ -f release.env ]; then | ||
| 26 | - # shellcheck source=/dev/null | ||
| 27 | - source release.env | ||
| 28 | -fi | ||
| 29 | -TAG="${1:-${TAG:-}}" | ||
| 30 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 31 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/publish.sh v1.2.3)" | ||
| 32 | - exit 1 | ||
| 33 | -fi | ||
| 34 | - | ||
| 35 | -# Secrets pasted with a trailing newline or stray spaces are a classic. | ||
| 36 | -DOCKER_HANDLE="$(printf '%s' "${DOCKER_HANDLE:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 37 | -DOCKER_PAT="$(printf '%s' "${DOCKER_PAT:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 38 | -case "${DOCKER_HANDLE}" in | ||
| 39 | -*@* | *:*) | ||
| 40 | - echo "❌ DOCKER_HANDLE must be the Docker ID (username), not an e-mail: access tokens only pair with the username" | ||
| 41 | - exit 1 | ||
| 42 | - ;; | ||
| 43 | -esac | ||
| 44 | -export IMAGE_OWNER="${IMAGE_OWNER:-${DOCKER_HANDLE:-k33g}}" | ||
| 45 | -VERSION="${TAG#v}" | ||
| 46 | - | ||
| 47 | -SBX="${SBX:-sbx}" | ||
| 48 | -if ! command -v "${SBX}" >/dev/null 2>&1; then | ||
| 49 | - echo "❌ sbx not found (${SBX}): install Docker Sandboxes, or SBX=/path/to/sbx" | ||
| 50 | - exit 1 | ||
| 51 | -fi | ||
| 52 | -export SBX | ||
| 53 | - | ||
| 54 | -logged_in_here="" | ||
| 55 | -if [ -n "${DOCKER_HANDLE}" ] && [ -n "${DOCKER_PAT}" ]; then | ||
| 56 | - echo "🔐 docker login as ${DOCKER_HANDLE}" | ||
| 57 | - printf '%s' "${DOCKER_PAT}" | docker login --username "${DOCKER_HANDLE}" --password-stdin | ||
| 58 | - logged_in_here=1 | ||
| 59 | -elif [ -n "${DOCKER_HANDLE}${DOCKER_PAT}" ]; then | ||
| 60 | - echo "❌ set both DOCKER_HANDLE and DOCKER_PAT, or neither (to reuse an existing docker login)" | ||
| 61 | - exit 1 | ||
| 62 | -else | ||
| 63 | - echo "🔐 no DOCKER_HANDLE/DOCKER_PAT: using the existing docker login, publishing under ${IMAGE_OWNER}" | ||
| 64 | -fi | ||
| 65 | -# Whatever happens below, a login made here does not outlive the script. | ||
| 66 | -cleanup() { | ||
| 67 | - if [ -n "${logged_in_here}" ]; then | ||
| 68 | - docker logout >/dev/null 2>&1 || true | ||
| 69 | - fi | ||
| 70 | -} | ||
| 71 | -trap cleanup EXIT | ||
| 72 | - | ||
| 73 | -echo | ||
| 74 | -echo "═══ 1/2 image ${IMAGE_OWNER}/mm-sandbox:${VERSION}" | ||
| 75 | -PUSH=1 ./docker-sbx/build.sh "${TAG}" | ||
| 76 | - | ||
| 77 | -echo | ||
| 78 | -echo "═══ 2/2 kits ${IMAGE_OWNER}/mm-tui:${VERSION} and ${IMAGE_OWNER}/mm-acp:${VERSION}" | ||
| 79 | -./docker-sbx/push-kits.sh "${TAG}" | ||
| 80 | - | ||
| 81 | -echo | ||
| 82 | -echo "✨ Published ${TAG}. The kits' spec.yaml now name version ${VERSION} — commit them." | ||
deleted
docker-sbx/push-kits.sh +0 -59 | deleted file mode 100644 | ||
| @@ -1,59 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Publish the two kits to Docker Hub as OCI kit artifacts: | |
| 3 | -# <owner>/mm-tui:<version> and <owner>/mm-acp:<version> | |
| 4 | -# | |
| 5 | -# Usage: | |
| 6 | -# ./docker-sbx/push-kits.sh # TAG from release.env | |
| 7 | -# ./docker-sbx/push-kits.sh v0.0.3 # override the tag | |
| 8 | -# IMAGE_OWNER=someone … # another owner (default k33g); the kits | |
| 9 | -# # are re-pointed at someone/mm-sandbox too | |
| 10 | -# REGISTRY=localhost:5000 … # another registry (default docker.io) | |
| 11 | -# SBX=/path/to/sbx … # the sbx binary, if not on the PATH | |
| 12 | -# | |
| 13 | -# Needs a login: `docker login -u <handle>` with a Docker Hub access token. | |
| 14 | -# `sbx kit push` talks to the registry directly — no sandbox daemon involved — | |
| 15 | -# and falls back to the Docker credential store for authentication. | |
| 16 | -# | |
| 17 | -# publish.sh runs this after the image. Push the image first: a kit names | |
| 18 | -# <owner>/mm-sandbox:<version>, and sbx pulls that image when the kit is used. | |
| 19 | -set -euo pipefail | |
| 20 | - | |
| 21 | -cd "$(dirname "$0")/.." | |
| 22 | - | |
| 23 | -if [ -f release.env ]; then | |
| 24 | - # shellcheck source=/dev/null | |
| 25 | - source release.env | |
| 26 | -fi | |
| 27 | -TAG="${1:-${TAG:-}}" | |
| 28 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 29 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/push-kits.sh v1.2.3)" | |
| 30 | - exit 1 | |
| 31 | -fi | |
| 32 | - | |
| 33 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | |
| 34 | -REGISTRY="${REGISTRY:-docker.io}" | |
| 35 | -VERSION="${TAG#v}" | |
| 36 | -SBX="${SBX:-sbx}" | |
| 37 | - | |
| 38 | -if ! command -v "${SBX}" >/dev/null 2>&1; then | |
| 39 | - echo "❌ sbx not found (${SBX}). Install Docker Sandboxes, or SBX=/path/to/sbx" | |
| 40 | - exit 1 | |
| 41 | -fi | |
| 42 | - | |
| 43 | -./docker-sbx/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | |
| 44 | - | |
| 45 | -for dir in docker-sbx/kits/*/; do | |
| 46 | - kit="$(basename "${dir}")" | |
| 47 | - ref="${REGISTRY}/${IMAGE_OWNER}/${kit}:${VERSION}" | |
| 48 | - "${SBX}" kit validate "${dir}" | |
| 49 | - "${SBX}" kit push "${dir}" "${ref}" | |
| 50 | -done | |
| 51 | - | |
| 52 | -cat <<NEXT | |
| 53 | - | |
| 54 | -Published. From any machine with Docker Sandboxes (docker.io is an allowed kit source by default): | |
| 55 | - | |
| 56 | - window mode sbx run ${IMAGE_OWNER}/mm-tui:${VERSION} . -- agent.dmr.yaml | |
| 57 | - editor (ACP) sbx create --name mm-acp ${IMAGE_OWNER}/mm-acp:${VERSION} . --kit-arg config=agent.dmr.yaml | |
| 58 | - then register sbx exec -i mm-acp mm -acp in the editor | |
| 59 | -NEXT | |
| deleted file mode 100644 | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Publish the two kits to Docker Hub as OCI kit artifacts: | ||
| 3 | -# <owner>/mm-tui:<version> and <owner>/mm-acp:<version> | ||
| 4 | -# | ||
| 5 | -# Usage: | ||
| 6 | -# ./docker-sbx/push-kits.sh # TAG from release.env | ||
| 7 | -# ./docker-sbx/push-kits.sh v0.0.3 # override the tag | ||
| 8 | -# IMAGE_OWNER=someone … # another owner (default k33g); the kits | ||
| 9 | -# # are re-pointed at someone/mm-sandbox too | ||
| 10 | -# REGISTRY=localhost:5000 … # another registry (default docker.io) | ||
| 11 | -# SBX=/path/to/sbx … # the sbx binary, if not on the PATH | ||
| 12 | -# | ||
| 13 | -# Needs a login: `docker login -u <handle>` with a Docker Hub access token. | ||
| 14 | -# `sbx kit push` talks to the registry directly — no sandbox daemon involved — | ||
| 15 | -# and falls back to the Docker credential store for authentication. | ||
| 16 | -# | ||
| 17 | -# publish.sh runs this after the image. Push the image first: a kit names | ||
| 18 | -# <owner>/mm-sandbox:<version>, and sbx pulls that image when the kit is used. | ||
| 19 | -set -euo pipefail | ||
| 20 | - | ||
| 21 | -cd "$(dirname "$0")/.." | ||
| 22 | - | ||
| 23 | -if [ -f release.env ]; then | ||
| 24 | - # shellcheck source=/dev/null | ||
| 25 | - source release.env | ||
| 26 | -fi | ||
| 27 | -TAG="${1:-${TAG:-}}" | ||
| 28 | -if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 29 | - echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/push-kits.sh v1.2.3)" | ||
| 30 | - exit 1 | ||
| 31 | -fi | ||
| 32 | - | ||
| 33 | -IMAGE_OWNER="${IMAGE_OWNER:-k33g}" | ||
| 34 | -REGISTRY="${REGISTRY:-docker.io}" | ||
| 35 | -VERSION="${TAG#v}" | ||
| 36 | -SBX="${SBX:-sbx}" | ||
| 37 | - | ||
| 38 | -if ! command -v "${SBX}" >/dev/null 2>&1; then | ||
| 39 | - echo "❌ sbx not found (${SBX}). Install Docker Sandboxes, or SBX=/path/to/sbx" | ||
| 40 | - exit 1 | ||
| 41 | -fi | ||
| 42 | - | ||
| 43 | -./docker-sbx/sync-kits.sh "${IMAGE_OWNER}" "${VERSION}" | ||
| 44 | - | ||
| 45 | -for dir in docker-sbx/kits/*/; do | ||
| 46 | - kit="$(basename "${dir}")" | ||
| 47 | - ref="${REGISTRY}/${IMAGE_OWNER}/${kit}:${VERSION}" | ||
| 48 | - "${SBX}" kit validate "${dir}" | ||
| 49 | - "${SBX}" kit push "${dir}" "${ref}" | ||
| 50 | -done | ||
| 51 | - | ||
| 52 | -cat <<NEXT | ||
| 53 | - | ||
| 54 | -Published. From any machine with Docker Sandboxes (docker.io is an allowed kit source by default): | ||
| 55 | - | ||
| 56 | - window mode sbx run ${IMAGE_OWNER}/mm-tui:${VERSION} . -- agent.dmr.yaml | ||
| 57 | - editor (ACP) sbx create --name mm-acp ${IMAGE_OWNER}/mm-acp:${VERSION} . --kit-arg config=agent.dmr.yaml | ||
| 58 | - then register sbx exec -i mm-acp mm -acp in the editor | ||
| 59 | -NEXT | ||
deleted
docker-sbx/sync-kits.sh +0 -37 | deleted file mode 100644 | ||
| @@ -1,37 +0,0 @@ | ||
| 1 | -#!/usr/bin/env bash | |
| 2 | -# Point the two kits at one image: <owner>/mm-sandbox:<version>. | |
| 3 | -# | |
| 4 | -# Usage: ./docker-sbx/sync-kits.sh OWNER VERSION (e.g. k33g 0.0.2) | |
| 5 | -# | |
| 6 | -# Rewrites, in docker-sbx/kits/*/spec.yaml, only these three values: | |
| 7 | -# version: "<version>" the kit's own version | |
| 8 | -# args.tag.default: "<version>" which image tag the kit uses | |
| 9 | -# sandbox.image: "<owner>/mm-sandbox:…" which owner the image lives under | |
| 10 | -# Everything else — comments included — is left byte-for-byte alone, so a | |
| 11 | -# kit that already matches is not changed at all. build.sh and push-kits.sh | |
| 12 | -# call this, so the published kits always name the image just pushed. | |
| 13 | -set -euo pipefail | |
| 14 | - | |
| 15 | -if [ $# -ne 2 ]; then | |
| 16 | - echo "usage: $0 OWNER VERSION" >&2 | |
| 17 | - exit 2 | |
| 18 | -fi | |
| 19 | -OWNER="$1" | |
| 20 | -VERSION="$2" | |
| 21 | - | |
| 22 | -cd "$(dirname "$0")/.." | |
| 23 | - | |
| 24 | -for kit in docker-sbx/kits/*/spec.yaml; do | |
| 25 | - if ! grep -q '^ tag:$' "${kit}" || ! grep -q '^version: ' "${kit}" || ! grep -q '^ image: "' "${kit}"; then | |
| 26 | - echo "❌ ${kit}: expected a top-level 'version:', an 'args.tag' and a quoted 'sandbox.image' — not updated" >&2 | |
| 27 | - exit 1 | |
| 28 | - fi | |
| 29 | - # sed -i.bak works on both GNU and BSD sed; the backup is removed at once. | |
| 30 | - sed -i.bak -E \ | |
| 31 | - -e "s|^(version: )\"[^\"]*\"|\1\"${VERSION}\"|" \ | |
| 32 | - -e "/^ tag:\$/,/^ default:/ s|^( default: )\"[^\"]*\"|\1\"${VERSION}\"|" \ | |
| 33 | - -e "s|^( image: \")[^/\"]+(/mm-sandbox:.*)|\1${OWNER}\2|" \ | |
| 34 | - "${kit}" | |
| 35 | - rm -f "${kit}.bak" | |
| 36 | - echo "✅ ${kit} → version \"${VERSION}\", tag default \"${VERSION}\", image ${OWNER}/mm-sandbox:\${{ kit.args.tag }}" | |
| 37 | -done | |
| deleted file mode 100644 | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# Point the two kits at one image: <owner>/mm-sandbox:<version>. | ||
| 3 | -# | ||
| 4 | -# Usage: ./docker-sbx/sync-kits.sh OWNER VERSION (e.g. k33g 0.0.2) | ||
| 5 | -# | ||
| 6 | -# Rewrites, in docker-sbx/kits/*/spec.yaml, only these three values: | ||
| 7 | -# version: "<version>" the kit's own version | ||
| 8 | -# args.tag.default: "<version>" which image tag the kit uses | ||
| 9 | -# sandbox.image: "<owner>/mm-sandbox:…" which owner the image lives under | ||
| 10 | -# Everything else — comments included — is left byte-for-byte alone, so a | ||
| 11 | -# kit that already matches is not changed at all. build.sh and push-kits.sh | ||
| 12 | -# call this, so the published kits always name the image just pushed. | ||
| 13 | -set -euo pipefail | ||
| 14 | - | ||
| 15 | -if [ $# -ne 2 ]; then | ||
| 16 | - echo "usage: $0 OWNER VERSION" >&2 | ||
| 17 | - exit 2 | ||
| 18 | -fi | ||
| 19 | -OWNER="$1" | ||
| 20 | -VERSION="$2" | ||
| 21 | - | ||
| 22 | -cd "$(dirname "$0")/.." | ||
| 23 | - | ||
| 24 | -for kit in docker-sbx/kits/*/spec.yaml; do | ||
| 25 | - if ! grep -q '^ tag:$' "${kit}" || ! grep -q '^version: ' "${kit}" || ! grep -q '^ image: "' "${kit}"; then | ||
| 26 | - echo "❌ ${kit}: expected a top-level 'version:', an 'args.tag' and a quoted 'sandbox.image' — not updated" >&2 | ||
| 27 | - exit 1 | ||
| 28 | - fi | ||
| 29 | - # sed -i.bak works on both GNU and BSD sed; the backup is removed at once. | ||
| 30 | - sed -i.bak -E \ | ||
| 31 | - -e "s|^(version: )\"[^\"]*\"|\1\"${VERSION}\"|" \ | ||
| 32 | - -e "/^ tag:\$/,/^ default:/ s|^( default: )\"[^\"]*\"|\1\"${VERSION}\"|" \ | ||
| 33 | - -e "s|^( image: \")[^/\"]+(/mm-sandbox:.*)|\1${OWNER}\2|" \ | ||
| 34 | - "${kit}" | ||
| 35 | - rm -f "${kit}.bak" | ||
| 36 | - echo "✅ ${kit} → version \"${VERSION}\", tag default \"${VERSION}\", image ${OWNER}/mm-sandbox:\${{ kit.args.tag }}" | ||
| 37 | -done | ||
deleted
docker-sbx/template/Dockerfile +0 -143 | deleted file mode 100644 | ||
| @@ -1,143 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | -# | |
| 3 | -# The mm sandbox template: Docker Sandboxes' `shell` image with mm installed. | |
| 4 | -# | |
| 5 | -# Build it from the REPOSITORY ROOT (the context is the mm sources), or run | |
| 6 | -# docker-sbx/build.sh, which does exactly that and stamps mm's tag — the | |
| 7 | -# image tag is that tag without the "v", k33g/mm-sandbox:0.0.2 for v0.0.2: | |
| 8 | -# | |
| 9 | -# docker build -f docker-sbx/template/Dockerfile \ | |
| 10 | -# --build-arg MM_VERSION=v0.0.2 -t k33g/mm-sandbox:0.0.2 . | |
| 11 | -# | |
| 12 | -# The two kits under docker-sbx/kits/ name this image. | |
| 13 | -# ENTRYPOINT and CMD are deliberately not set: the sandbox runtime keeps the | |
| 14 | -# shell template's tini entrypoint and replaces CMD with its own, and the kit's | |
| 15 | -# `sandbox.entrypoint` is what starts mm when you attach. | |
| 16 | - | |
| 17 | -ARG GO_VERSION=1.26 | |
| 18 | -ARG SHELL_TEMPLATE=docker/sandbox-templates:shell | |
| 19 | - | |
| 20 | -# ---- build stage: cross-compile mm for the target platform ----------------- | |
| 21 | -FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build | |
| 22 | -ARG TARGETOS | |
| 23 | -ARG TARGETARCH | |
| 24 | -# What `mm --version` reports: the tag, as 02-build-releases.sh stamps it. | |
| 25 | -ARG MM_VERSION=dev | |
| 26 | - | |
| 27 | -WORKDIR /src | |
| 28 | -COPY go.mod go.sum ./ | |
| 29 | -RUN --mount=type=cache,target=/go/pkg/mod go mod download | |
| 30 | -COPY . . | |
| 31 | -# Same flags as 02-build-releases.sh: no C, no local paths, no symbols, the | |
| 32 | -# version stamped into internal/version. | |
| 33 | -RUN --mount=type=cache,target=/go/pkg/mod \ | |
| 34 | - --mount=type=cache,target=/root/.cache/go-build \ | |
| 35 | - CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ | |
| 36 | - go build -trimpath -ldflags "-s -w -X mm/internal/version.stamped=${MM_VERSION}" -o /out/mm . | |
| 37 | - | |
| 38 | -# ---- template: the shell sandbox plus mm ----------------------------------- | |
| 39 | -FROM ${SHELL_TEMPLATE} | |
| 40 | - | |
| 41 | -COPY --from=build --chmod=0755 /out/mm /usr/local/bin/mm | |
| 42 | -# The two kit entry points. mm-tui runs `mm -tui "$@"`; mm-acp-info prints how | |
| 43 | -# an editor reaches this sandbox and opens a shell (see docker-sbx/README.md). | |
| 44 | -COPY --chmod=0755 docker-sbx/template/mm-tui docker-sbx/template/mm-acp-info /usr/local/bin/ | |
| 45 | - | |
| 46 | -# tcell (the window mode) needs a terminal type and a UTF-8 locale; the kits | |
| 47 | -# set them too, this is the fallback for a plain `docker run`. | |
| 48 | -ENV TERM=xterm-256color \ | |
| 49 | - COLORTERM=truecolor \ | |
| 50 | - LANG=C.UTF-8 | |
| 51 | - | |
| 52 | -# The pinned toolchains (/usr/local/go/bin, /usr/local/node/bin) must come | |
| 53 | -# before /usr/bin so they win over any Go or Node the base image ships. | |
| 54 | -ENV PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH | |
| 55 | - | |
| 56 | -# Without this, a go.mod whose `go` directive is newer than GO_VERSION makes the | |
| 57 | -# toolchain download and run a different Go, silently defeating the pin. | |
| 58 | -ENV GOTOOLCHAIN=local | |
| 59 | - | |
| 60 | -# ------------------------------------ | |
| 61 | -# Shared curl options for every download below. | |
| 62 | -# | |
| 63 | -# ARG, not ENV: this is build-time only and must not leak into the image. | |
| 64 | -# ------------------------------------ | |
| 65 | -ARG CURL_RETRY="--retry 5 --retry-all-errors --retry-delay 3 --connect-timeout 15" | |
| 66 | - | |
| 67 | -USER root | |
| 68 | - | |
| 69 | -# ------------------------------------ | |
| 70 | -# Install Go toolchain and Node.js | |
| 71 | -# ------------------------------------ | |
| 72 | -ARG GO_VERSION=1.26.0 | |
| 73 | -ARG NODE_VERSION=24.21.0 | |
| 74 | -ARG TARGETARCH | |
| 75 | - | |
| 76 | -RUN <<EOF | |
| 77 | -set -eux | |
| 78 | -apt-get update | |
| 79 | -apt-get install -y curl build-essential xz-utils | |
| 80 | -rm -rf /var/lib/apt/lists/* | |
| 81 | -EOF | |
| 82 | - | |
| 83 | -RUN <<EOF | |
| 84 | -set -eux | |
| 85 | -apt-get remove -y golang-go golang-doc | |
| 86 | -apt-get autoremove -y | |
| 87 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/go.tgz "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" | |
| 88 | -rm -rf /usr/local/go | |
| 89 | -tar -C /usr/local -xzf /tmp/go.tgz | |
| 90 | -rm /tmp/go.tgz | |
| 91 | -/usr/local/go/bin/go version | |
| 92 | -EOF | |
| 93 | - | |
| 94 | -RUN <<EOF | |
| 95 | -set -eux | |
| 96 | -case "${TARGETARCH}" in | |
| 97 | - amd64) node_arch=x64 ;; | |
| 98 | - arm64) node_arch=arm64 ;; | |
| 99 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | |
| 100 | -esac | |
| 101 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/node.tar.xz "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_arch}.tar.xz" | |
| 102 | -rm -rf /usr/local/node | |
| 103 | -mkdir -p /usr/local/node | |
| 104 | -tar -C /usr/local/node --strip-components=1 -xJf /tmp/node.tar.xz | |
| 105 | -rm /tmp/node.tar.xz | |
| 106 | -/usr/local/node/bin/node --version | |
| 107 | -/usr/local/node/bin/npm --version | |
| 108 | -EOF | |
| 109 | - | |
| 110 | -# ------------------------------------ | |
| 111 | -# Persist the Go and Node environment for sandbox shells. | |
| 112 | -# /etc/sandbox-persistent.sh is sourced before every bash command in the sbx. | |
| 113 | -# ------------------------------------ | |
| 114 | -RUN <<EOF | |
| 115 | -{ | |
| 116 | - echo 'export PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH' | |
| 117 | - echo 'export GOTOOLCHAIN=local' | |
| 118 | -} >> /etc/sandbox-persistent.sh | |
| 119 | -EOF | |
| 120 | - | |
| 121 | -# Switch to agent user for Go tools installation (they go to /home/agent/go/bin) | |
| 122 | -USER agent | |
| 123 | - | |
| 124 | -# ------------------------------------ | |
| 125 | -# Install Go developer tools | |
| 126 | -# ------------------------------------ | |
| 127 | -ARG GOPLS_VERSION=v0.23.0 | |
| 128 | -ARG X_TOOLS_VERSION=v0.49.0 | |
| 129 | -ARG STATICCHECK_VERSION=v0.7.0 | |
| 130 | - | |
| 131 | -# Retried: parallel multi-arch builds occasionally hit DNS timeouts on | |
| 132 | -# Docker Desktop's resolver. The module cache survives within this RUN, | |
| 133 | -# so a retry only fetches what's still missing. | |
| 134 | -RUN for i in 1 2 3 4 5; do \ | |
| 135 | - go install golang.org/x/tools/gopls@${GOPLS_VERSION} \ | |
| 136 | - && go install golang.org/x/tools/cmd/goimports@${X_TOOLS_VERSION} \ | |
| 137 | - && go install honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION} \ | |
| 138 | - && exit 0; \ | |
| 139 | - echo "go install failed (attempt $i), retrying..." >&2; sleep $((i * 5)); \ | |
| 140 | - done; exit 1 | |
| 141 | - | |
| 142 | -# Prove the binary runs on this platform before the image is tagged. | |
| 143 | -RUN mm --version && mm-tui --version | |
| deleted file mode 100644 | |||
| @@ -1,143 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | -# | ||
| 3 | -# The mm sandbox template: Docker Sandboxes' `shell` image with mm installed. | ||
| 4 | -# | ||
| 5 | -# Build it from the REPOSITORY ROOT (the context is the mm sources), or run | ||
| 6 | -# docker-sbx/build.sh, which does exactly that and stamps mm's tag — the | ||
| 7 | -# image tag is that tag without the "v", k33g/mm-sandbox:0.0.2 for v0.0.2: | ||
| 8 | -# | ||
| 9 | -# docker build -f docker-sbx/template/Dockerfile \ | ||
| 10 | -# --build-arg MM_VERSION=v0.0.2 -t k33g/mm-sandbox:0.0.2 . | ||
| 11 | -# | ||
| 12 | -# The two kits under docker-sbx/kits/ name this image. | ||
| 13 | -# ENTRYPOINT and CMD are deliberately not set: the sandbox runtime keeps the | ||
| 14 | -# shell template's tini entrypoint and replaces CMD with its own, and the kit's | ||
| 15 | -# `sandbox.entrypoint` is what starts mm when you attach. | ||
| 16 | - | ||
| 17 | -ARG GO_VERSION=1.26 | ||
| 18 | -ARG SHELL_TEMPLATE=docker/sandbox-templates:shell | ||
| 19 | - | ||
| 20 | -# ---- build stage: cross-compile mm for the target platform ----------------- | ||
| 21 | -FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build | ||
| 22 | -ARG TARGETOS | ||
| 23 | -ARG TARGETARCH | ||
| 24 | -# What `mm --version` reports: the tag, as 02-build-releases.sh stamps it. | ||
| 25 | -ARG MM_VERSION=dev | ||
| 26 | - | ||
| 27 | -WORKDIR /src | ||
| 28 | -COPY go.mod go.sum ./ | ||
| 29 | -RUN --mount=type=cache,target=/go/pkg/mod go mod download | ||
| 30 | -COPY . . | ||
| 31 | -# Same flags as 02-build-releases.sh: no C, no local paths, no symbols, the | ||
| 32 | -# version stamped into internal/version. | ||
| 33 | -RUN --mount=type=cache,target=/go/pkg/mod \ | ||
| 34 | - --mount=type=cache,target=/root/.cache/go-build \ | ||
| 35 | - CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ | ||
| 36 | - go build -trimpath -ldflags "-s -w -X mm/internal/version.stamped=${MM_VERSION}" -o /out/mm . | ||
| 37 | - | ||
| 38 | -# ---- template: the shell sandbox plus mm ----------------------------------- | ||
| 39 | -FROM ${SHELL_TEMPLATE} | ||
| 40 | - | ||
| 41 | -COPY --from=build --chmod=0755 /out/mm /usr/local/bin/mm | ||
| 42 | -# The two kit entry points. mm-tui runs `mm -tui "$@"`; mm-acp-info prints how | ||
| 43 | -# an editor reaches this sandbox and opens a shell (see docker-sbx/README.md). | ||
| 44 | -COPY --chmod=0755 docker-sbx/template/mm-tui docker-sbx/template/mm-acp-info /usr/local/bin/ | ||
| 45 | - | ||
| 46 | -# tcell (the window mode) needs a terminal type and a UTF-8 locale; the kits | ||
| 47 | -# set them too, this is the fallback for a plain `docker run`. | ||
| 48 | -ENV TERM=xterm-256color \ | ||
| 49 | - COLORTERM=truecolor \ | ||
| 50 | - LANG=C.UTF-8 | ||
| 51 | - | ||
| 52 | -# The pinned toolchains (/usr/local/go/bin, /usr/local/node/bin) must come | ||
| 53 | -# before /usr/bin so they win over any Go or Node the base image ships. | ||
| 54 | -ENV PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH | ||
| 55 | - | ||
| 56 | -# Without this, a go.mod whose `go` directive is newer than GO_VERSION makes the | ||
| 57 | -# toolchain download and run a different Go, silently defeating the pin. | ||
| 58 | -ENV GOTOOLCHAIN=local | ||
| 59 | - | ||
| 60 | -# ------------------------------------ | ||
| 61 | -# Shared curl options for every download below. | ||
| 62 | -# | ||
| 63 | -# ARG, not ENV: this is build-time only and must not leak into the image. | ||
| 64 | -# ------------------------------------ | ||
| 65 | -ARG CURL_RETRY="--retry 5 --retry-all-errors --retry-delay 3 --connect-timeout 15" | ||
| 66 | - | ||
| 67 | -USER root | ||
| 68 | - | ||
| 69 | -# ------------------------------------ | ||
| 70 | -# Install Go toolchain and Node.js | ||
| 71 | -# ------------------------------------ | ||
| 72 | -ARG GO_VERSION=1.26.0 | ||
| 73 | -ARG NODE_VERSION=24.21.0 | ||
| 74 | -ARG TARGETARCH | ||
| 75 | - | ||
| 76 | -RUN <<EOF | ||
| 77 | -set -eux | ||
| 78 | -apt-get update | ||
| 79 | -apt-get install -y curl build-essential xz-utils | ||
| 80 | -rm -rf /var/lib/apt/lists/* | ||
| 81 | -EOF | ||
| 82 | - | ||
| 83 | -RUN <<EOF | ||
| 84 | -set -eux | ||
| 85 | -apt-get remove -y golang-go golang-doc | ||
| 86 | -apt-get autoremove -y | ||
| 87 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/go.tgz "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" | ||
| 88 | -rm -rf /usr/local/go | ||
| 89 | -tar -C /usr/local -xzf /tmp/go.tgz | ||
| 90 | -rm /tmp/go.tgz | ||
| 91 | -/usr/local/go/bin/go version | ||
| 92 | -EOF | ||
| 93 | - | ||
| 94 | -RUN <<EOF | ||
| 95 | -set -eux | ||
| 96 | -case "${TARGETARCH}" in | ||
| 97 | - amd64) node_arch=x64 ;; | ||
| 98 | - arm64) node_arch=arm64 ;; | ||
| 99 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | ||
| 100 | -esac | ||
| 101 | -curl ${CURL_RETRY} -C - -fsSL -o /tmp/node.tar.xz "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_arch}.tar.xz" | ||
| 102 | -rm -rf /usr/local/node | ||
| 103 | -mkdir -p /usr/local/node | ||
| 104 | -tar -C /usr/local/node --strip-components=1 -xJf /tmp/node.tar.xz | ||
| 105 | -rm /tmp/node.tar.xz | ||
| 106 | -/usr/local/node/bin/node --version | ||
| 107 | -/usr/local/node/bin/npm --version | ||
| 108 | -EOF | ||
| 109 | - | ||
| 110 | -# ------------------------------------ | ||
| 111 | -# Persist the Go and Node environment for sandbox shells. | ||
| 112 | -# /etc/sandbox-persistent.sh is sourced before every bash command in the sbx. | ||
| 113 | -# ------------------------------------ | ||
| 114 | -RUN <<EOF | ||
| 115 | -{ | ||
| 116 | - echo 'export PATH=/usr/local/go/bin:/usr/local/node/bin:/home/agent/go/bin:$PATH' | ||
| 117 | - echo 'export GOTOOLCHAIN=local' | ||
| 118 | -} >> /etc/sandbox-persistent.sh | ||
| 119 | -EOF | ||
| 120 | - | ||
| 121 | -# Switch to agent user for Go tools installation (they go to /home/agent/go/bin) | ||
| 122 | -USER agent | ||
| 123 | - | ||
| 124 | -# ------------------------------------ | ||
| 125 | -# Install Go developer tools | ||
| 126 | -# ------------------------------------ | ||
| 127 | -ARG GOPLS_VERSION=v0.23.0 | ||
| 128 | -ARG X_TOOLS_VERSION=v0.49.0 | ||
| 129 | -ARG STATICCHECK_VERSION=v0.7.0 | ||
| 130 | - | ||
| 131 | -# Retried: parallel multi-arch builds occasionally hit DNS timeouts on | ||
| 132 | -# Docker Desktop's resolver. The module cache survives within this RUN, | ||
| 133 | -# so a retry only fetches what's still missing. | ||
| 134 | -RUN for i in 1 2 3 4 5; do \ | ||
| 135 | - go install golang.org/x/tools/gopls@${GOPLS_VERSION} \ | ||
| 136 | - && go install golang.org/x/tools/cmd/goimports@${X_TOOLS_VERSION} \ | ||
| 137 | - && go install honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION} \ | ||
| 138 | - && exit 0; \ | ||
| 139 | - echo "go install failed (attempt $i), retrying..." >&2; sleep $((i * 5)); \ | ||
| 140 | - done; exit 1 | ||
| 141 | - | ||
| 142 | -# Prove the binary runs on this platform before the image is tagged. | ||
| 143 | -RUN mm --version && mm-tui --version | ||
deleted
docker-sbx/template/mm-acp-info +0 -52 | deleted file mode 100644 | ||
| @@ -1,52 +0,0 @@ | ||
| 1 | -#!/bin/bash | |
| 2 | -# Entry point of the mm-acp sandbox kit (docker-sbx/kits/mm-acp). | |
| 3 | -# | |
| 4 | -# An editor never runs this script. It reaches mm with | |
| 5 | -# | |
| 6 | -# sbx exec -i <sandbox> mm -acp | |
| 7 | -# | |
| 8 | -# because an ACP client needs raw stdin/stdout and `sbx run` always allocates | |
| 9 | -# a terminal. So attaching to this sandbox with `sbx run` prints the wiring | |
| 10 | -# for the editor, with this sandbox's real name and paths, then opens a shell. | |
| 11 | -set -u | |
| 12 | - | |
| 13 | -name="${SANDBOX_NAME:-$(hostname)}" | |
| 14 | -workspace="${WORKSPACE_DIR:-$PWD}" | |
| 15 | -config="${AGENT_CONFIG:-}" | |
| 16 | -if [ -z "$config" ]; then | |
| 17 | - config_note="none set — mm reads ./agent.yaml in the workspace, then its built-in defaults" | |
| 18 | -elif [ "${config#/}" = "$config" ]; then | |
| 19 | - config_note="$config (relative to the workspace: ${workspace%/}/$config)" | |
| 20 | -else | |
| 21 | - config_note="$config" | |
| 22 | -fi | |
| 23 | - | |
| 24 | -cat <<INFO | |
| 25 | - | |
| 26 | - mm $(mm --version 2>/dev/null | awk '{print $2}') in sandbox "$name" | |
| 27 | - workspace : $workspace | |
| 28 | - config : $config_note | |
| 29 | - | |
| 30 | - This sandbox is meant for an editor (Agent Client Protocol). Register it in | |
| 31 | - Zed's settings.json — the editor starts mm inside the sandbox on every | |
| 32 | - conversation, and sbx starts the sandbox first when it is stopped: | |
| 33 | - | |
| 34 | - { | |
| 35 | - "agent_servers": { | |
| 36 | - "mini-me (sandbox)": { | |
| 37 | - "type": "custom", | |
| 38 | - "command": "sbx", | |
| 39 | - "args": ["exec", "-i", "$name", "mm", "-acp"] | |
| 40 | - } | |
| 41 | - } | |
| 42 | - } | |
| 43 | - | |
| 44 | - Use the absolute path of sbx as "command" if the editor cannot find it | |
| 45 | - (\`which sbx\` on the host). To change the configuration file for one | |
| 46 | - session, add "-e", "AGENT_CONFIG=/path/in/workspace/agent.yaml" before | |
| 47 | - "$name" in "args". Full guide: docs/en/how-to/run-in-a-docker-sandbox.md | |
| 48 | - | |
| 49 | - You are now in a shell inside the sandbox. \`mm agent.yaml\` works here too. | |
| 50 | - | |
| 51 | -INFO | |
| 52 | -exec bash -l | |
| deleted file mode 100644 | |||
| @@ -1,52 +0,0 @@ | |||
| 1 | -#!/bin/bash | ||
| 2 | -# Entry point of the mm-acp sandbox kit (docker-sbx/kits/mm-acp). | ||
| 3 | -# | ||
| 4 | -# An editor never runs this script. It reaches mm with | ||
| 5 | -# | ||
| 6 | -# sbx exec -i <sandbox> mm -acp | ||
| 7 | -# | ||
| 8 | -# because an ACP client needs raw stdin/stdout and `sbx run` always allocates | ||
| 9 | -# a terminal. So attaching to this sandbox with `sbx run` prints the wiring | ||
| 10 | -# for the editor, with this sandbox's real name and paths, then opens a shell. | ||
| 11 | -set -u | ||
| 12 | - | ||
| 13 | -name="${SANDBOX_NAME:-$(hostname)}" | ||
| 14 | -workspace="${WORKSPACE_DIR:-$PWD}" | ||
| 15 | -config="${AGENT_CONFIG:-}" | ||
| 16 | -if [ -z "$config" ]; then | ||
| 17 | - config_note="none set — mm reads ./agent.yaml in the workspace, then its built-in defaults" | ||
| 18 | -elif [ "${config#/}" = "$config" ]; then | ||
| 19 | - config_note="$config (relative to the workspace: ${workspace%/}/$config)" | ||
| 20 | -else | ||
| 21 | - config_note="$config" | ||
| 22 | -fi | ||
| 23 | - | ||
| 24 | -cat <<INFO | ||
| 25 | - | ||
| 26 | - mm $(mm --version 2>/dev/null | awk '{print $2}') in sandbox "$name" | ||
| 27 | - workspace : $workspace | ||
| 28 | - config : $config_note | ||
| 29 | - | ||
| 30 | - This sandbox is meant for an editor (Agent Client Protocol). Register it in | ||
| 31 | - Zed's settings.json — the editor starts mm inside the sandbox on every | ||
| 32 | - conversation, and sbx starts the sandbox first when it is stopped: | ||
| 33 | - | ||
| 34 | - { | ||
| 35 | - "agent_servers": { | ||
| 36 | - "mini-me (sandbox)": { | ||
| 37 | - "type": "custom", | ||
| 38 | - "command": "sbx", | ||
| 39 | - "args": ["exec", "-i", "$name", "mm", "-acp"] | ||
| 40 | - } | ||
| 41 | - } | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - Use the absolute path of sbx as "command" if the editor cannot find it | ||
| 45 | - (\`which sbx\` on the host). To change the configuration file for one | ||
| 46 | - session, add "-e", "AGENT_CONFIG=/path/in/workspace/agent.yaml" before | ||
| 47 | - "$name" in "args". Full guide: docs/en/how-to/run-in-a-docker-sandbox.md | ||
| 48 | - | ||
| 49 | - You are now in a shell inside the sandbox. \`mm agent.yaml\` works here too. | ||
| 50 | - | ||
| 51 | -INFO | ||
| 52 | -exec bash -l | ||
deleted
docker-sbx/template/mm-tui +0 -11 | deleted file mode 100644 | ||
| @@ -1,11 +0,0 @@ | ||
| 1 | -#!/bin/bash | |
| 2 | -# Entry point of the mm-tui sandbox kit (docker-sbx/kits/mm-tui). | |
| 3 | -# | |
| 4 | -# `sbx run` forwards whatever follows "--" as this script's arguments, so | |
| 5 | -# | |
| 6 | -# sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | |
| 7 | -# | |
| 8 | -# runs `mm -tui agent.dmr.yaml` in the workspace. Without an argument mm reads | |
| 9 | -# $AGENT_CONFIG (the kit's `config` argument), then ./agent.yaml, then its | |
| 10 | -# built-in defaults. Flags pass through too: `-- -config other.yaml`. | |
| 11 | -exec mm -tui "$@" | |
| deleted file mode 100644 | |||
| @@ -1,11 +0,0 @@ | |||
| 1 | -#!/bin/bash | ||
| 2 | -# Entry point of the mm-tui sandbox kit (docker-sbx/kits/mm-tui). | ||
| 3 | -# | ||
| 4 | -# `sbx run` forwards whatever follows "--" as this script's arguments, so | ||
| 5 | -# | ||
| 6 | -# sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml | ||
| 7 | -# | ||
| 8 | -# runs `mm -tui agent.dmr.yaml` in the workspace. Without an argument mm reads | ||
| 9 | -# $AGENT_CONFIG (the kit's `config` argument), then ./agent.yaml, then its | ||
| 10 | -# built-in defaults. Flags pass through too: `-- -config other.yaml`. | ||
| 11 | -exec mm -tui "$@" | ||
deleted
sandboxes/README.md +0 -3 | deleted file mode 100644 | ||
| @@ -1,3 +0,0 @@ | ||
| 1 | - | |
| 2 | -sbx rm mm-test | |
| 3 | -sbx run --name mm-test ./sbx-kits/mini-me | |
| \ No newline at end of file | ||
| deleted file mode 100644 | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | - | ||
| 2 | -sbx rm mm-test | ||
| 3 | -sbx run --name mm-test ./sbx-kits/mini-me | ||
| \ No newline at end of file | \ No newline at end of file | ||
deleted
sandboxes/docker-sbx/AGENTS.md +0 -3 | deleted file mode 100644 | ||
| @@ -1,3 +0,0 @@ | ||
| 1 | -# AGENTS.md | |
| 2 | - | |
| 3 | -The secret word is agent. | |
| deleted file mode 100644 | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | -# AGENTS.md | ||
| 2 | - | ||
| 3 | -The secret word is agent. | ||
deleted
sandboxes/docker-sbx/sbx-kits/cli-tools/cli-context.md +0 -5 | deleted file mode 100644 | ||
| @@ -1,5 +0,0 @@ | ||
| 1 | -## CLI tools | |
| 2 | - | |
| 3 | -Prefer these installed tools: `rg` (ripgrep) instead of `grep -r`, `eza -la --git` | |
| 4 | -(or `eza --tree -L 2`) instead of `ls`/`tree`, and `bat -n --paging=never <file>` | |
| 5 | -to read a file with line numbers. | |
| deleted file mode 100644 | |||
| @@ -1,5 +0,0 @@ | |||
| 1 | -## CLI tools | ||
| 2 | - | ||
| 3 | -Prefer these installed tools: `rg` (ripgrep) instead of `grep -r`, `eza -la --git` | ||
| 4 | -(or `eza --tree -L 2`) instead of `ls`/`tree`, and `bat -n --paging=never <file>` | ||
| 5 | -to read a file with line numbers. | ||
deleted
sandboxes/docker-sbx/sbx-kits/cli-tools/cli-tools.dockerfile +0 -37 | deleted file mode 100644 | ||
| @@ -1,37 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | -FROM debian:trixie-slim AS build | |
| 3 | -ARG RG_VERSION | |
| 4 | -ARG BAT_VERSION | |
| 5 | -ARG EZA_VERSION | |
| 6 | -ARG TARGETARCH | |
| 7 | - | |
| 8 | -RUN apt-get update \ | |
| 9 | - && apt-get install -y --no-install-recommends curl ca-certificates tar gzip findutils \ | |
| 10 | - && rm -rf /var/lib/apt/lists/* | |
| 11 | - | |
| 12 | -# Static (musl) builds where upstream publishes them for the architecture. | |
| 13 | -# eza only ships a musl build for x86_64; on arm64 we use its gnu build, | |
| 14 | -# which runs on the Ubuntu-based sandbox templates (glibc). | |
| 15 | -RUN set -eu; \ | |
| 16 | - case "${TARGETARCH}" in \ | |
| 17 | - amd64) arch=x86_64; eza_triple=x86_64-unknown-linux-musl ;; \ | |
| 18 | - arm64) arch=aarch64; eza_triple=aarch64-unknown-linux-gnu ;; \ | |
| 19 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | |
| 20 | - esac; \ | |
| 21 | - mkdir -p /out/usr/local/bin /tmp/rg /tmp/bat /tmp/eza; \ | |
| 22 | - \ | |
| 23 | - curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/ripgrep-${RG_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | |
| 24 | - | tar -xz -C /tmp/rg; \ | |
| 25 | - install -m 0755 "$(find /tmp/rg -type f -name rg | head -n1)" /out/usr/local/bin/rg; \ | |
| 26 | - \ | |
| 27 | - curl -fsSL "https://github.com/sharkdp/bat/releases/download/v${BAT_VERSION}/bat-v${BAT_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | |
| 28 | - | tar -xz -C /tmp/bat; \ | |
| 29 | - install -m 0755 "$(find /tmp/bat -type f -name bat | head -n1)" /out/usr/local/bin/bat; \ | |
| 30 | - \ | |
| 31 | - curl -fsSL "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/eza_${eza_triple}.tar.gz" \ | |
| 32 | - | tar -xz -C /tmp/eza; \ | |
| 33 | - install -m 0755 "$(find /tmp/eza -type f -name eza | head -n1)" /out/usr/local/bin/eza | |
| 34 | - | |
| 35 | -# Overlay: only the three binaries land on the workload. | |
| 36 | -FROM scratch | |
| 37 | -COPY --from=build /out/ / | |
| deleted file mode 100644 | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | -FROM debian:trixie-slim AS build | ||
| 3 | -ARG RG_VERSION | ||
| 4 | -ARG BAT_VERSION | ||
| 5 | -ARG EZA_VERSION | ||
| 6 | -ARG TARGETARCH | ||
| 7 | - | ||
| 8 | -RUN apt-get update \ | ||
| 9 | - && apt-get install -y --no-install-recommends curl ca-certificates tar gzip findutils \ | ||
| 10 | - && rm -rf /var/lib/apt/lists/* | ||
| 11 | - | ||
| 12 | -# Static (musl) builds where upstream publishes them for the architecture. | ||
| 13 | -# eza only ships a musl build for x86_64; on arm64 we use its gnu build, | ||
| 14 | -# which runs on the Ubuntu-based sandbox templates (glibc). | ||
| 15 | -RUN set -eu; \ | ||
| 16 | - case "${TARGETARCH}" in \ | ||
| 17 | - amd64) arch=x86_64; eza_triple=x86_64-unknown-linux-musl ;; \ | ||
| 18 | - arm64) arch=aarch64; eza_triple=aarch64-unknown-linux-gnu ;; \ | ||
| 19 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | ||
| 20 | - esac; \ | ||
| 21 | - mkdir -p /out/usr/local/bin /tmp/rg /tmp/bat /tmp/eza; \ | ||
| 22 | - \ | ||
| 23 | - curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/ripgrep-${RG_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | ||
| 24 | - | tar -xz -C /tmp/rg; \ | ||
| 25 | - install -m 0755 "$(find /tmp/rg -type f -name rg | head -n1)" /out/usr/local/bin/rg; \ | ||
| 26 | - \ | ||
| 27 | - curl -fsSL "https://github.com/sharkdp/bat/releases/download/v${BAT_VERSION}/bat-v${BAT_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | ||
| 28 | - | tar -xz -C /tmp/bat; \ | ||
| 29 | - install -m 0755 "$(find /tmp/bat -type f -name bat | head -n1)" /out/usr/local/bin/bat; \ | ||
| 30 | - \ | ||
| 31 | - curl -fsSL "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/eza_${eza_triple}.tar.gz" \ | ||
| 32 | - | tar -xz -C /tmp/eza; \ | ||
| 33 | - install -m 0755 "$(find /tmp/eza -type f -name eza | head -n1)" /out/usr/local/bin/eza | ||
| 34 | - | ||
| 35 | -# Overlay: only the three binaries land on the workload. | ||
| 36 | -FROM scratch | ||
| 37 | -COPY --from=build /out/ / | ||
deleted
sandboxes/docker-sbx/sbx-kits/go-toolchain/go-context.md +0 -6 | deleted file mode 100644 | ||
| @@ -1,6 +0,0 @@ | ||
| 1 | -## Go | |
| 2 | - | |
| 3 | -`go`, `gofmt` and `gopls` are installed (`/usr/local/go`). Run `go build ./...` | |
| 4 | -and `go test ./...` before reporting a task complete. Prefer `gopls` for | |
| 5 | -navigation and refactoring (definitions, references, rename) over text search. | |
| 6 | -Module downloads go through `proxy.golang.org`; other hosts may be blocked. | |
| deleted file mode 100644 | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | -## Go | ||
| 2 | - | ||
| 3 | -`go`, `gofmt` and `gopls` are installed (`/usr/local/go`). Run `go build ./...` | ||
| 4 | -and `go test ./...` before reporting a task complete. Prefer `gopls` for | ||
| 5 | -navigation and refactoring (definitions, references, rename) over text search. | ||
| 6 | -Module downloads go through `proxy.golang.org`; other hosts may be blocked. | ||
deleted
sandboxes/docker-sbx/sbx-kits/go-toolchain/go-toolchain.dockerfile +0 -29 | deleted file mode 100644 | ||
| @@ -1,29 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | - | |
| 3 | -# --- build stage: download Go, build gopls with that same Go ----------------- | |
| 4 | -FROM debian:trixie-slim AS build | |
| 5 | -ARG GO_VERSION | |
| 6 | -ARG GOPLS_VERSION=latest | |
| 7 | -ARG TARGETARCH | |
| 8 | - | |
| 9 | -RUN apt-get update \ | |
| 10 | - && apt-get install -y --no-install-recommends curl ca-certificates \ | |
| 11 | - && rm -rf /var/lib/apt/lists/* | |
| 12 | - | |
| 13 | -RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \ | |
| 14 | - | tar -C /usr/local -xz \ | |
| 15 | - && rm -rf /usr/local/go/test | |
| 16 | - | |
| 17 | -# Static gopls, installed straight into the overlay tree. | |
| 18 | -ENV PATH=/usr/local/go/bin:${PATH} \ | |
| 19 | - CGO_ENABLED=0 \ | |
| 20 | - GOBIN=/out/usr/local/bin \ | |
| 21 | - GOFLAGS=-trimpath | |
| 22 | -RUN go install golang.org/x/tools/gopls@${GOPLS_VERSION} \ | |
| 23 | - && ln -s /usr/local/go/bin/go /out/usr/local/bin/go \ | |
| 24 | - && ln -s /usr/local/go/bin/gofmt /out/usr/local/bin/gofmt | |
| 25 | - | |
| 26 | -# --- overlay: only the toolchain and the binaries land on the workload ------- | |
| 27 | -FROM scratch | |
| 28 | -COPY --from=build /usr/local/go /usr/local/go | |
| 29 | -COPY --from=build /out/ / | |
| deleted file mode 100644 | |||
| @@ -1,29 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | - | ||
| 3 | -# --- build stage: download Go, build gopls with that same Go ----------------- | ||
| 4 | -FROM debian:trixie-slim AS build | ||
| 5 | -ARG GO_VERSION | ||
| 6 | -ARG GOPLS_VERSION=latest | ||
| 7 | -ARG TARGETARCH | ||
| 8 | - | ||
| 9 | -RUN apt-get update \ | ||
| 10 | - && apt-get install -y --no-install-recommends curl ca-certificates \ | ||
| 11 | - && rm -rf /var/lib/apt/lists/* | ||
| 12 | - | ||
| 13 | -RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \ | ||
| 14 | - | tar -C /usr/local -xz \ | ||
| 15 | - && rm -rf /usr/local/go/test | ||
| 16 | - | ||
| 17 | -# Static gopls, installed straight into the overlay tree. | ||
| 18 | -ENV PATH=/usr/local/go/bin:${PATH} \ | ||
| 19 | - CGO_ENABLED=0 \ | ||
| 20 | - GOBIN=/out/usr/local/bin \ | ||
| 21 | - GOFLAGS=-trimpath | ||
| 22 | -RUN go install golang.org/x/tools/gopls@${GOPLS_VERSION} \ | ||
| 23 | - && ln -s /usr/local/go/bin/go /out/usr/local/bin/go \ | ||
| 24 | - && ln -s /usr/local/go/bin/gofmt /out/usr/local/bin/gofmt | ||
| 25 | - | ||
| 26 | -# --- overlay: only the toolchain and the binaries land on the workload ------- | ||
| 27 | -FROM scratch | ||
| 28 | -COPY --from=build /usr/local/go /usr/local/go | ||
| 29 | -COPY --from=build /out/ / | ||
deleted
sandboxes/docker-sbx/sbx-kits/mini-me/context.md +0 -8 | deleted file mode 100644 | ||
| @@ -1,8 +0,0 @@ | ||
| 1 | -## Mini Me sandbox | |
| 2 | - | |
| 3 | -You are running inside a Docker sandbox. The project is mounted as the | |
| 4 | -workspace; run commands from its root. Network access is restricted: if a | |
| 5 | -download fails, report the blocked host instead of retrying. | |
| 6 | - | |
| 7 | -the secret word is k33gorg | |
| 8 | - | |
| deleted file mode 100644 | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | -## Mini Me sandbox | ||
| 2 | - | ||
| 3 | -You are running inside a Docker sandbox. The project is mounted as the | ||
| 4 | -workspace; run commands from its root. Network access is restricted: if a | ||
| 5 | -download fails, report the blocked host instead of retrying. | ||
| 6 | - | ||
| 7 | -the secret word is k33gorg | ||
| 8 | - | ||
deleted
sandboxes/docker-sbx/sbx-kits/mini-me/mini-me.dockerfile +0 -32 | deleted file mode 100644 | ||
| @@ -1,32 +0,0 @@ | ||
| 1 | -# syntax=docker/dockerfile:1 | |
| 2 | -# | |
| 3 | -# Base: Docker's shell template = Ubuntu, non-root `agent` user (UID 1000), | |
| 4 | -# bash, git, curl, CA certificates. No agent pre-installed. | |
| 5 | -FROM docker/sandbox-templates:shell | |
| 6 | - | |
| 7 | -USER root | |
| 8 | - | |
| 9 | -# --- mm release v0.2.6 -------------------------------------------------------- | |
| 10 | -# rickub release assets are addressed by UUID, so the version cannot be derived | |
| 11 | -# from a template URL: to bump, replace these four values (URLs + SHA-256 from | |
| 12 | -# the release page). | |
| 13 | -ARG TARGETARCH | |
| 14 | -ARG MM_URL_AMD64=https://rickub.com/bots-garden/mini-me/release-assets/d9ffa7b2-1be7-4b92-b892-5e35b35f16a1 | |
| 15 | -ARG MM_SHA_AMD64=6a054a2ee31dffd97991c086c5477c0dd7ed60cde37d65926c9bdd1b6393df14 | |
| 16 | -ARG MM_URL_ARM64=https://rickub.com/bots-garden/mini-me/release-assets/282bcdb5-65d8-4ce9-92ad-82e8e4283e19 | |
| 17 | -ARG MM_SHA_ARM64=d6daa3305ba8fa48dbde06ecac21e3e0cb45ee9555beb52b91f45546f6e7d207 | |
| 18 | - | |
| 19 | -RUN set -eu; \ | |
| 20 | - case "${TARGETARCH}" in \ | |
| 21 | - amd64) url="${MM_URL_AMD64}"; sha="${MM_SHA_AMD64}" ;; \ | |
| 22 | - arm64) url="${MM_URL_ARM64}"; sha="${MM_SHA_ARM64}" ;; \ | |
| 23 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | |
| 24 | - esac; \ | |
| 25 | - curl -fsSL "${url}" -o /usr/local/bin/mm; \ | |
| 26 | - echo "${sha} /usr/local/bin/mm" | sha256sum -c -; \ | |
| 27 | - chmod 0755 /usr/local/bin/mm | |
| 28 | - | |
| 29 | -# Back to the sandbox user, then declare the launch command. | |
| 30 | -USER agent | |
| 31 | -ENTRYPOINT ["mm"] | |
| 32 | -CMD ["-tui"] | |
| \ No newline at end of file | ||
| deleted file mode 100644 | |||
| @@ -1,32 +0,0 @@ | |||
| 1 | -# syntax=docker/dockerfile:1 | ||
| 2 | -# | ||
| 3 | -# Base: Docker's shell template = Ubuntu, non-root `agent` user (UID 1000), | ||
| 4 | -# bash, git, curl, CA certificates. No agent pre-installed. | ||
| 5 | -FROM docker/sandbox-templates:shell | ||
| 6 | - | ||
| 7 | -USER root | ||
| 8 | - | ||
| 9 | -# --- mm release v0.2.6 -------------------------------------------------------- | ||
| 10 | -# rickub release assets are addressed by UUID, so the version cannot be derived | ||
| 11 | -# from a template URL: to bump, replace these four values (URLs + SHA-256 from | ||
| 12 | -# the release page). | ||
| 13 | -ARG TARGETARCH | ||
| 14 | -ARG MM_URL_AMD64=https://rickub.com/bots-garden/mini-me/release-assets/d9ffa7b2-1be7-4b92-b892-5e35b35f16a1 | ||
| 15 | -ARG MM_SHA_AMD64=6a054a2ee31dffd97991c086c5477c0dd7ed60cde37d65926c9bdd1b6393df14 | ||
| 16 | -ARG MM_URL_ARM64=https://rickub.com/bots-garden/mini-me/release-assets/282bcdb5-65d8-4ce9-92ad-82e8e4283e19 | ||
| 17 | -ARG MM_SHA_ARM64=d6daa3305ba8fa48dbde06ecac21e3e0cb45ee9555beb52b91f45546f6e7d207 | ||
| 18 | - | ||
| 19 | -RUN set -eu; \ | ||
| 20 | - case "${TARGETARCH}" in \ | ||
| 21 | - amd64) url="${MM_URL_AMD64}"; sha="${MM_SHA_AMD64}" ;; \ | ||
| 22 | - arm64) url="${MM_URL_ARM64}"; sha="${MM_SHA_ARM64}" ;; \ | ||
| 23 | - *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | ||
| 24 | - esac; \ | ||
| 25 | - curl -fsSL "${url}" -o /usr/local/bin/mm; \ | ||
| 26 | - echo "${sha} /usr/local/bin/mm" | sha256sum -c -; \ | ||
| 27 | - chmod 0755 /usr/local/bin/mm | ||
| 28 | - | ||
| 29 | -# Back to the sandbox user, then declare the launch command. | ||
| 30 | -USER agent | ||
| 31 | -ENTRYPOINT ["mm"] | ||
| 32 | -CMD ["-tui"] | ||
| \ No newline at end of file | \ No newline at end of file | ||
added
sbx/AGENTS.md +22 -0 | new file mode 100644 | ||
| @@ -0,0 +1,22 @@ | ||
| 1 | +# AGENTS.md | |
| 2 | + | |
| 3 | +## Mini Me sandbox | |
| 4 | + | |
| 5 | +You are running inside a Docker sandbox. The project is mounted as the | |
| 6 | +workspace; run commands from its root. Network access is restricted: if a | |
| 7 | +download fails, report the blocked host instead of retrying. | |
| 8 | + | |
| 9 | +the secret word is k33gorg | |
| 10 | + | |
| 11 | +## CLI tools | |
| 12 | + | |
| 13 | +Prefer these installed tools: `rg` (ripgrep) instead of `grep -r`, `eza -la --git` | |
| 14 | +(or `eza --tree -L 2`) instead of `ls`/`tree`, and `bat -n --paging=never <file>` | |
| 15 | +to read a file with line numbers. | |
| 16 | + | |
| 17 | +## Go | |
| 18 | + | |
| 19 | +`go`, `gofmt` and `gopls` are installed (`/usr/local/go`). Run `go build ./...` | |
| 20 | +and `go test ./...` before reporting a task complete. Prefer `gopls` for | |
| 21 | +navigation and refactoring (definitions, references, rename) over text search. | |
| 22 | +Module downloads go through `proxy.golang.org`; other hosts may be blocked. | |
| new file mode 100644 | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | +# AGENTS.md | ||
| 2 | + | ||
| 3 | +## Mini Me sandbox | ||
| 4 | + | ||
| 5 | +You are running inside a Docker sandbox. The project is mounted as the | ||
| 6 | +workspace; run commands from its root. Network access is restricted: if a | ||
| 7 | +download fails, report the blocked host instead of retrying. | ||
| 8 | + | ||
| 9 | +the secret word is k33gorg | ||
| 10 | + | ||
| 11 | +## CLI tools | ||
| 12 | + | ||
| 13 | +Prefer these installed tools: `rg` (ripgrep) instead of `grep -r`, `eza -la --git` | ||
| 14 | +(or `eza --tree -L 2`) instead of `ls`/`tree`, and `bat -n --paging=never <file>` | ||
| 15 | +to read a file with line numbers. | ||
| 16 | + | ||
| 17 | +## Go | ||
| 18 | + | ||
| 19 | +`go`, `gofmt` and `gopls` are installed (`/usr/local/go`). Run `go build ./...` | ||
| 20 | +and `go test ./...` before reporting a task complete. Prefer `gopls` for | ||
| 21 | +navigation and refactoring (definitions, references, rename) over text search. | ||
| 22 | +Module downloads go through `proxy.golang.org`; other hosts may be blocked. | ||
added
sbx/README.md +28 -0 | new file mode 100644 | ||
| @@ -0,0 +1,28 @@ | ||
| 1 | + | |
| 2 | +If the agent config file is name `agent.yaml` (default value), you don't need to specify the name of the config file. | |
| 3 | + | |
| 4 | +sbx run --name mm-0.3.0 ./kits/mini-me | |
| 5 | + | |
| 6 | +sbx run --name mm-0.3.0 ./kits/mini-me -- -tui -config agent.lucy.yaml | |
| 7 | + | |
| 8 | +sbx run --name mm-0.3.0 ./kits/mini-me --kit ./kits/go-toolchain --kit ./kits/cli-tools -- -tui -config agent.yaml | |
| 9 | + | |
| 10 | + | |
| 11 | +## ACP | |
| 12 | +sbx create --name mm-acp ./kits/mini-me . --kit ./kits/go-toolchain | |
| 13 | + | |
| 14 | +sbx exec -i mm-acp mm -acp -config agent.lucy.yaml | |
| 15 | + | |
| 16 | + | |
| 17 | +## | |
| 18 | + | |
| 19 | +sbx run --name mm-0.3.0 ./kits/mini-me | |
| 20 | + | |
| 21 | +$ sbx run "git+https://git.rickub.com/bots-garden/mini-me.git#ref=<REVISION>&dir=sbx-kits/mini-me" \ | |
| 22 | + --kit "git+https://github.com/<ORG>/<REPO>.git#ref=<REVISION>&dir=sbx-kits/go-toolchain" | |
| 23 | + | |
| 24 | + | |
| 25 | +https://rickub.com/bots-garden/mini-me/releases/v0.3.0 | |
| 26 | + | |
| 27 | +$ git rev-parse HEAD # commit courant | |
| 28 | +$ git rev-parse v1.0.0^{commit} # commit derrière un tag (annoté ou non) | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | + | ||
| 2 | +If the agent config file is name `agent.yaml` (default value), you don't need to specify the name of the config file. | ||
| 3 | + | ||
| 4 | +sbx run --name mm-0.3.0 ./kits/mini-me | ||
| 5 | + | ||
| 6 | +sbx run --name mm-0.3.0 ./kits/mini-me -- -tui -config agent.lucy.yaml | ||
| 7 | + | ||
| 8 | +sbx run --name mm-0.3.0 ./kits/mini-me --kit ./kits/go-toolchain --kit ./kits/cli-tools -- -tui -config agent.yaml | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +## ACP | ||
| 12 | +sbx create --name mm-acp ./kits/mini-me . --kit ./kits/go-toolchain | ||
| 13 | + | ||
| 14 | +sbx exec -i mm-acp mm -acp -config agent.lucy.yaml | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +## | ||
| 18 | + | ||
| 19 | +sbx run --name mm-0.3.0 ./kits/mini-me | ||
| 20 | + | ||
| 21 | +$ sbx run "git+https://git.rickub.com/bots-garden/mini-me.git#ref=<REVISION>&dir=sbx-kits/mini-me" \ | ||
| 22 | + --kit "git+https://github.com/<ORG>/<REPO>.git#ref=<REVISION>&dir=sbx-kits/go-toolchain" | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +https://rickub.com/bots-garden/mini-me/releases/v0.3.0 | ||
| 26 | + | ||
| 27 | +$ git rev-parse HEAD # commit courant | ||
| 28 | +$ git rev-parse v1.0.0^{commit} # commit derrière un tag (annoté ou non) | ||
| \ No newline at end of file | \ No newline at end of file | ||
added
sbx/agent.lucy.yaml +210 -0 | new file mode 100644 | ||
| @@ -0,0 +1,210 @@ | ||
| 1 | +# Agent settings — Lucy: mini-me on hf.co/Menlo/Lucy-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman) | |
| 2 | +# through its OpenAI-compatible endpoint (/v1/chat/completions). | |
| 3 | +# | |
| 4 | +# llmman pull hf.co/Menlo/Lucy-gguf:Q4_K_M # optional: the first question pulls it otherwise | |
| 5 | +# llmman serve # 127.0.0.1:17434 | |
| 6 | +# | |
| 7 | +# llmman loads the model on the first request (in its own llama-server) and | |
| 8 | +# unloads it after five idle minutes. | |
| 9 | +provider: llmman | |
| 10 | + | |
| 11 | +# The model id exactly as `llmman list` / GET /v1/models spells it. | |
| 12 | +model: hf.co/Menlo/Lucy-gguf:Q4_K_M | |
| 13 | + | |
| 14 | +# `llmman serve`'s default bind; the OpenAI routes sit under /v1. | |
| 15 | +baseUrl: http://127.0.0.1:17434/v1 | |
| 16 | + | |
| 17 | +# From a Docker sandbox, the daemon runs on the host. | |
| 18 | +fallback: http://host.docker.internal:17434/v1 | |
| 19 | + | |
| 20 | +# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it | |
| 21 | +# listens beyond loopback); unset otherwise. The key never goes in this file. | |
| 22 | +# apiKeyEnv: LLMMAN_API_KEY | |
| 23 | + | |
| 24 | +# Yolo mode. `true` (default): the tools run without asking. | |
| 25 | +# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change | |
| 26 | +# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the | |
| 27 | +# terminal, the window and the editor; MCP tools ask too. | |
| 28 | +# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs), | |
| 29 | +# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false. | |
| 30 | +yolo: true | |
| 31 | + | |
| 32 | +# The `bash` tool. | |
| 33 | +# `false` removes it: the model can still read and edit files (editTools) and load skills, | |
| 34 | +# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool". | |
| 35 | +bashTool: true | |
| 36 | + | |
| 37 | +# The built-in file tools: read_file, write_file, edit_file. | |
| 38 | +editTools: true | |
| 39 | + | |
| 40 | +# The built-in plan tool for managing multi-step plans. | |
| 41 | +# Set to false to disable plan creation and tracking via the `plan` tool. | |
| 42 | +planTool: true | |
| 43 | + | |
| 44 | +# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | |
| 45 | +# The file extension picks the server. A server missing from the PATH is skipped with a warning. | |
| 46 | +# No server listed = no `lsp` tool. Examples (uncomment what you have installed): | |
| 47 | +# lsp: | |
| 48 | +# servers: | |
| 49 | +# - name: gopls | |
| 50 | +# command: gopls | |
| 51 | +# extensions: [".go"] | |
| 52 | +# - name: typescript | |
| 53 | +# command: typescript-language-server | |
| 54 | +# args: ["--stdio"] | |
| 55 | +# extensions: [".ts", ".tsx", ".js", ".jsx"] | |
| 56 | +# - name: python | |
| 57 | +# command: pyright-langserver | |
| 58 | +# args: ["--stdio"] | |
| 59 | +# extensions: [".py"] | |
| 60 | +# - name: rust | |
| 61 | +# command: rust-analyzer | |
| 62 | +# extensions: [".rs"] | |
| 63 | + | |
| 64 | +# How many tokens the server actually serves. | |
| 65 | +# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is | |
| 66 | +# learned before the second question. Set it here if you want it from the start | |
| 67 | +# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable. | |
| 68 | +contextWindow: 0 | |
| 69 | + | |
| 70 | +# Max number of characters a tool returns to the model. | |
| 71 | +# Context safeguard: beyond that, the output is truncated (beginning + end kept). | |
| 72 | +maxOutput: 16000 | |
| 73 | + | |
| 74 | +# Max number of model <-> tools round trips for a single question. | |
| 75 | +# Raise it for tasks that need long chains of commands. | |
| 76 | +maxTurns: 40 | |
| 77 | + | |
| 78 | +# Where the `read_skill` tool looks for its markdown procedures. | |
| 79 | +# The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/. | |
| 80 | +skillsDir: ../skills | |
| 81 | + | |
| 82 | +# Persistent sessions, per project. | |
| 83 | +# When enabled, every conversation is saved as one JSON file under `dir`. | |
| 84 | +# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread. | |
| 85 | +sessions: | |
| 86 | + enabled: true | |
| 87 | + dir: .mm/sessions | |
| 88 | + | |
| 89 | +# How many lines of a command's output are echoed to the terminal. | |
| 90 | +# 0 disables it. | |
| 91 | +previewLines: 20 | |
| 92 | + | |
| 93 | +displayCommands: true | |
| 94 | +# Show what a thinking model reasons about before it answers (dim italic in the | |
| 95 | +# terminal, its own style in the window, a thought chunk in an editor). | |
| 96 | +# The reasoning is always READ — it is what keeps the watchdog alive while the | |
| 97 | +# model thinks — this only says whether to show it. | |
| 98 | +showThinking: true | |
| 99 | + | |
| 100 | +acp: | |
| 101 | + name: lucy | |
| 102 | + title: Lucy (coding agent) | |
| 103 | + | |
| 104 | +# The system prompt: what the agent is, and what it is allowed to do. | |
| 105 | +# This is the knob to play with — it is the shortest path to changing behaviour. | |
| 106 | +system: | | |
| 107 | + Your name is Lucy. | |
| 108 | + You are a coding agent working in a terminal. | |
| 109 | + You have a "bash" tool to run shell commands. | |
| 110 | + Use it to explore files, run tests, inspect the repository, etc. | |
| 111 | + Chain several commands if needed, then answer clearly in English. | |
| 112 | + | |
| 113 | + A request often mixes things you answer from yourself ("say hello") with | |
| 114 | + things only a command can answer ("list the files"). Handle every part, in | |
| 115 | + the order asked, and run a command for each part that needs one. | |
| 116 | + Never state the contents of a file, the output of a command, or the state of | |
| 117 | + the repository unless a command in THIS answer returned it. What you did not | |
| 118 | + read, you do not know: run the command instead of recalling it. | |
| 119 | + | |
| 120 | + SKILLS | |
| 121 | + You have a second tool, `read_skill`. Its description lists the procedures | |
| 122 | + available for this project — one per kind of task. | |
| 123 | + | |
| 124 | + Any request to DO something to a Go project is a skill, not a shell command | |
| 125 | + you invent. Match the request against that list, call `read_skill` FIRST, | |
| 126 | + before any bash command, and then follow what it says step by step. | |
| 127 | + | |
| 128 | + FILE EDITING | |
| 129 | + You have three tools for files: `read_file`, `edit_file` and `write_file`. | |
| 130 | + They are how a file gets read and changed here: each change is exact, | |
| 131 | + checked before it is written, and comes back as a diff with line numbers. | |
| 132 | + bash is for running things — building, testing, listing, searching. | |
| 133 | + | |
| 134 | + - Read before you write: call `read_file` on the file (numbered=true when | |
| 135 | + you need line numbers). You cannot target text you have not seen; never | |
| 136 | + rely on what you think you remember about a file. | |
| 137 | + - To change an existing file, call `edit_file` with one or more {old, new} | |
| 138 | + pairs. `old` is copied from the file character for character — same | |
| 139 | + spaces, same indentation, same line breaks — and appears exactly once: | |
| 140 | + add the surrounding lines until it is unique. Several pairs are applied | |
| 141 | + together, against the original file. An empty `new` deletes the text. | |
| 142 | + - Call `write_file` only to create a file, or to rewrite one entirely and | |
| 143 | + on purpose. On an existing file it replaces everything, including what | |
| 144 | + you did not intend to touch. | |
| 145 | + - Read the diff the tool returns: it says exactly what changed and on which | |
| 146 | + line. If `edit_file` refuses — text not found, ambiguous, overlapping | |
| 147 | + edits — read the file again and fix `old`. Do not fall back to | |
| 148 | + `write_file` to force the change through. | |
| 149 | + - After editing code, run the narrowest check with bash: the formatter, the | |
| 150 | + compiler, or the test covering that file. | |
| 151 | + | |
| 152 | + RULES | |
| 153 | + - Keep everything the file already does, unless the user asked to remove it. | |
| 154 | + - Touch only the files the request is about. Do not add tests, files or | |
| 155 | + features that were not asked for. | |
| 156 | + - Never run a git command unless the user says git, commit or push. | |
| 157 | + - Never move, rename or delete a file unless the user asked for it. | |
| 158 | + - Then answer in English, in a few lines. | |
| 159 | + - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`) | |
| 160 | + to understand the options, then run the command. | |
| 161 | + | |
| 162 | + BACKGROUND JOBS | |
| 163 | + Never let a command block the answer. Anything that serves, watches or runs | |
| 164 | + long goes to the background, with BOTH streams redirected and its pid kept: | |
| 165 | + | |
| 166 | + nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid | |
| 167 | + | |
| 168 | + Redirecting only stdout still blocks until the process exits. Read the | |
| 169 | + `bg-jobs` skill before you wait on, inspect or stop such a job — each has a | |
| 170 | + rule you cannot guess. Stop every job you started before you finish, and say | |
| 171 | + which ones you left running. | |
| 172 | + | |
| 173 | +# Generation settings (OpenAI API keys). Low temperature for a coding agent: | |
| 174 | +# we want precise and reproducible answers, not creativity. | |
| 175 | +sampling: | |
| 176 | + temperature: 0.0 | |
| 177 | + parallel_tool_calls: false | |
| 178 | + top_p: 0.9 | |
| 179 | + max_tokens: 4096 | |
| 180 | + | |
| 181 | +# Silence allowed between two tokens once the answer has started. | |
| 182 | +watchdogTimeout: 30s | |
| 183 | + | |
| 184 | +# Silence allowed while the model reads the prompt, before the first token: | |
| 185 | +# on a laptop a 25k-token prompt can take minutes. llama-server reports its | |
| 186 | +# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report | |
| 187 | +# restarts this clock, so it only has to cover one batch of the prompt. | |
| 188 | +firstTokenTimeout: 3m | |
| 189 | + | |
| 190 | +# Context compression. | |
| 191 | +# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to. | |
| 192 | +context: | |
| 193 | + enabled: true | |
| 194 | + | |
| 195 | + # Compress when the history reaches this share of the window. | |
| 196 | + threshold: 75 | |
| 197 | + | |
| 198 | + # Fallback on the message count, for when the window is unknown. | |
| 199 | + # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history. | |
| 200 | + maxMessages: 80 | |
| 201 | + | |
| 202 | + # How many recent questions (with their commands and answers) are kept as-is instead of being summarised. | |
| 203 | + # The model works on the last few turns, so summarising them would make it redo what it just did. | |
| 204 | + keepLastTurns: 3 | |
| 205 | + | |
| 206 | + # max_tokens of the summary request. Reasoning is turned off for it on this provider | |
| 207 | + # (a thinking model would otherwise spend the budget thinking and write nothing). | |
| 208 | + summaryMaxTokens: 1200 | |
| 209 | + | |
| 210 | + showStats: true | |
| new file mode 100644 | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | +# Agent settings — Lucy: mini-me on hf.co/Menlo/Lucy-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman) | ||
| 2 | +# through its OpenAI-compatible endpoint (/v1/chat/completions). | ||
| 3 | +# | ||
| 4 | +# llmman pull hf.co/Menlo/Lucy-gguf:Q4_K_M # optional: the first question pulls it otherwise | ||
| 5 | +# llmman serve # 127.0.0.1:17434 | ||
| 6 | +# | ||
| 7 | +# llmman loads the model on the first request (in its own llama-server) and | ||
| 8 | +# unloads it after five idle minutes. | ||
| 9 | +provider: llmman | ||
| 10 | + | ||
| 11 | +# The model id exactly as `llmman list` / GET /v1/models spells it. | ||
| 12 | +model: hf.co/Menlo/Lucy-gguf:Q4_K_M | ||
| 13 | + | ||
| 14 | +# `llmman serve`'s default bind; the OpenAI routes sit under /v1. | ||
| 15 | +baseUrl: http://127.0.0.1:17434/v1 | ||
| 16 | + | ||
| 17 | +# From a Docker sandbox, the daemon runs on the host. | ||
| 18 | +fallback: http://host.docker.internal:17434/v1 | ||
| 19 | + | ||
| 20 | +# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it | ||
| 21 | +# listens beyond loopback); unset otherwise. The key never goes in this file. | ||
| 22 | +# apiKeyEnv: LLMMAN_API_KEY | ||
| 23 | + | ||
| 24 | +# Yolo mode. `true` (default): the tools run without asking. | ||
| 25 | +# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change | ||
| 26 | +# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the | ||
| 27 | +# terminal, the window and the editor; MCP tools ask too. | ||
| 28 | +# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs), | ||
| 29 | +# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false. | ||
| 30 | +yolo: true | ||
| 31 | + | ||
| 32 | +# The `bash` tool. | ||
| 33 | +# `false` removes it: the model can still read and edit files (editTools) and load skills, | ||
| 34 | +# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool". | ||
| 35 | +bashTool: true | ||
| 36 | + | ||
| 37 | +# The built-in file tools: read_file, write_file, edit_file. | ||
| 38 | +editTools: true | ||
| 39 | + | ||
| 40 | +# The built-in plan tool for managing multi-step plans. | ||
| 41 | +# Set to false to disable plan creation and tracking via the `plan` tool. | ||
| 42 | +planTool: true | ||
| 43 | + | ||
| 44 | +# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | ||
| 45 | +# The file extension picks the server. A server missing from the PATH is skipped with a warning. | ||
| 46 | +# No server listed = no `lsp` tool. Examples (uncomment what you have installed): | ||
| 47 | +# lsp: | ||
| 48 | +# servers: | ||
| 49 | +# - name: gopls | ||
| 50 | +# command: gopls | ||
| 51 | +# extensions: [".go"] | ||
| 52 | +# - name: typescript | ||
| 53 | +# command: typescript-language-server | ||
| 54 | +# args: ["--stdio"] | ||
| 55 | +# extensions: [".ts", ".tsx", ".js", ".jsx"] | ||
| 56 | +# - name: python | ||
| 57 | +# command: pyright-langserver | ||
| 58 | +# args: ["--stdio"] | ||
| 59 | +# extensions: [".py"] | ||
| 60 | +# - name: rust | ||
| 61 | +# command: rust-analyzer | ||
| 62 | +# extensions: [".rs"] | ||
| 63 | + | ||
| 64 | +# How many tokens the server actually serves. | ||
| 65 | +# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is | ||
| 66 | +# learned before the second question. Set it here if you want it from the start | ||
| 67 | +# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable. | ||
| 68 | +contextWindow: 0 | ||
| 69 | + | ||
| 70 | +# Max number of characters a tool returns to the model. | ||
| 71 | +# Context safeguard: beyond that, the output is truncated (beginning + end kept). | ||
| 72 | +maxOutput: 16000 | ||
| 73 | + | ||
| 74 | +# Max number of model <-> tools round trips for a single question. | ||
| 75 | +# Raise it for tasks that need long chains of commands. | ||
| 76 | +maxTurns: 40 | ||
| 77 | + | ||
| 78 | +# Where the `read_skill` tool looks for its markdown procedures. | ||
| 79 | +# The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/. | ||
| 80 | +skillsDir: ../skills | ||
| 81 | + | ||
| 82 | +# Persistent sessions, per project. | ||
| 83 | +# When enabled, every conversation is saved as one JSON file under `dir`. | ||
| 84 | +# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread. | ||
| 85 | +sessions: | ||
| 86 | + enabled: true | ||
| 87 | + dir: .mm/sessions | ||
| 88 | + | ||
| 89 | +# How many lines of a command's output are echoed to the terminal. | ||
| 90 | +# 0 disables it. | ||
| 91 | +previewLines: 20 | ||
| 92 | + | ||
| 93 | +displayCommands: true | ||
| 94 | +# Show what a thinking model reasons about before it answers (dim italic in the | ||
| 95 | +# terminal, its own style in the window, a thought chunk in an editor). | ||
| 96 | +# The reasoning is always READ — it is what keeps the watchdog alive while the | ||
| 97 | +# model thinks — this only says whether to show it. | ||
| 98 | +showThinking: true | ||
| 99 | + | ||
| 100 | +acp: | ||
| 101 | + name: lucy | ||
| 102 | + title: Lucy (coding agent) | ||
| 103 | + | ||
| 104 | +# The system prompt: what the agent is, and what it is allowed to do. | ||
| 105 | +# This is the knob to play with — it is the shortest path to changing behaviour. | ||
| 106 | +system: | | ||
| 107 | + Your name is Lucy. | ||
| 108 | + You are a coding agent working in a terminal. | ||
| 109 | + You have a "bash" tool to run shell commands. | ||
| 110 | + Use it to explore files, run tests, inspect the repository, etc. | ||
| 111 | + Chain several commands if needed, then answer clearly in English. | ||
| 112 | + | ||
| 113 | + A request often mixes things you answer from yourself ("say hello") with | ||
| 114 | + things only a command can answer ("list the files"). Handle every part, in | ||
| 115 | + the order asked, and run a command for each part that needs one. | ||
| 116 | + Never state the contents of a file, the output of a command, or the state of | ||
| 117 | + the repository unless a command in THIS answer returned it. What you did not | ||
| 118 | + read, you do not know: run the command instead of recalling it. | ||
| 119 | + | ||
| 120 | + SKILLS | ||
| 121 | + You have a second tool, `read_skill`. Its description lists the procedures | ||
| 122 | + available for this project — one per kind of task. | ||
| 123 | + | ||
| 124 | + Any request to DO something to a Go project is a skill, not a shell command | ||
| 125 | + you invent. Match the request against that list, call `read_skill` FIRST, | ||
| 126 | + before any bash command, and then follow what it says step by step. | ||
| 127 | + | ||
| 128 | + FILE EDITING | ||
| 129 | + You have three tools for files: `read_file`, `edit_file` and `write_file`. | ||
| 130 | + They are how a file gets read and changed here: each change is exact, | ||
| 131 | + checked before it is written, and comes back as a diff with line numbers. | ||
| 132 | + bash is for running things — building, testing, listing, searching. | ||
| 133 | + | ||
| 134 | + - Read before you write: call `read_file` on the file (numbered=true when | ||
| 135 | + you need line numbers). You cannot target text you have not seen; never | ||
| 136 | + rely on what you think you remember about a file. | ||
| 137 | + - To change an existing file, call `edit_file` with one or more {old, new} | ||
| 138 | + pairs. `old` is copied from the file character for character — same | ||
| 139 | + spaces, same indentation, same line breaks — and appears exactly once: | ||
| 140 | + add the surrounding lines until it is unique. Several pairs are applied | ||
| 141 | + together, against the original file. An empty `new` deletes the text. | ||
| 142 | + - Call `write_file` only to create a file, or to rewrite one entirely and | ||
| 143 | + on purpose. On an existing file it replaces everything, including what | ||
| 144 | + you did not intend to touch. | ||
| 145 | + - Read the diff the tool returns: it says exactly what changed and on which | ||
| 146 | + line. If `edit_file` refuses — text not found, ambiguous, overlapping | ||
| 147 | + edits — read the file again and fix `old`. Do not fall back to | ||
| 148 | + `write_file` to force the change through. | ||
| 149 | + - After editing code, run the narrowest check with bash: the formatter, the | ||
| 150 | + compiler, or the test covering that file. | ||
| 151 | + | ||
| 152 | + RULES | ||
| 153 | + - Keep everything the file already does, unless the user asked to remove it. | ||
| 154 | + - Touch only the files the request is about. Do not add tests, files or | ||
| 155 | + features that were not asked for. | ||
| 156 | + - Never run a git command unless the user says git, commit or push. | ||
| 157 | + - Never move, rename or delete a file unless the user asked for it. | ||
| 158 | + - Then answer in English, in a few lines. | ||
| 159 | + - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`) | ||
| 160 | + to understand the options, then run the command. | ||
| 161 | + | ||
| 162 | + BACKGROUND JOBS | ||
| 163 | + Never let a command block the answer. Anything that serves, watches or runs | ||
| 164 | + long goes to the background, with BOTH streams redirected and its pid kept: | ||
| 165 | + | ||
| 166 | + nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid | ||
| 167 | + | ||
| 168 | + Redirecting only stdout still blocks until the process exits. Read the | ||
| 169 | + `bg-jobs` skill before you wait on, inspect or stop such a job — each has a | ||
| 170 | + rule you cannot guess. Stop every job you started before you finish, and say | ||
| 171 | + which ones you left running. | ||
| 172 | + | ||
| 173 | +# Generation settings (OpenAI API keys). Low temperature for a coding agent: | ||
| 174 | +# we want precise and reproducible answers, not creativity. | ||
| 175 | +sampling: | ||
| 176 | + temperature: 0.0 | ||
| 177 | + parallel_tool_calls: false | ||
| 178 | + top_p: 0.9 | ||
| 179 | + max_tokens: 4096 | ||
| 180 | + | ||
| 181 | +# Silence allowed between two tokens once the answer has started. | ||
| 182 | +watchdogTimeout: 30s | ||
| 183 | + | ||
| 184 | +# Silence allowed while the model reads the prompt, before the first token: | ||
| 185 | +# on a laptop a 25k-token prompt can take minutes. llama-server reports its | ||
| 186 | +# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report | ||
| 187 | +# restarts this clock, so it only has to cover one batch of the prompt. | ||
| 188 | +firstTokenTimeout: 3m | ||
| 189 | + | ||
| 190 | +# Context compression. | ||
| 191 | +# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to. | ||
| 192 | +context: | ||
| 193 | + enabled: true | ||
| 194 | + | ||
| 195 | + # Compress when the history reaches this share of the window. | ||
| 196 | + threshold: 75 | ||
| 197 | + | ||
| 198 | + # Fallback on the message count, for when the window is unknown. | ||
| 199 | + # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history. | ||
| 200 | + maxMessages: 80 | ||
| 201 | + | ||
| 202 | + # How many recent questions (with their commands and answers) are kept as-is instead of being summarised. | ||
| 203 | + # The model works on the last few turns, so summarising them would make it redo what it just did. | ||
| 204 | + keepLastTurns: 3 | ||
| 205 | + | ||
| 206 | + # max_tokens of the summary request. Reasoning is turned off for it on this provider | ||
| 207 | + # (a thinking model would otherwise spend the budget thinking and write nothing). | ||
| 208 | + summaryMaxTokens: 1200 | ||
| 209 | + | ||
| 210 | + showStats: true | ||
added
sbx/agent.yaml +211 -0 | new file mode 100644 | ||
| @@ -0,0 +1,211 @@ | ||
| 1 | +# Agent settings — Jan: mini-me on hf.co/Menlo/Jan-nano-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman) | |
| 2 | +# through its OpenAI-compatible endpoint (/v1/chat/completions). | |
| 3 | +# | |
| 4 | +# llmman pull hf.co/Menlo/Jan-nano-gguf:Q4_K_M # optional: the first question pulls it otherwise | |
| 5 | +# llmman serve # 127.0.0.1:17434 | |
| 6 | +# | |
| 7 | +# llmman loads the model on the first request (in its own llama-server) and | |
| 8 | +# unloads it after five idle minutes. | |
| 9 | +provider: llmman | |
| 10 | + | |
| 11 | +# The model id exactly as `llmman list` / GET /v1/models spells it. | |
| 12 | +model: hf.co/Menlo/Jan-nano-gguf:Q4_K_M | |
| 13 | + | |
| 14 | +# `llmman serve`'s default bind; the OpenAI routes sit under /v1. | |
| 15 | +baseUrl: http://127.0.0.1:17434/v1 | |
| 16 | + | |
| 17 | +# From a Docker sandbox, the daemon runs on the host. | |
| 18 | +fallback: http://host.docker.internal:17434/v1 | |
| 19 | + | |
| 20 | +# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it | |
| 21 | +# listens beyond loopback); unset otherwise. The key never goes in this file. | |
| 22 | +# apiKeyEnv: LLMMAN_API_KEY | |
| 23 | + | |
| 24 | +# Yolo mode. `true` (default): the tools run without asking. | |
| 25 | +# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change | |
| 26 | +# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the | |
| 27 | +# terminal, the window and the editor; MCP tools ask too. | |
| 28 | +# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs), | |
| 29 | +# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false. | |
| 30 | +yolo: true | |
| 31 | + | |
| 32 | +# The `bash` tool. | |
| 33 | +# `false` removes it: the model can still read and edit files (editTools) and load skills, | |
| 34 | +# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool". | |
| 35 | +bashTool: true | |
| 36 | + | |
| 37 | +# The built-in file tools: read_file, write_file, edit_file. | |
| 38 | +editTools: true | |
| 39 | + | |
| 40 | +# The built-in plan tool for managing multi-step plans. | |
| 41 | +# Set to false to disable plan creation and tracking via the `plan` tool. | |
| 42 | +planTool: true | |
| 43 | + | |
| 44 | +# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | |
| 45 | +# The file extension picks the server. A server missing from the PATH is skipped with a warning. | |
| 46 | +# No server listed = no `lsp` tool. Examples (uncomment what you have installed): | |
| 47 | +# lsp: | |
| 48 | +# servers: | |
| 49 | +# - name: gopls | |
| 50 | +# command: gopls | |
| 51 | +# extensions: [".go"] | |
| 52 | +# - name: typescript | |
| 53 | +# command: typescript-language-server | |
| 54 | +# args: ["--stdio"] | |
| 55 | +# extensions: [".ts", ".tsx", ".js", ".jsx"] | |
| 56 | +# - name: python | |
| 57 | +# command: pyright-langserver | |
| 58 | +# args: ["--stdio"] | |
| 59 | +# extensions: [".py"] | |
| 60 | +# - name: rust | |
| 61 | +# command: rust-analyzer | |
| 62 | +# extensions: [".rs"] | |
| 63 | + | |
| 64 | +# How many tokens the server actually serves. | |
| 65 | +# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is | |
| 66 | +# learned before the second question. Set it here if you want it from the start | |
| 67 | +# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable. | |
| 68 | +contextWindow: 0 | |
| 69 | + | |
| 70 | +# Max number of characters a tool returns to the model. | |
| 71 | +# Context safeguard: beyond that, the output is truncated (beginning + end kept). | |
| 72 | +maxOutput: 16000 | |
| 73 | + | |
| 74 | +# Max number of model <-> tools round trips for a single question. | |
| 75 | +# Raise it for tasks that need long chains of commands. | |
| 76 | +maxTurns: 40 | |
| 77 | + | |
| 78 | +# Where the `read_skill` tool looks for its markdown procedures. | |
| 79 | +# The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/. | |
| 80 | +skillsDir: ../skills | |
| 81 | + | |
| 82 | +# Persistent sessions, per project. | |
| 83 | +# When enabled, every conversation is saved as one JSON file under `dir`. | |
| 84 | +# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread. | |
| 85 | +sessions: | |
| 86 | + enabled: true | |
| 87 | + dir: .mm/sessions | |
| 88 | + | |
| 89 | +# How many lines of a command's output are echoed to the terminal. | |
| 90 | +# 0 disables it. | |
| 91 | +previewLines: 20 | |
| 92 | + | |
| 93 | +displayCommands: true | |
| 94 | +# Show what a thinking model reasons about before it answers (dim italic in the | |
| 95 | +# terminal, its own style in the window, a thought chunk in an editor). | |
| 96 | +# The reasoning is always READ — it is what keeps the watchdog alive while the | |
| 97 | +# model thinks — this only says whether to show it. | |
| 98 | +showThinking: true | |
| 99 | + | |
| 100 | + | |
| 101 | +acp: | |
| 102 | + name: jan | |
| 103 | + title: Jan (coding agent) | |
| 104 | + | |
| 105 | +# The system prompt: what the agent is, and what it is allowed to do. | |
| 106 | +# This is the knob to play with — it is the shortest path to changing behaviour. | |
| 107 | +system: | | |
| 108 | + Your name is Jan. | |
| 109 | + You are a coding agent working in a terminal. | |
| 110 | + You have a "bash" tool to run shell commands. | |
| 111 | + Use it to explore files, run tests, inspect the repository, etc. | |
| 112 | + Chain several commands if needed, then answer clearly in English. | |
| 113 | + | |
| 114 | + A request often mixes things you answer from yourself ("say hello") with | |
| 115 | + things only a command can answer ("list the files"). Handle every part, in | |
| 116 | + the order asked, and run a command for each part that needs one. | |
| 117 | + Never state the contents of a file, the output of a command, or the state of | |
| 118 | + the repository unless a command in THIS answer returned it. What you did not | |
| 119 | + read, you do not know: run the command instead of recalling it. | |
| 120 | + | |
| 121 | + SKILLS | |
| 122 | + You have a second tool, `read_skill`. Its description lists the procedures | |
| 123 | + available for this project — one per kind of task. | |
| 124 | + | |
| 125 | + Any request to DO something to a Go project is a skill, not a shell command | |
| 126 | + you invent. Match the request against that list, call `read_skill` FIRST, | |
| 127 | + before any bash command, and then follow what it says step by step. | |
| 128 | + | |
| 129 | + FILE EDITING | |
| 130 | + You have three tools for files: `read_file`, `edit_file` and `write_file`. | |
| 131 | + They are how a file gets read and changed here: each change is exact, | |
| 132 | + checked before it is written, and comes back as a diff with line numbers. | |
| 133 | + bash is for running things — building, testing, listing, searching. | |
| 134 | + | |
| 135 | + - Read before you write: call `read_file` on the file (numbered=true when | |
| 136 | + you need line numbers). You cannot target text you have not seen; never | |
| 137 | + rely on what you think you remember about a file. | |
| 138 | + - To change an existing file, call `edit_file` with one or more {old, new} | |
| 139 | + pairs. `old` is copied from the file character for character — same | |
| 140 | + spaces, same indentation, same line breaks — and appears exactly once: | |
| 141 | + add the surrounding lines until it is unique. Several pairs are applied | |
| 142 | + together, against the original file. An empty `new` deletes the text. | |
| 143 | + - Call `write_file` only to create a file, or to rewrite one entirely and | |
| 144 | + on purpose. On an existing file it replaces everything, including what | |
| 145 | + you did not intend to touch. | |
| 146 | + - Read the diff the tool returns: it says exactly what changed and on which | |
| 147 | + line. If `edit_file` refuses — text not found, ambiguous, overlapping | |
| 148 | + edits — read the file again and fix `old`. Do not fall back to | |
| 149 | + `write_file` to force the change through. | |
| 150 | + - After editing code, run the narrowest check with bash: the formatter, the | |
| 151 | + compiler, or the test covering that file. | |
| 152 | + | |
| 153 | + RULES | |
| 154 | + - Keep everything the file already does, unless the user asked to remove it. | |
| 155 | + - Touch only the files the request is about. Do not add tests, files or | |
| 156 | + features that were not asked for. | |
| 157 | + - Never run a git command unless the user says git, commit or push. | |
| 158 | + - Never move, rename or delete a file unless the user asked for it. | |
| 159 | + - Then answer in English, in a few lines. | |
| 160 | + - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`) | |
| 161 | + to understand the options, then run the command. | |
| 162 | + | |
| 163 | + BACKGROUND JOBS | |
| 164 | + Never let a command block the answer. Anything that serves, watches or runs | |
| 165 | + long goes to the background, with BOTH streams redirected and its pid kept: | |
| 166 | + | |
| 167 | + nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid | |
| 168 | + | |
| 169 | + Redirecting only stdout still blocks until the process exits. Read the | |
| 170 | + `bg-jobs` skill before you wait on, inspect or stop such a job — each has a | |
| 171 | + rule you cannot guess. Stop every job you started before you finish, and say | |
| 172 | + which ones you left running. | |
| 173 | + | |
| 174 | +# Generation settings (OpenAI API keys). Low temperature for a coding agent: | |
| 175 | +# we want precise and reproducible answers, not creativity. | |
| 176 | +sampling: | |
| 177 | + temperature: 0.0 | |
| 178 | + parallel_tool_calls: false | |
| 179 | + top_p: 0.9 | |
| 180 | + max_tokens: 4096 | |
| 181 | + | |
| 182 | +# Silence allowed between two tokens once the answer has started. | |
| 183 | +watchdogTimeout: 30s | |
| 184 | + | |
| 185 | +# Silence allowed while the model reads the prompt, before the first token: | |
| 186 | +# on a laptop a 25k-token prompt can take minutes. llama-server reports its | |
| 187 | +# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report | |
| 188 | +# restarts this clock, so it only has to cover one batch of the prompt. | |
| 189 | +firstTokenTimeout: 3m | |
| 190 | + | |
| 191 | +# Context compression. | |
| 192 | +# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to. | |
| 193 | +context: | |
| 194 | + enabled: true | |
| 195 | + | |
| 196 | + # Compress when the history reaches this share of the window. | |
| 197 | + threshold: 75 | |
| 198 | + | |
| 199 | + # Fallback on the message count, for when the window is unknown. | |
| 200 | + # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history. | |
| 201 | + maxMessages: 80 | |
| 202 | + | |
| 203 | + # How many recent questions (with their commands and answers) are kept as-is instead of being summarised. | |
| 204 | + # The model works on the last few turns, so summarising them would make it redo what it just did. | |
| 205 | + keepLastTurns: 3 | |
| 206 | + | |
| 207 | + # max_tokens of the summary request. Reasoning is turned off for it on this provider | |
| 208 | + # (a thinking model would otherwise spend the budget thinking and write nothing). | |
| 209 | + summaryMaxTokens: 1200 | |
| 210 | + | |
| 211 | + showStats: true | |
| new file mode 100644 | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | +# Agent settings — Jan: mini-me on hf.co/Menlo/Jan-nano-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman) | ||
| 2 | +# through its OpenAI-compatible endpoint (/v1/chat/completions). | ||
| 3 | +# | ||
| 4 | +# llmman pull hf.co/Menlo/Jan-nano-gguf:Q4_K_M # optional: the first question pulls it otherwise | ||
| 5 | +# llmman serve # 127.0.0.1:17434 | ||
| 6 | +# | ||
| 7 | +# llmman loads the model on the first request (in its own llama-server) and | ||
| 8 | +# unloads it after five idle minutes. | ||
| 9 | +provider: llmman | ||
| 10 | + | ||
| 11 | +# The model id exactly as `llmman list` / GET /v1/models spells it. | ||
| 12 | +model: hf.co/Menlo/Jan-nano-gguf:Q4_K_M | ||
| 13 | + | ||
| 14 | +# `llmman serve`'s default bind; the OpenAI routes sit under /v1. | ||
| 15 | +baseUrl: http://127.0.0.1:17434/v1 | ||
| 16 | + | ||
| 17 | +# From a Docker sandbox, the daemon runs on the host. | ||
| 18 | +fallback: http://host.docker.internal:17434/v1 | ||
| 19 | + | ||
| 20 | +# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it | ||
| 21 | +# listens beyond loopback); unset otherwise. The key never goes in this file. | ||
| 22 | +# apiKeyEnv: LLMMAN_API_KEY | ||
| 23 | + | ||
| 24 | +# Yolo mode. `true` (default): the tools run without asking. | ||
| 25 | +# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change | ||
| 26 | +# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the | ||
| 27 | +# terminal, the window and the editor; MCP tools ask too. | ||
| 28 | +# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs), | ||
| 29 | +# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false. | ||
| 30 | +yolo: true | ||
| 31 | + | ||
| 32 | +# The `bash` tool. | ||
| 33 | +# `false` removes it: the model can still read and edit files (editTools) and load skills, | ||
| 34 | +# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool". | ||
| 35 | +bashTool: true | ||
| 36 | + | ||
| 37 | +# The built-in file tools: read_file, write_file, edit_file. | ||
| 38 | +editTools: true | ||
| 39 | + | ||
| 40 | +# The built-in plan tool for managing multi-step plans. | ||
| 41 | +# Set to false to disable plan creation and tracking via the `plan` tool. | ||
| 42 | +planTool: true | ||
| 43 | + | ||
| 44 | +# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | ||
| 45 | +# The file extension picks the server. A server missing from the PATH is skipped with a warning. | ||
| 46 | +# No server listed = no `lsp` tool. Examples (uncomment what you have installed): | ||
| 47 | +# lsp: | ||
| 48 | +# servers: | ||
| 49 | +# - name: gopls | ||
| 50 | +# command: gopls | ||
| 51 | +# extensions: [".go"] | ||
| 52 | +# - name: typescript | ||
| 53 | +# command: typescript-language-server | ||
| 54 | +# args: ["--stdio"] | ||
| 55 | +# extensions: [".ts", ".tsx", ".js", ".jsx"] | ||
| 56 | +# - name: python | ||
| 57 | +# command: pyright-langserver | ||
| 58 | +# args: ["--stdio"] | ||
| 59 | +# extensions: [".py"] | ||
| 60 | +# - name: rust | ||
| 61 | +# command: rust-analyzer | ||
| 62 | +# extensions: [".rs"] | ||
| 63 | + | ||
| 64 | +# How many tokens the server actually serves. | ||
| 65 | +# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is | ||
| 66 | +# learned before the second question. Set it here if you want it from the start | ||
| 67 | +# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable. | ||
| 68 | +contextWindow: 0 | ||
| 69 | + | ||
| 70 | +# Max number of characters a tool returns to the model. | ||
| 71 | +# Context safeguard: beyond that, the output is truncated (beginning + end kept). | ||
| 72 | +maxOutput: 16000 | ||
| 73 | + | ||
| 74 | +# Max number of model <-> tools round trips for a single question. | ||
| 75 | +# Raise it for tasks that need long chains of commands. | ||
| 76 | +maxTurns: 40 | ||
| 77 | + | ||
| 78 | +# Where the `read_skill` tool looks for its markdown procedures. | ||
| 79 | +# The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/. | ||
| 80 | +skillsDir: ../skills | ||
| 81 | + | ||
| 82 | +# Persistent sessions, per project. | ||
| 83 | +# When enabled, every conversation is saved as one JSON file under `dir`. | ||
| 84 | +# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread. | ||
| 85 | +sessions: | ||
| 86 | + enabled: true | ||
| 87 | + dir: .mm/sessions | ||
| 88 | + | ||
| 89 | +# How many lines of a command's output are echoed to the terminal. | ||
| 90 | +# 0 disables it. | ||
| 91 | +previewLines: 20 | ||
| 92 | + | ||
| 93 | +displayCommands: true | ||
| 94 | +# Show what a thinking model reasons about before it answers (dim italic in the | ||
| 95 | +# terminal, its own style in the window, a thought chunk in an editor). | ||
| 96 | +# The reasoning is always READ — it is what keeps the watchdog alive while the | ||
| 97 | +# model thinks — this only says whether to show it. | ||
| 98 | +showThinking: true | ||
| 99 | + | ||
| 100 | + | ||
| 101 | +acp: | ||
| 102 | + name: jan | ||
| 103 | + title: Jan (coding agent) | ||
| 104 | + | ||
| 105 | +# The system prompt: what the agent is, and what it is allowed to do. | ||
| 106 | +# This is the knob to play with — it is the shortest path to changing behaviour. | ||
| 107 | +system: | | ||
| 108 | + Your name is Jan. | ||
| 109 | + You are a coding agent working in a terminal. | ||
| 110 | + You have a "bash" tool to run shell commands. | ||
| 111 | + Use it to explore files, run tests, inspect the repository, etc. | ||
| 112 | + Chain several commands if needed, then answer clearly in English. | ||
| 113 | + | ||
| 114 | + A request often mixes things you answer from yourself ("say hello") with | ||
| 115 | + things only a command can answer ("list the files"). Handle every part, in | ||
| 116 | + the order asked, and run a command for each part that needs one. | ||
| 117 | + Never state the contents of a file, the output of a command, or the state of | ||
| 118 | + the repository unless a command in THIS answer returned it. What you did not | ||
| 119 | + read, you do not know: run the command instead of recalling it. | ||
| 120 | + | ||
| 121 | + SKILLS | ||
| 122 | + You have a second tool, `read_skill`. Its description lists the procedures | ||
| 123 | + available for this project — one per kind of task. | ||
| 124 | + | ||
| 125 | + Any request to DO something to a Go project is a skill, not a shell command | ||
| 126 | + you invent. Match the request against that list, call `read_skill` FIRST, | ||
| 127 | + before any bash command, and then follow what it says step by step. | ||
| 128 | + | ||
| 129 | + FILE EDITING | ||
| 130 | + You have three tools for files: `read_file`, `edit_file` and `write_file`. | ||
| 131 | + They are how a file gets read and changed here: each change is exact, | ||
| 132 | + checked before it is written, and comes back as a diff with line numbers. | ||
| 133 | + bash is for running things — building, testing, listing, searching. | ||
| 134 | + | ||
| 135 | + - Read before you write: call `read_file` on the file (numbered=true when | ||
| 136 | + you need line numbers). You cannot target text you have not seen; never | ||
| 137 | + rely on what you think you remember about a file. | ||
| 138 | + - To change an existing file, call `edit_file` with one or more {old, new} | ||
| 139 | + pairs. `old` is copied from the file character for character — same | ||
| 140 | + spaces, same indentation, same line breaks — and appears exactly once: | ||
| 141 | + add the surrounding lines until it is unique. Several pairs are applied | ||
| 142 | + together, against the original file. An empty `new` deletes the text. | ||
| 143 | + - Call `write_file` only to create a file, or to rewrite one entirely and | ||
| 144 | + on purpose. On an existing file it replaces everything, including what | ||
| 145 | + you did not intend to touch. | ||
| 146 | + - Read the diff the tool returns: it says exactly what changed and on which | ||
| 147 | + line. If `edit_file` refuses — text not found, ambiguous, overlapping | ||
| 148 | + edits — read the file again and fix `old`. Do not fall back to | ||
| 149 | + `write_file` to force the change through. | ||
| 150 | + - After editing code, run the narrowest check with bash: the formatter, the | ||
| 151 | + compiler, or the test covering that file. | ||
| 152 | + | ||
| 153 | + RULES | ||
| 154 | + - Keep everything the file already does, unless the user asked to remove it. | ||
| 155 | + - Touch only the files the request is about. Do not add tests, files or | ||
| 156 | + features that were not asked for. | ||
| 157 | + - Never run a git command unless the user says git, commit or push. | ||
| 158 | + - Never move, rename or delete a file unless the user asked for it. | ||
| 159 | + - Then answer in English, in a few lines. | ||
| 160 | + - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`) | ||
| 161 | + to understand the options, then run the command. | ||
| 162 | + | ||
| 163 | + BACKGROUND JOBS | ||
| 164 | + Never let a command block the answer. Anything that serves, watches or runs | ||
| 165 | + long goes to the background, with BOTH streams redirected and its pid kept: | ||
| 166 | + | ||
| 167 | + nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid | ||
| 168 | + | ||
| 169 | + Redirecting only stdout still blocks until the process exits. Read the | ||
| 170 | + `bg-jobs` skill before you wait on, inspect or stop such a job — each has a | ||
| 171 | + rule you cannot guess. Stop every job you started before you finish, and say | ||
| 172 | + which ones you left running. | ||
| 173 | + | ||
| 174 | +# Generation settings (OpenAI API keys). Low temperature for a coding agent: | ||
| 175 | +# we want precise and reproducible answers, not creativity. | ||
| 176 | +sampling: | ||
| 177 | + temperature: 0.0 | ||
| 178 | + parallel_tool_calls: false | ||
| 179 | + top_p: 0.9 | ||
| 180 | + max_tokens: 4096 | ||
| 181 | + | ||
| 182 | +# Silence allowed between two tokens once the answer has started. | ||
| 183 | +watchdogTimeout: 30s | ||
| 184 | + | ||
| 185 | +# Silence allowed while the model reads the prompt, before the first token: | ||
| 186 | +# on a laptop a 25k-token prompt can take minutes. llama-server reports its | ||
| 187 | +# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report | ||
| 188 | +# restarts this clock, so it only has to cover one batch of the prompt. | ||
| 189 | +firstTokenTimeout: 3m | ||
| 190 | + | ||
| 191 | +# Context compression. | ||
| 192 | +# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to. | ||
| 193 | +context: | ||
| 194 | + enabled: true | ||
| 195 | + | ||
| 196 | + # Compress when the history reaches this share of the window. | ||
| 197 | + threshold: 75 | ||
| 198 | + | ||
| 199 | + # Fallback on the message count, for when the window is unknown. | ||
| 200 | + # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history. | ||
| 201 | + maxMessages: 80 | ||
| 202 | + | ||
| 203 | + # How many recent questions (with their commands and answers) are kept as-is instead of being summarised. | ||
| 204 | + # The model works on the last few turns, so summarising them would make it redo what it just did. | ||
| 205 | + keepLastTurns: 3 | ||
| 206 | + | ||
| 207 | + # max_tokens of the summary request. Reasoning is turned off for it on this provider | ||
| 208 | + # (a thinking model would otherwise spend the budget thinking and write nothing). | ||
| 209 | + summaryMaxTokens: 1200 | ||
| 210 | + | ||
| 211 | + showStats: true | ||
added
sbx/kits/cli-tools/cli-tools.dockerfile +44 -0 | new file mode 100644 | ||
| @@ -0,0 +1,44 @@ | ||
| 1 | +# syntax=docker/dockerfile:1 | |
| 2 | +FROM debian:trixie-slim AS build | |
| 3 | +ARG RG_VERSION | |
| 4 | +ARG BAT_VERSION | |
| 5 | +ARG EZA_VERSION | |
| 6 | +ARG TARGETARCH | |
| 7 | + | |
| 8 | +# A heredoc RUN does not stop at the first failing line by itself: every | |
| 9 | +# script starts with `set -eu`. | |
| 10 | +RUN <<EOF | |
| 11 | +set -eu | |
| 12 | +apt-get update | |
| 13 | +apt-get install -y --no-install-recommends curl ca-certificates tar gzip findutils | |
| 14 | +rm -rf /var/lib/apt/lists/* | |
| 15 | +EOF | |
| 16 | + | |
| 17 | +# Static (musl) builds where upstream publishes them for the architecture. | |
| 18 | +# eza only ships a musl build for x86_64; on arm64 we use its gnu build, | |
| 19 | +# which runs on the Ubuntu-based sandbox templates (glibc). | |
| 20 | +RUN <<EOF | |
| 21 | +set -eu | |
| 22 | +case "${TARGETARCH}" in | |
| 23 | + amd64) arch=x86_64; eza_triple=x86_64-unknown-linux-musl ;; | |
| 24 | + arm64) arch=aarch64; eza_triple=aarch64-unknown-linux-gnu ;; | |
| 25 | + *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | |
| 26 | +esac | |
| 27 | +mkdir -p /out/usr/local/bin /tmp/rg /tmp/bat /tmp/eza | |
| 28 | + | |
| 29 | +curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/ripgrep-${RG_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | |
| 30 | + | tar -xz -C /tmp/rg | |
| 31 | +install -m 0755 "$(find /tmp/rg -type f -name rg | head -n1)" /out/usr/local/bin/rg | |
| 32 | + | |
| 33 | +curl -fsSL "https://github.com/sharkdp/bat/releases/download/v${BAT_VERSION}/bat-v${BAT_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | |
| 34 | + | tar -xz -C /tmp/bat | |
| 35 | +install -m 0755 "$(find /tmp/bat -type f -name bat | head -n1)" /out/usr/local/bin/bat | |
| 36 | + | |
| 37 | +curl -fsSL "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/eza_${eza_triple}.tar.gz" \ | |
| 38 | + | tar -xz -C /tmp/eza | |
| 39 | +install -m 0755 "$(find /tmp/eza -type f -name eza | head -n1)" /out/usr/local/bin/eza | |
| 40 | +EOF | |
| 41 | + | |
| 42 | +# Overlay: only the three binaries land on the workload. | |
| 43 | +FROM scratch | |
| 44 | +COPY --from=build /out/ / | |
| new file mode 100644 | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | +# syntax=docker/dockerfile:1 | ||
| 2 | +FROM debian:trixie-slim AS build | ||
| 3 | +ARG RG_VERSION | ||
| 4 | +ARG BAT_VERSION | ||
| 5 | +ARG EZA_VERSION | ||
| 6 | +ARG TARGETARCH | ||
| 7 | + | ||
| 8 | +# A heredoc RUN does not stop at the first failing line by itself: every | ||
| 9 | +# script starts with `set -eu`. | ||
| 10 | +RUN <<EOF | ||
| 11 | +set -eu | ||
| 12 | +apt-get update | ||
| 13 | +apt-get install -y --no-install-recommends curl ca-certificates tar gzip findutils | ||
| 14 | +rm -rf /var/lib/apt/lists/* | ||
| 15 | +EOF | ||
| 16 | + | ||
| 17 | +# Static (musl) builds where upstream publishes them for the architecture. | ||
| 18 | +# eza only ships a musl build for x86_64; on arm64 we use its gnu build, | ||
| 19 | +# which runs on the Ubuntu-based sandbox templates (glibc). | ||
| 20 | +RUN <<EOF | ||
| 21 | +set -eu | ||
| 22 | +case "${TARGETARCH}" in | ||
| 23 | + amd64) arch=x86_64; eza_triple=x86_64-unknown-linux-musl ;; | ||
| 24 | + arm64) arch=aarch64; eza_triple=aarch64-unknown-linux-gnu ;; | ||
| 25 | + *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | ||
| 26 | +esac | ||
| 27 | +mkdir -p /out/usr/local/bin /tmp/rg /tmp/bat /tmp/eza | ||
| 28 | + | ||
| 29 | +curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/ripgrep-${RG_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | ||
| 30 | + | tar -xz -C /tmp/rg | ||
| 31 | +install -m 0755 "$(find /tmp/rg -type f -name rg | head -n1)" /out/usr/local/bin/rg | ||
| 32 | + | ||
| 33 | +curl -fsSL "https://github.com/sharkdp/bat/releases/download/v${BAT_VERSION}/bat-v${BAT_VERSION}-${arch}-unknown-linux-musl.tar.gz" \ | ||
| 34 | + | tar -xz -C /tmp/bat | ||
| 35 | +install -m 0755 "$(find /tmp/bat -type f -name bat | head -n1)" /out/usr/local/bin/bat | ||
| 36 | + | ||
| 37 | +curl -fsSL "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/eza_${eza_triple}.tar.gz" \ | ||
| 38 | + | tar -xz -C /tmp/eza | ||
| 39 | +install -m 0755 "$(find /tmp/eza -type f -name eza | head -n1)" /out/usr/local/bin/eza | ||
| 40 | +EOF | ||
| 41 | + | ||
| 42 | +# Overlay: only the three binaries land on the workload. | ||
| 43 | +FROM scratch | ||
| 44 | +COPY --from=build /out/ / | ||
renamed
sbx/kits/cli-tools/cli-tools.yaml +4 -4 | similarity index 87% | ||
| rename from sandboxes/docker-sbx/sbx-kits/cli-tools/cli-tools.yaml | ||
| rename to sbx/kits/cli-tools/cli-tools.yaml | ||
| @@ -26,7 +26,7 @@ provides: | ||
| 26 | 26 | |
| 27 | 27 | # No runtime network: the tools are local. The downloads in the Dockerfile |
| 28 | 28 | # use the builder's network, not the sandbox policy. |
| 29 | -capabilities: | |
| 30 | - - type: com.docker.sandbox/agent-context@1 | |
| 31 | - config: | |
| 32 | - contentFile: ./cli-context.md | |
| 29 | +# capabilities: | |
| 30 | +# - type: com.docker.sandbox/agent-context@1 | |
| 31 | +# config: | |
| 32 | +# contentFile: ./cli-context.md | |
| similarity index 87% | |||
| rename from sandboxes/docker-sbx/sbx-kits/cli-tools/cli-tools.yaml | |||
| rename to sbx/kits/cli-tools/cli-tools.yaml | |||
| @@ -26,7 +26,7 @@ provides: | |||
| 26 | 26 | ||
| 27 | # No runtime network: the tools are local. The downloads in the Dockerfile | 27 | # No runtime network: the tools are local. The downloads in the Dockerfile |
| 28 | # use the builder's network, not the sandbox policy. | 28 | # use the builder's network, not the sandbox policy. |
| 29 | -capabilities: | 29 | +# capabilities: |
| 30 | - - type: com.docker.sandbox/agent-context@1 | 30 | +# - type: com.docker.sandbox/agent-context@1 |
| 31 | - config: | 31 | +# config: |
| 32 | - contentFile: ./cli-context.md | 32 | +# contentFile: ./cli-context.md |
added
sbx/kits/go-toolchain/go-toolchain.dockerfile +40 -0 | new file mode 100644 | ||
| @@ -0,0 +1,40 @@ | ||
| 1 | +# syntax=docker/dockerfile:1 | |
| 2 | + | |
| 3 | +# --- build stage: download Go, build gopls with that same Go ----------------- | |
| 4 | +FROM debian:trixie-slim AS build | |
| 5 | +ARG GO_VERSION | |
| 6 | +ARG GOPLS_VERSION=latest | |
| 7 | +ARG TARGETARCH | |
| 8 | + | |
| 9 | +# A heredoc RUN does not stop at the first failing line by itself: every | |
| 10 | +# script starts with `set -eu`. | |
| 11 | +RUN <<EOF | |
| 12 | +set -eu | |
| 13 | +apt-get update | |
| 14 | +apt-get install -y --no-install-recommends curl ca-certificates | |
| 15 | +rm -rf /var/lib/apt/lists/* | |
| 16 | +EOF | |
| 17 | + | |
| 18 | +RUN <<EOF | |
| 19 | +set -eu | |
| 20 | +curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \ | |
| 21 | + | tar -C /usr/local -xz | |
| 22 | +rm -rf /usr/local/go/test | |
| 23 | +EOF | |
| 24 | + | |
| 25 | +# Static gopls, installed straight into the overlay tree. | |
| 26 | +ENV PATH=/usr/local/go/bin:${PATH} \ | |
| 27 | + CGO_ENABLED=0 \ | |
| 28 | + GOBIN=/out/usr/local/bin \ | |
| 29 | + GOFLAGS=-trimpath | |
| 30 | +RUN <<EOF | |
| 31 | +set -eu | |
| 32 | +go install "golang.org/x/tools/gopls@${GOPLS_VERSION}" | |
| 33 | +ln -s /usr/local/go/bin/go /out/usr/local/bin/go | |
| 34 | +ln -s /usr/local/go/bin/gofmt /out/usr/local/bin/gofmt | |
| 35 | +EOF | |
| 36 | + | |
| 37 | +# --- overlay: only the toolchain and the binaries land on the workload ------- | |
| 38 | +FROM scratch | |
| 39 | +COPY --from=build /usr/local/go /usr/local/go | |
| 40 | +COPY --from=build /out/ / | |
| new file mode 100644 | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | +# syntax=docker/dockerfile:1 | ||
| 2 | + | ||
| 3 | +# --- build stage: download Go, build gopls with that same Go ----------------- | ||
| 4 | +FROM debian:trixie-slim AS build | ||
| 5 | +ARG GO_VERSION | ||
| 6 | +ARG GOPLS_VERSION=latest | ||
| 7 | +ARG TARGETARCH | ||
| 8 | + | ||
| 9 | +# A heredoc RUN does not stop at the first failing line by itself: every | ||
| 10 | +# script starts with `set -eu`. | ||
| 11 | +RUN <<EOF | ||
| 12 | +set -eu | ||
| 13 | +apt-get update | ||
| 14 | +apt-get install -y --no-install-recommends curl ca-certificates | ||
| 15 | +rm -rf /var/lib/apt/lists/* | ||
| 16 | +EOF | ||
| 17 | + | ||
| 18 | +RUN <<EOF | ||
| 19 | +set -eu | ||
| 20 | +curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \ | ||
| 21 | + | tar -C /usr/local -xz | ||
| 22 | +rm -rf /usr/local/go/test | ||
| 23 | +EOF | ||
| 24 | + | ||
| 25 | +# Static gopls, installed straight into the overlay tree. | ||
| 26 | +ENV PATH=/usr/local/go/bin:${PATH} \ | ||
| 27 | + CGO_ENABLED=0 \ | ||
| 28 | + GOBIN=/out/usr/local/bin \ | ||
| 29 | + GOFLAGS=-trimpath | ||
| 30 | +RUN <<EOF | ||
| 31 | +set -eu | ||
| 32 | +go install "golang.org/x/tools/gopls@${GOPLS_VERSION}" | ||
| 33 | +ln -s /usr/local/go/bin/go /out/usr/local/bin/go | ||
| 34 | +ln -s /usr/local/go/bin/gofmt /out/usr/local/bin/gofmt | ||
| 35 | +EOF | ||
| 36 | + | ||
| 37 | +# --- overlay: only the toolchain and the binaries land on the workload ------- | ||
| 38 | +FROM scratch | ||
| 39 | +COPY --from=build /usr/local/go /usr/local/go | ||
| 40 | +COPY --from=build /out/ / | ||
renamed
sbx/kits/go-toolchain/go-toolchain.yaml +3 -3 | similarity index 89% | ||
| rename from sandboxes/docker-sbx/sbx-kits/go-toolchain/go-toolchain.yaml | ||
| rename to sbx/kits/go-toolchain/go-toolchain.yaml | ||
| @@ -28,6 +28,6 @@ capabilities: | ||
| 28 | 28 | - sum.golang.org |
| 29 | 29 | - github.com |
| 30 | 30 | - golang.org |
| 31 | - - type: com.docker.sandbox/agent-context@1 | |
| 32 | - config: | |
| 33 | - contentFile: ./go-context.md | |
| 31 | + # - type: com.docker.sandbox/agent-context@1 | |
| 32 | + # config: | |
| 33 | + # contentFile: ./go-context.md | |
| similarity index 89% | |||
| rename from sandboxes/docker-sbx/sbx-kits/go-toolchain/go-toolchain.yaml | |||
| rename to sbx/kits/go-toolchain/go-toolchain.yaml | |||
| @@ -28,6 +28,6 @@ capabilities: | |||
| 28 | - sum.golang.org | 28 | - sum.golang.org |
| 29 | - github.com | 29 | - github.com |
| 30 | - golang.org | 30 | - golang.org |
| 31 | - - type: com.docker.sandbox/agent-context@1 | 31 | + # - type: com.docker.sandbox/agent-context@1 |
| 32 | - config: | 32 | + # config: |
| 33 | - contentFile: ./go-context.md | 33 | + # contentFile: ./go-context.md |
added
sbx/kits/mini-me/mini-me.dockerfile +36 -0 | new file mode 100644 | ||
| @@ -0,0 +1,36 @@ | ||
| 1 | +# syntax=docker/dockerfile:1 | |
| 2 | +# | |
| 3 | +# Base: Docker's shell template = Ubuntu, non-root `agent` user (UID 1000), | |
| 4 | +# bash, git, curl, CA certificates. No agent pre-installed. | |
| 5 | +FROM docker/sandbox-templates:shell | |
| 6 | + | |
| 7 | +USER root | |
| 8 | + | |
| 9 | +# --- mm release v0.3.0 -------------------------------------------------------- | |
| 10 | +# rickub release assets are addressed by UUID, so the version cannot be derived | |
| 11 | +# from a template URL: to bump, replace these four values (URLs + SHA-256 from | |
| 12 | +# the release page). | |
| 13 | +ARG TARGETARCH | |
| 14 | +ARG MM_URL_AMD64=https://rickub.com/bots-garden/mini-me/release-assets/33d3bc3f-9195-487a-ab72-d55308f27e58 | |
| 15 | +ARG MM_SHA_AMD64=9743c634a53bfaf7dd817fbf61a27e8492464576d0223c920988025deea3732b | |
| 16 | +ARG MM_URL_ARM64=https://rickub.com/bots-garden/mini-me/release-assets/75b8fe40-a4f5-41bf-8f8d-f70ac445acd4 | |
| 17 | +ARG MM_SHA_ARM64=5557dd60d31cafa76c8c35f0eb02b0cf4ca110f11d226cbd2f9d1e2e5c429dfc | |
| 18 | + | |
| 19 | +# A heredoc RUN does not stop at the first failing line by itself: the | |
| 20 | +# script starts with `set -eu`, so a bad checksum fails the build. | |
| 21 | +RUN <<EOF | |
| 22 | +set -eu | |
| 23 | +case "${TARGETARCH}" in | |
| 24 | + amd64) url="${MM_URL_AMD64}"; sha="${MM_SHA_AMD64}" ;; | |
| 25 | + arm64) url="${MM_URL_ARM64}"; sha="${MM_SHA_ARM64}" ;; | |
| 26 | + *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | |
| 27 | +esac | |
| 28 | +curl -fsSL "${url}" -o /usr/local/bin/mm | |
| 29 | +echo "${sha} /usr/local/bin/mm" | sha256sum -c - | |
| 30 | +chmod 0755 /usr/local/bin/mm | |
| 31 | +EOF | |
| 32 | + | |
| 33 | +# Back to the sandbox user, then declare the launch command. | |
| 34 | +USER agent | |
| 35 | +ENTRYPOINT ["mm"] | |
| 36 | +CMD ["-tui"] | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | +# syntax=docker/dockerfile:1 | ||
| 2 | +# | ||
| 3 | +# Base: Docker's shell template = Ubuntu, non-root `agent` user (UID 1000), | ||
| 4 | +# bash, git, curl, CA certificates. No agent pre-installed. | ||
| 5 | +FROM docker/sandbox-templates:shell | ||
| 6 | + | ||
| 7 | +USER root | ||
| 8 | + | ||
| 9 | +# --- mm release v0.3.0 -------------------------------------------------------- | ||
| 10 | +# rickub release assets are addressed by UUID, so the version cannot be derived | ||
| 11 | +# from a template URL: to bump, replace these four values (URLs + SHA-256 from | ||
| 12 | +# the release page). | ||
| 13 | +ARG TARGETARCH | ||
| 14 | +ARG MM_URL_AMD64=https://rickub.com/bots-garden/mini-me/release-assets/33d3bc3f-9195-487a-ab72-d55308f27e58 | ||
| 15 | +ARG MM_SHA_AMD64=9743c634a53bfaf7dd817fbf61a27e8492464576d0223c920988025deea3732b | ||
| 16 | +ARG MM_URL_ARM64=https://rickub.com/bots-garden/mini-me/release-assets/75b8fe40-a4f5-41bf-8f8d-f70ac445acd4 | ||
| 17 | +ARG MM_SHA_ARM64=5557dd60d31cafa76c8c35f0eb02b0cf4ca110f11d226cbd2f9d1e2e5c429dfc | ||
| 18 | + | ||
| 19 | +# A heredoc RUN does not stop at the first failing line by itself: the | ||
| 20 | +# script starts with `set -eu`, so a bad checksum fails the build. | ||
| 21 | +RUN <<EOF | ||
| 22 | +set -eu | ||
| 23 | +case "${TARGETARCH}" in | ||
| 24 | + amd64) url="${MM_URL_AMD64}"; sha="${MM_SHA_AMD64}" ;; | ||
| 25 | + arm64) url="${MM_URL_ARM64}"; sha="${MM_SHA_ARM64}" ;; | ||
| 26 | + *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; | ||
| 27 | +esac | ||
| 28 | +curl -fsSL "${url}" -o /usr/local/bin/mm | ||
| 29 | +echo "${sha} /usr/local/bin/mm" | sha256sum -c - | ||
| 30 | +chmod 0755 /usr/local/bin/mm | ||
| 31 | +EOF | ||
| 32 | + | ||
| 33 | +# Back to the sandbox user, then declare the launch command. | ||
| 34 | +USER agent | ||
| 35 | +ENTRYPOINT ["mm"] | ||
| 36 | +CMD ["-tui"] | ||
| \ No newline at end of file | \ No newline at end of file | ||
renamed
sbx/kits/mini-me/mini-me.yaml +11 -11 | similarity index 63% | ||
| rename from sandboxes/docker-sbx/sbx-kits/mini-me/mini-me.yaml | ||
| rename to sbx/kits/mini-me/mini-me.yaml | ||
| @@ -7,7 +7,7 @@ sourceUrl: https://rickub.com/bots-garden/mini-me | ||
| 7 | 7 | |
| 8 | 8 | # Lets other kits declare `requires: [mini-me]`. |
| 9 | 9 | # Two kits that provide the same feature cannot be combined. |
| 10 | -provides: ["mini-me@0.2.6"] | |
| 10 | +provides: ["mini-me@0.3.0"] | |
| 11 | 11 | |
| 12 | 12 | capabilities: |
| 13 | 13 | # The workload is prepared for sbx to launch it (agent user, bash, ...). |
| @@ -22,14 +22,14 @@ capabilities: | ||
| 22 | 22 | allow: |
| 23 | 23 | - host.docker.internal:12434 |
| 24 | 24 | |
| 25 | - # Instructions for the agent. The workload picks the file name, | |
| 26 | - # mixins (go-toolchain, cli-tools) append their own guidance to it. | |
| 27 | - - type: com.docker.sandbox/agent-context@1 | |
| 28 | - config: | |
| 29 | - filename: AGENTS.md | |
| 30 | - contentFile: ./context.md | |
| 25 | + # # Instructions for the agent. The workload picks the file name, | |
| 26 | + # # mixins (go-toolchain, cli-tools) append their own guidance to it. | |
| 27 | + # - type: com.docker.sandbox/agent-context@1 | |
| 28 | + # config: | |
| 29 | + # filename: AGENTS.md | |
| 30 | + # contentFile: ./context.md | |
| 31 | 31 | |
| 32 | - # `sbx run` (TTY) => `mm -tui`. Headless runs use ENTRYPOINT + CMD as-is. | |
| 33 | - - type: com.docker.sandbox/lifecycle@1 | |
| 34 | - config: | |
| 35 | - interactive: ["-tui"] | |
| 32 | + # # `sbx run` (TTY) => `mm -tui`. Headless runs use ENTRYPOINT + CMD as-is. | |
| 33 | + # - type: com.docker.sandbox/lifecycle@1 | |
| 34 | + # config: | |
| 35 | + # interactive: ["-tui"] | |
| similarity index 63% | |||
| rename from sandboxes/docker-sbx/sbx-kits/mini-me/mini-me.yaml | |||
| rename to sbx/kits/mini-me/mini-me.yaml | |||
| @@ -7,7 +7,7 @@ sourceUrl: https://rickub.com/bots-garden/mini-me | |||
| 7 | 7 | ||
| 8 | # Lets other kits declare `requires: [mini-me]`. | 8 | # Lets other kits declare `requires: [mini-me]`. |
| 9 | # Two kits that provide the same feature cannot be combined. | 9 | # Two kits that provide the same feature cannot be combined. |
| 10 | -provides: ["mini-me@0.2.6"] | 10 | +provides: ["mini-me@0.3.0"] |
| 11 | 11 | ||
| 12 | capabilities: | 12 | capabilities: |
| 13 | # The workload is prepared for sbx to launch it (agent user, bash, ...). | 13 | # The workload is prepared for sbx to launch it (agent user, bash, ...). |
| @@ -22,14 +22,14 @@ capabilities: | |||
| 22 | allow: | 22 | allow: |
| 23 | - host.docker.internal:12434 | 23 | - host.docker.internal:12434 |
| 24 | 24 | ||
| 25 | - # Instructions for the agent. The workload picks the file name, | 25 | + # # Instructions for the agent. The workload picks the file name, |
| 26 | - # mixins (go-toolchain, cli-tools) append their own guidance to it. | 26 | + # # mixins (go-toolchain, cli-tools) append their own guidance to it. |
| 27 | - - type: com.docker.sandbox/agent-context@1 | 27 | + # - type: com.docker.sandbox/agent-context@1 |
| 28 | - config: | 28 | + # config: |
| 29 | - filename: AGENTS.md | 29 | + # filename: AGENTS.md |
| 30 | - contentFile: ./context.md | 30 | + # contentFile: ./context.md |
| 31 | 31 | ||
| 32 | - # `sbx run` (TTY) => `mm -tui`. Headless runs use ENTRYPOINT + CMD as-is. | 32 | + # # `sbx run` (TTY) => `mm -tui`. Headless runs use ENTRYPOINT + CMD as-is. |
| 33 | - - type: com.docker.sandbox/lifecycle@1 | 33 | + # - type: com.docker.sandbox/lifecycle@1 |
| 34 | - config: | 34 | + # config: |
| 35 | - interactive: ["-tui"] | 35 | + # interactive: ["-tui"] |