Class: Rubino::Agent::ResponseValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/agent/response_validator.rb

Overview

Judges a single normalized AdapterResponse on two axes the conversation loop cares about, mirroring the reference validate_response and _has_content_after_think_block.

Unlike the reference — which validates a raw provider object per api_mode and has to special-case codex/anthropic/bedrock/openai shapes — ruby_llm already raises typed errors for bad HTTP, so by the time a response reaches here it is the one normalized AdapterResponse shape. The validator therefore only judges that shape; there is no per-provider branching to port.

Two questions, two methods:

#valid?      STRUCTURAL — is this a usable response at all? (not nil,
             carries some text OR tool calls, not an interrupted partial)
#degenerate? SEMANTIC — a structurally valid text response that is
             nonetheless useless: thinking-only (no real content after
             the <think> block) or blank visible content.

Instance Method Summary collapse

Instance Method Details

#degenerate?(response) ⇒ Boolean

True when a STRUCTURALLY valid text response carries no real answer: its visible content is empty once the <think> block is stripped (the model reasoned but never spoke). Mirrors the reference ‘not _has_content_after_think_block(content)`.

Tool-call responses are never degenerate — the tool call IS the answer.

Returns:

  • (Boolean)


42
43
44
45
46
47
# File 'lib/rubino/agent/response_validator.rb', line 42

def degenerate?(response)
  return false if response.nil? || response.interrupted?
  return false if response.has_tool_calls?

  !content_after_think_block?(response.content)
end

#valid?(response) ⇒ Boolean

#valid? returns [Boolean, reason]. ‘reason` is nil when valid, otherwise a symbol naming the structural defect (for warnings / future telemetry):

:nil_response   — no response object
:interrupted    — buffered partial from a truncated stream, not a turn
:empty_response — neither text nor tool calls

Returns:

  • (Boolean)


27
28
29
30
31
32
33
34
# File 'lib/rubino/agent/response_validator.rb', line 27

def valid?(response)
  return [false, :nil_response] if response.nil?
  return [false, :interrupted]  if response.interrupted?
  return [true, nil]            if response.has_tool_calls?
  return [false, :empty_response] if response.content.to_s.strip.empty?

  [true, nil]
end