prompture 1.0.45.dev2__tar.gz → 1.0.46.dev1__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 (224) hide show
  1. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/PKG-INFO +1 -1
  2. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/_version.py +2 -2
  3. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/__init__.py +2 -0
  4. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/discovery.py +22 -7
  5. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/model_rates.py +158 -0
  6. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture.egg-info/PKG-INFO +1 -1
  7. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-driver/SKILL.md +0 -0
  8. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-driver/references/driver-template.md +0 -0
  9. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-example/SKILL.md +0 -0
  10. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-field/SKILL.md +0 -0
  11. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-persona/SKILL.md +0 -0
  12. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-test/SKILL.md +0 -0
  13. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/add-tool/SKILL.md +0 -0
  14. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/run-tests/SKILL.md +0 -0
  15. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/scaffold-extraction/SKILL.md +0 -0
  16. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.claude/skills/update-pricing/SKILL.md +0 -0
  17. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.env.copy +0 -0
  18. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/FUNDING.yml +0 -0
  19. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/scripts/update_docs_version.py +0 -0
  20. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/scripts/update_wrapper_version.py +0 -0
  21. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/workflows/dev.yml +0 -0
  22. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/workflows/documentation.yml +0 -0
  23. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/workflows/publish.yml +0 -0
  24. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.github/workflows/security.yml +0 -0
  25. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/.safety-project.ini +0 -0
  26. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/CLAUDE.md +0 -0
  27. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/CONTRIBUTING.md +0 -0
  28. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/LICENSE +0 -0
  29. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/MANIFEST.in +0 -0
  30. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/README.md +0 -0
  31. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/ROADMAP.md +0 -0
  32. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/SECURITY.md +0 -0
  33. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/dev.ps1 +0 -0
  34. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/dev.sh +0 -0
  35. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/_static/custom.css +0 -0
  36. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/_templates/footer.html +0 -0
  37. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/core.rst +0 -0
  38. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/drivers.rst +0 -0
  39. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/field_definitions.rst +0 -0
  40. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/index.rst +0 -0
  41. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/runner.rst +0 -0
  42. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/tools.rst +0 -0
  43. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/api/validator.rst +0 -0
  44. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/conf.py +0 -0
  45. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/contributing.rst +0 -0
  46. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/examples.rst +0 -0
  47. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/field_definitions_reference.rst +0 -0
  48. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/index.rst +0 -0
  49. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/installation.rst +0 -0
  50. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/quickstart.rst +0 -0
  51. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/docs/source/toon_input_guide.rst +0 -0
  52. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/mypy_errors.txt +0 -0
  53. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/README.md +0 -0
  54. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_json/README.md +0 -0
  55. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_json/llm_to_json/__init__.py +0 -0
  56. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_json/pyproject.toml +0 -0
  57. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_json/test.py +0 -0
  58. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_toon/README.md +0 -0
  59. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_toon/llm_to_toon/__init__.py +0 -0
  60. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_toon/pyproject.toml +0 -0
  61. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/packages/llm_to_toon/test.py +0 -0
  62. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/__init__.py +0 -0
  63. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/__init__.py +0 -0
  64. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/agent.py +0 -0
  65. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/async_agent.py +0 -0
  66. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/async_conversation.py +0 -0
  67. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/conversation.py +0 -0
  68. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/persona.py +0 -0
  69. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/simulated_tools.py +0 -0
  70. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/skills.py +0 -0
  71. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/tools_schema.py +0 -0
  72. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/agents/types.py +0 -0
  73. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/aio/__init__.py +0 -0
  74. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/bridges/__init__.py +0 -0
  75. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/bridges/tukuy_backend.py +0 -0
  76. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/cli/__init__.py +0 -0
  77. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/cli/cli.py +0 -0
  78. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/cli/runner.py +0 -0
  79. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/cli/server.py +0 -0
  80. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/__init__.py +0 -0
  81. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/airllm_driver.py +0 -0
  82. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_airllm_driver.py +0 -0
  83. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_azure_driver.py +0 -0
  84. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_base.py +0 -0
  85. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_cachibot_driver.py +0 -0
  86. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_claude_driver.py +0 -0
  87. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_elevenlabs_stt_driver.py +0 -0
  88. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_elevenlabs_tts_driver.py +0 -0
  89. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_embedding_base.py +0 -0
  90. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_google_driver.py +0 -0
  91. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_google_img_gen_driver.py +0 -0
  92. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_grok_driver.py +0 -0
  93. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_grok_img_gen_driver.py +0 -0
  94. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_groq_driver.py +0 -0
  95. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_hugging_driver.py +0 -0
  96. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_img_gen_base.py +0 -0
  97. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_lmstudio_driver.py +0 -0
  98. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_local_http_driver.py +0 -0
  99. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_modelscope_driver.py +0 -0
  100. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_moonshot_driver.py +0 -0
  101. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_ollama_driver.py +0 -0
  102. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_ollama_embedding_driver.py +0 -0
  103. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_openai_driver.py +0 -0
  104. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_openai_embedding_driver.py +0 -0
  105. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_openai_img_gen_driver.py +0 -0
  106. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_openai_stt_driver.py +0 -0
  107. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_openai_tts_driver.py +0 -0
  108. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_openrouter_driver.py +0 -0
  109. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_registry.py +0 -0
  110. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_stability_img_gen_driver.py +0 -0
  111. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_stt_base.py +0 -0
  112. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_tts_base.py +0 -0
  113. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/async_zai_driver.py +0 -0
  114. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/audio_registry.py +0 -0
  115. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/azure_config.py +0 -0
  116. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/azure_driver.py +0 -0
  117. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/base.py +0 -0
  118. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/cachibot_driver.py +0 -0
  119. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/claude_driver.py +0 -0
  120. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/elevenlabs_stt_driver.py +0 -0
  121. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/elevenlabs_tts_driver.py +0 -0
  122. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/embedding_base.py +0 -0
  123. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/embedding_registry.py +0 -0
  124. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/google_driver.py +0 -0
  125. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/google_img_gen_driver.py +0 -0
  126. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/grok_driver.py +0 -0
  127. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/grok_img_gen_driver.py +0 -0
  128. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/groq_driver.py +0 -0
  129. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/hugging_driver.py +0 -0
  130. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/img_gen_base.py +0 -0
  131. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/img_gen_registry.py +0 -0
  132. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/lmstudio_driver.py +0 -0
  133. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/local_http_driver.py +0 -0
  134. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/modelscope_driver.py +0 -0
  135. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/moonshot_driver.py +0 -0
  136. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/ollama_driver.py +0 -0
  137. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/ollama_embedding_driver.py +0 -0
  138. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/openai_driver.py +0 -0
  139. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/openai_embedding_driver.py +0 -0
  140. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/openai_img_gen_driver.py +0 -0
  141. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/openai_stt_driver.py +0 -0
  142. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/openai_tts_driver.py +0 -0
  143. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/openrouter_driver.py +0 -0
  144. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/registry.py +0 -0
  145. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/stability_img_gen_driver.py +0 -0
  146. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/stt_base.py +0 -0
  147. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/tts_base.py +0 -0
  148. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/vision_helpers.py +0 -0
  149. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/drivers/zai_driver.py +0 -0
  150. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/exceptions.py +0 -0
  151. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/__init__.py +0 -0
  152. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/async_core.py +0 -0
  153. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/core.py +0 -0
  154. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/fields.py +0 -0
  155. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/reasoning.py +0 -0
  156. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/tools.py +0 -0
  157. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/extraction/validator.py +0 -0
  158. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/groups/__init__.py +0 -0
  159. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/groups/async_groups.py +0 -0
  160. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/groups/consensus.py +0 -0
  161. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/groups/debate.py +0 -0
  162. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/groups/groups.py +0 -0
  163. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/groups/types.py +0 -0
  164. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/budget.py +0 -0
  165. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/cache.py +0 -0
  166. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/callbacks.py +0 -0
  167. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/cost_mixin.py +0 -0
  168. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/ledger.py +0 -0
  169. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/logging.py +0 -0
  170. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/provider_env.py +0 -0
  171. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/rates/anthropic.json +0 -0
  172. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/rates/google.json +0 -0
  173. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/rates/groq.json +0 -0
  174. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/rates/openai.json +0 -0
  175. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/rates/xai.json +0 -0
  176. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/session.py +0 -0
  177. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/settings.py +0 -0
  178. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/infra/tracker.py +0 -0
  179. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/__init__.py +0 -0
  180. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/chunking.py +0 -0
  181. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/detect.py +0 -0
  182. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/document.py +0 -0
  183. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/__init__.py +0 -0
  184. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/base.py +0 -0
  185. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/csv_parser.py +0 -0
  186. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/docx.py +0 -0
  187. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/html.py +0 -0
  188. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/markdown.py +0 -0
  189. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/pdf.py +0 -0
  190. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/ingestion/parsers/xlsx.py +0 -0
  191. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/integrations/__init__.py +0 -0
  192. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/integrations/tukuy_bridge.py +0 -0
  193. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/media/__init__.py +0 -0
  194. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/media/audio.py +0 -0
  195. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/media/image.py +0 -0
  196. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/persistence/__init__.py +0 -0
  197. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/persistence/history.py +0 -0
  198. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/persistence/serialization.py +0 -0
  199. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/persistence/store.py +0 -0
  200. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/pipeline/__init__.py +0 -0
  201. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/pipeline/pipeline.py +0 -0
  202. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/pipeline/resolver.py +0 -0
  203. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/pipeline/routing.py +0 -0
  204. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/py.typed +0 -0
  205. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/__init__.py +0 -0
  206. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/generator.py +0 -0
  207. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/Dockerfile.j2 +0 -0
  208. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/README.md.j2 +0 -0
  209. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/config.py.j2 +0 -0
  210. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/env.example.j2 +0 -0
  211. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/main.py.j2 +0 -0
  212. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/models.py.j2 +0 -0
  213. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture/scaffold/templates/requirements.txt.j2 +0 -0
  214. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture.egg-info/SOURCES.txt +0 -0
  215. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture.egg-info/dependency_links.txt +0 -0
  216. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture.egg-info/entry_points.txt +0 -0
  217. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture.egg-info/requires.txt +0 -0
  218. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture.egg-info/top_level.txt +0 -0
  219. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/prompture_cost_tracking.md +0 -0
  220. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/pyproject.toml +0 -0
  221. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/requirements.txt +0 -0
  222. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/setup.cfg +0 -0
  223. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/test.py +0 -0
  224. {prompture-1.0.45.dev2 → prompture-1.0.46.dev1}/test_version_diagnosis.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prompture
