voodoo-framework 2.2.0__tar.gz → 2.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/PKG-INFO +5 -1
  2. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/pyproject.toml +5 -0
  3. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/__init__.py +1 -1
  4. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/__init__.py +4 -0
  5. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/doctor.py +48 -0
  6. voodoo_framework-2.3.0/src/voodoo/cli/status.py +73 -0
  7. voodoo_framework-2.3.0/src/voodoo/cli/workers_cmd.py +71 -0
  8. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/telemetry/__init__.py +4 -0
  9. voodoo_framework-2.3.0/src/voodoo/telemetry/otlp.py +108 -0
  10. voodoo_framework-2.3.0/src/voodoo/telemetry/store.py +355 -0
  11. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/workers/queue.py +9 -2
  12. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo_framework.egg-info/PKG-INFO +5 -1
  13. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo_framework.egg-info/SOURCES.txt +4 -0
  14. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo_framework.egg-info/requires.txt +5 -0
  15. voodoo_framework-2.3.0/tests/test_observability.py +459 -0
  16. voodoo_framework-2.2.0/src/voodoo/telemetry/store.py +0 -200
  17. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/LICENSE +0 -0
  18. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/README.md +0 -0
  19. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/setup.cfg +0 -0
  20. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/adapters/__init__.py +0 -0
  21. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/adapters/capabilities.py +0 -0
  22. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/adapters/registry.py +0 -0
  23. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/adapters/tailwind.py +0 -0
  24. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/adapters/voodoo_css.py +0 -0
  25. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/agent.py +0 -0
  26. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/agents/__init__.py +0 -0
  27. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/agents/models.py +0 -0
  28. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/agents/registry.py +0 -0
  29. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/__init__.py +0 -0
  30. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/agent.py +0 -0
  31. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/providers/__init__.py +0 -0
  32. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/providers/anthropic.py +0 -0
  33. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/providers/gemini.py +0 -0
  34. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/providers/mock.py +0 -0
  35. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/providers/ollama.py +0 -0
  36. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/providers/openai.py +0 -0
  37. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/tools/__init__.py +0 -0
  38. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ai/tools/registry.py +0 -0
  39. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/api.py +0 -0
  40. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/__init__.py +0 -0
  41. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/cookies.py +0 -0
  42. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/guards.py +0 -0
  43. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/jwt.py +0 -0
  44. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/middleware.py +0 -0
  45. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/passwords.py +0 -0
  46. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/auth/user.py +0 -0
  47. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/__main__.py +0 -0
  48. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/agents.py +0 -0
  49. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/ai.py +0 -0
  50. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/approvals.py +0 -0
  51. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/auth.py +0 -0
  52. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/dev.py +0 -0
  53. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/executions.py +0 -0
  54. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/generate.py +0 -0
  55. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/inspect.py +0 -0
  56. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/new.py +0 -0
  57. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/objects.py +0 -0
  58. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/recover.py +0 -0
  59. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/routes.py +0 -0
  60. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/scaffolding.py +0 -0
  61. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/schedules.py +0 -0
  62. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/tasks.py +0 -0
  63. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/terminal.py +0 -0
  64. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/theme.py +0 -0
  65. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/cli/version.py +0 -0
  66. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/components.py +0 -0
  67. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/config.py +0 -0
  68. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/__init__.py +0 -0
  69. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/app.py +0 -0
  70. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/errors.py +0 -0
  71. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/events.py +0 -0
  72. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/render.py +0 -0
  73. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/routing.py +0 -0
  74. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/sitemap.py +0 -0
  75. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/core/state.py +0 -0
  76. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/data/__init__.py +0 -0
  77. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/data/base.py +0 -0
  78. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/data/model.py +0 -0
  79. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/i18n.py +0 -0
  80. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/mcp/__init__.py +0 -0
  81. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/mcp/client.py +0 -0
  82. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/memory/__init__.py +0 -0
  83. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/memory/interfaces.py +0 -0
  84. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/memory/sqlite.py +0 -0
  85. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/mesh/__init__.py +0 -0
  86. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/mesh/client.py +0 -0
  87. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/mesh/event_bus.py +0 -0
  88. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/__init__.py +0 -0
  89. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/capability.py +0 -0
  90. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/compute.py +0 -0
  91. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/constraint.py +0 -0
  92. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/effect.py +0 -0
  93. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/intent.py +0 -0
  94. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/resource.py +0 -0
  95. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/state.py +0 -0
  96. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/primitives/time.py +0 -0
  97. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/py.typed +0 -0
  98. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/queue.py +0 -0
  99. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/routing/api.py +0 -0
  100. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/routing/pages.py +0 -0
  101. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/__init__.py +0 -0
  102. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/adaptive.py +0 -0
  103. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/capability.py +0 -0
  104. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/constraint.py +0 -0
  105. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/context.py +0 -0
  106. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/engine.py +0 -0
  107. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/errors.py +0 -0
  108. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/execution.py +0 -0
  109. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/graph.py +0 -0
  110. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/human.py +0 -0
  111. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/persistence.py +0 -0
  112. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/planner.py +0 -0
  113. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/scheduler.py +0 -0
  114. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/task.py +0 -0
  115. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/runtime/workflow.py +0 -0
  116. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/schedule.py +0 -0
  117. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/__init__.py +0 -0
  118. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/cors.py +0 -0
  119. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/csrf.py +0 -0
  120. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/headers.py +0 -0
  121. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/passwords.py +0 -0
  122. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/rate_limit.py +0 -0
  123. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/redaction.py +0 -0
  124. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/security/secrets.py +0 -0
  125. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/seo.py +0 -0
  126. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/static/client.js +0 -0
  127. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/status.py +0 -0
  128. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/__init__.py +0 -0
  129. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/cache/__init__.py +0 -0
  130. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/cache/interfaces.py +0 -0
  131. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/cache/memory.py +0 -0
  132. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/cache/redis.py +0 -0
  133. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/database/__init__.py +0 -0
  134. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/database/interfaces.py +0 -0
  135. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/database/postgres.py +0 -0
  136. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/database/sqlite.py +0 -0
  137. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/events/__init__.py +0 -0
  138. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/events/interfaces.py +0 -0
  139. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/events/local.py +0 -0
  140. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/events/postgres.py +0 -0
  141. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/events/sqlite.py +0 -0
  142. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/execution/__init__.py +0 -0
  143. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/execution/migrations.py +0 -0
  144. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/execution/postgres.py +0 -0
  145. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/execution/sqlite.py +0 -0
  146. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/manager.py +0 -0
  147. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/objects/__init__.py +0 -0
  148. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/objects/interfaces.py +0 -0
  149. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/objects/local.py +0 -0
  150. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/objects/s3.py +0 -0
  151. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/queue/__init__.py +0 -0
  152. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/queue/interfaces.py +0 -0
  153. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/queue/memory.py +0 -0
  154. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/queue/postgres.py +0 -0
  155. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/queue/redis.py +0 -0
  156. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/queue/sqlite.py +0 -0
  157. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/scheduler/__init__.py +0 -0
  158. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/storage/scheduler/sqlite.py +0 -0
  159. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/telemetry/api.py +0 -0
  160. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/telemetry/middleware.py +0 -0
  161. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/theme.py +0 -0
  162. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/tools/__init__.py +0 -0
  163. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/tools/registry.py +0 -0
  164. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/__init__.py +0 -0
  165. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/component.py +0 -0
  166. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/events.py +0 -0
  167. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/library.py +0 -0
  168. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/markdown.py +0 -0
  169. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/rendering.py +0 -0
  170. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/state.py +0 -0
  171. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/styles/__init__.py +0 -0
  172. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/styles/presets.py +0 -0
  173. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/ui/styles/theme.py +0 -0
  174. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo/workers/__init__.py +0 -0
  175. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo_framework.egg-info/dependency_links.txt +0 -0
  176. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo_framework.egg-info/entry_points.txt +0 -0
  177. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/src/voodoo_framework.egg-info/top_level.txt +0 -0
  178. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_agent.py +0 -0
  179. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_agent_registry.py +0 -0
  180. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_agent_runtime.py +0 -0
  181. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_app.py +0 -0
  182. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_auth.py +0 -0
  183. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_capability_security.py +0 -0
  184. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_checkpoint_resume.py +0 -0
  185. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_chrome.py +0 -0
  186. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_cli.py +0 -0
  187. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_cli_inspect.py +0 -0
  188. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_components.py +0 -0
  189. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_config.py +0 -0
  190. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_contract_api.py +0 -0
  191. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_data.py +0 -0
  192. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_design_system.py +0 -0
  193. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_durable_hitl.py +0 -0
  194. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_events.py +0 -0
  195. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_execution_sqlite_store.py +0 -0
  196. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_http_runtime.py +0 -0
  197. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_human.py +0 -0
  198. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_i18n.py +0 -0
  199. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_integration.py +0 -0
  200. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_mcp.py +0 -0
  201. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_mcp_runtime.py +0 -0
  202. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_memory.py +0 -0
  203. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_mesh.py +0 -0
  204. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_mesh_event_bus.py +0 -0
  205. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_model.py +0 -0
  206. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_object_store.py +0 -0
  207. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_persistence.py +0 -0
  208. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_planner_adaptive.py +0 -0
  209. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_primitives.py +0 -0
  210. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_provider_switching.py +0 -0
  211. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_providers.py +0 -0
  212. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_queue.py +0 -0
  213. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_reactive.py +0 -0
  214. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_runtime.py +0 -0
  215. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_scheduler.py +0 -0
  216. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_security.py +0 -0
  217. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_seo.py +0 -0
  218. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_state.py +0 -0
  219. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_theme.py +0 -0
  220. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_theme_presets.py +0 -0
  221. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_tools.py +0 -0
  222. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_ui.py +0 -0
  223. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_websocket.py +0 -0
  224. {voodoo_framework-2.2.0 → voodoo_framework-2.3.0}/tests/test_workers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voodoo-framework
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: The programmable runtime for adaptive applications and operational systems — web, APIs, agents, workers, human workflows, distributed systems, and physical systems in one runtime.
5
5
  Author-email: Helder Perez <contact@helderperez.com>
6
6
  Maintainer-email: Helder Perez <contact@helderperez.com>
@@ -59,6 +59,10 @@ Requires-Dist: boto3>=1.34; extra == "s3"
59
59
  Requires-Dist: botocore>=1.34; extra == "s3"
60
60
  Provides-Extra: redis
61
61
  Requires-Dist: redis>=5.0; extra == "redis"
62
+ Provides-Extra: otel
63
+ Requires-Dist: opentelemetry-api>=1.20; extra == "otel"
64
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == "otel"
65
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20; extra == "otel"
62
66
  Dynamic: license-file
63
67
 
64
68
  <picture>
@@ -93,6 +93,11 @@ s3 = [
93
93
  redis = [
94
94
  "redis>=5.0",
95
95
  ]
96
+ otel = [
97
+ "opentelemetry-api>=1.20",
98
+ "opentelemetry-sdk>=1.20",
99
+ "opentelemetry-exporter-otlp-proto-grpc>=1.20",
100
+ ]
96
101
 
97
102
  [tool.setuptools.dynamic]
98
103
  version = { attr = "voodoo.__version__" }
@@ -102,7 +102,7 @@ from .ui.styles import (
102
102
  from .ui.styles.theme import Theme, ThemeColors, create_theme
103
103
  from .workers import task
104
104
 
105
- __version__ = "2.2.0"
105
+ __version__ = "2.3.0"
106
106
 
107
107
  __all__ = [
108
108
  # Core runtime
@@ -13,9 +13,11 @@ from voodoo.cli import (
13
13
  recover,
14
14
  routes,
15
15
  schedules,
16
+ status,
16
17
  tasks,
17
18
  theme,
18
19
  version,
20
+ workers_cmd,
19
21
  )
20
22
  from voodoo.cli.auth import auth_app
21
23
  from voodoo.cli.inspect import inspect_app
@@ -45,6 +47,8 @@ app.add_typer(theme.theme_app, name="theme")
45
47
  # (timeline from the journal) and `voodoo events` (recent journal events).
46
48
  app.command("execution")(executions.show_execution)
47
49
  app.command("events")(executions.list_events)
50
+ app.command()(status.status)
51
+ app.command()(workers_cmd.workers)
48
52
  app.command()(version.version)
49
53
  app.command()(doctor.doctor)
50
54
  app.command()(routes.routes)
@@ -217,6 +217,54 @@ def doctor(): # noqa: C901
217
217
  except Exception: # noqa: BLE001 - diagnostics must never crash doctor
218
218
  terminal.status("capability matrix", "unavailable")
219
219
 
220
+ # ── Queue depth ─────────────────────────────────
221
+ terminal.heading("queue")
222
+ try:
223
+ import asyncio
224
+
225
+ async def _check_queue() -> tuple[int, int]:
226
+ from voodoo.workers.queue import _get_queue, _workers
227
+
228
+ depth = 0
229
+ try:
230
+ q = await _get_queue()
231
+ if hasattr(q, "list"):
232
+ tasks = await q.list()
233
+ depth = len(tasks)
234
+ elif hasattr(q, "depth"):
235
+ depth = await q.depth()
236
+ except Exception:
237
+ pass
238
+ return depth, len(_workers)
239
+
240
+ depth, n_workers = asyncio.run(_check_queue())
241
+ terminal.status("depth", str(depth))
242
+ terminal.status("registered workers", str(n_workers))
243
+ except Exception: # noqa: BLE001
244
+ terminal.status("queue", "unavailable")
245
+
246
+ # ── Schedules ───────────────────────────────────
247
+ terminal.heading("schedules")
248
+ try:
249
+ from pathlib import Path as _Path
250
+
251
+ sched_db = _Path(cfg.db_path).parent / "schedules.db"
252
+ if sched_db.exists():
253
+ terminal.status("scheduler db", "present")
254
+ else:
255
+ terminal.status("scheduler db", "not found")
256
+ except Exception: # noqa: BLE001
257
+ terminal.status("schedules", "unavailable")
258
+
259
+ # ── OTLP ────────────────────────────────────────
260
+ terminal.heading("otel")
261
+ try:
262
+ from voodoo.telemetry.otlp import is_available
263
+
264
+ terminal.status("otlp exporter", "active" if is_available() else "off")
265
+ except Exception: # noqa: BLE001
266
+ terminal.status("otlp exporter", "off")
267
+
220
268
  # ── AI Kit ──────────────────────────────────────
221
269
  terminal.heading("ai kit")
222
270
 
@@ -0,0 +1,73 @@
1
+ """``voodoo status`` — runtime health overview.
2
+
3
+ Displays a quick snapshot of the runtime: request counts, error rate,
4
+ latency, agent activity, queue depth, and OTel export status.
5
+ Works after a restart because rolling counters are persisted to
6
+ ``.voodoo/telemetry_summary.json``.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import typer
12
+ from rich.console import Console
13
+ from rich.table import Table
14
+
15
+ __all__ = ["status"]
16
+
17
+
18
+ def status() -> None:
19
+ """Show runtime health overview."""
20
+ from voodoo.telemetry import telemetry_store
21
+ from voodoo.telemetry.otlp import is_available as otlp_available
22
+
23
+ summary = telemetry_store.get_summary()
24
+ console = Console()
25
+
26
+ # -- header --------------------------------------------------------
27
+ console.print("[bold cyan]Voodoo Runtime Status[/bold cyan]")
28
+ console.print()
29
+
30
+ # -- requests & errors ---------------------------------------------
31
+ tbl = Table(show_header=True, header_style="bold")
32
+ tbl.add_column("Metric", style="dim")
33
+ tbl.add_column("Value", justify="right")
34
+
35
+ total = summary.get("requests_total", 0)
36
+ errors = summary.get("errors_total", 0)
37
+ error_rate = f"{(errors / total * 100):.1f}%" if total else "—"
38
+ avg_lat = summary.get("average_latency_ms", 0.0)
39
+
40
+ tbl.add_row("Requests total", str(total))
41
+ tbl.add_row("Errors total", str(errors))
42
+ tbl.add_row("Error rate", error_rate)
43
+ tbl.add_row("Avg latency", f"{avg_lat:.1f} ms")
44
+ tbl.add_row("DB queries", str(summary.get("db_queries", 0)))
45
+ console.print(tbl)
46
+ console.print()
47
+
48
+ # -- agent activity ------------------------------------------------
49
+ agent_tbl = Table(show_header=True, header_style="bold")
50
+ agent_tbl.add_column("Agent Metric", style="dim")
51
+ agent_tbl.add_column("Value", justify="right")
52
+
53
+ agent_tbl.add_row("Agent runs", str(summary.get("agent_runs", 0)))
54
+ agent_tbl.add_row("Tokens in", str(summary.get("agent_tokens_in", 0)))
55
+ agent_tbl.add_row("Tokens out", str(summary.get("agent_tokens_out", 0)))
56
+ agent_tbl.add_row("Agent cost", f"${summary.get('agent_cost', 0.0):.6f}")
57
+ agent_tbl.add_row("Tool calls", str(summary.get("tool_calls_total", 0)))
58
+ agent_tbl.add_row("Tool errors", str(summary.get("tool_errors", 0)))
59
+ agent_tbl.add_row("Spans recorded", str(summary.get("spans_total", 0)))
60
+ console.print(agent_tbl)
61
+ console.print()
62
+
63
+ # -- infrastructure ------------------------------------------------
64
+ infra_tbl = Table(show_header=True, header_style="bold")
65
+ infra_tbl.add_column("Infrastructure", style="dim")
66
+ infra_tbl.add_column("Status")
67
+
68
+ infra_tbl.add_row("OTLP export", "active" if otlp_available() else "off")
69
+ console.print(infra_tbl)
70
+
71
+
72
+ app = typer.Typer(name="status", help="Runtime health overview.", no_args_is_help=True)
73
+ app.command()(status)
@@ -0,0 +1,71 @@
1
+ """``voodoo workers`` — worker state & queue depth.
2
+
3
+ Shows registered background workers, their queue depth, and whether
4
+ the worker loop is running.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ from typing import Any
11
+
12
+ import typer
13
+ from rich.console import Console
14
+ from rich.table import Table
15
+
16
+ __all__ = ["workers"]
17
+
18
+
19
+ async def _gather_worker_info() -> dict[str, Any]:
20
+ """Collect worker and queue state without side-effects."""
21
+ from voodoo.workers.queue import _get_queue, _worker_tasks, _workers
22
+
23
+ info: dict[str, Any] = {
24
+ "registered": list(_workers.keys()),
25
+ "running_tasks": len([t for t in _worker_tasks if not t.done()]),
26
+ "queue_depth": 0,
27
+ }
28
+
29
+ try:
30
+ q = await _get_queue()
31
+ if hasattr(q, "list"):
32
+ tasks = await q.list()
33
+ info["queue_depth"] = len(tasks)
34
+ elif hasattr(q, "depth"):
35
+ info["queue_depth"] = await q.depth()
36
+ except Exception:
37
+ pass
38
+
39
+ return info
40
+
41
+
42
+ def workers() -> None:
43
+ """Show registered workers and queue depth."""
44
+ console = Console()
45
+ info = asyncio.run(_gather_worker_info())
46
+
47
+ console.print("[bold cyan]Voodoo Workers[/bold cyan]")
48
+ console.print()
49
+
50
+ tbl = Table(show_header=True, header_style="bold")
51
+ tbl.add_column("Worker", style="dim")
52
+ tbl.add_column("Status")
53
+
54
+ registered = info["registered"]
55
+ if not registered:
56
+ console.print("[dim]No workers registered.[/dim]")
57
+ else:
58
+ running = info["running_tasks"]
59
+ for name in registered:
60
+ tbl.add_row(name, "running" if running > 0 else "idle")
61
+ console.print(tbl)
62
+
63
+ console.print()
64
+ console.print(f"Queue depth: [bold]{info['queue_depth']}[/bold]")
65
+ console.print(f"Running worker tasks: [bold]{info['running_tasks']}[/bold]")
66
+
67
+
68
+ app = typer.Typer(
69
+ name="workers", help="Worker state & queue depth.", no_args_is_help=True
70
+ )
71
+ app.command()(workers)
@@ -1,20 +1,24 @@
1
1
  from voodoo.telemetry.api import get_metrics
2
2
  from voodoo.telemetry.middleware import TelemetryMiddleware
3
3
  from voodoo.telemetry.store import (
4
+ Span,
4
5
  TelemetryStore,
5
6
  TraceFilter,
6
7
  logger,
8
+ new_trace_id,
7
9
  telemetry_store,
8
10
  trace,
9
11
  trace_id_var,
10
12
  )
11
13
 
12
14
  __all__ = [
15
+ "Span",
13
16
  "TelemetryMiddleware",
14
17
  "TelemetryStore",
15
18
  "TraceFilter",
16
19
  "get_metrics",
17
20
  "logger",
21
+ "new_trace_id",
18
22
  "telemetry_store",
19
23
  "trace",
20
24
  "trace_id_var",
@@ -0,0 +1,108 @@
1
+ """Optional OpenTelemetry OTLP exporter.
2
+
3
+ Activated only when the ``[otel]`` extra is installed **and**
4
+ ``VOODOO_OTEL_EXPORTER`` is set (any non-empty value). When
5
+ active, completed :class:`Span` objects are forwarded to the
6
+ configured OTLP endpoint (default ``http://localhost:4317``).
7
+
8
+ Usage::
9
+
10
+ pip install voodoo-framework[otel]
11
+ export VOODOO_OTEL_EXPORTER=1
12
+ # optional: export OTEL_EXPORTER_OTLP_ENDPOINT=http://my-collector:4317
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import os
19
+ from typing import Any
20
+
21
+ logger = logging.getLogger("voodoo.telemetry.otlp")
22
+
23
+ __all__ = ["OTLPExporter", "is_available", "export_span"]
24
+
25
+ #: Cached exporter instance (lazy-initialised).
26
+ _exporter: OTLPExporter | None = None
27
+ _checked: bool = False
28
+
29
+
30
+ def is_available() -> bool:
31
+ """Return ``True`` if OTel SDK is importable and the env var is set."""
32
+ try:
33
+ import opentelemetry # noqa: F401
34
+ except ImportError:
35
+ return False
36
+ return bool(os.environ.get("VOODOO_OTEL_EXPORTER"))
37
+
38
+
39
+ class OTLPExporter:
40
+ """Thin wrapper around the OTel SDK's OTLP gRPC exporter.
41
+
42
+ Each call to :meth:`export_span` builds an OTel ``Span`` from our
43
+ :class:`voodoo.telemetry.store.Span` and forwards it via the
44
+ configured ``TracerProvider``.
45
+ """
46
+
47
+ def __init__(self) -> None:
48
+ from opentelemetry import trace as otel_trace
49
+ from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
50
+ OTLPSpanExporter,
51
+ )
52
+ from opentelemetry.sdk.trace import TracerProvider
53
+ from opentelemetry.sdk.trace.export import BatchSpanProcessor
54
+
55
+ endpoint = os.environ.get(
56
+ "OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"
57
+ )
58
+ provider = TracerProvider()
59
+ processor = BatchSpanProcessor(OTLPSpanExporter(endpoint=endpoint))
60
+ provider.add_span_processor(processor)
61
+ otel_trace.set_tracer_provider(provider)
62
+ self._tracer = otel_trace.get_tracer("voodoo")
63
+ logger.info("OTLP exporter initialised → %s", endpoint)
64
+
65
+ def export_span(self, span: Any) -> None:
66
+ """Convert a voodoo :class:`Span` to an OTel span and export it."""
67
+ from opentelemetry import trace as otel_trace
68
+ from opentelemetry.trace import StatusCode
69
+
70
+ with self._tracer.start_as_current_span(
71
+ span.name,
72
+ kind=otel_trace.SpanKind.INTERNAL,
73
+ attributes=dict(span.attributes) if span.attributes else {},
74
+ ) as otel_span:
75
+ if span.status == "error":
76
+ otel_span.set_status(StatusCode.ERROR)
77
+ else:
78
+ otel_span.set_status(StatusCode.OK)
79
+ if span.end_time and span.start_time:
80
+ otel_span.set_attribute(
81
+ "duration_ms",
82
+ (span.end_time - span.start_time).total_seconds() * 1000,
83
+ )
84
+
85
+
86
+ def _get_exporter() -> OTLPExporter | None:
87
+ """Return the singleton exporter, or ``None`` if unavailable."""
88
+ global _exporter, _checked
89
+ if _checked:
90
+ return _exporter
91
+ _checked = True
92
+ if is_available():
93
+ try:
94
+ _exporter = OTLPExporter()
95
+ except Exception: # noqa: BLE001 — graceful degradation
96
+ logger.warning("Failed to initialise OTLP exporter", exc_info=True)
97
+ _exporter = None
98
+ return _exporter
99
+
100
+
101
+ def export_span(span: Any) -> None:
102
+ """Forward *span* to the OTLP endpoint if the exporter is active."""
103
+ exporter = _get_exporter()
104
+ if exporter is not None:
105
+ try:
106
+ exporter.export_span(span)
107
+ except Exception: # noqa: BLE001 — never break the runtime
108
+ logger.debug("OTLP export failed for span %s", span.span_id, exc_info=True)