by-framework 0.2.2.dev8__tar.gz → 0.2.2.dev9__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.
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/PKG-INFO +1 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/pyproject.toml +1 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/admin/cli.py +3 -2
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/config.py +10 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/constants.py +13 -3
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/app.py +29 -11
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/common/test_config.py +47 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/common/test_constants.py +21 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/common/test_redis_client.py +1 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_app.py +69 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/uv.lock +1 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.dockerignore +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/RELEASING.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/workflows/ci.yml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/workflows/publish.yml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/workflows/stale.yml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.gitignore +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.pre-commit-config.yaml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/AGENTS.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/CHANGELOG.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/CLAUDE.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/CODE_OF_CONDUCT.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/CONTRIBUTING.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/LICENSE +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/Makefile +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/README_zh.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/SECURITY.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/assets/img/architecture_en.png +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/assets/img/architecture_zh.png +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/autoformat.sh +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/by-framework-trace-change-usage.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/by-framework-trace-complete-guide.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/plans/2026-05-15-worker-task-state-stats.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/plans/2026-06-10-trace-metrics-correlation.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/worker_management.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/src/by_framework_adk/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/src/by_framework_adk/_utils.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/src/by_framework_adk/adapter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/src/by_framework_adk/worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/tests/test_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/Dockerfile +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/index.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/package-lock.json +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/package.json +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/src/main.jsx +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/src/styles.css +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/vite.config.js +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/adapters.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/dashboard.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/static/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/static/app.js +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/static/index.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/src/by_framework_dashboard/static/styles.css +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/tests/test_dashboard_server.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/src/by_framework_history_byclaw/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/src/by_framework_history_byclaw/byclaw_history.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/tests/test_byclaw_history.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-postgres/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-postgres/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-postgres/src/by_framework_history_postgres/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-postgres/src/by_framework_history_postgres/postgres.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-postgres/tests/test_postgres_history_storage.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/src/by_framework_langgraph/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/src/by_framework_langgraph/_utils.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/src/by_framework_langgraph/adapter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/src/by_framework_langgraph/tools.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/src/by_framework_langgraph/worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/tests/test_adapter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/tests/test_tools.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/tests/test_utils.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/src/by_framework_trace_langfuse/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/src/by_framework_trace_langfuse/langfuse.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/tests/test_langfuse_import.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/src/by_framework_trace_phoenix/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/src/by_framework_trace_phoenix/phoenix.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/tests/test_phoenix_import.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/tests/test_phoenix_plugin.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/src/by_framework_trace_query/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/src/by_framework_trace_query/client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/src/by_framework_trace_query/merger.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/src/by_framework_trace_query/models.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/src/by_framework_trace_query/redis_source.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/tests/test_trace_query_sdk.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/pylintrc +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/scripts/python_quality.sh +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/__main__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/admin/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/admin/worker_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/client/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/client/byai_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/client/client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/emitter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/exceptions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/logger.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/common/redis_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/availability.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/delivery_gate.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/discovery.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/extensions/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/extensions/agent_config.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/extensions/agent_config_audit.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/extensions/plugin.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/extensions/registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/extensions/trace_provider.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/action_type.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/agent_state.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/byai_codec.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/byai_command.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/byai_types.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/commands.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/content_codec.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/content_type.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/data_message.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/data_shapes.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/event_type.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/events.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/message.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/message_header.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/responses.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/protocol/results.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/agent_config_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/agent_runtime_state.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/file_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/file_paths.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/file_permissions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/filestore/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/filestore/base.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/filestore/local.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/history/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/history/base.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/history/history_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/history/in_memory.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/runtime/session_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/wakeup_controller.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/core/workspace.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/base.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/common.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/execution.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/http.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/protocol.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/errors/registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/metrics/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/metrics/catalog.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/metrics/collector.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/metrics/read_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/metrics/snapshot.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/trace/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/trace/external_trace.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/trace/span_recorder.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/trace/trace_schema.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/trace/trace_writer.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/util/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/util/discovery_http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/util/generate_message_id.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/util/http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/_control_handling.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/_execution_tracking.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/_message_processing.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/byai_context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/byai_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/heartbeat.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/processor.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/runner.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/sandbox/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/sandbox/hook_sandbox.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/worker/worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/admin/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/admin/test_cli.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/client/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/client/test_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/common/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/common/test_exceptions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/common/test_logger.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/conftest.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/protocol/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/protocol/test_byai_codec.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/protocol/test_command_wire.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/protocol/test_protocol.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/protocol/test_results.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/history/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/history/test_history_persistence.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_file_access_context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_file_manager_default_storage.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_file_paths.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_file_permissions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_filestore_local_collection.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_filestore_local_mutation.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_filestore_local_read.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/runtime/test_filestore_local_search.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/test_agent_config_audit.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/test_availability.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/test_discovery.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/test_registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/core/test_worker_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/integration/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/integration/test_ask_user_flow.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/integration/test_callback_flow.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/integration/test_logger_integration.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/integration/test_scatter_gather.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/metrics/test_catalog.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/metrics/test_collector.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/metrics/test_metrics.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/metrics/test_read_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/metrics/test_snapshot.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/plugin/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/plugin/test_langfuse_plugin.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/plugin/test_plugin_discovery.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/plugin/test_plugin_improvements.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/plugin/test_plugin_registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/plugin/test_plugin_system.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/trace/test_external_trace.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/trace/test_logger_correlation.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/trace/test_otel_exporter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/trace/test_span_recorder.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/trace/test_trace_writer.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/util/test_discovery_http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/util/test_discovery_http_client_download.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/util/test_discovery_http_client_upload.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/util/test_http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_admin_control_handling.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_byai_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_control_handling.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_emitter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_fetch_messages.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_gateway_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_heartbeat.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_message_processing.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_processor.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_runner.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_sandbox.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/tests/worker/test_workspace.py +0 -0
|
@@ -31,8 +31,9 @@ app = typer.Typer(
|
|
|
31
31
|
help=(
|
|
32
32
|
"by-framework cluster admin CLI. For Redis Cluster, omit --redis-url "
|
|
33
33
|
"and set REDIS_CLUSTER_HOST (comma-separated host:port list; implies "
|
|
34
|
-
"cluster mode
|
|
35
|
-
"REDIS_CLUSTER_NODES
|
|
34
|
+
"both cluster mode and REDIS_KEY_SCHEMA_VERSION=v2 unless set "
|
|
35
|
+
"explicitly). REDIS_MODE=cluster + REDIS_CLUSTER_NODES + "
|
|
36
|
+
"REDIS_KEY_SCHEMA_VERSION=v2 also still works."
|
|
36
37
|
),
|
|
37
38
|
)
|
|
38
39
|
worker_app = typer.Typer(no_args_is_help=True)
|
|
@@ -9,6 +9,7 @@ from dataclasses import dataclass, field
|
|
|
9
9
|
from typing import Literal, Optional
|
|
10
10
|
|
|
11
11
|
from by_framework.common.constants import RedisKeys
|
|
12
|
+
from by_framework.common.logger import logger
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
@dataclass(frozen=True)
|
|
@@ -36,6 +37,9 @@ class RedisConfig:
|
|
|
36
37
|
to switch to cluster mode, no separate REDIS_MODE=cluster needed.
|
|
37
38
|
An explicit REDIS_MODE still takes precedence when set, so existing
|
|
38
39
|
explicit REDIS_MODE=cluster + REDIS_CLUSTER_NODES setups keep working.
|
|
40
|
+
|
|
41
|
+
REDIS_DATABASE replaces REDIS_DB (which still works as a deprecated
|
|
42
|
+
fallback, logging a warning, during the transition period).
|
|
39
43
|
"""
|
|
40
44
|
password = os.environ.get("REDIS_PASSWORD", "")
|
|
41
45
|
username = os.environ.get("REDIS_USERNAME") or None
|
|
@@ -51,10 +55,15 @@ class RedisConfig:
|
|
|
51
55
|
for node in cluster_nodes_str.split(","):
|
|
52
56
|
node_host, node_port = node.rsplit(":", 1)
|
|
53
57
|
cluster_nodes.append((node_host, int(node_port)))
|
|
58
|
+
db_str = os.environ.get("REDIS_DATABASE")
|
|
59
|
+
if db_str is None:
|
|
60
|
+
db_str = os.environ.get("REDIS_DB")
|
|
61
|
+
if db_str is not None:
|
|
62
|
+
logger.warning("REDIS_DB is deprecated, use REDIS_DATABASE instead")
|
|
54
63
|
return cls(
|
|
55
64
|
host=os.environ.get("REDIS_HOST", "localhost"),
|
|
56
65
|
port=int(os.environ.get("REDIS_PORT", "6379")),
|
|
57
|
-
db=int(
|
|
66
|
+
db=int(db_str) if db_str is not None else 0,
|
|
58
67
|
password=password,
|
|
59
68
|
username=username,
|
|
60
69
|
max_connections=int(max_connections) if max_connections else None,
|
|
@@ -12,10 +12,20 @@ from typing import Optional
|
|
|
12
12
|
def get_key_schema_version() -> str:
|
|
13
13
|
"""Return the configured Redis key schema version ("v1" or "v2").
|
|
14
14
|
|
|
15
|
-
Controlled by REDIS_KEY_SCHEMA_VERSION,
|
|
16
|
-
|
|
15
|
+
Controlled by REDIS_KEY_SCHEMA_VERSION, which always wins when set
|
|
16
|
+
explicitly. When it isn't set, REDIS_CLUSTER_HOST being configured
|
|
17
|
+
implies "v2" (cluster mode requires v2 - v1 keys have no hash tags and
|
|
18
|
+
hit CROSSSLOT errors under Cluster; see redis_client.init_redis's
|
|
19
|
+
fail-fast check); otherwise it defaults to "v1" (the legacy unprefixed
|
|
20
|
+
key format). This mirrors RedisConfig.from_env()'s REDIS_MODE/
|
|
21
|
+
REDIS_CLUSTER_HOST precedence, but deliberately does NOT infer "v2"
|
|
22
|
+
from an explicit REDIS_MODE=cluster alone (without REDIS_CLUSTER_HOST)
|
|
23
|
+
- that legacy explicit-mode path still requires
|
|
24
|
+
REDIS_KEY_SCHEMA_VERSION=v2 to be set by hand.
|
|
17
25
|
"""
|
|
18
|
-
version = os.environ.get("REDIS_KEY_SCHEMA_VERSION"
|
|
26
|
+
version = os.environ.get("REDIS_KEY_SCHEMA_VERSION")
|
|
27
|
+
if version is None:
|
|
28
|
+
version = "v2" if os.environ.get("REDIS_CLUSTER_HOST") else "v1"
|
|
19
29
|
if version not in ("v1", "v2"):
|
|
20
30
|
raise ValueError(
|
|
21
31
|
f"Invalid REDIS_KEY_SCHEMA_VERSION: {version!r} (must be 'v1' or 'v2')"
|
|
@@ -131,6 +131,17 @@ async def _run_worker_async(
|
|
|
131
131
|
# parties can configure either mode purely programmatically or purely
|
|
132
132
|
# via env vars, without the two modes behaving inconsistently.
|
|
133
133
|
env_config = RedisConfig.from_env()
|
|
134
|
+
if redis_mode is not None:
|
|
135
|
+
effective_mode = redis_mode
|
|
136
|
+
elif redis_cluster_nodes:
|
|
137
|
+
# Mirrors REDIS_CLUSTER_HOST's env-var precedence: passing
|
|
138
|
+
# redis_cluster_nodes alone is enough to imply cluster mode, no
|
|
139
|
+
# separate redis_mode="cluster" required. Without this, passing
|
|
140
|
+
# redis_cluster_nodes alone would silently stay in standalone mode
|
|
141
|
+
# and the nodes list would be dropped on the floor.
|
|
142
|
+
effective_mode = "cluster"
|
|
143
|
+
else:
|
|
144
|
+
effective_mode = env_config.mode
|
|
134
145
|
effective_config = replace(
|
|
135
146
|
env_config,
|
|
136
147
|
host=redis_host if redis_host is not None else env_config.host,
|
|
@@ -142,7 +153,7 @@ async def _run_worker_async(
|
|
|
142
153
|
username=(
|
|
143
154
|
redis_username if redis_username is not None else env_config.username
|
|
144
155
|
),
|
|
145
|
-
mode=
|
|
156
|
+
mode=effective_mode,
|
|
146
157
|
cluster_nodes=(
|
|
147
158
|
redis_cluster_nodes
|
|
148
159
|
if redis_cluster_nodes is not None
|
|
@@ -276,16 +287,23 @@ def run_worker(
|
|
|
276
287
|
Redis configuration: every redis_* argument defaults to None, meaning
|
|
277
288
|
"not specified" - when not passed, the value is read from the
|
|
278
289
|
corresponding REDIS_* environment variable (REDIS_HOST, REDIS_PORT,
|
|
279
|
-
|
|
280
|
-
REDIS_CLUSTER_NODES), falling back to
|
|
281
|
-
none is set.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
290
|
+
REDIS_DATABASE, REDIS_PASSWORD, REDIS_USERNAME, REDIS_MODE,
|
|
291
|
+
REDIS_CLUSTER_HOST, REDIS_CLUSTER_NODES), falling back to
|
|
292
|
+
"localhost"/6379/standalone if none is set. REDIS_DATABASE replaces
|
|
293
|
+
REDIS_DB (still works as a deprecated fallback, logging a warning).
|
|
294
|
+
Setting REDIS_CLUSTER_HOST (comma-separated "host:port" list) alone is
|
|
295
|
+
enough to switch to cluster mode - no separate REDIS_MODE=cluster
|
|
296
|
+
required, though an explicit REDIS_MODE still wins if set; it also
|
|
297
|
+
implies REDIS_KEY_SCHEMA_VERSION=v2 unless that's set explicitly. An
|
|
298
|
+
explicitly-passed argument always takes precedence over its env var,
|
|
299
|
+
for every field, in both standalone and cluster mode. The same
|
|
300
|
+
single-argument convenience carries over to the programmatic path:
|
|
301
|
+
passing just ``redis_cluster_nodes=[("h1", 6379)]`` (no ``redis_mode``)
|
|
302
|
+
is enough to switch to cluster mode, mirroring REDIS_CLUSTER_HOST -
|
|
303
|
+
``redis_mode`` only needs to be passed to explicitly force a mode
|
|
304
|
+
(e.g. pin a script to standalone regardless of REDIS_CLUSTER_HOST).
|
|
305
|
+
So either mode can be configured purely programmatically or purely via
|
|
306
|
+
env vars, without the two paths behaving inconsistently.
|
|
289
307
|
|
|
290
308
|
Plugin support:
|
|
291
309
|
- **Auto mode**: System automatically discovers and loads all subclasses
|
|
@@ -49,6 +49,7 @@ class TestRedisConfig(unittest.TestCase):
|
|
|
49
49
|
env_vars = [
|
|
50
50
|
"REDIS_HOST",
|
|
51
51
|
"REDIS_PORT",
|
|
52
|
+
"REDIS_DATABASE",
|
|
52
53
|
"REDIS_DB",
|
|
53
54
|
"REDIS_PASSWORD",
|
|
54
55
|
"REDIS_USERNAME",
|
|
@@ -101,6 +102,52 @@ class TestRedisConfig(unittest.TestCase):
|
|
|
101
102
|
else:
|
|
102
103
|
os.environ.pop("REDIS_CLUSTER_NODES", None)
|
|
103
104
|
|
|
105
|
+
def test_from_env_reads_redis_database(self):
|
|
106
|
+
"""Test that from_env reads db from REDIS_DATABASE."""
|
|
107
|
+
env_vars = ["REDIS_DATABASE", "REDIS_DB"]
|
|
108
|
+
old_values = {k: os.environ.get(k) for k in env_vars}
|
|
109
|
+
try:
|
|
110
|
+
for k in env_vars:
|
|
111
|
+
os.environ.pop(k, None)
|
|
112
|
+
os.environ["REDIS_DATABASE"] = "3"
|
|
113
|
+
self.assertEqual(RedisConfig.from_env().db, 3)
|
|
114
|
+
finally:
|
|
115
|
+
for k, v in old_values.items():
|
|
116
|
+
if v is not None:
|
|
117
|
+
os.environ[k] = v
|
|
118
|
+
else:
|
|
119
|
+
os.environ.pop(k, None)
|
|
120
|
+
|
|
121
|
+
def test_from_env_falls_back_to_deprecated_redis_db(self):
|
|
122
|
+
"""Test that from_env falls back to REDIS_DB when REDIS_DATABASE is unset."""
|
|
123
|
+
env_vars = ["REDIS_DATABASE", "REDIS_DB"]
|
|
124
|
+
old_values = {k: os.environ.get(k) for k in env_vars}
|
|
125
|
+
try:
|
|
126
|
+
os.environ.pop("REDIS_DATABASE", None)
|
|
127
|
+
os.environ["REDIS_DB"] = "5"
|
|
128
|
+
self.assertEqual(RedisConfig.from_env().db, 5)
|
|
129
|
+
finally:
|
|
130
|
+
for k, v in old_values.items():
|
|
131
|
+
if v is not None:
|
|
132
|
+
os.environ[k] = v
|
|
133
|
+
else:
|
|
134
|
+
os.environ.pop(k, None)
|
|
135
|
+
|
|
136
|
+
def test_from_env_redis_database_takes_precedence_over_deprecated_redis_db(self):
|
|
137
|
+
"""Test that REDIS_DATABASE wins over REDIS_DB when both are set."""
|
|
138
|
+
env_vars = ["REDIS_DATABASE", "REDIS_DB"]
|
|
139
|
+
old_values = {k: os.environ.get(k) for k in env_vars}
|
|
140
|
+
try:
|
|
141
|
+
os.environ["REDIS_DATABASE"] = "2"
|
|
142
|
+
os.environ["REDIS_DB"] = "9"
|
|
143
|
+
self.assertEqual(RedisConfig.from_env().db, 2)
|
|
144
|
+
finally:
|
|
145
|
+
for k, v in old_values.items():
|
|
146
|
+
if v is not None:
|
|
147
|
+
os.environ[k] = v
|
|
148
|
+
else:
|
|
149
|
+
os.environ.pop(k, None)
|
|
150
|
+
|
|
104
151
|
def test_from_env_cluster_host_implies_cluster_mode(self):
|
|
105
152
|
"""Setting REDIS_CLUSTER_HOST alone (no REDIS_MODE) switches to cluster mode."""
|
|
106
153
|
env_vars = ["REDIS_MODE", "REDIS_CLUSTER_HOST", "REDIS_CLUSTER_NODES"]
|
|
@@ -478,12 +478,18 @@ class TestGetKeySchemaVersion(unittest.TestCase):
|
|
|
478
478
|
|
|
479
479
|
def setUp(self):
|
|
480
480
|
self._old_value = os.environ.get("REDIS_KEY_SCHEMA_VERSION")
|
|
481
|
+
self._old_cluster_host = os.environ.get("REDIS_CLUSTER_HOST")
|
|
482
|
+
os.environ.pop("REDIS_CLUSTER_HOST", None)
|
|
481
483
|
|
|
482
484
|
def tearDown(self):
|
|
483
485
|
if self._old_value is not None:
|
|
484
486
|
os.environ["REDIS_KEY_SCHEMA_VERSION"] = self._old_value
|
|
485
487
|
else:
|
|
486
488
|
os.environ.pop("REDIS_KEY_SCHEMA_VERSION", None)
|
|
489
|
+
if self._old_cluster_host is not None:
|
|
490
|
+
os.environ["REDIS_CLUSTER_HOST"] = self._old_cluster_host
|
|
491
|
+
else:
|
|
492
|
+
os.environ.pop("REDIS_CLUSTER_HOST", None)
|
|
487
493
|
|
|
488
494
|
def test_defaults_to_v1(self):
|
|
489
495
|
"""Test that the schema version defaults to v1 when unset."""
|
|
@@ -501,6 +507,21 @@ class TestGetKeySchemaVersion(unittest.TestCase):
|
|
|
501
507
|
with self.assertRaises(ValueError):
|
|
502
508
|
get_key_schema_version()
|
|
503
509
|
|
|
510
|
+
def test_defaults_to_v2_when_cluster_host_set(self):
|
|
511
|
+
"""REDIS_CLUSTER_HOST alone (no explicit schema version) implies v2."""
|
|
512
|
+
os.environ.pop("REDIS_KEY_SCHEMA_VERSION", None)
|
|
513
|
+
os.environ["REDIS_CLUSTER_HOST"] = "h1:6379,h2:6380"
|
|
514
|
+
self.assertEqual(get_key_schema_version(), "v2")
|
|
515
|
+
|
|
516
|
+
def test_explicit_value_wins_over_cluster_host(self):
|
|
517
|
+
"""An explicit REDIS_KEY_SCHEMA_VERSION always wins, even if it
|
|
518
|
+
contradicts REDIS_CLUSTER_HOST's implied v2 - redis_client.init_redis's
|
|
519
|
+
fail-fast check is what catches this combination, not silent
|
|
520
|
+
auto-correction here."""
|
|
521
|
+
os.environ["REDIS_CLUSTER_HOST"] = "h1:6379"
|
|
522
|
+
os.environ["REDIS_KEY_SCHEMA_VERSION"] = "v1"
|
|
523
|
+
self.assertEqual(get_key_schema_version(), "v1")
|
|
524
|
+
|
|
504
525
|
|
|
505
526
|
if __name__ == "__main__":
|
|
506
527
|
unittest.main()
|
|
@@ -225,6 +225,75 @@ async def test_run_worker_async_supports_fully_programmatic_cluster_config():
|
|
|
225
225
|
assert kwargs["config"].password == "cluster-secret"
|
|
226
226
|
|
|
227
227
|
|
|
228
|
+
@pytest.mark.asyncio
|
|
229
|
+
async def test_run_worker_async_cluster_nodes_alone_implies_cluster_mode():
|
|
230
|
+
"""Passing redis_cluster_nodes without redis_mode must imply cluster
|
|
231
|
+
mode, mirroring REDIS_CLUSTER_HOST's env-var precedence - otherwise the
|
|
232
|
+
nodes list would be silently dropped in standalone mode."""
|
|
233
|
+
with (
|
|
234
|
+
patch("by_framework.worker.app.init_redis") as mock_init_redis,
|
|
235
|
+
patch("by_framework.worker.app.close_redis", new_callable=AsyncMock),
|
|
236
|
+
patch("by_framework.worker.app.WorkerRegistry"),
|
|
237
|
+
patch("by_framework.worker.app.WorkspaceManager"),
|
|
238
|
+
patch("by_framework.worker.app.WorkerRunner") as mock_runner,
|
|
239
|
+
):
|
|
240
|
+
mock_init_redis.return_value = MagicMock()
|
|
241
|
+
mock_runner.return_value.start = AsyncMock()
|
|
242
|
+
|
|
243
|
+
await _run_worker_async(
|
|
244
|
+
worker_class=MyTestWorker,
|
|
245
|
+
worker_id="test-w1",
|
|
246
|
+
redis_host=None,
|
|
247
|
+
redis_port=None,
|
|
248
|
+
redis_db=None,
|
|
249
|
+
redis_password=None,
|
|
250
|
+
redis_username=None,
|
|
251
|
+
workspace_dir="/tmp/test-ws",
|
|
252
|
+
consumer_group="test-group",
|
|
253
|
+
max_concurrency=10,
|
|
254
|
+
fetch_count=5,
|
|
255
|
+
redis_cluster_nodes=[("h1", 6379), ("h2", 6380)],
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
_, kwargs = mock_init_redis.call_args
|
|
259
|
+
assert kwargs["config"].mode == "cluster"
|
|
260
|
+
assert kwargs["config"].cluster_nodes == [("h1", 6379), ("h2", 6380)]
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@pytest.mark.asyncio
|
|
264
|
+
async def test_run_worker_async_explicit_standalone_mode_overrides_cluster_nodes():
|
|
265
|
+
"""An explicitly-passed redis_mode still wins over the redis_cluster_nodes
|
|
266
|
+
inference, for callers that need to force standalone regardless."""
|
|
267
|
+
with (
|
|
268
|
+
patch("by_framework.worker.app.init_redis") as mock_init_redis,
|
|
269
|
+
patch("by_framework.worker.app.close_redis", new_callable=AsyncMock),
|
|
270
|
+
patch("by_framework.worker.app.WorkerRegistry"),
|
|
271
|
+
patch("by_framework.worker.app.WorkspaceManager"),
|
|
272
|
+
patch("by_framework.worker.app.WorkerRunner") as mock_runner,
|
|
273
|
+
):
|
|
274
|
+
mock_init_redis.return_value = MagicMock()
|
|
275
|
+
mock_runner.return_value.start = AsyncMock()
|
|
276
|
+
|
|
277
|
+
await _run_worker_async(
|
|
278
|
+
worker_class=MyTestWorker,
|
|
279
|
+
worker_id="test-w1",
|
|
280
|
+
redis_host=None,
|
|
281
|
+
redis_port=None,
|
|
282
|
+
redis_db=None,
|
|
283
|
+
redis_password=None,
|
|
284
|
+
redis_username=None,
|
|
285
|
+
workspace_dir="/tmp/test-ws",
|
|
286
|
+
consumer_group="test-group",
|
|
287
|
+
max_concurrency=10,
|
|
288
|
+
fetch_count=5,
|
|
289
|
+
redis_mode="standalone",
|
|
290
|
+
redis_cluster_nodes=[("h1", 6379)],
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
_, kwargs = mock_init_redis.call_args
|
|
294
|
+
assert kwargs["config"].mode == "standalone"
|
|
295
|
+
|
|
296
|
+
|
|
228
297
|
@pytest.mark.asyncio
|
|
229
298
|
async def test_run_worker_async_initializes_cluster_client_when_mode_is_cluster():
|
|
230
299
|
"""REDIS_MODE=cluster must route init_redis through config=, not the
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/.github/ISSUE_TEMPLATE/feature_request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/by-framework-trace-change-usage.html
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/by-framework-trace-complete-guide.html
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/docs/plans/2026-05-15-worker-task-state-stats.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-adk/tests/test_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/frontend/index.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-dashboard/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/README.md
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-byclaw/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-history-postgres/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/tests/test_tools.py
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-langgraph/tests/test_utils.py
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/README.md
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-langfuse/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/README.md
RENAMED
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-phoenix/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/libs/by-framework-trace-query/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev9}/src/by_framework/admin/worker_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|