Skip to main content
The ACP adapter wraps Mibyan’ synchronous AIAgent in an async JSON-RPC stdio server. Key implementation files:
  • acp_adapter/entry.py
  • acp_adapter/server.py
  • acp_adapter/session.py
  • acp_adapter/events.py
  • acp_adapter/permissions.py
  • acp_adapter/tools.py
  • acp_adapter/auth.py

Boot flow

Stdout is reserved for ACP JSON-RPC transport. Human-readable logs go to stderr.

Major components

MibyanACPAgent

acp_adapter/server.py implements the ACP agent protocol. Responsibilities:
  • initialize / authenticate
  • new/load/resume/fork/list/cancel session methods
  • prompt execution
  • session model switching
  • wiring sync AIAgent callbacks into ACP async notifications

SessionManager

acp_adapter/session.py tracks live ACP sessions. Each session stores:
  • session_id
  • agent
  • cwd
  • model
  • history
  • cancel_event
The manager is thread-safe and supports:
  • create
  • get
  • remove
  • fork
  • list
  • cleanup
  • cwd updates

Event bridge

acp_adapter/events.py converts AIAgent callbacks into ACP session_update events. Bridged callbacks:
  • tool_progress_callback
  • thinking_callback (currently set to None in the ACP bridge — reasoning is forwarded through step_callback instead)
  • step_callback
Every ACP tool call reaches a terminal status: tool.completed closes the call with its own result (completed / failed), the step_callback prev_tools pass is only a fallback for runtimes that never project a completion, and anything still open when the turn ends — a denied or blocked call, an interrupted one — is marked failed before the response is returned. Because AIAgent runs in a worker thread while ACP I/O lives on the main event loop, the bridge uses:

Permission bridge

acp_adapter/permissions.py adapts dangerous terminal approval prompts into ACP permission requests. Mapping:
  • allow_once -> Mibyan once
  • allow_always -> Mibyan always
  • reject options -> Mibyan deny
Timeouts and bridge failures deny by default.

Tool rendering helpers

acp_adapter/tools.py maps Mibyan tools to ACP tool kinds and builds editor-facing content. Examples:
  • patch / write_file -> file diffs
  • terminal -> shell command text
  • read_file / search_files -> text previews
  • large results -> truncated text blocks for UI safety

Session lifecycle

A turn that ends in a terminal failure (provider refusal, non-retryable error, exhausted retries, interrupt before any reply) is closed by the core loop with a Mibyan-authored assistant row (“Your request was not processed…” / “This turn did not complete…”) so the durable transcript never ends on an open user row. Without it the next prompt would be merged into the failed request and replayed. Context-overflow failures are exempt: their repair is session rotation, not another row.

Cancelation

cancel(session_id):
  • sets the session cancel event
  • calls agent.interrupt() when available
  • causes the prompt response to return stop_reason="cancelled"

Forking

fork_session() deep-copies message history into a new live session, preserving conversation state while giving the fork its own session ID and cwd.

Provider/auth behavior

ACP does not implement its own auth store. Instead it reuses Mibyan’ runtime resolver:
  • acp_adapter/auth.py
  • mibyan_cli/runtime_provider.py
So ACP advertises and uses the currently configured Mibyan provider/credentials. It also always advertises a terminal setup auth method (mibyan-setup, args --setup) so first-run ACP clients can open Mibyan’ interactive model/provider configuration before starting a normal ACP session.

Working directory binding

ACP sessions carry an editor cwd. The session manager binds that cwd to the ACP session ID via task-scoped terminal/file overrides, so file and terminal tools operate relative to the editor workspace.

Duplicate same-name tool calls

The event bridge tracks tool IDs FIFO per tool name, not just one ID per name. This is important for:
  • parallel same-name calls
  • repeated same-name calls in one step
Without FIFO queues, completion events would attach to the wrong tool invocation.

Approval callback restoration

ACP temporarily installs an approval callback on the terminal tool during prompt execution, then restores the previous callback afterward. This avoids leaving ACP session-specific approval handlers installed globally forever.

Current limitations

  • ACP sessions are persisted to the shared ~/.mibyan/state.db (SessionDB) and transparently restored across process restarts; they appear in session_search
  • non-text prompt blocks are currently ignored for request text extraction
  • editor-specific UX varies by ACP client implementation
  • tests/acp_adapter/ — ACP test suite
  • toolsets.py — mibyan-acp toolset definition
  • mibyan_cli/main.py — mibyan acp CLI subcommand
  • pyproject.toml — [acp] optional dependency + mibyan-acp script