Class CliChannel
- All Implemented Interfaces:
ChannelAdapter,StreamingChannelAdapter
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,/clearare 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 whosetextfield becomes the message body. Each response is written as{"type":"text","content":"..."}on its own line.
Streaming
The adapter implementsStreamingChannelAdapter (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
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumREPL = interactive prompt; JSON = newline-delimited JSON for scripting. -
Constructor Summary
ConstructorsConstructorDescriptionDefault constructor used by the SPI factory: REPL mode reading fromSystem.inand writing toSystem.out.CliChannel(CliChannel.Mode mode, BufferedReader reader, PrintStream writer) Constructor for tests or custom wiring (e.g. piping through JLine). -
Method Summary
Modifier and TypeMethodDescriptionDeclares what this channel supports.Human-readable display name.id()Unique identifier for this channel (e.g.booleanWhether the adapter is currently connected and operational.voidsend(UnifiedResponse response) Send a response back through this channel.voidsendChunk(UnifiedChunk chunk) Deliver oneUnifiedChunkto the channel.voidstart(ChannelContext context) Start listening for inbound messages.voidstop()Stop listening and release resources.
-
Constructor Details
-
CliChannel
public CliChannel()Default constructor used by the SPI factory: REPL mode reading fromSystem.inand writing toSystem.out. -
CliChannel
Constructor for tests or custom wiring (e.g. piping through JLine).- Parameters:
mode- REPL or JSONreader- stdin source — must not benullwriter- stdout sink — must not benull- Throws:
NullPointerException- if any argument isnull
-
-
Method Details
-
id
Description copied from interface:ChannelAdapterUnique identifier for this channel (e.g. "telegram", "discord", "slack").- Specified by:
idin interfaceChannelAdapter
-
displayName
Description copied from interface:ChannelAdapterHuman-readable display name.- Specified by:
displayNamein interfaceChannelAdapter
-
capabilities
Description copied from interface:ChannelAdapterDeclares what this channel supports.- Specified by:
capabilitiesin interfaceChannelAdapter
-
start
Description copied from interface:ChannelAdapterStart listening for inbound messages. The adapter should callChannelContext.onMessage(com.tnsai.channels.api.UnifiedMessage)when a message arrives.- Specified by:
startin interfaceChannelAdapter- Parameters:
context- callback interface for delivering events to the gateway
-
stop
public void stop()Description copied from interface:ChannelAdapterStop listening and release resources.- Specified by:
stopin interfaceChannelAdapter
-
isRunning
public boolean isRunning()Description copied from interface:ChannelAdapterWhether the adapter is currently connected and operational.- Specified by:
isRunningin interfaceChannelAdapter
-
send
Description copied from interface:ChannelAdapterSend a response back through this channel.- Specified by:
sendin interfaceChannelAdapter- Parameters:
response- the unified response to deliver
-
sendChunk
Description copied from interface:StreamingChannelAdapterDeliver oneUnifiedChunkto the channel. The adapter is expected to surfacechunk.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; flagdone=trueon 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:
sendChunkin interfaceStreamingChannelAdapter
-