Class: Rubino::UI::ToolArgsStream

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/ui/tool_args_stream.rb

Overview

Decodes a tool call's JSON arguments AS THEY STREAM into readable text, so the timeline can show what a write/edit/shell is composing while the model is still emitting it (#608). It surfaces the JSON string VALUES only (the content a write is producing, the command a shell will run) and drops the keys/structure, JSON-unescaping as it goes.

#feed returns the COMPLETE decoded lines available so far (each ending in "\n"), holding the partial last line back until its newline lands so the caller never renders a half-line that the next fragment continues. #flush returns whatever partial remains at the end of the call.

Single pass, O(n): fragments are concatenated only across an incomplete trailing escape (a "\" or "\uXXX" split mid-fragment), carried to the next feed so an escape is never decoded half-formed.

Constant Summary collapse

UNESCAPE =

JSON single-char escapes → their literal char (\uXXXX is handled inline).

{ "n" => "\n", "t" => "\t", "r" => "\r", "b" => "\b",
"f" => "\f", '"' => '"', "\\" => "\\", "/" => "/" }.freeze

Instance Method Summary collapse

Constructor Details

#initializeToolArgsStream

Returns a new instance of ToolArgsStream.



24
25
26
27
28
29
30
31
# File 'lib/rubino/ui/tool_args_stream.rb', line 24

def initialize
  @in_string  = false
  @is_value   = false      # the current string is a VALUE (emit) vs a KEY (skip)
  @containers = []         # stack of :obj / :arr to read `,` correctly
  @expect     = :value     # what the next opening string is (top-level value)
  @line       = +""        # decoded VALUE text not yet returned (current line)
  @carry      = +""        # raw chars held back across an incomplete escape
end

Instance Method Details

#feed(fragment) ⇒ Object

Feed a raw argument fragment; returns the complete decoded lines unlocked by it (possibly empty), with the partial last line held back.



35
36
37
38
39
40
# File 'lib/rubino/ui/tool_args_stream.rb', line 35

def feed(fragment)
  return "" if fragment.nil? || fragment.empty?

  scan(@carry + fragment)
  take_complete_lines
end

#flushObject

Final partial line (the value tail with no trailing newline), or "".



43
44
45
46
47
# File 'lib/rubino/ui/tool_args_stream.rb', line 43

def flush
  out = @line.dup
  @line.clear
  out
end