Module: Optimize::Demo::Claude::Invoker

Defined in:
lib/optimize/demo/claude/invoker.rb

Overview

Thin shell wrapper around ‘claude -p –output-format json`. Single-shot, no retries — the caller is responsible for orchestration.

Defined Under Namespace

Classes: CLIError, ParseError

Class Method Summary collapse

Class Method Details

.call(prompt:, binary: "claude") ⇒ Object

Shells out to ‘claude -p –output-format json`, pipes prompt on stdin. Returns the JSON-parsed assistant output (the contents of the envelope’s “result” field, re-parsed as JSON).

Parameters:

  • prompt (String)

    prompt body, fed on stdin.

  • binary (String) (defaults to: "claude")

    path or name of the claude CLI.

Returns:

  • (Object)

    parsed assistant JSON.

Raises:

  • (CLIError)

    on non-zero exit, missing “result” field, or unparseable outer envelope.

  • (ParseError)

    when the assistant’s “result” string cannot be parsed as JSON. ParseError < CLIError.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/optimize/demo/claude/invoker.rb', line 27

def call(prompt:, binary: "claude")
  stdout, stderr, status = Open3.capture3(
    binary, "-p", "--output-format", "json", stdin_data: prompt
  )

  unless status.exitstatus.zero?
    raise CLIError, "#{binary} exited #{status.exitstatus}: #{stderr}"
  end

  envelope =
    begin
      JSON.parse(stdout)
    rescue JSON::ParserError => e
      raise CLIError, "could not parse #{binary} envelope: #{e.message}"
    end

  unless envelope.is_a?(Hash) && envelope.key?("result")
    raise CLIError,
          "#{binary} envelope missing 'result' field: #{envelope.inspect[0, 200]}"
  end

  result_text = envelope["result"]

  begin
    JSON.parse(result_text)
  rescue JSON::ParserError => e
    raise ParseError, "could not parse assistant JSON: #{e.message}\n---\n#{result_text}"
  end
end