by-framework 0.2.2.dev8__tar.gz → 0.2.2.dev10__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.dev10}/PKG-INFO +1 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/pyproject.toml +1 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/__init__.py +2 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/admin/cli.py +3 -2
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/client/client.py +124 -3
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/config.py +10 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/constants.py +13 -3
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/emitter.py +16 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/__init__.py +2 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/__init__.py +2 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/content_type.py +1 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/responses.py +11 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/registry.py +2 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/app.py +29 -11
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/runner.py +10 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/client/test_client.py +345 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/common/test_config.py +85 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/common/test_constants.py +27 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/common/test_redis_client.py +1 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/test_registry.py +32 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_app.py +69 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_emitter.py +41 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_runner.py +76 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/uv.lock +1 -1
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.dockerignore +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/RELEASING.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/workflows/ci.yml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/workflows/publish.yml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.github/workflows/stale.yml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.gitignore +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/.pre-commit-config.yaml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/AGENTS.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/CHANGELOG.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/CLAUDE.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/CODE_OF_CONDUCT.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/CONTRIBUTING.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/LICENSE +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/Makefile +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/README_zh.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/SECURITY.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/assets/img/architecture_en.png +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/assets/img/architecture_zh.png +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/autoformat.sh +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/docs/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/docs/by-framework-trace-change-usage.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/docs/by-framework-trace-complete-guide.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/docs/plans/2026-05-15-worker-task-state-stats.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/docs/plans/2026-06-10-trace-metrics-correlation.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/docs/worker_management.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/src/by_framework_adk/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/src/by_framework_adk/_utils.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/src/by_framework_adk/adapter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/src/by_framework_adk/worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-adk/tests/test_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/Dockerfile +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/frontend/index.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/frontend/package-lock.json +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/frontend/package.json +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/frontend/src/main.jsx +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/frontend/src/styles.css +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/frontend/vite.config.js +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/adapters.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/dashboard.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/static/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/static/app.js +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/static/index.html +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/src/by_framework_dashboard/static/styles.css +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-dashboard/tests/test_dashboard_server.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-history-byclaw/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-history-byclaw/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/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.dev10}/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.dev10}/libs/by-framework-history-byclaw/tests/test_byclaw_history.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-history-postgres/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-history-postgres/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/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.dev10}/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.dev10}/libs/by-framework-history-postgres/tests/test_postgres_history_storage.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/src/by_framework_langgraph/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/src/by_framework_langgraph/_utils.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/src/by_framework_langgraph/adapter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/src/by_framework_langgraph/tools.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/src/by_framework_langgraph/worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/tests/test_adapter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/tests/test_tools.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-langgraph/tests/test_utils.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-trace-langfuse/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-trace-langfuse/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/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.dev10}/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.dev10}/libs/by-framework-trace-langfuse/tests/test_langfuse_import.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-trace-phoenix/README.md +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-trace-phoenix/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/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.dev10}/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.dev10}/libs/by-framework-trace-phoenix/tests/test_phoenix_import.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-trace-phoenix/tests/test_phoenix_plugin.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/libs/by-framework-trace-query/pyproject.toml +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/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.dev10}/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.dev10}/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.dev10}/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.dev10}/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.dev10}/libs/by-framework-trace-query/tests/test_trace_query_sdk.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/pylintrc +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/scripts/python_quality.sh +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/__main__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/admin/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/admin/worker_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/client/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/client/byai_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/exceptions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/logger.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/common/redis_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/availability.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/delivery_gate.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/discovery.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/extensions/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/extensions/agent_config.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/extensions/agent_config_audit.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/extensions/plugin.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/extensions/registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/extensions/trace_provider.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/action_type.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/agent_state.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/byai_codec.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/byai_command.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/byai_types.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/commands.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/content_codec.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/data_message.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/data_shapes.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/event_type.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/events.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/message.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/message_header.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/results.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/agent_config_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/agent_runtime_state.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/file_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/file_paths.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/file_permissions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/filestore/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/filestore/base.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/filestore/local.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/history/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/history/base.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/history/history_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/history/in_memory.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/runtime/session_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/wakeup_controller.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/workspace.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/base.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/common.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/execution.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/http.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/protocol.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/errors/registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/metrics/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/metrics/catalog.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/metrics/collector.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/metrics/read_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/metrics/snapshot.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/trace/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/trace/external_trace.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/trace/span_recorder.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/trace/trace_schema.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/trace/trace_writer.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/util/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/util/discovery_http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/util/generate_message_id.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/util/http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/_control_handling.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/_execution_tracking.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/_message_processing.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/byai_context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/byai_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/heartbeat.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/processor.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/sandbox/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/sandbox/hook_sandbox.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/worker/worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/admin/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/admin/test_cli.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/client/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/common/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/common/test_exceptions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/common/test_logger.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/conftest.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/protocol/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/protocol/test_byai_codec.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/protocol/test_command_wire.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/protocol/test_protocol.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/protocol/test_results.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/history/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/history/test_history_persistence.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_file_access_context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_file_manager_default_storage.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_file_paths.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_file_permissions.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_filestore_local_collection.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_filestore_local_mutation.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_filestore_local_read.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/runtime/test_filestore_local_search.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/test_agent_config_audit.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/test_availability.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/test_discovery.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/core/test_worker_manager.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/integration/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/integration/test_ask_user_flow.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/integration/test_callback_flow.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/integration/test_logger_integration.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/integration/test_scatter_gather.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/metrics/test_catalog.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/metrics/test_collector.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/metrics/test_metrics.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/metrics/test_read_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/metrics/test_snapshot.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/plugin/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/plugin/test_langfuse_plugin.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/plugin/test_plugin_discovery.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/plugin/test_plugin_improvements.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/plugin/test_plugin_registry.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/plugin/test_plugin_system.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/trace/test_external_trace.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/trace/test_logger_correlation.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/trace/test_otel_exporter.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/trace/test_span_recorder.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/trace/test_trace_writer.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/util/test_discovery_http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/util/test_discovery_http_client_download.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/util/test_discovery_http_client_upload.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/util/test_http_client.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/__init__.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_admin_control_handling.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_byai_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_context.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_control_handling.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_fetch_messages.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_gateway_worker.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_heartbeat.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_message_processing.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_processor.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_sandbox.py +0 -0
- {by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/tests/worker/test_workspace.py +0 -0
|
@@ -8,6 +8,7 @@ from `GatewayWorker` and running `run_worker`.
|
|
|
8
8
|
from .admin import WorkerManager
|
|
9
9
|
from .client.byai_client import ByaiGatewayClient
|
|
10
10
|
from .client.client import (
|
|
11
|
+
CancelSessionResponse,
|
|
11
12
|
CancelTaskResponse,
|
|
12
13
|
DataStreamEntry,
|
|
13
14
|
GatewayClient,
|
|
@@ -148,6 +149,7 @@ __all__ = [
|
|
|
148
149
|
"DataStreamEntry",
|
|
149
150
|
"SendMessageResponse",
|
|
150
151
|
"CancelTaskResponse",
|
|
152
|
+
"CancelSessionResponse",
|
|
151
153
|
"run_worker",
|
|
152
154
|
"logger",
|
|
153
155
|
"setup_logging",
|
|
@@ -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)
|
|
@@ -37,6 +37,7 @@ from by_framework.core.protocol.commands import (
|
|
|
37
37
|
from by_framework.core.protocol.data_message import DataMessage
|
|
38
38
|
from by_framework.core.protocol.message_header import MessageHeader
|
|
39
39
|
from by_framework.core.protocol.responses import (
|
|
40
|
+
CancelSessionResponse,
|
|
40
41
|
CancelTaskResponse,
|
|
41
42
|
ExecutionStatus,
|
|
42
43
|
SendMessageResponse,
|
|
@@ -581,6 +582,99 @@ class GatewayClient:
|
|
|
581
582
|
cancelled_count=len(to_cancel),
|
|
582
583
|
)
|
|
583
584
|
|
|
585
|
+
async def cancel_session(
|
|
586
|
+
self,
|
|
587
|
+
session_id: str,
|
|
588
|
+
reason: str = "",
|
|
589
|
+
requested_by: str = "client",
|
|
590
|
+
cancel_mode: str = CancelMode.GRACEFUL,
|
|
591
|
+
) -> CancelSessionResponse:
|
|
592
|
+
"""Cancel every active execution registered under a session.
|
|
593
|
+
|
|
594
|
+
Unlike cancel_task, this does not require a starting message_id:
|
|
595
|
+
it cancels the whole session's active executions in one call.
|
|
596
|
+
"""
|
|
597
|
+
if self.registry is None:
|
|
598
|
+
raise ValueError("GatewayClient requires a WorkerRegistry to cancel tasks")
|
|
599
|
+
|
|
600
|
+
all_executions = await self.registry.get_all_session_executions(session_id)
|
|
601
|
+
|
|
602
|
+
if not all_executions:
|
|
603
|
+
return CancelSessionResponse(
|
|
604
|
+
success=False,
|
|
605
|
+
session_id=session_id,
|
|
606
|
+
status=ExecutionStatus.NOT_FOUND,
|
|
607
|
+
timestamp=int(time.time() * 1000),
|
|
608
|
+
cancelled_count=0,
|
|
609
|
+
already_finished_count=0,
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
terminal_states = {"COMPLETED", "FAILED", "CANCELLED"}
|
|
613
|
+
to_cancel = [
|
|
614
|
+
node
|
|
615
|
+
for node in all_executions
|
|
616
|
+
if node.get("status", "") not in terminal_states
|
|
617
|
+
]
|
|
618
|
+
terminal_nodes = [
|
|
619
|
+
node for node in all_executions if node.get("status", "") in terminal_states
|
|
620
|
+
]
|
|
621
|
+
|
|
622
|
+
# Flag terminal executions so a still-running descendant can't wake
|
|
623
|
+
# them back up via callback, without changing their status.
|
|
624
|
+
for node in terminal_nodes:
|
|
625
|
+
await self.registry.mark_cancel_requested(
|
|
626
|
+
node.get("execution_id", ""), session_id, reason
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
if not to_cancel:
|
|
630
|
+
return CancelSessionResponse(
|
|
631
|
+
success=False,
|
|
632
|
+
session_id=session_id,
|
|
633
|
+
status=ExecutionStatus.ALREADY_FINISHED,
|
|
634
|
+
timestamp=int(time.time() * 1000),
|
|
635
|
+
cancelled_count=0,
|
|
636
|
+
already_finished_count=len(terminal_nodes),
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
for node in to_cancel:
|
|
640
|
+
node_execution_id = node.get("execution_id", "")
|
|
641
|
+
node_worker_id = node.get("worker_id", "")
|
|
642
|
+
node_message_id = node.get("message_id", "")
|
|
643
|
+
|
|
644
|
+
await self.registry.mark_execution_cancelling(
|
|
645
|
+
node_execution_id, session_id, reason
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
if node_worker_id:
|
|
649
|
+
cancel_command = CancelTaskCommand(
|
|
650
|
+
header=MessageHeader(
|
|
651
|
+
message_id=f"{CANCEL_MESSAGE_ID_PREFIX}{uuid.uuid4().hex[:8]}",
|
|
652
|
+
session_id=session_id,
|
|
653
|
+
trace_id=node.get("trace_id") or uuid.uuid4().hex,
|
|
654
|
+
target_agent_type=node.get("target_agent_type", ""),
|
|
655
|
+
parent_message_id=node_message_id,
|
|
656
|
+
),
|
|
657
|
+
target_message_id=node_message_id,
|
|
658
|
+
target_execution_id=node_execution_id,
|
|
659
|
+
target_worker_id=node_worker_id,
|
|
660
|
+
reason=reason,
|
|
661
|
+
requested_by=requested_by,
|
|
662
|
+
cancel_mode=cancel_mode,
|
|
663
|
+
)
|
|
664
|
+
await self.redis.xadd(
|
|
665
|
+
RedisKeys.worker_ctrl_stream(node_worker_id),
|
|
666
|
+
cancel_command.to_redis_payload(),
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
return CancelSessionResponse(
|
|
670
|
+
success=True,
|
|
671
|
+
session_id=session_id,
|
|
672
|
+
status=ExecutionStatus.CANCEL_REQUESTED,
|
|
673
|
+
timestamp=int(time.time() * 1000),
|
|
674
|
+
cancelled_count=len(to_cancel),
|
|
675
|
+
already_finished_count=len(terminal_nodes),
|
|
676
|
+
)
|
|
677
|
+
|
|
584
678
|
async def send_message(
|
|
585
679
|
self,
|
|
586
680
|
target_agent_type: str,
|
|
@@ -691,7 +785,28 @@ class GatewayClient:
|
|
|
691
785
|
content=params["content"],
|
|
692
786
|
extra_payload=params["extra_payload"],
|
|
693
787
|
)
|
|
694
|
-
|
|
788
|
+
|
|
789
|
+
# A RESUME reuses the message_id of the original AskAgentCommand so the
|
|
790
|
+
# worker can look the suspended execution back up. Reuse its
|
|
791
|
+
# execution_id too, and skip re-initializing the registry record for
|
|
792
|
+
# it below -- initialize_execution() would otherwise overwrite the
|
|
793
|
+
# message_id -> execution_id mapping and detach this resume from the
|
|
794
|
+
# execution it's meant to continue.
|
|
795
|
+
resumed_execution = None
|
|
796
|
+
if (
|
|
797
|
+
params["action_type"] == ActionType.RESUME.value
|
|
798
|
+
and self.registry
|
|
799
|
+
and hasattr(self.registry, "get_execution_by_message_id")
|
|
800
|
+
):
|
|
801
|
+
resumed_execution = await self.registry.get_execution_by_message_id(
|
|
802
|
+
message_id, session_id=params["session_id"]
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
execution_id = (
|
|
806
|
+
resumed_execution["execution_id"]
|
|
807
|
+
if resumed_execution
|
|
808
|
+
else f"{EXECUTION_ID_PREFIX}{uuid.uuid4().hex[:8]}"
|
|
809
|
+
)
|
|
695
810
|
|
|
696
811
|
# 3. Resolve route and optionally probe agent type/liveness
|
|
697
812
|
should_dispatch_control = True
|
|
@@ -837,8 +952,14 @@ class GatewayClient:
|
|
|
837
952
|
error_code=ExecutionStatus.ERR_AGENT_TYPE_UNAVAILABLE,
|
|
838
953
|
)
|
|
839
954
|
|
|
840
|
-
# Initialize execution tracking
|
|
841
|
-
|
|
955
|
+
# Initialize execution tracking. Skipped for a RESUME that reattached
|
|
956
|
+
# to an existing execution -- that execution is already tracked, and
|
|
957
|
+
# re-initializing it here would overwrite its message_id mapping.
|
|
958
|
+
if (
|
|
959
|
+
not resumed_execution
|
|
960
|
+
and self.registry
|
|
961
|
+
and hasattr(self.registry, "initialize_execution")
|
|
962
|
+
):
|
|
842
963
|
try:
|
|
843
964
|
await self.registry.initialize_execution(
|
|
844
965
|
{
|
|
@@ -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')"
|
|
@@ -107,6 +107,22 @@ class DefaultSseLayoutBuilder(DataLayoutBuilder):
|
|
|
107
107
|
parent_order_id: Optional[str] = None,
|
|
108
108
|
) -> Dict[str, Any]:
|
|
109
109
|
"""Build default BaiYing-compatible user input form payload."""
|
|
110
|
+
try:
|
|
111
|
+
parsed_prompt = json.loads(prompt)
|
|
112
|
+
except (json.JSONDecodeError, TypeError):
|
|
113
|
+
parsed_prompt = None
|
|
114
|
+
|
|
115
|
+
# Structured question prompts are already in the format expected by clients.
|
|
116
|
+
if isinstance(parsed_prompt, dict) and "questions" in parsed_prompt:
|
|
117
|
+
return self.build(
|
|
118
|
+
content=prompt,
|
|
119
|
+
role="assistant",
|
|
120
|
+
content_type=SseReasonMessageType.ask_user_question.value,
|
|
121
|
+
source_agent_type=source_agent_type,
|
|
122
|
+
order_id=order_id,
|
|
123
|
+
parent_order_id=parent_order_id,
|
|
124
|
+
)
|
|
125
|
+
|
|
110
126
|
input_form = {
|
|
111
127
|
"formStatus": 0,
|
|
112
128
|
"pluginMachineFields": [
|
|
@@ -26,6 +26,7 @@ from .protocol import (
|
|
|
26
26
|
BaiYingMessage,
|
|
27
27
|
BaiYingMessageRole,
|
|
28
28
|
BaseCommand,
|
|
29
|
+
CancelSessionResponse,
|
|
29
30
|
CancelTaskCommand,
|
|
30
31
|
CancelTaskResponse,
|
|
31
32
|
DataMessage,
|
|
@@ -53,6 +54,7 @@ from .workspace import WorkspaceManager
|
|
|
53
54
|
__all__ = [
|
|
54
55
|
"SendMessageResponse",
|
|
55
56
|
"CancelTaskResponse",
|
|
57
|
+
"CancelSessionResponse",
|
|
56
58
|
"BaiYingMessage",
|
|
57
59
|
"BaiYingMessageRole",
|
|
58
60
|
"MessageContent",
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/__init__.py
RENAMED
|
@@ -65,6 +65,7 @@ from .message import (
|
|
|
65
65
|
)
|
|
66
66
|
from .message_header import MessageHeader
|
|
67
67
|
from .responses import (
|
|
68
|
+
CancelSessionResponse,
|
|
68
69
|
CancelTaskResponse,
|
|
69
70
|
CancelTaskResponseDict,
|
|
70
71
|
SendMessageResponse,
|
|
@@ -81,6 +82,7 @@ from .results import (
|
|
|
81
82
|
__all__ = [
|
|
82
83
|
"SendMessageResponse",
|
|
83
84
|
"CancelTaskResponse",
|
|
85
|
+
"CancelSessionResponse",
|
|
84
86
|
"SendMessageResponseDict",
|
|
85
87
|
"CancelTaskResponseDict",
|
|
86
88
|
"AgentTaskResult",
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/content_type.py
RENAMED
|
@@ -33,6 +33,7 @@ class SseReasonMessageType(str, Enum):
|
|
|
33
33
|
think_code_result = "3007" # thinking process code execution result
|
|
34
34
|
task_finished = "3009" # task finished
|
|
35
35
|
task_user_input = "3013" # user input
|
|
36
|
+
ask_user_question = "3014" # ask user question
|
|
36
37
|
task_create_file = "3010" # create file
|
|
37
38
|
task_title = "3011" # task title
|
|
38
39
|
agent_card = "2015" # agent card
|
{by_framework-0.2.2.dev8 → by_framework-0.2.2.dev10}/src/by_framework/core/protocol/responses.py
RENAMED
|
@@ -92,3 +92,14 @@ class CancelTaskResponse:
|
|
|
92
92
|
timestamp: int
|
|
93
93
|
error: str = ""
|
|
94
94
|
cancelled_count: int = 0
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass(frozen=True)
|
|
98
|
+
class CancelSessionResponse:
|
|
99
|
+
success: bool
|
|
100
|
+
session_id: str
|
|
101
|
+
status: str
|
|
102
|
+
timestamp: int
|
|
103
|
+
cancelled_count: int = 0
|
|
104
|
+
already_finished_count: int = 0
|
|
105
|
+
error: str = ""
|
|
@@ -1011,7 +1011,8 @@ class WorkerRegistry:
|
|
|
1011
1011
|
old_execution = dict(current)
|
|
1012
1012
|
current["status"] = status
|
|
1013
1013
|
now = int(time.time() * 1000)
|
|
1014
|
-
|
|
1014
|
+
if is_terminal_state(status):
|
|
1015
|
+
current["finished_at"] = now
|
|
1015
1016
|
current["updated_at"] = now
|
|
1016
1017
|
if completion:
|
|
1017
1018
|
for key, value in completion.items():
|
|
@@ -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
|
|
@@ -505,6 +505,16 @@ class WorkerRunner:
|
|
|
505
505
|
header.message_id, session_id=header.session_id
|
|
506
506
|
)
|
|
507
507
|
|
|
508
|
+
if isinstance(command, ResumeCommand) and existing_execution is None:
|
|
509
|
+
logger.warning(
|
|
510
|
+
"[%s] ResumeCommand did not resolve to an existing execution "
|
|
511
|
+
"(message_id=%s, session_id=%s); starting a new, disconnected "
|
|
512
|
+
"execution instead of continuing the suspended one.",
|
|
513
|
+
self.worker.worker_id,
|
|
514
|
+
header.message_id,
|
|
515
|
+
header.session_id,
|
|
516
|
+
)
|
|
517
|
+
|
|
508
518
|
# Skip terminal state replays
|
|
509
519
|
if (
|
|
510
520
|
existing_execution
|