Class: Rubino::Tools::ShellInputTool
- Defined in:
- lib/rubino/tools/shell_input_tool.rb
Overview
Feeds input to a background shell’s stdin (registered by ShellTool when run_in_background: true). This is how the agent answers an interactive prompt a running command emits — Y/N confirmations, “select region” menus, apt-style questions — without having to pre-bake the answer at spawn time (‘echo y | cmd`, `-y`, heredoc).
Typical loop: shell(run_in_background: true) → shell_output (see the prompt) → shell_input(run_id:, text: “y”) → shell_output (see the result).
By default a newline is appended (like pressing Enter). Pass ‘enter: false` to send raw bytes without a newline. Pass `eof: true` to close stdin (send EOF) after writing — for commands that read until EOF.
Works for line-oriented prompts. Full-screen TTY programs (vim, REPLs that require a real terminal) are out of scope: the background shell uses a plain pipe, not a pseudo-terminal.
Instance Attribute Summary
Attributes inherited from Base
#cancel_token, #read_tracker, #stream_chunk
Instance Method Summary collapse
- #call(arguments) ⇒ Object
- #description ⇒ Object
- #input_schema ⇒ Object
- #name ⇒ Object
- #risk_level ⇒ Object
Methods inherited from Base
#cancellation_requested?, #config_key, #emit_chunk, #risky?, #to_tool_definition, workspace_root, workspace_roots
Instance Method Details
#call(arguments) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rubino/tools/shell_input_tool.rb', line 64 def call(arguments) run_id = arguments["run_id"] || arguments[:run_id] text = arguments["text"] || arguments[:text] || "" enter = arguments.fetch("enter", arguments.fetch(:enter, true)) eof = arguments["eof"] || arguments[:eof] || false return "Error: run_id is required" if run_id.nil? || run_id.to_s.empty? registry = ShellRegistry.instance entry = registry.find(run_id) return "Error: no background shell with run_id=#{run_id}" unless entry unless entry.wait_thr.alive? return "Error: [#{run_id}] already exited (exit=#{registry.exit_code(entry)}) — cannot send input" end written = begin registry.write_input(entry, text, enter: enter) rescue IOError, Errno::EPIPE => e return "Error: [#{run_id}] stdin is closed (#{e.})" end registry.close_stdin(entry) if eof msg = "[#{run_id}] wrote #{written} byte#{"s" unless written == 1} to stdin" msg << " (EOF sent)" if eof msg << "\nRead the result: shell_output run_id=#{run_id}" msg end |
#description ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/rubino/tools/shell_input_tool.rb', line 26 def description "Send input to a background shell started via `shell` with " \ "run_in_background: true — answer an interactive prompt (Y/N, menu " \ "selection, password) of a running command. A newline is appended by " \ "default (like pressing Enter); pass enter: false for raw bytes, or " \ "eof: true to close stdin (EOF). Read the prompt and the result with " \ "`shell_output`." end |
#input_schema ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/rubino/tools/shell_input_tool.rb', line 35 def input_schema { type: "object", properties: { run_id: { type: "string", description: "The run_id returned by `shell` when launched in background" }, text: { type: "string", description: "The text to write to the process's stdin (e.g. \"y\", \"2\")" }, enter: { type: "boolean", description: "Append a newline like pressing Enter (default true)" }, eof: { type: "boolean", description: "Close stdin / send EOF after writing (default false)" } }, required: %w[run_id] } end |
#name ⇒ Object
22 23 24 |
# File 'lib/rubino/tools/shell_input_tool.rb', line 22 def name "shell_input" end |
#risk_level ⇒ Object
60 61 62 |
# File 'lib/rubino/tools/shell_input_tool.rb', line 60 def risk_level :medium end |