llm-babel 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (556) hide show
  1. llm_babel-0.1.0/LICENSE +21 -0
  2. llm_babel-0.1.0/PKG-INFO +57 -0
  3. llm_babel-0.1.0/docs/pypi.md +45 -0
  4. llm_babel-0.1.0/llm_transform/__init__.py +0 -0
  5. llm_babel-0.1.0/llm_transform/capabilities.py +199 -0
  6. llm_babel-0.1.0/llm_transform/conformance.py +100 -0
  7. llm_babel-0.1.0/llm_transform/corpus/__init__.py +0 -0
  8. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_encode__empty_text_block_stripped.json +66 -0
  9. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_encode__multimodal_image_document.json +124 -0
  10. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_messages_error__authentication.json +30 -0
  11. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_messages_error__overloaded.json +30 -0
  12. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_messages_response__unknown_stop_maps_other.json +67 -0
  13. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_real__error_not_found.json +32 -0
  14. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_real__text.json +85 -0
  15. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_real__tool_call.json +100 -0
  16. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_real__tool_call_to_openai.json +109 -0
  17. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__code_execution_server_tool.json +127 -0
  18. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__context_window_exceeded.json +69 -0
  19. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__no_usage_absent.json +69 -0
  20. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__pause_turn_maps_other.json +69 -0
  21. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__pause_turn_maps_to_other.json +68 -0
  22. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__redacted_thinking_block.json +82 -0
  23. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__refusal_with_cache_usage.json +77 -0
  24. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__stop_sequence_ext.json +72 -0
  25. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__text_and_tool_use.json +74 -0
  26. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__thinking_signature_and_tool_use.json +113 -0
  27. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__web_search_citations.json +101 -0
  28. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response__web_search_server_tool.json +158 -0
  29. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response_roundtrip__text_tool.json +98 -0
  30. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_response_roundtrip__thinking_stop_tool_use.json +107 -0
  31. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__adjacent_user_and_tool_fold.json +118 -0
  32. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__all_tool_choice_none.json +88 -0
  33. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__block_cache_control.json +83 -0
  34. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__compaction_block.json +129 -0
  35. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__document_block.json +80 -0
  36. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__document_file_id.json +78 -0
  37. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__forced_tool_choice.json +112 -0
  38. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__image_url_source.json +77 -0
  39. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__multi_breakpoint_cache_control.json +159 -0
  40. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__multiblock_tool_result_content.json +139 -0
  41. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__parallel_tool_use_number_tokens.json +103 -0
  42. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__provider_ext_preserved.json +82 -0
  43. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__provider_ext_thinking_config.json +81 -0
  44. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__redacted_and_normal_thinking.json +112 -0
  45. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__redacted_thinking.json +70 -0
  46. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__server_tool_use_replay.json +137 -0
  47. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__stop_sequences_and_sampling.json +74 -0
  48. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__string_content.json +103 -0
  49. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__string_content_multiturn.json +96 -0
  50. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__system_cache_control.json +96 -0
  51. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__system_string_shorthand.json +65 -0
  52. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__thinking_and_image.json +115 -0
  53. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__tool_choice_auto.json +65 -0
  54. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__tool_choice_required.json +65 -0
  55. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__tool_result_is_error.json +97 -0
  56. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_roundtrip__web_search_provider_defined_tool.json +93 -0
  57. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__char_fragmented_tool_json.json +120 -0
  58. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__max_tokens_midblock.json +56 -0
  59. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__ping_and_empty_message.json +29 -0
  60. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__text_and_tool_call.json +113 -0
  61. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__text_only_end_turn.json +60 -0
  62. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__text_only_max_tokens.json +75 -0
  63. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__thinking_deltas_then_text.json +96 -0
  64. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__thinking_signature.json +62 -0
  65. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__thinking_then_tool_call.json +103 -0
  66. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream__unknown_stop_reason_default.json +61 -0
  67. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream_real__text.json +100 -0
  68. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_stream_real__tool_call.json +127 -0
  69. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_converse__forced_tool_choice.json +114 -0
  70. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_converse__multi_system_blocks.json +81 -0
  71. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_converse__multiturn_tool_loop.json +213 -0
  72. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_converse__system_tool_roundtrip.json +229 -0
  73. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_converse__tool_choice_none_dropped.json +93 -0
  74. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_converse__tool_result_is_error.json +120 -0
  75. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_gemini__multiturn_text.json +162 -0
  76. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_gemini__structured_system.json +97 -0
  77. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_gemini__system_tool_roundtrip.json +224 -0
  78. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_gemini_response__reasoning_signature_not_leaked.json +91 -0
  79. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_gemini_response__text.json +65 -0
  80. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai__multi_toolresult_turn.json +188 -0
  81. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai__multimodal_image_base64.json +78 -0
  82. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai__system_tool_roundtrip.json +206 -0
  83. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai__thinking_only_dropped.json +77 -0
  84. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai_error__rate_limit.json +32 -0
  85. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai_response__thinking_dropped_reasoning_kept.json +86 -0
  86. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai_response__tool.json +87 -0
  87. llm_babel-0.1.0/llm_transform/corpus/cases/anthropic_to_openai_responses__thinking_and_tool.json +165 -0
  88. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_converse_error__throttling.json +24 -0
  89. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_converse_error__validation.json +24 -0
  90. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_converse_response__unknown_stop_maps_other.json +62 -0
  91. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_docs__stop_sequence.json +70 -0
  92. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_docs__text.json +67 -0
  93. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_docs__text_to_openai.json +68 -0
  94. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_encode__empty_text_block_stripped.json +98 -0
  95. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_encode__multimodal_image_doc_video.json +126 -0
  96. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_real__cache_to_anthropic.json +76 -0
  97. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_real__cache_tokens.json +77 -0
  98. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_real__error_message_only.json +24 -0
  99. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response__cache_write_tokens.json +69 -0
  100. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response__guardrail_intervened.json +64 -0
  101. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response__max_tokens_no_model.json +63 -0
  102. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response__multi_block_text_and_two_tools.json +109 -0
  103. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response__reasoning_content.json +87 -0
  104. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response__text_and_tool.json +65 -0
  105. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response_roundtrip__guardrail_content_filter.json +72 -0
  106. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_response_roundtrip__text_tool.json +89 -0
  107. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_roundtrip__image_and_document.json +99 -0
  108. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_roundtrip__inference_full_params.json +94 -0
  109. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_roundtrip__json_tool_result_scalar.json +124 -0
  110. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_roundtrip__multiple_tool_results_one_turn.json +200 -0
  111. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_roundtrip__tool_result_error.json +115 -0
  112. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_roundtrip__video_block.json +72 -0
  113. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__content_filtered_stop.json +39 -0
  114. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__empty_text_delta.json +61 -0
  115. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__fragmented_tool_json_multi_delta.json +89 -0
  116. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__stop_only_single_event.json +26 -0
  117. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__text_and_tool.json +70 -0
  118. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__text_only_end_turn.json +36 -0
  119. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__text_then_tool_call.json +109 -0
  120. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_stream__unknown_finish_maps_other.json +36 -0
  121. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_to_anthropic_response__stop_sequence.json +65 -0
  122. llm_babel-0.1.0/llm_transform/corpus/cases/bedrock_to_openai_responses_response__reasoning_signature_not_leaked.json +93 -0
  123. llm_babel-0.1.0/llm_transform/corpus/cases/betas_anthropic__mcp_tool_only.json +35 -0
  124. llm_babel-0.1.0/llm_transform/corpus/cases/betas_anthropic__native_tool_compaction_thinking.json +51 -0
  125. llm_babel-0.1.0/llm_transform/corpus/cases/betas_anthropic__no_features.json +26 -0
  126. llm_babel-0.1.0/llm_transform/corpus/cases/cohere_docs__citations.json +92 -0
  127. llm_babel-0.1.0/llm_transform/corpus/cases/cohere_docs__text.json +76 -0
  128. llm_babel-0.1.0/llm_transform/corpus/cases/cohere_real__cached_tokens.json +78 -0
  129. llm_babel-0.1.0/llm_transform/corpus/cases/cohere_response__text_and_tool_call.json +98 -0
  130. llm_babel-0.1.0/llm_transform/corpus/cases/cohere_roundtrip__full_request.json +210 -0
  131. llm_babel-0.1.0/llm_transform/corpus/cases/cohere_stream__text_tool_call_end.json +81 -0
  132. llm_babel-0.1.0/llm_transform/corpus/cases/converse_response_to_anthropic__tool_use.json +88 -0
  133. llm_babel-0.1.0/llm_transform/corpus/cases/converse_roundtrip__document_s3_location.json +85 -0
  134. llm_babel-0.1.0/llm_transform/corpus/cases/converse_roundtrip__provider_ext_preserved.json +84 -0
  135. llm_babel-0.1.0/llm_transform/corpus/cases/converse_to_anthropic__multiturn_tool_loop.json +218 -0
  136. llm_babel-0.1.0/llm_transform/corpus/cases/converse_to_anthropic__provider_ext_guardrail.json +95 -0
  137. llm_babel-0.1.0/llm_transform/corpus/cases/converse_to_anthropic__required_tool_choice.json +100 -0
  138. llm_babel-0.1.0/llm_transform/corpus/cases/converse_to_anthropic__system_tool_roundtrip.json +203 -0
  139. llm_babel-0.1.0/llm_transform/corpus/cases/converse_to_anthropic__tool_result_error_status.json +117 -0
  140. llm_babel-0.1.0/llm_transform/corpus/cases/converse_to_gemini__system_tool_roundtrip.json +208 -0
  141. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_decode__content_as_text_chunk_array.json +57 -0
  142. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_decode__multi_turn_tool_result_name_backfill.json +116 -0
  143. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_decode__tool_choice_auto.json +47 -0
  144. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_decode__tool_choice_none.json +47 -0
  145. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_docs__text.json +75 -0
  146. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_real__reasoning.json +100 -0
  147. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_real__reasoning_to_anthropic.json +98 -0
  148. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_response__insufficient_resource.json +74 -0
  149. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_response__insufficient_system_resource_finish.json +73 -0
  150. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_response__reasoning_content.json +88 -0
  151. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_response__reasoning_content_and_cache.json +90 -0
  152. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_response__unknown_stop_maps_other.json +64 -0
  153. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_roundtrip__json_object_mode_and_tools.json +107 -0
  154. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_roundtrip__text_only_reasoning_content_response.json +92 -0
  155. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_roundtrip__tools_and_json_mode.json +178 -0
  156. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__insufficient_resource_finish.json +45 -0
  157. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__parallel_tools_after_reasoning.json +127 -0
  158. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__reasoning_before_text_no_tools.json +89 -0
  159. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__reasoning_interleaved_with_text.json +89 -0
  160. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__reasoning_only_then_stop.json +60 -0
  161. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__reasoning_text_tool.json +90 -0
  162. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream__unknown_finish_maps_other.json +43 -0
  163. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_stream_real__reasoning.json +237 -0
  164. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_to_mistral__reasoning_content_dropped_on_request.json +61 -0
  165. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_to_openai_chat_response__reasoning_content_to_reasoning.json +84 -0
  166. llm_babel-0.1.0/llm_transform/corpus/cases/deepseek_to_openai_chat_response__reasoning_field.json +110 -0
  167. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_encode__multimodal_image_document_video.json +127 -0
  168. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_encode__prepend_empty_user_when_model_first.json +105 -0
  169. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_error__resource_exhausted.json +29 -0
  170. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_real__error_not_found.json +30 -0
  171. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_real__text.json +96 -0
  172. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_real__tool_call.json +111 -0
  173. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_real__tool_call_to_anthropic.json +106 -0
  174. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__grounding_sources.json +149 -0
  175. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__image_safety_finish.json +57 -0
  176. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__malformed_function_call.json +71 -0
  177. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__recitation.json +71 -0
  178. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__safety_content_filter.json +58 -0
  179. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__text_and_tool.json +75 -0
  180. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__thought_reasoning_and_tool.json +113 -0
  181. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__thought_reasoning_part.json +85 -0
  182. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__thought_signature.json +76 -0
  183. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__two_candidates.json +107 -0
  184. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response__unknown_stop_maps_other.json +69 -0
  185. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_response_roundtrip__text_tool.json +101 -0
  186. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__function_call_no_id_name_correlated.json +159 -0
  187. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__generation_config_full_sampling_params.json +90 -0
  188. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__inline_image.json +68 -0
  189. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__multi_system_instruction_parts.json +83 -0
  190. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__provider_ext_preserved.json +84 -0
  191. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__provider_ext_safety_and_cached_content.json +89 -0
  192. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__reasoning_thought_signature.json +70 -0
  193. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__response_schema_nested.json +127 -0
  194. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__structured_output.json +93 -0
  195. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__thinking_config.json +76 -0
  196. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__tool_choice_any.json +64 -0
  197. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__tool_choice_none.json +64 -0
  198. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_roundtrip__tool_config_any_single_name_forces_tool.json +123 -0
  199. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__grounded_sources.json +99 -0
  200. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__interleaved_text_and_functioncall_one_chunk.json +69 -0
  201. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__max_tokens_finish.json +57 -0
  202. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__parallel_functioncalls_one_chunk.json +80 -0
  203. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__safety_finish_no_parts.json +33 -0
  204. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__text_and_tool.json +78 -0
  205. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__thought_then_text.json +61 -0
  206. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__thought_then_text_then_call.json +99 -0
  207. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__unknown_finish_maps_other.json +38 -0
  208. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream__unknown_finish_reason_default.json +50 -0
  209. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream_real__multi_chunk.json +119 -0
  210. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_stream_real__text.json +60 -0
  211. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_anthropic__pdf_is_a_document.json +70 -0
  212. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_anthropic__tool_config_any_multi_required.json +121 -0
  213. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_anthropic__tool_roundtrip.json +198 -0
  214. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_anthropic_error__server.json +32 -0
  215. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_anthropic_response__max_tokens_finish.json +94 -0
  216. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_anthropic_response__reasoning_signature_not_leaked.json +82 -0
  217. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_converse__tool_roundtrip.json +208 -0
  218. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_mistral__tool_roundtrip_name_to_id.json +124 -0
  219. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__audio_is_not_an_image.json +53 -0
  220. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__consecutive_user_turns_not_merged.json +136 -0
  221. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__parallel_tools_id_synth.json +213 -0
  222. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__provider_ext_dropped.json +71 -0
  223. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__response_schema_dropped_no_native.json +83 -0
  224. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__system_text.json +93 -0
  225. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai__two_parallel_calls_one_turn_id_synth.json +167 -0
  226. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai_response__parallel_tool_id_synth.json +113 -0
  227. llm_babel-0.1.0/llm_transform/corpus/cases/gemini_to_openai_responses__multiturn_image.json +111 -0
  228. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__empty_string_arguments_becomes_empty_obj.json +105 -0
  229. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__image_url_bare_string_form.json +70 -0
  230. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__json_schema_response_format.json +99 -0
  231. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__object_tool_arguments.json +49 -0
  232. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__object_tool_arguments_unstringified.json +110 -0
  233. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__object_tool_choice_named_function.json +90 -0
  234. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__tool_choice_any_forces_required.json +97 -0
  235. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__tool_choice_auto.json +47 -0
  236. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__tool_choice_none.json +47 -0
  237. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_decode__tool_choice_required.json +47 -0
  238. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_error__rate_limit.json +28 -0
  239. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_real__text.json +80 -0
  240. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__error_finish_reason.json +74 -0
  241. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__model_length.json +73 -0
  242. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__model_length_finish_reason.json +73 -0
  243. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__object_arguments_tool_call.json +101 -0
  244. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__thinking_chunk.json +104 -0
  245. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__tool_call.json +96 -0
  246. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_response__unknown_finish_maps_other.json +64 -0
  247. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_roundtrip__document_url.json +70 -0
  248. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_roundtrip__full_request.json +248 -0
  249. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_roundtrip__random_seed_and_safe_prompt.json +59 -0
  250. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_stream__model_length_finish.json +45 -0
  251. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_stream__text_and_tool_call.json +91 -0
  252. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_stream__text_only_stop.json +60 -0
  253. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_stream__tool_deltas_missing_index.json +79 -0
  254. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_stream__two_parallel_tool_calls_missing_index.json +93 -0
  255. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_stream__unknown_finish_and_empty.json +54 -0
  256. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_to_deepseek__seed_dropped_json_schema_downgraded.json +77 -0
  257. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_to_openai__random_seed_to_seed.json +53 -0
  258. llm_babel-0.1.0/llm_transform/corpus/cases/mistral_to_openai__tool_choice_any_becomes_required.json +78 -0
  259. llm_babel-0.1.0/llm_transform/corpus/cases/number__big_integer.json +8 -0
  260. llm_babel-0.1.0/llm_transform/corpus/cases/number__exponent.json +8 -0
  261. llm_babel-0.1.0/llm_transform/corpus/cases/number__integral_float.json +8 -0
  262. llm_babel-0.1.0/llm_transform/corpus/cases/number__large_exponent.json +8 -0
  263. llm_babel-0.1.0/llm_transform/corpus/cases/number__negative_zero.json +8 -0
  264. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_encode__multimodal_image_audio_doc.json +129 -0
  265. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_error__context_length_code.json +33 -0
  266. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_error__insufficient_quota.json +30 -0
  267. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_error__numeric_code.json +30 -0
  268. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__cerebras_llama.json +88 -0
  269. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__error_bad_param.json +34 -0
  270. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__error_not_found.json +34 -0
  271. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__error_to_anthropic.json +34 -0
  272. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__groq_llama.json +92 -0
  273. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__huggingface_r1.json +83 -0
  274. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__logprobs.json +146 -0
  275. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__openrouter.json +115 -0
  276. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__text.json +116 -0
  277. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__text_to_anthropic.json +102 -0
  278. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__tool_call.json +140 -0
  279. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__tool_call_to_anthropic.json +121 -0
  280. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_real__zai_glm_reasoning.json +100 -0
  281. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__audio_usage.json +85 -0
  282. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__content_filter.json +74 -0
  283. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__function_call_finish_reason.json +98 -0
  284. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__parallel_tool_calls_two.json +119 -0
  285. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__reasoning_and_cache_usage.json +94 -0
  286. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__reasoning_roundtrip.json +61 -0
  287. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__refusal.json +56 -0
  288. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__three_candidates_mixed_stop.json +145 -0
  289. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__unknown_finish_reason_other.json +74 -0
  290. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__unknown_stop_maps_other.json +64 -0
  291. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_response__url_citations.json +110 -0
  292. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_roundtrip__reasoning_effort.json +51 -0
  293. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_stream__reasoning_delta.json +80 -0
  294. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_stream__unknown_finish_maps_other.json +43 -0
  295. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_stream__usage_emit.json +67 -0
  296. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_stream_real__text.json +141 -0
  297. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_stream_real__tool_call.json +253 -0
  298. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_anthropic__real_image_url.json +64 -0
  299. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_anthropic_response__content_filter_to_refusal.json +72 -0
  300. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_deepseek__reasoning_field.json +48 -0
  301. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_mistral__seed_and_tool_choice.json +57 -0
  302. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_responses__assistant_text_and_tool.json +95 -0
  303. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_responses__image.json +48 -0
  304. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_responses__parallel_tools_and_system.json +187 -0
  305. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_responses__structured_output.json +75 -0
  306. llm_babel-0.1.0/llm_transform/corpus/cases/openai_chat_to_responses__system_tool_roundtrip.json +195 -0
  307. llm_babel-0.1.0/llm_transform/corpus/cases/openai_decode__developer_role.json +56 -0
  308. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__content_filter.json +54 -0
  309. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__created_and_metadata_provider_ext.json +60 -0
  310. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__length_finish_no_usage_details.json +64 -0
  311. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__multi_choice.json +93 -0
  312. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__reasoning.json +63 -0
  313. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__reasoning_tool_and_usage.json +128 -0
  314. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response__tool_call_no_args.json +66 -0
  315. llm_babel-0.1.0/llm_transform/corpus/cases/openai_response_to_anthropic__multi_candidate_tool.json +93 -0
  316. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_error__rate_limit.json +30 -0
  317. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_real__text.json +156 -0
  318. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__empty_reasoning_summary.json +91 -0
  319. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__empty_reasoning_summary_skipped.json +100 -0
  320. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__incomplete_content_filter.json +86 -0
  321. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__multi_output_text_and_two_calls.json +134 -0
  322. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__reasoning_encrypted_content.json +91 -0
  323. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__reasoning_summary_multi_and_fc.json +117 -0
  324. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__refusal.json +49 -0
  325. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__unknown_item_skipped.json +84 -0
  326. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response__unknown_stop_maps_other.json +78 -0
  327. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response_roundtrip__incomplete_max_tokens.json +104 -0
  328. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response_roundtrip__reasoning_tool.json +116 -0
  329. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_response_roundtrip__text.json +98 -0
  330. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__assistant_text_absent_args_skip.json +109 -0
  331. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__assistant_text_then_tool_call.json +134 -0
  332. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__bare_message_easy_form.json +81 -0
  333. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__image_data_url_split.json +57 -0
  334. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__input_file_document.json +72 -0
  335. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__instructions_multiline_multisys.json +63 -0
  336. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__multimodal_image.json +67 -0
  337. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__parallel_tool_calls_two.json +173 -0
  338. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__reasoning_item_dropped_on_decode.json +93 -0
  339. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__sampling_params_full.json +54 -0
  340. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__string_input_shorthand.json +44 -0
  341. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__structured_output.json +105 -0
  342. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__structured_output_json_object.json +57 -0
  343. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__structured_output_schema_full.json +90 -0
  344. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__tool_call_empty_args.json +76 -0
  345. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__tool_flow.json +135 -0
  346. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_roundtrip__tool_result_object_output.json +107 -0
  347. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__completed_only_end_turn.json +28 -0
  348. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__incomplete_max_output_tokens.json +48 -0
  349. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__incomplete_max_tokens_meta.json +38 -0
  350. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__non_fc_item_events_ignored.json +64 -0
  351. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__reasoning.json +42 -0
  352. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__reasoning_then_text_then_tool.json +89 -0
  353. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__server_tool_web_search.json +85 -0
  354. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__text_multi_delta_then_stop.json +52 -0
  355. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__text_stop.json +76 -0
  356. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__tool_call.json +86 -0
  357. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_stream__tool_call_null_arguments.json +61 -0
  358. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_anthropic__tool_flow.json +151 -0
  359. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_anthropic_response__reasoning_and_text.json +96 -0
  360. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_anthropic_response__reasoning_tool.json +107 -0
  361. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_bedrock__tool_flow.json +164 -0
  362. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_bedrock_response__reasoning_signature_not_leaked.json +86 -0
  363. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_deepseek__bare_message.json +104 -0
  364. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_gemini__image_and_system.json +84 -0
  365. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_gemini_response__max_tokens.json +81 -0
  366. llm_babel-0.1.0/llm_transform/corpus/cases/openai_responses_to_openai_chat__tool_flow_fold.json +143 -0
  367. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__all_sampling_and_penalties.json +101 -0
  368. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__assistant_text_and_tool_call.json +89 -0
  369. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__audio.json +75 -0
  370. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__common_sampling_params.json +73 -0
  371. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__developer_and_system_both.json +70 -0
  372. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__document.json +63 -0
  373. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__file_id_document.json +72 -0
  374. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__forced_tool_choice_named.json +107 -0
  375. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__image_url_data_uri_only.json +72 -0
  376. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__multimodal_content.json +115 -0
  377. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__multimodal_image.json +71 -0
  378. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__multimodal_image_audio_file.json +115 -0
  379. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__n_gt_1.json +47 -0
  380. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__numeric_text_parts_joined.json +8 -0
  381. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__parallel_tool_calls_assistant_turn.json +150 -0
  382. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__provider_ext_preserved.json +66 -0
  383. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__provider_ext_store_user_metadata.json +67 -0
  384. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__response_format_json_object.json +52 -0
  385. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__response_format_json_schema.json +107 -0
  386. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__response_format_json_schema_strict.json +102 -0
  387. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__response_format_text.json +52 -0
  388. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__stop_string_scalar.json +47 -0
  389. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__system_content_array_cache_control.json +84 -0
  390. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__tool_call_no_args.json +82 -0
  391. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__tool_choice_none.json +78 -0
  392. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__tool_result_multimodal_string.json +121 -0
  393. llm_babel-0.1.0/llm_transform/corpus/cases/openai_roundtrip__unicode_and_supplementary_key_sort.json +110 -0
  394. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__content_filter_finish.json +60 -0
  395. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__empty_content_deltas_skipped.json +82 -0
  396. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__late_id_name_backfill.json +93 -0
  397. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__parallel_tool_calls.json +140 -0
  398. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__parallel_tool_calls_interleaved.json +131 -0
  399. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__single_finish_only.json +30 -0
  400. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__text_and_single_tool_call.json +95 -0
  401. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__text_only_stop.json +71 -0
  402. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__text_then_stop.json +71 -0
  403. llm_babel-0.1.0/llm_transform/corpus/cases/openai_stream__three_parallel_tools_interleaved.json +184 -0
  404. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__assistant_text_and_tool.json +150 -0
  405. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__empty_tool_args.json +95 -0
  406. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__file_id.json +61 -0
  407. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__image.json +73 -0
  408. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__multi_system_merge.json +75 -0
  409. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__multimodal_image.json +73 -0
  410. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__multimodal_image_base64.json +78 -0
  411. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__parallel_tools.json +104 -0
  412. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__parallel_tools_and_system.json +184 -0
  413. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__provider_ext_dropped.json +67 -0
  414. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__system_tool_roundtrip.json +214 -0
  415. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic__tool_choice_forced.json +90 -0
  416. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_anthropic_response__text.json +69 -0
  417. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_bedrock__tool_flow.json +137 -0
  418. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_converse__system_tool_roundtrip.json +227 -0
  419. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_deepseek__reasoning_prefix_tools.json +94 -0
  420. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__inline_image_base64.json +70 -0
  421. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__parallel_tools_roundtrip.json +218 -0
  422. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__sampling_params_preserved.json +61 -0
  423. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__structured_output_native.json +85 -0
  424. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__system_tool.json +169 -0
  425. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__system_tools_sampling.json +133 -0
  426. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_gemini__tool_result_roundtrip.json +195 -0
  427. llm_babel-0.1.0/llm_transform/corpus/cases/openai_to_mistral__json_object_and_penalties.json +64 -0
  428. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_anthropic__provider_ext_roundtrip.json +80 -0
  429. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_anthropic_to_gemini__system_tools.json +176 -0
  430. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_anthropic_to_openai__test_anthropic_cache_rea.json +72 -0
  431. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_anthropic_to_openai__test_anthropic_compactio.json +140 -0
  432. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_anthropic_to_openai__tools.json +79 -0
  433. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_gemini_to_anthropic__test_anthropic_server_to.json +66 -0
  434. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_gemini_to_anthropic__test_google_model_empty_.json +97 -0
  435. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_gemini_to_anthropic__tools.json +67 -0
  436. llm_babel-0.1.0/llm_transform/corpus/cases/realtraffic_openai_to_gemini__test_cerebras_disable_re.json +60 -0
  437. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__builtin_tool_kept.json +64 -0
  438. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__drop_ignored_param.json +46 -0
  439. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__drop_reasoning_for_nonreasoning_target.json +61 -0
  440. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__drop_sampling_params_for_anthropic.json +55 -0
  441. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__emulate_structured_output.json +75 -0
  442. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__error_builtin_tool_unsupported.json +42 -0
  443. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__error_image_for_deepseek.json +45 -0
  444. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__error_image_for_text_only_target.json +33 -0
  445. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__error_multiple_candidates.json +27 -0
  446. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__gemini_top_k_preserved_seed_present.json +56 -0
  447. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__keep_native_params.json +43 -0
  448. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__logprobs_error_for_deepseek_reasoner.json +58 -0
  449. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__n_float_equals_one.json +56 -0
  450. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile__structured_output_emulation_for_mistral_no_native.json +83 -0
  451. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_anthropic_audio_unsupported.json +53 -0
  452. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_anthropic_keeps_top_k_drops_openai_extras.json +74 -0
  453. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_anthropic_n_gt_one_errors.json +43 -0
  454. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_bedrock_drops_top_p_and_sampling_extras.json +73 -0
  455. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_bedrock_strips_reasoning_multiturn.json +124 -0
  456. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_deepseek_document_unsupported.json +46 -0
  457. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_deepseek_image_request_errors.json +46 -0
  458. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_deepseek_reasoner_drops_temp_toppp_errors_logprobs.json +67 -0
  459. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_deepseek_reasoner_model_override_error_and_drop_combined.json +78 -0
  460. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_deepseek_reasoning_kept_target_reasoning_true.json +79 -0
  461. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_gemini_native_structured_output_kept.json +70 -0
  462. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_mistral_drops_topk_servicetier_paralleltools_logitbias.json +72 -0
  463. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_mistral_emulate_structured_output_with_existing_tools.json +110 -0
  464. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_n_exactly_one_kept_single_candidate_target.json +57 -0
  465. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_no_params_no_response_format_minimal.json +47 -0
  466. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_openai_chat_keeps_all_native_params.json +80 -0
  467. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_openai_responses_native_structured_output_kept.json +71 -0
  468. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_provider_ext_preserved_through_reconcile.json +86 -0
  469. llm_babel-0.1.0/llm_transform/corpus/cases/reconcile_text_response_format_not_emulated.json +60 -0
  470. llm_babel-0.1.0/llm_transform/corpus/cases/request_anthropic_top_k_and_temperature_tokens.json +62 -0
  471. llm_babel-0.1.0/llm_transform/corpus/cases/request_gemini_generationconfig_number_tokens.json +66 -0
  472. llm_babel-0.1.0/llm_transform/corpus/cases/request_mistral_random_seed_and_penalty_tokens.json +58 -0
  473. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_high_precision_tool_argument_numbers.json +110 -0
  474. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_logit_bias_int_value_tokens.json +58 -0
  475. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_negative_zero_presence_penalty.json +51 -0
  476. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_seed_19_digit_integer_token.json +49 -0
  477. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_stop_and_seed_zero_token.json +52 -0
  478. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_temperature_integral_float_1_dot_0.json +51 -0
  479. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_temperature_round_trip_float_token.json +49 -0
  480. llm_babel-0.1.0/llm_transform/corpus/cases/request_openai_chat_tiny_and_huge_exponents.json +51 -0
  481. llm_babel-0.1.0/llm_transform/corpus/cases/responses_response__audio_usage.json +99 -0
  482. llm_babel-0.1.0/llm_transform/corpus/cases/responses_response__url_citations.json +115 -0
  483. llm_babel-0.1.0/llm_transform/corpus/cases/responses_response__web_search_server_tool.json +113 -0
  484. llm_babel-0.1.0/llm_transform/corpus/cases/responses_roundtrip__reasoning_effort.json +70 -0
  485. llm_babel-0.1.0/llm_transform/corpus/cases/responses_roundtrip__web_search_provider_defined_tool.json +78 -0
  486. llm_babel-0.1.0/llm_transform/corpus/runner.py +150 -0
  487. llm_babel-0.1.0/llm_transform/dsl/__init__.py +0 -0
  488. llm_babel-0.1.0/llm_transform/dsl/_pyrt.py +194 -0
  489. llm_babel-0.1.0/llm_transform/dsl/generated.py +544 -0
  490. llm_babel-0.1.0/llm_transform/dsl/interp.py +334 -0
  491. llm_babel-0.1.0/llm_transform/dsl/nodes.py +315 -0
  492. llm_babel-0.1.0/llm_transform/dsl/optimize.py +152 -0
  493. llm_babel-0.1.0/llm_transform/dsl/rt.py +178 -0
  494. llm_babel-0.1.0/llm_transform/dsl/transpile.py +372 -0
  495. llm_babel-0.1.0/llm_transform/dsl/transpile_python.py +313 -0
  496. llm_babel-0.1.0/llm_transform/dsl/transpile_rust.py +368 -0
  497. llm_babel-0.1.0/llm_transform/dsl/transpile_ts.py +358 -0
  498. llm_babel-0.1.0/llm_transform/ir.py +341 -0
  499. llm_babel-0.1.0/llm_transform/ir_build.py +181 -0
  500. llm_babel-0.1.0/llm_transform/ir_dataclasses.py +172 -0
  501. llm_babel-0.1.0/llm_transform/ir_types.py +194 -0
  502. llm_babel-0.1.0/llm_transform/media.py +76 -0
  503. llm_babel-0.1.0/llm_transform/providers/__init__.py +0 -0
  504. llm_babel-0.1.0/llm_transform/providers/_common.py +18 -0
  505. llm_babel-0.1.0/llm_transform/providers/_correlate.py +51 -0
  506. llm_babel-0.1.0/llm_transform/providers/_provider_ext.py +50 -0
  507. llm_babel-0.1.0/llm_transform/providers/anthropic_messages.py +996 -0
  508. llm_babel-0.1.0/llm_transform/providers/bedrock_converse.py +704 -0
  509. llm_babel-0.1.0/llm_transform/providers/cohere.py +464 -0
  510. llm_babel-0.1.0/llm_transform/providers/deepseek.py +653 -0
  511. llm_babel-0.1.0/llm_transform/providers/gemini.py +800 -0
  512. llm_babel-0.1.0/llm_transform/providers/mistral.py +808 -0
  513. llm_babel-0.1.0/llm_transform/providers/openai_chat.py +1083 -0
  514. llm_babel-0.1.0/llm_transform/providers/openai_responses.py +878 -0
  515. llm_babel-0.1.0/llm_transform/reasoning.py +81 -0
  516. llm_babel-0.1.0/llm_transform/reconcile.py +307 -0
  517. llm_babel-0.1.0/llm_transform/reference.py +75 -0
  518. llm_babel-0.1.0/llm_transform/registry.py +176 -0
  519. llm_babel-0.1.0/llm_transform/router.py +151 -0
  520. llm_babel-0.1.0/llm_transform/tests/__init__.py +0 -0
  521. llm_babel-0.1.0/llm_transform/tests/fixtures/compliance_corpus.json +8082 -0
  522. llm_babel-0.1.0/llm_transform/tests/fixtures/compliance_responses.json +705 -0
  523. llm_babel-0.1.0/llm_transform/tests/fixtures/pydantic_ai_gateway.json +65 -0
  524. llm_babel-0.1.0/llm_transform/tests/fixtures/pydantic_ai_realtraffic.json +686 -0
  525. llm_babel-0.1.0/llm_transform/tests/test_compliance.py +70 -0
  526. llm_babel-0.1.0/llm_transform/tests/test_conformance.py +50 -0
  527. llm_babel-0.1.0/llm_transform/tests/test_correlation.py +139 -0
  528. llm_babel-0.1.0/llm_transform/tests/test_cross_backend.py +157 -0
  529. llm_babel-0.1.0/llm_transform/tests/test_dsl_nodes.py +93 -0
  530. llm_babel-0.1.0/llm_transform/tests/test_external_pydantic_ai.py +62 -0
  531. llm_babel-0.1.0/llm_transform/tests/test_gen_capabilities_fresh.py +36 -0
  532. llm_babel-0.1.0/llm_transform/tests/test_gen_ir_types_fresh.py +39 -0
  533. llm_babel-0.1.0/llm_transform/tests/test_gen_python_fresh.py +22 -0
  534. llm_babel-0.1.0/llm_transform/tests/test_gen_router_fresh.py +34 -0
  535. llm_babel-0.1.0/llm_transform/tests/test_generate.py +39 -0
  536. llm_babel-0.1.0/llm_transform/tests/test_interp.py +281 -0
  537. llm_babel-0.1.0/llm_transform/tests/test_ir.py +71 -0
  538. llm_babel-0.1.0/llm_transform/tests/test_ir_types.py +152 -0
  539. llm_babel-0.1.0/llm_transform/tests/test_materialize.py +42 -0
  540. llm_babel-0.1.0/llm_transform/tests/test_media.py +67 -0
  541. llm_babel-0.1.0/llm_transform/tests/test_optimize.py +110 -0
  542. llm_babel-0.1.0/llm_transform/tests/test_properties.py +341 -0
  543. llm_babel-0.1.0/llm_transform/tests/test_realtraffic.py +52 -0
  544. llm_babel-0.1.0/llm_transform/tests/test_reasoning.py +45 -0
  545. llm_babel-0.1.0/llm_transform/tests/test_reconcile.py +184 -0
  546. llm_babel-0.1.0/llm_transform/tests/test_registry.py +75 -0
  547. llm_babel-0.1.0/llm_transform/tests/test_response.py +71 -0
  548. llm_babel-0.1.0/llm_transform/tests/test_router.py +145 -0
  549. llm_babel-0.1.0/llm_transform/tests/test_runtime_import.py +44 -0
  550. llm_babel-0.1.0/llm_transform/tests/test_streaming.py +74 -0
  551. llm_babel-0.1.0/llm_transform/tests/test_transpile_analysis.py +167 -0
  552. llm_babel-0.1.0/llm_transform/tests/test_transpile_python.py +67 -0
  553. llm_babel-0.1.0/llm_transform/tests/test_vertical_slice.py +39 -0
  554. llm_babel-0.1.0/llm_transform/typed.py +46 -0
  555. llm_babel-0.1.0/pyproject.toml +37 -0
  556. llm_babel-0.1.0/pyproject.toml.orig +50 -0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 - present Pydantic Services inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: llm-babel
