Class: RubynCode::Tools::PhoneAFriend

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

Overview

Ask a different model for a second opinion. The "friend" is chosen to maximize perspective diversity: prefer the top-tier model of another configured provider (a genuinely different model family), and fall back to the active provider's top-tier model when no other provider has an API key available. One-shot, no tools, returns plain text.

Constant Summary collapse

TOOL_NAME =
'phone_a_friend'
DESCRIPTION =
'Ask a different model for a second opinion when you are stuck, ' \
'weighing two approaches, or want your reasoning sanity-checked. ' \
'Sends one question (plus optional context) to another model — ' \
'a different provider when one is configured, otherwise the ' \
'top-tier model of the current provider — and returns its answer. ' \
'The friend has no tools and sees nothing except what you send.'
PARAMETERS =
{
  question: {
    type: :string,
    required: true,
    description: 'The question to ask. Be specific about what kind of answer you ' \
                 'need (a decision, a review of reasoning, an alternative approach).'
  },
  context: {
    type: :string,
    required: false,
    description: 'Relevant code, error output, or background. The friend sees ' \
                 'only this — include everything needed to answer well.'
  }
}.freeze
RISK_LEVEL =
:external
SYSTEM_PROMPT =
<<~PROMPT
  You are giving a second opinion to another AI coding agent that is working
  inside a project and has hit a question it wants an outside perspective on.
  You cannot see the project — only what the agent sent you. Answer directly
  and concretely: commit to a recommendation, explain the key reason, and
  flag anything important the agent may have missed. If the provided context
  is insufficient to answer well, say exactly what is missing.
PROMPT

Constants inherited from Base

Base::REQUIRES_CONFIRMATION

Instance Attribute Summary collapse

Attributes inherited from Base

#project_root

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

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

Constructor Details

This class inherits a constructor from RubynCode::Tools::Base

Instance Attribute Details

#client_factory=(value) ⇒ Object (writeonly)

Injected by the Executor (active client) and overridable in tests.



47
48
49
# File 'lib/rubyn_code/tools/phone_a_friend.rb', line 47

def client_factory=(value)
  @client_factory = value
end

#llm_client=(value) ⇒ Object (writeonly)

Injected by the Executor (active client) and overridable in tests.



47
48
49
# File 'lib/rubyn_code/tools/phone_a_friend.rb', line 47

def llm_client=(value)
  @llm_client = value
end

Class Method Details

.summarize(_output, _args) ⇒ Object



63
64
65
# File 'lib/rubyn_code/tools/phone_a_friend.rb', line 63

def self.summarize(_output, _args)
  'asked another model for a second opinion'
end

Instance Method Details

#execute(question:, context: nil) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rubyn_code/tools/phone_a_friend.rb', line 49

def execute(question:, context: nil)
  return 'phone_a_friend: no LLM client available.' unless @llm_client

  provider, model = pick_friend
  response = call_friend(provider, model, build_message(question, context))
  answer = extract_text(response)
  return "phone_a_friend: #{provider}/#{model} returned no text." if answer.empty?

  "## Second Opinion — #{provider}/#{model}\n\n#{answer}"
rescue StandardError => e
  friend = provider ? "#{provider}/#{model}" : 'friend'
  "phone_a_friend: call to #{friend} failed: #{e.message}"
end