Class: RubynCode::Tools::AskUser

Inherits:
Base
  • Object
show all
Defined in:
lib/rubyn_code/tools/ask_user.rb

Constant Summary collapse

TOOL_NAME =
'ask_user'
DESCRIPTION =
'Ask the user a question and wait for their response. ' \
'Use this when you need clarification, want to confirm a plan before executing, ' \
'or are stuck and need guidance. The question is displayed and the user\'s answer ' \
'is returned as the tool result.'
PARAMETERS =
{
  question: {
    type: :string,
    description: 'The question to ask the user',
    required: true
  }
}.freeze
RISK_LEVEL =

Never needs approval — it IS the approval mechanism

:read
IDE_ASK_TIMEOUT =

The user may take a while to answer, so allow far longer than the default RPC timeout before giving up on the IDE round-trip.

300

Constants inherited from Base

Base::REQUIRES_CONFIRMATION

Instance Attribute Summary collapse

Attributes inherited from Base

#project_root

Instance Method Summary collapse

Methods inherited from Base

description, parameters, requires_confirmation?, risk_level, #safe_path, summarize, to_schema, tool_name, #truncate

Constructor Details

#initialize(project_root:, ide_client: nil) ⇒ AskUser

Returns a new instance of AskUser.



29
30
31
32
# File 'lib/rubyn_code/tools/ask_user.rb', line 29

def initialize(project_root:, ide_client: nil)
  super(project_root: project_root)
  @ide_client = ide_client
end

Instance Attribute Details

#prompt_callback=(value) ⇒ Object (writeonly)

seconds



27
28
29
# File 'lib/rubyn_code/tools/ask_user.rb', line 27

def prompt_callback=(value)
  @prompt_callback = value
end

Instance Method Details

#execute(question:) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rubyn_code/tools/ask_user.rb', line 34

def execute(question:)
  if @ide_client
    # IDE mode: round-trip the question through the extension's UI.
    response = @ide_client.request('ide/askUser', { question: question }, timeout: IDE_ASK_TIMEOUT)
    answer = response && response['answer']
    answer.nil? || answer.empty? ? '[no response]' : answer
  elsif @prompt_callback
    @prompt_callback.call(question)
  elsif $stdin.respond_to?(:tty?) && $stdin.tty?
    # Interactive fallback: prompt on stdin
    $stdout.puts
    $stdout.puts "  #{question}"
    $stdout.print '  > '
    $stdout.flush
    $stdin.gets&.strip || '[no response]'
  else
    # Non-interactive (piped input, -p mode, daemon) — can't ask
    '[non-interactive session — cannot ask user. Make your best judgment and proceed.]'
  end
end