Toolnexus.Translate (toolnexus v0.12.0)

Copy Markdown View Source

Single-turn translation — the translator path (SPEC.md §11, ADR-0011).

Toolnexus.Client.translate/2 is toolnexus used as a pure wire-format translator: OpenAI shapes in, exactly ONE provider call, OpenAI shapes out. No agent loop, no tool execution, no conversation state — so a caller can run it statelessly.

It is the INBOUND half of the §5 adapters: to_openai/1/to_anthropic/1/to_gemini/1 send declarations out, this reads the provider's tool calls back in.

Use it when the CALLER owns the conversation and executes tools itself (the standard OpenAI function-calling posture). When toolnexus owns the conversation, use the agent loop with relay tools instead (§10).

This module holds the pure translation functions; the entry point itself lives on Toolnexus.Client.

Summary

Functions

Parses a tool-call arguments value into a map, tolerating both wire forms — some clients send arguments as an object rather than a JSON string.

Renders a tool-call arguments value as the JSON string the OpenAI wire format uses.

Flattens an OpenAI content value to text: the string form and the parts-array form. Non-text parts are ignored.

Maps a provider stop reason onto an OpenAI finish reason. Tool calls win: a turn that emitted any tool call is always "tool_calls" to a conforming client.

True when the message list already carries a system-ish message.

Converts an OpenAI messages list into Anthropic-native messages plus the extracted system prompt, preserving the tool structure a text flattening destroys (§11)

Maps OpenAI tool_choice onto Anthropic's shape. Returns nil for absent/"auto" (the provider default) and for anything unrecognized.

Converts an OpenAI tools list into Anthropic tool declarations. Entries that are already provider-native pass through; anything unrecognized is skipped.

Renders a result's tool calls as an OpenAI tool_calls array, ready to put on an assistant message. Convenience for assembling a response envelope.

Reads an assistant message's OpenAI tool_calls.

Functions

args_object(args)

@spec args_object(term()) :: map()

Parses a tool-call arguments value into a map, tolerating both wire forms — some clients send arguments as an object rather than a JSON string.

args_string(args)

@spec args_string(term()) :: String.t()

Renders a tool-call arguments value as the JSON string the OpenAI wire format uses.

content_text(content)

@spec content_text(term()) :: String.t()

Flattens an OpenAI content value to text: the string form and the parts-array form. Non-text parts are ignored.

finish_reason_for(bool, stop)

@spec finish_reason_for(boolean(), String.t() | nil) :: String.t()

Maps a provider stop reason onto an OpenAI finish reason. Tool calls win: a turn that emitted any tool call is always "tool_calls" to a conforming client.

has_system_message?(messages)

@spec has_system_message?([map()]) :: boolean()

True when the message list already carries a system-ish message.

openai_messages_to_anthropic(messages)

@spec openai_messages_to_anthropic([map()]) :: {[map()], String.t()}

Converts an OpenAI messages list into Anthropic-native messages plus the extracted system prompt, preserving the tool structure a text flattening destroys (§11):

  • an assistant turn's tool_calls become tool_use blocks, with arguments parsed back from its JSON string into an object;
  • a tool-role result becomes a tool_result block keyed by tool_call_id, merged into a single user turn when consecutive (providers expect one result-bearing turn answering the preceding assistant turn);
  • system/developer messages are hoisted out, since Anthropic takes system separately.

Returns {messages, system}.

openai_tool_choice_to_anthropic(choice)

@spec openai_tool_choice_to_anthropic(term()) :: map() | nil

Maps OpenAI tool_choice onto Anthropic's shape. Returns nil for absent/"auto" (the provider default) and for anything unrecognized.

openai_tools_to_anthropic(tools)

@spec openai_tools_to_anthropic([map()] | nil) :: [map()]

Converts an OpenAI tools list into Anthropic tool declarations. Entries that are already provider-native pass through; anything unrecognized is skipped.

tool_calls_json(result)

@spec tool_calls_json(Toolnexus.Translate.Result.t()) :: [map()]

Renders a result's tool calls as an OpenAI tool_calls array, ready to put on an assistant message. Convenience for assembling a response envelope.

tool_calls_of(arg1)

@spec tool_calls_of(map()) :: [Toolnexus.Translate.ToolCall.t()]

Reads an assistant message's OpenAI tool_calls.