msgflux 0.2.0__tar.gz → 0.3.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 (460) hide show
  1. {msgflux-0.2.0 → msgflux-0.3.0}/.pre-commit-config.yaml +2 -2
  2. {msgflux-0.2.0 → msgflux-0.3.0}/CHANGELOG.md +7 -0
  3. {msgflux-0.2.0 → msgflux-0.3.0}/PKG-INFO +1 -1
  4. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/index.md +2 -0
  5. msgflux-0.3.0/docs/anatomy/llm-as-a-verifier.md +317 -0
  6. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/chat_completion.md +85 -18
  7. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/reasoning.md +5 -6
  8. msgflux-0.3.0/docs/learn/verifiers.md +583 -0
  9. {msgflux-0.2.0 → msgflux-0.3.0}/mkdocs.yml +14 -0
  10. msgflux-0.3.0/src/msgflux/generation/verifiers/__init__.py +62 -0
  11. msgflux-0.3.0/src/msgflux/generation/verifiers/formatters.py +149 -0
  12. msgflux-0.3.0/src/msgflux/generation/verifiers/llm_as_a_verifier.py +1633 -0
  13. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/openai.py +154 -35
  14. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/openrouter.py +8 -0
  15. msgflux-0.3.0/src/msgflux/version.py +1 -0
  16. msgflux-0.3.0/tests/generation/test_verifiers.py +842 -0
  17. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/providers/test_openai.py +158 -0
  18. msgflux-0.3.0/tests/models/providers/test_openrouter.py +96 -0
  19. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/providers/test_vllm.py +30 -0
  20. msgflux-0.2.0/src/msgflux/version.py +0 -1
  21. {msgflux-0.2.0 → msgflux-0.3.0}/.github/CODEOWNERS +0 -0
  22. {msgflux-0.2.0 → msgflux-0.3.0}/.github/SECURITY.md +0 -0
  23. {msgflux-0.2.0 → msgflux-0.3.0}/.github/dependabot.yml +0 -0
  24. {msgflux-0.2.0 → msgflux-0.3.0}/.github/labeler.yml +0 -0
  25. {msgflux-0.2.0 → msgflux-0.3.0}/.github/pull_request_template.md +0 -0
  26. {msgflux-0.2.0 → msgflux-0.3.0}/.github/release-drafter.yml +0 -0
  27. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/ci.yml +0 -0
  28. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/docs.yml +0 -0
  29. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/labeler.yml +0 -0
  30. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/merge-bot.yml +0 -0
  31. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/pre-commit-autoupdate.yml +0 -0
  32. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/publish.yml +0 -0
  33. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/release-drafter.yml +0 -0
  34. {msgflux-0.2.0 → msgflux-0.3.0}/.github/workflows/validate-release.yml +0 -0
  35. {msgflux-0.2.0 → msgflux-0.3.0}/.gitignore +0 -0
  36. {msgflux-0.2.0 → msgflux-0.3.0}/.python-version +0 -0
  37. {msgflux-0.2.0 → msgflux-0.3.0}/.readthedocs.yaml +0 -0
  38. {msgflux-0.2.0 → msgflux-0.3.0}/CONTRIBUTING.md +0 -0
  39. {msgflux-0.2.0 → msgflux-0.3.0}/LICENSE +0 -0
  40. {msgflux-0.2.0 → msgflux-0.3.0}/README.md +0 -0
  41. {msgflux-0.2.0 → msgflux-0.3.0}/docs/CHANGELOG.md +0 -0
  42. {msgflux-0.2.0 → msgflux-0.3.0}/docs/CNAME +0 -0
  43. {msgflux-0.2.0 → msgflux-0.3.0}/docs/_includes/init_chat_completion_model.md +0 -0
  44. {msgflux-0.2.0 → msgflux-0.3.0}/docs/_includes/install.md +0 -0
  45. {msgflux-0.2.0 → msgflux-0.3.0}/docs/_includes/install_openai.md +0 -0
  46. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/agent.md +0 -0
  47. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/chat-schema-utils.md +0 -0
  48. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/dict-lowering-and-restoration.md +0 -0
  49. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/logical-vs-provider-schema.md +0 -0
  50. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/msgspec-transport-lowering.md +0 -0
  51. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/openai-chat-completion.md +0 -0
  52. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/react-provider-schemas.md +0 -0
  53. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/signatures.md +0 -0
  54. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/tool-flow-control.md +0 -0
  55. {msgflux-0.2.0 → msgflux-0.3.0}/docs/anatomy/tool-library.md +0 -0
  56. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/databases/database.md +0 -0
  57. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/databases/types/kv.md +0 -0
  58. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/databases/types/vector.md +0 -0
  59. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/model.md +0 -0
  60. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/model_gateway.md +0 -0
  61. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/chat_completion.md +0 -0
  62. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/image_classifier.md +0 -0
  63. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/image_embedder.md +0 -0
  64. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/image_text_to_image.md +0 -0
  65. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/moderation.md +0 -0
  66. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/speech_to_text.md +0 -0
  67. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/text_classifier.md +0 -0
  68. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/text_embedder.md +0 -0
  69. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/text_reranker.md +0 -0
  70. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/text_to_image.md +0 -0
  71. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/models/types/text_to_speech.md +0 -0
  72. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/functional.md +0 -0
  73. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/agent.md +0 -0
  74. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/module.md +0 -0
  75. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/module_dict.md +0 -0
  76. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/module_list.md +0 -0
  77. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/predictor.md +0 -0
  78. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/searcher.md +0 -0
  79. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/sequential.md +0 -0
  80. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/speaker.md +0 -0
  81. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/tool.md +0 -0
  82. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference/nn/modules/transcriber.md +0 -0
  83. {msgflux-0.2.0 → msgflux-0.3.0}/docs/api-reference.md +0 -0
  84. {msgflux-0.2.0 → msgflux-0.3.0}/docs/assets/logo-msgflux-horizon.png +0 -0
  85. {msgflux-0.2.0 → msgflux-0.3.0}/docs/assets/logo.png +0 -0
  86. {msgflux-0.2.0 → msgflux-0.3.0}/docs/assets/msgflux-wordmark.png +0 -0
  87. {msgflux-0.2.0 → msgflux-0.3.0}/docs/assets/msgflux.png +0 -0
  88. {msgflux-0.2.0 → msgflux-0.3.0}/docs/assets/tmd-mascot.png +0 -0
  89. {msgflux-0.2.0 → msgflux-0.3.0}/docs/blog/.authors.yml +0 -0
  90. {msgflux-0.2.0 → msgflux-0.3.0}/docs/blog/index.md +0 -0
  91. {msgflux-0.2.0 → msgflux-0.3.0}/docs/blog/posts/.meta.yml +0 -0
  92. {msgflux-0.2.0 → msgflux-0.3.0}/docs/blog/posts/26-04/why-msgflux-exists.md +0 -0
  93. {msgflux-0.2.0 → msgflux-0.3.0}/docs/changelog.md +0 -0
  94. {msgflux-0.2.0 → msgflux-0.3.0}/docs/dependency-management.md +0 -0
  95. {msgflux-0.2.0 → msgflux-0.3.0}/docs/hooks/copy_markdown.py +0 -0
  96. {msgflux-0.2.0 → msgflux-0.3.0}/docs/index.md +0 -0
  97. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/dotdict.md +0 -0
  98. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/inline.md +0 -0
  99. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/image_text_to_image.md +0 -0
  100. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/model.md +0 -0
  101. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/model_gateway.md +0 -0
  102. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/moderation.md +0 -0
  103. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/speech_to_text.md +0 -0
  104. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/text_classifier.md +0 -0
  105. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/text_embedder.md +0 -0
  106. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/text_reranker.md +0 -0
  107. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/text_to_image.md +0 -0
  108. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/models/text_to_speech.md +0 -0
  109. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/async.md +0 -0
  110. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/debug.md +0 -0
  111. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/generation-schemas.md +0 -0
  112. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/hooks.md +0 -0
  113. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/index.md +0 -0
  114. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/model-gateway.md +0 -0
  115. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/prefilling.md +0 -0
  116. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/quickstart.md +0 -0
  117. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/signatures.md +0 -0
  118. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/streaming.md +0 -0
  119. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/system-prompt.md +0 -0
  120. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/task-and-context.md +0 -0
  121. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/tools.md +0 -0
  122. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/agent/vars.md +0 -0
  123. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/functional.md +0 -0
  124. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/mediamaker.md +0 -0
  125. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/message.md +0 -0
  126. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/composing.md +0 -0
  127. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/core-concepts.md +0 -0
  128. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/forward-and-async.md +0 -0
  129. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/index.md +0 -0
  130. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/module-dict.md +0 -0
  131. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/module-list.md +0 -0
  132. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/sequential.md +0 -0
  133. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/module/visualization.md +0 -0
  134. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/predictor.md +0 -0
  135. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/searcher.md +0 -0
  136. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/speaker.md +0 -0
  137. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/nn/transcriber.md +0 -0
  138. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/parsers.md +0 -0
  139. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/retrievers/fuzzy.md +0 -0
  140. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/retrievers/lexical.md +0 -0
  141. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/retrievers/retriever.md +0 -0
  142. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/retrievers/web.md +0 -0
  143. {msgflux-0.2.0 → msgflux-0.3.0}/docs/learn/telemetry.md +0 -0
  144. {msgflux-0.2.0 → msgflux-0.3.0}/docs/stylesheets/extra.css +0 -0
  145. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/ad-focus-group.md +0 -0
  146. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/advisor-specialist-tool.md +0 -0
  147. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/call-transcript-analysis.md +0 -0
  148. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/deal-briefing-generator.md +0 -0
  149. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/email-auto-responder.md +0 -0
  150. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/food-delivery-assistant.md +0 -0
  151. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/index.md +0 -0
  152. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/intent-router.md +0 -0
  153. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/lead-scoring.md +0 -0
  154. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/meeting-action-items.md +0 -0
  155. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/meeting-assistant.md +0 -0
  156. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/pix-assistant.md +0 -0
  157. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/plan-tool-with-root-context.md +0 -0
  158. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/product-poster.md +0 -0
  159. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/restaurant-supply-assistant.md +0 -0
  160. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/signature-router.md +0 -0
  161. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/streaming-support-triage.md +0 -0
  162. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/support-ticket-router.md +0 -0
  163. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/visit-report.md +0 -0
  164. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/workplace-incident-reporter.md +0 -0
  165. {msgflux-0.2.0 → msgflux-0.3.0}/docs/tutorials/youtube-cut-detector.md +0 -0
  166. {msgflux-0.2.0 → msgflux-0.3.0}/examples/ad_focus_group.py +0 -0
  167. {msgflux-0.2.0 → msgflux-0.3.0}/examples/advisor_specialist_tool.py +0 -0
  168. {msgflux-0.2.0 → msgflux-0.3.0}/examples/call_transcript_analysis.py +0 -0
  169. {msgflux-0.2.0 → msgflux-0.3.0}/examples/deal_briefing_generator.py +0 -0
  170. {msgflux-0.2.0 → msgflux-0.3.0}/examples/food_delivery_assistant.py +0 -0
  171. {msgflux-0.2.0 → msgflux-0.3.0}/examples/intent-router.py +0 -0
  172. {msgflux-0.2.0 → msgflux-0.3.0}/examples/lead_scoring.py +0 -0
  173. {msgflux-0.2.0 → msgflux-0.3.0}/examples/meeting_action_items.py +0 -0
  174. {msgflux-0.2.0 → msgflux-0.3.0}/examples/meeting_assistant.py +0 -0
  175. {msgflux-0.2.0 → msgflux-0.3.0}/examples/pix_assistant.py +0 -0
  176. {msgflux-0.2.0 → msgflux-0.3.0}/examples/plan_tool_with_root_history.py +0 -0
  177. {msgflux-0.2.0 → msgflux-0.3.0}/examples/restaurant-supply-assistant.py +0 -0
  178. {msgflux-0.2.0 → msgflux-0.3.0}/examples/streaming_support_triage.py +0 -0
  179. {msgflux-0.2.0 → msgflux-0.3.0}/examples/visit_report.py +0 -0
  180. {msgflux-0.2.0 → msgflux-0.3.0}/examples/youtube_cut_detector.py +0 -0
  181. {msgflux-0.2.0 → msgflux-0.3.0}/pyproject.toml +0 -0
  182. {msgflux-0.2.0 → msgflux-0.3.0}/scripts/release.sh +0 -0
  183. {msgflux-0.2.0 → msgflux-0.3.0}/scripts/setup-branch-protection.sh +0 -0
  184. {msgflux-0.2.0 → msgflux-0.3.0}/scripts/setup-labels.sh +0 -0
  185. {msgflux-0.2.0 → msgflux-0.3.0}/scripts/svg_render.py +0 -0
  186. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/__init__.py +0 -0
  187. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/_private/__init__.py +0 -0
  188. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/_private/client.py +0 -0
  189. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/_private/core.py +0 -0
  190. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/_private/executor.py +0 -0
  191. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/_private/response.py +0 -0
  192. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/auto/__init__.py +0 -0
  193. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/auto/params.py +0 -0
  194. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/cache.py +0 -0
  195. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/core/__init__.py +0 -0
  196. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/core/dotdict.py +0 -0
  197. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/core/examples.py +0 -0
  198. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/core/message.py +0 -0
  199. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/core/registry.py +0 -0
  200. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/__init__.py +0 -0
  201. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/audio.py +0 -0
  202. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/__init__.py +0 -0
  203. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/base.py +0 -0
  204. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/db.py +0 -0
  205. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/providers/__init__.py +0 -0
  206. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/providers/cachetools.py +0 -0
  207. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/providers/diskcache.py +0 -0
  208. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/providers/faiss.py +0 -0
  209. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/registry.py +0 -0
  210. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/response.py +0 -0
  211. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/dbs/types.py +0 -0
  212. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/__init__.py +0 -0
  213. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/base.py +0 -0
  214. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/parser.py +0 -0
  215. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/__init__.py +0 -0
  216. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/csv_parser.py +0 -0
  217. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/email_parser.py +0 -0
  218. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/html_parser.py +0 -0
  219. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/openpyxl.py +0 -0
  220. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/pypdf.py +0 -0
  221. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/python_docx.py +0 -0
  222. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/providers/python_pptx.py +0 -0
  223. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/registry.py +0 -0
  224. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/response.py +0 -0
  225. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/parsers/types.py +0 -0
  226. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/__init__.py +0 -0
  227. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/base.py +0 -0
  228. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/providers/__init__.py +0 -0
  229. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/providers/bm25.py +0 -0
  230. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/providers/bm25s.py +0 -0
  231. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/providers/rank_bm25.py +0 -0
  232. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/providers/rapidfuzz.py +0 -0
  233. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/providers/wikipedia.py +0 -0
  234. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/registry.py +0 -0
  235. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/retriever.py +0 -0
  236. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/retrievers/types.py +0 -0
  237. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/types/__init__.py +0 -0
  238. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/types/audio.py +0 -0
  239. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/types/base.py +0 -0
  240. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/types/file.py +0 -0
  241. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/types/image.py +0 -0
  242. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/data/types/video.py +0 -0
  243. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/__init__.py +0 -0
  244. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/inline.py +0 -0
  245. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/signature.py +0 -0
  246. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/typed_parsers/__init__.py +0 -0
  247. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/typed_parsers/base.py +0 -0
  248. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/typed_parsers/providers/__init__.py +0 -0
  249. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/typed_parsers/providers/xml.py +0 -0
  250. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/dsl/typed_parsers/registry.py +0 -0
  251. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/envs.py +0 -0
  252. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/exceptions.py +0 -0
  253. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/__init__.py +0 -0
  254. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/control_flow.py +0 -0
  255. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/reasoning/__init__.py +0 -0
  256. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/reasoning/cot.py +0 -0
  257. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/reasoning/react.py +0 -0
  258. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/reasoning/self_consistency.py +0 -0
  259. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/generation/templates.py +0 -0
  260. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/logger.py +0 -0
  261. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/__init__.py +0 -0
  262. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/base.py +0 -0
  263. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/cache.py +0 -0
  264. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/gateway.py +0 -0
  265. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/httpx.py +0 -0
  266. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/model.py +0 -0
  267. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/profiles/__init__.py +0 -0
  268. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/profiles/base.py +0 -0
  269. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/profiles/loader.py +0 -0
  270. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/profiles/registry.py +0 -0
  271. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/__init__.py +0 -0
  272. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/cerebras.py +0 -0
  273. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/groq.py +0 -0
  274. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/imagerouter.py +0 -0
  275. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/jinaai.py +0 -0
  276. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/ollama.py +0 -0
  277. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/replicate.py +0 -0
  278. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/sambanova.py +0 -0
  279. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/together.py +0 -0
  280. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/providers/vllm.py +0 -0
  281. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/registry.py +0 -0
  282. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/response.py +0 -0
  283. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/tool_call_agg.py +0 -0
  284. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/models/types.py +0 -0
  285. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/__init__.py +0 -0
  286. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/functional.py +0 -0
  287. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/hooks/__init__.py +0 -0
  288. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/hooks/guard.py +0 -0
  289. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/hooks/hook.py +0 -0
  290. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/__init__.py +0 -0
  291. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/agent.py +0 -0
  292. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/container.py +0 -0
  293. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/embedder.py +0 -0
  294. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/generator.py +0 -0
  295. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/mediamaker.py +0 -0
  296. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/module.py +0 -0
  297. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/predictor.py +0 -0
  298. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/searcher.py +0 -0
  299. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/speaker.py +0 -0
  300. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/tool.py +0 -0
  301. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/modules/transcriber.py +0 -0
  302. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/nn/parameter.py +0 -0
  303. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/__init__.py +0 -0
  304. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/__init__.py +0 -0
  305. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/__init__.py +0 -0
  306. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/apikey.py +0 -0
  307. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/base.py +0 -0
  308. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/basic.py +0 -0
  309. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/bearer.py +0 -0
  310. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/custom.py +0 -0
  311. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/auth/oauth2.py +0 -0
  312. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/client.py +0 -0
  313. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/exceptions.py +0 -0
  314. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/integration.py +0 -0
  315. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/loglevels.py +0 -0
  316. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/transports.py +0 -0
  317. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/protocols/mcp/types.py +0 -0
  318. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/py.typed +0 -0
  319. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/telemetry/__init__.py +0 -0
  320. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/telemetry/config.py +0 -0
  321. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/telemetry/span.py +0 -0
  322. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/tools/__init__.py +0 -0
  323. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/tools/builtin/__init__.py +0 -0
  324. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/tools/builtin/web_fetch.py +0 -0
  325. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/tools/config.py +0 -0
  326. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/tools/definitions.py +0 -0
  327. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/__init__.py +0 -0
  328. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/chat.py +0 -0
  329. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/common.py +0 -0
  330. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/console.py +0 -0
  331. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/convert.py +0 -0
  332. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/encode.py +0 -0
  333. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/html.py +0 -0
  334. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/imports.py +0 -0
  335. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/inspect.py +0 -0
  336. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/logging.py +0 -0
  337. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/mermaid.py +0 -0
  338. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/msgspec.py +0 -0
  339. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/pooling.py +0 -0
  340. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/templates.py +0 -0
  341. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/tenacity.py +0 -0
  342. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/torch.py +0 -0
  343. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/validation.py +0 -0
  344. {msgflux-0.2.0 → msgflux-0.3.0}/src/msgflux/utils/xml.py +0 -0
  345. {msgflux-0.2.0 → msgflux-0.3.0}/tests/__init__.py +0 -0
  346. {msgflux-0.2.0 → msgflux-0.3.0}/tests/auto/__init__.py +0 -0
  347. {msgflux-0.2.0 → msgflux-0.3.0}/tests/auto/test_params.py +0 -0
  348. {msgflux-0.2.0 → msgflux-0.3.0}/tests/conftest.py +0 -0
  349. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/__init__.py +0 -0
  350. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/parsers/__init__.py +0 -0
  351. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/parsers/test_parsers.py +0 -0
  352. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/__init__.py +0 -0
  353. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/providers/__init__.py +0 -0
  354. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/providers/test_bm25.py +0 -0
  355. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/providers/test_bm25s.py +0 -0
  356. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/providers/test_rank_bm25.py +0 -0
  357. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/providers/test_rapidfuzz.py +0 -0
  358. {msgflux-0.2.0 → msgflux-0.3.0}/tests/data/retrievers/providers/test_wikipedia.py +0 -0
  359. {msgflux-0.2.0 → msgflux-0.3.0}/tests/dsl/test_inline.py +0 -0
  360. {msgflux-0.2.0 → msgflux-0.3.0}/tests/dsl/test_signature.py +0 -0
  361. {msgflux-0.2.0 → msgflux-0.3.0}/tests/dsl/test_typed_parsers.py +0 -0
  362. {msgflux-0.2.0 → msgflux-0.3.0}/tests/generation/__init__.py +0 -0
  363. {msgflux-0.2.0 → msgflux-0.3.0}/tests/generation/test_control_flow.py +0 -0
  364. {msgflux-0.2.0 → msgflux-0.3.0}/tests/generation/test_reasoning.py +0 -0
  365. {msgflux-0.2.0 → msgflux-0.3.0}/tests/generation/test_templates.py +0 -0
  366. {msgflux-0.2.0 → msgflux-0.3.0}/tests/integration/test_agent_reasoning.py +0 -0
  367. {msgflux-0.2.0 → msgflux-0.3.0}/tests/integration/test_guard_moderation.py +0 -0
  368. {msgflux-0.2.0 → msgflux-0.3.0}/tests/integration/test_reasoning.py +0 -0
  369. {msgflux-0.2.0 → msgflux-0.3.0}/tests/integration/test_tool_dict_e2e.py +0 -0
  370. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/__init__.py +0 -0
  371. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/providers/__init__.py +0 -0
  372. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_base.py +0 -0
  373. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_cache.py +0 -0
  374. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_gateway.py +0 -0
  375. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_httpx.py +0 -0
  376. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_model.py +0 -0
  377. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_profiles.py +0 -0
  378. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_registry.py +0 -0
  379. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_response.py +0 -0
  380. {msgflux-0.2.0 → msgflux-0.3.0}/tests/models/test_tool_call_agg.py +0 -0
  381. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/__init__.py +0 -0
  382. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/__init__.py +0 -0
  383. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_agent.py +0 -0
  384. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_container.py +0 -0
  385. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_embedder.py +0 -0
  386. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_lm.py +0 -0
  387. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_mediamaker.py +0 -0
  388. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_module.py +0 -0
  389. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_predictor.py +0 -0
  390. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_searcher.py +0 -0
  391. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_speaker.py +0 -0
  392. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_tool.py +0 -0
  393. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_tool_transport_params.py +0 -0
  394. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/modules/test_transcriber.py +0 -0
  395. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/test_functional.py +0 -0
  396. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/test_guard.py +0 -0
  397. {msgflux-0.2.0 → msgflux-0.3.0}/tests/nn/test_parameter.py +0 -0
  398. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/__init__.py +0 -0
  399. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/__init__.py +0 -0
  400. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/auth/test_auth_providers.py +0 -0
  401. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/conftest.py +0 -0
  402. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/mcp_simple_server.py +0 -0
  403. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_client.py +0 -0
  404. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_exceptions.py +0 -0
  405. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_integration.py +0 -0
  406. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_loglevels.py +0 -0
  407. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_mcp_live.py +0 -0
  408. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_toollibrary_mcp.py +0 -0
  409. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_transports.py +0 -0
  410. {msgflux-0.2.0 → msgflux-0.3.0}/tests/protocols/mcp/test_types.py +0 -0
  411. {msgflux-0.2.0 → msgflux-0.3.0}/tests/telemetry/__init__.py +0 -0
  412. {msgflux-0.2.0 → msgflux-0.3.0}/tests/telemetry/test_config.py +0 -0
  413. {msgflux-0.2.0 → msgflux-0.3.0}/tests/telemetry/test_span_agent_decorators.py +0 -0
  414. {msgflux-0.2.0 → msgflux-0.3.0}/tests/telemetry/test_span_tool_decorators.py +0 -0
  415. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_as_tool_with_signature.py +0 -0
  416. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_generation_schema.py +0 -0
  417. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_image_detail.py +0 -0
  418. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_include_date.py +0 -0
  419. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_named_kwargs.py +0 -0
  420. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_signature_annotations.py +0 -0
  421. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_agent_templates_fix.py +0 -0
  422. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_async_hooks.py +0 -0
  423. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_autoparams.py +0 -0
  424. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_data_types.py +0 -0
  425. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_dotdict.py +0 -0
  426. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_embedder.py +0 -0
  427. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_examples.py +0 -0
  428. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_image_block_kwargs_refactor.py +0 -0
  429. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_inject_message.py +0 -0
  430. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_mcp_fastmcp.py +0 -0
  431. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_registry.py +0 -0
  432. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_tool_config_decorator.py +0 -0
  433. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_tool_control.py +0 -0
  434. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_tools_visualization.py +0 -0
  435. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_type_inheritance_struct.py +0 -0
  436. {msgflux-0.2.0 → msgflux-0.3.0}/tests/test_video_block_kwargs.py +0 -0
  437. {msgflux-0.2.0 → msgflux-0.3.0}/tests/tools/__init__.py +0 -0
  438. {msgflux-0.2.0 → msgflux-0.3.0}/tests/tools/builtin/__init__.py +0 -0
  439. {msgflux-0.2.0 → msgflux-0.3.0}/tests/tools/builtin/test_web_fetch.py +0 -0
  440. {msgflux-0.2.0 → msgflux-0.3.0}/tests/tools/test_config.py +0 -0
  441. {msgflux-0.2.0 → msgflux-0.3.0}/tests/tools/test_toolflowcontrol.py +0 -0
  442. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_chat.py +0 -0
  443. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_common.py +0 -0
  444. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_console.py +0 -0
  445. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_convert.py +0 -0
  446. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_encode.py +0 -0
  447. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_hint_to_schema_dict.py +0 -0
  448. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_hooks.py +0 -0
  449. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_imports.py +0 -0
  450. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_inspect.py +0 -0
  451. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_logging.py +0 -0
  452. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_mermaid.py +0 -0
  453. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_msgspec.py +0 -0
  454. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_pooling.py +0 -0
  455. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_templates.py +0 -0
  456. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_tenacity.py +0 -0
  457. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_torch.py +0 -0
  458. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_validation.py +0 -0
  459. {msgflux-0.2.0 → msgflux-0.3.0}/tests/utils/test_xml.py +0 -0
  460. {msgflux-0.2.0 → msgflux-0.3.0}/uv.lock +0 -0
