Skip to content

feat(adapters): multi-agent support via ACP preset registry#55

Merged
caoergou merged 2 commits into
mainfrom
claude/code-cli-tool-support-5txnzv
Jul 6, 2026
Merged

feat(adapters): multi-agent support via ACP preset registry#55
caoergou merged 2 commits into
mainfrom
claude/code-cli-tool-support-5txnzv

Conversation

@caoergou

@caoergou caoergou commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Implements phases 1–3 of #50: owloop now supports Claude Code, Codex, OpenCode, Qoder, Kimi, GLM, DeepSeek, Kiro (and Gemini/Qwen for free) through a single protocol-level integration.

Rebased onto #52 (Phase 1 trust & safety core): the ACP path composes cleanly with the new engine-owned verification gate — the agent signals DONE over ACP, then the engine runs the acceptance criteria itself and owns commit/push.

What changed

src/owloop/presets.py — agent preset registry (Phase 1)

  • AgentPreset dataclass: launch command, extra env (${VAR} references resolved from the user's environment at spawn time, {model} placeholder), worktree config dirs, experimental flag — per-tool knowledge is pure data, never code
  • 11 builtin presets; user-defined presets via .owloop/agents.toml (can also override builtins)

src/owloop/acp.py — one AcpAdapter for all non-native agents (Phase 2)

  • Minimal hand-rolled ACP client (JSON-RPC 2.0 over stdio): initializesession/newsession/prompt, one fresh process + session per iteration (preserves fresh-context-per-iteration)
  • Streams session/update into the existing on_line display conventions; usage_updateTokenTracker; stopReason decides success
  • Answers session/request_permission itself, preferring allow_once — agents are never launched in bypass/YOLO modes ("Auto Mode, not YOLO" now enforced by the harness, not just hoped for)
  • No new dependencies: the protocol subset a loop client needs is small, and the official SDK is asyncio/Pydantic-based while owloop's adapter interface is synchronous

Presets (Phase 3)

  • ACP: claude-acp, codex, opencode, qoder, kiro, gemini, qwen
  • glm / deepseek: their officially documented path is an Anthropic-compatible endpoint, so both ride the Claude ACP adapter with ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/model env — zero extra code (GLM: api.z.ai/api/anthropic, model glm-5.2; DeepSeek: api.deepseek.com/anthropic, model deepseek-v4-pro — deliberately not the deprecated deepseek-chat/deepseek-reasoner)
  • Presets not yet validated against the real agent are labeled experimental in owloop agents output

Wiring

Testing

  • tests/fake_acp_agent.py: scripted fake ACP agent run as a real subprocess — deterministic, no network. Scenarios: full happy turn, permission round-trip (the fake agent only emits DONE if the client selected the allow_once option, proving the auto-answer policy), refusal, hang → idle timeout, crash → stderr-tail diagnostics, missing binary, missing env var
  • tests/test_presets.py: registry coverage of all requested agents, env expansion, model placeholder, official endpoint/model assertions for GLM/DeepSeek, agents.toml load/override
  • 305 tests pass; ruff and mypy clean
  • Manual end-to-end (post-rebase): temp git repo + agents.toml custom preset + owloop run --agent faketool --no-tui -n 1 completes a full iteration — ACP streaming, DONE promise, engine verification gate passes, engine commits owloop: complete 01-demo.md, terminal state success

Closes #50 (phases 1–3; phase 4 — flipping claude/kimi defaults to ACP — deferred per the issue).

@caoergou caoergou force-pushed the claude/code-cli-tool-support-5txnzv branch from 2cb9df9 to e878edc Compare July 6, 2026 17:03
caoergou added 2 commits July 6, 2026 17:13
Integrate coding agents through two paths: the pre-existing native
stream-json adapters (claude, kimi) and one new AcpAdapter speaking the
Agent Client Protocol (JSON-RPC over stdio) for everything else.

- presets.py: AgentPreset registry — per-tool launch command, env, and
  worktree config dirs as pure data; user presets via .owloop/agents.toml;
  ${VAR} env expansion and {model} substitution
- acp.py: hand-rolled minimal ACP client (initialize → session/new →
  session/prompt), streams session/update into on_line, answers
  session/request_permission with allow_once (never bypass/YOLO modes),
  maps usage_update → TokenTracker and stopReason → AgentResult
- builtin presets: claude-acp, codex, opencode, qoder, kiro, gemini,
  qwen, plus glm/deepseek via their official Anthropic-compatible
  endpoints through the Claude ACP adapter
- get_adapter() resolves presets; --agent accepts any preset key; new
  'owloop agents' command lists presets with readiness status
- engine copies adapter-declared config dirs into worktrees
- tests: scripted fake ACP agent subprocess covering happy path,
  permission round-trip, refusal, hang/timeout, crash, missing binary/env

Closes #50 phases 1-3
tomllib only exists in the stdlib from 3.11; the CI matrix runs 3.10 on
ubuntu/macos where user-preset parsing raised RuntimeError. Depend on
tomli (the tomllib reference backport) for python_version < 3.11.
@caoergou caoergou force-pushed the claude/code-cli-tool-support-5txnzv branch from cb2d92c to ffcefbe Compare July 6, 2026 17:14
@caoergou caoergou merged commit 00e0307 into main Jul 6, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(adapters): multi-agent CLI support — ACP-first architecture covering Claude Code, Codex, OpenCode, Qoder, Kimi, GLM, DeepSeek, Kiro

1 participant