timbal 2.2.0__tar.gz → 2.2.1__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 (222) hide show
  1. {timbal-2.2.0 → timbal-2.2.1}/PKG-INFO +1 -1
  2. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/_version.py +2 -2
  3. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/flow.py +14 -2
  4. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/krea.py +196 -160
  5. {timbal-2.2.0 → timbal-2.2.1}/.gitignore +0 -0
  6. {timbal-2.2.0 → timbal-2.2.1}/LICENSE +0 -0
  7. {timbal-2.2.0 → timbal-2.2.1}/README.md +0 -0
  8. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/chat-completions.mdx +0 -0
  9. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/create-from-workforce.mdx +0 -0
  10. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/cancel.mdx +0 -0
  11. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/get.mdx +0 -0
  12. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/list.mdx +0 -0
  13. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/retry.mdx +0 -0
  14. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/link.mdx +0 -0
  15. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/list-context-vars.mdx +0 -0
  16. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/list-policies.mdx +0 -0
  17. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/messages.mdx +0 -0
  18. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/responses.mdx +0 -0
  19. {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/unlink.mdx +0 -0
  20. {timbal-2.2.0 → timbal-2.2.1}/pyproject.toml +0 -0
  21. {timbal-2.2.0 → timbal-2.2.1}/pyrightconfig.json +0 -0
  22. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/__init__.py +0 -0
  23. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/__init__.py +0 -0
  24. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/__main__.py +0 -0
  25. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/cli_utils.py +0 -0
  26. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/cst_utils.py +0 -0
  27. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/format.py +0 -0
  28. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/model_discovery.py +0 -0
  29. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/test.py +0 -0
  30. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/tool_discovery.py +0 -0
  31. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/__init__.py +0 -0
  32. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/add_edge.py +0 -0
  33. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/add_step.py +0 -0
  34. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/add_tool.py +0 -0
  35. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/remove_edge.py +0 -0
  36. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/remove_step.py +0 -0
  37. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/remove_tool.py +0 -0
  38. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/set_config.py +0 -0
  39. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/set_param.py +0 -0
  40. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/set_position.py +0 -0
  41. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/__init__.py +0 -0
  42. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/base.py +0 -0
  43. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/__init__.py +0 -0
  44. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/anthropic.py +0 -0
  45. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/default.py +0 -0
  46. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/message.py +0 -0
  47. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/openai.py +0 -0
  48. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/string.py +0 -0
  49. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/timbal.py +0 -0
  50. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/registry.py +0 -0
  51. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/__init__.py +0 -0
  52. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/agent.py +0 -0
  53. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/fallback_model.py +0 -0
  54. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/llm_router.py +0 -0
  55. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/mcp.py +0 -0
  56. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/memory_compaction.py +0 -0
  57. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/models.py +0 -0
  58. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/runnable.py +0 -0
  59. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/skill.py +0 -0
  60. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/test_model.py +0 -0
  61. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/tool.py +0 -0
  62. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/tool_set.py +0 -0
  63. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/workflow.py +0 -0
  64. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/errors.py +0 -0
  65. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/__init__.py +0 -0
  66. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/cli.py +0 -0
  67. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/display.py +0 -0
  68. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/agent.py +0 -0
  69. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_examples.yaml +0 -0
  70. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_flow_validators.yaml +0 -0
  71. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_negations.yaml +0 -0
  72. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_parallel.yaml +0 -0
  73. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_subagent.yaml +0 -0
  74. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_transforms.yaml +0 -0
  75. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/test_invalid_validator.yaml +0 -0
  76. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/models.py +0 -0
  77. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/runner.py +0 -0
  78. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/utils.py +0 -0
  79. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/__init__.py +0 -0
  80. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/base.py +0 -0
  81. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/comparison_base.py +0 -0
  82. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/contains.py +0 -0
  83. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/contains_all.py +0 -0
  84. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/contains_any.py +0 -0
  85. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/context.py +0 -0
  86. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/email.py +0 -0
  87. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/ends_with.py +0 -0
  88. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/eq.py +0 -0
  89. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/gt.py +0 -0
  90. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/gte.py +0 -0
  91. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/json.py +0 -0
  92. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/language.py +0 -0
  93. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/length.py +0 -0
  94. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/llm_base.py +0 -0
  95. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/lt.py +0 -0
  96. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/lte.py +0 -0
  97. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/max_length.py +0 -0
  98. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/min_length.py +0 -0
  99. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/not_null.py +0 -0
  100. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/parallel.py +0 -0
  101. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/pattern.py +0 -0
  102. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/prompt.py +0 -0
  103. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/semantic.py +0 -0
  104. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/seq.py +0 -0
  105. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/starts_with.py +0 -0
  106. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/type.py +0 -0
  107. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/logs.py +0 -0
  108. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/models.yaml +0 -0
  109. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/__init__.py +0 -0
  110. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/integrations.py +0 -0
  111. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/knowledge_bases/__init__.py +0 -0
  112. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/knowledge_bases/query.py +0 -0
  113. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/tool_proxy.py +0 -0
  114. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/types.py +0 -0
  115. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/utils.py +0 -0
  116. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/__init__.py +0 -0
  117. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/__main__.py +0 -0
  118. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/http.py +0 -0
  119. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/jobs.py +0 -0
  120. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/voice.html +0 -0
  121. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/voice.py +0 -0
  122. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/__init__.py +0 -0
  123. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/config.py +0 -0
  124. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/config_loader.py +0 -0
  125. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/context.py +0 -0
  126. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/dependency_analyzer.py +0 -0
  127. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/__init__.py +0 -0
  128. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/exporters/__init__.py +0 -0
  129. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/exporters/otel.py +0 -0
  130. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/__init__.py +0 -0
  131. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/base.py +0 -0
  132. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/in_memory.py +0 -0
  133. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/jsonl.py +0 -0
  134. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/platform.py +0 -0
  135. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/sqlite.py +0 -0
  136. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/span.py +0 -0
  137. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/trace.py +0 -0
  138. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/__init__.py +0 -0
  139. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/_creds.py +0 -0
  140. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/asana.py +0 -0
  141. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/bash.py +0 -0
  142. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/cala.py +0 -0
  143. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/cloudflare.py +0 -0
  144. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/dynamics_business_central.py +0 -0
  145. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/dynamics_sales.py +0 -0
  146. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/edit.py +0 -0
  147. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/elasticsearch.py +0 -0
  148. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/elevenlabs.py +0 -0
  149. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/excel.py +0 -0
  150. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/fal.py +0 -0
  151. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/fathom.py +0 -0
  152. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/firecrawl.py +0 -0
  153. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/gemini_images.py +0 -0
  154. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/gmail.py +0 -0
  155. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_analytics.py +0 -0
  156. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_business.py +0 -0
  157. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_calendar.py +0 -0
  158. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_docs.py +0 -0
  159. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_drive.py +0 -0
  160. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_maps.py +0 -0
  161. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_merchant_center.py +0 -0
  162. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_search_console.py +0 -0
  163. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_sheets.py +0 -0
  164. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/happy_scribe.py +0 -0
  165. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/hubspot.py +0 -0
  166. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/interaction.py +0 -0
  167. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/jira.py +0 -0
  168. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/klaviyo.py +0 -0
  169. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/knowledge_base.py +0 -0
  170. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/lancedb.py +0 -0
  171. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/linkedin.py +0 -0
  172. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/mongodb.py +0 -0
  173. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/netsuite.py +0 -0
  174. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/onedrive.py +0 -0
  175. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/outlook.py +0 -0
  176. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/pinecone.py +0 -0
  177. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/powerbi.py +0 -0
  178. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/quiver_ai.py +0 -0
  179. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/read.py +0 -0
  180. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/replicate.py +0 -0
  181. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/resend.py +0 -0
  182. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/salesforce.py +0 -0
  183. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/scraperapi.py +0 -0
  184. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/sharepoint.py +0 -0
  185. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/shopify.py +0 -0
  186. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/slack.py +0 -0
  187. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/stripe.py +0 -0
  188. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/tavily.py +0 -0
  189. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/web_search.py +0 -0
  190. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/write.py +0 -0
  191. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/xai.py +0 -0
  192. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/zendesk.py +0 -0
  193. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/zoho_crm.py +0 -0
  194. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/__init__.py +0 -0
  195. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/approval.py +0 -0
  196. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/__init__.py +0 -0
  197. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/base.py +0 -0
  198. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/custom.py +0 -0
  199. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/file.py +0 -0
  200. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/text.py +0 -0
  201. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/thinking.py +0 -0
  202. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/tool_result.py +0 -0
  203. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/tool_use.py +0 -0
  204. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/__init__.py +0 -0
  205. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/approval.py +0 -0
  206. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/base.py +0 -0
  207. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/delta.py +0 -0
  208. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/interaction.py +0 -0
  209. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/output.py +0 -0
  210. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/start.py +0 -0
  211. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/file.py +0 -0
  212. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/message.py +0 -0
  213. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/run_status.py +0 -0
  214. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/__init__.py +0 -0
  215. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/import_spec.py +0 -0
  216. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/model.py +0 -0
  217. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/net.py +0 -0
  218. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/schema.py +0 -0
  219. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/serialization.py +0 -0
  220. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/voice/__init__.py +0 -0
  221. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/voice/elevenlabs.py +0 -0
  222. {timbal-2.2.0 → timbal-2.2.1}/python/timbal/voice/session.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: timbal
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Simple, performant, battle-tested framework for building reliable AI applications
5
5
  Project-URL: Source, https://github.com/timbal-ai/timbal
6
6
  Author-email: Timbal <team@timbal.ai>
@@ -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 = '2.2.0'
22
- __version_tuple__ = version_tuple = (2, 2, 0)
21
+ __version__ = version = '2.2.1'
22
+ __version_tuple__ = version_tuple = (2, 2, 1)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -71,8 +71,20 @@ def _extract_key_from_lambda(fn: Any, source_step: str) -> str | None:
71
71
 
72
72
 
73
73
  def _is_model_enum(values: list) -> bool:
74
- """Return True if a list of enum values looks like LLM model IDs (provider/name)."""
75
- return len(values) > 5 and all(isinstance(v, str) and "/" in v for v in values[:5])
74
+ """Return True if an enum is the canonical LLM model ID set (provider/name).
75
+
76
+ Matches against ``timbal.core.models.Model`` rather than guessing from shape:
77
+ other registries (e.g. Krea's image/video IDs) share the ``provider/name``
78
+ form but must keep their enum inline so editors resolve the right options.
79
+ """
80
+ if len(values) <= 5 or not all(isinstance(v, str) and "/" in v for v in values[:5]):
81
+ return False
82
+ import typing
83
+
84
+ from timbal.core.models import Model
85
+
86
+ known = set(typing.get_args(Model))
87
+ return all(v in known for v in values)
76
88
 
77
89
 
78
90
  def _compact_field(field: dict) -> dict:
@@ -26,6 +26,72 @@ _FAILED_STATUSES = frozenset({"failed", "cancelled"})
26
26
 
27
27
  MediaKind = Literal["video", "image"]
28
28
 
29
+ # Model identifiers map directly to Krea's POST /generate/{media}/{provider}/{model} endpoints.
30
+ # Source of truth: https://api.krea.ai/openapi.json. Update when Krea adds/removes models.
31
+ KreaImageModel = Literal[
32
+ "bfl/flux-1-dev",
33
+ "bfl/flux-1-kontext-dev",
34
+ "bfl/flux-1.1-pro",
35
+ "bfl/flux-1.1-pro-ultra",
36
+ "bytedance/seededit",
37
+ "bytedance/seedream-4",
38
+ "bytedance/seedream-5-lite",
39
+ "google/imagen-3",
40
+ "google/imagen-4",
41
+ "google/imagen-4-fast",
42
+ "google/imagen-4-ultra",
43
+ "google/nano-banana",
44
+ "google/nano-banana-2",
45
+ "google/nano-banana-pro",
46
+ "ideogram/ideogram-2-turbo",
47
+ "ideogram/ideogram-3",
48
+ "krea/krea-2/large",
49
+ "krea/krea-2/medium",
50
+ "krea/krea-2/medium-turbo",
51
+ "luma/uni-1",
52
+ "openai/gpt-image",
53
+ "openai/gpt-image-2",
54
+ "qwen/2512",
55
+ "runway/gen-4-image",
56
+ "z-image/z-image",
57
+ ]
58
+
59
+ KreaVideoModel = Literal[
60
+ "alibaba/wan-2.1",
61
+ "alibaba/wan-2.2",
62
+ "alibaba/wan-2.5",
63
+ "bytedance/seedance-1.0-pro",
64
+ "bytedance/seedance-1.0-pro-fast",
65
+ "bytedance/seedance-2",
66
+ "bytedance/seedance-2-fast",
67
+ "google/veo-2",
68
+ "google/veo-3",
69
+ "google/veo-3-fast",
70
+ "google/veo-3.1",
71
+ "google/veo-3.1-fast",
72
+ "google/veo-3.1-lite",
73
+ "kling/kling-1",
74
+ "kling/kling-1.5",
75
+ "kling/kling-1.6",
76
+ "kling/kling-2",
77
+ "kling/kling-2.1",
78
+ "kling/kling-2.5",
79
+ "kling/kling-2.6",
80
+ "kling/kling-3.0",
81
+ "kling/kling-o1",
82
+ "lightricks/ltx-video-2.3-22b",
83
+ "luma/ray-2",
84
+ "minimax/hailuo",
85
+ "minimax/hailuo-02",
86
+ "minimax/hailuo-2.3",
87
+ "minimax/hailuo-2.3-fast",
88
+ "runway/aleph",
89
+ "runway/gen-3",
90
+ "runway/gen-4-video",
91
+ "runway/gen-4.5",
92
+ "xai/grok-video",
93
+ ]
94
+
29
95
 
30
96
  def _krea_headers(api_key: str, *, webhook_url: str | None = None) -> dict[str, str]:
31
97
  headers = {
@@ -248,9 +314,9 @@ class KreaGenerateVideo(Tool):
248
314
  def __init__(self, **kwargs: Any) -> None:
249
315
  async def _krea_generate_video(
250
316
  prompt: str = Field(..., description="Text description of the video to generate."),
251
- model: str = Field(
317
+ model: KreaVideoModel = Field(
252
318
  "google/veo-3.1-fast",
253
- description="Krea video model path: provider/model (e.g. google/veo-3.1-fast).",
319
+ description="Krea video model as provider/model (e.g. google/veo-3.1-fast, kling/kling-2.5).",
254
320
  ),
255
321
  aspect_ratio: str = Field("16:9", description="Aspect ratio when supported by the model."),
256
322
  duration: int | None = Field(None, description="Duration in seconds when supported by the model."),
@@ -279,89 +345,74 @@ class KreaGenerateVideo(Tool):
279
345
  start = time.monotonic()
280
346
  resolved_model = model.strip()
281
347
 
282
- try:
283
- if not prompt or not prompt.strip():
284
- raise ValueError("prompt is required and must be non-empty")
285
-
286
- payload: dict[str, Any] = {"prompt": prompt.strip()}
287
- if aspect_ratio:
288
- payload["aspect_ratio"] = aspect_ratio
289
- if duration is not None:
290
- payload["duration"] = duration
291
- if resolution is not None:
292
- payload["resolution"] = resolution
293
- if generate_audio is not None:
294
- payload["generate_audio"] = generate_audio
295
- if start_image:
296
- payload["start_image"] = start_image
297
- if end_image:
298
- payload["end_image"] = end_image
299
- if reference_images:
300
- payload["reference_images"] = reference_images
301
- if provider_params:
302
- for key, value in provider_params.items():
303
- if value is not None:
304
- payload[key] = value
305
-
306
- path = _build_generate_path("video", resolved_model)
307
- api_key = await resolve_api_key(tool=self, provider_name="Krea", env_var="KREA_API_KEY")
308
- import httpx
309
-
310
- async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=None)) as client:
311
- submit = await client.post(
312
- f"{_KREA_BASE}{path}",
313
- headers=_krea_headers(api_key, webhook_url=webhook_url),
314
- json=payload,
315
- )
316
- await _raise_for_krea_response(submit)
317
- submit_data = submit.json()
318
-
319
- job_id = submit_data.get("job_id")
320
- if not isinstance(job_id, str) or not job_id:
321
- raise ValueError(f"Krea video API returned no job_id: {submit_data}")
322
-
323
- job = await _poll_krea_job(
324
- client,
325
- api_key=api_key,
326
- job_id=job_id,
327
- poll_interval=poll_interval,
328
- timeout=timeout,
329
- )
330
-
331
- urls = _extract_job_urls(job)
332
- if not urls:
333
- raise ValueError(f"No output URLs in completed Krea job: {job}")
334
-
335
- elapsed = time.monotonic() - start
336
- logger.info(
337
- "Krea video generated",
338
- model=resolved_model,
348
+ if not prompt or not prompt.strip():
349
+ raise ValueError("prompt is required and must be non-empty")
350
+
351
+ payload: dict[str, Any] = {"prompt": prompt.strip()}
352
+ if aspect_ratio:
353
+ payload["aspect_ratio"] = aspect_ratio
354
+ if duration is not None:
355
+ payload["duration"] = duration
356
+ if resolution is not None:
357
+ payload["resolution"] = resolution
358
+ if generate_audio is not None:
359
+ payload["generate_audio"] = generate_audio
360
+ if start_image:
361
+ payload["start_image"] = start_image
362
+ if end_image:
363
+ payload["end_image"] = end_image
364
+ if reference_images:
365
+ payload["reference_images"] = reference_images
366
+ if provider_params:
367
+ for key, value in provider_params.items():
368
+ if value is not None:
369
+ payload[key] = value
370
+
371
+ path = _build_generate_path("video", resolved_model)
372
+ api_key = await resolve_api_key(tool=self, provider_name="Krea", env_var="KREA_API_KEY")
373
+ import httpx
374
+
375
+ async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=None)) as client:
376
+ submit = await client.post(
377
+ f"{_KREA_BASE}{path}",
378
+ headers=_krea_headers(api_key, webhook_url=webhook_url),
379
+ json=payload,
380
+ )
381
+ await _raise_for_krea_response(submit)
382
+ submit_data = submit.json()
383
+
384
+ job_id = submit_data.get("job_id")
385
+ if not isinstance(job_id, str) or not job_id:
386
+ raise ValueError(f"Krea video API returned no job_id: {submit_data}")
387
+
388
+ job = await _poll_krea_job(
389
+ client,
390
+ api_key=api_key,
339
391
  job_id=job_id,
340
- elapsed_s=round(elapsed, 2),
392
+ poll_interval=poll_interval,
393
+ timeout=timeout,
341
394
  )
342
- return {
343
- "success": True,
344
- "model": resolved_model,
345
- "job_id": job_id,
346
- "video_url": urls[0],
347
- "urls": urls,
348
- "job": job,
349
- "elapsed_seconds": round(elapsed, 2),
350
- }
351
-
352
- except Exception as exc:
353
- elapsed = time.monotonic() - start
354
- logger.error("Krea video generation failed", model=resolved_model, error=str(exc))
355
- return {
356
- "success": False,
357
- "model": resolved_model,
358
- "job_id": None,
359
- "video_url": None,
360
- "urls": [],
361
- "error": str(exc),
362
- "error_type": type(exc).__name__,
363
- "elapsed_seconds": round(elapsed, 2),
364
- }
395
+
396
+ urls = _extract_job_urls(job)
397
+ if not urls:
398
+ raise ValueError(f"No output URLs in completed Krea job: {job}")
399
+
400
+ elapsed = time.monotonic() - start
401
+ logger.info(
402
+ "Krea video generated",
403
+ model=resolved_model,
404
+ job_id=job_id,
405
+ elapsed_s=round(elapsed, 2),
406
+ )
407
+ return {
408
+ "success": True,
409
+ "model": resolved_model,
410
+ "job_id": job_id,
411
+ "video_url": urls[0],
412
+ "urls": urls,
413
+ "job": job,
414
+ "elapsed_seconds": round(elapsed, 2),
415
+ }
365
416
 
366
417
  super().__init__(handler=_krea_generate_video, **kwargs)
367
418
 
@@ -385,9 +436,9 @@ class KreaGenerateImage(Tool):
385
436
  def __init__(self, **kwargs: Any) -> None:
386
437
  async def _krea_generate_image(
387
438
  prompt: str = Field(..., description="Text description of the image to generate."),
388
- model: str = Field(
439
+ model: KreaImageModel = Field(
389
440
  "bfl/flux-1-dev",
390
- description="Krea image model path: provider/model (e.g. bfl/flux-1-dev).",
441
+ description="Krea image model as provider/model (e.g. bfl/flux-1-dev, krea/krea-2/large).",
391
442
  ),
392
443
  width: int | None = Field(None, description="Output width in pixels when supported."),
393
444
  height: int | None = Field(None, description="Output height in pixels when supported."),
@@ -407,82 +458,67 @@ class KreaGenerateImage(Tool):
407
458
  start = time.monotonic()
408
459
  resolved_model = model.strip()
409
460
 
410
- try:
411
- if not prompt or not prompt.strip():
412
- raise ValueError("prompt is required and must be non-empty")
413
-
414
- payload: dict[str, Any] = {"prompt": prompt.strip()}
415
- if width is not None:
416
- payload["width"] = width
417
- if height is not None:
418
- payload["height"] = height
419
- if seed is not None:
420
- payload["seed"] = seed
421
- if image_url:
422
- payload["image_url"] = image_url
423
- if provider_params:
424
- for key, value in provider_params.items():
425
- if value is not None:
426
- payload[key] = value
427
-
428
- path = _build_generate_path("image", resolved_model)
429
- api_key = await resolve_api_key(tool=self, provider_name="Krea", env_var="KREA_API_KEY")
430
- import httpx
431
-
432
- async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=None)) as client:
433
- submit = await client.post(
434
- f"{_KREA_BASE}{path}",
435
- headers=_krea_headers(api_key, webhook_url=webhook_url),
436
- json=payload,
437
- )
438
- await _raise_for_krea_response(submit)
439
- submit_data = submit.json()
440
-
441
- job_id = submit_data.get("job_id")
442
- if not isinstance(job_id, str) or not job_id:
443
- raise ValueError(f"Krea image API returned no job_id: {submit_data}")
444
-
445
- job = await _poll_krea_job(
446
- client,
447
- api_key=api_key,
448
- job_id=job_id,
449
- poll_interval=poll_interval,
450
- timeout=timeout,
451
- )
452
-
453
- urls = _extract_job_urls(job)
454
- if not urls:
455
- raise ValueError(f"No output URLs in completed Krea job: {job}")
456
-
457
- elapsed = time.monotonic() - start
458
- logger.info(
459
- "Krea image generated",
460
- model=resolved_model,
461
+ if not prompt or not prompt.strip():
462
+ raise ValueError("prompt is required and must be non-empty")
463
+
464
+ payload: dict[str, Any] = {"prompt": prompt.strip()}
465
+ if width is not None:
466
+ payload["width"] = width
467
+ if height is not None:
468
+ payload["height"] = height
469
+ if seed is not None:
470
+ payload["seed"] = seed
471
+ if image_url:
472
+ payload["image_url"] = image_url
473
+ if provider_params:
474
+ for key, value in provider_params.items():
475
+ if value is not None:
476
+ payload[key] = value
477
+
478
+ path = _build_generate_path("image", resolved_model)
479
+ api_key = await resolve_api_key(tool=self, provider_name="Krea", env_var="KREA_API_KEY")
480
+ import httpx
481
+
482
+ async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=None)) as client:
483
+ submit = await client.post(
484
+ f"{_KREA_BASE}{path}",
485
+ headers=_krea_headers(api_key, webhook_url=webhook_url),
486
+ json=payload,
487
+ )
488
+ await _raise_for_krea_response(submit)
489
+ submit_data = submit.json()
490
+
491
+ job_id = submit_data.get("job_id")
492
+ if not isinstance(job_id, str) or not job_id:
493
+ raise ValueError(f"Krea image API returned no job_id: {submit_data}")
494
+
495
+ job = await _poll_krea_job(
496
+ client,
497
+ api_key=api_key,
461
498
  job_id=job_id,
462
- elapsed_s=round(elapsed, 2),
499
+ poll_interval=poll_interval,
500
+ timeout=timeout,
463
501
  )