3
- Version: 1.0.45.dev2
3
+ Version: 1.0.46.dev1
4
4
  Summary: Ask LLMs to return structured JSON and run cross-model tests. API-first.
5
5
  Author-email: Juan Denis <juan@vene.co>
6
6
  License-Expression: MIT
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.0.45.dev2'
32
- __version_tuple__ = version_tuple = (1, 0, 45, 'dev2')
31
+ __version__ = version = '1.0.46.dev1'
32
+ __version_tuple__ = version_tuple = (1, 0, 46, 'dev1')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -31,6 +31,7 @@ from .model_rates import (
31
31
  ModelCapabilities,
32
32
  get_model_capabilities,
33
33
  get_model_info,
34
+ get_model_lifecycle,
34
35
  get_model_rates,
35
36
  refresh_rates_cache,
36
37
  )
@@ -69,6 +70,7 @@ __all__ = [
69
70
  "get_cache",
70
71
  "get_model_capabilities",
71
72
  "get_model_info",
73
+ "get_model_lifecycle",
72
74
  "get_model_rates",
73
75
  "get_recently_used_models",
74
76
  "get_tracker",
@@ -166,7 +166,8 @@ def get_available_models(
166
166
  return cached # type: ignore[no-any-return]
167
167
 
168
168
  logger.debug("Discovery cache miss for key=%s — querying providers", cache_key)
169
- available_models: set[str] = set()
169
+ # Maps model string → source ("api", "static", "catalog"). First source wins.
170
+ model_sources: dict[str, str] = {}
170
171
  configured_providers: set[str] = set()
171
172
  # Providers where list_models() returned an authoritative model list.
172
173
  # For these, we trust the API response and skip MODEL_PRICING / models.dev additions.
@@ -265,7 +266,9 @@ def get_available_models(
265
266
  api_succeeded = True
266
267
  api_authoritative_providers.add(provider)
267
268
  for model_id in api_models:
268
- available_models.add(f"{provider}/{model_id}")
269
+ model_str = f"{provider}/{model_id}"
270
+ if model_str not in model_sources:
271
+ model_sources[model_str] = "api"
269
272
  except Exception as e:
270
273
  logger.warning("list_models() failed for %s: %s", provider, e)
271
274
 
@@ -277,7 +280,9 @@ def get_available_models(
277
280
  for model_id in pricing:
278
281
  if model_id == "default":
279
282
  continue
280
- available_models.add(f"{provider}/{model_id}")
283
+ model_str = f"{provider}/{model_id}"
284
+ if model_str not in model_sources:
285
+ model_sources[model_str] = "static"
281
286
 
282
287
  except Exception as e:
283
288
  logger.warning(f"Error detecting models for provider {provider}: {e}")
@@ -293,9 +298,11 @@ def get_available_models(
293
298
  for prompture_name, api_name in PROVIDER_MAP.items():
294
299
  if prompture_name in configured_providers and prompture_name not in api_authoritative_providers:
295
300
  for model_id in get_all_provider_models(api_name):
296
- available_models.add(f"{prompture_name}/{model_id}")
301
+ model_str = f"{prompture_name}/{model_id}"
302
+ if model_str not in model_sources:
303
+ model_sources[model_str] = "catalog"
297
304
 
298
- sorted_models = sorted(available_models)
305
+ sorted_models = sorted(model_sources.keys())
299
306
 
300
307
  # --- verified_only filtering ---
301
308
  verified_set: set[str] | None = None
@@ -316,8 +323,8 @@ def get_available_models(
316
323
  _discovery_cache.set(cache_key, sorted_models, ttl=ttl)
317
324
  return sorted_models
318
325
 
319
- # Build enriched dicts with capabilities from models.dev
320
- from .model_rates import get_model_capabilities
326
+ # Build enriched dicts with capabilities and lifecycle from models.dev
327
+ from .model_rates import get_model_capabilities, get_model_lifecycle
321
328
 
322
329
  # Fetch all ledger stats for annotation (keyed by model_name)
323
330
  ledger_stats: dict[str, dict[str, Any]] = {}
@@ -348,12 +355,20 @@ def get_available_models(
348
355
  caps = get_model_capabilities(provider, model_id)
349
356
  caps_dict = dataclasses.asdict(caps) if caps is not None else None
350
357
 
358
+ lifecycle = get_model_lifecycle(provider, model_id)
359
+
351
360
  entry: dict[str, Any] = {
352
361
  "model": model_str,
353
362
  "provider": provider,
354
363
  "model_id": model_id,
355
364
  "capabilities": caps_dict,
365
+ "source": model_sources.get(model_str, "unknown"),
356
366
  "verified": verified_set is not None and model_str in verified_set,
367
+ "status": lifecycle.get("status") if lifecycle else None,
368
+ "family": lifecycle.get("family") if lifecycle else None,
369
+ "release_date": lifecycle.get("release_date") if lifecycle else None,
370
+ "superseded_by": lifecycle.get("superseded_by") if lifecycle else None,
371
+ "end_of_support": lifecycle.get("end_of_support") if lifecycle else None,
357
372
  }
358
373
 
359
374
  stats = ledger_stats.get(model_str)
@@ -44,6 +44,10 @@ _lock = threading.Lock()
44
44
  _data: Optional[dict[str, Any]] = None
45
45
  _loaded = False
46
46
 
47
+ # Lifecycle cache: maps models.dev provider name → {model_id: lifecycle_dict}
48
+ _lifecycle_cache: dict[str, dict[str, dict[str, Any]]] = {}
49
+ _lifecycle_lock = threading.Lock()
50
+
47
51
 
48
52
  def _get_ttl_days() -> int:
49
53
  """Get TTL from settings if available, otherwise default to 7."""
@@ -321,6 +325,9 @@ def refresh_rates_cache(force: bool = False) -> bool:
321
325
  _data = fresh
322
326
  _write_cache(fresh)
323
327
  _loaded = True
328
+ # Clear lifecycle cache so it's recomputed from fresh data
329
+ with _lifecycle_lock:
330
+ _lifecycle_cache.clear()
324
331
  return True
325
332
 
326
333
  return False
@@ -482,3 +489,154 @@ def get_model_capabilities(provider: str, model_id: str) -> Optional[ModelCapabi
482
489
 
483
490
  # models.dev unavailable — fall back to KB
484
491
  return kb_entry
492
+
493
+
494
+ # ── Model Lifecycle / Deprecation ──────────────────────────────────────────
495
+
496
+
497
+ def _compute_family_status(provider_api_name: str) -> dict[str, dict[str, Any]]:
498
+ """Compute lifecycle status for every model of a provider from models.dev data.
499
+
500
+ Groups models by ``family`` field, sorts each family by ``release_date``
501
+ descending, and assigns statuses:
502
+
503
+ - ``"current"`` — newest model in the family (or has ``"(latest)"`` marker).
504
+ - ``"legacy"`` — >6 months old with a newer sibling.
505
+ - ``"deprecated"`` — >18 months old with a newer sibling, or explicitly
506
+ marked ``status: "deprecated"`` in models.dev.
507
+
508
+ Returns a dict mapping ``model_id`` → lifecycle metadata dict with keys:
509
+ ``status``, ``family``, ``release_date``, ``superseded_by``, ``end_of_support``.
510
+ """
511
+ from datetime import timedelta
512
+
513
+ data = _ensure_loaded()
514
+ if data is None:
515
+ return {}
516
+
517
+ provider_data = data.get(provider_api_name)
518
+ if not isinstance(provider_data, dict):
519
+ return {}
520
+
521
+ models = provider_data.get("models", provider_data)
522
+ if not isinstance(models, dict):
523
+ return {}
524
+
525
+ now = datetime.now(timezone.utc)
526
+
527
+ # Build per-family lists: {family: [(model_id, entry, release_date, is_latest_marker), ...]}
528
+ families: dict[str, list[tuple[str, dict[str, Any], Optional[datetime], bool]]] = {}
529
+ for model_id, entry in models.items():
530
+ if not isinstance(entry, dict):
531
+ continue
532
+
533
+ family = entry.get("family") or _infer_family(model_id)
534
+ name = entry.get("name", "")
535
+ is_latest_marker = "(latest)" in name.lower() if name else False
536
+
537
+ release_date: Optional[datetime] = None
538
+ raw_date = entry.get("release_date")
539
+ if raw_date:
540
+ with contextlib.suppress(Exception):
541
+ release_date = datetime.fromisoformat(str(raw_date).replace("Z", "+00:00"))
542
+ if release_date.tzinfo is None:
543
+ release_date = release_date.replace(tzinfo=timezone.utc)
544
+
545
+ families.setdefault(family, []).append((model_id, entry, release_date, is_latest_marker))
546
+
547
+ result: dict[str, dict[str, Any]] = {}
548
+
549
+ for family, members in families.items():
550
+ # Sort by release_date descending (None dates go last)
551
+ members.sort(key=lambda m: m[2] or datetime.min.replace(tzinfo=timezone.utc), reverse=True)
552
+
553
+ # Identify the "current" model: explicit (latest) marker wins, else newest by date
554
+ current_idx = 0
555
+ for i, (_, _, _, is_latest) in enumerate(members):
556
+ if is_latest:
557
+ current_idx = i
558
+ break
559
+
560
+ for i, (model_id, entry, release_date, _) in enumerate(members):
561
+ # Check explicit status from models.dev
562
+ explicit_status = entry.get("status")
563
+ if isinstance(explicit_status, str) and explicit_status.lower() == "deprecated":
564
+ status = "deprecated"
565
+ elif i == current_idx:
566
+ status = "current"
567
+ elif release_date is not None:
568
+ age = now - release_date
569
+ has_newer = i > current_idx # there's a newer sibling
570
+ if has_newer and age > timedelta(days=548): # ~18 months
571
+ status = "deprecated"
572
+ elif has_newer and age > timedelta(days=183): # ~6 months
573
+ status = "legacy"
574
+ else:
575
+ status = "current"
576
+ else:
577
+ # No date info — if not the current one, mark as unknown
578
+ status = "current" if i == current_idx else "unknown"
579
+
580
+ # Compute superseded_by: next newer model in the family
581
+ superseded_by: Optional[str] = None
582
+ if i > current_idx and i > 0:
583
+ superseded_by = members[i - 1][0]
584
+
585
+ # Estimate end_of_support for legacy/deprecated: release_date + 24 months
586
+ end_of_support: Optional[str] = None
587
+ if status in ("legacy", "deprecated") and release_date is not None:
588
+ eos = release_date + timedelta(days=730) # ~24 months
589
+ end_of_support = eos.strftime("%Y-%m-%d")
590
+
591
+ result[model_id] = {
592
+ "status": status,
593
+ "family": family,
594
+ "release_date": release_date.strftime("%Y-%m-%d") if release_date else None,
595
+ "superseded_by": superseded_by,
596
+ "end_of_support": end_of_support,
597
+ }
598
+
599
+ return result
600
+
601
+
602
+ def _infer_family(model_id: str) -> str:
603
+ """Infer a family name from a model ID by stripping date/version suffixes.
604
+
605
+ Examples:
606
+ - ``claude-3-haiku-20240307`` → ``claude-3-haiku``
607
+ - ``gpt-4o-2024-08-06`` → ``gpt-4o``
608
+ - ``gemini-1.5-pro`` → ``gemini-1.5-pro`` (no suffix to strip)
609
+ """
610
+ import re
611
+
612
+ # Strip trailing date patterns: -YYYYMMDD or -YYYY-MM-DD
613
+ stripped = re.sub(r"-\d{4}-?\d{2}-?\d{2}$", "", model_id)
614
+ return stripped
615
+
616
+
617
+ def get_model_lifecycle(provider: str, model_id: str) -> Optional[dict[str, Any]]:
618
+ """Return lifecycle/deprecation metadata for a model.
619
+
620
+ Returns a dict with keys: ``status``, ``family``, ``release_date``,
621
+ ``superseded_by``, ``end_of_support``. Returns ``None`` for unknown models.
622
+
623
+ Results are cached per-provider; call :func:`refresh_rates_cache` to clear.
624
+ """
625
+ api_provider = PROVIDER_MAP.get(provider, provider)
626
+
627
+ with _lifecycle_lock:
628
+ if api_provider not in _lifecycle_cache:
629
+ _lifecycle_cache[api_provider] = _compute_family_status(api_provider)
630
+
631
+ family_status = _lifecycle_cache.get(api_provider, {})
632
+
633
+ # Exact match
634
+ if model_id in family_status:
635
+ return dict(family_status[model_id])
636
+
637
+ # Try base model fallback (date-stripped)
638
+ base = _strip_to_base_model(model_id)
639
+ if base is not None and base in family_status:
640
+ return dict(family_status[base])
641
+
642
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prompture
3
- Version: 1.0.45.dev2
3
+ Version: 1.0.46.dev1
4
4
  Summary: Ask LLMs to return structured JSON and run cross-model tests. API-first.
5
5
  Author-email: Juan Denis <juan@vene.co>
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes