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.
Files changed (326) hide show
  1. by_framework-0.2.2.dev15/CHANGELOG.md +30 -0
  2. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/CLAUDE.md +17 -0
  3. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/Makefile +28 -5
  4. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/PKG-INFO +1 -1
  5. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/KEY_FILES.md +68 -4
  6. by_framework-0.2.2.dev15/docs/architecture/langfuse-tracing-memory.md +130 -0
  7. {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
  8. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/pyproject.toml +1 -1
  9. by_framework-0.2.2.dev15/scripts/check-metric-catalog.sh +65 -0
  10. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/verify.sh +1 -0
  11. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/client/client.py +6 -0
  12. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/catalog.py +54 -0
  13. by_framework-0.2.2.dev15/src/by_framework/worker/_resume_metadata.py +65 -0
  14. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/processor.py +89 -22
  15. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/runner.py +29 -1
  16. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/worker.py +43 -0
  17. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/client/test_client.py +29 -0
  18. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_nested_chain.py +148 -0
  19. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_catalog.py +14 -2
  20. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_langfuse_plugin.py +358 -0
  21. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_gateway_worker.py +182 -0
  22. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_processor.py +220 -0
  23. by_framework-0.2.2.dev15/tests/worker/test_resume_metadata.py +69 -0
  24. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_runner.py +52 -0
  25. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/uv.lock +1 -1
  26. by_framework-0.2.2.dev13/CHANGELOG.md +0 -16
  27. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.codex/hooks.json +0 -0
  28. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.dockerignore +0 -0
  29. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  30. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  31. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  32. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/RELEASING.md +0 -0
  33. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/ci.yml +0 -0
  34. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/deploy-smoke-test.yml +0 -0
  35. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/publish.yml +0 -0
  36. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/stale.yml +0 -0
  37. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.github/workflows/verify.yml +0 -0
  38. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.gitignore +0 -0
  39. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/.pre-commit-config.yaml +0 -0
  40. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/AGENTS.md +0 -0
  41. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/CODE_OF_CONDUCT.md +0 -0
  42. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/CONTRIBUTING.md +0 -0
  43. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/LICENSE +0 -0
  44. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/README.md +0 -0
  45. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/README_zh.md +0 -0
  46. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/SECURITY.md +0 -0
  47. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/assets/img/architecture_en.png +0 -0
  48. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/assets/img/architecture_zh.png +0 -0
  49. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/autoformat.sh +0 -0
  50. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/Dockerfile +0 -0
  51. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/docker-compose.yml +0 -0
  52. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/entrypoint.sh +0 -0
  53. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/deploy/kubernetes/worker-deployment.yaml +0 -0
  54. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/README.md +0 -0
  55. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/GUARD_AUTHORING.md +0 -0
  56. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/production-deployment.md +0 -0
  57. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/redis-cluster-mode.md +0 -0
  58. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/suspend-resume-liveness.md +0 -0
  59. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/architecture/worker-readiness-endpoint.md +0 -0
  60. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/by-framework-trace-change-usage.html +0 -0
  61. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/by-framework-trace-complete-guide.html +0 -0
  62. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/plans/2026-05-15-worker-task-state-stats.md +0 -0
  63. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/plans/2026-06-10-trace-metrics-correlation.md +0 -0
  64. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/docs/worker_management.html +0 -0
  65. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/examples/__init__.py +0 -0
  66. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/examples/echo_worker.py +0 -0
  67. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/examples/send_and_verify.py +0 -0
  68. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/README.md +0 -0
  69. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/pyproject.toml +0 -0
  70. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/__init__.py +0 -0
  71. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/_utils.py +0 -0
  72. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/adapter.py +0 -0
  73. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/src/by_framework_adk/worker.py +0 -0
  74. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/tests/test_adapter.py +0 -0
  75. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-adk/tests/test_worker.py +0 -0
  76. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/README.md +0 -0
  77. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/01_basic_chat.py +0 -0
  78. {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
  79. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/03_agent_delegation.py +0 -0
  80. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/04_task_group.py +0 -0
  81. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/05_real_model_react.py +0 -0
  82. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/README.md +0 -0
  83. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/examples/_infra.py +0 -0
  84. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/pyproject.toml +0 -0
  85. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/__init__.py +0 -0
  86. {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
  87. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/loop.py +0 -0
  88. {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
  89. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/testing.py +0 -0
  90. {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
  91. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/src/by_framework_agent/worker.py +0 -0
  92. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/conftest.py +0 -0
  93. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_agent_as_tool.py +0 -0
  94. {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
  95. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_cancel_cleanup.py +0 -0
  96. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_native_agent_worker.py +0 -0
  97. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_task_group_batching.py +0 -0
  98. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-agent/tests/test_tool_calling_loop.py +0 -0
  99. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/Dockerfile +0 -0
  100. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/README.md +0 -0
  101. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/index.html +0 -0
  102. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/package-lock.json +0 -0
  103. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/package.json +0 -0
  104. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/src/main.jsx +0 -0
  105. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/src/styles.css +0 -0
  106. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/frontend/vite.config.js +0 -0
  107. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/pyproject.toml +0 -0
  108. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/__init__.py +0 -0
  109. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/adapters.py +0 -0
  110. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/src/by_framework_dashboard/dashboard.py +0 -0
  111. {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
  112. {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
  113. {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
  114. {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
  115. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-dashboard/tests/test_dashboard_server.py +0 -0
  116. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/README.md +0 -0
  117. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/pyproject.toml +0 -0
  118. {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
  119. {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
  120. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-byclaw/tests/test_byclaw_history.py +0 -0
  121. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/README.md +0 -0
  122. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-history-postgres/pyproject.toml +0 -0
  123. {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
  124. {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
  125. {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
  126. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/README.md +0 -0
  127. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/pyproject.toml +0 -0
  128. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/__init__.py +0 -0
  129. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/_utils.py +0 -0
  130. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/adapter.py +0 -0
  131. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/tools.py +0 -0
  132. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/src/by_framework_langgraph/worker.py +0 -0
  133. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/tests/test_adapter.py +0 -0
  134. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/tests/test_tools.py +0 -0
  135. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-langgraph/tests/test_utils.py +0 -0
  136. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/README.md +0 -0
  137. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/pyproject.toml +0 -0
  138. {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
  139. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-langfuse/tests/test_langfuse_import.py +0 -0
  140. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/README.md +0 -0
  141. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/pyproject.toml +0 -0
  142. {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
  143. {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
  144. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/tests/test_phoenix_import.py +0 -0
  145. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-phoenix/tests/test_phoenix_plugin.py +0 -0
  146. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/libs/by-framework-trace-query/pyproject.toml +0 -0
  147. {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
  148. {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
  149. {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
  150. {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
  151. {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
  152. {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
  153. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/pylintrc +0 -0
  154. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/.map.conf +0 -0
  155. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/check-doc-discipline.sh +0 -0
  156. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/check-entry-freshness.sh +0 -0
  157. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/check-map-territory.sh +0 -0
  158. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/map-stop-hook.sh +0 -0
  159. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/python_quality.sh +0 -0
  160. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/scripts/test-growth-ladder.sh +0 -0
  161. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/__init__.py +0 -0
  162. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/__main__.py +0 -0
  163. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/admin/__init__.py +0 -0
  164. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/admin/cli.py +0 -0
  165. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/admin/worker_manager.py +0 -0
  166. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/client/__init__.py +0 -0
  167. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/client/byai_client.py +0 -0
  168. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/__init__.py +0 -0
  169. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/config.py +0 -0
  170. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/constants.py +0 -0
  171. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/emitter.py +0 -0
  172. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/exceptions.py +0 -0
  173. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/logger.py +0 -0
  174. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/common/redis_client.py +0 -0
  175. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/__init__.py +0 -0
  176. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/availability.py +0 -0
  177. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/delivery_gate.py +0 -0
  178. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/discovery.py +0 -0
  179. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/__init__.py +0 -0
  180. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/agent_config.py +0 -0
  181. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/agent_config_audit.py +0 -0
  182. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/plugin.py +0 -0
  183. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/registry.py +0 -0
  184. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/extensions/trace_provider.py +0 -0
  185. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/__init__.py +0 -0
  186. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/action_type.py +0 -0
  187. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/agent_state.py +0 -0
  188. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/byai_codec.py +0 -0
  189. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/byai_command.py +0 -0
  190. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/byai_types.py +0 -0
  191. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/commands.py +0 -0
  192. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/content_codec.py +0 -0
  193. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/content_type.py +0 -0
  194. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/data_message.py +0 -0
  195. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/data_shapes.py +0 -0
  196. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/event_type.py +0 -0
  197. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/events.py +0 -0
  198. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/message.py +0 -0
  199. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/message_header.py +0 -0
  200. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/responses.py +0 -0
  201. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/protocol/results.py +0 -0
  202. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/registry.py +0 -0
  203. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/__init__.py +0 -0
  204. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/agent_config_manager.py +0 -0
  205. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/agent_runtime_state.py +0 -0
  206. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/file_manager.py +0 -0
  207. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/file_paths.py +0 -0
  208. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/file_permissions.py +0 -0
  209. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/filestore/__init__.py +0 -0
  210. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/filestore/base.py +0 -0
  211. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/filestore/local.py +0 -0
  212. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/__init__.py +0 -0
  213. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/base.py +0 -0
  214. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/history_manager.py +0 -0
  215. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/history/in_memory.py +0 -0
  216. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/runtime/session_manager.py +0 -0
  217. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_gate.py +0 -0
  218. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_index.py +0 -0
  219. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_reply.py +0 -0
  220. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wait_sweeper.py +0 -0
  221. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/wakeup_controller.py +0 -0
  222. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/core/workspace.py +0 -0
  223. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/__init__.py +0 -0
  224. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/base.py +0 -0
  225. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/common.py +0 -0
  226. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/execution.py +0 -0
  227. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/http.py +0 -0
  228. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/protocol.py +0 -0
  229. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/errors/registry.py +0 -0
  230. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/__init__.py +0 -0
  231. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/collector.py +0 -0
  232. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/read_client.py +0 -0
  233. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/metrics/snapshot.py +0 -0
  234. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/__init__.py +0 -0
  235. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/external_trace.py +0 -0
  236. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/span_recorder.py +0 -0
  237. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/trace_schema.py +0 -0
  238. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/trace/trace_writer.py +0 -0
  239. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/__init__.py +0 -0
  240. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/discovery_http_client.py +0 -0
  241. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/generate_message_id.py +0 -0
  242. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/util/http_client.py +0 -0
  243. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/__init__.py +0 -0
  244. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/_control_handling.py +0 -0
  245. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/_execution_tracking.py +0 -0
  246. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/_message_processing.py +0 -0
  247. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/app.py +0 -0
  248. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/byai_context.py +0 -0
  249. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/byai_worker.py +0 -0
  250. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/context.py +0 -0
  251. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/health_server.py +0 -0
  252. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/heartbeat.py +0 -0
  253. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/sandbox/__init__.py +0 -0
  254. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/src/by_framework/worker/sandbox/hook_sandbox.py +0 -0
  255. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/admin/__init__.py +0 -0
  256. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/admin/test_cli.py +0 -0
  257. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/client/__init__.py +0 -0
  258. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/__init__.py +0 -0
  259. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_config.py +0 -0
  260. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_constants.py +0 -0
  261. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_exceptions.py +0 -0
  262. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_logger.py +0 -0
  263. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/common/test_redis_client.py +0 -0
  264. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/conftest.py +0 -0
  265. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/__init__.py +0 -0
  266. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/__init__.py +0 -0
  267. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_byai_codec.py +0 -0
  268. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_command_wire.py +0 -0
  269. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_protocol.py +0 -0
  270. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/protocol/test_results.py +0 -0
  271. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/history/__init__.py +0 -0
  272. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/history/test_history_persistence.py +0 -0
  273. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_access_context.py +0 -0
  274. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_manager_default_storage.py +0 -0
  275. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_paths.py +0 -0
  276. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_file_permissions.py +0 -0
  277. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_collection.py +0 -0
  278. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_mutation.py +0 -0
  279. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_read.py +0 -0
  280. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/runtime/test_filestore_local_search.py +0 -0
  281. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_agent_config_audit.py +0 -0
  282. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_availability.py +0 -0
  283. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_discovery.py +0 -0
  284. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_registry.py +0 -0
  285. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_wait_gate.py +0 -0
  286. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_wait_index.py +0 -0
  287. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_wait_sweeper.py +0 -0
  288. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/core/test_worker_manager.py +0 -0
  289. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/__init__.py +0 -0
  290. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_ask_user_flow.py +0 -0
  291. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_callback_flow.py +0 -0
  292. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_logger_integration.py +0 -0
  293. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_orphan_recovery.py +0 -0
  294. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/integration/test_scatter_gather.py +0 -0
  295. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_collector.py +0 -0
  296. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_metrics.py +0 -0
  297. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_read_client.py +0 -0
  298. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/metrics/test_snapshot.py +0 -0
  299. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/__init__.py +0 -0
  300. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_discovery.py +0 -0
  301. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_improvements.py +0 -0
  302. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_registry.py +0 -0
  303. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/plugin/test_plugin_system.py +0 -0
  304. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/test_main.py +0 -0
  305. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_external_trace.py +0 -0
  306. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_logger_correlation.py +0 -0
  307. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_otel_exporter.py +0 -0
  308. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_span_recorder.py +0 -0
  309. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/trace/test_trace_writer.py +0 -0
  310. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_discovery_http_client.py +0 -0
  311. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_discovery_http_client_download.py +0 -0
  312. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_discovery_http_client_upload.py +0 -0
  313. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/util/test_http_client.py +0 -0
  314. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/__init__.py +0 -0
  315. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_admin_control_handling.py +0 -0
  316. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_app.py +0 -0
  317. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_byai_worker.py +0 -0
  318. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_context.py +0 -0
  319. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_control_handling.py +0 -0
  320. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_emitter.py +0 -0
  321. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_fetch_messages.py +0 -0
  322. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_health_server.py +0 -0
  323. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_heartbeat.py +0 -0
  324. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_message_processing.py +0 -0
  325. {by_framework-0.2.2.dev13 → by_framework-0.2.2.dev15}/tests/worker/test_sandbox.py +0 -0
  326. {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
- @for project in $(PROJECTS); do \
42
- echo "==> Syncing $$project"; \
43
- (cd $$project && uv sync --all-extras); \
44
- done
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 --extra dev pytest); \
113
+ (cd $$project && uv run --all-extras pytest); \
91
114
  done
92
115
 
93
116
  clean:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: by-framework
3
- Version: 0.2.2.dev13
3
+ Version: 0.2.2.dev15
4
4
  Summary: 分布式 Agent 调度框架
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -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. Every `ResumeCommand` passes the `core/wait_gate.py`
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`; and no callback may be sent while
435
- `context._is_suspended` (with the same terminal-status exception).
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.