openab:基于 ACP 协议的多平台编码代理桥接项目

A lightweight, secure, cloud-native ACP harness that bridges Discord and any ACP-compatible coding CLI.

分支299Tags198
文件最后提交记录最后更新时间
ci: add native to merge-manifests matrix (#932)18 小时前
fix(agy-acp): use --conversation ID + delta extraction for multi-turn (#906) Replace --continue with --conversation <ID> to fix two bugs: 1. Full conversation history repeated on every turn (#905) 2. Concurrent sessions unsafe (--continue targets most recent globally) Now tracks per-session: agy conversation ID (from conversations dir) and cumulative output length. Only emits the delta on each turn. Fixes #905 Co-authored-by: Pahud Hsieh <pahud@Pahuds-MacBook-Neo.local>4 天前
release: v0.8.4-beta.5 (#929) Co-authored-by: openab-app[bot] <274185012+openab-app[bot]@users.noreply.github.com>19 小时前
docs(adr): openab-agent — native Rust coding agent (#922) * docs(adr): propose openab-agent — native Rust coding agent with built-in ACP Single binary, no external runtime, no adapter wrapper needed. Inspired by Pi's minimal design (4 tools, tiny prompt, session trees) but implemented in Rust for zero-overhead ACP integration with openab core. * docs(adr): add required crates and key advantage sections * docs(adr): address review findings from 普渡 and 覺渡 - Fix LlmProvider trait: use BoxStream instead of bare Stream trait (compile error: Stream is a trait, not a concrete type) - Fix tokio-process deprecation: use tokio::process (merged since 0.2) - Add futures crate for Stream/BoxStream - Add Testing Strategy section (unit test boundaries, hand-written mocks, integration test tags, CI pipeline) - Remove deprecated sandbox-exec reliance on macOS - Add explanatory notes on trait object safety design decisions --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>15 小时前
fix(gateway/googlechat): handle HTTP endpoint URL events + correct JWT signer email (#909) * fix(gateway/googlechat): handle HTTP endpoint URL events + correct JWT signer email Two independent bugs prevent the Google Chat adapter from working with the connection mode recommended by docs/google-chat.md: 1. Envelope schema only deserialized the Pub/Sub-wrapped shape, but HTTP endpoint URL connections deliver top-level fields (message, user, space). All real webhooks silently dropped at `envelope.chat is None` with a 200 response. 2. JWT email allow-list expected @gcp-sa-gsuiteaddons.iam.gserviceaccount.com (Workspace Add-ons signer), but Google Chat HTTP webhooks are signed by chat@system.gserviceaccount.com. Setting GOOGLE_CHAT_AUDIENCE per docs returned 401 to every webhook. Together, following the docs produced a 100% non-working bot. This change: - Extends GoogleChatEnvelope with optional top-level fields and adds a fallback branch in the webhook handler; existing wrapped-shape tests continue to pass unchanged. - Renames GOOGLE_CHAT_EMAIL_SUFFIX → GOOGLE_CHAT_SIGNER_EMAIL, changes the value to chat@system.gserviceaccount.com, and tightens the check from `ends_with` to exact equality. - Updates the existing email-claim test to assert the new signer. Verified end-to-end on a production cc-agent deployment (1:1 DM + Space @mention) via Cloudflare Tunnel sidecar; gateway forwards events to OAB and replies arrive in Chat. Closes #899 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test: add unit test for HTTP endpoint URL top-level envelope parsing --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: chaodu-agent[bot] <chaodu-agent[bot]@users.noreply.github.com>3 天前
docs: replace banner with official project artwork Swap the placeholder banner.png for the new official OpenAB banner image (banner.jpg) and update the README reference accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> 1 个月前
fix: harden Dockerfiles with non-root user, HEALTHCHECK, and securityContext (#73) - Dockerfile: useradd -u 1000, --chown=agent:agent, curl --retry, HEALTHCHECK - Dockerfile.claude/codex/gemini: use built-in node user /home/node, --chown=node:node, npm --retry, HEALTHCHECK - Helm chart: podSecurityContext + containerSecurityContext, preset-aware home helper - k8s manifests: pod + container securityContext Co-authored-by: thepagent <thepagent@users.noreply.github.com>1 个月前
feat: openab-agent — native Rust coding agent with subscription auth (#924) * feat: openab-agent v0.1 — native Rust coding agent with ACP Implements the v0.1 scope from ADR (PR #922): - ACP layer: stdin/stdout JSON-RPC (initialize, session/new, session/prompt, session/cancel) - LLM client: Anthropic provider with non-streaming API (BoxStream deferred to v0.2) - 4 tools: read, write, edit, bash - Path traversal protection (canonicalize + boundary check) - Environment variable filtering (allow-list only) - Process group kill on timeout (setsid + kill(-pgid)) - Agent core: system prompt + tool dispatch loop (max 50 iterations) - Unit tests: hand-written MockLlmProvider, tests for prompt assembly, tool dispatch, error handling, and multi-step tool chains - Flat session (session tree deferred to v0.2) Architecture: openab ──stdio JSON-RPC──► openab-agent ──HTTP──► Anthropic API No external runtime required. Single binary, ~20MB when compiled. * fix: address review findings from 覺渡 (PR #924) - Fix validate_path: remove create_dir_all side-effect that could create directories outside working_dir before boundary check. Now uses parent traversal to find nearest existing ancestor without modifying filesystem. - Fix unit test isolation: mark all FS/process tests with #[ignore] per Unit Test Strategy ADR. Only pure logic tests run by default. - Fix unsafe setsid: check return value, propagate error on failure. - Fix OPENAB_AGENT_BASH_ENV_ALLOW: read comma-separated env var and pass allowed keys to build_env for subprocess inheritance. - Fix streaming capability: set to false in ACP initialize response since v0.1 uses non-streaming Anthropic Messages API. * fix: address review findings from 普渡 (PR #924) - 🔴 F1: Add context window truncation (MAX_CONTEXT_MESSAGES=100), drops oldest messages preserving first user prompt - 🟡 F3: Return error when MAX_TOOL_LOOPS exhausted instead of empty string - 🟡 F5: Fail-fast on missing/empty ANTHROPIC_API_KEY at session creation - 🟡 F6: Add retry with exponential backoff for 429/529 (max 3 retries) - 🟡 F7: Await child process after SIGKILL to prevent zombies - 🟡 F8: Add TODO(v0.2) for session/cancel implementation - 🟡 F9: Validate empty prompt, return -32602 error - 🟡 F10: Add TODO(v0.2) for session TTL/cleanup - 🟡 F11: Remove std::env::set_var from tests (UB in multi-thread) * fix: truncate_context pair-drain + test_session_new CI fix - N1: truncate_context now drains in pairs (assistant+user) to maintain strict role alternation required by Anthropic API - N2: test_session_new sets fake ANTHROPIC_API_KEY for CI environments; added test_session_new_missing_key for error case * feat: add subscription auth via OAuth device flow Add support for Codex/OpenAI subscription authentication: CLI: openab-agent auth codex-oauth # device flow login openab-agent auth status # show stored credentials openab-agent # ACP mode (default) Auth flow: - Device code flow against OpenAI auth endpoints - Prints verification URL + user code for headless environments - Polls until user authorizes in browser - Stores tokens at ~/.openab/agent/auth.json (0600 perms) - Auto-refreshes expired tokens with 120s skew Provider fallback in ACP mode: 1. ANTHROPIC_API_KEY env var → Anthropic provider 2. ~/.openab/agent/auth.json → OpenAI provider (subscription) 3. Error with instructions if neither available OpenAI provider: - Full OpenAI chat completions API format - Tool call translation (Anthropic format ↔ OpenAI format) - Retry with exponential backoff on 429/529 * fix: address auth review findings from 覺渡 - 🔴 save_tokens permission race: use OpenOptions::mode(0o600) to create file with correct permissions atomically (no window for exposure) - 🔴 OPENAB_AGENT_PROVIDER ignored: respect env var to force provider selection (anthropic|openai|codex), auto-detect only when unset - 🟡 Token masking: safe display for any token length (>12 chars shows first 8 + last 4, otherwise shows ****) * fix: address 普渡 findings F2-F8 (auth + OpenAI provider) - F2: Add OPENAB_AGENT_OPENAI_MODEL + OPENAB_AGENT_OPENAI_BASE_URL env vars so OpenAI and Anthropic model namespaces don't conflict - F3: Increase poll interval on 'slow_down' per RFC 8628 Section 3.5 - F4: Add 10-minute wall-clock timeout to device flow polling loop - F5: Enforce minimum 5s polling interval regardless of server response - F6: Retry on 401 with token refresh; fetch fresh token each attempt - F8: Token masking already fixed in previous commit F1 (client_id) and F9 (scope) pending 主人 decision. * fix: make OAuth client_id configurable (F1) Default: 'app_scp_codex_prod_001' (same as Codex CLI, public client) Override: OPENAB_AGENT_OAUTH_CLIENT_ID env var This allows users to register their own OAuth app if needed, while maintaining compatibility with existing Codex subscriptions by default. * fix: address remaining 普渡 findings F6-F8 - F6: Add force_refresh() that bypasses expiry check; 401 handler now calls force_refresh() to guarantee a new token on next retry - F7: Add unit tests for parse_openai_response (text, tool_call, empty) and auth module (is_expired, auth_path, codex_client_id) - F8: Token masking confirmed already fixed (len>12 check at line 244) * ci: add CI workflow + Dockerfile for openab-agent CI (.github/workflows/ci-openab-agent.yml): - cargo fmt --check - cargo clippy -- -D warnings - cargo test (unit tests) - cargo test -- --ignored (integration tests) Dockerfile (Dockerfile.openab-agent): - Multi-stage build: rust:1-bookworm → distroless/cc-debian12 - Final image ~20MB, runs as nonroot - Entrypoint: openab-agent (ACP mode by default) * fix: CI compilation errors - Fix borrow-after-move: capture child pid before wait_with_output - Fix unused import: restructure cfg(unix) block for pre_exec - Fix unused variable: remove dead content Vec in OpenAiProvider - Fix extra closing brace * fix: resolve all clippy warnings - Remove unused imports (anyhow::Result, serde_json::Value, Path) - Mark Agent::new as #[cfg(test)] (only used in tests) - Allow dead_code on LlmEvent::Error variant (reserved for future use) - Move CommandExt import to top-level #[cfg(unix)] - Remove unnecessary mut on child variable - Collapse if-in-match per clippy suggestion * fix: CI errors — cannot move in pattern guard + unused import - Revert collapsed match (cannot move l in guard), add clippy allow - Move CommandExt import inside unsafe block with allow(unused_imports) * fix(openab-agent): correct device code auth flow for OpenAI - Use https://auth.openai.com/api/accounts/deviceauth/usercode endpoint - Use server-provided code_verifier (not client PKCE) - Token exchange at /oauth/token with redirect_uri=https://auth.openai.com/deviceauth/callback - Handle OpenAI's nested error format (error.code) - Correct client_id: app_EMoamEEZ73f0CkXaXp7hrann * refactor(openab-agent): remove unused PKCE deps (base64, sha2, getrandom) * refactor(openab-agent): remove unused PKCE deps from Cargo.toml * ci: add ACP smoke test — verify binary starts and speaks ACP Sends an 'initialize' JSON-RPC request to the built binary and verifies the response contains valid ACP agentInfo. This catches protocol-level regressions without needing LLM credentials. * style: cargo fmt * fix: remove unused constants (CODEX_SCOPES, CODEX_AUDIENCE) * feat(openab-agent): browser PKCE + device code auth flows * feat(openab-agent): switch to Responses API (chatgpt.com/backend-api/codex/responses) * feat(openab-agent): add codex-device subcommand + --no-browser flag * fix(openab-agent): test cleanup for OAuth auth * feat(openab-agent): add deps for browser PKCE flow (base64, sha2, getrandom, urlencoding, open, url) * docs(openab-agent): guide headless users through copy-paste callback flow * feat(openab-agent): paste-based callback for headless auth + simplified flow params * fix(openab-agent): stop tool loop when text response received * feat(openab-agent): Responses API with SSE stream parsing * fix(openab-agent): correct Responses API input format for tool results (function_call_output) * feat(openab-agent): read AGENTS.md from cwd as custom system prompt * feat: add Dockerfile.openab-agent — native Rust agent (~20MB image) * rename: Dockerfile.openab-agent → Dockerfile.native * rename: remove old Dockerfile.openab-agent * docs: add native-agent.md * docs(README): add Native Agent to Other Agents table * docs(native-agent): clarify AGENTS.md support, note Skills not yet supported * docs(native-agent): note MCP not yet supported * docs(native-agent): note MCP not yet supported * style: cargo fmt * style: cargo fmt * style: cargo fmt * style: cargo fmt * fix: resolve clippy warnings (dead_code, is_multiple_of) --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com> Co-authored-by: thepagent <hehsieh1010@gmail.com>19 小时前
feat: pivot xai-proxy → openab-auth-proxy (generic OAuth sidecar) (#891) * feat: rename xai-proxy → openab-auth-proxy, make provider-generic BREAKING: xai-proxy binary renamed to openab-auth-proxy. - Extract xAI-specific OAuth values into a TOML config file - Default to xAI preset when no config is provided (backward compat) - Support any OIDC provider via auth-proxy.toml - Add AUTH_PROXY_TOKEN_PATH env var (XAI_PROXY_TOKEN_PATH still works) - Token storage moved to ~/.openab-auth-proxy/<provider>/tokens.json - Update CI workflow, Dockerfile, README, and docs - Add docs/refarch/sidecar-proxy.md for the generic pattern * fix(auth-proxy): remove needless borrow to satisfy clippy --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>4 天前
docs(operator): add README and sample manifest (#852) Co-authored-by: Kiro <kiro@openab.dev>8 天前
fix: prefer global_name over username for display_name fallback (#934) Co-authored-by: Jelli Bot <jelli-bot@openab.dev>25 分钟前
chore: ignore .claude/ and .claude.local.md (#837) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>5 天前
feat(pi): support Pi coding agent via Dockerfile.pi (#920) * feat(pi): support Pi coding agent via Dockerfile.pi * fix(pi): install git in Dockerfile.pi * chore: fix CI matrices and Dockerfile count * docs(pi): remove standalone Pi guide * chore: remove redundant Anthropic API key env from config-reference.md * chore: correct Helm NOTES.txt instructions for Pi agent authentication * docs(pi): add docs/pi.md with advantages over other native coding agents - No auth proxy required (native subscription support like Codex/Copilot) - Minimal tool surface (4 tools) maximizes context window - Multi-model support (15+ providers, switchable mid-session) - Branching session trees for code exploration * docs(pi): add Pi agent to README.md --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com> Co-authored-by: 小喬 <xiaoqiao@openab.internal>1 天前
docs: add PR lifecycle flow to CONTRIBUTING.md (#912) * docs: add PR lifecycle flow to CONTRIBUTING.md * docs: fix box alignment and split label transition table rows * docs: note immediate closing-soon for missing Discord URL * docs: align stale to 2 days, clarify re-check may re-apply closing-soon * docs: rewrite lifecycle diagram with checks-first flow and re-check loop * docs: clarify maintainer flips to pending-contributor when pending actions exist * docs: add LGTM/approve/merge path from pending-maintainer --------- Co-authored-by: chaodu-agent[bot] <chaodu-agent[bot]@users.noreply.github.com>3 天前
feat(cron): goal-driven auto-disable usercron jobs (implements #816) (#818) * feat(cron): auto-disable usercron jobs on success * fix(cron): atomic write, kill child on timeout, add timeout test - update_usercron_job: write to .toml.tmp then rename (atomic on POSIX) - check_disable_on_success: use spawn() + wait_with_output() to retain child handle; explicitly kill on timeout to prevent orphan processes - Add disable_on_success_kills_child_on_timeout test (sleep 999 + 1s timeout) * fix(cron): remove unused timeout import * fix(cron): serialize usercron writebacks * docs: add re-enable instructions for goal-driven cronjobs --------- Co-authored-by: chaodufashi <chaodu-agent@users.noreply.github.com> Co-authored-by: 超渡法師 <chaodu@openab.dev>5 天前
release: v0.8.4-beta.1 (#893) Co-authored-by: openab-app[bot] <274185012+openab-app[bot]@users.noreply.github.com>5 天前
docs: add The Design of OpenAB (#735) * docs: add The Design of OpenAB * docs: move to DESIGN.md at repo root * docs: sandbox is the only option, no escape --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>21 天前
chore: bump all coding CLI versions to latest (#888) - kiro-cli: 2.2.0 → 2.4.0 - claude-code: 2.1.124 → 2.1.146 (+ add bubblewrap/socat for sandbox) - codex: 0.128.0 → 0.133.0 - copilot: 1.0.40 → 1.0.51 - cursor: 2026.04.30-4edb302 → 2026.05.20-2b5dd59 - gemini-cli: 0.40.1 → 0.42.0 - opencode-ai: 1.14.31 → 1.15.7 Claude Code v2.1.144+ requires bubblewrap and socat for its sandbox on Linux. Without them the CLI silently exits (anthropics/claude-code#61094). Added both packages to Dockerfile.claude apt-get layer. Co-authored-by: 張飛 (Zhang Fei) <zhangfei@openab.dev>5 天前
feat: add agy-acp adapter for Google Antigravity CLI (#896) Add a thin Rust ACP stdio adapter (agy-acp) that translates openab's JSON-RPC protocol into `agy -p` invocations, enabling Antigravity CLI as an agent backend. - agy-acp/: standalone Rust crate, reads ACP JSON-RPC on stdin, spawns `agy -p "prompt"` for each session/prompt, uses --continue for multi-turn session continuity - Dockerfile.antigravity: multi-stage build bundling openab + agy-acp + agy binary from Google Storage - docs/antigravity.md: configuration and usage guide Tested end-to-end locally with Discord (周嘟嘟 bot) — ~5s response time. Closes #863 Co-authored-by: Pahud Hsieh <pahud@Pahuds-MacBook-Neo.local>5 天前
chore: bump all coding CLI versions to latest (#888) - kiro-cli: 2.2.0 → 2.4.0 - claude-code: 2.1.124 → 2.1.146 (+ add bubblewrap/socat for sandbox) - codex: 0.128.0 → 0.133.0 - copilot: 1.0.40 → 1.0.51 - cursor: 2026.04.30-4edb302 → 2026.05.20-2b5dd59 - gemini-cli: 0.40.1 → 0.42.0 - opencode-ai: 1.14.31 → 1.15.7 Claude Code v2.1.144+ requires bubblewrap and socat for its sandbox on Linux. Without them the CLI silently exits (anthropics/claude-code#61094). Added both packages to Dockerfile.claude apt-get layer. Co-authored-by: 張飛 (Zhang Fei) <zhangfei@openab.dev>5 天前
docs(codex): troubleshoot bubblewrap unavailable in sandboxed runtimes (#917) * docs(codex): add troubleshooting for bubblewrap unavailable in sandboxed runtimes When Codex runs inside an already-isolated OpenAB runtime without bubblewrap installed, its inner sandbox fails with 'bubblewrap is unavailable'. Document both resolution options: installing bwrap or disabling the inner sandbox. Closes #908 * docs(codex): add non-privileged container reminder to sandbox note * docs(codex): remove Dockerfile option, we provide the images * fix(codex): install bubblewrap in Dockerfile.codex Aligns with Dockerfile.claude which already includes bubblewrap. This resolves the 'bubblewrap is unavailable' error at runtime. --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>3 天前
chore: bump all coding CLI versions to latest (#888) - kiro-cli: 2.2.0 → 2.4.0 - claude-code: 2.1.124 → 2.1.146 (+ add bubblewrap/socat for sandbox) - codex: 0.128.0 → 0.133.0 - copilot: 1.0.40 → 1.0.51 - cursor: 2026.04.30-4edb302 → 2026.05.20-2b5dd59 - gemini-cli: 0.40.1 → 0.42.0 - opencode-ai: 1.14.31 → 1.15.7 Claude Code v2.1.144+ requires bubblewrap and socat for its sandbox on Linux. Without them the CLI silently exits (anthropics/claude-code#61094). Added both packages to Dockerfile.claude apt-get layer. Co-authored-by: 張飛 (Zhang Fei) <zhangfei@openab.dev>5 天前
chore: bump all coding CLI versions to latest (#888) - kiro-cli: 2.2.0 → 2.4.0 - claude-code: 2.1.124 → 2.1.146 (+ add bubblewrap/socat for sandbox) - codex: 0.128.0 → 0.133.0 - copilot: 1.0.40 → 1.0.51 - cursor: 2026.04.30-4edb302 → 2026.05.20-2b5dd59 - gemini-cli: 0.40.1 → 0.42.0 - opencode-ai: 1.14.31 → 1.15.7 Claude Code v2.1.144+ requires bubblewrap and socat for its sandbox on Linux. Without them the CLI silently exits (anthropics/claude-code#61094). Added both packages to Dockerfile.claude apt-get layer. Co-authored-by: 張飛 (Zhang Fei) <zhangfei@openab.dev>5 天前
chore: bump all coding CLI versions to latest (#888) - kiro-cli: 2.2.0 → 2.4.0 - claude-code: 2.1.124 → 2.1.146 (+ add bubblewrap/socat for sandbox) - codex: 0.128.0 → 0.133.0 - copilot: 1.0.40 → 1.0.51 - cursor: 2026.04.30-4edb302 → 2026.05.20-2b5dd59 - gemini-cli: 0.40.1 → 0.42.0 - opencode-ai: 1.14.31 → 1.15.7 Claude Code v2.1.144+ requires bubblewrap and socat for its sandbox on Linux. Without them the CLI silently exits (anthropics/claude-code#61094). Added both packages to Dockerfile.claude apt-get layer. Co-authored-by: 張飛 (Zhang Fei) <zhangfei@openab.dev>5 天前
feat: add Grok Build CLI as supported agent (#831) * feat: add Grok Build (xAI) as agent provider Add xAI's official Grok Build CLI as a supported agent provider via its native ACP entry (`grok agent stdio`) — no wrapper required. Files added: - Dockerfile.grok: runtime image with pinned grok 0.1.211 binary (SHA256-verified, sourced from xAI's public artifacts bucket) - docs/grok.md: setup guide covering Docker build, Helm install, three auth options (API key / device-code / deployment key), credential persistence, and a comparison with Dockerfile.hermes - config.toml.example: agent example placed next to the hermes one - .github/workflows/build.yml: grok variant added to build-image, merge-manifests, and promote-stable matrices so the ghcr.io/openabdev/openab-grok image is published alongside other agent variants Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: add grok variant to docker-smoke-test matrix Mirrors the other agent variants so CI builds the Dockerfile.grok image and verifies that `grok agent stdio` answers the ACP initialize handshake (falling back to `grok --help` when auth is missing, same as other agents). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(helm): add grok agent example to values.yaml and NOTES.txt * docs(helm): recommend API key for grok bot deployments in NOTES.txt Add guidance for bot/CI users to prefer GROK_CODE_XAI_API_KEY via secretEnv instead of interactive device-auth login. * fix(docker): remove unused /usr/local/bin/agent symlink in Dockerfile.grok The symlink is not referenced by OpenAB, Helm, or CI and may cause confusion in multi-agent environments. * docs(readme): add Grok Build to supported agents list --------- Co-authored-by: Can <can@zeabur.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>10 天前
feat: add Hermes Agent as agent provider (#824) * feat: add Hermes Agent as agent provider Add Hermes Agent (NousResearch) as a supported agent provider, enabling OAB to leverage Hermes's multi-provider OAuth infrastructure via ACP. Key benefits: - xAI Grok OAuth (SuperGrok $30/mo flat rate vs pay-per-token) - 30+ providers accessible through one agent - OAuth token lifecycle managed by Hermes (zero auth complexity for OAB) - Multi-modal support (TTS, image gen, video gen) via same OAuth token - Built-in fallback chains for provider resilience Files added: - Dockerfile.hermes: runtime image with Hermes Agent installed - docs/hermes.md: setup guide with auth and provider switching docs - config.toml.example: added Hermes agent config example Closes #823 * fix: pin install script, correct ACP invocation, add credential persistence docs - Dockerfile.hermes: pin install script to commit cc07e30f with SHA256 checksum verification instead of curl-pipe-bash from main - docs/hermes.md & config.toml.example: correct command from 'hermes --acp --stdio' to 'hermes-acp' (verified upstream) - docs/hermes.md: add PVC/volume mount guidance for credential persistence Addresses review findings from PR #824. * ci: add hermes variant to build & release matrix Adds Dockerfile.hermes to the build-image, merge-manifests, and promote-stable matrices so the ghcr.io/openabdev/openab-hermes image is published by CI alongside other agent variants. * fix: Dockerfile user/permission ordering and missing deps - Create agent user before WORKDIR so /home/agent has correct ownership - Set HERMES_HOME=/home/agent/.hermes during install so OAuth tokens are stored in agent user's home (not /root/.hermes) - Add ffmpeg for Hermes multi-modal support - chown /home/agent after all root operations complete Addresses review findings from 覺渡法師. * ci: add hermes to smoke-test matrix; clarify persistence docs - docker-smoke-test.yml: add Dockerfile.hermes variant - docs/hermes.md: clarify that Helm chart persistence covers .hermes by default; manual PVC only needed for non-Helm deploys * ci: add hermes to pr-preview variant choices * docs(chart): add hermes agent example to values.yaml The chart is generic over agents.<name>, so hermes already works, but adding a commented example makes discoverability easier and aligns with the docs/hermes.md Helm install instructions. * fix: add xz-utils for Node.js tar.xz extraction in hermes install * fix: symlink hermes-acp to /usr/local/bin for PATH visibility FHS root install only links 'hermes' to /usr/local/bin, but 'hermes-acp' stays in the venv. Add explicit symlink. * fix: recreate venv with system Python to avoid uv-managed path issues uv installs its own Python 3.11 at /root/.local/share/uv/python/ which is inaccessible to the agent user. Recreate venv with the image's system Python 3.12 after install script completes. * fix(docker): chmod uv-managed Python for non-root agent user The hermes install script uses uv which places Python 3.11 under /root/.local/share/uv/. The container runs as non-root user 'agent', causing 'Permission denied' when the venv tries to resolve its Python interpreter. Fix: chmod the uv directory and parent paths to be world-readable/executable. Also symlink hermes-acp to /usr/local/bin for PATH accessibility. Tested and verified working on orbstack with xai-oauth + grok-4.3. * docs(hermes): add xAI OAuth auth guide with port-forward for K8s pods * docs(hermes): emphasize SuperGrok paid subscription requirement * docs: add Hermes Agent to README table and config-reference * docs(readme): add Hermes to architecture diagram and feature list * docs(readme): fix diagram alignment --------- Co-authored-by: 張飛 <zhangfei@openab.dev> Co-authored-by: chaodufashi <chaodu-agent@users.noreply.github.com> Co-authored-by: thepagent <thepagent@users.noreply.github.com>11 天前
fix(Dockerfile.native): build openab-agent from its own crate directory (#931)18 小时前
chore: bump all coding CLI versions to latest (#888) - kiro-cli: 2.2.0 → 2.4.0 - claude-code: 2.1.124 → 2.1.146 (+ add bubblewrap/socat for sandbox) - codex: 0.128.0 → 0.133.0 - copilot: 1.0.40 → 1.0.51 - cursor: 2026.04.30-4edb302 → 2026.05.20-2b5dd59 - gemini-cli: 0.40.1 → 0.42.0 - opencode-ai: 1.14.31 → 1.15.7 Claude Code v2.1.144+ requires bubblewrap and socat for its sandbox on Linux. Without them the CLI silently exits (anthropics/claude-code#61094). Added both packages to Dockerfile.claude apt-get layer. Co-authored-by: 張飛 (Zhang Fei) <zhangfei@openab.dev>5 天前
fix(pi): bump pi-coding-agent to 0.75.5 (#923)1 天前
docs(license): add MIT LICENSE file 1 个月前
feat: openab-agent — native Rust coding agent with subscription auth (#924) * feat: openab-agent v0.1 — native Rust coding agent with ACP Implements the v0.1 scope from ADR (PR #922): - ACP layer: stdin/stdout JSON-RPC (initialize, session/new, session/prompt, session/cancel) - LLM client: Anthropic provider with non-streaming API (BoxStream deferred to v0.2) - 4 tools: read, write, edit, bash - Path traversal protection (canonicalize + boundary check) - Environment variable filtering (allow-list only) - Process group kill on timeout (setsid + kill(-pgid)) - Agent core: system prompt + tool dispatch loop (max 50 iterations) - Unit tests: hand-written MockLlmProvider, tests for prompt assembly, tool dispatch, error handling, and multi-step tool chains - Flat session (session tree deferred to v0.2) Architecture: openab ──stdio JSON-RPC──► openab-agent ──HTTP──► Anthropic API No external runtime required. Single binary, ~20MB when compiled. * fix: address review findings from 覺渡 (PR #924) - Fix validate_path: remove create_dir_all side-effect that could create directories outside working_dir before boundary check. Now uses parent traversal to find nearest existing ancestor without modifying filesystem. - Fix unit test isolation: mark all FS/process tests with #[ignore] per Unit Test Strategy ADR. Only pure logic tests run by default. - Fix unsafe setsid: check return value, propagate error on failure. - Fix OPENAB_AGENT_BASH_ENV_ALLOW: read comma-separated env var and pass allowed keys to build_env for subprocess inheritance. - Fix streaming capability: set to false in ACP initialize response since v0.1 uses non-streaming Anthropic Messages API. * fix: address review findings from 普渡 (PR #924) - 🔴 F1: Add context window truncation (MAX_CONTEXT_MESSAGES=100), drops oldest messages preserving first user prompt - 🟡 F3: Return error when MAX_TOOL_LOOPS exhausted instead of empty string - 🟡 F5: Fail-fast on missing/empty ANTHROPIC_API_KEY at session creation - 🟡 F6: Add retry with exponential backoff for 429/529 (max 3 retries) - 🟡 F7: Await child process after SIGKILL to prevent zombies - 🟡 F8: Add TODO(v0.2) for session/cancel implementation - 🟡 F9: Validate empty prompt, return -32602 error - 🟡 F10: Add TODO(v0.2) for session TTL/cleanup - 🟡 F11: Remove std::env::set_var from tests (UB in multi-thread) * fix: truncate_context pair-drain + test_session_new CI fix - N1: truncate_context now drains in pairs (assistant+user) to maintain strict role alternation required by Anthropic API - N2: test_session_new sets fake ANTHROPIC_API_KEY for CI environments; added test_session_new_missing_key for error case * feat: add subscription auth via OAuth device flow Add support for Codex/OpenAI subscription authentication: CLI: openab-agent auth codex-oauth # device flow login openab-agent auth status # show stored credentials openab-agent # ACP mode (default) Auth flow: - Device code flow against OpenAI auth endpoints - Prints verification URL + user code for headless environments - Polls until user authorizes in browser - Stores tokens at ~/.openab/agent/auth.json (0600 perms) - Auto-refreshes expired tokens with 120s skew Provider fallback in ACP mode: 1. ANTHROPIC_API_KEY env var → Anthropic provider 2. ~/.openab/agent/auth.json → OpenAI provider (subscription) 3. Error with instructions if neither available OpenAI provider: - Full OpenAI chat completions API format - Tool call translation (Anthropic format ↔ OpenAI format) - Retry with exponential backoff on 429/529 * fix: address auth review findings from 覺渡 - 🔴 save_tokens permission race: use OpenOptions::mode(0o600) to create file with correct permissions atomically (no window for exposure) - 🔴 OPENAB_AGENT_PROVIDER ignored: respect env var to force provider selection (anthropic|openai|codex), auto-detect only when unset - 🟡 Token masking: safe display for any token length (>12 chars shows first 8 + last 4, otherwise shows ****) * fix: address 普渡 findings F2-F8 (auth + OpenAI provider) - F2: Add OPENAB_AGENT_OPENAI_MODEL + OPENAB_AGENT_OPENAI_BASE_URL env vars so OpenAI and Anthropic model namespaces don't conflict - F3: Increase poll interval on 'slow_down' per RFC 8628 Section 3.5 - F4: Add 10-minute wall-clock timeout to device flow polling loop - F5: Enforce minimum 5s polling interval regardless of server response - F6: Retry on 401 with token refresh; fetch fresh token each attempt - F8: Token masking already fixed in previous commit F1 (client_id) and F9 (scope) pending 主人 decision. * fix: make OAuth client_id configurable (F1) Default: 'app_scp_codex_prod_001' (same as Codex CLI, public client) Override: OPENAB_AGENT_OAUTH_CLIENT_ID env var This allows users to register their own OAuth app if needed, while maintaining compatibility with existing Codex subscriptions by default. * fix: address remaining 普渡 findings F6-F8 - F6: Add force_refresh() that bypasses expiry check; 401 handler now calls force_refresh() to guarantee a new token on next retry - F7: Add unit tests for parse_openai_response (text, tool_call, empty) and auth module (is_expired, auth_path, codex_client_id) - F8: Token masking confirmed already fixed (len>12 check at line 244) * ci: add CI workflow + Dockerfile for openab-agent CI (.github/workflows/ci-openab-agent.yml): - cargo fmt --check - cargo clippy -- -D warnings - cargo test (unit tests) - cargo test -- --ignored (integration tests) Dockerfile (Dockerfile.openab-agent): - Multi-stage build: rust:1-bookworm → distroless/cc-debian12 - Final image ~20MB, runs as nonroot - Entrypoint: openab-agent (ACP mode by default) * fix: CI compilation errors - Fix borrow-after-move: capture child pid before wait_with_output - Fix unused import: restructure cfg(unix) block for pre_exec - Fix unused variable: remove dead content Vec in OpenAiProvider - Fix extra closing brace * fix: resolve all clippy warnings - Remove unused imports (anyhow::Result, serde_json::Value, Path) - Mark Agent::new as #[cfg(test)] (only used in tests) - Allow dead_code on LlmEvent::Error variant (reserved for future use) - Move CommandExt import to top-level #[cfg(unix)] - Remove unnecessary mut on child variable - Collapse if-in-match per clippy suggestion * fix: CI errors — cannot move in pattern guard + unused import - Revert collapsed match (cannot move l in guard), add clippy allow - Move CommandExt import inside unsafe block with allow(unused_imports) * fix(openab-agent): correct device code auth flow for OpenAI - Use https://auth.openai.com/api/accounts/deviceauth/usercode endpoint - Use server-provided code_verifier (not client PKCE) - Token exchange at /oauth/token with redirect_uri=https://auth.openai.com/deviceauth/callback - Handle OpenAI's nested error format (error.code) - Correct client_id: app_EMoamEEZ73f0CkXaXp7hrann * refactor(openab-agent): remove unused PKCE deps (base64, sha2, getrandom) * refactor(openab-agent): remove unused PKCE deps from Cargo.toml * ci: add ACP smoke test — verify binary starts and speaks ACP Sends an 'initialize' JSON-RPC request to the built binary and verifies the response contains valid ACP agentInfo. This catches protocol-level regressions without needing LLM credentials. * style: cargo fmt * fix: remove unused constants (CODEX_SCOPES, CODEX_AUDIENCE) * feat(openab-agent): browser PKCE + device code auth flows * feat(openab-agent): switch to Responses API (chatgpt.com/backend-api/codex/responses) * feat(openab-agent): add codex-device subcommand + --no-browser flag * fix(openab-agent): test cleanup for OAuth auth * feat(openab-agent): add deps for browser PKCE flow (base64, sha2, getrandom, urlencoding, open, url) * docs(openab-agent): guide headless users through copy-paste callback flow * feat(openab-agent): paste-based callback for headless auth + simplified flow params * fix(openab-agent): stop tool loop when text response received * feat(openab-agent): Responses API with SSE stream parsing * fix(openab-agent): correct Responses API input format for tool results (function_call_output) * feat(openab-agent): read AGENTS.md from cwd as custom system prompt * feat: add Dockerfile.openab-agent — native Rust agent (~20MB image) * rename: Dockerfile.openab-agent → Dockerfile.native * rename: remove old Dockerfile.openab-agent * docs: add native-agent.md * docs(README): add Native Agent to Other Agents table * docs(native-agent): clarify AGENTS.md support, note Skills not yet supported * docs(native-agent): note MCP not yet supported * docs(native-agent): note MCP not yet supported * style: cargo fmt * style: cargo fmt * style: cargo fmt * style: cargo fmt * fix: resolve clippy warnings (dead_code, is_multiple_of) --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com> Co-authored-by: thepagent <hehsieh1010@gmail.com>19 小时前
feat: add Cursor Agent CLI support Add Cursor Agent CLI as a new agent backend using native ACP support (`cursor-agent acp`). Includes Dockerfile with pinned version download, CI matrix entries, Helm chart config, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 1 个月前
docs(config): fix claude examples to use claude-agent-acp (#892) * docs(config): fix claude examples to use claude-agent-acp Both config.toml.example and docs/config-reference.md used `command = "claude"` with `args = ["--acp"]`, but the Claude Code CLI has no --acp flag. ACP support is provided by the separate @agentclientprotocol/claude-agent-acp npm package. Update both files to match docs/claude-code.md: - command = "claude-agent-acp" - args = [] - env = { CLAUDE_CODE_OAUTH_TOKEN } (OAuth-first, per project recommendation) Fixes #632 * docs(config): use neutral env example * docs(config): address review feedback on claude auth examples - Fix install hint to include both required packages: @anthropic-ai/claude-code and @agentclientprotocol/claude-agent-acp - Remove CLAUDE_CODE_OAUTH_TOKEN env var example; replace with claude auth login + PVC comment per docs/claude-code.md - Remove misleading 'or set CLAUDE_CODE_OAUTH_TOKEN' phrasing - Update command field example: claude -> claude-agent-acp Fixes findings from chaodu-agent, howie, canyugs review. * docs(config): remove npm install hint — adapter is baked into container image --------- Co-authored-by: feiyun968-agent <feiyun968-agent@users.noreply.github.com> Co-authored-by: shaun-agent <shaun-agent@users.noreply.github.com> Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>5 天前

OpenAB — Open Agent Broker

Stars GitHub Release License

OpenAB banner

A lightweight, secure, cloud-native ACP harness that bridges Discord, Slack, and any Agent Client Protocol-compatible coding CLI (Kiro CLI, Claude Code, Codex, Gemini, OpenCode, Copilot CLI, Hermes, Grok Build, Antigravity, Pi, etc.) over stdio JSON-RPC — delivering the next-generation development experience. Telegram, LINE, Feishu/Lark, Google Chat, and other webhook-based platforms are supported via the standalone Custom Gateway.

🪼 Join our community! Come say hi on Discord — we'd love to have you: 🪼 OpenAB — Official 🎉

┌──────────────┐  Gateway WS   ┌──────────────┐  ACP stdio    ┌──────────────────┐
│   Discord    │◄─────────────►│              │──────────────►│   coding CLI     │
│   User       │               │    openab    │◄── JSON-RPC ──│   (acp mode)     │
├──────────────┤  Socket Mode  │    (Rust)    │               ├──────────────────┤
│   Slack      │◄─────────────►│              │               │ kiro-cli acp     │
│   User       │               └──────┬───────┘               │ claude-agent-acp │
├──────────────┤                      │  WebSocket            │ codex-acp        │
│   Telegram   │◄──webhook──┐         │   (outbound)          │ gemini --acp     │
│   User       │            │         │                       │ copilot --acp    │
├──────────────┤            ▼         ▼                       │ hermes-acp       │
│   LINE       │◄──webhook──┌──────────────────┐              │ opencode acp     │
│   User       │            │  Custom Gateway  │              │ grok agent stdio │
├──────────────┤            │  (standalone)    │              │ agy-acp          │
│  Feishu/Lark │◄───WS──────│                  │              │ pi-acp           │
│   User       │            │                  │              └──────────────────┘
├──────────────┤            │                  │
│ Google Chat  │◄──webhook──│                  │
│   User       │            └──────────────────┘
└──────────────┘

Demo

openab demo

Features

  • Multi-platform — supports Discord and Slack, run one or both simultaneously
  • Custom Gateway — extend to Telegram, LINE, Feishu/Lark, Google Chat, MS Teams via standalone gateway
  • Pluggable agent backend — swap between Kiro CLI, Claude Code, Codex, Gemini, OpenCode, Copilot CLI, Hermes, Grok Build, Antigravity, Pi 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
  • Multi-agent collaboration — bot-to-bot messaging for coordinated workflows (docs/multi-agent.md)
  • Agent-controlled reply-to — agents choose which message to reply to via [[reply_to:id]] directive, enabling clear conversation threads in multi-bot channels (docs/output-directives.md)
  • Edit-streaming — live-updates the Discord message every 1.5s as tokens arrive
  • Emoji status reactions — 👀→🤔→🔥/👨‍💻/⚡→👍+random mood face
  • Image & file support — send images and files through chat (docs/sendimages.md, docs/sendfiles.md)
  • Scheduled messages — config-driven cron jobs for automated agent prompts (docs/cronjob.md)
  • Slash commands — built-in slash command support (docs/slash-commands.md)
  • Session pool — one CLI process per thread, auto-managed lifecycle
  • ACP protocol — JSON-RPC over stdio with tool call, thinking, and permission auto-reply support
  • Kubernetes-ready — Dockerfile + k8s manifests with PVC for auth persistence
  • Voice message STT — auto-transcribes Discord voice messages via Groq, OpenAI, or local Whisper server (docs/stt.md)

Quick Start

Prerequisites

Before running openab, enable these in the Discord Developer Portal:

  1. Bot → Privileged Gateway Intents:
    • ✅ Message Content Intent
    • ✅ Server Members Intent
  2. OAuth2 → URL Generator → Bot Permissions:
    • Send Messages, Embed Links, Attach Files
    • Read Message History, Add Reactions

See docs/discord.md for a detailed step-by-step guide.

1. Create a Bot

Discord

See docs/discord.md for a detailed step-by-step guide.

Slack

See docs/slack-bot-howto.md for a detailed step-by-step guide.

Telegram (via Custom Gateway)

See docs/telegram.md for the full setup guide. Requires the standalone Custom Gateway service.

LINE (via Custom Gateway)

See docs/line.md for the full setup guide. Requires the standalone Custom Gateway service.

Feishu/Lark (via Custom Gateway)

See docs/feishu.md for the full setup guide. Requires the standalone Custom Gateway service. Supports WebSocket long-connection (default, no public URL needed) and HTTP webhook fallback.

Google Chat (via Custom Gateway)

See docs/google-chat.md for the full setup guide. Requires the standalone Custom Gateway service.

WeCom (企业微信) (via Custom Gateway)

See docs/wecom.md for the full setup guide. Requires the standalone Custom Gateway service.

2. Install with Helm (Kiro CLI — default)

helm repo add openab https://openabdev.github.io/openab
helm repo update

helm install openab openab/openab \
  --set agents.kiro.discord.botToken="$DISCORD_BOT_TOKEN" \
  --set-string 'agents.kiro.discord.allowedChannels[0]=YOUR_CHANNEL_ID'

# Slack
helm install openab openab/openab \
  --set agents.kiro.slack.enabled=true \
  --set agents.kiro.slack.botToken="$SLACK_BOT_TOKEN" \
  --set agents.kiro.slack.appToken="$SLACK_APP_TOKEN" \
  --set-string 'agents.kiro.slack.allowedChannels[0]=C0123456789'

For additional Helm values such as fullnameOverride, nameOverride, envFrom, and agentsMd, see charts/openab/README.md.

3. Authenticate (first time only)

kubectl exec -it deployment/openab-kiro -- kiro-cli login --use-device-flow
kubectl rollout restart deployment/openab-kiro

4. Use

In your Discord channel:

@YourBot explain this code

The bot creates a thread. After that, just type in the thread — no @mention needed.

Slack: @YourBot explain this code in a channel — same thread-based workflow as Discord.

Other Agents

Agent CLI ACP Adapter Guide
Kiro (default) kiro-cli acp Native docs/kiro.md
Claude Code claude-agent-acp @agentclientprotocol/claude-agent-acp docs/claude-code.md
Codex codex-acp @zed-industries/codex-acp docs/codex.md
Gemini gemini --acp Native docs/gemini.md
OpenCode opencode acp Native docs/opencode.md
Copilot CLI ⚠️ copilot --acp --stdio Native docs/copilot.md
Cursor cursor-agent acp Native docs/cursor.md
Hermes Agent hermes-acp Native docs/hermes.md
Grok Build grok agent stdio Native docs/grok.md
Antigravity agy-acp agy-acp docs/antigravity.md
Pi pi-acp pi-acp docs/pi.md
Native Agent openab-agent Built-in (Rust) docs/native-agent.md

🔧 Running multiple agents? See docs/multi-agent.md

Configuration Reference

📖 Full reference with all options, defaults, and Helm mapping: docs/config-reference.md

[discord]
bot_token = "${DISCORD_BOT_TOKEN}"   # supports env var expansion
allowed_channels = ["123456789"]      # channel ID allowlist
# allowed_users = ["987654321"]       # user ID allowlist (empty = all users)

[slack]
bot_token = "${SLACK_BOT_TOKEN}"     # Bot User OAuth Token (xoxb-...)
app_token = "${SLACK_APP_TOKEN}"     # App-Level Token (xapp-...) for Socket Mode
allowed_channels = ["C0123456789"]   # channel ID allowlist (empty = allow all)
# allowed_users = ["U0123456789"]    # user ID allowlist (empty = allow all)

[agent]
command = "kiro-cli"                  # CLI command
args = ["acp", "--trust-all-tools"]   # ACP mode args
working_dir = "/tmp"                  # agent working directory
env = {}                              # extra env vars passed to the agent

[pool]
max_sessions = 10                     # max concurrent sessions
session_ttl_hours = 24                # idle session TTL

[reactions]
enabled = true                        # enable emoji status reactions
remove_after_reply = false            # remove reactions after reply

Kubernetes Deployment

The Docker image bundles both openab and kiro-cli in a single container.

┌─ Kubernetes Pod ──────────────────────────────────────┐
│  openab (PID 1)                                       │
│    └─ kiro-cli acp --trust-all-tools (child process)  │
│       ├─ stdin  ◄── JSON-RPC requests                 │
│       └─ stdout ──► JSON-RPC responses                │
│                                                       │
│  PVC (/data)                                          │
│    ├─ ~/.kiro/                  (settings, sessions)  │
│    └─ ~/.local/share/kiro-cli/  (OAuth tokens)        │
└───────────────────────────────────────────────────────┘

Deploy without Helm

kubectl create secret generic openab-secret \
  --from-literal=discord-bot-token="your-token"

kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/pvc.yaml
kubectl apply -f k8s/deployment.yaml
Manifest Purpose
k8s/deployment.yaml Single-container pod with config + data volume mounts
k8s/configmap.yaml config.toml mounted at /etc/openab/
k8s/secret.yaml DISCORD_BOT_TOKEN injected as env var
k8s/pvc.yaml Persistent storage for auth + settings

Inspired By

License

MIT

项目介绍

A lightweight, secure, cloud-native ACP harness that bridges Discord and any ACP-compatible coding CLI.

定制我的领域

下载使用量

0

项目总下载次数(含Clone、Pull、 zip 包及 release 下载),每日凌晨更新

语言类型

Rust99.14%
Smarty0.53%
Dockerfile0.26%
Shell0.07%