Class NaruThinkingTagParser

java.lang.Object
net.thevpc.naru.api.model.NaruThinkingTagParser

public class NaruThinkingTagParser extends Object
Splits a text stream into thinking and answer content using a delimiter pair.

Stateful on purpose. A tag can be split across two network packets -- a chunk may well end mid-way through the literal <thi, and a parser that assumed a whole tag per chunk would leak that fragment into the answer as visible text. So this buffers the longest tail that could still turn out to be the start of a tag, and only emits text once it knows the tail is not a tag.

Not thread-safe: one parser belongs to one response, driven by one transport thread.

Why not a regex

Pattern cannot express "a tag may straddle a chunk boundary" without being handed the whole stream, which is exactly what defeats incremental display. The buffering is the feature.

  • Field Details

  • Constructor Details

    • NaruThinkingTagParser

      public NaruThinkingTagParser()
    • NaruThinkingTagParser

      public NaruThinkingTagParser(String openTag, String closeTag)
  • Method Details

    • openTag

      public String openTag()
    • closeTag

      public String closeTag()
    • extraction

      public NaruThinkingExtraction extraction()
    • tags

      public NaruThinkingTags tags()
      The delimiter pair this parser was built with, for handing to a NaruStreamPipeline or a NaruModelConfig.
    • sawThinking

      public boolean sawThinking()
      Whether an unterminated openTag was seen. A provider that opened a reasoning block and never closed it is common, and the tail is still thinking -- it just has no closing boundary.
    • isTruncated

      public boolean isTruncated()
      Whether the last thinking segment was left open at the end of the stream.
    • feed

      public List<NaruStreamChunk> feed(String text, String provider)
      Feeds one chunk of stream text.
      Returns:
      the chunks this input completed, in order; empty when the input was absorbed into the tag-boundary buffer
    • flush

      public List<NaruStreamChunk> flush(String provider)
      Signals the end of the stream and returns whatever was still buffered.

      Must be called, or a tag that straddles the final chunk is never emitted and text is silently lost.

    • markOpenSegmentTruncated

      public List<NaruStreamChunk> markOpenSegmentTruncated(String provider)
      Re-tags the chunk of the given kind that is still open as truncated.

      Called when a generation is interrupted. Mid-stream text was already emitted as non-final, so usually there is nothing buffered here; this exists for the case where the interrupt landed on a chunk boundary and the tail is still ambiguous, and it settles the segment either way.

    • isSegmentComplete

      public boolean isSegmentComplete()
      Whether the stream ended with every segment properly closed.

      This is the authoritative completion signal, and unlike NaruStreamChunk.complete() it is meaningful for a stream that was cut short -- a chunk delivered mid-stream cannot know what comes next, but after the stream ends this says definitively whether the reasoning was finished or interrupted. This is what a persisted thinking segment records.

    • chunks

      public List<NaruStreamChunk> chunks()
      Every chunk this parser has produced, in order.
    • parseAll

      public static void parseAll(String text, String openTag, String closeTag, String provider, Consumer<NaruStreamChunk> sink)
      Feeds a whole response's text through the parser and hands each chunk to sink, then flushes. The batch counterpart of feed(java.lang.String, java.lang.String).
    • toString

      public String toString()
      Overrides:
      toString in class Object