Class CliChannel

java.lang.Object
com.tnsai.channels.cli.CliChannel
All Implemented Interfaces:
ChannelAdapter, StreamingChannelAdapter

@Channel(id="cli", displayName="Command Line") public final class CliChannel extends Object implements StreamingChannelAdapter
Command-line channel adapter.

Reads user input from a BufferedReader on a dedicated daemon thread and delivers each line to the gateway as a UnifiedMessage. Responses come back through send(UnifiedResponse) and render straight to the configured PrintStream.

Modes

  • CliChannel.Mode.REPL — interactive prompt ("> "), human-friendly output with assistant prefix and (optional) ANSI colour. Local slash commands /exit, /quit, /clear are intercepted and never forwarded; everything else flows as a message so the gateway's skill registry can handle it.
  • CliChannel.Mode.JSON — newline-delimited JSON for scripting. Each input line is parsed as a JSON object whose text field becomes the message body. Each response is written as {"type":"text","content":"..."} on its own line.

Streaming

The adapter implements StreamingChannelAdapter (TNS-440): the framework routes per-token UnifiedChunks through sendChunk(com.tnsai.channels.api.UnifiedChunk) as the agent generates them. REPL mode prints one assistant prefix and concatenates deltas inline; JSON mode emits newline-delimited {"type":"chunk","content":"...","done":...} records. The final send(UnifiedResponse) call after a stream is suppressed (no duplicate render of the assembled reply); non-streaming downstreams still receive the assembled response through the normal ChannelAdapter path.

Thread safety

The reader runs on its own daemon thread; send(com.tnsai.channels.api.UnifiedResponse) may be called concurrently from gateway threads. Output is synchronised on the writer lock so an inbound prompt redraw and an outbound response can't interleave.
Since:
0.10.1
  • Constructor Details

    • CliChannel

      public CliChannel()
      Default constructor used by the SPI factory: REPL mode reading from System.in and writing to System.out.
    • CliChannel

      public CliChannel(CliChannel.Mode mode, BufferedReader reader, PrintStream writer)
      Constructor for tests or custom wiring (e.g. piping through JLine).
      Parameters:
      mode - REPL or JSON
      reader - stdin source — must not be null
      writer - stdout sink — must not be null
      Throws:
      NullPointerException - if any argument is null
  • Method Details

    • id

      public String id()
      Description copied from interface: ChannelAdapter
      Unique identifier for this channel (e.g. "telegram", "discord", "slack").
      Specified by:
      id in interface ChannelAdapter
    • displayName

      public String displayName()
      Description copied from interface: ChannelAdapter
      Human-readable display name.
      Specified by:
      displayName in interface ChannelAdapter
    • capabilities

      public ChannelCapabilities capabilities()
      Description copied from interface: ChannelAdapter
      Declares what this channel supports.
      Specified by:
      capabilities in interface ChannelAdapter
    • start

      public void start(ChannelContext context)
      Description copied from interface: ChannelAdapter
      Start listening for inbound messages. The adapter should call ChannelContext.onMessage(com.tnsai.channels.api.UnifiedMessage) when a message arrives.
      Specified by:
      start in interface ChannelAdapter
      Parameters:
      context - callback interface for delivering events to the gateway
    • stop

      public void stop()
      Description copied from interface: ChannelAdapter
      Stop listening and release resources.
      Specified by:
      stop in interface ChannelAdapter
    • isRunning

      public boolean isRunning()
      Description copied from interface: ChannelAdapter
      Whether the adapter is currently connected and operational.
      Specified by:
      isRunning in interface ChannelAdapter
    • send

      public void send(UnifiedResponse response)
      Description copied from interface: ChannelAdapter
      Send a response back through this channel.
      Specified by:
      send in interface ChannelAdapter
      Parameters:
      response - the unified response to deliver
    • sendChunk

      public void sendChunk(UnifiedChunk chunk)
      Description copied from interface: StreamingChannelAdapter
      Deliver one UnifiedChunk to the channel. The adapter is expected to surface chunk.delta() immediately — flush the underlying transport so the user sees incremental progress.

      For text-only sinks (CLI stdout, plain HTTP SSE), this is usually a write + flush. For platforms with an editing model (Telegram, Slack) the recommended pattern is to send the first chunk as a new message and edit it on every subsequent non-empty chunk; flag done=true on the final chunk to release any "still typing…" affordance.

      Empty deltas (chunk.delta().isEmpty()) are valid — they may carry only metadata (e.g. a tool-call start marker). Adapters that only render text should treat empty deltas as no-op rather than throwing.

      Specified by:
      sendChunk in interface StreamingChannelAdapter