464
- return {
465
- "success": True,
466
- "model": resolved_model,
467
- "job_id": job_id,
468
- "image_url": urls[0],
469
- "urls": urls,
470
- "job": job,
471
- "elapsed_seconds": round(elapsed, 2),
472
- }
473
-
474
- except Exception as exc:
475
- elapsed = time.monotonic() - start
476
- logger.error("Krea image generation failed", model=resolved_model, error=str(exc))
477
- return {
478
- "success": False,
479
- "model": resolved_model,
480
- "job_id": None,
481
- "image_url": None,
482
- "urls": [],
483
- "error": str(exc),
484
- "error_type": type(exc).__name__,
485
- "elapsed_seconds": round(elapsed, 2),
486
- }
502
+
503
+ urls = _extract_job_urls(job)
504
+ if not urls:
505
+ raise ValueError(f"No output URLs in completed Krea job: {job}")
506
+
507
+ elapsed = time.monotonic() - start
508
+ logger.info(
509
+ "Krea image generated",
510
+ model=resolved_model,
511
+ job_id=job_id,
512
+ elapsed_s=round(elapsed, 2),
513
+ )
514
+ return {
515
+ "success": True,
516
+ "model": resolved_model,
517
+ "job_id": job_id,
518
+ "image_url": urls[0],
519
+ "urls": urls,
520
+ "job": job,
521
+ "elapsed_seconds": round(elapsed, 2),
522
+ }
487
523
 
488
524
  super().__init__(handler=_krea_generate_image, **kwargs)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes