prompture 1.0.55.dev2__tar.gz → 1.0.56.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 (248) hide show
  1. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.env.copy +4 -1
  2. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/PKG-INFO +25 -2
  3. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/README.md +24 -1
  4. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/_version.py +2 -2
  5. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/__init__.py +37 -1
  6. prompture-1.0.56.dev1/prompture/drivers/async_grok_video_gen_driver.py +194 -0
  7. prompture-1.0.56.dev1/prompture/drivers/async_video_gen_base.py +78 -0
  8. prompture-1.0.56.dev1/prompture/drivers/grok_video_gen_driver.py +241 -0
  9. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/provider_descriptors.py +17 -2
  10. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/registry.py +79 -0
  11. prompture-1.0.56.dev1/prompture/drivers/video_gen_base.py +94 -0
  12. prompture-1.0.56.dev1/prompture/drivers/video_gen_registry.py +33 -0
  13. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/__init__.py +4 -1
  14. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/cost_mixin.py +42 -0
  15. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/discovery.py +38 -0
  16. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/provider_env.py +1 -0
  17. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/settings.py +2 -0
  18. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/media/__init__.py +17 -1
  19. prompture-1.0.56.dev1/prompture/media/video.py +191 -0
  20. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/serialization.py +4 -0
  21. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/PKG-INFO +25 -2
  22. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/SOURCES.txt +6 -0
  23. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-driver/SKILL.md +0 -0
  24. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-driver/references/driver-template.md +0 -0
  25. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-example/SKILL.md +0 -0
  26. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-field/SKILL.md +0 -0
  27. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-persona/SKILL.md +0 -0
  28. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-test/SKILL.md +0 -0
  29. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-tool/SKILL.md +0 -0
  30. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/create-pr/SKILL.md +0 -0
  31. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/run-tests/SKILL.md +0 -0
  32. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/scaffold-extraction/SKILL.md +0 -0
  33. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/update-pricing/SKILL.md +0 -0
  34. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/FUNDING.yml +0 -0
  35. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  36. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/pricing_cost_mismatch.yml +0 -0
  37. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/provider_driver_bug.yml +0 -0
  38. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/schema_extraction_failure.yml +0 -0
  39. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/scripts/update_docs_version.py +0 -0
  40. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/scripts/update_wrapper_version.py +0 -0
  41. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/dev.yml +0 -0
  42. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/documentation.yml +0 -0
  43. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/pricing-freshness.yml +0 -0
  44. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/publish.yml +0 -0
  45. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/security.yml +0 -0
  46. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.safety-project.ini +0 -0
  47. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/AGENTS.md +0 -0
  48. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/BREAKING_CHANGES.md +0 -0
  49. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/CLAUDE.md +0 -0
  50. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/CONTRIBUTING.md +0 -0
  51. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/LICENSE +0 -0
  52. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/MANIFEST.in +0 -0
  53. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/ROADMAP.md +0 -0
  54. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/SECURITY.md +0 -0
  55. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/dev.ps1 +0 -0
  56. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/dev.sh +0 -0
  57. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/mypy_errors.txt +0 -0
  58. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/README.md +0 -0
  59. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/README.md +0 -0
  60. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/llm_to_json/__init__.py +0 -0
  61. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/pyproject.toml +0 -0
  62. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/test.py +0 -0
  63. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/README.md +0 -0
  64. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/llm_to_toon/__init__.py +0 -0
  65. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/pyproject.toml +0 -0
  66. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/test.py +0 -0
  67. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/__init__.py +0 -0
  68. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/__init__.py +0 -0
  69. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/agent.py +0 -0
  70. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/async_agent.py +0 -0
  71. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/async_conversation.py +0 -0
  72. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/conversation.py +0 -0
  73. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/persona.py +0 -0
  74. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/simulated_tools.py +0 -0
  75. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/skills.py +0 -0
  76. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/tools_schema.py +0 -0
  77. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/types.py +0 -0
  78. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/aio/__init__.py +0 -0
  79. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/bridges/__init__.py +0 -0
  80. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/bridges/tukuy_backend.py +0 -0
  81. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/__init__.py +0 -0
  82. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/cli.py +0 -0
  83. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/formatters.py +0 -0
  84. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/runner.py +0 -0
  85. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/server.py +0 -0
  86. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/airllm_driver.py +0 -0
  87. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_airllm_driver.py +0 -0
  88. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_azure_driver.py +0 -0
  89. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_base.py +0 -0
  90. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_cachibot_driver.py +0 -0
  91. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_claude_driver.py +0 -0
  92. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_elevenlabs_stt_driver.py +0 -0
  93. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_elevenlabs_tts_driver.py +0 -0
  94. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_embedding_base.py +0 -0
  95. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_google_driver.py +0 -0
  96. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_google_img_gen_driver.py +0 -0
  97. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_google_vertexai_driver.py +0 -0
  98. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_grok_driver.py +0 -0
  99. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_grok_img_gen_driver.py +0 -0
  100. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_groq_driver.py +0 -0
  101. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_hugging_driver.py +0 -0
  102. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_img_gen_base.py +0 -0
  103. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_lmstudio_driver.py +0 -0
  104. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_local_http_driver.py +0 -0
  105. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_modelscope_driver.py +0 -0
  106. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_moonshot_driver.py +0 -0
  107. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_ollama_driver.py +0 -0
  108. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_ollama_embedding_driver.py +0 -0
  109. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_driver.py +0 -0
  110. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_embedding_driver.py +0 -0
  111. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_img_gen_driver.py +0 -0
  112. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_stt_driver.py +0 -0
  113. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_tts_driver.py +0 -0
  114. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openrouter_driver.py +0 -0
  115. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_registry.py +0 -0
  116. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_stability_img_gen_driver.py +0 -0
  117. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_stt_base.py +0 -0
  118. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_tts_base.py +0 -0
  119. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_zai_driver.py +0 -0
  120. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/audio_registry.py +0 -0
  121. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/azure_config.py +0 -0
  122. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/azure_driver.py +0 -0
  123. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/base.py +0 -0
  124. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/cachibot_driver.py +0 -0
  125. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/claude_driver.py +0 -0
  126. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/driver_registry.py +0 -0
  127. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/elevenlabs_stt_driver.py +0 -0
  128. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/elevenlabs_tts_driver.py +0 -0
  129. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/embedding_base.py +0 -0
  130. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/embedding_registry.py +0 -0
  131. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/google_driver.py +0 -0
  132. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/google_img_gen_driver.py +0 -0
  133. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/google_vertexai_driver.py +0 -0
  134. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/grok_driver.py +0 -0
  135. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/grok_img_gen_driver.py +0 -0
  136. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/groq_driver.py +0 -0
  137. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/hugging_driver.py +0 -0
  138. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/img_gen_base.py +0 -0
  139. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/img_gen_registry.py +0 -0
  140. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/lmstudio_driver.py +0 -0
  141. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/local_http_driver.py +0 -0
  142. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/modelscope_driver.py +0 -0
  143. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/moonshot_driver.py +0 -0
  144. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/ollama_driver.py +0 -0
  145. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/ollama_embedding_driver.py +0 -0
  146. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_driver.py +0 -0
  147. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_embedding_driver.py +0 -0
  148. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_img_gen_driver.py +0 -0
  149. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_stt_driver.py +0 -0
  150. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_tts_driver.py +0 -0
  151. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openrouter_driver.py +0 -0
  152. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/stability_img_gen_driver.py +0 -0
  153. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/stt_base.py +0 -0
  154. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/tts_base.py +0 -0
  155. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/vision_helpers.py +0 -0
  156. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/zai_driver.py +0 -0
  157. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/exceptions.py +0 -0
  158. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/__init__.py +0 -0
  159. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/async_core.py +0 -0
  160. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/core.py +0 -0
  161. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/fields.py +0 -0
  162. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/reasoning.py +0 -0
  163. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/strategy.py +0 -0
  164. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/tools.py +0 -0
  165. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/tukuy_bridge.py +0 -0
  166. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/validator.py +0 -0
  167. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/__init__.py +0 -0
  168. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/async_groups.py +0 -0
  169. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/consensus.py +0 -0
  170. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/debate.py +0 -0
  171. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/groups.py +0 -0
  172. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/types.py +0 -0
  173. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/budget.py +0 -0
  174. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/cache.py +0 -0
  175. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/callbacks.py +0 -0
  176. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/capabilities.py +0 -0
  177. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/ledger.py +0 -0
  178. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/logging.py +0 -0
  179. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/model_rates.py +0 -0
  180. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/pricing.py +0 -0
  181. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/anthropic.json +0 -0
  182. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/azure.json +0 -0
  183. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/google.json +0 -0
  184. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/google_vertexai.json +0 -0
  185. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/groq.json +0 -0
  186. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/moonshot.json +0 -0
  187. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/openai.json +0 -0
  188. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/openrouter.json +0 -0
  189. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/xai.json +0 -0
  190. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/session.py +0 -0
  191. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/tracker.py +0 -0
  192. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/tukuy_backend.py +0 -0
  193. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/__init__.py +0 -0
  194. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/chunking.py +0 -0
  195. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/detect.py +0 -0
  196. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/document.py +0 -0
  197. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/__init__.py +0 -0
  198. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/base.py +0 -0
  199. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/csv_parser.py +0 -0
  200. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/docx.py +0 -0
  201. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/html.py +0 -0
  202. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/markdown.py +0 -0
  203. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/pdf.py +0 -0
  204. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/xlsx.py +0 -0
  205. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/integrations/__init__.py +0 -0
  206. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/integrations/tukuy_bridge.py +0 -0
  207. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/media/audio.py +0 -0
  208. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/media/image.py +0 -0
  209. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/01-why-prompture.md +0 -0
  210. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/02-installation.md +0 -0
  211. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/03-quickstart.md +0 -0
  212. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/04-toon-input.md +0 -0
  213. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/05-test-harness.md +0 -0
  214. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/06-stability.md +0 -0
  215. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/07-migration.md +0 -0
  216. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/__init__.py +0 -0
  217. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/history.py +0 -0
  218. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/store.py +0 -0
  219. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/__init__.py +0 -0
  220. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/pipeline.py +0 -0
  221. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/resolver.py +0 -0
  222. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/routing.py +0 -0
  223. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/py.typed +0 -0
  224. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/__init__.py +0 -0
  225. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/generator.py +0 -0
  226. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/Dockerfile.j2 +0 -0
  227. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/README.md.j2 +0 -0
  228. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/config.py.j2 +0 -0
  229. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/env.example.j2 +0 -0
  230. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/main.py.j2 +0 -0
  231. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/models.py.j2 +0 -0
  232. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/requirements.txt.j2 +0 -0
  233. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/testing/__init__.py +0 -0
  234. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/testing/driver_contract.py +0 -0
  235. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/dependency_links.txt +0 -0
  236. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/entry_points.txt +0 -0
  237. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/requires.txt +0 -0
  238. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/top_level.txt +0 -0
  239. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture_cost_tracking.md +0 -0
  240. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/pyproject.toml +0 -0
  241. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/requirements.txt +0 -0
  242. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/scripts/check_pricing_freshness.py +0 -0
  243. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/setup.cfg +0 -0
  244. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/specs/basic_extraction.json +0 -0
  245. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/specs/schema_validation.json +0 -0
  246. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/specs/strategy_comparison.json +0 -0
  247. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/test.py +0 -0
  248. {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/test_version_diagnosis.py +0 -0
@@ -53,7 +53,10 @@ OPENROUTER_MODEL=openai/gpt-4o-mini
53
53
 
54
54
  # ─── Grok (xAI) ─────────────────────────────────────────────────────────────
55
55
  GROK_API_KEY=your-grok-api-key
56
+ # XAI_API_KEY is also supported for xAI docs compatibility.
57
+ XAI_API_KEY=
56
58
  GROK_MODEL=grok-4-fast-reasoning
59
+ GROK_VIDEO_MODEL=grok-imagine-video
57
60
 
58
61
  # ─── Moonshot AI (Kimi) ─────────────────────────────────────────────────────
59
62
  MOONSHOT_API_KEY=your-moonshot-api-key
@@ -86,4 +89,4 @@ AIRLLM_MODEL=meta-llama/Llama-2-7b-hf
86
89
  AIRLLM_COMPRESSION=
87
90
 
88
91
  # ─── Stability AI (image generation) ────────────────────────────────────────
89
- STABILITY_API_KEY=
92
+ STABILITY_API_KEY=
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prompture
3
- Version: 1.0.55.dev2
3
+ Version: 1.0.56.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
@@ -96,7 +96,7 @@ print(person.name) # Maria
96
96
 
97
97
  - **Structured output** — JSON schema enforcement and direct Pydantic model population
98
98
  - **17+ providers** — OpenAI, Claude, Google, Groq, Grok, Azure, Ollama, LM Studio, OpenRouter, HuggingFace, Moonshot, ModelScope, Z.ai, Vertex AI, AirLLM, CachiBot, and generic HTTP
99
- - **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
99
+ - **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), video generation (Grok Imagine Video), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
100
100
  - **Multi-model fallback** — Try a list of models in sequence with per-attempt cost, token, and capability accounting
101
101
  - **Strategy cascade** — Auto-selects between provider-native JSON mode, tool-call extraction, and prompted repair so extraction works on any model
102
102
  - **TOON input conversion** — 45-60% token savings when sending structured data via [Token-Oriented Object Notation](https://github.com/jhd3197/python-toon)
@@ -141,6 +141,8 @@ ANTHROPIC_API_KEY=sk-ant-...
141
141
  GOOGLE_API_KEY=...
142
142
  GROQ_API_KEY=...
143
143
  GROK_API_KEY=...
144
+ # optional xAI-compatible alias for Grok APIs
145
+ XAI_API_KEY=...
144
146
  OPENROUTER_API_KEY=...
145
147
  AZURE_OPENAI_ENDPOINT=...
146
148
  AZURE_OPENAI_API_KEY=...
@@ -198,6 +200,7 @@ Beyond text LLMs, Prompture exposes drivers for adjacent modalities under the sa
198
200
 
199
201
  - **Embeddings** — OpenAI (`text-embedding-3-*`) and Ollama (`nomic-embed-text`)
200
202
  - **Image generation** — OpenAI DALL-E, Google Imagen, Grok, Stability AI
203
+ - **Video generation** — Grok Imagine Video (`grok-imagine-video`) with text-to-video, image-to-video, reference images, and polling
201
204
  - **Text-to-speech** — OpenAI (`tts-1`) and ElevenLabs
202
205
  - **Speech-to-text** — OpenAI Whisper and ElevenLabs
203
206
 
@@ -212,6 +215,26 @@ result = driver.generate_image(
212
215
  print(result["meta"]["cost"], result["meta"]["image_count"])
213
216
  ```
214
217
 
218
+ Video generation uses the same provider/model routing. Set `GROK_API_KEY` or `XAI_API_KEY`, then request a Grok video model:
219
+
220
+ ```python
221
+ from prompture import get_video_gen_driver_for_model
222
+
223
+ driver = get_video_gen_driver_for_model("grok/grok-imagine-video")
224
+ result = driver.generate_video(
225
+ "wide shot of a crystal-powered rocket launching from red desert dunes",
226
+ {"duration": 8, "aspect_ratio": "16:9", "resolution": "720p"},
227
+ )
228
+
229
+ video = result["videos"][0]
230
+ print(video.url)
231
+ print(result["meta"]["request_id"], result["meta"]["cost"])
232
+ ```
233
+
234
+ For local smoke tests without waiting on the render, pass `{"poll": False}` to get the provider request ID. The async factory is available as `get_async_video_gen_driver_for_model()`.
235
+
236
+ Runnable example: `python examples/grok_video_generation_example.py`.
237
+
215
238
  ## Usage
216
239
 
217
240
  ### One-Shot Pydantic Extraction
@@ -32,7 +32,7 @@ print(person.name) # Maria
32
32
 
33
33
  - **Structured output** — JSON schema enforcement and direct Pydantic model population
34
34
  - **17+ providers** — OpenAI, Claude, Google, Groq, Grok, Azure, Ollama, LM Studio, OpenRouter, HuggingFace, Moonshot, ModelScope, Z.ai, Vertex AI, AirLLM, CachiBot, and generic HTTP
35
- - **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
35
+ - **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), video generation (Grok Imagine Video), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
36
36
  - **Multi-model fallback** — Try a list of models in sequence with per-attempt cost, token, and capability accounting
37
37
  - **Strategy cascade** — Auto-selects between provider-native JSON mode, tool-call extraction, and prompted repair so extraction works on any model
38
38
  - **TOON input conversion** — 45-60% token savings when sending structured data via [Token-Oriented Object Notation](https://github.com/jhd3197/python-toon)
@@ -77,6 +77,8 @@ ANTHROPIC_API_KEY=sk-ant-...
77
77
  GOOGLE_API_KEY=...
78
78
  GROQ_API_KEY=...
79
79
  GROK_API_KEY=...
80
+ # optional xAI-compatible alias for Grok APIs
81
+ XAI_API_KEY=...
80
82
  OPENROUTER_API_KEY=...
81
83
  AZURE_OPENAI_ENDPOINT=...
82
84
  AZURE_OPENAI_API_KEY=...
@@ -134,6 +136,7 @@ Beyond text LLMs, Prompture exposes drivers for adjacent modalities under the sa
134
136
 
135
137
  - **Embeddings** — OpenAI (`text-embedding-3-*`) and Ollama (`nomic-embed-text`)
136
138
  - **Image generation** — OpenAI DALL-E, Google Imagen, Grok, Stability AI
139
+ - **Video generation** — Grok Imagine Video (`grok-imagine-video`) with text-to-video, image-to-video, reference images, and polling
137
140
  - **Text-to-speech** — OpenAI (`tts-1`) and ElevenLabs
138
141
  - **Speech-to-text** — OpenAI Whisper and ElevenLabs
139
142
 
@@ -148,6 +151,26 @@ result = driver.generate_image(
148
151
  print(result["meta"]["cost"], result["meta"]["image_count"])
149
152
  ```
150
153
 
154
+ Video generation uses the same provider/model routing. Set `GROK_API_KEY` or `XAI_API_KEY`, then request a Grok video model:
155
+
156
+ ```python
157
+ from prompture import get_video_gen_driver_for_model
158
+
159
+ driver = get_video_gen_driver_for_model("grok/grok-imagine-video")
160
+ result = driver.generate_video(
161
+ "wide shot of a crystal-powered rocket launching from red desert dunes",
162
+ {"duration": 8, "aspect_ratio": "16:9", "resolution": "720p"},
163
+ )
164
+
165
+ video = result["videos"][0]
166
+ print(video.url)
167
+ print(result["meta"]["request_id"], result["meta"]["cost"])
168
+ ```
169
+
170
+ For local smoke tests without waiting on the render, pass `{"poll": False}` to get the provider request ID. The async factory is available as `get_async_video_gen_driver_for_model()`.
171
+
172
+ Runnable example: `python examples/grok_video_generation_example.py`.
173
+
151
174
  ## Usage
152
175
 
153
176
  ### One-Shot Pydantic Extraction
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.0.55.dev2'
22
- __version_tuple__ = version_tuple = (1, 0, 55, 'dev2')
21
+ __version__ = version = '1.0.56.dev1'
22
+ __version_tuple__ = version_tuple = (1, 0, 56, 'dev1')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -41,6 +41,7 @@ from .async_google_driver import AsyncGoogleDriver
41
41
  from .async_google_img_gen_driver import AsyncGoogleImageGenDriver
42
42
  from .async_grok_driver import AsyncGrokDriver
43
43
  from .async_grok_img_gen_driver import AsyncGrokImageGenDriver
44
+ from .async_grok_video_gen_driver import AsyncGrokVideoGenDriver
44
45
  from .async_groq_driver import AsyncGroqDriver
45
46
  from .async_hugging_driver import AsyncHuggingFaceDriver
46
47
  from .async_img_gen_base import AsyncImageGenDriver
@@ -59,6 +60,7 @@ from .async_openrouter_driver import AsyncOpenRouterDriver
59
60
  from .async_stability_img_gen_driver import AsyncStabilityImageGenDriver
60
61
  from .async_stt_base import AsyncSTTDriver
61
62
  from .async_tts_base import AsyncTTSDriver
63
+ from .async_video_gen_base import AsyncVideoGenDriver
62
64
  from .async_zai_driver import AsyncZaiDriver
63
65
  from .azure_config import (
64
66
  clear_azure_configs,
@@ -76,6 +78,7 @@ from .google_driver import GoogleDriver
76
78
  from .google_img_gen_driver import GoogleImageGenDriver
77
79
  from .grok_driver import GrokDriver
78
80
  from .grok_img_gen_driver import GrokImageGenDriver
81
+ from .grok_video_gen_driver import GrokVideoGenDriver
79
82
  from .groq_driver import GroqDriver
80
83
  from .hugging_driver import HuggingFaceDriver
81
84
  from .img_gen_base import ImageGenDriver
@@ -104,59 +107,70 @@ from .registry import (
104
107
  get_async_img_gen_driver_factory,
105
108
  get_async_stt_driver_factory,
106
109
  get_async_tts_driver_factory,
110
+ get_async_video_gen_driver_factory,
107
111
  get_driver_factory,
108
112
  get_embedding_driver_factory,
109
113
  get_img_gen_driver_factory,
110
114
  get_stt_driver_factory,
111
115
  get_tts_driver_factory,
116
+ get_video_gen_driver_factory,
112
117
  is_async_driver_registered,
113
118
  is_async_embedding_driver_registered,
114
119
  is_async_img_gen_driver_registered,
115
120
  is_async_stt_driver_registered,
116
121
  is_async_tts_driver_registered,
122
+ is_async_video_gen_driver_registered,
117
123
  is_driver_registered,
118
124
  is_embedding_driver_registered,
119
125
  is_img_gen_driver_registered,
120
126
  is_stt_driver_registered,
121
127
  is_tts_driver_registered,
128
+ is_video_gen_driver_registered,
122
129
  list_registered_async_drivers,
123
130
  list_registered_async_embedding_drivers,
124
131
  list_registered_async_img_gen_drivers,
125
132
  list_registered_async_stt_drivers,
126
133
  list_registered_async_tts_drivers,
134
+ list_registered_async_video_gen_drivers,
127
135
  list_registered_drivers,
128
136
  list_registered_embedding_drivers,
129
137
  list_registered_img_gen_drivers,
130
138
  list_registered_stt_drivers,
131
139
  list_registered_tts_drivers,
140
+ list_registered_video_gen_drivers,
132
141
  load_entry_point_drivers,
133
142
  register_async_driver,
134
143
  register_async_embedding_driver,
135
144
  register_async_img_gen_driver,
136
145
  register_async_stt_driver,
137
146
  register_async_tts_driver,
147
+ register_async_video_gen_driver,
138
148
  register_driver,
139
149
  register_embedding_driver,
140
150
  register_img_gen_driver,
141
151
  register_stt_driver,
142
152
  register_tts_driver,
153
+ register_video_gen_driver,
143
154
  unregister_async_driver,
144
155
  unregister_async_embedding_driver,
145
156
  unregister_async_img_gen_driver,
146
157
  unregister_async_stt_driver,
147
158
  unregister_async_tts_driver,
159
+ unregister_async_video_gen_driver,
148
160
  unregister_driver,
149
161
  unregister_embedding_driver,
150
162
  unregister_img_gen_driver,
151
163
  unregister_stt_driver,
152
164
  unregister_tts_driver,
165
+ unregister_video_gen_driver,
153
166
  )
154
167
  from .stability_img_gen_driver import StabilityImageGenDriver
155
168
  from .stt_base import STTDriver
156
169
  from .tts_base import TTSDriver
170
+ from .video_gen_base import VideoGenDriver
157
171
  from .zai_driver import ZaiDriver
158
172
 
159
- # Register all built-in drivers (LLM sync/async, STT, TTS, img_gen, embedding)
173
+ # Register all built-in drivers (LLM sync/async, STT, TTS, img_gen, video_gen, embedding)
160
174
  # from the unified ProviderDescriptor list — replaces ~200 lines of individual
161
175
  # register_*() calls that were previously scattered across this file,
162
176
  # async_registry.py, audio_registry.py, embedding_registry.py, and img_gen_registry.py.
@@ -185,6 +199,10 @@ from .img_gen_registry import (
185
199
  get_async_img_gen_driver_for_model,
186
200
  get_img_gen_driver_for_model,
187
201
  )
202
+ from .video_gen_registry import (
203
+ get_async_video_gen_driver_for_model,
204
+ get_video_gen_driver_for_model,
205
+ )
188
206
 
189
207
  # Backwards compatibility: expose registry dict (read-only view recommended)
190
208
  DRIVER_REGISTRY = _get_sync_registry()
@@ -449,6 +467,7 @@ __all__ = [
449
467
  "AsyncGoogleImageGenDriver",
450
468
  "AsyncGrokDriver",
451
469
  "AsyncGrokImageGenDriver",
470
+ "AsyncGrokVideoGenDriver",
452
471
  "AsyncGroqDriver",
453
472
  "AsyncHuggingFaceDriver",
454
473
  "AsyncImageGenDriver",
@@ -467,6 +486,7 @@ __all__ = [
467
486
  "AsyncSTTDriver",
468
487
  "AsyncStabilityImageGenDriver",
469
488
  "AsyncTTSDriver",
489
+ "AsyncVideoGenDriver",
470
490
  "AsyncZaiDriver",
471
491
  # Sync LLM drivers
472
492
  "AzureDriver",
@@ -482,6 +502,7 @@ __all__ = [
482
502
  "GoogleImageGenDriver",
483
503
  "GrokDriver",
484
504
  "GrokImageGenDriver",
505
+ "GrokVideoGenDriver",
485
506
  "GroqDriver",
486
507
  "HuggingFaceDriver",
487
508
  # Image gen base class
@@ -502,6 +523,7 @@ __all__ = [
502
523
  "STTDriver",
503
524
  "StabilityImageGenDriver",
504
525
  "TTSDriver",
526
+ "VideoGenDriver",
505
527
  "ZaiDriver",
506
528
  # Azure config API
507
529
  "clear_azure_configs",
@@ -521,6 +543,10 @@ __all__ = [
521
543
  "get_async_stt_driver_for_model",
522
544
  "get_async_tts_driver_factory",
523
545
  "get_async_tts_driver_for_model",
546
+ # Video gen registry query functions
547
+ "get_async_video_gen_driver_factory",
548
+ # Video gen factory functions
549
+ "get_async_video_gen_driver_for_model",
524
550
  # LLM factory functions
525
551
  "get_driver",
526
552
  "get_driver_for_model",
@@ -532,27 +558,33 @@ __all__ = [
532
558
  "get_stt_driver_for_model",
533
559
  "get_tts_driver_factory",
534
560
  "get_tts_driver_for_model",
561
+ "get_video_gen_driver_factory",
562
+ "get_video_gen_driver_for_model",
535
563
  # Other registry query functions
536
564
  "is_async_driver_registered",
537
565
  "is_async_embedding_driver_registered",
538
566
  "is_async_img_gen_driver_registered",
539
567
  "is_async_stt_driver_registered",
540
568
  "is_async_tts_driver_registered",
569
+ "is_async_video_gen_driver_registered",
541
570
  "is_driver_registered",
542
571
  "is_embedding_driver_registered",
543
572
  "is_img_gen_driver_registered",
544
573
  "is_stt_driver_registered",
545
574
  "is_tts_driver_registered",
575
+ "is_video_gen_driver_registered",
546
576
  "list_registered_async_drivers",
547
577
  "list_registered_async_embedding_drivers",
548
578
  "list_registered_async_img_gen_drivers",
549
579
  "list_registered_async_stt_drivers",
550
580
  "list_registered_async_tts_drivers",
581
+ "list_registered_async_video_gen_drivers",
551
582
  "list_registered_drivers",
552
583
  "list_registered_embedding_drivers",
553
584
  "list_registered_img_gen_drivers",
554
585
  "list_registered_stt_drivers",
555
586
  "list_registered_tts_drivers",
587
+ "list_registered_video_gen_drivers",
556
588
  "load_entry_point_drivers",
557
589
  "parse_model_string",
558
590
  "provider_for_model",
@@ -562,6 +594,7 @@ __all__ = [
562
594
  "register_async_img_gen_driver",
563
595
  "register_async_stt_driver",
564
596
  "register_async_tts_driver",
597
+ "register_async_video_gen_driver",
565
598
  "register_azure_config",
566
599
  # Registry functions (public API)
567
600
  "register_driver",
@@ -569,16 +602,19 @@ __all__ = [
569
602
  "register_img_gen_driver",
570
603
  "register_stt_driver",
571
604
  "register_tts_driver",
605
+ "register_video_gen_driver",
572
606
  "set_azure_config_resolver",
573
607
  "unregister_async_driver",
574
608
  "unregister_async_embedding_driver",
575
609
  "unregister_async_img_gen_driver",
576
610
  "unregister_async_stt_driver",
577
611
  "unregister_async_tts_driver",
612
+ "unregister_async_video_gen_driver",
578
613
  "unregister_azure_config",
579
614
  "unregister_driver",
580
615
  "unregister_embedding_driver",
581
616
  "unregister_img_gen_driver",
582
617
  "unregister_stt_driver",
583
618
  "unregister_tts_driver",
619
+ "unregister_video_gen_driver",
584
620
  ]
@@ -0,0 +1,194 @@
1
+ """Async xAI Grok Imagine video generation driver."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import os
7
+ import time
8
+ from typing import Any
9
+
10
+ import httpx
11
+
12
+ from ..infra.cost_mixin import VideoCostMixin
13
+ from .async_video_gen_base import AsyncVideoGenDriver
14
+ from .grok_video_gen_driver import (
15
+ _DEFAULT_ENDPOINT,
16
+ _duration_from_options,
17
+ _error_text,
18
+ _extract_video_content,
19
+ _get_xai_api_key,
20
+ _image_payload,
21
+ )
22
+
23
+
24
+ class AsyncGrokVideoGenDriver(VideoCostMixin, AsyncVideoGenDriver):
25
+ """Async video generation via xAI Grok Imagine Video REST API."""
26
+
27
+ supports_image_input = True
28
+ supports_reference_images = True
29
+ supports_video_input = False
30
+ supports_audio = True
31
+ supports_polling = True
32
+ supported_aspect_ratios = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"]
33
+ supported_resolutions = ["480p", "720p"]
34
+ max_seconds = 15
35
+
36
+ KNOWN_MODELS = ["grok-imagine-video"]
37
+ VIDEO_PRICING: dict[str, dict[str, Any]] = {
38
+ "grok-imagine-video": {
39
+ "per_second": 0.05,
40
+ "per_second_by_resolution": {
41
+ "480p": 0.05,
42
+ "720p": 0.07,
43
+ },
44
+ }
45
+ }
46
+
47
+ def __init__(
48
+ self,
49
+ api_key: str | None = None,
50
+ model: str = "grok-imagine-video",
51
+ endpoint: str | None = None,
52
+ ):
53
+ self.api_key = _get_xai_api_key(api_key)
54
+ self.model = model
55
+ self.endpoint = (endpoint or os.getenv("GROK_ENDPOINT") or _DEFAULT_ENDPOINT).rstrip("/")
56
+
57
+ @classmethod
58
+ def list_models(cls, *, api_key: str | None = None, **kw: object) -> list[str] | None:
59
+ """Return known xAI video models when an API key is configured."""
60
+ key = _get_xai_api_key(api_key)
61
+ if not key:
62
+ return None
63
+ return list(cls.KNOWN_MODELS)
64
+
65
+ async def generate_video(self, prompt: str, options: dict[str, Any]) -> dict[str, Any]:
66
+ """Generate a video using xAI Grok Imagine Video (async)."""
67
+ if not self.api_key:
68
+ raise RuntimeError("GROK_API_KEY or XAI_API_KEY environment variable is required")
69
+ if not prompt:
70
+ raise ValueError("prompt cannot be empty")
71
+
72
+ model = options.get("model", self.model)
73
+ duration = _duration_from_options(options)
74
+ aspect_ratio = options.get("aspect_ratio", "16:9")
75
+ resolution = options.get("resolution", "480p")
76
+
77
+ if aspect_ratio not in self.supported_aspect_ratios:
78
+ raise ValueError(f"Unsupported aspect_ratio '{aspect_ratio}'")
79
+ if resolution not in self.supported_resolutions:
80
+ raise ValueError(f"Unsupported resolution '{resolution}'")
81
+
82
+ image = options.get("image")
83
+ reference_images = options.get("reference_images")
84
+ if image is not None and reference_images:
85
+ raise ValueError("image and reference_images cannot be used together")
86
+ if reference_images:
87
+ if len(reference_images) > 7:
88
+ raise ValueError("reference_images supports at most 7 images")
89
+ if duration > 10:
90
+ raise ValueError("duration must be 10 seconds or less when using reference_images")
91
+
92
+ payload: dict[str, Any] = {
93
+ "model": model,
94
+ "prompt": prompt,
95
+ "duration": duration,
96
+ "aspect_ratio": aspect_ratio,
97
+ "resolution": resolution,
98
+ }
99
+ if image is not None:
100
+ payload["image"] = _image_payload(image)
101
+ if reference_images:
102
+ payload["reference_images"] = [_image_payload(img) for img in reference_images]
103
+
104
+ headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
105
+ async with httpx.AsyncClient() as client:
106
+ response = await client.post(
107
+ f"{self.endpoint}/videos/generations",
108
+ headers=headers,
109
+ json=payload,
110
+ timeout=120.0,
111
+ )
112
+ if response.status_code >= 400:
113
+ raise RuntimeError(
114
+ f"Grok video generation failed: HTTP {response.status_code}: {_error_text(response)}"
115
+ )
116
+
117
+ start_data = response.json()
118
+ request_id = start_data.get("request_id")
119
+ if not request_id:
120
+ raise RuntimeError("Grok video generation response did not include request_id")
121
+
122
+ if not options.get("poll", True):
123
+ return {
124
+ "videos": [],
125
+ "meta": {
126
+ "video_count": 0,
127
+ "request_id": request_id,
128
+ "status": start_data.get("status", "pending"),
129
+ "duration_seconds": duration,
130
+ "aspect_ratio": aspect_ratio,
131
+ "resolution": resolution,
132
+ "cost": 0.0,
133
+ "model_name": f"grok/{model}",
134
+ "raw_response": start_data,
135
+ },
136
+ }
137
+
138
+ final_data = await self._poll_until_done(
139
+ client,
140
+ request_id,
141
+ headers=headers,
142
+ poll_interval=float(options.get("poll_interval", 5)),
143
+ timeout_seconds=float(options.get("timeout", 600)),
144
+ )
145
+
146
+ video = _extract_video_content(final_data)
147
+ duration_seconds = video.duration_seconds or float(duration)
148
+ cost = self._calculate_video_cost(
149
+ "grok",
150
+ model,
151
+ duration_seconds=duration_seconds,
152
+ n=1,
153
+ resolution=resolution,
154
+ )
155
+
156
+ return {
157
+ "videos": [video],
158
+ "meta": {
159
+ "video_count": 1,
160
+ "request_id": request_id,
161
+ "status": final_data.get("status"),
162
+ "duration_seconds": duration_seconds,
163
+ "aspect_ratio": aspect_ratio,
164
+ "resolution": resolution,
165
+ "cost": cost,
166
+ "model_name": f"grok/{model}",
167
+ "raw_response": {"start": start_data, "final": final_data},
168
+ },
169
+ }
170
+
171
+ async def _poll_until_done(
172
+ self,
173
+ client: httpx.AsyncClient,
174
+ request_id: str,
175
+ *,
176
+ headers: dict[str, str],
177
+ poll_interval: float,
178
+ timeout_seconds: float,
179
+ ) -> dict[str, Any]:
180
+ deadline = time.monotonic() + timeout_seconds
181
+ while True:
182
+ response = await client.get(f"{self.endpoint}/videos/{request_id}", headers=headers, timeout=30.0)
183
+ if response.status_code >= 400:
184
+ raise RuntimeError(f"Grok video status failed: HTTP {response.status_code}: {_error_text(response)}")
185
+
186
+ data = response.json()
187
+ status = data.get("status")
188
+ if status == "done":
189
+ return data
190
+ if status in {"failed", "expired"}:
191
+ raise RuntimeError(f"Grok video generation {status}: {data}")
192
+ if time.monotonic() >= deadline:
193
+ raise TimeoutError(f"Grok video generation timed out for request_id={request_id}")
194
+ await asyncio.sleep(poll_interval)
@@ -0,0 +1,78 @@
1
+ """Async base class for video generation drivers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import time
7
+ from typing import Any
8
+
9
+ from ..infra.callbacks import DriverCallbacks
10
+
11
+ logger = logging.getLogger("prompture.async_video_gen_driver")
12
+
13
+
14
+ class AsyncVideoGenDriver:
15
+ """Async adapter base for video generation. Implement ``async generate_video(prompt, options)``."""
16
+
17
+ supports_image_input: bool = False
18
+ supports_reference_images: bool = False
19
+ supports_video_input: bool = False
20
+ supports_audio: bool = False
21
+ supports_polling: bool = True
22
+ supported_aspect_ratios: list[str] = []
23
+ supported_resolutions: list[str] = []
24
+ max_seconds: int | None = None
25
+
26
+ callbacks: DriverCallbacks | None = None
27
+
28
+ async def generate_video(self, prompt: str, options: dict[str, Any]) -> dict[str, Any]:
29
+ """Generate video(s) from a text prompt (async)."""
30
+ raise NotImplementedError
31
+
32
+ async def generate_video_with_hooks(self, prompt: str, options: dict[str, Any]) -> dict[str, Any]:
33
+ """Wrap :meth:`generate_video` with on_request / on_response / on_error callbacks."""
34
+ driver_name = getattr(self, "model", self.__class__.__name__)
35
+ self._fire_callback(
36
+ "on_request",
37
+ {"prompt_length": len(prompt), "options": options, "driver": driver_name},
38
+ )
39
+ t0 = time.perf_counter()
40
+ try:
41
+ resp = await self.generate_video(prompt, options)
42
+ except Exception as exc:
43
+ self._fire_callback(
44
+ "on_error",
45
+ {"error": exc, "prompt_length": len(prompt), "options": options, "driver": driver_name},
46
+ )
47
+ raise
48
+ elapsed_ms = (time.perf_counter() - t0) * 1000
49
+ meta = resp.get("meta", {})
50
+ logger.debug(
51
+ "[video_gen] async generate driver=%s videos=%d cost=%.6f elapsed=%.0fms",
52
+ driver_name,
53
+ meta.get("video_count", 0),
54
+ meta.get("cost", 0.0),
55
+ elapsed_ms,
56
+ )
57
+ self._fire_callback(
58
+ "on_response",
59
+ {
60
+ "video_count": meta.get("video_count", 0),
61
+ "meta": meta,
62
+ "driver": driver_name,
63
+ "elapsed_ms": elapsed_ms,
64
+ },
65
+ )
66
+ return resp
67
+
68
+ def _fire_callback(self, event: str, payload: dict[str, Any]) -> None:
69
+ """Invoke a single callback, swallowing and logging any exception."""
70
+ if self.callbacks is None:
71
+ return
72
+ cb = getattr(self.callbacks, event, None)
73
+ if cb is None:
74
+ return
75
+ try:
76
+ cb(payload)
77
+ except Exception:
78
+ logger.exception("Callback %s raised an exception", event)