timbal 2.3.2__tar.gz → 2.3.4__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. {timbal-2.3.2 → timbal-2.3.4}/PKG-INFO +1 -1
  2. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/_version.py +2 -2
  3. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/tool.py +26 -16
  4. timbal-2.3.4/python/timbal/server/playground.py +277 -0
  5. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/voice.html +667 -79
  6. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/voice.py +34 -24
  7. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/config.py +5 -1
  8. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/turn_detection.py +35 -21
  9. {timbal-2.3.2 → timbal-2.3.4}/.gitignore +0 -0
  10. {timbal-2.3.2 → timbal-2.3.4}/LICENSE +0 -0
  11. {timbal-2.3.2 → timbal-2.3.4}/README.md +0 -0
  12. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/chat-completions.mdx +0 -0
  13. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/create-from-workforce.mdx +0 -0
  14. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/jobs/cancel.mdx +0 -0
  15. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/jobs/create.mdx +0 -0
  16. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/jobs/get.mdx +0 -0
  17. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/jobs/list.mdx +0 -0
  18. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/jobs/retry.mdx +0 -0
  19. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/link.mdx +0 -0
  20. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/list-context-vars.mdx +0 -0
  21. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/list-policies.mdx +0 -0
  22. {timbal-2.3.2 → timbal-2.3.4}/docs/api-reference/ace/unlink.mdx +0 -0
  23. {timbal-2.3.2 → timbal-2.3.4}/pyproject.toml +0 -0
  24. {timbal-2.3.2 → timbal-2.3.4}/pyrightconfig.json +0 -0
  25. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/__init__.py +0 -0
  26. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/__init__.py +0 -0
  27. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/__main__.py +0 -0
  28. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/cli_utils.py +0 -0
  29. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/cst_utils.py +0 -0
  30. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/flow.py +0 -0
  31. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/format.py +0 -0
  32. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/model_discovery.py +0 -0
  33. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/test.py +0 -0
  34. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/tool_discovery.py +0 -0
  35. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/__init__.py +0 -0
  36. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/add_edge.py +0 -0
  37. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/add_mcp.py +0 -0
  38. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/add_step.py +0 -0
  39. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/add_tool.py +0 -0
  40. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/remove_edge.py +0 -0
  41. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/remove_step.py +0 -0
  42. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/remove_tool.py +0 -0
  43. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/set_config.py +0 -0
  44. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/set_param.py +0 -0
  45. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/codegen/transformers/set_position.py +0 -0
  46. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/__init__.py +0 -0
  47. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/base.py +0 -0
  48. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/__init__.py +0 -0
  49. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/anthropic.py +0 -0
  50. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/default.py +0 -0
  51. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/message.py +0 -0
  52. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/openai.py +0 -0
  53. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/string.py +0 -0
  54. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/impl/timbal.py +0 -0
  55. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/collectors/registry.py +0 -0
  56. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/__init__.py +0 -0
  57. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/agent.py +0 -0
  58. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/fallback_model.py +0 -0
  59. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/llm_router.py +0 -0
  60. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/mcp.py +0 -0
  61. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/memory_compaction.py +0 -0
  62. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/models.py +0 -0
  63. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/runnable.py +0 -0
  64. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/skill.py +0 -0
  65. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/test_model.py +0 -0
  66. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/tool_set.py +0 -0
  67. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/core/workflow.py +0 -0
  68. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/errors.py +0 -0
  69. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/__init__.py +0 -0
  70. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/cli.py +0 -0
  71. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/display.py +0 -0
  72. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/agent.py +0 -0
  73. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/eval_examples.yaml +0 -0
  74. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/eval_flow_validators.yaml +0 -0
  75. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/eval_negations.yaml +0 -0
  76. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/eval_parallel.yaml +0 -0
  77. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/eval_subagent.yaml +0 -0
  78. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/eval_transforms.yaml +0 -0
  79. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/fixtures/test_invalid_validator.yaml +0 -0
  80. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/models.py +0 -0
  81. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/reporters.py +0 -0
  82. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/runner.py +0 -0
  83. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/utils.py +0 -0
  84. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/__init__.py +0 -0
  85. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/base.py +0 -0
  86. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/comparison_base.py +0 -0
  87. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/contains.py +0 -0
  88. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/contains_all.py +0 -0
  89. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/contains_any.py +0 -0
  90. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/context.py +0 -0
  91. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/email.py +0 -0
  92. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/ends_with.py +0 -0
  93. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/eq.py +0 -0
  94. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/gt.py +0 -0
  95. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/gte.py +0 -0
  96. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/json.py +0 -0
  97. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/language.py +0 -0
  98. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/length.py +0 -0
  99. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/llm_base.py +0 -0
  100. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/lt.py +0 -0
  101. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/lte.py +0 -0
  102. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/max_length.py +0 -0
  103. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/min_length.py +0 -0
  104. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/not_null.py +0 -0
  105. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/parallel.py +0 -0
  106. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/pattern.py +0 -0
  107. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/prompt.py +0 -0
  108. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/semantic.py +0 -0
  109. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/seq.py +0 -0
  110. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/starts_with.py +0 -0
  111. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/evals/validators/type.py +0 -0
  112. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/logs.py +0 -0
  113. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/models.yaml +0 -0
  114. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/__init__.py +0 -0
  115. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/integrations.py +0 -0
  116. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/knowledge_bases/__init__.py +0 -0
  117. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/knowledge_bases/query.py +0 -0
  118. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/tool_proxy.py +0 -0
  119. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/types.py +0 -0
  120. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/platform/utils.py +0 -0
  121. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/__init__.py +0 -0
  122. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/__main__.py +0 -0
  123. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/http.py +0 -0
  124. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/jobs.py +0 -0
  125. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/recording_upload.py +0 -0
  126. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/rtc.py +0 -0
  127. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/server/single_session.py +0 -0
  128. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/__init__.py +0 -0
  129. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/config.py +0 -0
  130. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/config_loader.py +0 -0
  131. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/context.py +0 -0
  132. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/dependency_analyzer.py +0 -0
  133. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/__init__.py +0 -0
  134. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/exporters/__init__.py +0 -0
  135. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/exporters/otel.py +0 -0
  136. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/providers/__init__.py +0 -0
  137. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/providers/base.py +0 -0
  138. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/providers/in_memory.py +0 -0
  139. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/providers/jsonl.py +0 -0
  140. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/providers/platform.py +0 -0
  141. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/providers/sqlite.py +0 -0
  142. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/span.py +0 -0
  143. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/state/tracing/trace.py +0 -0
  144. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/__init__.py +0 -0
  145. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/_creds.py +0 -0
  146. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/aircall.py +0 -0
  147. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/asana.py +0 -0
  148. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/bash.py +0 -0
  149. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/cala.py +0 -0
  150. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/cloudflare.py +0 -0
  151. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/connectif.py +0 -0
  152. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/dynamics_business_central.py +0 -0
  153. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/dynamics_sales.py +0 -0
  154. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/edit.py +0 -0
  155. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/elasticsearch.py +0 -0
  156. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/elevenlabs.py +0 -0
  157. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/excel.py +0 -0
  158. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/fal.py +0 -0
  159. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/fathom.py +0 -0
  160. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/firecrawl.py +0 -0
  161. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/gemini_images.py +0 -0
  162. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/gmail.py +0 -0
  163. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_analytics.py +0 -0
  164. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_business.py +0 -0
  165. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_calendar.py +0 -0
  166. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_docs.py +0 -0
  167. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_drive.py +0 -0
  168. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_maps.py +0 -0
  169. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_merchant_center.py +0 -0
  170. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_search_console.py +0 -0
  171. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/google_sheets.py +0 -0
  172. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/happy_scribe.py +0 -0
  173. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/higgsfield.py +0 -0
  174. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/hubspot.py +0 -0
  175. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/interaction.py +0 -0
  176. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/jira.py +0 -0
  177. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/klaviyo.py +0 -0
  178. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/knowledge_base.py +0 -0
  179. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/krea.py +0 -0
  180. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/lancedb.py +0 -0
  181. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/linkedin.py +0 -0
  182. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/mongodb.py +0 -0
  183. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/netsuite.py +0 -0
  184. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/onedrive.py +0 -0
  185. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/outlook.py +0 -0
  186. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/parallel.py +0 -0
  187. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/pinecone.py +0 -0
  188. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/powerbi.py +0 -0
  189. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/quiver_ai.py +0 -0
  190. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/read.py +0 -0
  191. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/replicate.py +0 -0
  192. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/resend.py +0 -0
  193. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/salesforce.py +0 -0
  194. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/scraperapi.py +0 -0
  195. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/sharepoint.py +0 -0
  196. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/shopify.py +0 -0
  197. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/slack.py +0 -0
  198. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/stripe.py +0 -0
  199. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/tavily.py +0 -0
  200. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/web_search.py +0 -0
  201. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/write.py +0 -0
  202. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/xai.py +0 -0
  203. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/zendesk.py +0 -0
  204. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/tools/zoho_crm.py +0 -0
  205. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/__init__.py +0 -0
  206. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/approval.py +0 -0
  207. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/__init__.py +0 -0
  208. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/base.py +0 -0
  209. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/custom.py +0 -0
  210. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/file.py +0 -0
  211. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/text.py +0 -0
  212. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/thinking.py +0 -0
  213. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/tool_result.py +0 -0
  214. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/content/tool_use.py +0 -0
  215. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/__init__.py +0 -0
  216. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/approval.py +0 -0
  217. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/base.py +0 -0
  218. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/delta.py +0 -0
  219. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/interaction.py +0 -0
  220. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/output.py +0 -0
  221. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/events/start.py +0 -0
  222. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/file.py +0 -0
  223. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/message.py +0 -0
  224. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/types/run_status.py +0 -0
  225. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/utils/__init__.py +0 -0
  226. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/utils/import_spec.py +0 -0
  227. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/utils/model.py +0 -0
  228. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/utils/net.py +0 -0
  229. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/utils/schema.py +0 -0
  230. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/utils/serialization.py +0 -0
  231. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/__init__.py +0 -0
  232. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/_whisper_features.py +0 -0
  233. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/ambience.py +0 -0
  234. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/deepgram.py +0 -0
  235. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/elevenlabs.py +0 -0
  236. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/endpointing.py +0 -0
  237. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/eou.py +0 -0
  238. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/events.py +0 -0
  239. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/metrics.py +0 -0
  240. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/namo.py +0 -0
  241. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/playback.py +0 -0
  242. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/providers.py +0 -0
  243. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/realtime.py +0 -0
  244. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/recording.py +0 -0
  245. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/session.py +0 -0
  246. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/smart_turn.py +0 -0
  247. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/vad.py +0 -0
  248. {timbal-2.3.2 → timbal-2.3.4}/python/timbal/voice/webrtc.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: timbal
3
- Version: 2.3.2
3
+ Version: 2.3.4
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.3.2'
22
- __version_tuple__ = version_tuple = (2, 3, 2)
21
+ __version__ = version = '2.3.4'
22
+ __version_tuple__ = version_tuple = (2, 3, 4)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -142,27 +142,37 @@ class Tool(Runnable):
142
142
  ``ToolProxyUnavailable`` so the user fixes platform setup rather than
143
143
  local provider credentials.
144
144
  """
145
+ cred_error: CredentialNotAvailable | None = None
145
146
  try:
146
147
  async for event, final_output, collector in super()._execute_handler(
147
148
  validated_input, run_context, span, event_queue
148
149
  ):
149
150
  yield (event, final_output, collector)
150
- except CredentialNotAvailable as cred_error:
151
- try:
152
- output = await execute_tool_proxy(self.name, validated_input)
153
- except ToolProxyUnavailable:
154
- if run_context.platform_config is None:
155
- # Local run without platform config — fall back to credential error.
156
- raise cred_error from None
157
- raise
158
- except PlatformError as proxy_error:
159
- # 403 is what the platform returns when no proxy is available for this
160
- # tool (no service-account credentials configured). 404/501 are kept as
161
- # fallbacks. In all these cases, surface the actionable credential error.
162
- if proxy_error.status_code in (403, 404, 501):
163
- raise cred_error from None
164
- raise
165
- yield (None, output, None)
151
+ except CredentialNotAvailable as e:
152
+ # Capture and fall through instead of calling the proxy here: anything
153
+ # raised inside this except block would implicitly chain the credential
154
+ # error as __context__, making unrelated proxy failures read as auth
155
+ # problems in tracebacks.
156
+ cred_error = e
157
+
158
+ if cred_error is None:
159
+ return
160
+
161
+ try:
162
+ output = await execute_tool_proxy(self.name, validated_input)
163
+ except ToolProxyUnavailable:
164
+ if run_context.platform_config is None:
165
+ # Local run without platform config — fall back to credential error.
166
+ raise cred_error from None
167
+ raise
168
+ except PlatformError as proxy_error:
169
+ # 403 is what the platform returns when no proxy is available for this
170
+ # tool (no service-account credentials configured). 404/501 are kept as
171
+ # fallbacks. In all these cases, surface the actionable credential error.
172
+ if proxy_error.status_code in (403, 404, 501):
173
+ raise cred_error from None
174
+ raise
175
+ yield (None, output, None)
166
176
 
167
177
  @override
168
178
  def nest(self, parent_path: str) -> None:
@@ -0,0 +1,277 @@
1
+ """Standalone voice playground launcher: ``python -m timbal.server.playground``.
2
+
3
+ Serves ``voice.html`` *without* a running agent underneath. The page detects it
4
+ was served raw (no injected runnable meta) and switches to standalone mode,
5
+ where you pick a target:
6
+
7
+ * **Local server** — pick an agent file (``path/to/agent.py::object``) and
8
+ press Start: the page asks *this* launcher to spawn ``uv run python -m
9
+ timbal.server --import_spec … --port …`` from the agent file's directory (so
10
+ ``uv`` resolves that project's environment and ``.env``), waits for the
11
+ healthcheck, and dials it. The port is picked automatically unless fixed in
12
+ the form. Changing the agent or port respawns on the next Start.
13
+ * **Platform** — a deployed workforce through ``api.timbal.ai`` /
14
+ ``api.dev.timbal.ai``. The page talks to the platform directly (ticket mint
15
+ for WS, bearer-authenticated POST for RTC); the launcher is not involved.
16
+
17
+ Deliberately stdlib-only: the launcher must work even when no agent project
18
+ (and therefore no fastapi/uvicorn environment) is set up yet.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import argparse
24
+ import json
25
+ import shutil
26
+ import socket
27
+ import subprocess
28
+ import threading
29
+ import webbrowser
30
+ from collections import deque
31
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
32
+ from pathlib import Path
33
+ from urllib.request import urlopen
34
+
35
+ from .. import __version__
36
+
37
+ _HTML_PATH = Path(__file__).parent / "voice.html"
38
+
39
+ _LOG_LINES = 400
40
+ _STOP_GRACE_SECS = 5.0
41
+
42
+
43
+ def _free_port() -> int:
44
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
45
+ s.bind(("127.0.0.1", 0))
46
+ return s.getsockname()[1]
47
+
48
+
49
+ def _healthy(port: int) -> bool:
50
+ try:
51
+ with urlopen(f"http://127.0.0.1:{port}/healthcheck", timeout=0.5) as resp:
52
+ return resp.status in (200, 204)
53
+ except Exception:
54
+ return False
55
+
56
+
57
+ class ChildServer:
58
+ """The single ``timbal.server`` subprocess this launcher manages."""
59
+
60
+ def __init__(self) -> None:
61
+ self._lock = threading.Lock()
62
+ self._proc: subprocess.Popen | None = None
63
+ self._port: int | None = None
64
+ self._import_spec: str | None = None
65
+ self._requested_spec: str | None = None
66
+ """The spec exactly as the client sent it — echoed in status so the page
67
+ can tell whether the running child matches its form without having to
68
+ replicate the launcher's path resolution."""
69
+ self._logs: deque[str] = deque(maxlen=_LOG_LINES)
70
+
71
+ def _reader(self, proc: subprocess.Popen) -> None:
72
+ assert proc.stdout is not None
73
+ for line in proc.stdout:
74
+ self._logs.append(line.rstrip("\n"))
75
+
76
+ def spawn(self, import_spec: str, port: int | None = None) -> dict:
77
+ spec = import_spec.strip()
78
+ parts = spec.split("::")
79
+ if len(parts) != 2 or not parts[0] or not parts[1]:
80
+ raise ValueError("Import spec must look like 'path/to/agent.py::object_name'.")
81
+ spec_path = Path(parts[0]).expanduser()
82
+ if not spec_path.is_absolute():
83
+ spec_path = Path.cwd() / spec_path
84
+ spec_path = spec_path.resolve()
85
+ if not spec_path.is_file():
86
+ raise ValueError(f"No such file: {spec_path}")
87
+ if shutil.which("uv") is None:
88
+ raise ValueError("'uv' was not found on PATH — install uv or start the server manually.")
89
+ resolved_spec = f"{spec_path}::{parts[1]}"
90
+
91
+ with self._lock:
92
+ self._stop_locked()
93
+ child_port = port or _free_port()
94
+ cmd = [
95
+ "uv",
96
+ "run",
97
+ "python",
98
+ "-m",
99
+ "timbal.server",
100
+ "--import_spec",
101
+ resolved_spec,
102
+ "--host",
103
+ "127.0.0.1",
104
+ "--port",
105
+ str(child_port),
106
+ ]
107
+ self._logs.clear()
108
+ self._logs.append(f"$ {' '.join(cmd)} (cwd: {spec_path.parent})")
109
+ # cwd = the agent file's directory: `uv run` walks up from there to
110
+ # find the agent project's pyproject/venv, and load_dotenv picks up
111
+ # that project's .env — not the launcher's.
112
+ proc = subprocess.Popen( # noqa: S603
113
+ cmd,
114
+ cwd=spec_path.parent,
115
+ stdout=subprocess.PIPE,
116
+ stderr=subprocess.STDOUT,
117
+ text=True,
118
+ )
119
+ self._proc = proc
120
+ self._port = child_port
121
+ self._import_spec = resolved_spec
122
+ self._requested_spec = spec
123
+ threading.Thread(target=self._reader, args=(proc,), daemon=True).start()
124
+ return self.status_locked()
125
+
126
+ def stop(self) -> dict:
127
+ with self._lock:
128
+ self._stop_locked()
129
+ return self.status_locked()
130
+
131
+ def _stop_locked(self) -> None:
132
+ proc = self._proc
133
+ if proc is None:
134
+ return
135
+ if proc.poll() is None:
136
+ proc.terminate()
137
+ try:
138
+ proc.wait(timeout=_STOP_GRACE_SECS)
139
+ except subprocess.TimeoutExpired:
140
+ proc.kill()
141
+ proc.wait(timeout=_STOP_GRACE_SECS)
142
+ self._proc = None
143
+ self._port = None
144
+ self._import_spec = None
145
+ self._requested_spec = None
146
+
147
+ def status(self) -> dict:
148
+ with self._lock:
149
+ return self.status_locked()
150
+
151
+ def status_locked(self) -> dict:
152
+ proc = self._proc
153
+ if proc is None:
154
+ # Keep the last logs around so a crash is inspectable after stop.
155
+ return {"state": "stopped", "logs": list(self._logs)}
156
+ exit_code = proc.poll()
157
+ if exit_code is not None:
158
+ return {
159
+ "state": "exited",
160
+ "exit_code": exit_code,
161
+ "port": self._port,
162
+ "import_spec": self._import_spec,
163
+ "requested_import_spec": self._requested_spec,
164
+ "logs": list(self._logs),
165
+ }
166
+ state = "running" if _healthy(self._port) else "starting"
167
+ return {
168
+ "state": state,
169
+ "pid": proc.pid,
170
+ "port": self._port,
171
+ "import_spec": self._import_spec,
172
+ "requested_import_spec": self._requested_spec,
173
+ "logs": list(self._logs),
174
+ }
175
+
176
+
177
+ def _make_handler(child: ChildServer, default_import_spec: str) -> type[BaseHTTPRequestHandler]:
178
+ class Handler(BaseHTTPRequestHandler):
179
+ server_version = f"timbal-playground/{__version__}"
180
+
181
+ def log_message(self, format: str, *args) -> None: # noqa: A002
182
+ pass # keep the terminal usable; the page shows child logs itself
183
+
184
+ def _send_json(self, status: int, payload: dict) -> None:
185
+ body = json.dumps(payload).encode("utf-8")
186
+ self.send_response(status)
187
+ self.send_header("Content-Type", "application/json")
188
+ self.send_header("Content-Length", str(len(body)))
189
+ self.end_headers()
190
+ self.wfile.write(body)
191
+
192
+ def do_GET(self) -> None: # noqa: N802
193
+ path = self.path.split("?", 1)[0].rstrip("/") or "/"
194
+ if path in ("/", "/voice"):
195
+ body = _HTML_PATH.read_bytes()
196
+ self.send_response(200)
197
+ self.send_header("Content-Type", "text/html; charset=utf-8")
198
+ self.send_header("Content-Length", str(len(body)))
199
+ self.end_headers()
200
+ self.wfile.write(body)
201
+ return
202
+ if path == "/launcher/status":
203
+ self._send_json(
204
+ 200,
205
+ {
206
+ "launcher": {"version": __version__, "default_import_spec": default_import_spec},
207
+ "child": child.status(),
208
+ },
209
+ )
210
+ return
211
+ self._send_json(404, {"error": "not found"})
212
+
213
+ def do_POST(self) -> None: # noqa: N802
214
+ path = self.path.split("?", 1)[0].rstrip("/")
215
+ length = int(self.headers.get("Content-Length") or 0)
216
+ try:
217
+ body = json.loads(self.rfile.read(length) or b"{}")
218
+ except json.JSONDecodeError:
219
+ self._send_json(400, {"error": "invalid JSON body"})
220
+ return
221
+ if path == "/launcher/spawn":
222
+ import_spec = str(body.get("import_spec") or "").strip()
223
+ if not import_spec:
224
+ self._send_json(400, {"error": "import_spec is required"})
225
+ return
226
+ port = body.get("port")
227
+ try:
228
+ status = child.spawn(import_spec, port=int(port) if port else None)
229
+ except ValueError as e:
230
+ self._send_json(400, {"error": str(e)})
231
+ return
232
+ except OSError as e:
233
+ self._send_json(500, {"error": f"spawn failed: {e}"})
234
+ return
235
+ self._send_json(200, {"child": status})
236
+ return
237
+ if path == "/launcher/stop":
238
+ self._send_json(200, {"child": child.stop()})
239
+ return
240
+ self._send_json(404, {"error": "not found"})
241
+
242
+ return Handler
243
+
244
+
245
+ def main(argv: list[str] | None = None) -> None:
246
+ parser = argparse.ArgumentParser(description="Standalone Timbal voice playground.")
247
+ parser.add_argument("--host", type=str, default="127.0.0.1", help="Host to bind the playground to.")
248
+ parser.add_argument("--port", type=int, default=7777, help="Port to bind the playground to.")
249
+ parser.add_argument(
250
+ "--import_spec",
251
+ "--import-spec",
252
+ dest="import_spec",
253
+ type=str,
254
+ default="",
255
+ help="Default import spec prefilled in the page's spawn field (path/to/agent.py::object).",
256
+ )
257
+ parser.add_argument("--no-open", action="store_true", help="Don't open the browser automatically.")
258
+ args = parser.parse_args(argv)
259
+
260
+ child = ChildServer()
261
+ handler = _make_handler(child, args.import_spec)
262
+ httpd = ThreadingHTTPServer((args.host, args.port), handler)
263
+ url = f"http://{'localhost' if args.host in ('0.0.0.0', '127.0.0.1') else args.host}:{args.port}/"
264
+ print(f"Voice playground at {url}") # noqa: T201
265
+ if not args.no_open:
266
+ webbrowser.open(url)
267
+ try:
268
+ httpd.serve_forever()
269
+ except KeyboardInterrupt:
270
+ pass
271
+ finally:
272
+ child.stop()
273
+ httpd.server_close()
274
+
275
+
276
+ if __name__ == "__main__":
277
+ main()