3
+ Version: 0.1.0
4
+ Summary: One transform spec, compiled to Python/Rust/TypeScript, translating LLM requests between provider formats.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Dist: pydantic>=2 ; extra == 'validation'
8
+ Requires-Python: >=3.10
9
+ Project-URL: Repository, https://github.com/pydantic/babel
10
+ Provides-Extra: validation
11
+ Description-Content-Type: text/markdown
12
+
13
+ # llm-babel
14
+
15
+ Translate an LLM request, response, error, or stream between provider wire formats, and get the
16
+ exact same result whether it runs in Python, Rust, or TypeScript.
17
+
18
+ Every provider speaks a slightly different dialect on the wire. `llm-babel` routes everything
19
+ through one neutral intermediate representation, so a format is one decoder plus one encoder
20
+ rather than a converter per pair. The transforms are authored once as a small pure spec and
21
+ compiled to plain Python, Rust, and TypeScript, proven byte-identical against a shared golden
22
+ corpus that ships in this package.
23
+
24
+ Formats: `openai-chat`, `openai-responses`, `anthropic-messages`, `bedrock-converse`, `gemini`,
25
+ `mistral`, `deepseek`, `cohere`, plus the OpenAI-compatible providers (Groq, Cerebras, xAI,
26
+ Z.AI, OpenRouter, HuggingFace) as routes over the `openai-chat` codec.
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pip install llm-babel # the runtime: pure stdlib, no dependencies
32
+ pip install "llm-babel[validation]" # adds Pydantic for the typed, validating IR surface
33
+ ```
34
+
35
+ The import name is `llm_transform`.
36
+
37
+ ## Use
38
+
39
+ ```python
40
+ from llm_transform.registry import translate, decode, encode
41
+
42
+ translate("openai-chat", "anthropic-messages", openai_request) # source wire -> target wire
43
+ decode("gemini", gemini_request) # any wire -> IR
44
+ encode("bedrock-converse", ir) # IR -> any wire
45
+ ```
46
+
47
+ Responses, errors, and streams have the same shape of API (`translate_response`,
48
+ `translate_error`, `fold_stream`), and `reconcile` fits a request to a target's declared
49
+ capabilities before encoding.
50
+
51
+ Re-run the proof against the corpus shipped in the wheel:
52
+
53
+ ```bash
54
+ python -m llm_transform.corpus.runner
55
+ ```
56
+
57
+ The same transforms are published for TypeScript as `@pydantic/llm-babel` on npm.
@@ -0,0 +1,45 @@
1
+ # llm-babel
2
+
3
+ Translate an LLM request, response, error, or stream between provider wire formats, and get the
4
+ exact same result whether it runs in Python, Rust, or TypeScript.
5
+
6
+ Every provider speaks a slightly different dialect on the wire. `llm-babel` routes everything
7
+ through one neutral intermediate representation, so a format is one decoder plus one encoder
8
+ rather than a converter per pair. The transforms are authored once as a small pure spec and
9
+ compiled to plain Python, Rust, and TypeScript, proven byte-identical against a shared golden
10
+ corpus that ships in this package.
11
+
12
+ Formats: `openai-chat`, `openai-responses`, `anthropic-messages`, `bedrock-converse`, `gemini`,
13
+ `mistral`, `deepseek`, `cohere`, plus the OpenAI-compatible providers (Groq, Cerebras, xAI,
14
+ Z.AI, OpenRouter, HuggingFace) as routes over the `openai-chat` codec.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install llm-babel # the runtime: pure stdlib, no dependencies
20
+ pip install "llm-babel[validation]" # adds Pydantic for the typed, validating IR surface
21
+ ```
22
+
23
+ The import name is `llm_transform`.
24
+
25
+ ## Use
26
+
27
+ ```python
28
+ from llm_transform.registry import translate, decode, encode
29
+
30
+ translate("openai-chat", "anthropic-messages", openai_request) # source wire -> target wire
31
+ decode("gemini", gemini_request) # any wire -> IR
32
+ encode("bedrock-converse", ir) # IR -> any wire
33
+ ```
34
+
35
+ Responses, errors, and streams have the same shape of API (`translate_response`,
36
+ `translate_error`, `fold_stream`), and `reconcile` fits a request to a target's declared
37
+ capabilities before encoding.
38
+
39
+ Re-run the proof against the corpus shipped in the wheel:
40
+
41
+ ```bash
42
+ python -m llm_transform.corpus.runner
43
+ ```
44
+
45
+ The same transforms are published for TypeScript as `@pydantic/llm-babel` on npm.
File without changes
@@ -0,0 +1,199 @@
1
+ """Model/format capability matrix, data, not code.
2
+
3
+ The research's clearest lesson (LiteLLM's `"claude-3-7-sonnet" in model`
4
+ substring branching is its drift engine): keep per-model support facts in a data
5
+ table that *gates* transforms and reconciliation, never as inline conditionals in
6
+ the transform logic. A transform asks the matrix "does this target support X?"
7
+ and applies the drop/error/emulate policy accordingly.
8
+
9
+ Per-format defaults live in `CAPABILITIES`; per-model quirks that override a
10
+ default (e.g. DeepSeek's reasoner silently ignoring sampling params and rejecting
11
+ `logprobs`) live in `MODEL_CAPABILITIES`, and `capabilities_for(fmt, model)` prefers
12
+ a model row over the format default.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from dataclasses import dataclass, field, replace
18
+
19
+ from llm_transform.router import ROUTES
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class Capabilities:
24
+ """What a target format/model can represent. Absence -> reconcile (drop/error/emulate)."""
25
+
26
+ system_prompt: bool = True
27
+ tools: bool = True
28
+ parallel_tools: bool = True
29
+ streaming: bool = True
30
+ # Media-input support, per kind. Default True (permissive, like a modern chat model);
31
+ # reconcile fails fast on a media kind the target can't accept rather than sending a
32
+ # doomed request. Set False only where a target is known not to accept that kind.
33
+ multimodal_image: bool = True
34
+ multimodal_audio: bool = True
35
+ multimodal_document: bool = True
36
+ multimodal_video: bool = True
37
+ image_url_source: bool = True # Vertex-Anthropic: base64 only
38
+ reasoning: bool = False
39
+ prompt_caching: bool = False
40
+ structured_output_native: bool = False
41
+ multiple_candidates: bool = False # OpenAI n>1; Anthropic/Converse cannot
42
+ tool_call_ids: bool = True # Gemini has no tool-call id (matches by name)
43
+ logprobs: bool = False
44
+ max_tools: int | None = None
45
+ # provider_defined (server-side) tool ids this target can execute, web search,
46
+ # code interpreter, etc. Reconcile errors on a requested provider_defined tool whose
47
+ # id isn't listed (the target's API would reject it). Ids are provider-specific wire
48
+ # ids (`web_search_20250305`, `web_search_preview`), not a canonical taxonomy.
49
+ builtin_tools: frozenset[str] = field(default_factory=frozenset)
50
+ # params the target silently ignores (DeepSeek reasoner: temperature/top_p/penalties)
51
+ silently_ignored_params: frozenset[str] = field(default_factory=frozenset)
52
+ # params the target hard-errors on (DeepSeek reasoner: logprobs)
53
+ rejected_params: frozenset[str] = field(default_factory=frozenset)
54
+
55
+
56
+ # The per-format defaults, keyed by format name. Per-model quirks that override a
57
+ # format default live in `MODEL_CAPABILITIES` below; `capabilities_for(fmt, model)`
58
+ # prefers a model row when one exists, else falls back to this table.
59
+ CAPABILITIES: dict[str, Capabilities] = {
60
+ 'openai-chat': Capabilities(
61
+ reasoning=True,
62
+ structured_output_native=True,
63
+ multiple_candidates=True,
64
+ logprobs=True,
65
+ multimodal_video=False, # image / audio (gpt-4o-audio) / file, no video in chat completions
66
+ ),
67
+ 'anthropic-messages': Capabilities(
68
+ reasoning=True,
69
+ prompt_caching=True,
70
+ image_url_source=True,
71
+ multiple_candidates=False,
72
+ multimodal_audio=False, # image + PDF document only, no audio/video input
73
+ multimodal_video=False,
74
+ builtin_tools=frozenset({'web_search_20250305', 'memory_20250818', 'code_execution_20250522'}),
75
+ # No OpenAI-style sampling extras, reconciling to Anthropic drops them.
76
+ silently_ignored_params=frozenset({'seed', 'presence_penalty', 'frequency_penalty', 'logit_bias'}),
77
+ ),
78
+ 'bedrock-converse': Capabilities(
79
+ prompt_caching=True,
80
+ image_url_source=False, # Converse takes bytes, not image URLs
81
+ multiple_candidates=False, # Converse cannot do n>1
82
+ multimodal_audio=False, # Converse: image / document / video blocks, no audio
83
+ silently_ignored_params=frozenset({'seed', 'presence_penalty', 'frequency_penalty', 'logit_bias', 'top_p'}),
84
+ ),
85
+ 'gemini': Capabilities(
86
+ reasoning=True,
87
+ structured_output_native=True,
88
+ image_url_source=False, # inlineData is base64 bytes
89
+ multiple_candidates=True, # candidateCount > 1
90
+ tool_call_ids=False, # no tool-call id; correlated by name
91
+ ),
92
+ 'cohere': Capabilities(
93
+ reasoning=True, # v2 `thinking` content chunks
94
+ structured_output_native=True, # response_format json_object/json_schema
95
+ multiple_candidates=False, # a single `message`, no n>1
96
+ silently_ignored_params=frozenset({'logit_bias', 'service_tier', 'parallel_tool_calls'}),
97
+ ),
98
+ 'mistral': Capabilities(
99
+ structured_output_native=True, # response_format json_schema (custom structured output)
100
+ multiple_candidates=True, # `n` > 1
101
+ multimodal_audio=False, # Pixtral image + document OCR, no audio/video input
102
+ multimodal_video=False,
103
+ # Mistral has no logit_bias / service_tier / parallel_tool_calls / top_k,
104
+ # reconciling to Mistral drops them.
105
+ silently_ignored_params=frozenset({'top_k', 'logit_bias', 'service_tier', 'parallel_tool_calls'}),
106
+ ),
107
+ 'deepseek': Capabilities(
108
+ reasoning=True, # reasoner surfaces chain-of-thought in `reasoning_content`
109
+ multimodal_image=False, # text-only
110
+ multimodal_audio=False,
111
+ multimodal_document=False,
112
+ multimodal_video=False,
113
+ structured_output_native=False, # JSON mode only (json_object); schema -> emulate
114
+ multiple_candidates=False,
115
+ logprobs=True,
116
+ # No seed / logit_bias / service_tier / parallel_tool_calls / top_k on the wire.
117
+ silently_ignored_params=frozenset({'seed', 'logit_bias', 'service_tier', 'parallel_tool_calls', 'top_k'}),
118
+ ),
119
+ 'openai-responses': Capabilities(
120
+ reasoning=True, # `reasoning` output items (o-series), decoded/encoded
121
+ structured_output_native=True, # native via `text.format` (encode/decode round-trip)
122
+ prompt_caching=True, # usage.input_tokens_details.cached_tokens
123
+ multiple_candidates=False, # one `output` list, no n>1
124
+ multimodal_audio=False, # input_image + input_file, no audio/video input
125
+ multimodal_video=False,
126
+ builtin_tools=frozenset({'web_search_preview', 'file_search', 'code_interpreter'}),
127
+ ),
128
+ # --- OpenAI-compatible providers (share the openai-chat codec via router body_format) -----------
129
+ # Conservative baselines: each supports function tools + JSON structured output and hosts reasoning
130
+ # models (CoT in `reasoning`/`reasoning_content`, both now decoded by openai-chat). `n>1` and
131
+ # `logprobs` are left off (default) so reconcile fails safe rather than sending a param the target
132
+ # may reject; per-model precision (a text-only or non-reasoning model) is a MODEL_CAPABILITIES row.
133
+ 'groq': Capabilities(reasoning=True, structured_output_native=True),
134
+ 'cerebras': Capabilities(reasoning=True, structured_output_native=True),
135
+ 'xai': Capabilities(reasoning=True, structured_output_native=True, prompt_caching=True),
136
+ 'zai': Capabilities(reasoning=True, structured_output_native=True), # GLM thinking -> reasoning_content
137
+ 'openrouter': Capabilities(reasoning=True, structured_output_native=True), # aggregator; caps vary by routed model
138
+ 'huggingface': Capabilities(reasoning=True, structured_output_native=True), # HF router; caps vary by model
139
+ }
140
+
141
+
142
+ # Per-model overrides, keyed by model id. The "models explode" axis: a model that
143
+ # shares a format's wire but differs in what it accepts lands as ONE data row
144
+ # here, no transform code changes. DeepSeek's reasoner speaks the OpenAI wire but
145
+ # silently ignores sampling params and hard-errors on logprobs; that is data, not
146
+ # a `"deepseek" in model` branch (LiteLLM's drift engine).
147
+ # A model row REPLACES the format row wholesale (see `capabilities_for`), so build
148
+ # each from its format's caps with `replace(...)`, otherwise it silently reverts every
149
+ # unspecified field to the dataclass default (e.g. `multimodal_image=True`), losing the
150
+ # format's own facts (DeepSeek is text-only, JSON-mode-only, and ignores several params).
151
+ # Deployment variants (gemini-vertex -> gemini, openai-azure -> openai-chat) serve an existing
152
+ # codec's *body* at a different endpoint/auth, so their support facts ARE that codec's. Fill a caps
153
+ # row for any route whose body_format differs and lacks an explicit row of its own (the
154
+ # OpenAI-compatible providers customize theirs, so they keep their rows), instead of falling back to
155
+ # the permissive default and mis-gating reconcile. Generated to every backend via CAPABILITIES.
156
+ for _name, _route in ROUTES.items():
157
+ if _route.body_format and _route.body_format != _name and _name not in CAPABILITIES:
158
+ _codec_caps = CAPABILITIES.get(_route.body_format)
159
+ if _codec_caps is not None:
160
+ CAPABILITIES[_name] = _codec_caps
161
+
162
+
163
+ _DEEPSEEK = CAPABILITIES['deepseek']
164
+ MODEL_CAPABILITIES: dict[str, Capabilities] = {
165
+ # The reasoner additionally silently-ignores sampling params and hard-errors on
166
+ # `logprobs`; everything else (text-only, no schema, etc.) inherits the format.
167
+ 'deepseek-reasoner': replace(
168
+ _DEEPSEEK,
169
+ tools=False, # the reasoner has no function calling (per DeepSeek reasoning-model docs)
170
+ silently_ignored_params=_DEEPSEEK.silently_ignored_params | {'temperature', 'top_p'},
171
+ rejected_params=frozenset({'logprobs'}),
172
+ ),
173
+ # deepseek-chat matches the format facts (text-only, JSON-mode-only, no json_schema,
174
+ # so structured output is emulated); kept explicit for discoverability.
175
+ 'deepseek-chat': replace(_DEEPSEEK),
176
+ }
177
+
178
+
179
+ def capabilities_for(fmt: str, model: str | None = None) -> Capabilities:
180
+ """Capabilities of a translation *target*. A per-model row (if any) wins over
181
+ the format default; unknown models fall back to the format's capabilities."""
182
+ if model is not None and model in MODEL_CAPABILITIES:
183
+ return MODEL_CAPABILITIES[model]
184
+ return CAPABILITIES.get(fmt, Capabilities())
185
+
186
+
187
+ # The canonical `IRError` kinds worth retrying, the cross-library consensus (HTTP 408/409/429/≥500):
188
+ # transient rate-limit / overload / server / transport failures. Everything else (bad request, auth,
189
+ # context-length, content-filter, quota) is terminal. Lives here so it ships to every backend as data
190
+ # alongside the capability facts (`error_is_retryable`), rather than being re-hand-written per language.
191
+ RETRYABLE_ERROR_KINDS: frozenset[str] = frozenset(
192
+ {'rate_limit', 'overloaded', 'server_error', 'timeout', 'connection'}
193
+ )
194
+
195
+
196
+ def error_is_retryable(kind: str) -> bool:
197
+ """Whether a canonical error `kind` is worth retrying, a pure, total fact over
198
+ `RETRYABLE_ERROR_KINDS`. `retryable` is *derived* from `kind`, never stored on the error."""
199
+ return kind in RETRYABLE_ERROR_KINDS
@@ -0,0 +1,100 @@
1
+ """Conformance oracle, is a host's native provider mapping equivalent to babel's?
2
+
3
+ Pure and host-agnostic. Give it two wire values (a host's *native* mapper output and
4
+ babel's `encode()` output) and it reports whether they're equivalent, normalizing the
5
+ differences that are serialization *convention*, not mapping *semantics*:
6
+
7
+ - tool-call `arguments` re-serialized key-sorted (a host that forwards the raw JSON
8
+ string vs babel canonicalizing the parsed value, same object),
9
+ - optionally camelCase<->snake_case (a vendor SDK's dict types vs the REST wire).
10
+
11
+ This is the conformance wedge: a **test-only** dependency. A host, pydantic-ai,
12
+ a gateway, runs its own mapper and babel's over the same inputs and asserts
13
+ `conforms(...).identical`, catching drift in either, with zero runtime dependency and no
14
+ DSL. The oracle reports the raw structured deltas; whether a given delta is *acceptable*
15
+ (a documented valid-form / SDK-convention difference) is the host's policy to apply.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import re
22
+ from dataclasses import dataclass, field
23
+ from typing import Any
24
+
25
+ _ARG_KEYS = ('arguments', 'args') # tool-call argument payloads (values kept opaque)
26
+
27
+
28
+ def _camel_to_snake(k: str) -> str:
29
+ return re.sub(r'([A-Z])', r'_\1', k).lower()
30
+
31
+
32
+ def normalize(value: Any, *, snake_case: bool = False) -> Any:
33
+ """A canonical, comparable form of a wire `value`: tool-call `arguments`/`args`
34
+ re-serialized key-sorted, and (optionally) every structural key lowered to snake_case.
35
+ Argument *values* stay opaque, only their own serialization is canonicalized, so
36
+ user data (a tool arg `{cityName: ...}`) is never mangled."""
37
+ def walk(v: Any, *, in_args: bool = False) -> Any:
38
+ if isinstance(v, dict):
39
+ out = {}
40
+ for k, val in v.items():
41
+ key = _camel_to_snake(k) if (snake_case and not in_args) else k
42
+ if k in _ARG_KEYS and isinstance(val, str):
43
+ try:
44
+ val = json.dumps(json.loads(val), sort_keys=True)
45
+ except (ValueError, TypeError):
46
+ pass
47
+ out[key] = val
48
+ else:
49
+ out[key] = walk(val, in_args=in_args or k in _ARG_KEYS)
50
+ return out
51
+ if isinstance(v, list):
52
+ return [walk(i, in_args=in_args) for i in v]
53
+ return v
54
+
55
+ return walk(json.loads(json.dumps(value, default=str)))
56
+
57
+
58
+ @dataclass(frozen=True)
59
+ class Delta:
60
+ """One structural difference, located by a JSON-ish path."""
61
+ path: str
62
+ ours: Any
63
+ native: Any
64
+
65
+
66
+ @dataclass
67
+ class ConformanceResult:
68
+ identical: bool
69
+ deltas: list[Delta] = field(default_factory=list)
70
+
71
+ def __bool__(self) -> bool:
72
+ return self.identical
73
+
74
+
75
+ def _diff(ours: Any, native: Any, path: str, out: list[Delta]) -> None:
76
+ if isinstance(ours, dict) and isinstance(native, dict):
77
+ for k in sorted(set(ours) | set(native)):
78
+ _diff(ours.get(k, _MISSING), native.get(k, _MISSING), f'{path}.{k}' if path else k, out)
79
+ elif isinstance(ours, list) and isinstance(native, list):
80
+ if len(ours) != len(native):
81
+ out.append(Delta(f'{path}[len]', len(ours), len(native)))
82
+ for i in range(min(len(ours), len(native))):
83
+ _diff(ours[i], native[i], f'{path}[{i}]', out)
84
+ elif ours != native:
85
+ out.append(Delta(path or '<root>', ours, native))
86
+
87
+
88
+ _MISSING = object()
89
+
90
+
91
+ def conforms(ours: Any, native: Any, *, snake_case: bool = False) -> ConformanceResult:
92
+ """Compare babel's wire output (`ours`) to a native mapper's (`native`), normalizing
93
+ serialization convention. Returns `identical` plus the structured deltas that remain,
94
+ the host decides which of those are acceptable (documented valid-form / SDK deltas)."""
95
+ a, b = normalize(ours, snake_case=snake_case), normalize(native, snake_case=snake_case)
96
+ if a == b:
97
+ return ConformanceResult(identical=True)
98
+ deltas: list[Delta] = []
99
+ _diff(a, b, '', deltas)
100
+ return ConformanceResult(identical=False, deltas=deltas)
File without changes
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "anthropic_encode__empty_text_block_stripped",
3
+ "tags": [
4
+ "text",
5
+ "empty",
6
+ "filter",
7
+ "encode"
8
+ ],
9
+ "source": "anthropic-messages",
10
+ "target": "anthropic-messages",
11
+ "input_wire": {
12
+ "model": "claude-haiku-4-5",
13
+ "max_tokens": 64,
14
+ "messages": [
15
+ {
16
+ "role": "user",
17
+ "content": [
18
+ {
19
+ "type": "text",
20
+ "text": "Hello"
21
+ },
22
+ {
23
+ "type": "text",
24
+ "text": ""
25
+ }
26
+ ]
27
+ }
28
+ ]
29
+ },
30
+ "expected_ir": {
31
+ "messages": [
32
+ {
33
+ "content": [
34
+ {
35
+ "kind": "text",
36
+ "text": "Hello"
37
+ },
38
+ {
39
+ "kind": "text",
40
+ "text": ""
41
+ }
42
+ ],
43
+ "role": "user"
44
+ }
45
+ ],
46
+ "model": "claude-haiku-4-5",
47
+ "params": {
48
+ "max_tokens": 64
49
+ }
50
+ },
51
+ "expected_out_wire": {
52
+ "max_tokens": 64,
53
+ "messages": [
54
+ {
55
+ "content": [
56
+ {
57
+ "text": "Hello",
58
+ "type": "text"
59
+ }
60
+ ],
61
+ "role": "user"
62
+ }
63
+ ],
64
+ "model": "claude-haiku-4-5"
65
+ }
66
+ }
@@ -0,0 +1,124 @@
1
+ {
2
+ "name": "anthropic_encode__multimodal_image_document",
3
+ "tags": [
4
+ "anthropic",
5
+ "multimodal",
6
+ "encode",
7
+ "roundtrip"
8
+ ],
9
+ "source": "anthropic-messages",
10
+ "target": "anthropic-messages",
11
+ "input_wire": {
12
+ "max_tokens": 1024,
13
+ "messages": [
14
+ {
15
+ "content": [
16
+ {
17
+ "text": "look at these",
18
+ "type": "text"
19
+ },
20
+ {
21
+ "source": {
22
+ "data": "aW1n",
23
+ "media_type": "image/png",
24
+ "type": "base64"
25
+ },
26
+ "type": "image"
27
+ },
28
+ {
29
+ "source": {
30
+ "type": "url",
31
+ "url": "https://ex.com/a.png"
32
+ },
33
+ "type": "image"
34
+ },
35
+ {
36
+ "source": {
37
+ "data": "ZG9j",
38
+ "media_type": "application/pdf",
39
+ "type": "base64"
40
+ },
41
+ "type": "document"
42
+ }
43
+ ],
44
+ "role": "user"
45
+ }
46
+ ],
47
+ "model": "m"
48
+ },
49
+ "expected_ir": {
50
+ "messages": [
51
+ {
52
+ "content": [
53
+ {
54
+ "kind": "text",
55
+ "text": "look at these"
56
+ },
57
+ {
58
+ "data": "aW1n",
59
+ "kind": "file",
60
+ "media_kind": "image",
61
+ "media_type": "image/png",
62
+ "source": "base64"
63
+ },
64
+ {
65
+ "data": "https://ex.com/a.png",
66
+ "kind": "file",
67
+ "media_kind": "image",
68
+ "source": "url"
69
+ },
70
+ {
71
+ "data": "ZG9j",
72
+ "kind": "file",
73
+ "media_kind": "document",
74
+ "media_type": "application/pdf",
75
+ "source": "base64"
76
+ }
77
+ ],
78
+ "role": "user"
79
+ }
80
+ ],
81
+ "model": "m",
82
+ "params": {
83
+ "max_tokens": 1024
84
+ }
85
+ },
86
+ "expected_out_wire": {
87
+ "max_tokens": 1024,
88
+ "messages": [
89
+ {
90
+ "content": [
91
+ {
92
+ "text": "look at these",
93
+ "type": "text"
94
+ },
95
+ {
96
+ "source": {
97
+ "data": "aW1n",
98
+ "media_type": "image/png",
99
+ "type": "base64"
100
+ },
101
+ "type": "image"
102
+ },
103
+ {
104
+ "source": {
105
+ "type": "url",
106
+ "url": "https://ex.com/a.png"
107
+ },
108
+ "type": "image"
109
+ },
110
+ {
111
+ "source": {
112
+ "data": "ZG9j",
113
+ "media_type": "application/pdf",
114
+ "type": "base64"
115
+ },
116
+ "type": "document"
117
+ }
118
+ ],
119
+ "role": "user"
120
+ }
121
+ ],
122
+ "model": "m"
123
+ }
124
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "anthropic_messages_error__authentication",
3
+ "kind": "error",
4
+ "tags": [
5
+ "anthropic",
6
+ "error",
7
+ "auth"
8
+ ],
9
+ "source": "anthropic-messages",
10
+ "target": "anthropic-messages",
11
+ "input_wire": {
12
+ "type": "error",
13
+ "error": {
14
+ "type": "authentication_error",
15
+ "message": "invalid x-api-key"
16
+ }
17
+ },
18
+ "expected_ir": {
19
+ "kind": "authentication",
20
+ "message": "invalid x-api-key",
21
+ "provider_code": "authentication_error"
22
+ },
23
+ "expected_out_wire": {
24
+ "type": "error",
25
+ "error": {
26
+ "type": "authentication_error",
27
+ "message": "invalid x-api-key"
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "anthropic_messages_error__overloaded",
3
+ "kind": "error",
4
+ "tags": [
5
+ "anthropic",
6
+ "error",
7
+ "overloaded"
8
+ ],
9
+ "source": "anthropic-messages",
10
+ "target": "anthropic-messages",
11
+ "input_wire": {
12
+ "type": "error",
13
+ "error": {
14
+ "type": "overloaded_error",
15
+ "message": "Overloaded"
16
+ }
17
+ },
18
+ "expected_ir": {
19
+ "kind": "overloaded",
20
+ "message": "Overloaded",
21
+ "provider_code": "overloaded_error"
22
+ },
23
+ "expected_out_wire": {
24
+ "type": "error",
25
+ "error": {
26
+ "type": "overloaded_error",
27
+ "message": "Overloaded"
28
+ }
29
+ }
30
+ }