diff --git a/.github/workflows/loongsuite_test_0.yml b/.github/workflows/loongsuite_test_0.yml index 73da298f5..47f330d67 100644 --- a/.github/workflows/loongsuite_test_0.yml +++ b/.github/workflows/loongsuite_test_0.yml @@ -84,7 +84,7 @@ jobs: shell: bash env: LOONGSUITE_ALL_JOBS: >- - [{"name": "py310-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.13 ARC"}, {"name": "py39-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.9", "tox_env": "py39-test-util-genai", "ui_name": "util-genai 3.9 ARC"}, {"name": "py310-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.10", "tox_env": "py310-test-util-genai", "ui_name": "util-genai 3.10 ARC"}, {"name": "py311-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.11", "tox_env": "py311-test-util-genai", "ui_name": "util-genai 3.11 ARC"}, {"name": "py312-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.12", "tox_env": "py312-test-util-genai", "ui_name": "util-genai 3.12 ARC"}, {"name": "py313-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.13", "tox_env": "py313-test-util-genai", "ui_name": "util-genai 3.13 ARC"}, {"name": "py314-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.14", "tox_env": "py314-test-util-genai", "ui_name": "util-genai 3.14 ARC"}, {"name": "pypy3-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "pypy-3.9", "tox_env": "pypy3-test-util-genai", "ui_name": "util-genai pypy-3.9 ARC"}, {"name": "py311-test-detect-loongsuite-changes_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "detect-loongsuite-changes", "python_version": "3.11", "tox_env": "py311-test-detect-loongsuite-changes", "ui_name": "detect-loongsuite-changes 3.11 ARC"}, {"name": "py310-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.13 ARC"}, {"name": "py39-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.9", "tox_env": "py39-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.9 ARC"}, {"name": "py310-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.10", "tox_env": "py310-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.10 ARC"}, {"name": "py311-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.11", "tox_env": "py311-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.11 ARC"}, {"name": "py312-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.12", "tox_env": "py312-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.12 ARC"}, {"name": "py313-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.13", "tox_env": "py313-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.13 ARC"}] + [{"name": "py310-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.13 ARC"}, {"name": "py39-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.9", "tox_env": "py39-test-util-genai", "ui_name": "util-genai 3.9 ARC"}, {"name": "py310-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.10", "tox_env": "py310-test-util-genai", "ui_name": "util-genai 3.10 ARC"}, {"name": "py311-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.11", "tox_env": "py311-test-util-genai", "ui_name": "util-genai 3.11 ARC"}, {"name": "py312-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.12", "tox_env": "py312-test-util-genai", "ui_name": "util-genai 3.12 ARC"}, {"name": "py313-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.13", "tox_env": "py313-test-util-genai", "ui_name": "util-genai 3.13 ARC"}, {"name": "py314-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.14", "tox_env": "py314-test-util-genai", "ui_name": "util-genai 3.14 ARC"}, {"name": "pypy3-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "pypy-3.9", "tox_env": "pypy3-test-util-genai", "ui_name": "util-genai pypy-3.9 ARC"}, {"name": "py311-test-detect-loongsuite-changes_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "detect-loongsuite-changes", "python_version": "3.11", "tox_env": "py311-test-detect-loongsuite-changes", "ui_name": "detect-loongsuite-changes 3.11 ARC"}, {"name": "py310-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-v1_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-v1", "ui_name": "loongsuite-instrumentation-qwenpaw-v1 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-v1_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-v1", "ui_name": "loongsuite-instrumentation-qwenpaw-v1 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-v1_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-v1", "ui_name": "loongsuite-instrumentation-qwenpaw-v1 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-v1_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-v1", "ui_name": "loongsuite-instrumentation-qwenpaw-v1 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.13 ARC"}, {"name": "py39-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.9", "tox_env": "py39-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.9 ARC"}, {"name": "py310-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.10", "tox_env": "py310-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.10 ARC"}, {"name": "py311-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.11", "tox_env": "py311-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.11 ARC"}, {"name": "py312-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.12", "tox_env": "py312-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.12 ARC"}, {"name": "py313-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.13", "tox_env": "py313-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.13 ARC"}] LOONGSUITE_FULL: ${{ steps.detect.outputs.full }} LOONGSUITE_PACKAGES: ${{ steps.detect.outputs.packages }} run: | diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/CHANGELOG.md b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/CHANGELOG.md index da5f3c297..5b40fb344 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/CHANGELOG.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Derive AgentScope v2 ReAct rounds from the agent iteration state instead of + a `ContextVar` token that could fail when QwenPaw advances a reply stream + from different asyncio tasks. +- Restore Agent, ReAct, and tool span contexts for each stream advance so + cross-task QwenPaw handoffs preserve parentage, and treat `GeneratorExit` as + a successful stream close instead of a tool failure. - Start AgentScope v2 streaming LLM spans before invoking the underlying model call so TTFT and stream lifecycle are recorded on the framework LLM span. - Capture AgentScope v2 string message content as text parts so LLM input and diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/_v2_middleware.py b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/_v2_middleware.py index 982adf987..9cf186e79 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/_v2_middleware.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/_v2_middleware.py @@ -20,9 +20,14 @@ import json import logging import timeit -from collections.abc import AsyncGenerator, Awaitable, Callable, Sequence -from contextvars import ContextVar -from dataclasses import asdict, is_dataclass +from collections.abc import ( + AsyncGenerator, + AsyncIterator, + Awaitable, + Callable, + Sequence, +) +from dataclasses import asdict, dataclass, is_dataclass from typing import Any from agentscope.agent import Agent @@ -31,13 +36,16 @@ from agentscope.model import ChatModelBase, ChatResponse from agentscope.tool import ToolResponse -from opentelemetry.context import get_current +from opentelemetry import context as otel_context +from opentelemetry.context import Context, get_current +from opentelemetry.util.genai import hook_advice from opentelemetry.util.genai.extended_handler import ExtendedTelemetryHandler from opentelemetry.util.genai.extended_types import ( ExecuteToolInvocation, InvokeAgentInvocation, ReactStepInvocation, ) +from opentelemetry.util.genai.handler import _safe_detach from opentelemetry.util.genai.types import ( Error, FunctionToolDefinition, @@ -60,6 +68,252 @@ } +@dataclass +class _AgentState: + handler: ExtendedTelemetryHandler + invocation: InvokeAgentInvocation + context: Context + first_token_seen: bool = False + last_msg: Msg | None = None + finalized: bool = False + + +@dataclass +class _ActingState: + handler: ExtendedTelemetryHandler + react_invocation: ReactStepInvocation + tool_invocation: ExecuteToolInvocation + react_context: Context + tool_context: Context + last_item: Any = None + tool_finalized: bool = False + react_finalized: bool = False + + +def _abandon_invocation(invocation: Any) -> None: + token = invocation.context_token + invocation.context_token = None + _safe_detach(token) + span = invocation.span + if span is not None and span.is_recording(): + span.end() + + +@hook_advice("agentscope", "start_invoke_agent") +def _start_agent( + handler: ExtendedTelemetryHandler, + invocation: InvokeAgentInvocation, +) -> _AgentState: + """Start Agent, save its Context, then detach before yielding ownership.""" + + try: + handler.start_invoke_agent(invocation) + agent_context = get_current() + except Exception: + _abandon_invocation(invocation) + raise + + token = invocation.context_token + invocation.context_token = None + _safe_detach(token) + return _AgentState( + handler=handler, + invocation=invocation, + context=agent_context, + ) + + +@hook_advice("agentscope", "attach_stream_context") +def _attach_stream_context(context: Context) -> object: + return otel_context.attach(context) + + +@hook_advice("agentscope", "detach_stream_context") +def _detach_stream_context(token: object | None) -> None: + _safe_detach(token) + + +@hook_advice("agentscope", "record_agent_chunk") +def _record_agent_chunk(state: _AgentState, item: Any) -> None: + if not state.first_token_seen and _is_first_token_event(item): + state.invocation.monotonic_first_token_s = timeit.default_timer() + state.first_token_seen = True + if isinstance(item, Msg): + state.last_msg = item + + +@hook_advice("agentscope", "finish_invoke_agent") +def _finish_agent( + state: _AgentState, + error: BaseException | None = None, +) -> None: + if state.finalized: + return + state.finalized = True + + invocation = state.invocation + if state.last_msg is not None: + invocation.output_messages = [_message_to_output(state.last_msg)] + if state.last_msg.usage is not None: + invocation.input_tokens = state.last_msg.usage.input_tokens + invocation.output_tokens = state.last_msg.usage.output_tokens + + token = None + span = invocation.span + try: + token = otel_context.attach(state.context) + invocation.context_token = token + if error is None or isinstance(error, GeneratorExit): + state.handler.stop_invoke_agent(invocation) + else: + state.handler.fail_invoke_agent( + invocation, + Error( + message=str(error) or type(error).__name__, + type=type(error), + ), + ) + finally: + invocation.context_token = None + if span is not None and span.is_recording(): + _safe_detach(token) + span.end() + + +@hook_advice("agentscope", "start_acting") +def _start_acting( + handler: ExtendedTelemetryHandler, + agent: Agent, + tool_call: Any, +) -> _ActingState: + react_invocation = ReactStepInvocation( + round=getattr( + getattr(agent, "state", None), + "cur_iter", + 0, + ) + + 1 + ) + tool_invocation = ExecuteToolInvocation( + tool_name=getattr(tool_call, "name", "unknown_tool"), + tool_type="function", + tool_call_id=getattr(tool_call, "id", None), + tool_call_arguments=_loads_json(getattr(tool_call, "input", None)), + provider="agentscope", + ) + + try: + handler.start_react_step(react_invocation, context=get_current()) + react_context = get_current() + handler.start_execute_tool(tool_invocation) + tool_context = get_current() + except Exception: + _abandon_invocation(tool_invocation) + _abandon_invocation(react_invocation) + raise + + tool_token = tool_invocation.context_token + tool_invocation.context_token = None + _safe_detach(tool_token) + react_token = react_invocation.context_token + react_invocation.context_token = None + _safe_detach(react_token) + return _ActingState( + handler=handler, + react_invocation=react_invocation, + tool_invocation=tool_invocation, + react_context=react_context, + tool_context=tool_context, + ) + + +@hook_advice("agentscope", "finish_execute_tool") +def _finish_tool( + state: _ActingState, + error: BaseException | None = None, +) -> None: + if state.tool_finalized: + return + state.tool_finalized = True + + invocation = state.tool_invocation + if error is None or isinstance(error, GeneratorExit): + if isinstance(state.last_item, ToolResponse): + invocation.tool_call_result = _jsonable( + _blocks_to_parts(state.last_item.content) + ) + elif state.last_item is not None: + invocation.tool_call_result = str(state.last_item) + + token = None + span = invocation.span + try: + token = otel_context.attach(state.tool_context) + invocation.context_token = token + if error is None or isinstance(error, GeneratorExit): + state.handler.stop_execute_tool(invocation) + else: + state.handler.fail_execute_tool( + invocation, + Error( + message=str(error) or type(error).__name__, + type=type(error), + ), + ) + finally: + invocation.context_token = None + if span is not None and span.is_recording(): + _safe_detach(token) + span.end() + + +@hook_advice("agentscope", "finish_react_step") +def _finish_react( + state: _ActingState, + error: BaseException | None = None, +) -> None: + if state.react_finalized: + return + state.react_finalized = True + + invocation = state.react_invocation + token = None + span = invocation.span + try: + token = otel_context.attach(state.react_context) + invocation.context_token = token + if error is None or isinstance(error, GeneratorExit): + invocation.finish_reason = "tool_calls" + state.handler.stop_react_step(invocation) + else: + state.handler.fail_react_step( + invocation, + Error( + message=str(error) or type(error).__name__, + type=type(error), + ), + ) + finally: + invocation.context_token = None + if span is not None and span.is_recording(): + _safe_detach(token) + span.end() + + +def _finish_acting( + state: _ActingState, + error: BaseException | None = None, +) -> None: + _finish_tool(state, error) + _finish_react(state, error) + + +async def _close_iterator(iterator: AsyncIterator[Any]) -> None: + close = getattr(iterator, "aclose", None) + if close is not None: + await close() + + def append_loongsuite_middleware( args: tuple[Any, ...], kwargs: dict[str, Any], @@ -105,10 +359,6 @@ def __init__( self, handler: Callable[[], ExtendedTelemetryHandler | None] ) -> None: self._handler = handler - self._react_round: ContextVar[int] = ContextVar( - "loongsuite_agentscope_v2_react_round", - default=0, - ) async def on_reply( self, @@ -123,38 +373,52 @@ async def on_reply( return invocation = _create_agent_invocation(agent, input_kwargs) - handler.start_invoke_agent(invocation) - round_token = self._react_round.set(0) - first_token_seen = False - last_msg = None - closed = False + state = _start_agent(handler, invocation) try: - async for item in next_handler(**input_kwargs): - if not first_token_seen and _is_first_token_event(item): - invocation.monotonic_first_token_s = timeit.default_timer() - first_token_seen = True - if isinstance(item, Msg): - last_msg = item + business_stream = next_handler(**input_kwargs) + iterator = business_stream.__aiter__() + except BaseException as exc: + if state is not None: + _finish_agent(state, exc) + raise + if state is None: + try: + async for item in iterator: + yield item + except GeneratorExit: + await _close_iterator(iterator) + raise + return + + try: + while True: + token = _attach_stream_context(state.context) + try: + item = await iterator.__anext__() + except StopAsyncIteration: + break + finally: + _detach_stream_context(token) + + _record_agent_chunk(state, item) yield item + except GeneratorExit as exc: + token = _attach_stream_context(state.context) + try: + await _close_iterator(iterator) + except BaseException as close_error: + _finish_agent(state, close_error) + raise + finally: + _detach_stream_context(token) + _finish_agent(state, exc) + raise except BaseException as exc: - handler.fail_invoke_agent( - invocation, - Error(message=str(exc) or type(exc).__name__, type=type(exc)), - ) - closed = True + _finish_agent(state, exc) raise - else: - if last_msg is not None: - invocation.output_messages = [_message_to_output(last_msg)] - if last_msg.usage is not None: - invocation.input_tokens = last_msg.usage.input_tokens - invocation.output_tokens = last_msg.usage.output_tokens - handler.stop_invoke_agent(invocation) - closed = True finally: - self._react_round.reset(round_token) - if not closed: - handler.stop_invoke_agent(invocation) + if not state.finalized: + _finish_agent(state) async def on_model_call( self, @@ -239,57 +503,52 @@ async def on_acting( return tool_call = input_kwargs.get("tool_call") - react_invocation = ReactStepInvocation(round=self._next_react_round()) - handler.start_react_step(react_invocation, context=get_current()) - invocation = ExecuteToolInvocation( - tool_name=getattr(tool_call, "name", "unknown_tool"), - tool_type="function", - tool_call_id=getattr(tool_call, "id", None), - tool_call_arguments=_loads_json(getattr(tool_call, "input", None)), - provider="agentscope", - ) - handler.start_execute_tool(invocation) - last_item = None - tool_closed = False - react_closed = False + state = _start_acting(handler, agent, tool_call) try: - async for item in next_handler(**input_kwargs): - last_item = item + business_stream = next_handler(**input_kwargs) + iterator = business_stream.__aiter__() + except BaseException as exc: + if state is not None: + _finish_acting(state, exc) + raise + if state is None: + try: + async for item in iterator: + yield item + except GeneratorExit: + await _close_iterator(iterator) + raise + return + + try: + while True: + token = _attach_stream_context(state.tool_context) + try: + item = await iterator.__anext__() + except StopAsyncIteration: + break + finally: + _detach_stream_context(token) + + state.last_item = item yield item + except GeneratorExit as exc: + token = _attach_stream_context(state.tool_context) + try: + await _close_iterator(iterator) + except BaseException as close_error: + _finish_acting(state, close_error) + raise + finally: + _detach_stream_context(token) + _finish_acting(state, exc) + raise except BaseException as exc: - error = Error( - message=str(exc) or type(exc).__name__, type=type(exc) - ) - handler.fail_execute_tool( - invocation, - error, - ) - tool_closed = True - handler.fail_react_step(react_invocation, error) - react_closed = True + _finish_acting(state, exc) raise - else: - if isinstance(last_item, ToolResponse): - invocation.tool_call_result = _jsonable( - _blocks_to_parts(last_item.content) - ) - elif last_item is not None: - invocation.tool_call_result = str(last_item) - handler.stop_execute_tool(invocation) - tool_closed = True - react_invocation.finish_reason = "tool_calls" - handler.stop_react_step(react_invocation) - react_closed = True finally: - if not tool_closed: - handler.stop_execute_tool(invocation) - if not react_closed: - handler.stop_react_step(react_invocation) - - def _next_react_round(self) -> int: - current = self._react_round.get() + 1 - self._react_round.set(current) - return current + if not state.tool_finalized or not state.react_finalized: + _finish_acting(state) def _create_agent_invocation( diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/requirements.oldest.txt b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/requirements.oldest.txt index 6c2358ca2..d570386af 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/requirements.oldest.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/requirements.oldest.txt @@ -16,6 +16,7 @@ # the oldest supported version of external dependencies. agentscope>=1.0.0,<2.0.0 +mcp<2 pytest pytest-asyncio pytest-cov diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/test_v2_instrumentation.py b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/test_v2_instrumentation.py index 8b73b572a..0ddcbccb0 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/test_v2_instrumentation.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/test_v2_instrumentation.py @@ -322,6 +322,256 @@ async def stream(): assert output_messages[0]["parts"][0]["content"] == "done" +async def test_v2_reply_stream_survives_cross_task_heartbeat( + instrument, + tracer_provider, + span_exporter, +): + agent = Agent( + name="cross_task_agent", + system_prompt="Reply briefly.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._reply_middlewares) + child_tracer = trace_api.get_tracer( + "agentscope-cross-task-test", + tracer_provider=tracer_provider, + ) + expected = Msg( + name="assistant", + role="assistant", + content=[TextBlock(text="done")], + ) + + async def reply_handler(**kwargs): + del kwargs + with child_tracer.start_as_current_span("reply-child"): + pass + yield expected + + stream = middleware.on_reply(agent, {"inputs": []}, reply_handler) + + assert await _heartbeat_next(stream) is expected + with pytest.raises(StopAsyncIteration): + await _heartbeat_next(stream) + + agent_spans = _spans_by_operation( + span_exporter.get_finished_spans(), + "invoke_agent", + ) + assert len(agent_spans) == 1 + assert agent_spans[0].status.status_code == StatusCode.UNSET + [child_span] = [ + span + for span in span_exporter.get_finished_spans() + if span.name == "reply-child" + ] + assert child_span.parent.span_id == agent_spans[0].context.span_id + assert not trace_api.get_current_span().get_span_context().is_valid + + +async def test_v2_reply_stream_preserves_cross_task_business_error( + instrument, + span_exporter, +): + agent = Agent( + name="cross_task_error_agent", + system_prompt="Reply briefly.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._reply_middlewares) + expected_error = RuntimeError("reply failed") + + async def reply_handler(**kwargs): + del kwargs + yield Msg( + name="assistant", + role="assistant", + content=[TextBlock(text="partial")], + ) + raise expected_error + + stream = middleware.on_reply(agent, {"inputs": []}, reply_handler) + + await _heartbeat_next(stream) + with pytest.raises(RuntimeError, match="reply failed") as caught: + await _heartbeat_next(stream) + + assert caught.value is expected_error + agent_spans = _spans_by_operation( + span_exporter.get_finished_spans(), + "invoke_agent", + ) + assert len(agent_spans) == 1 + assert agent_spans[0].status.status_code == StatusCode.ERROR + + +async def test_v2_reply_start_failure_preserves_business_stream( + instrument, + span_exporter, + monkeypatch, +): + agent = Agent( + name="start_failure_agent", + system_prompt="Reply briefly.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._reply_middlewares) + expected = Msg( + name="assistant", + role="assistant", + content=[TextBlock(text="business result")], + ) + handler = middleware._handler() + + def start_invoke_agent(*args, **kwargs): + del args, kwargs + raise ValueError("probe start failure") + + monkeypatch.setattr(handler, "start_invoke_agent", start_invoke_agent) + + async def reply_handler(**kwargs): + del kwargs + yield expected + + results = [ + item + async for item in middleware.on_reply( + agent, + {"inputs": []}, + reply_handler, + ) + ] + + assert results == [expected] + assert not span_exporter.get_finished_spans() + assert not trace_api.get_current_span().get_span_context().is_valid + + +async def test_v2_reply_finish_failure_does_not_replace_business_result( + instrument, + span_exporter, + monkeypatch, +): + agent = Agent( + name="finish_failure_agent", + system_prompt="Reply briefly.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._reply_middlewares) + expected = Msg( + name="assistant", + role="assistant", + content=[TextBlock(text="business result")], + ) + handler = middleware._handler() + + def stop_invoke_agent(*args, **kwargs): + del args, kwargs + raise ValueError("probe finish failure") + + monkeypatch.setattr(handler, "stop_invoke_agent", stop_invoke_agent) + + async def reply_handler(**kwargs): + del kwargs + yield expected + + results = [ + item + async for item in middleware.on_reply( + agent, + {"inputs": []}, + reply_handler, + ) + ] + + assert results == [expected] + assert len(span_exporter.get_finished_spans()) == 1 + assert not trace_api.get_current_span().get_span_context().is_valid + + +async def test_v2_reply_fail_callback_preserves_original_business_error( + instrument, + span_exporter, + monkeypatch, +): + agent = Agent( + name="fail_callback_agent", + system_prompt="Reply briefly.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._reply_middlewares) + handler = middleware._handler() + business_error = RuntimeError("business failure") + + def fail_invoke_agent(*args, **kwargs): + del args, kwargs + raise ValueError("probe fail callback failure") + + monkeypatch.setattr(handler, "fail_invoke_agent", fail_invoke_agent) + + async def reply_handler(**kwargs): + del kwargs + yield Msg( + name="assistant", + role="assistant", + content=[TextBlock(text="partial")], + ) + raise business_error + + stream = middleware.on_reply(agent, {"inputs": []}, reply_handler) + await _heartbeat_next(stream) + try: + await _heartbeat_next(stream) + except RuntimeError as exc: + assert exc is business_error + else: + pytest.fail("business error was not raised") + + assert len(span_exporter.get_finished_spans()) == 1 + assert not trace_api.get_current_span().get_span_context().is_valid + + +async def test_v2_reply_stream_preserves_cross_task_cancellation( + instrument, + span_exporter, +): + agent = Agent( + name="cross_task_cancel_agent", + system_prompt="Reply briefly.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._reply_middlewares) + resumed = asyncio.Event() + + async def reply_handler(**kwargs): + del kwargs + yield Msg( + name="assistant", + role="assistant", + content=[TextBlock(text="partial")], + ) + resumed.set() + await asyncio.Event().wait() + + stream = middleware.on_reply(agent, {"inputs": []}, reply_handler) + await _heartbeat_next(stream) + + pending_next = asyncio.create_task(_heartbeat_next(stream)) + await asyncio.wait_for(resumed.wait(), timeout=1) + pending_next.cancel() + with pytest.raises(asyncio.CancelledError): + await pending_next + + agent_spans = _spans_by_operation( + span_exporter.get_finished_spans(), + "invoke_agent", + ) + assert len(agent_spans) == 1 + assert agent_spans[0].status.status_code == StatusCode.ERROR + assert agent_spans[0].attributes["error.type"] == "CancelledError" + + async def test_v2_tool_acting_hook(instrument, span_exporter): agent = Agent( name="tool_agent", @@ -356,6 +606,105 @@ async def tool_handler(**kwargs): assert tool_span.attributes["gen_ai.tool.type"] == "function" +async def test_v2_acting_aclose_is_normal_across_tasks( + instrument, + span_exporter, + caplog, +): + caplog.set_level("DEBUG", logger="opentelemetry.util.genai.handler") + agent = Agent( + name="cross_task_close_agent", + system_prompt="Use tools.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._acting_middlewares) + tool_call = SimpleNamespace( + name="successful_tool", + id="tool-call-close", + input="{}", + ) + expected = ToolResponse(content=[TextBlock(text="success")]) + closed = 0 + + async def tool_handler(**kwargs): + nonlocal closed + del kwargs + try: + yield expected + yield ToolResponse(content=[TextBlock(text="unused")]) + finally: + closed += 1 + + stream = middleware.on_acting( + agent, + {"tool_call": tool_call}, + tool_handler, + ) + assert await _heartbeat_next(stream) is expected + await asyncio.create_task(stream.aclose()) + + spans = span_exporter.get_finished_spans() + [tool_span] = _spans_by_operation(spans, "execute_tool") + [react_span] = _spans_by_operation(spans, "react") + assert closed == 1 + assert tool_span.status.status_code == StatusCode.UNSET + assert react_span.status.status_code == StatusCode.UNSET + assert "error.type" not in tool_span.attributes + assert "error.type" not in react_span.attributes + assert not any( + "Context detach failed" in record.getMessage() + for record in caplog.records + ) + assert not trace_api.get_current_span().get_span_context().is_valid + + +async def test_v2_acting_aclose_error_preserves_original_exception( + instrument, + span_exporter, +): + agent = Agent( + name="cross_task_close_error_agent", + system_prompt="Use tools.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._acting_middlewares) + tool_call = SimpleNamespace( + name="failing_close_tool", + id="tool-call-close-error", + input="{}", + ) + close_error = ValueError("business close failure") + + async def tool_handler(**kwargs): + del kwargs + try: + yield ToolResponse(content=[TextBlock(text="partial")]) + finally: + raise close_error + + stream = middleware.on_acting( + agent, + {"tool_call": tool_call}, + tool_handler, + ) + await _heartbeat_next(stream) + try: + await asyncio.create_task(stream.aclose()) + except ValueError as exc: + assert exc is close_error + else: + pytest.fail("business close error was not raised") + + spans = span_exporter.get_finished_spans() + [tool_span] = _spans_by_operation(spans, "execute_tool") + [react_span] = _spans_by_operation(spans, "react") + assert tool_span.status.status_code == StatusCode.ERROR + assert react_span.status.status_code == StatusCode.ERROR + assert tool_span.attributes["error.type"] == "ValueError" + assert react_span.attributes["error.type"] == "ValueError" + assert not trace_api.get_current_span().get_span_context().is_valid + + async def test_v2_tool_result_content_capture( instrument_with_content, span_exporter, @@ -421,6 +770,7 @@ async def tool_handler(**kwargs): del kwargs yield ToolResponse(content=[TextBlock(text=f"result {idx}")]) + agent.state.cur_iter = idx - 1 results = [ item async for item in middleware.on_acting( @@ -454,6 +804,52 @@ async def tool_handler(**kwargs): assert {span.parent.span_id for span in tool_spans} == react_span_ids +async def test_v2_react_concurrent_tools_share_agent_iteration( + instrument, + span_exporter, +): + agent = Agent( + name="concurrent_tool_agent", + system_prompt="Use tools.", + model=_make_model(stream=False), + ) + middleware = _middleware(agent._acting_middlewares) + agent.state.cur_iter = 2 + + async def call_tool(idx: int): + tool_call = SimpleNamespace( + name=f"tool_{idx}", + id=f"tool-call-{idx}", + input=f'{{"idx": {idx}}}', + ) + + async def tool_handler(**kwargs): + del kwargs + await asyncio.sleep(0) + yield ToolResponse(content=[TextBlock(text=f"result {idx}")]) + + return [ + item + async for item in middleware.on_acting( + agent, + {"tool_call": tool_call}, + tool_handler, + ) + ] + + results = await asyncio.gather(*(call_tool(idx) for idx in range(4))) + + assert all(results) + react_spans = _spans_by_operation( + span_exporter.get_finished_spans(), + "react", + ) + assert len(react_spans) == 4 + assert {span.attributes["gen_ai.react.round"] for span in react_spans} == { + 3 + } + + @pytest.mark.vcr() async def test_v2_agent_non_streaming_e2e(instrument, span_exporter): model = _make_model(stream=False) @@ -544,6 +940,15 @@ def _spans_by_operation(spans, operation_name): ] +async def _heartbeat_next(stream): + """Advance an async generator in a fresh Task, like QwenPaw heartbeat.""" + + async def advance(): + return await stream.__anext__() + + return await asyncio.wait_for(asyncio.create_task(advance()), timeout=1) + + def _middleware(middlewares): return next( middleware diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/CHANGELOG.md b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/CHANGELOG.md index 458ca653a..7ed0855dd 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/CHANGELOG.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added QwenPaw 2 Entry telemetry around each `Runtime.run` request while + preserving the QwenPaw 1 and legacy CoPaw entry points. +- Added task-safe stream context handoff so QwenPaw heartbeat tasks inherit the + Entry span without keeping an attached context token across yields. +- Records QwenPaw 2 Entry TTFT only after user-visible output and preserves + business stream cleanup when Entry telemetry setup fails. + +### Fixed + +- Restore the Entry context while closing downstream streams and preserve + downstream `aclose()` errors instead of finalizing the Entry as successful. + ## Version 0.7.0 (2026-07-03) There are no changelog entries for this release. diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/README.md b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/README.md index 5ba2eaa47..47f726eba 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/README.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/README.md @@ -5,7 +5,9 @@ LoongSuite instrumentation for on AgentScope. Compatibility note: CoPaw was renamed to QwenPaw. Installations pinned to -`copaw<=1.0.2` are still supported during the transition. +`copaw<=1.0.2` are still supported during the transition. QwenPaw 1 uses +`AgentRunner.query_handler` as its request entry point; QwenPaw 2 uses +`Runtime.run`. ## Getting Started @@ -113,15 +115,17 @@ With Site-bootstrap enabled in the same shell/session, start the app as usual: qwenpaw app ``` -Telemetry for `AgentRunner.query_handler` (Entry span) is then active without -modifying QwenPaw source code. +Telemetry for the installed runtime's request entry point +(`AgentRunner.query_handler` on QwenPaw 1, or `Runtime.run` on QwenPaw 2) is +then active without modifying QwenPaw source code. ### Optional: programmatic hook If you control an embedding process and prefer not to use site-bootstrap, you can call `QwenPawInstrumentor().instrument()` (and `uninstrument()` when done) before QwenPaw runs in that process—the hook point is still -`AgentRunner.query_handler`. You must still configure the global +`AgentRunner.query_handler` on QwenPaw 1 / CoPaw or `Runtime.run` on QwenPaw 2. +You must still configure the global `TracerProvider` / export (for example via OpenTelemetry env vars) consistently with the rest of your app. diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/__init__.py index a2bc5ffaf..b8cac3ee7 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/__init__.py @@ -15,7 +15,8 @@ """ LoongSuite QwenPaw instrumentation. -Instruments ``AgentRunner.query_handler`` with ``ExtendedTelemetryHandler.entry`` +Instruments QwenPaw 1 ``AgentRunner.query_handler`` and QwenPaw 2 +``Runtime.run`` with ``ExtendedTelemetryHandler.entry`` (``enter_ai_application_system``). Agent / tool / LLM spans come from AgentScope and other instrumentations. @@ -42,10 +43,11 @@ from opentelemetry.instrumentation.qwenpaw.package import ( _instruments_any, get_installed_instrumentation_dependencies, - get_installed_runner_modules, + get_installed_runtime_targets, ) from opentelemetry.instrumentation.qwenpaw.patch import ( make_query_handler_wrapper, + make_runtime_wrapper, ) from opentelemetry.instrumentation.utils import unwrap from opentelemetry.util.genai.extended_handler import ExtendedTelemetryHandler @@ -76,36 +78,50 @@ def _instrument(self, **kwargs: Any) -> None: meter_provider=meter_provider, logger_provider=logger_provider, ) - runner_modules = tuple(get_installed_runner_modules()) - if not runner_modules: + runtime_targets = tuple(get_installed_runtime_targets()) + if not runtime_targets: raise ModuleNotFoundError( "No supported QwenPaw runtime package is installed" ) - for module_name in runner_modules: + for target in runtime_targets: + wrapper_factory = ( + make_runtime_wrapper + if target.wrapper_kind == "runtime" + else make_query_handler_wrapper + ) wrap_function_wrapper( - module_name, - "AgentRunner.query_handler", - make_query_handler_wrapper(self._handler, module_name), + target.module_name, + f"{target.class_name}.{target.method_name}", + wrapper_factory(self._handler, target.module_name), ) logger.debug( - "Instrumented %s.AgentRunner.query_handler", module_name + "Instrumented %s.%s.%s", + target.module_name, + target.class_name, + target.method_name, ) def _uninstrument(self, **kwargs: Any) -> None: del kwargs self._handler = None - for module_name in get_installed_runner_modules(): + for target in get_installed_runtime_targets(): try: - runner_module = import_module(module_name) - unwrap(runner_module.AgentRunner, "query_handler") + runtime_module = import_module(target.module_name) + runtime_class = getattr(runtime_module, target.class_name) + unwrap(runtime_class, target.method_name) logger.debug( - "Uninstrumented %s.AgentRunner.query_handler", module_name + "Uninstrumented %s.%s.%s", + target.module_name, + target.class_name, + target.method_name, ) except Exception as exc: logger.warning( - "Failed to uninstrument %s.AgentRunner.query_handler: %s", - module_name, + "Failed to uninstrument %s.%s.%s: %s", + target.module_name, + target.class_name, + target.method_name, exc, ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/_entry_utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/_entry_utils.py index 751ec9900..ca9f148b1 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/_entry_utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/_entry_utils.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Build ``EntryInvocation`` from ``AgentRunner.query_handler`` call arguments.""" +"""Build QwenPaw ``EntryInvocation`` objects and message attributes.""" from __future__ import annotations @@ -29,6 +29,16 @@ def _non_empty_str(value: Any) -> str | None: return s if s else None +def _attribute(value: Any, name: str) -> Any: + if isinstance(value, dict): + return value.get(name) + return getattr(value, name, None) + + +def _enum_value(value: Any) -> Any: + return getattr(value, "value", value) + + def parse_query_handler_call( args: tuple[Any, ...], kwargs: dict[str, Any], @@ -47,6 +57,35 @@ def parse_query_handler_call( return msgs, request +def parse_runtime_call( + args: tuple[Any, ...], + kwargs: dict[str, Any], +) -> Any: + """Return the QwenPaw 2 ``AgentRequest`` passed to ``Runtime.run``.""" + + if args: + return args[0] + return kwargs.get("request") + + +def _message_text(message: Any) -> str | None: + if hasattr(message, "get_text_content"): + return _non_empty_str(message.get_text_content()) + + content = _attribute(message, "content") + if isinstance(content, str): + return _non_empty_str(content) + if not isinstance(content, (list, tuple)): + return None + + texts: list[str] = [] + for part in content: + text = _non_empty_str(_attribute(part, "text")) + if text: + texts.append(text) + return "\n".join(texts) or None + + def input_messages_from_msgs(msgs: Any) -> list[InputMessage]: """Turn AgentScope / runtime message list into ``InputMessage`` entries.""" if not msgs: @@ -55,19 +94,24 @@ def input_messages_from_msgs(msgs: Any) -> list[InputMessage]: msgs = [msgs] out: list[InputMessage] = [] for m in msgs: - role = getattr(m, "role", None) or "user" - if hasattr(m, "get_text_content"): - text = m.get_text_content() - if text: - out.append( - InputMessage( - role=role, - parts=[Text(content=text)], - ) + role = _enum_value(_attribute(m, "role")) or "user" + text = _message_text(m) + if text: + out.append( + InputMessage( + role=str(role), + parts=[Text(content=text)], ) + ) return out +def input_messages_from_runtime_request(request: Any) -> list[InputMessage]: + """Map QwenPaw 2 ``AgentRequest.input`` into GenAI input messages.""" + + return input_messages_from_msgs(_attribute(request, "input")) + + def output_message_from_yield_item(item: Any) -> OutputMessage | None: """If *item* is ``(Msg, last)`` with an assistant text message, map to output.""" if not isinstance(item, tuple) or not item: @@ -89,6 +133,42 @@ def output_message_from_yield_item(item: Any) -> OutputMessage | None: ) +def output_message_from_runtime_item(item: Any) -> OutputMessage | None: + """Map a completed QwenPaw 2 response/message envelope.""" + + candidates: list[Any] + if _attribute(item, "object") == "response": + output = _attribute(item, "output") + candidates = list(output) if isinstance(output, (list, tuple)) else [] + else: + candidates = [item] + + for message in reversed(candidates): + role = _enum_value(_attribute(message, "role")) + status = _enum_value(_attribute(message, "status")) + if role != "assistant" or status != "completed": + continue + text = _message_text(message) + if text: + return OutputMessage( + role="assistant", + parts=[Text(content=text)], + finish_reason="stop", + ) + return None + + +def _entry_attributes(agent_id: str | None, channel: str | None) -> dict: + extra_attrs: dict[str, Any] = {} + if agent_id: + extra_attrs["qwenpaw.agent_id"] = agent_id + extra_attrs["copaw.agent_id"] = agent_id + if channel: + extra_attrs["qwenpaw.channel"] = channel + extra_attrs["copaw.channel"] = channel + return extra_attrs + + def build_entry_invocation( instance: Any, msgs: Any, @@ -99,23 +179,34 @@ def build_entry_invocation( user_id = None channel = None if request is not None: - session_id = _non_empty_str(getattr(request, "session_id", None)) - user_id = _non_empty_str(getattr(request, "user_id", None)) - channel = _non_empty_str(getattr(request, "channel", None)) + session_id = _non_empty_str(_attribute(request, "session_id")) + user_id = _non_empty_str(_attribute(request, "user_id")) + channel = _non_empty_str(_attribute(request, "channel")) agent_id = _non_empty_str(getattr(instance, "agent_id", None)) - extra_attrs: dict[str, Any] = {} - if agent_id: - extra_attrs["qwenpaw.agent_id"] = agent_id - extra_attrs["copaw.agent_id"] = agent_id - if channel: - extra_attrs["qwenpaw.channel"] = channel - extra_attrs["copaw.channel"] = channel - return EntryInvocation( session_id=session_id, user_id=user_id, input_messages=input_messages_from_msgs(msgs), - attributes=extra_attrs, + attributes=_entry_attributes(agent_id, channel), + ) + + +def build_runtime_entry_invocation( + instance: Any, + request: Any, +) -> EntryInvocation: + """Build an Entry invocation for QwenPaw 2 ``Runtime.run``.""" + + workspace = getattr(instance, "workspace", None) + agent_id = _non_empty_str( + _attribute(request, "agent_id") or getattr(workspace, "agent_id", None) + ) + channel = _non_empty_str(_attribute(request, "channel")) + return EntryInvocation( + session_id=_non_empty_str(_attribute(request, "session_id")), + user_id=_non_empty_str(_attribute(request, "user_id")), + input_messages=input_messages_from_runtime_request(request), + attributes=_entry_attributes(agent_id, channel), ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/package.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/package.py index cf5352c64..4f58f473c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/package.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/package.py @@ -14,6 +14,7 @@ from __future__ import annotations +from dataclasses import dataclass from importlib.metadata import PackageNotFoundError, version from typing import Collection, Iterator @@ -21,32 +22,71 @@ _instruments = () _instruments_copaw = "copaw >= 0.1.0, <= 1.0.2" +_instruments_qwenpaw_v1 = "qwenpaw >= 1.1.0, < 2.0.0" +_instruments_qwenpaw_v2 = "qwenpaw >= 2.0.0" _instruments_qwenpaw = "qwenpaw >= 1.1.0" _instruments_any = (_instruments_qwenpaw, _instruments_copaw) + + +@dataclass(frozen=True) +class RuntimeTarget: + requirement: str + distribution_name: str + module_name: str + class_name: str + method_name: str + wrapper_kind: str + + _runtime_targets = ( - (_instruments_qwenpaw, "qwenpaw", "qwenpaw.app.runner.runner"), - (_instruments_copaw, "copaw", "copaw.app.runner.runner"), + RuntimeTarget( + _instruments_qwenpaw_v2, + "qwenpaw", + "qwenpaw.runtime.runtime", + "Runtime", + "run", + "runtime", + ), + RuntimeTarget( + _instruments_qwenpaw_v1, + "qwenpaw", + "qwenpaw.app.runner.runner", + "AgentRunner", + "query_handler", + "query_handler", + ), + RuntimeTarget( + _instruments_copaw, + "copaw", + "copaw.app.runner.runner", + "AgentRunner", + "query_handler", + "query_handler", + ), ) -def _get_matched_runtime_targets() -> Iterator[tuple[str, str, str]]: +def get_installed_runtime_targets() -> Iterator[RuntimeTarget]: for runtime_target in _runtime_targets: - requirement, distribution_name, _ = runtime_target try: - installed_version = version(distribution_name) + installed_version = version(runtime_target.distribution_name) except PackageNotFoundError: continue - if Requirement(requirement).specifier.contains(installed_version): + if Requirement(runtime_target.requirement).specifier.contains( + installed_version + ): yield runtime_target def get_installed_instrumentation_dependencies() -> Collection[str]: return tuple( - requirement for requirement, _, _ in _get_matched_runtime_targets() + target.requirement for target in get_installed_runtime_targets() ) def get_installed_runner_modules() -> Collection[str]: + """Return matched module names for compatibility with older callers.""" + return tuple( - module_name for _, _, module_name in _get_matched_runtime_targets() + target.module_name for target in get_installed_runtime_targets() ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/patch.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/patch.py index cb041914d..e13986074 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/patch.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/src/opentelemetry/instrumentation/qwenpaw/patch.py @@ -12,33 +12,260 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Wrap ``AgentRunner.query_handler`` with LoongSuite Entry telemetry.""" +"""Wrap QwenPaw request streams with task-safe LoongSuite Entry telemetry.""" from __future__ import annotations import logging import timeit -from typing import Any, Callable +from dataclasses import dataclass +from typing import Any, AsyncIterator, Callable +from opentelemetry import context as otel_context +from opentelemetry.context import Context +from opentelemetry.util.genai import hook_advice from opentelemetry.util.genai.extended_handler import ExtendedTelemetryHandler -from opentelemetry.util.genai.types import Error +from opentelemetry.util.genai.extended_types import EntryInvocation +from opentelemetry.util.genai.handler import _safe_detach +from opentelemetry.util.genai.types import Error, OutputMessage from ._entry_utils import ( build_entry_invocation, + build_runtime_entry_invocation, + output_message_from_runtime_item, output_message_from_yield_item, parse_query_handler_call, + parse_runtime_call, ) logger = logging.getLogger(__name__) -_PATCH_TARGET = "AgentRunner.query_handler" + +@dataclass +class _EntryState: + handler: ExtendedTelemetryHandler + invocation: EntryInvocation + context: Context + saw_first_token: bool = False + last_assistant: OutputMessage | None = None + finalized: bool = False + + +@hook_advice("qwenpaw", "build_entry") +def _build_entry( + factory: Callable[..., EntryInvocation], + *args: Any, +) -> EntryInvocation: + return factory(*args) + + +def _build_query_handler_entry( + instance: Any, + args: Any, + kwargs: Any, +) -> EntryInvocation: + msgs, request = parse_query_handler_call(args, kwargs) + return build_entry_invocation(instance, msgs, request) + + +def _build_runtime_entry( + instance: Any, + args: Any, + kwargs: Any, +) -> EntryInvocation: + request = parse_runtime_call(args, kwargs) + return build_runtime_entry_invocation(instance, request) + + +@hook_advice("qwenpaw", "start_entry") +def _start_entry( + handler: ExtendedTelemetryHandler, + invocation: EntryInvocation, +) -> _EntryState: + """Start Entry, save its Context, then detach before stream ownership moves.""" + + try: + handler.start_entry(invocation) + entry_context = otel_context.get_current() + except Exception: + token = invocation.context_token + invocation.context_token = None + _safe_detach(token) + span = invocation.span + if span is not None and span.is_recording(): + span.end() + raise + + token = invocation.context_token + invocation.context_token = None + _safe_detach(token) + return _EntryState( + handler=handler, + invocation=invocation, + context=entry_context, + ) + + +@hook_advice("qwenpaw", "attach_entry") +def _attach_entry(state: _EntryState) -> object: + return otel_context.attach(state.context) + + +@hook_advice("qwenpaw", "detach_entry") +def _detach_entry(token: object | None) -> None: + _safe_detach(token) + + +@hook_advice("qwenpaw", "record_entry_first_token") +def _record_entry_first_token( + state: _EntryState, + item: Any, + first_token_predicate: Callable[[Any], bool], +) -> None: + if not state.saw_first_token and first_token_predicate(item): + state.invocation.response_time_to_first_token = int( + (timeit.default_timer() - state.invocation.monotonic_start_s) + * 1_000_000_000 + ) + state.saw_first_token = True + + +@hook_advice("qwenpaw", "record_entry_output") +def _record_entry_output( + state: _EntryState, + item: Any, + output_mapper: Callable[[Any], OutputMessage | None], +) -> None: + output = output_mapper(item) + if output is not None: + state.last_assistant = output + + +def _is_query_handler_first_token(item: Any) -> bool: + del item + return True + + +def _is_runtime_first_token(item: Any) -> bool: + """Ignore QwenPaw protocol envelopes until user-visible output arrives.""" + + if getattr(item, "delta", False) is True: + text = getattr(item, "text", None) + if isinstance(text, str) and text: + return True + + data = getattr(item, "data", None) + if isinstance(data, dict): + arguments = data.get("arguments") + if isinstance(arguments, str) and arguments: + return True + + return output_message_from_runtime_item(item) is not None + + +@hook_advice("qwenpaw", "finish_entry") +def _finish_entry( + state: _EntryState, + error: BaseException | None = None, +) -> None: + """Finalize once, with cleanup even if handler post-processing fails.""" + + if state.finalized: + return + state.finalized = True + + invocation = state.invocation + if state.last_assistant is not None: + invocation.output_messages = [state.last_assistant] + + token = None + span = invocation.span + try: + token = otel_context.attach(state.context) + invocation.context_token = token + if error is None or isinstance(error, GeneratorExit): + state.handler.stop_entry(invocation) + else: + state.handler.fail_entry( + invocation, + Error( + message=str(error) or type(error).__name__, + type=type(error), + ), + ) + finally: + invocation.context_token = None + if span is not None and span.is_recording(): + _safe_detach(token) + span.end() + + +async def _close_iterator(iterator: AsyncIterator[Any]) -> None: + close = getattr(iterator, "aclose", None) + if close is not None: + await close() + + +async def _entry_stream( + wrapped: Any, + args: Any, + kwargs: Any, + handler: ExtendedTelemetryHandler, + invocation: EntryInvocation, + first_token_predicate: Callable[[Any], bool], + output_mapper: Callable[[Any], OutputMessage | None], +) -> AsyncIterator[Any]: + """Advance one business item per same-Context Entry attach/detach pair.""" + + business_stream = wrapped(*args, **kwargs) + iterator = business_stream.__aiter__() + state = _start_entry(handler, invocation) + if state is None: + try: + async for item in iterator: + yield item + except GeneratorExit: + await _close_iterator(iterator) + raise + return + + try: + while True: + token = _attach_entry(state) + try: + item = await iterator.__anext__() + except StopAsyncIteration: + break + finally: + _detach_entry(token) + + _record_entry_first_token(state, item, first_token_predicate) + _record_entry_output(state, item, output_mapper) + yield item + except GeneratorExit as exc: + token = _attach_entry(state) + try: + await _close_iterator(iterator) + except BaseException as close_error: + _finish_entry(state, close_error) + raise + finally: + _detach_entry(token) + _finish_entry(state, exc) + raise + except BaseException as exc: + _finish_entry(state, exc) + raise + finally: + if not state.finalized: + _finish_entry(state) def make_query_handler_wrapper( handler: ExtendedTelemetryHandler, module_name: str, ) -> Callable[..., Any]: - """Factory for ``wrapt`` wrapper bound to *handler*.""" + """Wrap QwenPaw 1 / CoPaw ``AgentRunner.query_handler``.""" def query_handler_wrapper( wrapped: Any, @@ -46,52 +273,57 @@ def query_handler_wrapper( args: Any, kwargs: Any, ) -> Any: - async def _aiter(): - msgs, request = parse_query_handler_call(args, kwargs) - invocation = build_entry_invocation(instance, msgs, request) - handler.start_entry(invocation) - monotonic_start = timeit.default_timer() - saw_first_token = False - last_assistant = None - try: - agen = wrapped(*args, **kwargs) - async for item in agen: - if not saw_first_token: - invocation.response_time_to_first_token = int( - (timeit.default_timer() - monotonic_start) - * 1_000_000_000 - ) - saw_first_token = True - out = output_message_from_yield_item(item) - if out is not None: - last_assistant = out - yield item - except BaseException as exc: - if isinstance(exc, GeneratorExit): - if last_assistant is not None: - invocation.output_messages = [last_assistant] - handler.stop_entry(invocation) - raise - logger.debug( - "%s.%s raised %s", - module_name, - _PATCH_TARGET, - type(exc).__name__, - exc_info=True, - ) - handler.fail_entry( - invocation, - Error( - message=str(exc) or type(exc).__name__, - type=type(exc), - ), - ) - raise - else: - if last_assistant is not None: - invocation.output_messages = [last_assistant] - handler.stop_entry(invocation) - - return _aiter() + invocation = _build_entry( + _build_query_handler_entry, + instance, + args, + kwargs, + ) + if invocation is None: + return wrapped(*args, **kwargs) + logger.debug("Tracing %s.AgentRunner.query_handler", module_name) + return _entry_stream( + wrapped, + args, + kwargs, + handler, + invocation, + _is_query_handler_first_token, + output_message_from_yield_item, + ) return query_handler_wrapper + + +def make_runtime_wrapper( + handler: ExtendedTelemetryHandler, + module_name: str, +) -> Callable[..., Any]: + """Wrap QwenPaw 2 ``Runtime.run`` as one Entry span per request.""" + + def runtime_wrapper( + wrapped: Any, + instance: Any, + args: Any, + kwargs: Any, + ) -> Any: + invocation = _build_entry( + _build_runtime_entry, + instance, + args, + kwargs, + ) + if invocation is None: + return wrapped(*args, **kwargs) + logger.debug("Tracing %s.Runtime.run", module_name) + return _entry_stream( + wrapped, + args, + kwargs, + handler, + invocation, + _is_runtime_first_token, + output_message_from_runtime_item, + ) + + return runtime_wrapper diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/conftest.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/conftest.py index f3b541696..b6ad1ac56 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/conftest.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/conftest.py @@ -69,3 +69,11 @@ def _import_runner_module(): @pytest.fixture(name="runner_module") def fixture_runner_module(): return _import_runner_module() + + +@pytest.fixture(name="runtime_module") +def fixture_runtime_module(): + try: + return importlib.import_module("qwenpaw.runtime.runtime") + except ImportError: + pytest.skip("QwenPaw 2 runtime is not installed") diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.latest.txt b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.latest.txt index 0d6b211fb..0c905102b 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.latest.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.latest.txt @@ -12,10 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This variant of the requirements aims to test the system using -# the latest supported QwenPaw runtime. +# This variant tests the latest supported QwenPaw 2 runtime. -qwenpaw==1.1.12.post3 +qwenpaw==2.0.1 pytest pytest-asyncio wrapt<2.0.0 @@ -24,5 +23,6 @@ opentelemetry-sdk opentelemetry-semantic-conventions opentelemetry-instrumentation +-e instrumentation-loongsuite/loongsuite-instrumentation-agentscope -e instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw -e util/opentelemetry-util-genai diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.oldest.txt b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.oldest.txt index 79481ca1b..d9ec1ad6e 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.oldest.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.oldest.txt @@ -16,6 +16,7 @@ # the last supported legacy runtime. copaw==1.0.2 +mcp<2 pytest pytest-asyncio wrapt diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.v1.txt b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.v1.txt new file mode 100644 index 000000000..53b19c512 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.v1.txt @@ -0,0 +1,28 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This variant tests the latest supported QwenPaw 1 runtime. + +qwenpaw==1.1.12.post3 +mcp<2 +pytest +pytest-asyncio +wrapt<2.0.0 +opentelemetry-api +opentelemetry-sdk +opentelemetry-semantic-conventions +opentelemetry-instrumentation + +-e instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw +-e util/opentelemetry-util-genai diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_compatibility.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_compatibility.py index 6d4e826b6..b71a509c8 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_compatibility.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_compatibility.py @@ -26,6 +26,7 @@ from opentelemetry.instrumentation.qwenpaw.package import ( get_installed_instrumentation_dependencies, get_installed_runner_modules, + get_installed_runtime_targets, ) @@ -41,6 +42,12 @@ def _fake_copaw_version(name): raise importlib.metadata.PackageNotFoundError +def _fake_qwenpaw_v2_version(name): + if name == "qwenpaw": + return "2.0.0.post4" + raise importlib.metadata.PackageNotFoundError + + def test_runtime_detection_prefers_installed_qwenpaw(monkeypatch): monkeypatch.setattr( "opentelemetry.instrumentation.qwenpaw.package.version", @@ -48,13 +55,29 @@ def test_runtime_detection_prefers_installed_qwenpaw(monkeypatch): ) assert get_installed_instrumentation_dependencies() == ( - "qwenpaw >= 1.1.0", + "qwenpaw >= 1.1.0, < 2.0.0", ) assert get_installed_runner_modules() == ("qwenpaw.app.runner.runner",) assert CoPawInstrumentor().instrumentation_dependencies() == ( - "qwenpaw >= 1.1.0", + "qwenpaw >= 1.1.0, < 2.0.0", + ) + + +def test_runtime_detection_uses_qwenpaw_v2_runtime(monkeypatch): + monkeypatch.setattr( + "opentelemetry.instrumentation.qwenpaw.package.version", + _fake_qwenpaw_v2_version, ) + assert get_installed_instrumentation_dependencies() == ( + "qwenpaw >= 2.0.0", + ) + [target] = get_installed_runtime_targets() + assert target.module_name == "qwenpaw.runtime.runtime" + assert target.class_name == "Runtime" + assert target.method_name == "run" + assert target.wrapper_kind == "runtime" + def test_runtime_detection_falls_back_to_legacy_copaw(monkeypatch): monkeypatch.setattr( @@ -77,8 +100,8 @@ def test_uninstrument_handles_qwenpaw_runner(monkeypatch): unwrap_calls = [] monkeypatch.setattr( - "opentelemetry.instrumentation.qwenpaw.get_installed_runner_modules", - lambda: ("qwenpaw.app.runner.runner",), + "opentelemetry.instrumentation.qwenpaw.package.version", + _fake_qwenpaw_version, ) monkeypatch.setattr( "opentelemetry.instrumentation.qwenpaw.import_module", diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_runtime_v2.py b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_runtime_v2.py new file mode 100644 index 000000000..be6766317 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/test_runtime_v2.py @@ -0,0 +1,670 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""QwenPaw 2 ``Runtime.run`` Entry lifecycle and isolation tests.""" + +from __future__ import annotations + +import asyncio +import json +from types import SimpleNamespace + +import pytest + +pytest.importorskip( + "opentelemetry.instrumentation.agentscope._v2_middleware", + reason="QwenPaw 2 runtime tests require AgentScope v2 instrumentation", +) + +from agentscope.message import TextBlock +from agentscope.model import ChatModelBase, ChatResponse +from agentscope.tool import ToolResponse + +from opentelemetry import trace +from opentelemetry.instrumentation.agentscope._v2_middleware import ( + AgentScopeV2Middleware, +) +from opentelemetry.instrumentation.qwenpaw import QwenPawInstrumentor +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAI, +) +from opentelemetry.util.genai.extended_semconv.gen_ai_extended_attributes import ( + GEN_AI_RESPONSE_TIME_TO_FIRST_TOKEN, + GEN_AI_SESSION_ID, + GEN_AI_USER_ID, +) + + +def _request(session_id: str, text: str = "hello"): + return SimpleNamespace( + session_id=session_id, + user_id=f"user-{session_id}", + channel="console", + input=[ + SimpleNamespace( + role="user", + content=[SimpleNamespace(text=text)], + ) + ], + ) + + +def _completed_message(text: str): + return SimpleNamespace( + object="message", + role="assistant", + status="completed", + content=[SimpleNamespace(text=text)], + ) + + +def _runtime(runtime_module, agent_id: str = "v2-agent"): + return runtime_module.Runtime( + workspace=SimpleNamespace(agent_id=agent_id), + app_services=None, + ) + + +def _instrument(tracer_provider): + instrumentor = QwenPawInstrumentor() + instrumentor.instrument( + skip_dep_check=True, + tracer_provider=tracer_provider, + ) + return instrumentor + + +async def _task_next(stream): + async def advance(): + return await stream.__anext__() + + return await asyncio.create_task(advance()) + + +def _entry_spans(span_exporter): + return [ + span + for span in span_exporter.get_finished_spans() + if span.name == "enter_ai_application_system" + ] + + +@pytest.mark.asyncio +async def test_runtime_entry_parents_heartbeat_child_across_tasks( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + child_tracer = trace.get_tracer( + "qwenpaw-v2-test", + tracer_provider=tracer_provider, + ) + expected = _completed_message("done") + + async def fake_run(self, request): + del self, request + + async def heartbeat_child(): + with child_tracer.start_as_current_span("invoke_agent"): + return expected + + yield await asyncio.create_task(heartbeat_child()) + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + stream = ( + _runtime(runtime_module).run(_request("session-1")).__aiter__() + ) + assert await _task_next(stream) is expected + with pytest.raises(StopAsyncIteration): + await _task_next(stream) + finally: + instrumentor.uninstrument() + + spans = span_exporter.get_finished_spans() + [entry] = [ + span for span in spans if span.name == "enter_ai_application_system" + ] + [agent] = [span for span in spans if span.name == "invoke_agent"] + assert agent.context.trace_id == entry.context.trace_id + assert agent.parent.span_id == entry.context.span_id + assert not trace.get_current_span().get_span_context().is_valid + assert entry.attributes[GEN_AI_SESSION_ID] == "session-1" + assert entry.attributes[GEN_AI_USER_ID] == "user-session-1" + assert entry.attributes["qwenpaw.agent_id"] == "v2-agent" + assert entry.attributes["qwenpaw.channel"] == "console" + + +@pytest.mark.asyncio +async def test_runtime_sequential_requests_finish_as_separate_traces( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + child_tracer = trace.get_tracer( + "qwenpaw-v2-test", + tracer_provider=tracer_provider, + ) + + async def fake_run(self, request): + del self + with child_tracer.start_as_current_span("invoke_agent"): + yield _completed_message(request.session_id) + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + runtime = _runtime(runtime_module) + for session_id in ("session-a", "session-b"): + chunks = [item async for item in runtime.run(_request(session_id))] + assert len(chunks) == 1 + assert len(_entry_spans(span_exporter)) == ( + 1 if session_id == "session-a" else 2 + ) + finally: + instrumentor.uninstrument() + + entries = _entry_spans(span_exporter) + assert len(entries) == 2 + assert len({span.context.trace_id for span in entries}) == 2 + + +@pytest.mark.asyncio +async def test_runtime_entry_captures_v2_input_and_output( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + monkeypatch.setenv( + "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT", + "SPAN_ONLY", + ) + expected = _completed_message("v2-output") + + async def fake_run(self, request): + del self, request + yield expected + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + chunks = [ + item + async for item in _runtime(runtime_module).run( + _request("content-session", "v2-input") + ) + ] + assert chunks == [expected] + finally: + instrumentor.uninstrument() + + [entry] = _entry_spans(span_exporter) + input_messages = json.loads(entry.attributes[GenAI.GEN_AI_INPUT_MESSAGES]) + output_messages = json.loads( + entry.attributes[GenAI.GEN_AI_OUTPUT_MESSAGES] + ) + assert input_messages[0]["parts"][0]["content"] == "v2-input" + assert output_messages[0]["parts"][0]["content"] == "v2-output" + + +@pytest.mark.asyncio +async def test_runtime_ttft_ignores_protocol_and_heartbeat_envelopes( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + created = SimpleNamespace(object="response", status="created", output=[]) + heartbeat = SimpleNamespace( + object="response", + status="in_progress", + output=[], + ) + first_delta = SimpleNamespace(delta=True, text="first token") + expected = _completed_message("done") + + async def fake_run(self, request): + del self, request + yield created + yield heartbeat + yield first_delta + yield expected + + timer_values = iter((10.0, 10.5, 11.0)) + monkeypatch.setattr( + "opentelemetry.instrumentation.qwenpaw.patch.timeit.default_timer", + lambda: next(timer_values), + ) + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + chunks = [ + item + async for item in _runtime(runtime_module).run( + _request("ttft-session") + ) + ] + finally: + instrumentor.uninstrument() + + assert chunks == [created, heartbeat, first_delta, expected] + [entry] = _entry_spans(span_exporter) + assert entry.attributes[GEN_AI_RESPONSE_TIME_TO_FIRST_TOKEN] == 500_000_000 + + +@pytest.mark.asyncio +async def test_runtime_preserves_business_error_when_fail_callback_fails( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + business_error = RuntimeError("business failure") + + async def fake_run(self, request): + del self, request + yield _completed_message("partial") + raise business_error + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + + def fail_entry(*args, **kwargs): + del args, kwargs + raise ValueError("probe failure") + + monkeypatch.setattr(instrumentor._handler, "fail_entry", fail_entry) + try: + stream = _runtime(runtime_module).run(_request("error-session")) + iterator = stream.__aiter__() + await iterator.__anext__() + try: + await iterator.__anext__() + except RuntimeError as exc: + assert exc is business_error + else: + pytest.fail("business error was not raised") + finally: + instrumentor.uninstrument() + + assert len(_entry_spans(span_exporter)) == 1 + + +@pytest.mark.asyncio +async def test_runtime_start_failure_preserves_business_chunks( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + expected = _completed_message("business-result") + calls = 0 + + async def fake_run(self, request): + nonlocal calls + del self, request + calls += 1 + yield expected + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + original_start_entry = instrumentor._handler.start_entry + + def start_entry(*args, **kwargs): + del args, kwargs + raise ValueError("probe start failure") + + monkeypatch.setattr(instrumentor._handler, "start_entry", start_entry) + try: + chunks = [ + item + async for item in _runtime(runtime_module).run( + _request("start-failure") + ) + ] + monkeypatch.setattr( + instrumentor._handler, + "start_entry", + original_start_entry, + ) + clean_chunks = [ + item + async for item in _runtime(runtime_module).run( + _request("clean-sibling") + ) + ] + finally: + instrumentor.uninstrument() + + assert calls == 2 + assert chunks == [expected] + assert clean_chunks == [expected] + assert len(_entry_spans(span_exporter)) == 1 + + +@pytest.mark.asyncio +async def test_runtime_start_failure_aclose_closes_business_stream_once( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + expected = _completed_message("first") + closed = 0 + + async def fake_run(self, request): + nonlocal closed + del self, request + try: + yield expected + yield _completed_message("second") + finally: + closed += 1 + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + + def start_entry(*args, **kwargs): + del args, kwargs + raise ValueError("probe start failure") + + monkeypatch.setattr(instrumentor._handler, "start_entry", start_entry) + try: + stream = _runtime(runtime_module).run(_request("start-failure-close")) + assert await stream.__anext__() is expected + await asyncio.create_task(stream.aclose()) + finally: + instrumentor.uninstrument() + + assert closed == 1 + assert len(_entry_spans(span_exporter)) == 0 + assert not trace.get_current_span().get_span_context().is_valid + + +@pytest.mark.asyncio +async def test_runtime_mapping_and_stop_failures_preserve_business_chunks( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + expected = _completed_message("business-result") + + async def fake_run(self, request): + del self, request + yield expected + + def map_output(item): + del item + raise ValueError("probe mapping failure") + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + monkeypatch.setattr( + "opentelemetry.instrumentation.qwenpaw.patch." + "output_message_from_runtime_item", + map_output, + ) + instrumentor = _instrument(tracer_provider) + + def stop_entry(*args, **kwargs): + del args, kwargs + raise ValueError("probe stop failure") + + monkeypatch.setattr(instrumentor._handler, "stop_entry", stop_entry) + try: + chunks = [ + item + async for item in _runtime(runtime_module).run( + _request("stop-failure") + ) + ] + finally: + instrumentor.uninstrument() + + assert chunks == [expected] + assert len(_entry_spans(span_exporter)) == 1 + + +@pytest.mark.asyncio +async def test_runtime_cancellation_finishes_entry( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + started = asyncio.Event() + never = asyncio.Event() + + async def fake_run(self, request): + del self, request + started.set() + await never.wait() + yield None + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + stream = _runtime(runtime_module).run(_request("cancel-session")) + task = asyncio.create_task(stream.__anext__()) + await started.wait() + task.cancel() + with pytest.raises(asyncio.CancelledError): + await task + finally: + instrumentor.uninstrument() + + assert len(_entry_spans(span_exporter)) == 1 + + +@pytest.mark.asyncio +async def test_runtime_aclose_closes_business_stream_once( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + expected = _completed_message("first") + closed = 0 + + async def fake_run(self, request): + nonlocal closed + del self, request + try: + yield expected + yield _completed_message("second") + finally: + closed += 1 + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + stream = _runtime(runtime_module).run(_request("close-session")) + assert await stream.__anext__() is expected + await asyncio.create_task(stream.aclose()) + finally: + instrumentor.uninstrument() + + assert closed == 1 + assert len(_entry_spans(span_exporter)) == 1 + assert not trace.get_current_span().get_span_context().is_valid + + +@pytest.mark.asyncio +async def test_runtime_aclose_preserves_agentscope_tree_and_success_status( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, + caplog, +): + caplog.set_level("DEBUG", logger="opentelemetry.util.genai.handler") + model = object.__new__(ChatModelBase) + model.model = "test-model" + model.parameters = None + agent = SimpleNamespace( + name="combined-agent", + model=model, + state=SimpleNamespace(cur_iter=0, session_id="combined-session"), + _system_prompt="Use the tool.", + ) + tool_call = SimpleNamespace( + name="successful_tool", + id="tool-call-combined", + input="{}", + ) + agent_middleware = None + + async def model_handler(**kwargs): + del kwargs + return ChatResponse( + content=[TextBlock(text="Use the tool.")], + is_last=True, + ) + + async def tool_handler(**kwargs): + del kwargs + yield ToolResponse(content=[TextBlock(text="success")]) + yield ToolResponse(content=[TextBlock(text="unused")]) + + async def reply_handler(**kwargs): + del kwargs + assert agent_middleware is not None + await agent_middleware.on_model_call( + agent, + { + "current_model": model, + "messages": [], + }, + model_handler, + ) + acting_stream = agent_middleware.on_acting( + agent, + {"tool_call": tool_call}, + tool_handler, + ) + try: + async for item in acting_stream: + yield item + except GeneratorExit: + await acting_stream.aclose() + raise + + async def fake_run(self, request): + del self, request + assert agent_middleware is not None + reply_stream = agent_middleware.on_reply( + agent, + {"inputs": []}, + reply_handler, + ) + try: + async for item in reply_stream: + yield item + except GeneratorExit: + await reply_stream.aclose() + raise + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + monkeypatch.setattr( + instrumentor._handler, + "process_multimodal_stop", + lambda *args, **kwargs: False, + ) + agent_middleware = AgentScopeV2Middleware(lambda: instrumentor._handler) + try: + stream = _runtime(runtime_module).run( + _request("combined-runtime-close") + ) + first = await asyncio.create_task(stream.__anext__()) + assert isinstance(first, ToolResponse) + await asyncio.create_task(stream.aclose()) + finally: + instrumentor.uninstrument() + + spans = span_exporter.get_finished_spans() + [entry] = _entry_spans(span_exporter) + [agent_span] = [ + span + for span in spans + if span.attributes.get("gen_ai.operation.name") == "invoke_agent" + ] + [llm_span] = [ + span + for span in spans + if span.attributes.get("gen_ai.operation.name") == "chat" + ] + [react_span] = [ + span + for span in spans + if span.attributes.get("gen_ai.operation.name") == "react" + ] + [tool_span] = [ + span + for span in spans + if span.attributes.get("gen_ai.operation.name") == "execute_tool" + ] + + assert agent_span.parent.span_id == entry.context.span_id + assert llm_span.parent.span_id == agent_span.context.span_id + assert react_span.parent.span_id == agent_span.context.span_id + assert tool_span.parent.span_id == react_span.context.span_id + for span in (entry, agent_span, llm_span, react_span, tool_span): + assert span.status.status_code.name == "UNSET" + assert "error.type" not in span.attributes + assert not any( + "Context detach failed" in record.getMessage() + or "Failed to detach context" in record.getMessage() + for record in caplog.records + ) + assert not trace.get_current_span().get_span_context().is_valid + + +@pytest.mark.asyncio +async def test_runtime_aclose_error_still_finishes_entry( + runtime_module, + tracer_provider, + span_exporter, + monkeypatch, +): + close_error = ValueError("business close failure") + + async def fake_run(self, request): + del self, request + try: + yield _completed_message("first") + finally: + raise close_error + + monkeypatch.setattr(runtime_module.Runtime, "run", fake_run) + instrumentor = _instrument(tracer_provider) + try: + stream = _runtime(runtime_module).run(_request("close-error")) + await stream.__anext__() + try: + await stream.aclose() + except ValueError as exc: + assert exc is close_error + else: + pytest.fail("business close error was not raised") + finally: + instrumentor.uninstrument() + + [entry] = _entry_spans(span_exporter) + assert entry.status.status_code.name == "ERROR" + assert entry.attributes["error.type"] == "ValueError" diff --git a/tox-loongsuite.ini b/tox-loongsuite.ini index 1c64bb97e..51ccf7b06 100644 --- a/tox-loongsuite.ini +++ b/tox-loongsuite.ini @@ -96,7 +96,8 @@ envlist = lint-loongsuite-instrumentation-crewai ; loongsuite-instrumentation-qwenpaw - py3{10,11,12,13}-test-loongsuite-instrumentation-qwenpaw-{latest,legacy} + py3{11,12,13}-test-loongsuite-instrumentation-qwenpaw-latest + py3{10,11,12,13}-test-loongsuite-instrumentation-qwenpaw-{v1,legacy} lint-loongsuite-instrumentation-qwenpaw ; loongsuite-instrumentation-algotune @@ -233,6 +234,7 @@ deps = crewai: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test-requirements.txt qwenpaw-latest: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.latest.txt + qwenpaw-v1: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.v1.txt qwenpaw-legacy: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.oldest.txt lint-loongsuite-instrumentation-qwenpaw: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-qwenpaw/tests/requirements.latest.txt