Class: Rubino::UI::HeadlessTrace
- Defined in:
- lib/rubino/ui/headless_trace.rb
Overview
Non-interactive one-shot TEXT adapter that adds a default-on per-tool
ACTIVITY TRACE to the otherwise-silent headless path. It IS a Null adapter
(so it keeps every fail-closed / approval-block-latch behaviour the
rubino prompt / -q text path depends on — see UI::Null) and adds ONE
concise line per tool completion, routed to STDERR:
· edit foo.rb
· bash npm test
· read README.md
The trace goes to STDERR by construction so the final answer on STDOUT
stays clean — x=$(rubino prompt …) captures ONLY the answer (#418), while
a human watching the terminal still sees what the agent did. This mirrors
the industry norm: Codex exec, gemini-cli -p, and rubino's upstream
Hermes (-q) all show tool activity on stderr by default, with --quiet
(Hermes -Q) selecting the silent machine path (plain UI::Null).
The line vocabulary (name hint) is shared with the interactive tool-card
open row via UI::ToolLabel, so the two never drift.
Instance Attribute Summary
Attributes inherited from Null
Instance Method Summary collapse
-
#initialize(verbose: false, io: $stderr) ⇒ HeadlessTrace
constructor
verbose:widens the per-tool hint (fuller args), mirroring Claude's--verbose. -
#tool_finished(name, result: nil) ⇒ Object
Emit the one trace line per tool COMPLETION (not start) — so a tool that never returns doesn't leave a dangling line, and the order matches the actual work done.
-
#tool_started(name, arguments: nil, at: nil, call_id: nil) ⇒ Object
Capture the arguments at start so #tool_finished can render the same
name hintlabel the interactive card shows.
Methods inherited from Null
#approval_blocked?, #ask, #assistant_text, #blank_line, #blocked_messages, #body, #box_close, #box_open, #branch_confirmation, #compression_finished, #compression_started, #confirm, #confirm_destructive, #error, #info, #input_injected, #interactive?, #job_enqueued, #job_finished, #job_started, #mode_changed, #note, #probe_aside, #queued, #reasoning_changed, #reasoning_status, #replay_user_input, #reset!, #select, #separator, #status, #stream, #stream_end, #subagent_approval_choice, #success, #table, #think_changed, #think_status, #thinking_finished, #thinking_started, #tool_blocked, #tool_body, #tool_chunk, #warning
Methods inherited from Base
#ask, #assistant_text, #blank_line, #blocking_human_input?, #body, #box_close, #box_open, #compression_finished, #compression_started, #confirm, #confirm_destructive, #error, #hint_row, #info, #input_injected, #interactive?, #job_enqueued, #job_finished, #job_started, #mode_changed, #note, #panel_line, #queued, #replay_user_input, #select, #separator, #status, #stream, #stream_end, #success, #table, #thinking_started, #tool_body, #turn_interrupted, #warning
Constructor Details
#initialize(verbose: false, io: $stderr) ⇒ HeadlessTrace
verbose: widens the per-tool hint (fuller args), mirroring Claude's
--verbose. io: is injectable for specs; defaults to the real stderr.
27 28 29 30 31 32 |
# File 'lib/rubino/ui/headless_trace.rb', line 27 def initialize(verbose: false, io: $stderr) super() @verbose = verbose @trace_io = io @pending_args = {} end |
Instance Method Details
#tool_finished(name, result: nil) ⇒ Object
Emit the one trace line per tool COMPLETION (not start) — so a tool that never returns doesn't leave a dangling line, and the order matches the actual work done. Best-effort: a trace write must NEVER fail the run or leak onto stdout.
46 47 48 49 |
# File 'lib/rubino/ui/headless_trace.rb', line 46 def tool_finished(name, result: nil) super emit_trace_line(name.to_s) end |
#tool_started(name, arguments: nil, at: nil, call_id: nil) ⇒ Object
Capture the arguments at start so #tool_finished can render the same
name hint label the interactive card shows. The task subagent tool
renders its own delegation line on finish, so we skip it here.
37 38 39 40 |
# File 'lib/rubino/ui/headless_trace.rb', line 37 def tool_started(name, arguments: nil, at: nil, call_id: nil) super @pending_args[name.to_s] = arguments end |