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