diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2dcf67..0c48ac1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,7 @@ jobs: - { suffix: "-claude", dockerfile: "Dockerfile.claude", artifact: "claude" } - { suffix: "-gemini", dockerfile: "Dockerfile.gemini", artifact: "gemini" } - { suffix: "-copilot", dockerfile: "Dockerfile.copilot", artifact: "copilot" } + - { suffix: "-opencode", dockerfile: "Dockerfile.opencode", artifact: "opencode" } platform: - { os: linux/amd64, runner: ubuntu-latest } - { os: linux/arm64, runner: ubuntu-24.04-arm } @@ -131,6 +132,7 @@ jobs: - { suffix: "-claude", artifact: "claude" } - { suffix: "-gemini", artifact: "gemini" } - { suffix: "-copilot", artifact: "copilot" } + - { suffix: "-opencode", artifact: "opencode" } runs-on: ubuntu-latest permissions: contents: read @@ -179,6 +181,7 @@ jobs: - { suffix: "-claude" } - { suffix: "-gemini" } - { suffix: "-copilot" } + - { suffix: "-opencode" } runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/docker-smoke-test.yml b/.github/workflows/docker-smoke-test.yml index 4045c8b..d20db90 100644 --- a/.github/workflows/docker-smoke-test.yml +++ b/.github/workflows/docker-smoke-test.yml @@ -18,6 +18,7 @@ jobs: - { dockerfile: Dockerfile.codex, suffix: "-codex", agent: "codex-acp", agent_args: "" } - { dockerfile: Dockerfile.gemini, suffix: "-gemini", agent: "gemini", agent_args: "--acp" } - { dockerfile: Dockerfile.copilot, suffix: "-copilot", agent: "copilot", agent_args: "--acp" } + - { dockerfile: Dockerfile.opencode, suffix: "-opencode", agent: "opencode", agent_args: "acp" } runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 diff --git a/Dockerfile.opencode b/Dockerfile.opencode new file mode 100644 index 0000000..a93c054 --- /dev/null +++ b/Dockerfile.opencode @@ -0,0 +1,48 @@ +# --- Build stage --- +FROM rust:1-bookworm AS builder +WORKDIR /build +COPY Cargo.toml Cargo.lock ./ +RUN mkdir src && echo 'fn main() {}' > src/main.rs && cargo build --release && rm -rf src +COPY src/ src/ +RUN touch src/main.rs && cargo build --release + +# --- Runtime stage --- +# node:22-bookworm-slim mirrors the base image used by Dockerfile.claude, +# Dockerfile.codex, and Dockerfile.gemini, keeping the project on a single +# consistent runtime base. +# +# opencode is published to npm as `opencode-ai`; the npm package is a thin +# postinstall wrapper (~9 KB) that downloads the same pre-compiled binary +# used by the official install script, so `npm install -g` and +# `curl | bash` are equivalent in the end result. +# +# Version is pinned for reproducible builds. +# opencode releases very frequently (often daily); bump this version via +# a dedicated PR when a new release is needed. +# +# Note: opencode does not publish SHA256 checksums for its releases, +# so checksum verification is not possible at this time. +FROM node:22-bookworm-slim +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl && rm -rf /var/lib/apt/lists/* + +# Install opencode +RUN npm install -g opencode-ai@1.4.3 --retry 3 + +# Install gh CLI (matches Dockerfile.claude / Dockerfile.gemini / Dockerfile.codex) +RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ + -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ + > /etc/apt/sources.list.d/github-cli.list && \ + apt-get update && apt-get install -y --no-install-recommends gh && \ + rm -rf /var/lib/apt/lists/* + +ENV HOME=/home/node +WORKDIR /home/node + +COPY --from=builder --chown=node:node /build/target/release/openab /usr/local/bin/openab + +USER node +HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ + CMD pgrep -x openab || exit 1 +ENTRYPOINT ["openab"] +CMD ["run", "/etc/openab/config.toml"] diff --git a/README.md b/README.md index 6ad1dbc..a516382 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OpenAB — Open Agent Broker -A lightweight, secure, cloud-native ACP harness that bridges Discord and any [Agent Client Protocol](https://github.com/anthropics/agent-protocol)-compatible coding CLI (Kiro CLI, Claude Code, Codex, Gemini, Copilot CLI, etc.) over stdio JSON-RPC — delivering the next-generation development experience. +A lightweight, secure, cloud-native ACP harness that bridges Discord and any [Agent Client Protocol](https://github.com/anthropics/agent-protocol)-compatible coding CLI (Kiro CLI, Claude Code, Codex, Gemini, OpenCode, Copilot CLI, etc.) over stdio JSON-RPC — delivering the next-generation development experience. 🪼 **Join our community!** Come say hi on Discord — we'd love to have you: **[🪼 OpenAB — Official](https://discord.gg/YNksK9M6)** 🎉 @@ -17,7 +17,7 @@ A lightweight, secure, cloud-native ACP harness that bridges Discord and any [Ag ## Features -- **Pluggable agent backend** — swap between Kiro CLI, Claude Code, Codex, Gemini, Copilot CLI via config +- **Pluggable agent backend** — swap between Kiro CLI, Claude Code, Codex, Gemini, OpenCode, Copilot CLI via config - **@mention trigger** — mention the bot in an allowed channel to start a conversation - **Thread-based multi-turn** — auto-creates threads; no @mention needed for follow-ups - **Edit-streaming** — live-updates the Discord message every 1.5s as tokens arrive @@ -68,6 +68,7 @@ The bot creates a thread. After that, just type in the thread — no @mention ne | Claude Code | `claude-agent-acp` | [@agentclientprotocol/claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) | [docs/claude-code.md](docs/claude-code.md) | | Codex | `codex-acp` | [@zed-industries/codex-acp](https://github.com/zed-industries/codex-acp) | [docs/codex.md](docs/codex.md) | | Gemini | `gemini --acp` | Native | [docs/gemini.md](docs/gemini.md) | +| OpenCode | `opencode acp` | Native | [docs/opencode.md](docs/opencode.md) | | Copilot CLI ⚠️ | `copilot --acp --stdio` | Native | [docs/copilot.md](docs/copilot.md) | > 🔧 Running multiple agents? See [docs/multi-agent.md](docs/multi-agent.md) diff --git a/charts/openab/Chart.yaml b/charts/openab/Chart.yaml index e3506b0..1e1112f 100644 --- a/charts/openab/Chart.yaml +++ b/charts/openab/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: openab -description: Discord ↔ ACP coding CLI bridge (Kiro CLI, Claude Code, Codex, Gemini) +description: A lightweight, secure, cloud-native ACP harness that bridges Discord and any ACP-compatible coding CLI. type: application version: 0.7.5 appVersion: "0.7.5" diff --git a/charts/openab/values.yaml b/charts/openab/values.yaml index 4cb6bac..f895671 100644 --- a/charts/openab/values.yaml +++ b/charts/openab/values.yaml @@ -53,6 +53,33 @@ agents: # tolerations: [] # affinity: {} # image: "ghcr.io/openabdev/openab-claude:latest" + # opencode: + # command: opencode + # args: + # - acp + # discord: + # botToken: "" + # allowedChannels: + # - "YOUR_CHANNEL_ID" + # allowedUsers: [] + # allowBotMessages: "off" + # trustedBotIds: [] + # workingDir: /home/node + # env: {} + # envFrom: [] + # pool: + # maxSessions: 10 + # sessionTtlHours: 24 + # reactions: + # enabled: true + # removeAfterReply: false + # persistence: + # enabled: true + # storageClass: "" + # size: 1Gi + # agentsMd: "" + # resources: {} + # image: "ghcr.io/openabdev/openab-opencode:latest" image: "" command: kiro-cli args: diff --git a/config.toml.example b/config.toml.example index 60db88f..538e2fe 100644 --- a/config.toml.example +++ b/config.toml.example @@ -35,6 +35,15 @@ working_dir = "/home/agent" # working_dir = "/home/agent" # env = {} # Auth via: kubectl exec -it -- gh auth login -p https -w +# [agent] +# command = "opencode" +# args = ["acp"] +# working_dir = "/home/node" +# # Note: opencode handles tool authorization internally and never emits +# # session/request_permission — all tools run without user confirmation, +# # equivalent to --trust-all-tools on other backends. +# # Run `opencode auth login` once before starting openab. + [pool] max_sessions = 10 session_ttl_hours = 24 diff --git a/docs/opencode.md b/docs/opencode.md new file mode 100644 index 0000000..8d452d0 --- /dev/null +++ b/docs/opencode.md @@ -0,0 +1,52 @@ +# OpenCode + +OpenCode supports ACP natively via the `acp` subcommand — no adapter needed. + +## Docker Image + +```bash +docker build -f Dockerfile.opencode -t openab-opencode:latest . +``` + +The image installs `opencode-ai` globally via npm on `node:22-bookworm-slim`. + +## Helm Install + +```bash +helm install openab openab/openab \ + --set agents.kiro.enabled=false \ + --set agents.opencode.discord.botToken="$DISCORD_BOT_TOKEN" \ + --set-string 'agents.opencode.discord.allowedChannels[0]=YOUR_CHANNEL_ID' \ + --set agents.opencode.image=ghcr.io/openabdev/openab-opencode:latest \ + --set agents.opencode.command=opencode \ + --set 'agents.opencode.args={acp}' \ + --set agents.opencode.workingDir=/home/node +``` + +> Set `agents.kiro.enabled=false` to disable the default Kiro agent. + +## Manual config.toml + +```toml +[agent] +command = "opencode" +args = ["acp"] +working_dir = "/home/node" +``` + +## Authentication + +```bash +kubectl exec -it deployment/openab-opencode -- opencode auth login +``` + +Follow the browser OAuth flow, then restart the pod: + +```bash +kubectl rollout restart deployment/openab-opencode +``` + +## Notes + +- **Tool authorization**: OpenCode handles tool authorization internally and never emits `session/request_permission` — all tools run without user confirmation, equivalent to `--trust-all-tools` on other backends. +- **Frequent releases**: OpenCode releases very frequently (often daily). The pinned version in `Dockerfile.opencode` should be bumped via a dedicated PR when an update is needed.