PtcRunner.SubAgent.Loop.Shared (PtcRunner v0.12.0)

Copy Markdown View Source

Helpers shared across the loop drivers (Loop, TextMode, PtcToolCall, JsonHandler, StepAssembler).

These functions used to be copy-pasted into each driver and had begun to drift. Keeping a single definition here guarantees the drivers agree on memory accounting, error classification, final-text parsing, collected-message assembly, and schema usage metrics.

Summary

Functions

Annotate a usage map with schema-usage metrics (:schema_used and, when a schema map is present, :schema_bytes).

Build the optional collected-message list returned to callers that requested collect_messages: true. Prepends the current system prompt; returns nil when collection is disabled.

Check whether memory exceeds limit bytes.

Map a Step.fail map onto a coarse error reason atom (:parse_error, :timeout, :memory_limit, or :runtime_error).

Approximate in-memory byte size of the agent memory map.

Parse a piece of final text into a value of the expected return type.

Functions

add_schema_metrics(usage, schema)

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

Annotate a usage map with schema-usage metrics (:schema_used and, when a schema map is present, :schema_bytes).

build_collected_messages(state, messages)

@spec build_collected_messages(map(), list() | nil) :: list() | nil

Build the optional collected-message list returned to callers that requested collect_messages: true. Prepends the current system prompt; returns nil when collection is disabled.

check_memory_limit(memory, limit)

@spec check_memory_limit(map(), non_neg_integer() | nil) ::
  {:ok, non_neg_integer()} | {:error, :memory_limit_exceeded, non_neg_integer()}

Check whether memory exceeds limit bytes.

Returns {:ok, size} when within the limit (or when limit is nil), and {:error, :memory_limit_exceeded, size} when exceeded.

classify_lisp_error(map)

Map a Step.fail map onto a coarse error reason atom (:parse_error, :timeout, :memory_limit, or :runtime_error).

reason may be an atom or a string (PtcRunner.Step.fail/0 allows both). No @spec is declared on purpose: the callers pass lisp_step.fail, whose type is fail | nil, and dialyzer's success-typing narrowing constrains it to the non-nil map here — which keeps the subsequent fail.message access safe. A narrower explicit contract would break that narrowing.

memory_size(memory)

@spec memory_size(map()) :: non_neg_integer()

Approximate in-memory byte size of the agent memory map.

parse_for_type(content, arg2)

@spec parse_for_type(binary(), term()) :: {:ok, term()} | {:error, binary()}

Parse a piece of final text into a value of the expected return type.

:datetime accepts both JSON-quoted ISO-8601 ("\"2026-05-06T...\"") and a bare ISO-8601 string. All other types parse via Jason.decode/1.