voodoo-framework 2.9.0__tar.gz → 3.0.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 (395) hide show
  1. {voodoo_framework-2.9.0/src/voodoo_framework.egg-info → voodoo_framework-3.0.0}/PKG-INFO +1 -1
  2. voodoo_framework-3.0.0/src/voodoo/__init__.py +25 -0
  3. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/adapters/tailwind.py +31 -19
  4. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/adapters/voodoo_css.py +1 -3
  5. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/agent_legacy.py +42 -34
  6. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/agent_runtime_truth.py +2 -2
  7. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/providers/__init__.py +8 -8
  8. voodoo_framework-3.0.0/src/voodoo/ai/providers/anthropic.py +7 -0
  9. voodoo_framework-3.0.0/src/voodoo/ai/providers/gemini.py +7 -0
  10. voodoo_framework-3.0.0/src/voodoo/ai/providers/ollama.py +7 -0
  11. voodoo_framework-3.0.0/src/voodoo/ai/providers/openai.py +7 -0
  12. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/tools/__init__.py +3 -3
  13. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/tools/registry.py +2 -2
  14. voodoo_framework-3.0.0/src/voodoo/auth/guards.py +144 -0
  15. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/auth/jwt.py +28 -34
  16. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/__init__.py +2 -0
  17. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/approvals.py +1 -1
  18. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/dev.py +1 -1
  19. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/doctor.py +78 -73
  20. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/fabric.py +1 -1
  21. voodoo_framework-3.0.0/src/voodoo/cli/graph.py +36 -0
  22. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/inspect.py +91 -55
  23. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/new.py +78 -110
  24. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/recover.py +1 -1
  25. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/scaffolding.py +103 -102
  26. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/status.py +2 -2
  27. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/tasks.py +1 -1
  28. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/theme.py +4 -4
  29. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/workers_cmd.py +1 -1
  30. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/core/__init__.py +2 -1
  31. voodoo_framework-3.0.0/src/voodoo/core/app.py +561 -0
  32. voodoo_framework-3.0.0/src/voodoo/core/events.py +23 -0
  33. voodoo_framework-3.0.0/src/voodoo/core/routing.py +14 -0
  34. voodoo_framework-3.0.0/src/voodoo/core/sitemap.py +110 -0
  35. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/core/state.py +4 -5
  36. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/data/base.py +15 -4
  37. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/data/model.py +5 -5
  38. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/data/store_facade.py +1 -1
  39. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/gateway.py +2 -2
  40. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/http.py +1 -1
  41. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/mqtt.py +5 -6
  42. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/protocol.py +2 -2
  43. voodoo_framework-3.0.0/src/voodoo/integrations/__init__.py +1 -0
  44. voodoo_framework-3.0.0/src/voodoo/integrations/ai/__init__.py +1 -0
  45. {voodoo_framework-2.9.0/src/voodoo/ai/providers → voodoo_framework-3.0.0/src/voodoo/integrations/ai}/anthropic.py +1 -1
  46. {voodoo_framework-2.9.0/src/voodoo/ai/providers → voodoo_framework-3.0.0/src/voodoo/integrations/ai}/gemini.py +1 -1
  47. {voodoo_framework-2.9.0/src/voodoo/ai/providers → voodoo_framework-3.0.0/src/voodoo/integrations/ai}/ollama.py +1 -1
  48. {voodoo_framework-2.9.0/src/voodoo/ai/providers → voodoo_framework-3.0.0/src/voodoo/integrations/ai}/openai.py +1 -1
  49. {voodoo_framework-2.9.0/src/voodoo → voodoo_framework-3.0.0/src/voodoo/integrations}/mcp/__init__.py +67 -107
  50. voodoo_framework-2.9.0/src/voodoo/telemetry/otlp.py → voodoo_framework-3.0.0/src/voodoo/integrations/otel.py +8 -9
  51. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/memory/interfaces.py +2 -3
  52. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/mesh/__init__.py +10 -10
  53. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/mesh/client.py +1 -1
  54. {voodoo_framework-2.9.0/src/voodoo/telemetry → voodoo_framework-3.0.0/src/voodoo/observability}/__init__.py +5 -3
  55. {voodoo_framework-2.9.0/src/voodoo/telemetry → voodoo_framework-3.0.0/src/voodoo/observability}/api.py +1 -1
  56. {voodoo_framework-2.9.0/src/voodoo/telemetry → voodoo_framework-3.0.0/src/voodoo/observability}/middleware.py +1 -1
  57. {voodoo_framework-2.9.0/src/voodoo/telemetry → voodoo_framework-3.0.0/src/voodoo/observability}/store.py +5 -5
  58. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/protocol/schemas.py +2 -2
  59. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/routing/api.py +78 -74
  60. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/__init__.py +138 -30
  61. voodoo_framework-3.0.0/src/voodoo/runtime/agency/__init__.py +39 -0
  62. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/agency}/adaptive.py +102 -98
  63. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/agency}/goal.py +3 -3
  64. voodoo_framework-3.0.0/src/voodoo/runtime/application_graph.py +541 -0
  65. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/context.py +1 -1
  66. voodoo_framework-3.0.0/src/voodoo/runtime/conventions.py +71 -0
  67. voodoo_framework-3.0.0/src/voodoo/runtime/dependency_graph.py +138 -0
  68. voodoo_framework-3.0.0/src/voodoo/runtime/distributed/__init__.py +35 -0
  69. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/distributed}/fabric.py +10 -4
  70. {voodoo_framework-2.9.0/src/voodoo/mesh → voodoo_framework-3.0.0/src/voodoo/runtime/distributed}/replay.py +4 -1
  71. voodoo_framework-3.0.0/src/voodoo/runtime/execution/__init__.py +5 -0
  72. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/execution}/engine.py +7 -7
  73. voodoo_framework-2.9.0/src/voodoo/runtime/execution.py → voodoo_framework-3.0.0/src/voodoo/runtime/execution/model.py +1 -1
  74. voodoo_framework-3.0.0/src/voodoo/runtime/extension.py +116 -0
  75. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/graph.py +1 -1
  76. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/human.py +1 -1
  77. voodoo_framework-3.0.0/src/voodoo/runtime/inspection/__init__.py +11 -0
  78. voodoo_framework-3.0.0/src/voodoo/runtime/inspection/lineage.py +147 -0
  79. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/persistence.py +1 -1
  80. voodoo_framework-3.0.0/src/voodoo/runtime/reconciliation/__init__.py +25 -0
  81. voodoo_framework-3.0.0/src/voodoo/runtime/reconciliation/reconcile.py +318 -0
  82. voodoo_framework-3.0.0/src/voodoo/runtime/runtime.py +468 -0
  83. voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/__init__.py +34 -0
  84. voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/dispatch.py +104 -0
  85. voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/handoff.py +81 -0
  86. voodoo_framework-2.9.0/src/voodoo/runtime/scheduler.py → voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/schedule_service.py +1 -1
  87. voodoo_framework-2.9.0/src/voodoo/workers/__init__.py → voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/tasks.py +6 -6
  88. voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/work.py +275 -0
  89. voodoo_framework-2.9.0/src/voodoo/workers/queue.py → voodoo_framework-3.0.0/src/voodoo/runtime/scheduling/workers.py +12 -7
  90. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/store.py +3 -3
  91. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/task.py +3 -3
  92. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/workflow.py +5 -5
  93. voodoo_framework-3.0.0/src/voodoo/security/headers.py +46 -0
  94. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/secrets.py +1 -1
  95. voodoo_framework-3.0.0/src/voodoo/seo.py +292 -0
  96. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/status.py +3 -3
  97. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/events/local.py +1 -1
  98. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/events/postgres.py +1 -1
  99. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/events/sqlite.py +1 -1
  100. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/events/store.py +1 -1
  101. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/objects/s3.py +3 -3
  102. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/component.py +2 -4
  103. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/controls.py +6 -10
  104. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/data_extended.py +13 -15
  105. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/forms_extended.py +12 -6
  106. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/foundation.py +10 -6
  107. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/interaction_kernel.py +4 -11
  108. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/interactions.py +1 -2
  109. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/library.py +2 -6
  110. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/navigation.py +5 -7
  111. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/navigation_extended.py +15 -17
  112. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/state.py +49 -1
  113. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/palette.py +3 -1
  114. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/presets.py +2 -2
  115. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/workspace.py +27 -19
  116. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0/src/voodoo_framework.egg-info}/PKG-INFO +1 -1
  117. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo_framework.egg-info/SOURCES.txt +46 -145
  118. voodoo_framework-2.9.0/src/voodoo/__init__.py +0 -413
  119. voodoo_framework-2.9.0/src/voodoo/agent.py +0 -9
  120. voodoo_framework-2.9.0/src/voodoo/api.py +0 -13
  121. voodoo_framework-2.9.0/src/voodoo/auth/guards.py +0 -282
  122. voodoo_framework-2.9.0/src/voodoo/core/app.py +0 -443
  123. voodoo_framework-2.9.0/src/voodoo/core/events.py +0 -21
  124. voodoo_framework-2.9.0/src/voodoo/core/routing.py +0 -18
  125. voodoo_framework-2.9.0/src/voodoo/core/sitemap.py +0 -134
  126. voodoo_framework-2.9.0/src/voodoo/queue.py +0 -12
  127. voodoo_framework-2.9.0/src/voodoo/security/headers.py +0 -50
  128. voodoo_framework-2.9.0/src/voodoo/seo.py +0 -292
  129. voodoo_framework-2.9.0/src/voodoo/theme.py +0 -29
  130. voodoo_framework-2.9.0/src/voodoo/tools/__init__.py +0 -9
  131. voodoo_framework-2.9.0/src/voodoo/tools/registry.py +0 -20
  132. voodoo_framework-2.9.0/tests/test_adaptive_agency_correctness.py +0 -233
  133. voodoo_framework-2.9.0/tests/test_agency_runtime_truth.py +0 -172
  134. voodoo_framework-2.9.0/tests/test_agent.py +0 -603
  135. voodoo_framework-2.9.0/tests/test_agent_registry.py +0 -391
  136. voodoo_framework-2.9.0/tests/test_agent_runtime.py +0 -108
  137. voodoo_framework-2.9.0/tests/test_app.py +0 -344
  138. voodoo_framework-2.9.0/tests/test_auth.py +0 -267
  139. voodoo_framework-2.9.0/tests/test_brand.py +0 -61
  140. voodoo_framework-2.9.0/tests/test_capability_security.py +0 -426
  141. voodoo_framework-2.9.0/tests/test_checkpoint_resume.py +0 -134
  142. voodoo_framework-2.9.0/tests/test_chrome.py +0 -156
  143. voodoo_framework-2.9.0/tests/test_cli.py +0 -431
  144. voodoo_framework-2.9.0/tests/test_cli_fabric.py +0 -28
  145. voodoo_framework-2.9.0/tests/test_cli_inspect.py +0 -223
  146. voodoo_framework-2.9.0/tests/test_components.py +0 -269
  147. voodoo_framework-2.9.0/tests/test_config.py +0 -234
  148. voodoo_framework-2.9.0/tests/test_contract_api.py +0 -242
  149. voodoo_framework-2.9.0/tests/test_create.py +0 -104
  150. voodoo_framework-2.9.0/tests/test_create_store_smoke.py +0 -60
  151. voodoo_framework-2.9.0/tests/test_data.py +0 -92
  152. voodoo_framework-2.9.0/tests/test_data_extended.py +0 -275
  153. voodoo_framework-2.9.0/tests/test_design_system.py +0 -201
  154. voodoo_framework-2.9.0/tests/test_design_system2.py +0 -136
  155. voodoo_framework-2.9.0/tests/test_design_system_premium.py +0 -101
  156. voodoo_framework-2.9.0/tests/test_design_system_theme_contract.py +0 -53
  157. voodoo_framework-2.9.0/tests/test_durable_goal_runtime.py +0 -161
  158. voodoo_framework-2.9.0/tests/test_durable_hitl.py +0 -346
  159. voodoo_framework-2.9.0/tests/test_durable_workflow_runtime.py +0 -157
  160. voodoo_framework-2.9.0/tests/test_edge_device.py +0 -325
  161. voodoo_framework-2.9.0/tests/test_edge_e2e.py +0 -186
  162. voodoo_framework-2.9.0/tests/test_edge_gateway.py +0 -1002
  163. voodoo_framework-2.9.0/tests/test_edge_http.py +0 -331
  164. voodoo_framework-2.9.0/tests/test_edge_protocol.py +0 -159
  165. voodoo_framework-2.9.0/tests/test_edge_security.py +0 -399
  166. voodoo_framework-2.9.0/tests/test_edge_voodoo_store.py +0 -102
  167. voodoo_framework-2.9.0/tests/test_edge_world.py +0 -156
  168. voodoo_framework-2.9.0/tests/test_events.py +0 -54
  169. voodoo_framework-2.9.0/tests/test_execution_sqlite_store.py +0 -152
  170. voodoo_framework-2.9.0/tests/test_forms_extended.py +0 -209
  171. voodoo_framework-2.9.0/tests/test_foundation_components.py +0 -138
  172. voodoo_framework-2.9.0/tests/test_goal_runtime.py +0 -169
  173. voodoo_framework-2.9.0/tests/test_hitl_persistence_correctness.py +0 -140
  174. voodoo_framework-2.9.0/tests/test_http_runtime.py +0 -129
  175. voodoo_framework-2.9.0/tests/test_human.py +0 -133
  176. voodoo_framework-2.9.0/tests/test_i18n.py +0 -77
  177. voodoo_framework-2.9.0/tests/test_identity_execution.py +0 -149
  178. voodoo_framework-2.9.0/tests/test_identity_foundation.py +0 -156
  179. voodoo_framework-2.9.0/tests/test_integration.py +0 -626
  180. voodoo_framework-2.9.0/tests/test_interaction_components.py +0 -363
  181. voodoo_framework-2.9.0/tests/test_interaction_kernel.py +0 -307
  182. voodoo_framework-2.9.0/tests/test_mcp.py +0 -326
  183. voodoo_framework-2.9.0/tests/test_mcp_runtime.py +0 -102
  184. voodoo_framework-2.9.0/tests/test_memory.py +0 -412
  185. voodoo_framework-2.9.0/tests/test_mesh.py +0 -350
  186. voodoo_framework-2.9.0/tests/test_mesh_event_bus.py +0 -67
  187. voodoo_framework-2.9.0/tests/test_mesh_remote_auth.py +0 -216
  188. voodoo_framework-2.9.0/tests/test_mesh_remote_authority.py +0 -164
  189. voodoo_framework-2.9.0/tests/test_mesh_remote_execution.py +0 -326
  190. voodoo_framework-2.9.0/tests/test_mesh_remote_outcomes.py +0 -205
  191. voodoo_framework-2.9.0/tests/test_mesh_remote_replay.py +0 -178
  192. voodoo_framework-2.9.0/tests/test_mesh_two_node_acceptance.py +0 -254
  193. voodoo_framework-2.9.0/tests/test_model.py +0 -193
  194. voodoo_framework-2.9.0/tests/test_navigation_extended.py +0 -224
  195. voodoo_framework-2.9.0/tests/test_node_membership.py +0 -134
  196. voodoo_framework-2.9.0/tests/test_object_store.py +0 -92
  197. voodoo_framework-2.9.0/tests/test_observability.py +0 -459
  198. voodoo_framework-2.9.0/tests/test_operational_policy.py +0 -160
  199. voodoo_framework-2.9.0/tests/test_operational_runtime_ui.py +0 -70
  200. voodoo_framework-2.9.0/tests/test_persistence.py +0 -187
  201. voodoo_framework-2.9.0/tests/test_planner_adaptive.py +0 -269
  202. voodoo_framework-2.9.0/tests/test_primitives.py +0 -529
  203. voodoo_framework-2.9.0/tests/test_product_components.py +0 -176
  204. voodoo_framework-2.9.0/tests/test_protocol.py +0 -369
  205. voodoo_framework-2.9.0/tests/test_protocol_fabric.py +0 -55
  206. voodoo_framework-2.9.0/tests/test_protocol_operational.py +0 -96
  207. voodoo_framework-2.9.0/tests/test_provider_switching.py +0 -71
  208. voodoo_framework-2.9.0/tests/test_providers.py +0 -352
  209. voodoo_framework-2.9.0/tests/test_public_api_3.py +0 -43
  210. voodoo_framework-2.9.0/tests/test_public_assets.py +0 -48
  211. voodoo_framework-2.9.0/tests/test_queue.py +0 -44
  212. voodoo_framework-2.9.0/tests/test_reactive.py +0 -332
  213. voodoo_framework-2.9.0/tests/test_runtime.py +0 -596
  214. voodoo_framework-2.9.0/tests/test_runtime_correctness.py +0 -93
  215. voodoo_framework-2.9.0/tests/test_runtime_fabric.py +0 -226
  216. voodoo_framework-2.9.0/tests/test_runtime_store_app_lifecycle.py +0 -53
  217. voodoo_framework-2.9.0/tests/test_runtime_store_lifecycle.py +0 -211
  218. voodoo_framework-2.9.0/tests/test_runtime_store_provider.py +0 -200
  219. voodoo_framework-2.9.0/tests/test_runtime_transaction.py +0 -156
  220. voodoo_framework-2.9.0/tests/test_scheduler.py +0 -128
  221. voodoo_framework-2.9.0/tests/test_security.py +0 -460
  222. voodoo_framework-2.9.0/tests/test_seo.py +0 -508
  223. voodoo_framework-2.9.0/tests/test_sprint27_convergence.py +0 -129
  224. voodoo_framework-2.9.0/tests/test_sprint28_acceptance.py +0 -154
  225. voodoo_framework-2.9.0/tests/test_state.py +0 -108
  226. voodoo_framework-2.9.0/tests/test_store_first_user_journey.py +0 -116
  227. voodoo_framework-2.9.0/tests/test_store_model_backend.py +0 -209
  228. voodoo_framework-2.9.0/tests/test_store_only_core_import.py +0 -89
  229. voodoo_framework-2.9.0/tests/test_theme.py +0 -119
  230. voodoo_framework-2.9.0/tests/test_theme_presets.py +0 -107
  231. voodoo_framework-2.9.0/tests/test_tools.py +0 -241
  232. voodoo_framework-2.9.0/tests/test_ui.py +0 -603
  233. voodoo_framework-2.9.0/tests/test_ui_magic.py +0 -101
  234. voodoo_framework-2.9.0/tests/test_ui_magic_acceptance.py +0 -99
  235. voodoo_framework-2.9.0/tests/test_voodoo_store_events.py +0 -64
  236. voodoo_framework-2.9.0/tests/test_voodoo_store_execution.py +0 -104
  237. voodoo_framework-2.9.0/tests/test_voodoo_store_hitl_restart.py +0 -138
  238. voodoo_framework-2.9.0/tests/test_voodoo_store_queue.py +0 -290
  239. voodoo_framework-2.9.0/tests/test_voodoo_store_scheduler.py +0 -253
  240. voodoo_framework-2.9.0/tests/test_voodoo_system_components.py +0 -197
  241. voodoo_framework-2.9.0/tests/test_websocket.py +0 -62
  242. voodoo_framework-2.9.0/tests/test_worker_retry_semantics.py +0 -77
  243. voodoo_framework-2.9.0/tests/test_workers.py +0 -201
  244. voodoo_framework-2.9.0/tests/test_workspace.py +0 -249
  245. voodoo_framework-2.9.0/tests/test_world_aware_execution.py +0 -103
  246. voodoo_framework-2.9.0/tests/test_world_model.py +0 -134
  247. voodoo_framework-2.9.0/tests/test_world_sqlite.py +0 -121
  248. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/LICENSE +0 -0
  249. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/README.md +0 -0
  250. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/pyproject.toml +0 -0
  251. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/setup.cfg +0 -0
  252. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/adapters/__init__.py +0 -0
  253. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/adapters/capabilities.py +0 -0
  254. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/adapters/registry.py +0 -0
  255. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/agents/__init__.py +0 -0
  256. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/agents/models.py +0 -0
  257. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/agents/registry.py +0 -0
  258. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/__init__.py +0 -0
  259. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/agent.py +0 -0
  260. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ai/providers/mock.py +0 -0
  261. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/auth/__init__.py +0 -0
  262. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/auth/cookies.py +0 -0
  263. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/auth/middleware.py +0 -0
  264. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/auth/passwords.py +0 -0
  265. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/auth/user.py +0 -0
  266. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/__main__.py +0 -0
  267. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/agents.py +0 -0
  268. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/ai.py +0 -0
  269. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/auth.py +0 -0
  270. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/create.py +0 -0
  271. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/executions.py +0 -0
  272. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/generate.py +0 -0
  273. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/objects.py +0 -0
  274. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/protocol.py +0 -0
  275. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/routes.py +0 -0
  276. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/schedules.py +0 -0
  277. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/start.py +0 -0
  278. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/terminal.py +0 -0
  279. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/cli/version.py +0 -0
  280. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/components.py +0 -0
  281. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/config.py +0 -0
  282. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/core/errors.py +0 -0
  283. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/core/render.py +0 -0
  284. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/data/__init__.py +0 -0
  285. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/data/store_backend.py +0 -0
  286. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/data/store_model.py +0 -0
  287. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/__init__.py +0 -0
  288. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/auth.py +0 -0
  289. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/errors.py +0 -0
  290. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/models.py +0 -0
  291. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/simulator.py +0 -0
  292. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/store.py +0 -0
  293. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/store_voodoo.py +0 -0
  294. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/edge/world.py +0 -0
  295. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/i18n.py +0 -0
  296. {voodoo_framework-2.9.0/src/voodoo → voodoo_framework-3.0.0/src/voodoo/integrations}/mcp/client.py +0 -0
  297. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/memory/__init__.py +0 -0
  298. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/memory/sqlite.py +0 -0
  299. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/mesh/event_bus.py +0 -0
  300. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/__init__.py +0 -0
  301. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/capability.py +0 -0
  302. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/compute.py +0 -0
  303. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/constraint.py +0 -0
  304. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/effect.py +0 -0
  305. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/intent.py +0 -0
  306. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/resource.py +0 -0
  307. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/state.py +0 -0
  308. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/primitives/time.py +0 -0
  309. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/protocol/__init__.py +0 -0
  310. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/protocol/export.py +0 -0
  311. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/protocol/fabric.py +0 -0
  312. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/protocol/operational.py +0 -0
  313. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/py.typed +0 -0
  314. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/routing/pages.py +0 -0
  315. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/agency}/goal_store.py +0 -0
  316. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/capability.py +0 -0
  317. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/constraint.py +0 -0
  318. {voodoo_framework-2.9.0/src/voodoo/mesh → voodoo_framework-3.0.0/src/voodoo/runtime/distributed}/auth.py +0 -0
  319. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/distributed}/membership.py +0 -0
  320. {voodoo_framework-2.9.0/src/voodoo/mesh → voodoo_framework-3.0.0/src/voodoo/runtime/distributed}/remote.py +0 -0
  321. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/errors.py +0 -0
  322. /voodoo_framework-2.9.0/src/voodoo/runtime/world_execution.py → /voodoo_framework-3.0.0/src/voodoo/runtime/execution/world.py +0 -0
  323. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/identity.py +0 -0
  324. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/identity_store.py +0 -0
  325. {voodoo_framework-2.9.0/src/voodoo/runtime → voodoo_framework-3.0.0/src/voodoo/runtime/inspection}/dashboard.py +0 -0
  326. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/operations.py +0 -0
  327. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/planner.py +0 -0
  328. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/policy.py +0 -0
  329. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/transaction.py +0 -0
  330. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/runtime/workflow_store.py +0 -0
  331. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/schedule.py +0 -0
  332. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/__init__.py +0 -0
  333. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/cors.py +0 -0
  334. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/csrf.py +0 -0
  335. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/passwords.py +0 -0
  336. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/rate_limit.py +0 -0
  337. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/security/redaction.py +0 -0
  338. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/static/client.js +0 -0
  339. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/__init__.py +0 -0
  340. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/cache/__init__.py +0 -0
  341. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/cache/interfaces.py +0 -0
  342. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/cache/memory.py +0 -0
  343. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/cache/redis.py +0 -0
  344. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/database/__init__.py +0 -0
  345. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/database/interfaces.py +0 -0
  346. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/database/postgres.py +0 -0
  347. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/database/sqlite.py +0 -0
  348. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/events/__init__.py +0 -0
  349. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/events/interfaces.py +0 -0
  350. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/execution/__init__.py +0 -0
  351. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/execution/migrations.py +0 -0
  352. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/execution/postgres.py +0 -0
  353. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/execution/sqlite.py +0 -0
  354. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/execution/store.py +0 -0
  355. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/manager.py +0 -0
  356. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/objects/__init__.py +0 -0
  357. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/objects/interfaces.py +0 -0
  358. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/objects/local.py +0 -0
  359. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/objects/store.py +0 -0
  360. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/__init__.py +0 -0
  361. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/interfaces.py +0 -0
  362. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/memory.py +0 -0
  363. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/postgres.py +0 -0
  364. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/redis.py +0 -0
  365. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/sqlite.py +0 -0
  366. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/queue/store.py +0 -0
  367. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/scheduler/__init__.py +0 -0
  368. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/scheduler/sqlite.py +0 -0
  369. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/storage/scheduler/store.py +0 -0
  370. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/__init__.py +0 -0
  371. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/brand.py +0 -0
  372. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/events.py +0 -0
  373. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/interactive.py +0 -0
  374. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/layout.py +0 -0
  375. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/markdown.py +0 -0
  376. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/primitives.py +0 -0
  377. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/product.py +0 -0
  378. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/rendering.py +0 -0
  379. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/__init__.py +0 -0
  380. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/extended.py +0 -0
  381. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/product.py +0 -0
  382. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/system.py +0 -0
  383. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/theme.py +0 -0
  384. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/theme_contract.py +0 -0
  385. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/styles/voodoo_system.py +0 -0
  386. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/ui/voodoo_system.py +0 -0
  387. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/world/__init__.py +0 -0
  388. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/world/model.py +0 -0
  389. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/world/models.py +0 -0
  390. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/world/sqlite.py +0 -0
  391. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo/world/store.py +0 -0
  392. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo_framework.egg-info/dependency_links.txt +0 -0
  393. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo_framework.egg-info/entry_points.txt +0 -0
  394. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo_framework.egg-info/requires.txt +0 -0
  395. {voodoo_framework-2.9.0 → voodoo_framework-3.0.0}/src/voodoo_framework.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voodoo-framework
3
- Version: 2.9.0
3
+ Version: 3.0.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>
@@ -0,0 +1,25 @@
1
+ """Voodoo — programmable runtime for adaptive applications and operational systems.
2
+
3
+ The package root is intentionally small. It exposes only the common application
4
+ vocabulary. Catalogs and advanced primitives live in the namespace that owns
5
+ their semantics: voodoo.ui, voodoo.runtime, voodoo.world, voodoo.edge,
6
+ voodoo.protocol, voodoo.observability and voodoo.integrations.
7
+ """
8
+
9
+ from .ai.agent import Agent
10
+ from .ai.tools import tool
11
+ from .core import App, page, state
12
+ from .data import Model
13
+ from .runtime.scheduling.tasks import task
14
+
15
+ __version__ = "3.0.0"
16
+
17
+ __all__ = [
18
+ "Agent",
19
+ "App",
20
+ "Model",
21
+ "page",
22
+ "state",
23
+ "task",
24
+ "tool",
25
+ ]
@@ -420,18 +420,17 @@ def _alert(props: dict[str, Any], theme: Theme) -> str:
420
420
  if variant == "solid":
421
421
  foreground = "text-black" if tone == "warning" else "text-white"
422
422
  return f"{base} {foreground} bg-[{color}] border-[{color}]"
423
- background = "bg-transparent" if variant == "outline" else f"bg-[color-mix(in_srgb,{color}_8%,transparent)]"
424
- return (
425
- f"{base} {background} "
426
- f"border-[color-mix(in_srgb,{color}_28%,transparent)]"
423
+ background = (
424
+ "bg-transparent"
425
+ if variant == "outline"
426
+ else f"bg-[color-mix(in_srgb,{color}_8%,transparent)]"
427
427
  )
428
+ return f"{base} {background} border-[color-mix(in_srgb,{color}_28%,transparent)]"
428
429
 
429
430
 
430
431
  def _progress(props: dict[str, Any], theme: Theme) -> str:
431
432
  tone = props.get("tone", "primary")
432
- size = {"sm": "h-1", "md": "h-2", "lg": "h-3"}.get(
433
- props.get("size", "md"), "h-2"
434
- )
433
+ size = {"sm": "h-1", "md": "h-2", "lg": "h-3"}.get(props.get("size", "md"), "h-2")
435
434
  return (
436
435
  f"block w-full {size} appearance-none overflow-hidden rounded-full "
437
436
  "bg-[var(--vd-color-surface-raised)] "
@@ -481,7 +480,9 @@ def _breadcrumb_item(props: dict[str, Any], theme: Theme) -> str:
481
480
 
482
481
 
483
482
  def _breadcrumb_link(props: dict[str, Any], theme: Theme) -> str:
484
- return "text-inherit no-underline transition-colors hover:text-[var(--vd-color-text)]"
483
+ return (
484
+ "text-inherit no-underline transition-colors hover:text-[var(--vd-color-text)]"
485
+ )
485
486
 
486
487
 
487
488
  def _breadcrumb_current(props: dict[str, Any], theme: Theme) -> str:
@@ -518,15 +519,14 @@ def _accordion(props: dict[str, Any], theme: Theme) -> str:
518
519
  "[&>details+details]:border-t"
519
520
  )
520
521
  if variant == "ghost":
521
- return (
522
- "grid gap-2 [&>details]:border-transparent "
523
- "[&>details]:bg-transparent"
524
- )
522
+ return "grid gap-2 [&>details]:border-transparent [&>details]:bg-transparent"
525
523
  return "grid gap-2"
526
524
 
527
525
 
528
526
  def _accordion_item(props: dict[str, Any], theme: Theme) -> str:
529
- return "rounded-lg border border-[var(--vd-color-border)] bg-[var(--vd-color-surface)]"
527
+ return (
528
+ "rounded-lg border border-[var(--vd-color-border)] bg-[var(--vd-color-surface)]"
529
+ )
530
530
 
531
531
 
532
532
  def _accordion_summary(props: dict[str, Any], theme: Theme) -> str:
@@ -793,12 +793,18 @@ _STYLES: dict[str, Callable[[dict[str, Any], Theme], str]] = {
793
793
  "bg-[var(--vd-color-surface)] px-2 pb-[env(safe-area-inset-bottom)] md:hidden"
794
794
  ),
795
795
  "bottom-nav-item": _bottom_nav_item,
796
- "bottom-nav-item.icon": lambda props, theme: "inline-flex size-6 items-center justify-center",
796
+ "bottom-nav-item.icon": lambda props, theme: (
797
+ "inline-flex size-6 items-center justify-center"
798
+ ),
797
799
  "bottom-nav-item.label": lambda props, theme: "max-w-full truncate",
798
800
  "sidebar-item": _sidebar_item,
799
- "sidebar-item.icon": lambda props, theme: "inline-flex size-6 shrink-0 items-center justify-center",
801
+ "sidebar-item.icon": lambda props, theme: (
802
+ "inline-flex size-6 shrink-0 items-center justify-center"
803
+ ),
800
804
  "sidebar-item.label": lambda props, theme: "min-w-0 truncate",
801
- "sidebar-item.badge": lambda props, theme: "ml-auto text-xs text-[var(--vd-color-text-muted)]",
805
+ "sidebar-item.badge": lambda props, theme: (
806
+ "ml-auto text-xs text-[var(--vd-color-text-muted)]"
807
+ ),
802
808
  "sidebar-header": lambda props, theme: (
803
809
  "flex min-h-10 shrink-0 items-center justify-between gap-2 "
804
810
  "[aside[data-vd-sidebar-mode=rail]_&]:flex-col "
@@ -836,14 +842,20 @@ _STYLES: dict[str, Callable[[dict[str, Any], Theme], str]] = {
836
842
  "border-b border-[var(--vd-color-border)] p-4"
837
843
  ),
838
844
  "drawer.title": lambda props, theme: "text-lg font-semibold",
839
- "drawer.description": lambda props, theme: "text-sm text-[var(--vd-color-text-muted)]",
845
+ "drawer.description": lambda props, theme: (
846
+ "text-sm text-[var(--vd-color-text-muted)]"
847
+ ),
840
848
  "drawer.body": lambda props, theme: "min-h-0 flex-1 overflow-y-auto p-4",
841
849
  "dropdown-shell": lambda props, theme: "contents",
842
850
  "dropdown-menu": _dropdown_menu,
843
851
  "menu-item": _menu_item,
844
852
  "menu-item.label": lambda props, theme: "min-w-0 flex-1",
845
- "menu-shortcut": lambda props, theme: "ml-auto text-xs text-[var(--vd-color-text-muted)]",
846
- "menu-separator": lambda props, theme: "my-1 h-px border-0 bg-[var(--vd-color-border)]",
853
+ "menu-shortcut": lambda props, theme: (
854
+ "ml-auto text-xs text-[var(--vd-color-text-muted)]"
855
+ ),
856
+ "menu-separator": lambda props, theme: (
857
+ "my-1 h-px border-0 bg-[var(--vd-color-border)]"
858
+ ),
847
859
  "tabs": _tabs,
848
860
  "tabs.list": lambda props, theme: (
849
861
  "flex items-center gap-1 border-b border-[var(--vd-color-border)]"
@@ -141,9 +141,7 @@ class VoodooCSSAdapter:
141
141
  if component == "sidebar":
142
142
  classes.append(f"vd-sidebar--{props.get('mode', 'expanded')}")
143
143
  if component == "sidebar-toggle":
144
- classes.append(
145
- f"vd-sidebar-toggle--{props.get('placement', 'standalone')}"
146
- )
144
+ classes.append(f"vd-sidebar-toggle--{props.get('placement', 'standalone')}")
147
145
  if component == "sidebar-item" and props.get("active"):
148
146
  classes.append("vd-sidebar-item--active")
149
147
  if component == "bottom-nav-item" and props.get("active"):
@@ -6,7 +6,7 @@ The Agent turns a prompt into a final answer by iterating:
6
6
 
7
7
  The Agent is a *participant* in the runtime, not a parallel execution
8
8
  framework. ``run()`` creates an :class:`~voodoo.runtime.execution.Execution`
9
- via the :class:`~voodoo.runtime.engine.ExecutionEngine` so that agent
9
+ via the :class:`~voodoo.runtime.execution.engine.ExecutionEngine` so that agent
10
10
  runs share the same lifecycle, persistence, recovery, authorization and
11
11
  observability as every other execution path (HTTP, Worker, Task, MCP, …).
12
12
 
@@ -33,7 +33,7 @@ from enum import StrEnum
33
33
  from typing import Any
34
34
 
35
35
  from voodoo.ai.providers import LLMProvider, Message, default_model, get_provider
36
- from voodoo.tools.registry import ToolRegistry, default_registry
36
+ from voodoo.ai.tools.registry import ToolRegistry, default_registry
37
37
 
38
38
  __all__ = ["Agent", "AgentRun", "AgentEvent"]
39
39
 
@@ -312,7 +312,7 @@ class Agent:
312
312
  )
313
313
  try:
314
314
  self.memory.write(entry)
315
- except Exception: # noqa: BLE001 — memory writes never break the run
315
+ except Exception:
316
316
  pass
317
317
 
318
318
  # -- helpers -----------------------------------------------------------
@@ -361,7 +361,7 @@ class Agent:
361
361
  Flow: Agent → Intent → capability check → Tool → Effect → Mesh.
362
362
 
363
363
  When running inside an
364
- :class:`~voodoo.runtime.engine.ExecutionEngine` Execution, each
364
+ :class:`~voodoo.runtime.execution.engine.ExecutionEngine` Execution, each
365
365
  tool call creates a *child* Execution so the full agent activity
366
366
  is visible in the execution graph:
367
367
 
@@ -422,7 +422,7 @@ class Agent:
422
422
  await self._broadcast("tool.called", {"tool": name, "arguments": arguments})
423
423
  try:
424
424
  result = await self.registry.call(name, **arguments)
425
- except Exception as e: # noqa: BLE001 — capture for telemetry
425
+ except Exception as e:
426
426
  effect.mark_failed(str(e))
427
427
  if ctx is not None:
428
428
  ctx.add_effect(effect)
@@ -470,7 +470,7 @@ class Agent:
470
470
  {"tool": name, "status": "succeeded"},
471
471
  )
472
472
  return result
473
- except Exception as e: # noqa: BLE001
473
+ except Exception as e:
474
474
  await self._broadcast(
475
475
  "tool.completed",
476
476
  {"tool": name, "status": "failed", "error": str(e)},
@@ -496,7 +496,7 @@ class Agent:
496
496
  ) -> AgentRun:
497
497
  """Execute prompt → provider → tool calls → final; return AgentRun.
498
498
 
499
- When an :class:`~voodoo.runtime.engine.ExecutionEngine` is
499
+ When an :class:`~voodoo.runtime.execution.engine.ExecutionEngine` is
500
500
  available (either passed at construction or attached to the
501
501
  active :class:`~voodoo.runtime.context.ExecutionContext`), the
502
502
  run creates a first-class
@@ -537,7 +537,7 @@ class Agent:
537
537
  observability. The agent's provider loop is the *compute*
538
538
  participant — it receives an
539
539
  :class:`~voodoo.runtime.context.ExecutionContext` and returns a
540
- :class:`~voodoo.runtime.engine.ComputeResult`.
540
+ :class:`~voodoo.runtime.execution.engine.ComputeResult`.
541
541
  """
542
542
  from voodoo.primitives.intent import Intent
543
543
  from voodoo.runtime.context import ExecutionContext
@@ -613,7 +613,7 @@ class Agent:
613
613
  When ``run_id`` is ``None``, a new UUID is generated. When
614
614
  called inside an engine Execution, ``run_id`` is the execution id.
615
615
  """
616
- from voodoo.telemetry import telemetry_store
616
+ from voodoo.observability import telemetry_store
617
617
 
618
618
  run_id = run_id or str(uuid.uuid4())
619
619
  trace_id = (
@@ -652,7 +652,7 @@ class Agent:
652
652
  try:
653
653
  desc = self.provider.describe()
654
654
  tools_arg = self._tools_for_provider() if desc.tool_use else None
655
- except Exception: # noqa: BLE001 — best-effort capability check
655
+ except Exception:
656
656
  tools_arg = self._tools_for_provider()
657
657
  response = await self.provider.complete(messages, tools=tools_arg)
658
658
  await self._broadcast(
@@ -724,7 +724,7 @@ class Agent:
724
724
  output = response.content
725
725
  break
726
726
 
727
- except Exception as e: # noqa: BLE001
727
+ except Exception as e:
728
728
  self.state = AgentState.error
729
729
  error = str(e)
730
730
  await self._broadcast("agent.failed", {"run_id": run_id, "error": error})
@@ -771,7 +771,18 @@ class Agent:
771
771
 
772
772
  # -- stream ------------------------------------------------------------
773
773
 
774
- async def stream( # noqa: C901
774
+ async def _stream_provider_events(
775
+ self, messages: list[Message]
776
+ ) -> AsyncIterator[tuple[str, Any]]:
777
+ try:
778
+ description = self.provider.describe()
779
+ tools = self._tools_for_provider() if description.tool_use else None
780
+ except Exception:
781
+ tools = self._tools_for_provider()
782
+ async for event in self.provider.stream(messages, tools=tools):
783
+ yield event.type, event.data
784
+
785
+ async def stream(
775
786
  self,
776
787
  prompt: str,
777
788
  context: dict | None = None,
@@ -779,7 +790,7 @@ class Agent:
779
790
  ) -> AsyncIterator[AgentEvent]:
780
791
  """Yield normalized events: text, tool_started, tool_finished, thinking, error, completed."""
781
792
  run_id = str(uuid.uuid4())
782
- from voodoo.telemetry import telemetry_store
793
+ from voodoo.observability import telemetry_store
783
794
 
784
795
  trace_id = (
785
796
  telemetry_store.trace_id_var.get()
@@ -813,27 +824,24 @@ class Agent:
813
824
  "model": self.model,
814
825
  },
815
826
  )
816
- try:
817
- desc = self.provider.describe()
818
- tools_arg = self._tools_for_provider() if desc.tool_use else None
819
- except Exception: # noqa: BLE001 — best-effort capability check
820
- tools_arg = self._tools_for_provider()
821
- async for event in self.provider.stream(messages, tools=tools_arg):
822
- if event.type == "text":
823
- accumulated_text += event.data.get("text", "")
824
- yield AgentEvent(type="text", data=event.data)
825
- elif event.type == "tool_call":
827
+ async for event_type, event_data in self._stream_provider_events(
828
+ messages
829
+ ):
830
+ if event_type == "text":
831
+ accumulated_text += event_data.get("text", "")
832
+ yield AgentEvent(type="text", data=event_data)
833
+ elif event_type == "tool_call":
826
834
  structured_tool_request = {
827
- "name": event.data.get("name", ""),
828
- "arguments": event.data.get("arguments", {}),
829
- "id": event.data.get("id"),
835
+ "name": event_data.get("name", ""),
836
+ "arguments": event_data.get("arguments", {}),
837
+ "id": event_data.get("id"),
830
838
  }
831
- elif event.type == "done":
832
- tokens_in += event.data.get("tokens_in", 0)
833
- tokens_out += event.data.get("tokens_out", 0)
834
- cost += event.data.get("cost", 0.0)
835
- elif event.type == "error":
836
- raise Exception(event.data.get("error", "Provider error"))
839
+ elif event_type == "done":
840
+ tokens_in += event_data.get("tokens_in", 0)
841
+ tokens_out += event_data.get("tokens_out", 0)
842
+ cost += event_data.get("cost", 0.0)
843
+ elif event_type == "error":
844
+ raise Exception(event_data.get("error", "Provider error"))
837
845
  await self._broadcast(
838
846
  "model.completed",
839
847
  {
@@ -918,7 +926,7 @@ class Agent:
918
926
  output = accumulated_text
919
927
  break
920
928
 
921
- except Exception as e: # noqa: BLE001
929
+ except Exception as e:
922
930
  self.state = AgentState.error
923
931
  error = str(e)
924
932
  yield AgentEvent(type="error", data={"error": error})
@@ -1083,5 +1091,5 @@ class Agent:
1083
1091
  from voodoo.mesh import mesh
1084
1092
 
1085
1093
  await mesh.broadcast(event, payload)
1086
- except Exception: # noqa: BLE001 — mesh is optional in tests
1094
+ except Exception:
1087
1095
  pass
@@ -23,7 +23,7 @@ class RuntimeTruthAgent(LegacyAgent):
23
23
  from voodoo.runtime.context import current_context
24
24
 
25
25
  return current_context()
26
- except Exception: # noqa: BLE001
26
+ except Exception:
27
27
  return None
28
28
 
29
29
  def _canonical_execution_id(self, run_record: AgentRun) -> str | None:
@@ -113,7 +113,7 @@ class RuntimeTruthAgent(LegacyAgent):
113
113
  )
114
114
  try:
115
115
  self.memory.write(entry)
116
- except Exception: # noqa: BLE001 — memory writes never break the run
116
+ except Exception:
117
117
  pass
118
118
 
119
119
  async def _execute_tool_as_child_execution(
@@ -188,7 +188,7 @@ class LLMProvider(ABC):
188
188
  """Yield normalized streaming events."""
189
189
  raise NotImplementedError
190
190
  # pragma: no cover - abstract generator marker
191
- yield # type: ignore[unreachable] # noqa: B018
191
+ yield # type: ignore[unreachable]
192
192
 
193
193
  async def generate(
194
194
  self, messages: list[Message], **kwargs: Any
@@ -230,10 +230,10 @@ class LLMProvider(ABC):
230
230
 
231
231
  #: Maps provider name → fully-qualified provider class path (lazy import).
232
232
  _PROVIDER_CLASSES: dict[str, str] = {
233
- "openai": "voodoo.ai.providers.openai.OpenAIProvider",
234
- "anthropic": "voodoo.ai.providers.anthropic.AnthropicProvider",
235
- "gemini": "voodoo.ai.providers.gemini.GeminiProvider",
236
- "ollama": "voodoo.ai.providers.ollama.OllamaProvider",
233
+ "openai": "voodoo.integrations.ai.openai.OpenAIProvider",
234
+ "anthropic": "voodoo.integrations.ai.anthropic.AnthropicProvider",
235
+ "gemini": "voodoo.integrations.ai.gemini.GeminiProvider",
236
+ "ollama": "voodoo.integrations.ai.ollama.OllamaProvider",
237
237
  "mock": "voodoo.ai.providers.mock.MockProvider",
238
238
  }
239
239
 
@@ -270,7 +270,7 @@ def _routing_aliases(aliases: dict[str, str] | None) -> dict[str, str]:
270
270
 
271
271
  merged.update(config.models.aliases or {})
272
272
  merged.update(config.ai.aliases or {})
273
- except Exception: # noqa: BLE001 — config resolution is best-effort here
273
+ except Exception:
274
274
  pass
275
275
  if aliases:
276
276
  merged.update(aliases)
@@ -329,7 +329,7 @@ def default_model() -> str:
329
329
  provider = config.ai.provider or "openai"
330
330
  return f"{provider}:{config.ai.model}"
331
331
  return config.models.default
332
- except Exception: # noqa: BLE001 — config resolution is best-effort here
332
+ except Exception:
333
333
  return "mock:default"
334
334
 
335
335
 
@@ -357,7 +357,7 @@ def get_provider(model: str, **kwargs: Any) -> LLMProvider:
357
357
  kwargs.setdefault("base_url", config.ai.base_url)
358
358
  if config.ai.api_key:
359
359
  kwargs.setdefault("api_key", config.ai.api_key)
360
- except Exception: # noqa: BLE001 — config resolution is best-effort here
360
+ except Exception:
361
361
  pass
362
362
 
363
363
  return provider_cls(model=model_id, **kwargs)
@@ -0,0 +1,7 @@
1
+ """Compatibility alias for :mod:`voodoo.integrations.ai.anthropic`."""
2
+
3
+ import sys
4
+
5
+ from voodoo.integrations.ai import anthropic
6
+
7
+ sys.modules[__name__] = anthropic
@@ -0,0 +1,7 @@
1
+ """Compatibility alias for :mod:`voodoo.integrations.ai.gemini`."""
2
+
3
+ import sys
4
+
5
+ from voodoo.integrations.ai import gemini
6
+
7
+ sys.modules[__name__] = gemini
@@ -0,0 +1,7 @@
1
+ """Compatibility alias for :mod:`voodoo.integrations.ai.ollama`."""
2
+
3
+ import sys
4
+
5
+ from voodoo.integrations.ai import ollama
6
+
7
+ sys.modules[__name__] = ollama
@@ -0,0 +1,7 @@
1
+ """Compatibility alias for :mod:`voodoo.integrations.ai.openai`."""
2
+
3
+ import sys
4
+
5
+ from voodoo.integrations.ai import openai
6
+
7
+ sys.modules[__name__] = openai
@@ -15,7 +15,7 @@ Usage::
15
15
 
16
16
  The decorated function remains callable as plain Python while carrying a
17
17
  ``__tool_spec__`` attribute (a :class:`ToolSpec`) and being registered in the
18
- default registry (``voodoo.tools.registry.default_registry``).
18
+ default registry (``voodoo.ai.tools.registry.default_registry``).
19
19
  """
20
20
 
21
21
  from __future__ import annotations
@@ -29,7 +29,7 @@ __all__ = ["tool", "ToolSpec", "ToolRegistry", "default_registry"]
29
29
 
30
30
  # Re-export the default registry instance (lives in the registry module so it
31
31
  # can be monkeypatched in tests without being shadowed by this package).
32
- from voodoo.ai.tools.registry import default_registry # noqa: E402, F401
32
+ from voodoo.ai.tools.registry import default_registry
33
33
 
34
34
 
35
35
  def _resolve_default_registry() -> ToolRegistry:
@@ -54,7 +54,7 @@ def tool(
54
54
  ) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ...
55
55
 
56
56
 
57
- def tool( # noqa: ANN201 — intentionally generic decorator return
57
+ def tool(
58
58
  func: Callable[..., Any] | None = None,
59
59
  *,
60
60
  name: str | None = None,
@@ -76,7 +76,7 @@ def _build_schemas(func: Callable[..., Any]) -> tuple[dict[str, Any], dict[str,
76
76
  """Derive input/output JSON schemas from a function's type hints."""
77
77
  try:
78
78
  hints = get_type_hints(func)
79
- except Exception: # noqa: BLE001 — unresolved forward refs fall back to raw
79
+ except Exception:
80
80
  hints = getattr(func, "__annotations__", {}) or {}
81
81
 
82
82
  sig = inspect.signature(func)
@@ -108,7 +108,7 @@ def _source_metadata(func: Callable[..., Any]) -> str:
108
108
  try:
109
109
  file = inspect.getsourcefile(inspect.unwrap(func)) or "<unknown>"
110
110
  line = inspect.getsourcelines(inspect.unwrap(func))[1]
111
- except (OSError, TypeError): # noqa: UP024 — broad: builtins/C extensions
111
+ except (OSError, TypeError):
112
112
  line = 0
113
113
  file = "<unknown>"
114
114
  return f"{module}:{file}:{line}"
@@ -0,0 +1,144 @@
1
+ import inspect
2
+ from collections.abc import Callable
3
+ from functools import wraps
4
+ from typing import Any
5
+
6
+ from starlette.requests import Request
7
+ from starlette.responses import JSONResponse, RedirectResponse
8
+
9
+ from voodoo.auth.user import get_current_user
10
+
11
+
12
+ def _request(args: tuple[Any, ...], kwargs: dict[str, Any]) -> Request | None:
13
+ req = kwargs.get("request")
14
+ if isinstance(req, Request):
15
+ return req
16
+ if args and isinstance(args[0], Request):
17
+ return args[0]
18
+ return None
19
+
20
+
21
+ def _unauthenticated(req: Request | None, redirect_url: str | None = None) -> Any:
22
+ if req and redirect_url and "text/html" in req.headers.get("accept", ""):
23
+ return RedirectResponse(url=redirect_url, status_code=302)
24
+ return JSONResponse(
25
+ {"error": "Authentication required", "code": 401}, status_code=401
26
+ )
27
+
28
+
29
+ def _inject_user(sig: inspect.Signature, kwargs: dict[str, Any], user: Any) -> None:
30
+ if "user" in sig.parameters and "user" not in kwargs:
31
+ kwargs["user"] = user
32
+
33
+
34
+ def _guard(
35
+ check: Callable[[Any], Any | None],
36
+ redirect_url: str | None = None,
37
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
38
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
39
+ sig = inspect.signature(func)
40
+
41
+ def authorize(
42
+ args: tuple[Any, ...], kwargs: dict[str, Any]
43
+ ) -> tuple[Any, Any | None]:
44
+ req = _request(args, kwargs)
45
+ user = get_current_user(req)
46
+ if not user or not user.is_authenticated:
47
+ return None, _unauthenticated(req, redirect_url)
48
+ denied = check(user)
49
+ if denied is not None:
50
+ return None, denied
51
+ _inject_user(sig, kwargs, user)
52
+ return user, None
53
+
54
+ @wraps(func)
55
+ async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
56
+ _, denied = authorize(args, kwargs)
57
+ if denied is not None:
58
+ return denied
59
+ return await func(*args, **kwargs)
60
+
61
+ @wraps(func)
62
+ def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
63
+ _, denied = authorize(args, kwargs)
64
+ if denied is not None:
65
+ return denied
66
+ return func(*args, **kwargs)
67
+
68
+ return async_wrapper if inspect.iscoroutinefunction(func) else sync_wrapper
69
+
70
+ return decorator
71
+
72
+
73
+ def require_auth(
74
+ redirect_url: str | None = None,
75
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
76
+ """Require an authenticated user."""
77
+ return _guard(lambda _user: None, redirect_url)
78
+
79
+
80
+ def require_roles(
81
+ *roles: str, redirect_url: str | None = None
82
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
83
+ """Require the user to hold one of the specified roles."""
84
+
85
+ def check(user: Any) -> Any | None:
86
+ if user.has_role(*roles):
87
+ return None
88
+ return JSONResponse(
89
+ {
90
+ "error": "Forbidden: Insufficient role permissions",
91
+ "code": 403,
92
+ "required_roles": list(roles),
93
+ },
94
+ status_code=403,
95
+ )
96
+
97
+ return _guard(check, redirect_url)
98
+
99
+
100
+ def require_scopes(*scopes: str) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
101
+ """Require specific API key scopes or permissions."""
102
+
103
+ def check(user: Any) -> Any | None:
104
+ if user.has_scope(*scopes):
105
+ return None
106
+ return JSONResponse(
107
+ {
108
+ "error": "Forbidden: Missing required scope",
109
+ "code": 403,
110
+ "required_scopes": list(scopes),
111
+ },
112
+ status_code=403,
113
+ )
114
+
115
+ return _guard(check)
116
+
117
+
118
+ def require_api_key(
119
+ scopes: list[str] | None = None,
120
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
121
+ """Enforce machine-to-machine API key authentication."""
122
+
123
+ def check(user: Any) -> Any | None:
124
+ if user.auth_type != "api_key":
125
+ return JSONResponse(
126
+ {"error": "Valid API Key required", "code": 401}, status_code=401
127
+ )
128
+ if scopes and not user.has_scope(*scopes):
129
+ return JSONResponse(
130
+ {"error": "Forbidden: Insufficient API key permissions", "code": 403},
131
+ status_code=403,
132
+ )
133
+ return None
134
+
135
+ return _guard(check)
136
+
137
+
138
+ login_required = require_auth
139
+ requires_role = require_roles
140
+ requires_roles = require_roles
141
+ requires_permission = require_scopes
142
+ requires_permissions = require_scopes
143
+ requires_scopes = require_scopes
144
+ requires_api_key = require_api_key