Module: Clacky::MessageFormat::Anthropic
- Defined in:
- lib/clacky/message_format/anthropic.rb
Overview
Static helpers for Anthropic API message format.
Responsibilities:
- Identify Anthropic-style messages stored in @messages
- Convert internal @messages → Anthropic API request body
- Parse Anthropic API response → internal format
- Format tool results for the next turn
Internal @messages always use OpenAI-style canonical format:
assistant tool_calls: { role: "assistant", tool_calls: [{id:, function:{name:,arguments:}}] }
tool result: { role: "tool", tool_call_id:, content: }
This module converts that canonical format to Anthropic native on the way OUT, and converts Anthropic native back to canonical on the way IN.
Class Method Summary collapse
-
.build_request_body(messages, model, tools, max_tokens, caching_enabled) ⇒ Hash
Convert canonical @messages + tools into an Anthropic API request body.
-
.format_tool_results(response, tool_results) ⇒ Object
Format tool results into canonical messages to append to @messages.
-
.parse_response(data) ⇒ Hash
Parse Anthropic API response into canonical internal format.
-
.tool_result_message?(msg) ⇒ Boolean
Returns true if the message is an Anthropic-native tool result stored in NOTE: After the refactor, new tool results are stored in canonical format (role: “tool”).
-
.tool_use_ids(msg) ⇒ Object
Returns the tool_use_ids referenced in an Anthropic-native tool result message.
Class Method Details
.build_request_body(messages, model, tools, max_tokens, caching_enabled) ⇒ Hash
Convert canonical @messages + tools into an Anthropic API request body.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/clacky/message_format/anthropic.rb', line 51 def build_request_body(, model, tools, max_tokens, caching_enabled) = .select { |m| m[:role] == "system" } = .reject { |m| m[:role] == "system" } system_text = .map { |m| extract_text(m[:content]) }.join("\n\n") = .map { |msg| (msg, caching_enabled) } api_tools = tools&.map { |t| to_api_tool(t) } if caching_enabled && api_tools&.any? api_tools.last[:cache_control] = { type: "ephemeral" } end body = { model: model, max_tokens: max_tokens, messages: } body[:system] = system_text unless system_text.empty? body[:tools] = api_tools if api_tools&.any? body end |
.format_tool_results(response, tool_results) ⇒ Object
Format tool results into canonical messages to append to @messages. Input: response (canonical, has :tool_calls), tool_results array Output: canonical messages: [{ role: “tool”, tool_call_id:, content: }]
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/clacky/message_format/anthropic.rb', line 111 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]] { role: "tool", tool_call_id: tc[:id], content: result ? result[:content] : { error: "Tool result missing" }.to_json } end end |
.parse_response(data) ⇒ Hash
Parse Anthropic API response into canonical internal format.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/clacky/message_format/anthropic.rb', line 75 def parse_response(data) blocks = data["content"] || [] usage = data["usage"] || {} content = blocks.select { |b| b["type"] == "text" }.map { |b| b["text"] }.join("") # tool_calls use canonical format (id, function: {name, arguments}) tool_calls = blocks.select { |b| b["type"] == "tool_use" }.map do |tc| args = tc["input"].is_a?(String) ? tc["input"] : tc["input"].to_json { id: tc["id"], type: "function", name: tc["name"], arguments: args } end finish_reason = case data["stop_reason"] when "end_turn" then "stop" when "tool_use" then "tool_calls" when "max_tokens" then "length" else data["stop_reason"] end usage_data = { prompt_tokens: usage["input_tokens"], completion_tokens: usage["output_tokens"], total_tokens: usage["input_tokens"].to_i + usage["output_tokens"].to_i } usage_data[:cache_read_input_tokens] = usage["cache_read_input_tokens"] if usage["cache_read_input_tokens"] usage_data[:cache_creation_input_tokens] = usage["cache_creation_input_tokens"] if usage["cache_creation_input_tokens"] { content: content, tool_calls: tool_calls, finish_reason: finish_reason, usage: usage_data, raw_api_usage: usage } end |
.tool_result_message?(msg) ⇒ Boolean
Returns true if the message is an Anthropic-native tool result stored in NOTE: After the refactor, new tool results are stored in canonical format (role: “tool”). This helper handles legacy messages that might exist in older sessions.
29 30 31 32 33 |
# File 'lib/clacky/message_format/anthropic.rb', line 29 def (msg) msg[:role] == "user" && msg[:content].is_a?(Array) && msg[:content].any? { |b| b.is_a?(Hash) && b[:type] == "tool_result" } end |
.tool_use_ids(msg) ⇒ Object
Returns the tool_use_ids referenced in an Anthropic-native tool result message.
36 37 38 39 40 |
# File 'lib/clacky/message_format/anthropic.rb', line 36 def tool_use_ids(msg) return [] unless (msg) msg[:content].select { |b| b[:type] == "tool_result" }.map { |b| b[:tool_use_id] } end |