Skip to content

[Feature]: Connect CodeBuddy Code via ACP protocol instead of -p headless mode #4464

Description

@studyzy

Deployment type

self-host

What do you want and why?

The CodeBuddy backend in server/pkg/agent/codebuddy.go currently drives the CodeBuddy CLI using Claude Code's private --output-format stream-json / -p headless protocol. This diverges from the ACP (Agent Client Protocol) standard already used by the kimi and hermes backends in the same package, forcing multica to maintain a parallel SDK JSON parsing layer (codebuddySDKMessage, handleAssistant, handleControlRequest, writeCodebuddyInput, etc.) and a separate code path for permission auto-approval, MCP config handling, and session resume.

CodeBuddy Code now natively supports ACP via codebuddy --acp (official docs: https://www.codebuddy.cn/docs/cli/acp and https://www.codebuddy.ai/docs/cli/acp). Switching to ACP would:

  • Unify the transport: reuse the existing hermesClient ACP transport (already proven by kimiBackend) instead of a backend-specific stream-json parser.
  • Reduce maintenance burden: delete ~250 lines of CodeBuddy-specific SDK types and handlers; permission approval, MCP config translation, stderr sniffing, and provider-error promotion all flow through the shared ACP helpers (buildACPMcpServers, filterACPMcpServersByCapability, newACPProviderErrorSniffer, promoteACPResultOnProviderError).
  • Unlock ACP-native features: tool proxy (fs.readTextFile/fs.writeTextFile/terminal), available_commands_update slash-command push, and the codebuddy.ai/teamUpdate Agent Teams extension — none of which the stream-json path exposes.
  • Standardize the session lifecycle: initializesession/new|resumesession/set_modelsession/prompt, matching how kimi/hermes already work. Model switching goes through session/set_model (single source of truth) rather than a root --model flag; resume goes through session/resume rather than --resume; MCP servers go through session/new.mcpServers rather than a temp file + --mcp-config.

Proposed solution

Rewrite codebuddyBackend.Execute to mirror kimiBackend:

  1. Launch codebuddy --acp (blocked-args collapses to {"--acp": blockedStandalone}).
  2. Instantiate hermesClient with onMessage calling a new codebuddyToolNameFromTitle (mirrors kimiToolNameFromTitle) to normalize CodeBuddy's capitalized ACP tool titles ("Read file: …" → read_file).
  3. Drive the standard ACP lifecycle: initializesession/new (or session/resume when ResumeSessionID is set, with the same stale-session-id fallback kimi/hermes use) → session/set_model when Model is set → session/prompt.
  4. Translate McpConfig via buildACPMcpServers + filterACPMcpServersByCapability.
  5. Sniff stderr via newACPProviderErrorSniffer("codebuddy") and promote upstream LLM errors via promoteACPResultOnProviderError.
  6. Keep the root-level --effort, --max-turns, and --append-system-prompt flags (CodeBuddy CLI root params coexist with --acp); drop -p, --output-format, --input-format, --permission-mode, --mcp-config, --disallowedTools, --verbose, --strict-mcp-config.

Open questions that need validation against a real codebuddy --acp runtime (cannot be answered from the docs alone):

  • Do --effort / --max-turns / --append-system-prompt take effect under --acp mode?
  • Does session/set_model accept modelId (same field name as kimi)?
  • Does session/new return models.availableModels?

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions