voodoo-framework 2.8.1__tar.gz → 2.8.3__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 (346) hide show
  1. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/PKG-INFO +1 -1
  2. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/__init__.py +1 -1
  3. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/__init__.py +2 -0
  4. voodoo_framework-2.8.3/src/voodoo/cli/start.py +55 -0
  5. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/__init__.py +1 -1
  6. voodoo_framework-2.8.3/src/voodoo/ui/brand.py +137 -0
  7. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/rendering.py +4 -0
  8. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo_framework.egg-info/PKG-INFO +1 -1
  9. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo_framework.egg-info/SOURCES.txt +3 -0
  10. voodoo_framework-2.8.3/tests/test_brand.py +61 -0
  11. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_cli.py +94 -0
  12. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/LICENSE +0 -0
  13. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/README.md +0 -0
  14. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/pyproject.toml +0 -0
  15. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/setup.cfg +0 -0
  16. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/adapters/__init__.py +0 -0
  17. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/adapters/capabilities.py +0 -0
  18. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/adapters/registry.py +0 -0
  19. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/adapters/tailwind.py +0 -0
  20. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/adapters/voodoo_css.py +0 -0
  21. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/agent.py +0 -0
  22. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/agents/__init__.py +0 -0
  23. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/agents/models.py +0 -0
  24. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/agents/registry.py +0 -0
  25. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/__init__.py +0 -0
  26. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/agent.py +0 -0
  27. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/agent_legacy.py +0 -0
  28. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/agent_runtime_truth.py +0 -0
  29. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/providers/__init__.py +0 -0
  30. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/providers/anthropic.py +0 -0
  31. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/providers/gemini.py +0 -0
  32. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/providers/mock.py +0 -0
  33. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/providers/ollama.py +0 -0
  34. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/providers/openai.py +0 -0
  35. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/tools/__init__.py +0 -0
  36. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ai/tools/registry.py +0 -0
  37. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/api.py +0 -0
  38. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/__init__.py +0 -0
  39. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/cookies.py +0 -0
  40. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/guards.py +0 -0
  41. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/jwt.py +0 -0
  42. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/middleware.py +0 -0
  43. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/passwords.py +0 -0
  44. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/auth/user.py +0 -0
  45. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/__main__.py +0 -0
  46. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/agents.py +0 -0
  47. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/ai.py +0 -0
  48. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/approvals.py +0 -0
  49. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/auth.py +0 -0
  50. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/create.py +0 -0
  51. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/dev.py +0 -0
  52. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/doctor.py +0 -0
  53. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/executions.py +0 -0
  54. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/fabric.py +0 -0
  55. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/generate.py +0 -0
  56. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/inspect.py +0 -0
  57. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/new.py +0 -0
  58. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/objects.py +0 -0
  59. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/protocol.py +0 -0
  60. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/recover.py +0 -0
  61. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/routes.py +0 -0
  62. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/scaffolding.py +0 -0
  63. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/schedules.py +0 -0
  64. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/status.py +0 -0
  65. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/tasks.py +0 -0
  66. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/terminal.py +0 -0
  67. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/theme.py +0 -0
  68. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/version.py +0 -0
  69. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/cli/workers_cmd.py +0 -0
  70. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/components.py +0 -0
  71. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/config.py +0 -0
  72. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/__init__.py +0 -0
  73. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/app.py +0 -0
  74. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/errors.py +0 -0
  75. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/events.py +0 -0
  76. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/render.py +0 -0
  77. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/routing.py +0 -0
  78. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/sitemap.py +0 -0
  79. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/core/state.py +0 -0
  80. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/data/__init__.py +0 -0
  81. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/data/base.py +0 -0
  82. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/data/model.py +0 -0
  83. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/data/store_backend.py +0 -0
  84. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/data/store_facade.py +0 -0
  85. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/data/store_model.py +0 -0
  86. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/__init__.py +0 -0
  87. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/auth.py +0 -0
  88. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/errors.py +0 -0
  89. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/gateway.py +0 -0
  90. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/http.py +0 -0
  91. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/models.py +0 -0
  92. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/mqtt.py +0 -0
  93. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/protocol.py +0 -0
  94. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/simulator.py +0 -0
  95. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/store.py +0 -0
  96. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/store_voodoo.py +0 -0
  97. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/edge/world.py +0 -0
  98. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/i18n.py +0 -0
  99. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mcp/__init__.py +0 -0
  100. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mcp/client.py +0 -0
  101. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/memory/__init__.py +0 -0
  102. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/memory/interfaces.py +0 -0
  103. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/memory/sqlite.py +0 -0
  104. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mesh/__init__.py +0 -0
  105. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mesh/auth.py +0 -0
  106. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mesh/client.py +0 -0
  107. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mesh/event_bus.py +0 -0
  108. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mesh/remote.py +0 -0
  109. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/mesh/replay.py +0 -0
  110. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/__init__.py +0 -0
  111. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/capability.py +0 -0
  112. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/compute.py +0 -0
  113. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/constraint.py +0 -0
  114. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/effect.py +0 -0
  115. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/intent.py +0 -0
  116. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/resource.py +0 -0
  117. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/state.py +0 -0
  118. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/primitives/time.py +0 -0
  119. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/protocol/__init__.py +0 -0
  120. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/protocol/export.py +0 -0
  121. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/protocol/fabric.py +0 -0
  122. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/protocol/operational.py +0 -0
  123. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/protocol/schemas.py +0 -0
  124. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/py.typed +0 -0
  125. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/queue.py +0 -0
  126. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/routing/api.py +0 -0
  127. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/routing/pages.py +0 -0
  128. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/__init__.py +0 -0
  129. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/adaptive.py +0 -0
  130. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/capability.py +0 -0
  131. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/constraint.py +0 -0
  132. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/context.py +0 -0
  133. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/dashboard.py +0 -0
  134. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/engine.py +0 -0
  135. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/errors.py +0 -0
  136. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/execution.py +0 -0
  137. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/fabric.py +0 -0
  138. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/goal.py +0 -0
  139. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/goal_store.py +0 -0
  140. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/graph.py +0 -0
  141. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/human.py +0 -0
  142. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/identity.py +0 -0
  143. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/identity_store.py +0 -0
  144. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/membership.py +0 -0
  145. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/operations.py +0 -0
  146. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/persistence.py +0 -0
  147. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/planner.py +0 -0
  148. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/policy.py +0 -0
  149. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/scheduler.py +0 -0
  150. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/store.py +0 -0
  151. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/task.py +0 -0
  152. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/transaction.py +0 -0
  153. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/workflow.py +0 -0
  154. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/workflow_store.py +0 -0
  155. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/runtime/world_execution.py +0 -0
  156. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/schedule.py +0 -0
  157. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/__init__.py +0 -0
  158. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/cors.py +0 -0
  159. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/csrf.py +0 -0
  160. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/headers.py +0 -0
  161. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/passwords.py +0 -0
  162. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/rate_limit.py +0 -0
  163. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/redaction.py +0 -0
  164. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/security/secrets.py +0 -0
  165. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/seo.py +0 -0
  166. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/static/client.js +0 -0
  167. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/status.py +0 -0
  168. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/__init__.py +0 -0
  169. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/cache/__init__.py +0 -0
  170. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/cache/interfaces.py +0 -0
  171. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/cache/memory.py +0 -0
  172. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/cache/redis.py +0 -0
  173. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/database/__init__.py +0 -0
  174. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/database/interfaces.py +0 -0
  175. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/database/postgres.py +0 -0
  176. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/database/sqlite.py +0 -0
  177. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/events/__init__.py +0 -0
  178. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/events/interfaces.py +0 -0
  179. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/events/local.py +0 -0
  180. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/events/postgres.py +0 -0
  181. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/events/sqlite.py +0 -0
  182. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/events/store.py +0 -0
  183. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/execution/__init__.py +0 -0
  184. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/execution/migrations.py +0 -0
  185. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/execution/postgres.py +0 -0
  186. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/execution/sqlite.py +0 -0
  187. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/execution/store.py +0 -0
  188. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/manager.py +0 -0
  189. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/objects/__init__.py +0 -0
  190. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/objects/interfaces.py +0 -0
  191. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/objects/local.py +0 -0
  192. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/objects/s3.py +0 -0
  193. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/objects/store.py +0 -0
  194. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/__init__.py +0 -0
  195. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/interfaces.py +0 -0
  196. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/memory.py +0 -0
  197. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/postgres.py +0 -0
  198. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/redis.py +0 -0
  199. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/sqlite.py +0 -0
  200. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/queue/store.py +0 -0
  201. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/scheduler/__init__.py +0 -0
  202. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/scheduler/sqlite.py +0 -0
  203. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/storage/scheduler/store.py +0 -0
  204. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/telemetry/__init__.py +0 -0
  205. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/telemetry/api.py +0 -0
  206. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/telemetry/middleware.py +0 -0
  207. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/telemetry/otlp.py +0 -0
  208. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/telemetry/store.py +0 -0
  209. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/theme.py +0 -0
  210. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/tools/__init__.py +0 -0
  211. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/tools/registry.py +0 -0
  212. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/component.py +0 -0
  213. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/events.py +0 -0
  214. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/interactive.py +0 -0
  215. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/layout.py +0 -0
  216. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/library.py +0 -0
  217. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/markdown.py +0 -0
  218. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/primitives.py +0 -0
  219. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/product.py +0 -0
  220. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/state.py +0 -0
  221. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/__init__.py +0 -0
  222. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/presets.py +0 -0
  223. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/product.py +0 -0
  224. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/system.py +0 -0
  225. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/theme.py +0 -0
  226. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/theme_contract.py +0 -0
  227. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/styles/voodoo_system.py +0 -0
  228. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/ui/voodoo_system.py +0 -0
  229. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/workers/__init__.py +0 -0
  230. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/workers/queue.py +0 -0
  231. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/world/__init__.py +0 -0
  232. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/world/model.py +0 -0
  233. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/world/models.py +0 -0
  234. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/world/sqlite.py +0 -0
  235. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo/world/store.py +0 -0
  236. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo_framework.egg-info/dependency_links.txt +0 -0
  237. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo_framework.egg-info/entry_points.txt +0 -0
  238. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo_framework.egg-info/requires.txt +0 -0
  239. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/src/voodoo_framework.egg-info/top_level.txt +0 -0
  240. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_adaptive_agency_correctness.py +0 -0
  241. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_agency_runtime_truth.py +0 -0
  242. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_agent.py +0 -0
  243. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_agent_registry.py +0 -0
  244. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_agent_runtime.py +0 -0
  245. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_app.py +0 -0
  246. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_auth.py +0 -0
  247. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_capability_security.py +0 -0
  248. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_checkpoint_resume.py +0 -0
  249. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_chrome.py +0 -0
  250. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_cli_fabric.py +0 -0
  251. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_cli_inspect.py +0 -0
  252. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_components.py +0 -0
  253. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_config.py +0 -0
  254. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_contract_api.py +0 -0
  255. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_create.py +0 -0
  256. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_create_store_smoke.py +0 -0
  257. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_data.py +0 -0
  258. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_design_system.py +0 -0
  259. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_design_system2.py +0 -0
  260. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_design_system_premium.py +0 -0
  261. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_design_system_theme_contract.py +0 -0
  262. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_durable_goal_runtime.py +0 -0
  263. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_durable_hitl.py +0 -0
  264. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_durable_workflow_runtime.py +0 -0
  265. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_device.py +0 -0
  266. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_e2e.py +0 -0
  267. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_gateway.py +0 -0
  268. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_http.py +0 -0
  269. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_protocol.py +0 -0
  270. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_security.py +0 -0
  271. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_voodoo_store.py +0 -0
  272. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_edge_world.py +0 -0
  273. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_events.py +0 -0
  274. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_execution_sqlite_store.py +0 -0
  275. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_goal_runtime.py +0 -0
  276. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_hitl_persistence_correctness.py +0 -0
  277. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_http_runtime.py +0 -0
  278. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_human.py +0 -0
  279. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_i18n.py +0 -0
  280. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_identity_execution.py +0 -0
  281. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_identity_foundation.py +0 -0
  282. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_integration.py +0 -0
  283. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mcp.py +0 -0
  284. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mcp_runtime.py +0 -0
  285. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_memory.py +0 -0
  286. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh.py +0 -0
  287. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_event_bus.py +0 -0
  288. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_remote_auth.py +0 -0
  289. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_remote_authority.py +0 -0
  290. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_remote_execution.py +0 -0
  291. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_remote_outcomes.py +0 -0
  292. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_remote_replay.py +0 -0
  293. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_mesh_two_node_acceptance.py +0 -0
  294. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_model.py +0 -0
  295. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_node_membership.py +0 -0
  296. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_object_store.py +0 -0
  297. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_observability.py +0 -0
  298. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_operational_policy.py +0 -0
  299. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_operational_runtime_ui.py +0 -0
  300. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_persistence.py +0 -0
  301. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_planner_adaptive.py +0 -0
  302. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_primitives.py +0 -0
  303. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_product_components.py +0 -0
  304. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_protocol.py +0 -0
  305. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_protocol_fabric.py +0 -0
  306. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_protocol_operational.py +0 -0
  307. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_provider_switching.py +0 -0
  308. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_providers.py +0 -0
  309. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_public_api_3.py +0 -0
  310. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_public_assets.py +0 -0
  311. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_queue.py +0 -0
  312. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_reactive.py +0 -0
  313. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime.py +0 -0
  314. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime_correctness.py +0 -0
  315. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime_fabric.py +0 -0
  316. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime_store_app_lifecycle.py +0 -0
  317. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime_store_lifecycle.py +0 -0
  318. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime_store_provider.py +0 -0
  319. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_runtime_transaction.py +0 -0
  320. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_scheduler.py +0 -0
  321. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_security.py +0 -0
  322. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_seo.py +0 -0
  323. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_sprint27_convergence.py +0 -0
  324. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_sprint28_acceptance.py +0 -0
  325. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_state.py +0 -0
  326. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_store_first_user_journey.py +0 -0
  327. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_store_model_backend.py +0 -0
  328. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_store_only_core_import.py +0 -0
  329. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_theme.py +0 -0
  330. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_theme_presets.py +0 -0
  331. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_tools.py +0 -0
  332. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_ui.py +0 -0
  333. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_ui_magic.py +0 -0
  334. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_ui_magic_acceptance.py +0 -0
  335. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_voodoo_store_events.py +0 -0
  336. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_voodoo_store_execution.py +0 -0
  337. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_voodoo_store_hitl_restart.py +0 -0
  338. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_voodoo_store_queue.py +0 -0
  339. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_voodoo_store_scheduler.py +0 -0
  340. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_voodoo_system_components.py +0 -0
  341. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_websocket.py +0 -0
  342. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_worker_retry_semantics.py +0 -0
  343. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_workers.py +0 -0
  344. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_world_aware_execution.py +0 -0
  345. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_world_model.py +0 -0
  346. {voodoo_framework-2.8.1 → voodoo_framework-2.8.3}/tests/test_world_sqlite.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voodoo-framework
3
- Version: 2.8.1
3
+ Version: 2.8.3
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>
@@ -105,7 +105,7 @@ from .ui.styles import (
105
105
  from .ui.styles.theme import Theme, ThemeColors, create_theme
106
106
  from .workers import task
107
107
 
108
- __version__ = "2.8.1"
108
+ __version__ = "2.8.3"
109
109
 
110
110
  __all__ = [
111
111
  # Core runtime
@@ -16,6 +16,7 @@ from voodoo.cli import (
16
16
  recover,
17
17
  routes,
18
18
  schedules,
19
+ start,
19
20
  status,
20
21
  tasks,
21
22
  theme,
@@ -36,6 +37,7 @@ app = typer.Typer(
36
37
  app.command()(new.new)
37
38
  app.command()(create.create)
38
39
  app.command()(dev.dev)
40
+ app.command()(start.start)
39
41
  app.command()(generate.generate)
40
42
  app.add_typer(auth_app, name="auth")
41
43
  app.add_typer(ai.ai_app, name="ai")
@@ -0,0 +1,55 @@
1
+ """Production server command for Voodoo applications."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from pathlib import Path
7
+
8
+ import typer
9
+
10
+ __all__ = ["start"]
11
+
12
+
13
+ def start(
14
+ app_str: str | None = typer.Argument(
15
+ None,
16
+ help="App instance to run. Defaults to main:app or voodoo.core:app.",
17
+ ),
18
+ host: str | None = typer.Option(
19
+ None,
20
+ help="Host to bind to. Defaults to VOODOO_HOST or 0.0.0.0.",
21
+ ),
22
+ port: int | None = typer.Option(
23
+ None,
24
+ help="Port to bind to. Defaults to PORT, VOODOO_PORT, or 8000.",
25
+ ),
26
+ ) -> None:
27
+ """Start a Voodoo application in production mode."""
28
+ if app_str is None:
29
+ app_str = "main:app" if Path("main.py").exists() else "voodoo.core:app"
30
+
31
+ resolved_host = host or os.getenv("VOODOO_HOST") or "0.0.0.0"
32
+ configured_port = os.getenv("PORT") or os.getenv("VOODOO_PORT") or "8000"
33
+ resolved_port = port if port is not None else int(configured_port)
34
+
35
+ # Production should be the safe default for this command while still
36
+ # allowing an explicitly configured environment to win.
37
+ os.environ.setdefault("VOODOO_ENV", "production")
38
+ os.environ.setdefault("WEBSOCKETS_MAX_LINE_LENGTH", "8388608")
39
+ os.environ.setdefault("WEBSOCKETS_MAX_NUM_HEADERS", "256")
40
+
41
+ import uvicorn
42
+
43
+ uvicorn.run(
44
+ app_str,
45
+ host=resolved_host,
46
+ port=resolved_port,
47
+ # One process owns one live local Store writer. Horizontal scaling uses
48
+ # separate Voodoo Nodes with node-local Stores.
49
+ workers=1,
50
+ proxy_headers=True,
51
+ forwarded_allow_ips=os.getenv("FORWARDED_ALLOW_IPS", "127.0.0.1"),
52
+ http="h11",
53
+ ws="websockets",
54
+ h11_max_incomplete_event_size=5_242_880,
55
+ )
@@ -12,6 +12,7 @@ Voodoo::
12
12
  Button("Save", on_click=save)
13
13
  """
14
14
 
15
+ from voodoo.ui.brand import Brand
15
16
  from voodoo.ui.component import Component, Html, escape, tone_to_color_var
16
17
  from voodoo.ui.events import UIEvent
17
18
  from voodoo.ui.interactive import (
@@ -36,7 +37,6 @@ from voodoo.ui.library import (
36
37
  BackLink,
37
38
  Badge,
38
39
  Box,
39
- Brand,
40
40
  Card,
41
41
  ChatBox,
42
42
  ChatMessage,
@@ -0,0 +1,137 @@
1
+ """Branding primitives for logos and wordmarks.
2
+
3
+ ``Brand`` preserves the existing child-based API while adding a first-class
4
+ image mode that can switch logo assets with the active light/dark theme.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ from voodoo.ui.component import Component
12
+
13
+ BRAND_CSS = """
14
+ /* Brand image contract */
15
+ .vd-brand-logo {
16
+ display: block;
17
+ max-width: 100%;
18
+ height: auto;
19
+ border-radius: 0 !important;
20
+ }
21
+ .vd-brand-logo--light { display: block; }
22
+ .vd-brand-logo--dark { display: none; }
23
+ .dark .vd-brand-logo--light { display: none; }
24
+ .dark .vd-brand-logo--dark { display: block; }
25
+ """
26
+
27
+
28
+ class _BrandLogo(Component):
29
+ """Internal logo image with no generic ``Img`` presentation styles."""
30
+
31
+ tag = "img"
32
+ auto_id = False
33
+
34
+ def __init__(
35
+ self,
36
+ *,
37
+ src: str,
38
+ alt: str,
39
+ variant: str | None = None,
40
+ width: str | int | None = None,
41
+ height: str | int | None = None,
42
+ ) -> None:
43
+ classes = "vd-brand-logo"
44
+ if variant:
45
+ classes += f" vd-brand-logo--{variant}"
46
+ super().__init__(class_=classes)
47
+ self.attrs["src"] = src
48
+ self.attrs["alt"] = alt
49
+ if width is not None:
50
+ self.attrs["width"] = width
51
+ if height is not None:
52
+ self.attrs["height"] = height
53
+
54
+
55
+ class Brand(Component):
56
+ """Brand link supporting either child content or theme-aware logo assets.
57
+
58
+ Existing usage remains valid::
59
+
60
+ Brand("Acme", href="/")
61
+ Brand(Img(src="/logo.png", alt="Acme"), href="/")
62
+
63
+ Image mode keeps branding free of generic image presentation styles and
64
+ automatically selects the correct asset for the active theme::
65
+
66
+ Brand(
67
+ light="/logo-black.png",
68
+ dark="/logo-white.png",
69
+ alt="Acme",
70
+ width=160,
71
+ href="/",
72
+ )
73
+
74
+ When only ``light`` or ``dark`` is supplied, that asset is used for both
75
+ themes. Image mode and explicit children are intentionally mutually
76
+ exclusive so the rendered brand stays unambiguous.
77
+ """
78
+
79
+ tag = "a"
80
+ style = "brand"
81
+
82
+ def __init__(
83
+ self,
84
+ *children: Any,
85
+ href: str = "/",
86
+ light: str | None = None,
87
+ dark: str | None = None,
88
+ alt: str = "",
89
+ width: str | int | None = None,
90
+ height: str | int | None = None,
91
+ **kwargs: Any,
92
+ ) -> None:
93
+ image_mode = light is not None or dark is not None
94
+ if image_mode and children:
95
+ raise ValueError(
96
+ "Brand image mode cannot be combined with child content. "
97
+ "Use either Brand(...children) or Brand(light=..., dark=...)."
98
+ )
99
+
100
+ super().__init__(*children, **kwargs)
101
+ self.attrs["href"] = href
102
+
103
+ if not image_mode:
104
+ return
105
+
106
+ light_src = light or dark
107
+ dark_src = dark or light
108
+ assert light_src is not None
109
+ assert dark_src is not None
110
+
111
+ if light_src == dark_src:
112
+ self.children = (
113
+ _BrandLogo(
114
+ src=light_src,
115
+ alt=alt,
116
+ width=width,
117
+ height=height,
118
+ ),
119
+ )
120
+ return
121
+
122
+ self.children = (
123
+ _BrandLogo(
124
+ src=light_src,
125
+ alt=alt,
126
+ variant="light",
127
+ width=width,
128
+ height=height,
129
+ ),
130
+ _BrandLogo(
131
+ src=dark_src,
132
+ alt=alt,
133
+ variant="dark",
134
+ width=width,
135
+ height=height,
136
+ ),
137
+ )
@@ -40,6 +40,7 @@ def render_page(component: Any, seo: Any = None) -> str:
40
40
  """Render a complete HTML document for a Voodoo component tree."""
41
41
  from voodoo.config import config
42
42
  from voodoo.seo import SEO
43
+ from voodoo.ui.brand import BRAND_CSS
43
44
  from voodoo.ui.component import Component
44
45
  from voodoo.ui.styles.theme import default_theme
45
46
 
@@ -162,6 +163,9 @@ def render_page(component: Any, seo: Any = None) -> str:
162
163
  /* Stable primitive component layer */
163
164
  {component_css}
164
165
 
166
+ /* Brand asset switching */
167
+ {BRAND_CSS}
168
+
165
169
  /* Voodoo Design System 3 */
166
170
  {design_system_css}
167
171
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voodoo-framework
3
- Version: 2.8.1
3
+ Version: 2.8.3
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>
@@ -60,6 +60,7 @@ src/voodoo/cli/recover.py
60
60
  src/voodoo/cli/routes.py
61
61
  src/voodoo/cli/scaffolding.py
62
62
  src/voodoo/cli/schedules.py
63
+ src/voodoo/cli/start.py
63
64
  src/voodoo/cli/status.py
64
65
  src/voodoo/cli/tasks.py
65
66
  src/voodoo/cli/terminal.py
@@ -200,6 +201,7 @@ src/voodoo/telemetry/store.py
200
201
  src/voodoo/tools/__init__.py
201
202
  src/voodoo/tools/registry.py
202
203
  src/voodoo/ui/__init__.py
204
+ src/voodoo/ui/brand.py
203
205
  src/voodoo/ui/component.py
204
206
  src/voodoo/ui/events.py
205
207
  src/voodoo/ui/interactive.py
@@ -238,6 +240,7 @@ tests/test_agent_registry.py
238
240
  tests/test_agent_runtime.py
239
241
  tests/test_app.py
240
242
  tests/test_auth.py
243
+ tests/test_brand.py
241
244
  tests/test_capability_security.py
242
245
  tests/test_checkpoint_resume.py
243
246
  tests/test_chrome.py
@@ -0,0 +1,61 @@
1
+ """Tests for the theme-aware Brand component."""
2
+
3
+ import pytest
4
+
5
+ from voodoo.ui import Brand
6
+ from voodoo.ui.brand import BRAND_CSS
7
+ from voodoo.ui.rendering import render_page
8
+
9
+
10
+ def test_brand_preserves_child_based_api():
11
+ html = Brand("Voodoo", href="/home").render()
12
+
13
+ assert 'href="/home"' in html
14
+ assert ">Voodoo</a>" in html
15
+ assert "vd-brand-logo" not in html
16
+
17
+
18
+ def test_brand_renders_theme_specific_assets_without_generic_img_style():
19
+ html = Brand(
20
+ light="/logo-black.png",
21
+ dark="/logo-white.png",
22
+ alt="Voodoo",
23
+ width=160,
24
+ href="/",
25
+ ).render()
26
+
27
+ assert 'src="/logo-black.png"' in html
28
+ assert 'src="/logo-white.png"' in html
29
+ assert 'alt="Voodoo"' in html
30
+ assert 'width="160"' in html
31
+ assert "vd-brand-logo--light" in html
32
+ assert "vd-brand-logo--dark" in html
33
+ assert "vd-img" not in html
34
+
35
+
36
+ def test_brand_single_asset_is_shared_by_both_themes():
37
+ html = Brand(light="/logo.svg", alt="Acme").render()
38
+
39
+ assert html.count("<img") == 1
40
+ assert 'src="/logo.svg"' in html
41
+ assert "vd-brand-logo--light" not in html
42
+ assert "vd-brand-logo--dark" not in html
43
+
44
+
45
+ def test_brand_rejects_children_in_image_mode():
46
+ with pytest.raises(ValueError, match="cannot be combined"):
47
+ Brand("Voodoo", light="/logo.svg")
48
+
49
+
50
+ def test_brand_css_switches_assets_and_removes_radius():
51
+ assert "border-radius: 0 !important" in BRAND_CSS
52
+ assert ".dark .vd-brand-logo--light { display: none; }" in BRAND_CSS
53
+ assert ".dark .vd-brand-logo--dark { display: block; }" in BRAND_CSS
54
+
55
+
56
+ def test_render_page_includes_brand_css():
57
+ html = render_page(Brand(light="/logo-black.png", dark="/logo-white.png"))
58
+
59
+ assert "/* Brand asset switching */" in html
60
+ assert ".vd-brand-logo--light" in html
61
+ assert ".dark .vd-brand-logo--dark" in html
@@ -335,3 +335,97 @@ def test_cli_dev_does_not_leak_pythonpath(tmp_path: Path, monkeypatch):
335
335
 
336
336
  assert result.exit_code == 0
337
337
  assert "PYTHONPATH" not in captured
338
+
339
+
340
+ def test_cli_start_uses_safe_production_defaults(
341
+ tmp_path: Path,
342
+ monkeypatch,
343
+ ):
344
+ """start should discover main.py and preserve Store-safe server defaults."""
345
+ monkeypatch.chdir(tmp_path)
346
+ (tmp_path / "main.py").write_text("app = object()\n")
347
+ for name in (
348
+ "VOODOO_ENV",
349
+ "VOODOO_HOST",
350
+ "VOODOO_PORT",
351
+ "PORT",
352
+ "FORWARDED_ALLOW_IPS",
353
+ "WEBSOCKETS_MAX_LINE_LENGTH",
354
+ "WEBSOCKETS_MAX_NUM_HEADERS",
355
+ ):
356
+ monkeypatch.delenv(name, raising=False)
357
+
358
+ with patch("uvicorn.run") as run:
359
+ result = runner.invoke(app, ["start"])
360
+
361
+ assert result.exit_code == 0
362
+ run.assert_called_once_with(
363
+ "main:app",
364
+ host="0.0.0.0",
365
+ port=8000,
366
+ workers=1,
367
+ proxy_headers=True,
368
+ forwarded_allow_ips="127.0.0.1",
369
+ http="h11",
370
+ ws="websockets",
371
+ h11_max_incomplete_event_size=5_242_880,
372
+ )
373
+ assert os.environ["VOODOO_ENV"] == "production"
374
+ assert os.environ["WEBSOCKETS_MAX_LINE_LENGTH"] == "8388608"
375
+ assert os.environ["WEBSOCKETS_MAX_NUM_HEADERS"] == "256"
376
+
377
+
378
+ def test_cli_start_respects_explicit_configuration(
379
+ tmp_path: Path,
380
+ monkeypatch,
381
+ ):
382
+ """CLI arguments and explicit environment settings should remain authoritative."""
383
+ monkeypatch.chdir(tmp_path)
384
+ monkeypatch.setenv("VOODOO_ENV", "staging")
385
+ monkeypatch.setenv("VOODOO_HOST", "127.0.0.2")
386
+ monkeypatch.setenv("PORT", "9100")
387
+ monkeypatch.setenv("FORWARDED_ALLOW_IPS", "10.0.0.0/8")
388
+
389
+ with patch("uvicorn.run") as run:
390
+ result = runner.invoke(
391
+ app,
392
+ [
393
+ "start",
394
+ "custom.application:app",
395
+ "--host",
396
+ "127.0.0.3",
397
+ "--port",
398
+ "9200",
399
+ ],
400
+ )
401
+
402
+ assert result.exit_code == 0
403
+ call = run.call_args
404
+ assert call.args == ("custom.application:app",)
405
+ assert call.kwargs["host"] == "127.0.0.3"
406
+ assert call.kwargs["port"] == 9200
407
+ assert call.kwargs["forwarded_allow_ips"] == "10.0.0.0/8"
408
+ assert call.kwargs["workers"] == 1
409
+ assert os.environ["VOODOO_ENV"] == "staging"
410
+
411
+
412
+ def test_cli_start_falls_back_to_folder_routing_app(
413
+ tmp_path: Path,
414
+ monkeypatch,
415
+ ):
416
+ """Projects without main.py should use the folder-routing application."""
417
+ monkeypatch.chdir(tmp_path)
418
+
419
+ with patch("uvicorn.run") as run:
420
+ result = runner.invoke(app, ["start"])
421
+
422
+ assert result.exit_code == 0
423
+ assert run.call_args.args == ("voodoo.core:app",)
424
+
425
+
426
+ def test_cli_start_does_not_offer_unsafe_multi_worker_mode():
427
+ """One local Store writer means the production command has no workers option."""
428
+ result = runner.invoke(app, ["start", "--workers", "2"])
429
+
430
+ assert result.exit_code != 0
431
+ assert "No such option" in result.output