PtcRunner.SubAgent.Loop.JsonHandler (PtcRunner v0.9.0)

Copy Markdown View Source

Shared JSON response handling for text mode variants.

Extracted from JsonMode and ToolCallingMode to eliminate duplication. Provides JSON parsing, validation, key atomization, and error handling that is shared across the json-only and tool-calling code paths.

Summary

Functions

Atomize map keys based on signature (safe conversion).

Atomize list elements based on signature.

Atomize value based on expected type.

Format validation errors for display.

Handle a JSON answer from an LLM response.

Handle parse error - retry with feedback or return error signal.

Handle validation error - retry with feedback or return error signal.

Safe atom conversion - try existing atom first, keep string if not found.

Check if the signature expects a list as return type.

Validate parsed JSON map and complete or retry.

Validate return value against signature.

Functions

atomize_keys(map, arg2)

@spec atomize_keys(map(), term()) :: map()

Atomize map keys based on signature (safe conversion).

atomize_list(list, arg2)

@spec atomize_list(list(), term()) :: list()

Atomize list elements based on signature.

atomize_value(map, arg2)

@spec atomize_value(term(), term()) :: term()

Atomize value based on expected type.

format_validation_errors(errors)

@spec format_validation_errors(list()) :: String.t()

Format validation errors for display.

handle_json_answer(content, agent, state, opts \\ [])

@spec handle_json_answer(String.t(), PtcRunner.SubAgent.t(), map(), keyword()) ::
  {:continue, map(), map()}
  | {:stop, {:ok | :error, PtcRunner.Step.t()}, map() | nil, map() | nil}

Handle a JSON answer from an LLM response.

Parses JSON from the response content, validates against the agent's signature, and returns the appropriate signal for the driver loop.

Returns:

  • {:stop, {:ok, step}, turn, turn_tokens} on success
  • {:stop, {:error, step}, turn, turn_tokens} on final failure
  • {:continue, state, turn} for retry with feedback

handle_parse_error(error, response, agent, state, opts \\ [])

@spec handle_parse_error(
  String.t(),
  String.t(),
  PtcRunner.SubAgent.t(),
  map(),
  keyword()
) ::
  {:continue, map(), map()}
  | {:stop, {:error, PtcRunner.Step.t()}, map() | nil, map() | nil}

Handle parse error - retry with feedback or return error signal.

handle_validation_error(errors, response, agent, state, opts \\ [])

@spec handle_validation_error(
  list(),
  String.t(),
  PtcRunner.SubAgent.t(),
  map(),
  keyword()
) ::
  {:continue, map(), map()}
  | {:stop, {:error, PtcRunner.Step.t()}, map() | nil, map() | nil}

Handle validation error - retry with feedback or return error signal.

safe_to_atom(string)

@spec safe_to_atom(String.t()) :: atom() | String.t()

Safe atom conversion - try existing atom first, keep string if not found.

signature_expects_list?(arg1)

@spec signature_expects_list?(term()) :: boolean()

Check if the signature expects a list as return type.

validate_and_complete(parsed, response, agent, state, opts \\ [])

@spec validate_and_complete(
  map(),
  String.t(),
  PtcRunner.SubAgent.t(),
  map(),
  keyword()
) ::
  {:continue, map(), map()}
  | {:stop, {:ok | :error, PtcRunner.Step.t()}, map() | nil, map() | nil}

Validate parsed JSON map and complete or retry.

validate_and_complete_list(parsed_list, response, agent, state, opts \\ [])

@spec validate_and_complete_list(
  list(),
  String.t(),
  PtcRunner.SubAgent.t(),
  map(),
  keyword()
) ::
  {:continue, map(), map()}
  | {:stop, {:ok | :error, PtcRunner.Step.t()}, map() | nil, map() | nil}

Validate parsed list and complete or retry.

validate_return(map, value)

@spec validate_return(PtcRunner.SubAgent.t(), term()) :: :ok | {:error, list()}

Validate return value against signature.