Module: Clacky::MessageFormat::OpenAI
- Defined in:
- lib/clacky/message_format/open_ai.rb
Overview
Static helpers for OpenAI-compatible API message format.
The canonical internal @messages format IS OpenAI format, so this module mainly handles response parsing, tool result formatting, and message type identification — minimal transformation needed.
Class Method Summary collapse
-
.build_request_body(messages, model, tools, max_tokens, caching_enabled) ⇒ Hash
Build an OpenAI-compatible request body.
-
.format_tool_results(response, tool_results) ⇒ Array<Hash>
Format tool results into canonical messages to append to @messages.
-
.parse_response(data) ⇒ Hash
Parse OpenAI-compatible API response into canonical internal format.
-
.tool_call_ids(msg) ⇒ Object
Returns the tool_call_ids referenced in a tool result message.
-
.tool_result_message?(msg) ⇒ Boolean
Returns true if the message is a canonical tool result.
Class Method Details
.build_request_body(messages, model, tools, max_tokens, caching_enabled) ⇒ Hash
Build an OpenAI-compatible request body. Canonical messages are already in OpenAI format — no conversion needed.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/clacky/message_format/open_ai.rb', line 37 def build_request_body(, model, tools, max_tokens, caching_enabled) body = { model: model, max_tokens: max_tokens, messages: } if tools&.any? if caching_enabled cached_tools = deep_clone(tools) cached_tools.last[:cache_control] = { type: "ephemeral" } body[:tools] = cached_tools else body[:tools] = tools end end body end |
.format_tool_results(response, tool_results) ⇒ Array<Hash>
Format tool results into canonical messages to append to @messages.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/clacky/message_format/open_ai.rb', line 97 def format_tool_results(response, tool_results) results_map = tool_results.each_with_object({}) { |r, h| h[r[:id]] = r } response[:tool_calls].map do |tc| result = results_map[tc[:id]] raw_content = result ? result[:content] : { error: "Tool result missing" }.to_json # OpenAI tool message content must be a String. # If a tool returned multipart Array blocks (e.g. screenshot image), convert to JSON. content = raw_content.is_a?(Array) ? JSON.generate(raw_content) : raw_content { role: "tool", tool_call_id: tc[:id], content: content } end end |
.parse_response(data) ⇒ Hash
Parse OpenAI-compatible API response into canonical internal format.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/clacky/message_format/open_ai.rb', line 58 def parse_response(data) = data["choices"].first["message"] usage = data["usage"] || {} raw_api_usage = usage.dup usage_data = { prompt_tokens: usage["prompt_tokens"], completion_tokens: usage["completion_tokens"], total_tokens: usage["total_tokens"] } usage_data[:api_cost] = usage["cost"] if usage["cost"] usage_data[:cache_creation_input_tokens] = usage["cache_creation_input_tokens"] if usage["cache_creation_input_tokens"] usage_data[:cache_read_input_tokens] = usage["cache_read_input_tokens"] if usage["cache_read_input_tokens"] # OpenRouter stores cache info under prompt_tokens_details if (details = usage["prompt_tokens_details"]) usage_data[:cache_read_input_tokens] = details["cached_tokens"] if details["cached_tokens"].to_i > 0 usage_data[:cache_creation_input_tokens] = details["cache_write_tokens"] if details["cache_write_tokens"].to_i > 0 end result = { content: ["content"], tool_calls: parse_tool_calls(["tool_calls"]), finish_reason: data["choices"].first["finish_reason"], usage: usage_data, raw_api_usage: raw_api_usage } # Preserve reasoning_content (e.g. Kimi/Moonshot extended thinking) result[:reasoning_content] = ["reasoning_content"] if ["reasoning_content"] result end |
.tool_call_ids(msg) ⇒ Object
Returns the tool_call_ids referenced in a tool result message.
21 22 23 24 25 |
# File 'lib/clacky/message_format/open_ai.rb', line 21 def tool_call_ids(msg) return [] unless (msg) [msg[:tool_call_id]] end |
.tool_result_message?(msg) ⇒ Boolean
Returns true if the message is a canonical tool result.
16 17 18 |
# File 'lib/clacky/message_format/open_ai.rb', line 16 def (msg) msg[:role] == "tool" && !msg[:tool_call_id].nil? end |