Skip to content

feat(worker/acp): implement universal ACP Worker for HotPlex #569

@hrygo

Description

@hrygo

Summary

Implement a universal ACP (Agent Client Protocol) Worker that enables HotPlex to connect with any ACP-compatible agent via stdio (JSON-RPC 2.0). Hermes Agent is the first pilot implementation.

Design spec: docs/specs/ACP-Worker-Spec.md

Motivation

HotPlex currently supports 3 Workers (ClaudeCode / CodexCLI / OpenCodeServer), each with a private protocol. Adding a new agent requires writing a complete Worker from scratch. ACP is an open protocol adopted by Claude Code, Codex CLI, OpenCode, Hermes, and more — one generic Worker serves all.

Implementation Plan

P0 — MVP

  • AEP Protocol Extension (pkg/events/events.go)

    • Add 3 new Kind constants: ToolUpdate, Plan, ModeUpdate
    • Add 5 new Data structs: ToolUpdateData, PlanData, PlanItem, ModeUpdateData, FileLocation, FileDiff
    • Extend ToolCallData with Title, Kind, Status, Locations
    • Extend ToolResultData with Status, Diff
    • All new fields omitempty — zero breaking change
  • NDJSON Codec (internal/worker/acp/codec.go ~150 lines)

    • JSON-RPC 2.0 message types (Request/Response/Notification/Error)
    • NDJSON line read/write over stdio pipes
    • Message dispatch by id/method presence
  • ACP Client (internal/worker/acp/client.go ~300 lines)

    • InitializeNewSessionPrompt lifecycle
    • Pending response map with channel-based matching
    • Background read loop dispatching notifications
  • ACP ↔ AEP Mapper (internal/worker/acp/mapper.go ~350 lines)

    • MapNotification() converts session/update → AEP Envelopes
    • Synthetic events: message.start/message.end/state
    • Full mapping: agent_message_chunk, agent_thought_chunk, tool_call, tool_call_update, plan, current_mode_update, request_permission
    • Prompt Response → done with Stats
  • Worker Interface (internal/worker/acp/worker.go ~200 lines)

    • Embed base.BaseWorker
    • Start: proc.Start → Initialize → NewSession → readLoop
    • Input: construct session/prompt
    • Terminate: Cancel → SIGTERM → 5s → SIGKILL
    • Send: bridge permission_response back to ACP
  • Registration (internal/worker/acp/init.go ~20 lines)

    • worker.Register("acp", ...) in init()
  • Config (internal/config/config.go ~15 lines)

    • ACPConfig struct: Command, Args, AutoApprove, SessionStore

P1 — Important

  • Session restore via LoadSession
  • Permission request bridge (request_permissionpermission_request/response)
  • auto_approve config support
  • Usage stats complete mapping

P2 — Enhancements

  • SetSessionModel / SetSessionMode
  • Session fork / list
  • MCP server registration (session/new mcpServers param)

Estimated Effort

~1570 lines of Go across 8 new files. See spec §8 for breakdown.

Acceptance Criteria

  • AC-ACP-001 ~ AC-ACP-012 (see spec §10)
  • Hermes hermes-acp binary works end-to-end through HotPlex Gateway
  • Existing Workers (ClaudeCode/Codex/OCS) unaffected

Validation

See spec §11 for Hermes pilot validation plan.

Supersedes

  • Worker-ACPX-Spec.md (acpx CLI middleware approach)
  • AEP-ACP-Extension-Spec.md (consolidated into this spec)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/workerScope: Claude Code/OCS/Pi adapters, base workerenhancementFeature: new capabilities or improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions