by-framework 0.2.2.dev13__tar.gz → 0.2.2.dev15__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.dev15/CHANGELOG.md +30 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/CLAUDE.md +17 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/Makefile +28 -5
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/PKG-INFO +1 -1
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/KEY_FILES.md +68 -4
- by_framework-0.2.2.dev15/docs/architecture/langfuse-tracing-memory.md +130 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/src/by_framework_trace_langfuse/langfuse.py +387 -80
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/pyproject.toml +1 -1
- by_framework-0.2.2.dev15/scripts/check-metric-catalog.sh +65 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/verify.sh +1 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/client/client.py +6 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/catalog.py +54 -0
- by_framework-0.2.2.dev15/src/by_framework/worker/_resume_metadata.py +65 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/processor.py +89 -22
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/runner.py +29 -1
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/worker.py +43 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/client/test_client.py +29 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_nested_chain.py +148 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_catalog.py +14 -2
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_langfuse_plugin.py +358 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_gateway_worker.py +182 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_processor.py +220 -0
- by_framework-0.2.2.dev15/tests/worker/test_resume_metadata.py +69 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_runner.py +52 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/uv.lock +1 -1
- by_framework-0.2.2.dev13/CHANGELOG.md +0 -16
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.codex/hooks.json +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.dockerignore +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/RELEASING.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/ci.yml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/deploy-smoke-test.yml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/publish.yml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/stale.yml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/verify.yml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.gitignore +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.pre-commit-config.yaml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/AGENTS.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/CODE_OF_CONDUCT.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/CONTRIBUTING.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/LICENSE +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/README_zh.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/SECURITY.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/assets/img/architecture_en.png +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/assets/img/architecture_zh.png +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/autoformat.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/Dockerfile +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/docker-compose.yml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/entrypoint.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/kubernetes/worker-deployment.yaml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/GUARD_AUTHORING.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/production-deployment.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/redis-cluster-mode.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/suspend-resume-liveness.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/worker-readiness-endpoint.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/by-framework-trace-change-usage.html +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/by-framework-trace-complete-guide.html +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/plans/2026-05-15-worker-task-state-stats.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/plans/2026-06-10-trace-metrics-correlation.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/worker_management.html +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/examples/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/examples/echo_worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/examples/send_and_verify.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/_utils.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/adapter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/tests/test_adapter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/tests/test_worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/01_basic_chat.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/02_tools_and_ask_user.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/03_agent_delegation.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/04_task_group.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/05_real_model_react.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/_infra.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/litellm_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/loop.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/model_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/testing.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/tool_spec.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/conftest.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_agent_as_tool.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_ask_user_suspend_resume.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_cancel_cleanup.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_native_agent_worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_task_group_batching.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_tool_calling_loop.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/Dockerfile +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/index.html +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/package-lock.json +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/package.json +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/src/main.jsx +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/src/styles.css +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/vite.config.js +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/adapters.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/dashboard.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/static/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/static/app.js +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/static/index.html +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/static/styles.css +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/tests/test_dashboard_server.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/src/by_framework_history_byclaw/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/src/by_framework_history_byclaw/byclaw_history.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/tests/test_byclaw_history.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/src/by_framework_history_postgres/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/src/by_framework_history_postgres/postgres.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/tests/test_postgres_history_storage.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/_utils.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/adapter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/tools.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/tests/test_adapter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/tests/test_tools.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/tests/test_utils.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/src/by_framework_trace_langfuse/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/tests/test_langfuse_import.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/README.md +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/src/by_framework_trace_phoenix/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/src/by_framework_trace_phoenix/phoenix.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/tests/test_phoenix_import.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/tests/test_phoenix_plugin.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/pyproject.toml +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/src/by_framework_trace_query/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/src/by_framework_trace_query/client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/src/by_framework_trace_query/merger.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/src/by_framework_trace_query/models.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/src/by_framework_trace_query/redis_source.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/tests/test_trace_query_sdk.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/pylintrc +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/.map.conf +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/check-doc-discipline.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/check-entry-freshness.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/check-map-territory.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/map-stop-hook.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/python_quality.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/test-growth-ladder.sh +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/__main__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/admin/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/admin/cli.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/admin/worker_manager.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/client/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/client/byai_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/config.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/constants.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/emitter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/exceptions.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/logger.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/redis_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/availability.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/delivery_gate.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/discovery.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/agent_config.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/agent_config_audit.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/plugin.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/registry.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/trace_provider.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/action_type.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/agent_state.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/byai_codec.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/byai_command.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/byai_types.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/commands.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/content_codec.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/content_type.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/data_message.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/data_shapes.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/event_type.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/events.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/message.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/message_header.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/responses.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/results.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/registry.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/agent_config_manager.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/agent_runtime_state.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/file_manager.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/file_paths.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/file_permissions.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/filestore/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/filestore/base.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/filestore/local.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/base.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/history_manager.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/in_memory.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/session_manager.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_gate.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_index.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_reply.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_sweeper.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wakeup_controller.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/workspace.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/base.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/common.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/execution.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/http.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/protocol.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/registry.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/collector.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/read_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/snapshot.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/external_trace.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/span_recorder.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/trace_schema.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/trace_writer.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/discovery_http_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/generate_message_id.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/http_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/_control_handling.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/_execution_tracking.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/_message_processing.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/app.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/byai_context.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/byai_worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/context.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/health_server.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/heartbeat.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/sandbox/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/sandbox/hook_sandbox.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/admin/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/admin/test_cli.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/client/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_config.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_constants.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_exceptions.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_logger.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_redis_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/conftest.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_byai_codec.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_command_wire.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_protocol.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_results.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/history/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/history/test_history_persistence.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_access_context.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_manager_default_storage.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_paths.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_permissions.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_collection.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_mutation.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_read.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_search.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_agent_config_audit.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_availability.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_discovery.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_registry.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_wait_gate.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_wait_index.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_wait_sweeper.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_worker_manager.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_ask_user_flow.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_callback_flow.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_logger_integration.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_orphan_recovery.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_scatter_gather.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_collector.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_metrics.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_read_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_snapshot.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_discovery.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_improvements.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_registry.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_system.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/test_main.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_external_trace.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_logger_correlation.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_otel_exporter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_span_recorder.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_trace_writer.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_discovery_http_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_discovery_http_client_download.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_discovery_http_client_upload.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_http_client.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/__init__.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_admin_control_handling.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_app.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_byai_worker.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_context.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_control_handling.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_emitter.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_fetch_messages.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_health_server.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_heartbeat.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_message_processing.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_sandbox.py +0 -0
- {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_workspace.py +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- A resumed agent can read its own request metadata again. Previously,
|
|
12
|
+
`command.header.metadata` after a suspend (`ask_user`, or a `call_agent`
|
|
13
|
+
hop) held only the metadata of the message that woke the agent up, and
|
|
14
|
+
everything it had originally been dispatched with was gone. It is now the
|
|
15
|
+
original dispatch metadata with the waking message's merged on top (the
|
|
16
|
+
waking message wins on key collisions). Handlers that treated the resumed
|
|
17
|
+
header's metadata as "only what this hop just sent" will now see additional
|
|
18
|
+
keys. Per-hop trace fields (`trace_parent_span_id`,
|
|
19
|
+
`framework_parent_span_id`, `langfuse_parent_observation_id`) still
|
|
20
|
+
describe the current hop and are not restored from the record. Executions
|
|
21
|
+
recorded before this change are unaffected — they degrade to the previous
|
|
22
|
+
behaviour rather than erroring.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Standardized Open Source governance files (CONTRIBUTING, CODE_OF_CONDUCT, SECURITY).
|
|
26
|
+
- GitHub Issue and Pull Request templates.
|
|
27
|
+
- Dependabot configuration for dependency monitoring.
|
|
28
|
+
|
|
29
|
+
## [0.2.0] - 2026-05-13
|
|
30
|
+
### Initial release
|
|
@@ -151,6 +151,22 @@ Pre-commit hooks are configured in `.pre-commit-config.yaml` and run isort, ruff
|
|
|
151
151
|
plugin/trace integration point must degrade to a no-op (logged) rather
|
|
152
152
|
than raising.
|
|
153
153
|
|
|
154
|
+
- **A rule enforced only behind an optional dependency is not enforced.** If
|
|
155
|
+
the check short-circuits when a package is missing, then whatever controls
|
|
156
|
+
the environment controls the rule — and a green run stops meaning anything.
|
|
157
|
+
Incident: `tests/metrics/test_catalog.py` asserts every exported metric has a
|
|
158
|
+
`metrics/catalog.py` entry, but returned early when `prometheus-client` was
|
|
159
|
+
absent, while `make test` synced with `--extra dev` and dropped the root
|
|
160
|
+
`observability` extra. The assertion ran against an empty registry and
|
|
161
|
+
reported success for months; four uncatalogued metrics landed on main with CI
|
|
162
|
+
green (#142, then the CI fix). Correct form: enforce the rule where the
|
|
163
|
+
optional dependency cannot reach it — here `scripts/check-metric-catalog.sh`
|
|
164
|
+
reads the source, so **every new Prometheus `Counter`/`Gauge`/`Histogram` in
|
|
165
|
+
`src/` needs a `catalog.py` entry** regardless of what is installed — and
|
|
166
|
+
make the dependent test `pytest.skip()` rather than `return`, so degrading is
|
|
167
|
+
at least visible. Test commands must sync the extras the tests exercise
|
|
168
|
+
(`make test` uses `--all-extras`); narrowing them silently deletes coverage.
|
|
169
|
+
|
|
154
170
|
## Iron rules
|
|
155
171
|
|
|
156
172
|
<!-- No process rules (test invocation, release steps) have caused an
|
|
@@ -166,6 +182,7 @@ Pre-commit hooks are configured in `.pre-commit-config.yaml` and run isort, ruff
|
|
|
166
182
|
| Worker deployment/production-readiness — README's 部署 section, `__main__.py` CLI flags, `run_worker()`'s signature, or shutdown/signal handling | `docs/architecture/production-deployment.md` |
|
|
167
183
|
| Worker readiness/health-check endpoint (`WorkerHealthServer`, `/readyz`, `--health-port`) — building it, or touching anything that changes what "ready" means | `docs/architecture/worker-readiness-endpoint.md` |
|
|
168
184
|
| suspend/resume liveness — the wait index, its idempotency gate, or the sweep that resolves callers whose reply never arrives | `docs/architecture/suspend-resume-liveness.md` |
|
|
185
|
+
| Langfuse tracing state held in worker memory — `_active_workflows`, trace-output uploads, or anything that queues/retains per-task telemetry | `docs/architecture/langfuse-tracing-memory.md` |
|
|
169
186
|
|
|
170
187
|
## Maintaining this map
|
|
171
188
|
|
|
@@ -37,11 +37,22 @@ list-projects:
|
|
|
37
37
|
echo $$project; \
|
|
38
38
|
done
|
|
39
39
|
|
|
40
|
+
# All ten projects share the workspace venv, so syncing them in a loop makes
|
|
41
|
+
# each one PRUNE the previous one's dependencies — the loop used to end with a
|
|
42
|
+
# venv holding only the last project's deps (and it uninstalled prometheus-client
|
|
43
|
+
# on the second iteration). --all-packages resolves the whole workspace once
|
|
44
|
+
# instead. The loop survives only for an explicit PROJECTS override, where
|
|
45
|
+
# narrowing the venv is what the caller asked for.
|
|
40
46
|
install:
|
|
41
|
-
@
|
|
42
|
-
echo "==> Syncing
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
@if [ "$(strip $(PROJECTS))" = "$(strip $(PYTHON_PROJECTS))" ]; then \
|
|
48
|
+
echo "==> Syncing workspace (all packages, all extras)"; \
|
|
49
|
+
uv sync --all-extras --all-packages; \
|
|
50
|
+
else \
|
|
51
|
+
for project in $(PROJECTS); do \
|
|
52
|
+
echo "==> Syncing $$project (narrowed: PROJECTS override)"; \
|
|
53
|
+
(cd $$project && uv sync --all-extras); \
|
|
54
|
+
done; \
|
|
55
|
+
fi
|
|
45
56
|
|
|
46
57
|
format:
|
|
47
58
|
@PROJECTS="$(PROJECTS)" ./scripts/python_quality.sh format $(FILES)
|
|
@@ -80,6 +91,18 @@ lint-changed:
|
|
|
80
91
|
$(MAKE) lint PROJECTS="$(PROJECTS)" FILES="$$changed_files"; \
|
|
81
92
|
fi
|
|
82
93
|
|
|
94
|
+
# --all-extras, not --extra dev: `uv run` only ever adds what it is asked for,
|
|
95
|
+
# it never restores an extra it was not told about. So once `install`'s old
|
|
96
|
+
# per-project loop had uninstalled prometheus-client, `--extra dev` left it
|
|
97
|
+
# uninstalled and the root project's whole `observability` extra stayed missing
|
|
98
|
+
# for the entire test run. tests/metrics then ran against a build with no
|
|
99
|
+
# Prometheus registry, where the metric catalog check short-circuits and reports
|
|
100
|
+
# success without inspecting anything. State what the tests need, rather than
|
|
101
|
+
# inheriting whatever `install` happened to leave behind.
|
|
102
|
+
#
|
|
103
|
+
# Deliberately per-project rather than --all-packages: each project must be
|
|
104
|
+
# testable with only its own declared dependencies, or a package that quietly
|
|
105
|
+
# leans on a sibling's deps would still pass here and break on install.
|
|
83
106
|
test:
|
|
84
107
|
@set -e; for project in $(PROJECTS); do \
|
|
85
108
|
if ! find "$$project/tests" -type f \( -name 'test_*.py' -o -name '*_test.py' \) -print -quit 2>/dev/null | grep -q .; then \
|
|
@@ -87,7 +110,7 @@ test:
|
|
|
87
110
|
continue; \
|
|
88
111
|
fi; \
|
|
89
112
|
echo "==> Testing $$project"; \
|
|
90
|
-
(cd $$project && uv run --
|
|
113
|
+
(cd $$project && uv run --all-extras pytest); \
|
|
91
114
|
done
|
|
92
115
|
|
|
93
116
|
clean:
|
|
@@ -260,7 +260,13 @@ Entry anatomy:
|
|
|
260
260
|
implementations fall back to minting a fresh execution_id. Root-dispatch
|
|
261
261
|
trace writes (`_write_trace_root_start/_end`) must only fire when
|
|
262
262
|
`not parent_message_id` — firing them on every `call_agent` hop would
|
|
263
|
-
duplicate trace roots.
|
|
263
|
+
duplicate trace roots. `initialize_execution()`'s payload carries the
|
|
264
|
+
dispatch `metadata`: a root agent suspends (an `ask_user` round is the
|
|
265
|
+
common case) and comes back on a `ResumeCommand` carrying the *callee's*
|
|
266
|
+
metadata, so the record is the only place its own request metadata still
|
|
267
|
+
exists for `worker.py`'s inbound restore to find. `runner.py` records the
|
|
268
|
+
same field independently on first pickup, which is what makes this work
|
|
269
|
+
for dispatchers that don't write it (TS/Java callers, a bare `xadd`).
|
|
264
270
|
|
|
265
271
|
- `src/by_framework/worker/runner.py` — `WorkerRunner`, the consume loop:
|
|
266
272
|
`XREADGROUP` fetch, command dispatch, resume/suspend bookkeeping, denylist
|
|
@@ -290,7 +296,16 @@ Entry anatomy:
|
|
|
290
296
|
suspended caller persists as `WAITING_AGENT`/`WAITING_USER` precisely to
|
|
291
297
|
keep that inference true; reusing QUEUED for any post-pickup state silently
|
|
292
298
|
makes a resume re-derive its identity from the message header instead of
|
|
293
|
-
the record.
|
|
299
|
+
the record. On a **non-resume** pickup it also writes `header.metadata`
|
|
300
|
+
onto the record (as an `update_execution_status` kwarg, or in the
|
|
301
|
+
`save_execution` fallback payload): `header.metadata` *is* the dispatch
|
|
302
|
+
metadata by definition, so recording it here — rather than trusting
|
|
303
|
+
whoever sent the message to have done it — is what makes
|
|
304
|
+
`worker.py`'s inbound restore work for a client root dispatch and for a
|
|
305
|
+
TS/Java caller, neither of which writes the field. The `ResumeCommand`
|
|
306
|
+
guard is load-bearing: a resume writing its own waking metadata over the
|
|
307
|
+
record would destroy the stored original that the restore exists to
|
|
308
|
+
recover, and nothing else keeps a copy. Every `ResumeCommand` passes the `core/wait_gate.py`
|
|
294
309
|
idempotency gate *here*, before the execution lookup — and being upstream
|
|
295
310
|
of `GatewayWorker` is what also puts it before Task Group join, whose
|
|
296
311
|
`HINCRBY completed` a duplicate would push past `total` and aggregate a
|
|
@@ -353,6 +368,22 @@ Entry anatomy:
|
|
|
353
368
|
transient hop overwrite the caller's own data instead of being layered
|
|
354
369
|
under `task_result.metadata` like `_enqueue_agent_return()`'s merge
|
|
355
370
|
already does correctly.
|
|
371
|
+
That is the OUTBOUND direction. The INBOUND one — what this execution's own
|
|
372
|
+
handler reads — is `_restore_inbound_metadata()`, and it is deliberately a
|
|
373
|
+
different rule: the original dispatch metadata from the same snapshot is
|
|
374
|
+
the base and the waking message's metadata is **merged on top** (waking
|
|
375
|
+
message wins collisions), because this agent *is* the addressee of that
|
|
376
|
+
message. Without it, everything a handler was dispatched with disappears
|
|
377
|
+
the moment it first suspends. Two constraints keep the directions from
|
|
378
|
+
contaminating each other: the restore must build a NEW command
|
|
379
|
+
(`prepare_command_for_processing()` returns the *same* object for the base
|
|
380
|
+
worker, so an in-place header mutation would rewrite `raw_command`'s and
|
|
381
|
+
leak the merge into the reply), and `_resolve_reply_command()` must keep
|
|
382
|
+
taking `raw_command`. The shared merge rule, including which framework
|
|
383
|
+
trace keys are excluded from the restored base, lives in
|
|
384
|
+
`_resume_metadata.py` — one copy, because the last time these two files
|
|
385
|
+
each carried their own version of a resume rule the processor was left
|
|
386
|
+
behind for a whole commit.
|
|
356
387
|
The success path must NOT reply while `context._is_suspended` — a suspended
|
|
357
388
|
execution has no result, and forwarding the value the handler returned in
|
|
358
389
|
order to unwind both wakes the caller early and consumes the single reply it
|
|
@@ -431,8 +462,22 @@ Entry anatomy:
|
|
|
431
462
|
to no execution. `_resolve_reply_header()` must read a resumed execution's
|
|
432
463
|
caller from the execution record, not from the resume header (which names
|
|
433
464
|
the sub-agent), while excluding `CLIENT_SOURCE_AGENT_TYPE` for the reason
|
|
434
|
-
spelled out under `worker.py`;
|
|
435
|
-
`
|
|
465
|
+
spelled out under `worker.py`; it restores **four** fields from that record
|
|
466
|
+
— `source_agent_type`, `parent_message_id`, `task_group_id` and
|
|
467
|
+
`metadata` — the last one as a full replacement, never merged with the
|
|
468
|
+
waking message's own metadata, exactly as `worker.py`'s
|
|
469
|
+
`_resolve_reply_command()` does (restoring only the three routing fields is
|
|
470
|
+
the drift this entry warns about: it shipped that way and leaked the waking
|
|
471
|
+
hop's metadata to the caller); `_restore_inbound_metadata()` mirrors
|
|
472
|
+
`worker.py`'s inbound merge for what the *handler* reads, and must run even
|
|
473
|
+
when `_resolve_reply_header()` returned `None` — a client-dispatched root
|
|
474
|
+
is owed no reply but still has its own metadata to get back, so the two
|
|
475
|
+
must not share a short-circuit. `_load_execution_snapshot()` is the single
|
|
476
|
+
registry read feeding both directions; being fail-soft there is what keeps
|
|
477
|
+
a registry error a degrade rather than a lost reply. The reply is built
|
|
478
|
+
from `raw_command`, never the inbound-restored one. And no callback may be
|
|
479
|
+
sent while `context._is_suspended` (with the same terminal-status
|
|
480
|
+
exception).
|
|
436
481
|
Being a *second* entry point for replies, it carries the same
|
|
437
482
|
`core/wait_gate.py` gate as `runner.py` — a gate on one of two doors is not
|
|
438
483
|
a gate, and an ungated reply here would both wake a resolved caller and
|
|
@@ -441,6 +486,25 @@ Entry anatomy:
|
|
|
441
486
|
`call_agents`' queued stand-ins on the same terms as `worker.py` — after
|
|
442
487
|
the handler returns, never when it raised.
|
|
443
488
|
|
|
489
|
+
- `src/by_framework/worker/_resume_metadata.py` — the one copy of the
|
|
490
|
+
**inbound** resume-metadata rule, shared by `worker.py` and `processor.py`
|
|
491
|
+
so the two cannot drift again. `merge_resume_metadata()` puts the
|
|
492
|
+
execution's original dispatch metadata underneath the waking message's
|
|
493
|
+
(waking message wins collisions) — the opposite of the outbound
|
|
494
|
+
replacement, because a resumed handler *is* the addressee of the message
|
|
495
|
+
that woke it. `FRAMEWORK_HOP_METADATA_KEYS` (`trace_parent_span_id`,
|
|
496
|
+
`framework_parent_span_id`, `langfuse_parent_observation_id`) are dropped
|
|
497
|
+
from the restored base: the framework injects them per dispatch, so a
|
|
498
|
+
stored copy describes the hop that *created* the execution, and
|
|
499
|
+
`context.py`'s `_resolve_call_langfuse_parent_id()` reads that key straight
|
|
500
|
+
off the current command — restoring it would parent a post-resume call to
|
|
501
|
+
an observation from before the suspend. The filter belongs here, at read
|
|
502
|
+
time, and not at write time: the outbound path deliberately restores the
|
|
503
|
+
stored dict verbatim, trace keys included, to stay identical to the
|
|
504
|
+
non-suspended reply. A missing/absent stored value degrades to the waking
|
|
505
|
+
message's metadata unchanged, which is the pre-restore behaviour, so old
|
|
506
|
+
records and cross-SDK callers need no migration or version gate.
|
|
507
|
+
|
|
444
508
|
- `src/by_framework/core/registry.py` — `WorkerRegistry`: Redis-backed worker
|
|
445
509
|
membership/heartbeat/execution-state, admin lifecycle, locking primitives.
|
|
446
510
|
`mark_execution_finished()` must stamp `finished_at` only
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Langfuse tracing: what the worker holds, and for how long
|
|
2
|
+
|
|
3
|
+
## What this covers
|
|
4
|
+
|
|
5
|
+
`libs/by-framework-trace-langfuse` is the only plugin that keeps **live
|
|
6
|
+
per-task state in worker memory across hook calls**. Everything else in the
|
|
7
|
+
trace layer is either fire-and-forget (`RedisSpanExporter`) or bounded by the
|
|
8
|
+
SDK (`LangfuseSpanProcessor` wraps OTel's `BatchSpanProcessor`, whose queue
|
|
9
|
+
tops out at 2048 spans and drops the overflow).
|
|
10
|
+
|
|
11
|
+
This doc exists because three separate unbounded-growth bugs shipped in that
|
|
12
|
+
plugin and none of them were visible from reading a single function. They
|
|
13
|
+
shared one root cause, stated below, and the fixes are only correct as long
|
|
14
|
+
as that framing holds.
|
|
15
|
+
|
|
16
|
+
## The rule everything follows from
|
|
17
|
+
|
|
18
|
+
**Langfuse reporting is best-effort telemetry, not business data.** A slow or
|
|
19
|
+
unreachable Langfuse must cost trace fidelity — never worker memory, never
|
|
20
|
+
worker shutdown, never a shared executor.
|
|
21
|
+
|
|
22
|
+
Every degraded path therefore **sheds load**: drop the work, count it, log it
|
|
23
|
+
sparsely. The failure mode to avoid is the intuitive one — "queue it, we'll
|
|
24
|
+
send it when Langfuse recovers" — because a worker completing tasks faster
|
|
25
|
+
than Langfuse accepts them turns that queue into an OOM with the whole
|
|
26
|
+
serialized task output pinned in each entry.
|
|
27
|
+
|
|
28
|
+
This is a stricter rule than the repo-wide fail-soft invariant in `CLAUDE.md`.
|
|
29
|
+
Fail-soft says *don't raise into the task path*. This says *don't accumulate
|
|
30
|
+
in the task path either* — a plugin that swallows every exception can still
|
|
31
|
+
kill the worker by growing.
|
|
32
|
+
|
|
33
|
+
## The three things the plugin holds
|
|
34
|
+
|
|
35
|
+
### 1. `_active_workflows` — durable workflow spans
|
|
36
|
+
|
|
37
|
+
An `agent.workflow` observation spans the **logical** task, which outlives any
|
|
38
|
+
single worker execution: `ask_user` and `call_agent` suspend the execution and
|
|
39
|
+
a later `RESUME` reattaches to it (see `suspend-resume-liveness.md`). So the
|
|
40
|
+
handle cannot be closed when the first execution returns — it lives in an
|
|
41
|
+
`OrderedDict` keyed by `(session_id, message_id)` until the task reaches a
|
|
42
|
+
terminal status.
|
|
43
|
+
|
|
44
|
+
Three things can end an entry, and all three must exist:
|
|
45
|
+
|
|
46
|
+
| Exit | Trigger |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Normal | terminal `on_task_complete` / `on_task_error` / `on_task_cancel` |
|
|
49
|
+
| TTL | `_expire_active_workflows()`, for a suspend whose resume never came |
|
|
50
|
+
| LRU | `_evict_active_workflows_if_needed()`, at `max_active_workflows` |
|
|
51
|
+
|
|
52
|
+
**Invariant — LRU order equals expiry order.** `_expire_active_workflows()`
|
|
53
|
+
scans from the head and stops at the first live entry, which is only valid
|
|
54
|
+
because every write goes through `_track_active_workflow()`, which refreshes
|
|
55
|
+
`expires_at` *and* moves the entry to the tail. A future write that bypasses
|
|
56
|
+
that helper silently turns expiry into a no-op for everything behind it.
|
|
57
|
+
|
|
58
|
+
**Ownership is claimed at registration, not at the end of the hook.**
|
|
59
|
+
`on_task_start` registers the workflow and immediately sets
|
|
60
|
+
`LANGFUSE_WORKFLOW_OBSERVATION_ATTR` on the context, because the tracer calls
|
|
61
|
+
that follow it can raise — and `PluginRegistry._execute_hook()` swallows that.
|
|
62
|
+
`_end_workflow_observation()` additionally falls back to the
|
|
63
|
+
`(session_id, message_id)` key when the context attribute is missing. Both
|
|
64
|
+
halves are load-bearing: without the fallback, a mid-hook SDK error orphaned
|
|
65
|
+
100% of entries until LRU eviction, each one a live span that would never
|
|
66
|
+
export.
|
|
67
|
+
|
|
68
|
+
For the same reason `on_task_error` / `on_task_cancel` must **not** return
|
|
69
|
+
early when the context has no agent/worker observations. The workflow entry
|
|
70
|
+
can outlive them, and bailing is what stranded it.
|
|
71
|
+
|
|
72
|
+
### 2. `_pending_trace_output_updates` — in-flight trace-output uploads
|
|
73
|
+
|
|
74
|
+
`update_trace_output` is a *synchronous* HTTP POST — it patches the trace-list
|
|
75
|
+
`output` field, which the OTel span pipeline does not carry. It runs on the
|
|
76
|
+
plugin's **own** `ThreadPoolExecutor`, never the asyncio default executor:
|
|
77
|
+
that pool is shared with the rest of the framework's blocking calls, and a
|
|
78
|
+
stalled Langfuse would starve unrelated work.
|
|
79
|
+
|
|
80
|
+
The bound is enforced **before submitting**, not by trimming the tracking set.
|
|
81
|
+
Dropping only the future leaves the work item — and the payload it closes
|
|
82
|
+
over — sitting in the executor queue, which is exactly the growth being
|
|
83
|
+
guarded. At the limit the upload is discarded and counted.
|
|
84
|
+
|
|
85
|
+
`on_worker_shutdown` waits on the remainder with a deadline and abandons
|
|
86
|
+
whatever misses it. The discard callback catches `BaseException`, not
|
|
87
|
+
`Exception`: shutdown cancels the stragglers, and `CancelledError` is a
|
|
88
|
+
`BaseException`, so a narrower catch dumps one traceback per abandoned upload.
|
|
89
|
+
|
|
90
|
+
### 3. Serialized output
|
|
91
|
+
|
|
92
|
+
`_serialize_value` deep-copies the whole task result. The end-of-task path
|
|
93
|
+
serializes **once**, at the top of `on_task_complete`; `_end_observation`,
|
|
94
|
+
`_end_workflow_observation` and `_update_trace_output` all take an
|
|
95
|
+
already-serialized value and must not re-serialize it. Their docstrings state
|
|
96
|
+
this precondition — it is a contract, not an optimization, because copy #3 is
|
|
97
|
+
what an in-flight upload pins.
|
|
98
|
+
|
|
99
|
+
## Tunables
|
|
100
|
+
|
|
101
|
+
All have safe defaults; unset behaves no worse than the built-in values.
|
|
102
|
+
Explicit constructor kwargs always win over the environment, per `CLAUDE.md`'s
|
|
103
|
+
"explicitly-passed kwarg" invariant.
|
|
104
|
+
|
|
105
|
+
| Env | Default | What it bounds |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `BYAI_LANGFUSE_MAX_ACTIVE_WORKFLOWS` | 10000 | live workflow spans |
|
|
108
|
+
| `BYAI_LANGFUSE_WORKFLOW_TTL_SECONDS` | 3600 | how long a suspended workflow is held |
|
|
109
|
+
| `BYAI_LANGFUSE_MAX_PENDING_TRACE_OUTPUTS` | 128 | in-flight trace-output uploads |
|
|
110
|
+
| `BYAI_LANGFUSE_SHUTDOWN_FLUSH_TIMEOUT_SECONDS` | 5 | shutdown flush deadline |
|
|
111
|
+
|
|
112
|
+
## Accepted trade-off
|
|
113
|
+
|
|
114
|
+
A workflow reclaimed by TTL or LRU whose resume arrives later gets a *new*
|
|
115
|
+
observation built from the same deterministic span id
|
|
116
|
+
(`str_to_uint64(f"{execution_anchor}:agent.workflow")`), so Langfuse sees a
|
|
117
|
+
duplicate span id. This is pre-existing LRU behaviour, not new; the 1-hour
|
|
118
|
+
default TTL keeps it rare. Trace-output drops under load are likewise
|
|
119
|
+
deliberate — the trace and its observations still ship via the SDK's own
|
|
120
|
+
batch pipeline, so only the trace-list `output` preview is lost.
|
|
121
|
+
|
|
122
|
+
## One more thing that is not a leak
|
|
123
|
+
|
|
124
|
+
`build_langchain_callback` subclasses the Langfuse `CallbackHandler` to stop
|
|
125
|
+
LangChain runs being promoted to trace roots. That subclass is cached per base
|
|
126
|
+
class in a `WeakKeyDictionary`. Minting one per call was *not* a hard leak —
|
|
127
|
+
the classes are reclaimable — but it ran once per task, and type objects are
|
|
128
|
+
only collected by the generational GC while every creation invalidates
|
|
129
|
+
CPython's type method cache. Per-callback state lives on the instance
|
|
130
|
+
(`_by_framework_metadata`), so one shared subclass is safe.
|