The Mjai Protocol Adapter layer serves as the Anti-Corruption Layer (ACL) between the external Mjai JSON Lines protocol and the internal domain logic. It is responsible for the bidirectional translation of messages, managing connection lifecycles (TCP or Stdio), and driving the game state via a message loop.
The adapter resides between the cmd/ entry points (such as mjai-tsumogiri cmd/mjai-tsumogiri/main.go46-64) and the application/ layer. It ensures that the domain model remains agnostic of JSON structures or network protocols.
Title: Mjai Adapter Data Flow
Sources: internal/adapter/mjai/runtime/driver.go34-74 internal/adapter/mjai/runtime/json_lines.go37-78
The runtime package handles the execution environment. It provides two primary entry points: RunTCP for connecting to Mjai servers (e.g., via the mjsonp:// scheme) and RunStdio for local engine integration.
RunTCP parses Mjsonp URLs and dials the server using net.Dial internal/adapter/mjai/runtime/tcp.go33-45runJSONLines, which continuously reads inbound JSON using a bufio.Scanner, dispatches it to the Driver.Handle method, and writes back responses internal/adapter/mjai/runtime/json_lines.go32-50mjairuntime.Driver maintains the session state, including the application.Bot instance and the ai.Agent internal/adapter/mjai/runtime/driver.go14-22 It handles meta-messages like hello (returning a join message) and start_game (resetting the agent and creating a new bot) internal/adapter/mjai/runtime/driver.go36-50For details, see Runtime: TCP and Stdio Drivers.
Inbound messages are decoded in a two-stage process to ensure type safety and validation before reaching the domain.
inbound.Dahai, inbound.Ankan) using a dispatch table within ParseMessage internal/adapter/mjai/inbound/dahai.go9-14event.Discard) via ToEvent() methods, which perform field validation using helpers like parseSeatField and parseKnownTileField internal/adapter/mjai/inbound/dahai.go18-37 internal/adapter/mjai/inbound/convert.go11-39Title: Inbound Decoding Pipeline
Sources: internal/adapter/mjai/inbound/dahai.go9-37 internal/adapter/mjai/runtime/driver.go61-64 internal/adapter/mjai/inbound/convert.go1-125
For details, see Inbound Message Decoding.
When the AI decides on an action, the adapter translates the internal action.Action back into a JSON-serializable outbound.Message.
outbound.ToMessage function uses a type switch to map domain actions to their Mjai protocol counterparts (e.g., action.Discard to outbound.Dahai, action.Pass to outbound.Pass) internal/adapter/mjai/outbound/marshal_message.go14-39log field containing AI reasoning or tracing data, which is passed through the translation layer internal/adapter/mjai/outbound/marshal_message.go14MarshalMessage, which utilizes the encoding/json/v2 experimental package internal/adapter/mjai/outbound/marshal_message.go4-12For details, see Outbound Message Encoding.
| Component | Role | Source |
|---|---|---|
mjairuntime.Driver | Orchestrates message flow between protocol and bot. | internal/adapter/mjai/runtime/driver.go14 |
inbound.Message | Interface for all incoming Mjai JSON structures. | internal/adapter/mjai/inbound/dahai.go16 |
outbound.Message | Interface for all outgoing Mjai JSON structures. | internal/adapter/mjai/outbound/marshal_message.go10 |
application.Bot | Application service that processes domain events. | internal/adapter/mjai/runtime/driver.go48 |
mjairuntime.RunTCP | Entry point for TCP-based Mjsonp connections. | internal/adapter/mjai/runtime/tcp.go33 |
mjairuntime.RunStdio | Entry point for Standard I/O communication. | internal/adapter/mjai/runtime/stdio.go19 |
Sources: internal/adapter/mjai/runtime/driver.go14-74 internal/adapter/mjai/outbound/marshal_message.go10-39 internal/adapter/mjai/runtime/tcp.go33-59 internal/adapter/mjai/runtime/stdio.go19-21