Dsxir.Adapter.Chat.StreamParser (dsxir v0.5.0)

Copy Markdown

Incremental parser for the Chat adapter's [[ ## field ## ]] marker protocol, used to stream individual output fields as their text arrives.

push/2 feeds a raw text delta and returns {events, parser} where each event is a %Dsxir.Stream.Event{type: :field_delta, field: name, data: fragment} for a listened field, with marker-edge whitespace stripped (matching the batch parser's String.trim/1, so the concatenated stream equals the parsed value). Text that could still grow into a marker — or trailing whitespace that might be the gap before one — is held back until the next delta disambiguates it. finish/1 flushes the final field, which has no closing marker.

Pure and process-free: the struct is threaded as the accumulator of a streaming callback, so no process is needed to carry state across deltas.

Summary

Functions

Flush the final field's withheld buffer (it has no closing marker).

Build a parser that emits :field_delta events for listened_fields.

Feed a raw text delta, returning {events, parser}. Emitted events are marker-stripped :field_delta fragments for listened fields; text that could still grow into a marker is withheld in the returned parser.

Types

t()

@type t() :: %Dsxir.Adapter.Chat.StreamParser{
  at_field_start: boolean(),
  buffer: String.t(),
  current_field: atom() | nil,
  listened: MapSet.t(atom())
}

Functions

finish(parser)

@spec finish(t()) :: {[Dsxir.Stream.Event.t()], t()}

Flush the final field's withheld buffer (it has no closing marker).

new(listened_fields)

@spec new([atom()]) :: t()

Build a parser that emits :field_delta events for listened_fields.

push(parser, text)

@spec push(t(), String.t()) :: {[Dsxir.Stream.Event.t()], t()}

Feed a raw text delta, returning {events, parser}. Emitted events are marker-stripped :field_delta fragments for listened fields; text that could still grow into a marker is withheld in the returned parser.