@@ -7,12 +7,12 @@ repos:
7
7
  - id: gitleaks
8
8
 
9
9
  - repo: https://github.com/astral-sh/uv-pre-commit
10
- rev: 0.11.6 # uv version.
10
+ rev: 0.11.7 # uv version.
11
11
  hooks:
12
12
  - id: uv-lock
13
13
 
14
14
  - repo: https://github.com/astral-sh/ruff-pre-commit
15
- rev: v0.15.10
15
+ rev: v0.15.11
16
16
  hooks:
17
17
  - id: ruff
18
18
  args: [--fix]
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0] - 2026-04-20
4
+
5
+ - Features: added OpenAI prompt cache retention support (#52), token logprobs metadata for chat completions (#53), and the `LLMAsVerifier` workflow with docs and examples (#54).
6
+ - Fixes: mapped OpenRouter `reasoning_max_tokens` to `extra_body.reasoning.max_tokens` and enforced the `reasoning_effort` conflict rule (#57).
7
+ - Docs: updated chat completion and agent reasoning docs to reflect the OpenRouter-only reasoning budget behavior (#56, #57).
8
+ - Maintenance: updated pre-commit hooks (#55).
9
+
3
10
  ## [0.2.0] - 2026-04-17
4
11
 
5
12
  - Features: added `provider/model-id` string shorthand support to `Agent`, `Speaker`, and `Transcriber` (#26, #27, #28), plus runtime tool controls for `Agent` (#30).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: msgflux
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Messages and Dynamic AI Systems in Python powered by pretrained models
5
5
  Project-URL: Homepage, https://github.com/msgflux/msgflux
6
6
  Project-URL: Documentation, https://github.com/msgflux/msgflux
@@ -41,3 +41,5 @@ Use this section when you need to answer questions like:
41
41
  `dict[K, V]` is encoded for strict structured outputs and restored at runtime.
42
42
  - [ReAct Provider Schemas](react-provider-schemas.md): how ReAct uses tool
43
43
  schemas to build a dynamic provider-facing response format.
44
+ - [LLM-as-a-Verifier](llm-as-a-verifier.md): how verifier prompts, concurrent
45
+ execution, score-token parsing, and weighted aggregation fit together.
@@ -0,0 +1,317 @@
1
+ # LLM-as-a-Verifier
2
+
3
+ `src/msgflux/generation/verifiers/llm_as_a_verifier.py` is the first verifier
4
+ module in msgFlux.
5
+
6
+ At a high level, it turns a verification task into a reusable runtime with four
7
+ main jobs:
8
+
9
+ - build a verifier prompt from task, criteria, candidates, and context
10
+ - request discrete score tokens from the model
11
+ - estimate a stable score from `logprobs` instead of trusting only the chosen
12
+ token
13
+ - aggregate repeated attempts and multiple criteria into a final verdict
14
+
15
+ It is not tied to `Agent`. It is a callable verification layer that can be used
16
+ from plain generation code, tool workflows, candidate reranking, or future
17
+ optimizers.
18
+
19
+ ## Mental Model
20
+
21
+ The verifier pipeline looks like this:
22
+
23
+ ```text
24
+ task + candidates + criteria
25
+ -> prompt builder
26
+ -> request batch
27
+ -> concurrent model calls
28
+ -> per-attempt evidence extraction
29
+ -> text token
30
+ -> logprob distribution
31
+ -> criterion aggregation
32
+ -> final verifier result
33
+ ```
34
+
35
+ The important part is that the verifier does not ask the model for an open-ended
36
+ score. It asks for a small discrete token from a known scale, then uses the
37
+ token distribution to estimate the final normalized score.
38
+
39
+ ## Why The Output Is A Score Token
40
+
41
+ The verifier uses a discrete score scale such as `A..T`.
42
+
43
+ That choice is deliberate:
44
+
45
+ - it keeps the scoring space bounded
46
+ - it makes the provider response easier to parse
47
+ - it makes `logprobs` directly useful
48
+ - it lets the runtime compute an expected score instead of a brittle hard label
49
+
50
+ Letters are preferred over digits for the default scale because they behave
51
+ more like single symbolic labels as granularity grows.
52
+
53
+ That matters for `logprobs` extraction:
54
+
55
+ - `A..T` is a cleaner discrete label set than `1..20`
56
+ - multi-digit numeric scales are more likely to split across tokens
57
+ - numeric labels are more likely to attach to punctuation or formatting noise
58
+ - letter labels are easier to rank, normalize, and recover from imperfect tag
59
+ formatting
60
+
61
+ So the default runtime chooses a letter-based scale not for presentation, but
62
+ for tokenization stability and better score-distribution extraction.
63
+
64
+ So the model is not asked to emit a floating-point score. It is asked to emit a
65
+ single token inside a known tag:
66
+
67
+ ```text
68
+ <score>A</score>
69
+ ```
70
+
71
+ or, in pairwise mode:
72
+
73
+ ```text
74
+ <score_A>A</score_A>
75
+ <score_B>H</score_B>
76
+ ```
77
+
78
+ `ScoreScale.letter(granularity=20)` is the public way to ask for 20 score
79
+ levels explicitly. That is also the default runtime scale.
80
+
81
+ ## Prompt Construction
82
+
83
+ `default_prompt_builder(...)` assembles the verifier prompt from
84
+ `VerificationPromptInput`.
85
+
86
+ That input contains:
87
+
88
+ - `task`
89
+ - `criterion`
90
+ - `candidates`
91
+ - `score_scale`
92
+ - optional `context`
93
+ - optional verifier-level instructions
94
+
95
+ The default builder always explains:
96
+
97
+ - the criterion being judged
98
+ - the valid score-token range
99
+ - the exact tag format expected at the end
100
+
101
+ This is why the verifier can support custom prompting without changing the rest
102
+ of the execution pipeline. The builder is only responsible for prompt text; the
103
+ runtime remains responsible for scoring and aggregation.
104
+
105
+ ## Trajectory Formatting Helpers
106
+
107
+ Benchmark-style presets work best when the candidate contains the full execution
108
+ evidence, not only the final answer.
109
+
110
+ The public API therefore exposes:
111
+
112
+ - `format_terminal_trajectory(...)`
113
+ - `format_swe_bench_trajectory(...)`
114
+
115
+ These helpers deliberately format only candidate evidence:
116
+
117
+ - summaries
118
+ - command/output steps
119
+ - metadata such as expected output
120
+ - final patch text for SWE-style runs
121
+ - final answer or final narration
122
+
123
+ The task or issue description stays outside the helper and should still be
124
+ passed through the verifier's `task` argument. That keeps the verifier API
125
+ clean: `task` carries the evaluation target, while the formatted candidate
126
+ string carries the evidence being judged.
127
+
128
+ ## Request Batching And Concurrency
129
+
130
+ The verifier builds a `VerificationRequest` for each independent
131
+ criterion/repetition pair.
132
+
133
+ That means the number of model calls in a single verification is:
134
+
135
+ ```text
136
+ len(criteria) * n_verifications
137
+ ```
138
+
139
+ Those requests are independent, so the verifier fans them out concurrently:
140
+
141
+ - `__call__` uses `F.map_gather(...)`
142
+ - `acall` uses `F.amap_gather(...)`
143
+
144
+ This matters because a verifier with multiple criteria and repeated attempts can
145
+ otherwise accumulate latency linearly.
146
+
147
+ The runtime still keeps the final result deterministic:
148
+
149
+ - requests are built in criterion order, then repetition order
150
+ - gather responses preserve input order
151
+ - attempts are regrouped per criterion after execution
152
+
153
+ So the work is concurrent, but the aggregation order remains stable.
154
+
155
+ ## Why `select_best(...)` Is Separate
156
+
157
+ `__call__` and `acall` support only one or two candidates.
158
+
159
+ That boundary is intentional:
160
+
161
+ - one candidate -> verification
162
+ - two candidates -> pairwise comparison
163
+ - more than two candidates -> tournament selection
164
+
165
+ `select_best(...)` and `aselect_best(...)` implement the tournament layer on top
166
+ of the base verifier. They run pairwise matches, accumulate wins, and use
167
+ average score as a tiebreaker.
168
+
169
+ The tournament layer can also fan out its pairwise matches concurrently. That
170
+ means a multi-candidate selection now has two concurrency layers:
171
+
172
+ - concurrent attempts inside each verifier call
173
+ - concurrent pairwise matches across the tournament
174
+
175
+ This keeps the core verifier simple instead of making `__call__` return
176
+ different shapes for different candidate counts.
177
+
178
+ ## Scoring From Logprobs
179
+
180
+ The central scoring path is:
181
+
182
+ ```text
183
+ model response
184
+ -> locate score token
185
+ -> collect chosen token + top_logprobs alternatives
186
+ -> convert logprobs to probabilities
187
+ -> compute expected value on the discrete score scale
188
+ -> normalize to [0, 1]
189
+ ```
190
+
191
+ This is why `LLMAsVerifier` always requests:
192
+
193
+ - `logprobs=True`
194
+ - `top_logprobs=<scale size or override>`
195
+
196
+ If the provider returns a good token distribution, the verifier uses that
197
+ distribution directly.
198
+
199
+ If not, and `strict_logprobs=False`, it falls back to parsing the score from the
200
+ response text.
201
+
202
+ ## Why The Parser Has Heuristics
203
+
204
+ Provider tokenization around XML-like tags is not always clean.
205
+
206
+ The verifier therefore uses a layered extraction strategy:
207
+
208
+ 1. parse the text tag if possible
209
+ 2. try to find the matching score entry directly in `logprobs`
210
+ 3. fall back to finding the expected score token near the closing tag
211
+ 4. if strict mode is disabled, fall back to text-only extraction
212
+
213
+ This is also why the parser tolerates malformed openings such as:
214
+
215
+ ```text
216
+ <20A</score>
217
+ ```
218
+
219
+ The runtime treats the text and token stream as evidence that must be reconciled,
220
+ not as perfectly formatted output.
221
+
222
+ ## Aggregation Model
223
+
224
+ There are two aggregation stages.
225
+
226
+ ### Attempt Aggregation
227
+
228
+ Each criterion can run multiple repetitions.
229
+
230
+ Those repeated attempts are averaged into a single score per criterion and
231
+ candidate.
232
+
233
+ ### Criterion Aggregation
234
+
235
+ Each criterion carries a weight.
236
+
237
+ The final score per candidate is the weighted average of all criterion scores.
238
+
239
+ That is what makes the verifier reusable across different presets: the
240
+ execution path stays the same while the criteria set changes.
241
+
242
+ ## Verdict Semantics
243
+
244
+ The final verdict depends on candidate count.
245
+
246
+ For a single candidate:
247
+
248
+ - `pass`
249
+ - `fail`
250
+ - `uncertain`
251
+
252
+ For two candidates:
253
+
254
+ - winner label
255
+ - `tie`
256
+
257
+ This is why `VerifierResult` exposes both:
258
+
259
+ - `verdict`
260
+ - optional `winner`
261
+
262
+ ## Verbose Mode
263
+
264
+ When `verbose=True`, the verifier stores enough information to debug prompt and
265
+ scoring behavior without rerunning the call.
266
+
267
+ Per attempt, it keeps:
268
+
269
+ - final prompt text
270
+ - raw response text
271
+ - per-candidate evidence
272
+ - extracted token probabilities
273
+
274
+ That data is exposed both in:
275
+
276
+ - `criteria_results[*].attempts[*]`
277
+ - `result.metadata["raw_outputs"]`
278
+
279
+ Tournament mode mirrors that same information in each match entry of
280
+ `TournamentResult.metadata["raw_outputs"]`.
281
+
282
+ ## Presets
283
+
284
+ The preset constructors are thin wrappers around the same runtime:
285
+
286
+ - `trajectory_analysis`
287
+ - `answer_reranking`
288
+ - `grounded_answer_verification`
289
+ - `patch_selection`
290
+ - `terminal_bench`
291
+ - `swe_bench_verified`
292
+ - `tool_trace_verification`
293
+ - `synthetic_data_filtering`
294
+
295
+ Each preset only supplies:
296
+
297
+ - a default criteria set
298
+ - optional default instructions or ground-truth notes
299
+
300
+ The runtime path stays identical.
301
+
302
+ This is important for maintenance because it means new verifier presets should
303
+ usually be data/config additions, not new execution engines.
304
+
305
+ ## Main Design Choices
306
+
307
+ The current design makes a few explicit tradeoffs:
308
+
309
+ - verifier core is independent from `Agent`
310
+ - prompt building is pluggable, scoring is centralized
311
+ - discrete score tokens are preferred over free-form numeric scores
312
+ - `logprobs` are first-class evidence
313
+ - tournament selection is built on top of pairwise verification
314
+ - verbose debugging is part of the runtime, not an external wrapper
315
+
316
+ These choices make the verifier easier to reuse for reranking, trajectory
317
+ selection, patch selection, and future optimizer integrations.
@@ -59,17 +59,20 @@ Chat completion models are stateless - they don't maintain conversation history
59
59
  reasoning_effort="medium", # "minimal", "low", "medium", "high"
60
60
  enable_thinking=True, # Enable extended model reasoning
61
61
  return_reasoning=True, # Include reasoning content in response
62
- reasoning_max_tokens=4096, # Max tokens reserved for reasoning/thinking
62
+ reasoning_max_tokens=4096, # OpenRouter only: max tokens reserved for reasoning/thinking
63
63
  reasoning_in_tool_call=True, # Preserve reasoning context across tool calls
64
64
  # --- Output ---
65
65
  modalities=["text"], # ["text"], ["audio"] or ["text", "audio"]
66
66
  audio={"voice": "alloy", "format": "mp3"}, # Audio output config
67
67
  verbosity="medium", # Response verbosity: "low", "medium", "high"
68
+ logprobs=True, # Include token logprobs in metadata
69
+ top_logprobs=2, # Return 2 alternatives per token
68
70
  parallel_tool_calls=True, # Allow model to call multiple tools in parallel
69
71
  validate_typed_parser_output=False, # Validate typed parser output with schema
70
72
  verbose=False, # Print raw output before transformation
71
73
  # --- Search ---
72
74
  web_search_options={}, # Web search config (OpenAI / OpenRouter only)
75
+ prompt_cache_retention="24h", # OpenAI only: "in_memory" or "24h"
73
76
  # --- Infrastructure ---
74
77
  base_url="https://api.openai.com/v1", # Override provider API endpoint
75
78
  context_length=128000, # Override maximum context window
@@ -837,7 +840,7 @@ msgFlux exposes five parameters that control reasoning behaviour at model initia
837
840
  | Parameter | Description | Default |
838
841
  |---|---|---|
839
842
  | `reasoning_effort` | How much reasoning to do. One of `"minimal"`, `"low"`, `"medium"`, `"high"`. | — |
840
- | `reasoning_max_tokens` | Hard cap (in tokens) on the internal thinking budget. | — |
843
+ | `reasoning_max_tokens` | OpenRouter-only hard cap (in tokens) for the internal thinking budget. Maps to `extra_body.reasoning.max_tokens` and cannot be combined with `reasoning_effort`. | — |
841
844
  | `return_reasoning` | Store the reasoning trace in `response.reasoning`. When `False`, reasoning is discarded even if the provider returns it. | `True` |
842
845
  | `enable_thinking` | Activate extended model reasoning. | `False` |
843
846
  | `reasoning_in_tool_call` | Preserve reasoning context across tool calls so the model keeps its chain of thought intact. When enabled, the `ToolCallAggregator` embeds the reasoning in `<think>` tags inside the assistant message history, allowing the model to see its previous reasoning when processing tool results. | `False` |
@@ -1007,7 +1010,7 @@ Providers that keep reasoning internal (like OpenAI) still report how many token
1007
1010
 
1008
1011
  ### 12.6 **Controlling the Reasoning Budget**
1009
1012
 
1010
- `reasoning_max_tokens` caps how many tokens the model can use for internal thinking. Use it to bound latency and cost while still enabling reasoning:
1013
+ `reasoning_max_tokens` is an OpenRouter-only parameter in msgFlux. It maps to `extra_body={"reasoning": {"max_tokens": ...}}` on the OpenRouter API and cannot be combined with `reasoning_effort`.
1011
1014
 
1012
1015
  ???+ example
1013
1016
 
@@ -1015,17 +1018,17 @@ Providers that keep reasoning internal (like OpenAI) still report how many token
1015
1018
  import msgflux as mf
1016
1019
 
1017
1020
  model = mf.Model.chat_completion(
1018
- "groq/openai/gpt-oss-120b",
1019
- reasoning_effort="high",
1020
- reasoning_max_tokens=512, # Cap the thinking budget
1021
+ "openrouter/anthropic/claude-sonnet-4.5",
1022
+ reasoning_max_tokens=2000,
1021
1023
  )
1022
1024
 
1023
- response = model("Solve: if 3x + 7 = 22, what is x?")
1024
- print(response.consume_reasoning()) # Kept short by the token cap
1025
+ response = model("What's the weather like in Boston? Then recommend what to wear.")
1026
+ print(response.consume_reasoning())
1025
1027
  print(response.consume())
1026
- # x = 5
1027
1028
  ```
1028
1029
 
1030
+ OpenRouter's own API examples pass the reasoning budget inside `extra_body={"reasoning": {"max_tokens": 2000}}`; msgFlux translates the model-level `reasoning_max_tokens` parameter to that shape for you.
1031
+
1029
1032
  ### 12.7 **Streaming with Reasoning**
1030
1033
 
1031
1034
  Streaming introduces a dual-queue architecture. Content and reasoning flow through independent queues, allowing consumers to process them in parallel or sequentially.
@@ -1383,7 +1386,61 @@ if "tool_call" in model_response.response_type:
1383
1386
 
1384
1387
  The Agent reads `model_response.reasoning` to pass it downstream. If the Agent's `config["reasoning_in_response"]` is `True`, the final output is wrapped as `dotdict(answer=raw_response, reasoning=reasoning)` — this is an explicit opt-in at the Agent level, not a silent model-level behaviour.
1385
1388
 
1386
- ## 13. **Response Metadata**
1389
+ ## 13. **Token Logprobs**
1390
+
1391
+ `logprobs` and `top_logprobs` are forwarded for `openai/...` chat completion models. Providers that inherit from `OpenAIChatCompletion` but are not OpenAI do not receive these fields.
1392
+
1393
+ Use `logprobs=True` to request token log probabilities. Set `top_logprobs` to the number of alternative tokens you want returned for each generated token.
1394
+
1395
+ | Parameter | Description |
1396
+ |---|---|
1397
+ | `logprobs` | Enables token-level logprob data in the response metadata. |
1398
+ | `top_logprobs` | Number of alternative tokens returned per generated token. Use with `logprobs=True`. |
1399
+
1400
+ The returned payload is exposed in `response.metadata.logprobs` and follows OpenAI's native shape. It includes the `content` list with token entries and nested `top_logprobs` alternatives.
1401
+
1402
+ ???+ example
1403
+
1404
+ ```python
1405
+ import msgflux as mf
1406
+
1407
+ model = mf.Model.chat_completion(
1408
+ "openai/gpt-4.1-mini",
1409
+ logprobs=True,
1410
+ top_logprobs=2,
1411
+ )
1412
+
1413
+ response = model("Hello!")
1414
+ print(response.metadata.logprobs["content"][0]["token"])
1415
+ print(response.metadata.logprobs["content"][0]["top_logprobs"][0]["token"])
1416
+ ```
1417
+
1418
+ ## 14. **OpenAI Prompt Caching**
1419
+
1420
+ `prompt_cache_retention` is an OpenAI-only initialization parameter. msgFlux forwards it only for `openai/...` chat completion models. OpenAI-compatible providers that inherit from `OpenAIChatCompletion` do not use it.
1421
+
1422
+ Use it when you want OpenAI to keep cached prefixes in memory or retain them for longer:
1423
+
1424
+ | Value | Behaviour |
1425
+ |---|---|
1426
+ | `"in_memory"` | Default. Keeps the cache in volatile memory for short-lived reuse. |
1427
+ | `"24h"` | Extended retention. Keeps cached prefixes available for longer. |
1428
+
1429
+ ???+ example
1430
+
1431
+ ```python
1432
+ import msgflux as mf
1433
+
1434
+ model = mf.Model.chat_completion(
1435
+ "openai/gpt-5.1",
1436
+ prompt_cache_retention="24h",
1437
+ )
1438
+
1439
+ response = model("Summarize the attached policy.")
1440
+ print(response.consume())
1441
+ ```
1442
+
1443
+ ## 15. **Response Metadata**
1387
1444
 
1388
1445
  All responses include metadata with usage information:
1389
1446
 
@@ -1419,7 +1476,7 @@ All responses include metadata with usage information:
1419
1476
  print(f"Request cost: ${cost:.4f}")
1420
1477
  ```
1421
1478
 
1422
- ## 14. **Error Handling**
1479
+ ## 16. **Error Handling**
1423
1480
 
1424
1481
  Handle common errors gracefully:
1425
1482
 
@@ -1441,7 +1498,7 @@ Handle common errors gracefully:
1441
1498
  print(f"API error: {e}")
1442
1499
  ```
1443
1500
 
1444
- ## 15. **Model Profiles**
1501
+ ## 17. **Model Profiles**
1445
1502
 
1446
1503
  Model profiles provide metadata about capabilities, pricing, and limits from [models.dev](https://models.dev).
1447
1504
 
@@ -1507,11 +1564,11 @@ Every initialized model exposes a `.profile` property that returns this metadata
1507
1564
  print(f"Estimated cost: ${cost:.4f}")
1508
1565
  ```
1509
1566
 
1510
- ## 16. **Adding a Custom Provider**
1567
+ ## 18. **Adding a Custom Provider**
1511
1568
 
1512
1569
  If the service you want to use exposes an **OpenAI-compatible API**, you can add it as a provider by subclassing `OpenAIChatCompletion`. The process has two stages depending on how compatible the endpoint is.
1513
1570
 
1514
- ### 16.1 **Stage 1 — URL and API key only**
1571
+ ### 18.1 **Stage 1 — URL and API key only**
1515
1572
 
1516
1573
  When the target API is fully OpenAI-compatible and only requires a different base URL and authentication key, the entire subclass is a small configuration mixin plus the `@register_model` decorator.
1517
1574
 
@@ -1555,7 +1612,7 @@ After registering, the model is available through the standard factory. The stri
1555
1612
  print(response.consume())
1556
1613
  ```
1557
1614
 
1558
- ### 16.2 **Stage 2 — Adapting parameters**
1615
+ ### 18.2 **Stage 2 — Adapting parameters**
1559
1616
 
1560
1617
  Some providers are mostly OpenAI-compatible but have small differences: renamed fields, required extra headers, or unsupported parameters. Override `_adapt_params` to transform the parameter dict before it reaches the API.
1561
1618
 
@@ -1598,12 +1655,22 @@ The built-in OpenRouter provider is a real-world example:
1598
1655
  if params["tool_choice"] is None:
1599
1656
  params["tool_choice"] = "auto" if params["tools"] else "none"
1600
1657
 
1601
- # 3. Map reasoning_effort to the provider format
1658
+ # 3. Map reasoning parameters to the provider format
1602
1659
  reasoning_effort = params.pop("reasoning_effort", None)
1660
+ reasoning_max_tokens = params.pop("reasoning_max_tokens", None)
1661
+ if reasoning_effort is not None and reasoning_max_tokens is not None:
1662
+ raise ValueError(
1663
+ "`reasoning_max_tokens` cannot be used together with "
1664
+ "`reasoning_effort` for OpenRouter."
1665
+ )
1603
1666
  if reasoning_effort is not None:
1604
1667
  extra_body = params.get("extra_body", {})
1605
1668
  extra_body["reasoning"] = {"effort": reasoning_effort}
1606
1669
  params["extra_body"] = extra_body
1670
+ if reasoning_max_tokens is not None:
1671
+ extra_body = params.get("extra_body", {})
1672
+ extra_body["reasoning"] = {"max_tokens": reasoning_max_tokens}
1673
+ params["extra_body"] = extra_body
1607
1674
 
1608
1675
  # 4. Add required headers
1609
1676
  params["extra_headers"] = {
@@ -1619,11 +1686,11 @@ Common adaptations inside `_adapt_params`:
1619
1686
  |---|---|
1620
1687
  | Provider uses `max_completion_tokens` instead of `max_tokens` | `params["max_completion_tokens"] = params.pop("max_tokens")` |
1621
1688
  | Provider rejects `tool_choice=None` | Set it explicitly to `"auto"` or `"none"` |
1622
- | Provider uses a different field for reasoning | `params.pop("reasoning_effort")` and remap into `extra_body` |
1689
+ | Provider uses a different field for reasoning | `params.pop("reasoning_effort")` or `params.pop("reasoning_max_tokens")` and remap into `extra_body` |
1623
1690
  | Provider requires extra headers | Add keys to `params["extra_headers"]` |
1624
1691
  | Provider accepts non-standard extensions | Add keys to `params["extra_body"]` |
1625
1692
 
1626
- ### 16.3 **Stage 3 — Using a different client**
1693
+ ### 18.3 **Stage 3 — Using a different client**
1627
1694
 
1628
1695
  The two previous stages assume the service is reached through the `openai` Python package. If you want to use a completely different HTTP client or SDK — one that is **not** the `openai` package but still exposes a compatible interface — override `_initialize` instead.
1629
1696
 
@@ -8,9 +8,9 @@ Modern language models can "think before answering" — generating an internal c
8
8
  |---|---|---|
9
9
  | **What it is** | The model's native thinking capability (e.g. `reasoning_effort="high"`) | A `generation_schema` that forces structured thinking (CoT, ReAct, SelfConsistency) |
10
10
  | **Where reasoning lives** | `response.reasoning` — a first-class field on the response object | Inside `response.consume()` — as a field of the structured output (e.g. `result.reasoning`) |
11
- | **Configured via** | Model params: `reasoning_effort`, `return_reasoning`, `reasoning_max_tokens` | Agent param: `generation_schema=ChainOfThought` |
11
+ | **Configured via** | Model params: `reasoning_effort`, `return_reasoning`, `reasoning_max_tokens` (OpenRouter only) | Agent param: `generation_schema=ChainOfThought` |
12
12
  | **Works with any model** | No — requires a reasoning-capable model (Groq gpt-oss, OpenAI o-series, etc.) | Yes — any model that supports structured output |
13
- | **Controllable budget** | Yes — `reasoning_effort` and `reasoning_max_tokens` | No — the model decides how much to write in the schema field |
13
+ | **Controllable budget** | Yes — `reasoning_effort`; OpenRouter also supports `reasoning_max_tokens` | No — the model decides how much to write in the schema field |
14
14
  | **Can combine with tools** | Yes — `reasoning_in_tool_call=True` preserves the chain across calls | Yes — ReAct is specifically designed for tool use |
15
15
 
16
16
  !!! tip
@@ -28,10 +28,9 @@ Model-level reasoning is configured at model initialization through parameters f
28
28
  import msgflux as mf
29
29
 
30
30
  model = mf.Model.chat_completion(
31
- "groq/openai/gpt-oss-120b",
32
- reasoning_effort="low", # How much to think: "minimal", "low", "medium", "high"
31
+ "openrouter/anthropic/claude-sonnet-4.5",
33
32
  return_reasoning=True, # Store the trace in response.reasoning (default: True)
34
- reasoning_max_tokens=1024, # Cap the thinking budget in tokens
33
+ reasoning_max_tokens=1024, # OpenRouter only: cap the thinking budget in tokens
35
34
  reasoning_in_tool_call=True, # Preserve reasoning across tool call rounds
36
35
  )
37
36
  ```
@@ -600,7 +599,7 @@ This is useful for debugging the relationship between the model's thinking and i
600
599
  |---|---|---|---|
601
600
  | `reasoning_effort` | `str` | — | `"minimal"`, `"low"`, `"medium"`, `"high"` |
602
601
  | `return_reasoning` | `bool` | `True` | Store reasoning in `response.reasoning` |
603
- | `reasoning_max_tokens` | `int` | — | Cap reasoning token budget |
602
+ | `reasoning_max_tokens` | `int` | — | OpenRouter-only cap on reasoning token budget |
604
603
  | `reasoning_in_tool_call` | `bool` | `False` | Embed reasoning in `<think>` tags across tool call rounds |
605
604
  | `enable_thinking` | `bool` | `False` | Provider-level switch (e.g. Anthropic) |
606
605