Module: Mistri::TaskOutput

Defined in:
lib/mistri/task_output.rb

Overview

The text side of task mode: how a schema is asked for, how the answer parses, and how a violation is sent back for a fix. Pure functions over strings and schemas; Agent#task owns the loop that drives them.

Constant Summary collapse

PARSE_FAILED =

Distinguishable from a parsed nil: JSON "null" is a valid value.

Object.new.freeze

Class Method Summary collapse

Class Method Details

.errors(value, schema) ⇒ Object



28
29
30
31
32
# File 'lib/mistri/task_output.rb', line 28

def errors(value, schema)
  return ["the answer is not valid JSON"] if value.equal?(PARSE_FAILED)

  Schema.violations(value, schema)
end

.fix_prompt(errors) ⇒ Object



34
35
36
37
38
# File 'lib/mistri/task_output.rb', line 34

def fix_prompt(errors)
  lines = errors.map { |error| "- #{error}" }.join("\n")
  "Your answer did not satisfy the required output schema. Problems:\n" \
    "#{lines}\nReply with ONLY the corrected JSON."
end

.parse(text) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/mistri/task_output.rb', line 20

def parse(text)
  body = text.to_s.strip
  body = body[/\A```(?:json)?\s*(.*?)```\z/m, 1] || body
  JSON.parse(body)
rescue JSON::ParserError
  PARSE_FAILED
end

.prompt(input, schema) ⇒ Object



15
16
17
18
# File 'lib/mistri/task_output.rb', line 15

def prompt(input, schema)
  "#{input}\n\nAnswer with ONLY a JSON value matching this schema:\n" \
    "#{JSON.generate(Schema.strict(schema))}"
end