diff --git a/Dockerfile.qwen b/Dockerfile.qwen new file mode 100644 index 00000000..f5908138 --- /dev/null +++ b/Dockerfile.qwen @@ -0,0 +1,23 @@ +# --- 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 --- +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 Qwen Code CLI (native ACP support via --experimental-acp) +RUN npm install -g @qwen-code/qwen-code + +RUN mkdir -p /home/agent && chown node:node /home/agent +ENV HOME=/home/agent +WORKDIR /home/agent + +COPY --from=builder /build/target/release/agent-broker /usr/local/bin/agent-broker + +ENTRYPOINT ["agent-broker"] +CMD ["/etc/agent-broker/config.toml"] diff --git a/README.md b/README.md index 4c05fdb2..48fd7d9e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # agent-broker -A Rust bridge service between Discord and any ACP-compatible coding CLI (Kiro CLI, Claude Code, Codex, Gemini, etc.) using the [Agent Client Protocol](https://github.com/anthropics/agent-protocol) over stdio JSON-RPC. +A Rust bridge service between Discord and any ACP-compatible coding CLI (Kiro CLI, Claude Code, Codex, Gemini, Qwen Code, etc.) using the [Agent Client Protocol](https://github.com/anthropics/agent-protocol) over stdio JSON-RPC. ``` ┌──────────────┐ Gateway WS ┌──────────────┐ ACP stdio ┌──────────────┐ @@ -15,7 +15,7 @@ A Rust bridge service between Discord and any ACP-compatible coding CLI (Kiro CL ## Features -- **Pluggable agent backend** — swap between Kiro CLI, Claude Code, Codex, Gemini via config +- **Pluggable agent backend** — swap between Kiro CLI, Claude Code, Codex, Gemini, Qwen Code 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 @@ -89,6 +89,7 @@ Swap backends using the `agent.preset` Helm value or manual config. Tested backe | `codex` | Codex | [@zed-industries/codex-acp](https://github.com/zed-industries/codex-acp) | `codex login --device-auth` | | `claude` | Claude Code | [@agentclientprotocol/claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) | `claude setup-token` | | `gemini` | Gemini CLI | Native `gemini --acp` | Google OAuth or `GEMINI_API_KEY` | +| `qwen` | Qwen Code | Native `qwen --experimental-acp` | `QWEN_API_KEY` | ### Helm Install (recommended) @@ -118,6 +119,12 @@ helm install agent-broker agent-broker/agent-broker \ --set discord.botToken="$DISCORD_BOT_TOKEN" \ --set discord.allowedChannels[0]="YOUR_CHANNEL_ID" \ --set agent.preset=gemini + +# Qwen Code +helm install agent-broker agent-broker/agent-broker \ + --set discord.botToken="$DISCORD_BOT_TOKEN" \ + --set discord.allowedChannels[0]="YOUR_CHANNEL_ID" \ + --set agent.preset=qwen ``` Then authenticate inside the pod (first time only): @@ -136,6 +143,9 @@ kubectl exec -it deployment/agent-broker -- claude setup-token # Gemini (Google OAuth — open URL in browser, curl callback from pod) kubectl exec -it deployment/agent-broker -- gemini # Or use API key: helm upgrade agent-broker agent-broker/agent-broker --set env.GEMINI_API_KEY="" + +# Qwen Code (API key) +# helm upgrade agent-broker agent-broker/agent-broker --set env.QWEN_API_KEY="" ``` Restart after auth: `kubectl rollout restart deployment agent-broker` @@ -169,6 +179,13 @@ command = "gemini" args = ["--acp"] working_dir = "/tmp" env = { GEMINI_API_KEY = "${GEMINI_API_KEY}" } + +# Qwen Code +[agent] +command = "qwen" +args = ["--experimental-acp", "--trust-all-tools"] +working_dir = "/tmp" +env = { QWEN_API_KEY = "${QWEN_API_KEY}" } ``` ## Configuration Reference @@ -262,7 +279,7 @@ The Docker image bundles both `agent-broker` and `kiro-cli` in a single containe ### Install with Your Coding CLI -Use one of these prompts with any coding CLI (Kiro CLI, Claude Code, Codex, Gemini, etc.) on the host that has `helm` and `kubectl` access to your cluster: +Use one of these prompts with any coding CLI (Kiro CLI, Claude Code, Codex, Gemini, Qwen Code, etc.) on the host that has `helm` and `kubectl` access to your cluster: **Kiro CLI (default):** > Install agent-broker on my local k8s cluster using the Helm chart from https://thepagent.github.io/agent-broker. My Discord bot token is in the environment variable DISCORD_BOT_TOKEN and my channel ID is . After install, follow the NOTES output to authenticate, then restart the deployment. @@ -276,6 +293,9 @@ Use one of these prompts with any coding CLI (Kiro CLI, Claude Code, Codex, Gemi **Gemini:** > Install agent-broker on my local k8s cluster using the Helm chart from https://thepagent.github.io/agent-broker with `--set agent.preset=gemini`. My Discord bot token is in the environment variable DISCORD_BOT_TOKEN and my channel ID is . After install, follow the NOTES output to authenticate, then restart the deployment. +**Qwen Code:** +> Install agent-broker on my local k8s cluster using the Helm chart from https://thepagent.github.io/agent-broker with `--set agent.preset=qwen`. My Discord bot token is in the environment variable DISCORD_BOT_TOKEN and my channel ID is . After install, follow the NOTES output to authenticate, then restart the deployment. + ### Build & Push ```bash diff --git a/charts/agent-broker/templates/NOTES.txt b/charts/agent-broker/templates/NOTES.txt index 93ce32df..153fb922 100644 --- a/charts/agent-broker/templates/NOTES.txt +++ b/charts/agent-broker/templates/NOTES.txt @@ -40,6 +40,13 @@ Authenticate Gemini CLI (first time only): Alternatively, set GEMINI_API_KEY: helm upgrade {{ .Release.Name }} agent-broker/agent-broker --set env.GEMINI_API_KEY="" +{{- else if eq $cmd "qwen" }} + +Authenticate Qwen Code (first time only): + + Set QWEN_API_KEY (Alibaba Cloud ModelStudio): + + helm upgrade {{ .Release.Name }} agent-broker/agent-broker --set env.QWEN_API_KEY="" {{- else }} Authenticate your agent CLI (first time only) — refer to your CLI's documentation. diff --git a/charts/agent-broker/templates/_helpers.tpl b/charts/agent-broker/templates/_helpers.tpl index 852c50f3..c8987102 100644 --- a/charts/agent-broker/templates/_helpers.tpl +++ b/charts/agent-broker/templates/_helpers.tpl @@ -41,6 +41,7 @@ Resolve agent preset → image repository {{- if eq .Values.agent.preset "codex" }}ghcr.io/thepagent/agent-broker-codex {{- else if eq .Values.agent.preset "claude" }}ghcr.io/thepagent/agent-broker-claude {{- else if eq .Values.agent.preset "gemini" }}ghcr.io/thepagent/agent-broker-gemini + {{- else if eq .Values.agent.preset "qwen" }}ghcr.io/thepagent/agent-broker-qwen {{- else }}{{ .Values.image.repository }} {{- end }} {{- else }}{{ .Values.image.repository }} @@ -55,6 +56,7 @@ Resolve agent preset → command {{- if eq .Values.agent.preset "codex" }}codex-acp {{- else if eq .Values.agent.preset "claude" }}claude-agent-acp {{- else if eq .Values.agent.preset "gemini" }}gemini + {{- else if eq .Values.agent.preset "qwen" }}qwen {{- else }}{{ .Values.agent.command }} {{- end }} {{- else }}{{ .Values.agent.command }} @@ -68,6 +70,7 @@ Resolve agent preset → args {{- if .Values.agent.preset }} {{- if or (eq .Values.agent.preset "codex") (eq .Values.agent.preset "claude") }}[] {{- else if eq .Values.agent.preset "gemini" }}["--acp"] + {{- else if eq .Values.agent.preset "qwen" }}["--experimental-acp", "--trust-all-tools"] {{- else }}{{ .Values.agent.args | toJson }} {{- end }} {{- else }}{{ .Values.agent.args | toJson }} diff --git a/charts/agent-broker/values.yaml b/charts/agent-broker/values.yaml index f5cb314d..cedbbcc3 100644 --- a/charts/agent-broker/values.yaml +++ b/charts/agent-broker/values.yaml @@ -21,7 +21,7 @@ discord: - "YOUR_CHANNEL_ID" agent: - preset: "" # kiro (default), codex, or claude — auto-configures image + command + preset: "" # kiro (default), codex, claude, gemini, or qwen — auto-configures image + command command: kiro-cli args: - acp diff --git a/config.toml.example b/config.toml.example index c4227dc6..1d467320 100644 --- a/config.toml.example +++ b/config.toml.example @@ -25,6 +25,12 @@ working_dir = "/home/agent" # working_dir = "/home/agent" # env = { GEMINI_API_KEY = "${GEMINI_API_KEY}" } +# [agent] +# command = "qwen" +# args = ["--experimental-acp", "--trust-all-tools"] +# working_dir = "/home/agent" +# env = { QWEN_API_KEY = "${QWEN_API_KEY}" } + [pool] max_sessions = 10 session_ttl_hours = 24