From 22148e26083d27026e6b3f5c22c816dd62fd13c3 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 13 May 2026 18:17:55 -0700 Subject: [PATCH 01/10] add conformance testing based on weaver live check --- .../instrumentation.instructions.md | 6 + .github/renovate.json5 | 12 + .../src/generate_workflows_lib/__init__.py | 1 + .../src/generate_workflows_lib/test.yml.j2 | 41 + .github/workflows/test.yml | 210 +++ .gitignore | 7 + AGENTS.md | 19 + dev-requirements-conformance.txt | 12 + .../pyproject.toml | 3 + .../cassettes/inference-conformance.yaml | 140 ++ .../cassettes/tool_calling-conformance.yaml | 168 ++ .../tests/conformance/__init__.py | 2 + .../tests/conformance/inference.py | 61 + .../tests/conformance/tool_calling.py | 75 + .../tests/conftest.py | 5 +- .../tests/test_conformance.py | 39 + .../cassettes/inference-conformance.yaml | 161 ++ .../tests/conformance/__init__.py | 2 + .../tests/conformance/inference.py | 72 + .../tests/test_conformance.py | 33 + .../cassettes/embedding-conformance.yaml | 1652 +++++++++++++++++ .../cassettes/inference-conformance.yaml | 134 ++ .../cassettes/tool_calling-conformance.yaml | 342 ++++ .../tests/conformance/__init__.py | 2 + .../tests/conformance/embedding.py | 46 + .../tests/conformance/inference.py | 47 + .../tests/conformance/tool_calling.py | 127 ++ .../tests/conftest.py | 5 +- .../tests/test_conformance.py | 47 + policies/genai_content_validation.rego | 53 + policies/genai_span_validation.rego | 246 +++ pyproject.toml | 13 + pytest.ini | 2 + tox.ini | 23 +- .../pyproject.toml | 3 + .../test_util_genai/_setup_weaver.py | 164 ++ .../test_util_genai/conformance.py | 189 ++ .../opentelemetry/test_util_genai/fixtures.py | 65 +- .../src/opentelemetry/test_util_genai/vcr.py | 14 - uv.lock | 358 ++-- versions.env | 8 + 41 files changed, 4424 insertions(+), 185 deletions(-) create mode 100644 dev-requirements-conformance.txt create mode 100644 instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference-conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling-conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py create mode 100644 instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py create mode 100644 instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py create mode 100644 instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference-conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py create mode 100644 instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding-conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference-conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling-conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py create mode 100644 instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py create mode 100644 policies/genai_content_validation.rego create mode 100644 policies/genai_span_validation.rego create mode 100644 util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py create mode 100644 util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py create mode 100644 versions.env diff --git a/.github/instructions/instrumentation.instructions.md b/.github/instructions/instrumentation.instructions.md index 717170ee..4163838b 100644 --- a/.github/instructions/instrumentation.instructions.md +++ b/.github/instructions/instrumentation.instructions.md @@ -69,6 +69,12 @@ prefer opt-in or additive. Breaking changes need explicit justification in the P (`from opentelemetry.test_util_genai.fixtures import *` and `from opentelemetry.test_util_genai.vcr import fixture_vcr, scrub_response_headers`). Do not re-implement in-memory provider/exporter setup or the VCR pretty-print serializer locally. +- Conformance: packages ship `tests/conformance/.py` modules (each + defining a subclass of + `opentelemetry.test_util_genai.conformance.Scenario` that sets + `expected_spans`, `expected_metrics`, and implements `run(...)`) and a + `tests/test_conformance.py` that runs them via + `opentelemetry.test_util_genai.conformance.run_conformance`. ## 6. Examples diff --git a/.github/renovate.json5 b/.github/renovate.json5 index af03085a..2c0d8fe0 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -13,6 +13,18 @@ // requirements.latest.txt files are skipped without this. "managerFilePatterns": ["/(^|/)requirements\\.latest\\.txt$/"] }, + // Manage WEAVER_VERSION and SEMCONV_VERSION in versions.env via their + // `# renovate:` annotations. + "customManagers": [ + { + "customType": "regex", + "managerFilePatterns": ["/^versions\\.env$/"], + "matchStrings": [ + "# renovate: datasource=(?\\S+) depName=(?\\S+) versioning=(?\\S+)\\s+WEAVER_VERSION=(?\\S+)", + "# renovate: datasource=(?\\S+) depName=(?\\S+) versioning=(?\\S+)\\s+SEMCONV_VERSION=(?\\S+)" + ] + } + ], "packageRules": [ { "groupName": "all patch versions", diff --git a/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/__init__.py b/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/__init__.py index 054508fa..5843196f 100644 --- a/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/__init__.py +++ b/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/__init__.py @@ -88,6 +88,7 @@ def get_test_job_datas(tox_envs: list, operating_systems: list) -> list: "python_version": aliased_python_version, "tox_env": tox_env, "os": operating_system, + "needs_weaver": tox_env.endswith("-conformance"), } ) diff --git a/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/test.yml.j2 b/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/test.yml.j2 index 5002f85f..1d8a1420 100644 --- a/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/test.yml.j2 +++ b/.github/workflows/generate_workflows_lib/src/generate_workflows_lib/test.yml.j2 @@ -45,6 +45,47 @@ jobs: - name: Configure git to support long filenames run: git config --system core.longpaths true {%- endif %} + {%- if job_data.needs_weaver %} + + - name: Read pinned weaver version + id: versions + {%- if job_data.os == "windows-latest" %} + shell: pwsh + run: | + Select-String -Path versions.env -Pattern '^WEAVER_VERSION=' | ForEach-Object { $_.Line } | Add-Content $env:GITHUB_OUTPUT + {%- else %} + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + {%- endif %} + + - name: Install weaver ${% raw %}{{ steps.versions.outputs.WEAVER_VERSION }}{% endraw %} + env: + WEAVER_VERSION: ${% raw %}{{ steps.versions.outputs.WEAVER_VERSION }}{% endraw %} + {%- if job_data.os == "windows-latest" %} + shell: pwsh + run: | + $url = "https://github.com/open-telemetry/weaver/releases/download/$env:WEAVER_VERSION/weaver-x86_64-pc-windows-msvc.zip" + Invoke-WebRequest -Uri $url -OutFile "$env:RUNNER_TEMP\weaver.zip" + Expand-Archive -Path "$env:RUNNER_TEMP\weaver.zip" -DestinationPath "$env:RUNNER_TEMP\weaver" + "$env:RUNNER_TEMP\weaver" | Add-Content $env:GITHUB_PATH + & "$env:RUNNER_TEMP\weaver\weaver.exe" --version + {%- elif job_data.os == "macos-latest" %} + run: | + WEAVER_ASSET="weaver-aarch64-apple-darwin" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + {%- else %} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + {%- endif %} + {%- endif %} - name: Run tests run: tox -e {{ job_data.tox_env }} -- -ra diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 554656fa..feeaa209 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -252,6 +252,76 @@ jobs: - name: Run tests run: tox -e pypy3-test-instrumentation-openai-v2-latest -- -ra + py312-test-instrumentation-openai-v2-conformance_ubuntu-latest: + name: instrumentation-openai-v2-conformance 3.12 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install tox + run: pip install tox-uv + + - name: Read pinned weaver version + id: versions + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + + - name: Install weaver ${{ steps.versions.outputs.WEAVER_VERSION }} + env: + WEAVER_VERSION: ${{ steps.versions.outputs.WEAVER_VERSION }} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + + - name: Run tests + run: tox -e py312-test-instrumentation-openai-v2-conformance -- -ra + + py313-test-instrumentation-openai-v2-conformance_ubuntu-latest: + name: instrumentation-openai-v2-conformance 3.13 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install tox + run: pip install tox-uv + + - name: Read pinned weaver version + id: versions + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + + - name: Install weaver ${{ steps.versions.outputs.WEAVER_VERSION }} + env: + WEAVER_VERSION: ${{ steps.versions.outputs.WEAVER_VERSION }} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + + - name: Run tests + run: tox -e py313-test-instrumentation-openai-v2-conformance -- -ra + py310-test-instrumentation-openai_agents-v2-oldest_ubuntu-latest: name: instrumentation-openai_agents-v2-oldest 3.10 Ubuntu runs-on: ubuntu-latest @@ -822,6 +892,76 @@ jobs: - name: Run tests run: tox -e py314-test-instrumentation-anthropic-latest -- -ra + py312-test-instrumentation-anthropic-conformance_ubuntu-latest: + name: instrumentation-anthropic-conformance 3.12 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install tox + run: pip install tox-uv + + - name: Read pinned weaver version + id: versions + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + + - name: Install weaver ${{ steps.versions.outputs.WEAVER_VERSION }} + env: + WEAVER_VERSION: ${{ steps.versions.outputs.WEAVER_VERSION }} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + + - name: Run tests + run: tox -e py312-test-instrumentation-anthropic-conformance -- -ra + + py313-test-instrumentation-anthropic-conformance_ubuntu-latest: + name: instrumentation-anthropic-conformance 3.13 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install tox + run: pip install tox-uv + + - name: Read pinned weaver version + id: versions + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + + - name: Install weaver ${{ steps.versions.outputs.WEAVER_VERSION }} + env: + WEAVER_VERSION: ${{ steps.versions.outputs.WEAVER_VERSION }} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + + - name: Run tests + run: tox -e py313-test-instrumentation-anthropic-conformance -- -ra + py310-test-instrumentation-claude-agent-sdk-oldest_ubuntu-latest: name: instrumentation-claude-agent-sdk-oldest 3.10 Ubuntu runs-on: ubuntu-latest @@ -974,6 +1114,76 @@ jobs: - name: Run tests run: tox -e py313-test-instrumentation-claude-agent-sdk-latest -- -ra + py312-test-instrumentation-langchain-conformance_ubuntu-latest: + name: instrumentation-langchain-conformance 3.12 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install tox + run: pip install tox-uv + + - name: Read pinned weaver version + id: versions + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + + - name: Install weaver ${{ steps.versions.outputs.WEAVER_VERSION }} + env: + WEAVER_VERSION: ${{ steps.versions.outputs.WEAVER_VERSION }} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + + - name: Run tests + run: tox -e py312-test-instrumentation-langchain-conformance -- -ra + + py313-test-instrumentation-langchain-conformance_ubuntu-latest: + name: instrumentation-langchain-conformance 3.13 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install tox + run: pip install tox-uv + + - name: Read pinned weaver version + id: versions + run: | + # shellcheck disable=SC2002 + cat versions.env | grep -E '^WEAVER_VERSION=' >> "$GITHUB_OUTPUT" + + - name: Install weaver ${{ steps.versions.outputs.WEAVER_VERSION }} + env: + WEAVER_VERSION: ${{ steps.versions.outputs.WEAVER_VERSION }} + run: | + WEAVER_ASSET="weaver-x86_64-unknown-linux-gnu" + WEAVER_URL="https://github.com/open-telemetry/weaver/releases/download/${WEAVER_VERSION}/${WEAVER_ASSET}.tar.xz" + curl -sSL "$WEAVER_URL" | tar -xJ -C /tmp "${WEAVER_ASSET}/weaver" + sudo mv "/tmp/${WEAVER_ASSET}/weaver" /usr/local/bin/weaver + weaver --version + + - name: Run tests + run: tox -e py313-test-instrumentation-langchain-conformance -- -ra + py310-test-util-genai_ubuntu-latest: name: util-genai 3.10 Ubuntu runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 6c3e08c1..fa7bfddc 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,10 @@ target opentelemetry-admin-jobs.txt .claude/settings.local.json + +# Generated by test_util_genai._setup_weaver +policies/_schemas.rego +.build/ + +# Conformance test weaver live-check reports +weaver_reports/ diff --git a/AGENTS.md b/AGENTS.md index a7b643e5..649d8a9d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -99,6 +99,25 @@ Apply to packages under `instrumentation/`. `from opentelemetry.test_util_genai.vcr import fixture_vcr, scrub_response_headers`) rather than re-implementing provider/exporter/VCR plumbing. +### Conformance tests + +Packages with substantive instrumentation ship `tests/conformance/.py` +scenarios and a `tests/test_conformance.py` that validates emitted telemetry +against the [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai) +via Weaver live-check. Each scenario module defines a subclass of +`opentelemetry.test_util_genai.conformance.Scenario` that sets +`expected_spans`, `expected_metrics`, and implements +`run(*, tracer_provider, meter_provider, logger_provider, vcr)`. + +`tests/test_conformance.py` must set `pytestmark = pytest.mark.conformance` at +module level. The `*-conformance` tox envs select these tests via +`-m conformance`; the regular `*-{oldest,latest}` envs deselect them via +`-m "not conformance"`. Without the marker the test won't run under the +conformance env and will leak into the regular suite (where `weaver` isn't +installed). + +Run via `tox -e py312-test-instrumentation--conformance`. + The parallel PR-review rules live in [`.github/instructions/instrumentation.instructions.md`](.github/instructions/instrumentation.instructions.md) and should be kept in sync with this section. diff --git a/dev-requirements-conformance.txt b/dev-requirements-conformance.txt new file mode 100644 index 00000000..e3618215 --- /dev/null +++ b/dev-requirements-conformance.txt @@ -0,0 +1,12 @@ +# Conformance tests use `opentelemetry.test.weaver_live_check`, not yet on +# PyPI. Pin the whole stack from git+main so versions stay coherent. Mirrors +# pyproject.toml's [tool.uv.sources]. Drop once the file ships to PyPI. + +opentelemetry-api @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-api +opentelemetry-sdk @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-sdk +opentelemetry-semantic-conventions @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-semantic-conventions +opentelemetry-test-utils @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=tests/opentelemetry-test-utils +opentelemetry-instrumentation @ git+https://github.com/open-telemetry/opentelemetry-python-contrib#subdirectory=opentelemetry-instrumentation +opentelemetry-exporter-otlp-proto-grpc @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=exporter/opentelemetry-exporter-otlp-proto-grpc +opentelemetry-exporter-otlp-proto-common @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=exporter/opentelemetry-exporter-otlp-proto-common +opentelemetry-proto @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-proto diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/pyproject.toml b/instrumentation/opentelemetry-instrumentation-anthropic/pyproject.toml index 6a318acb..72c0c17f 100644 --- a/instrumentation/opentelemetry-instrumentation-anthropic/pyproject.toml +++ b/instrumentation/opentelemetry-instrumentation-anthropic/pyproject.toml @@ -52,3 +52,6 @@ packages = ["src/opentelemetry"] [tool.pytest.ini_options] testpaths = ["tests"] +markers = [ + "conformance: GenAI semconv conformance scenario (run via the *-conformance tox envs)", +] diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference-conformance.yaml b/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference-conformance.yaml new file mode 100644 index 00000000..f7c1cab0 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference-conformance.yaml @@ -0,0 +1,140 @@ +interactions: +- request: + body: |- + { + "max_tokens": 100, + "messages": [ + { + "role": "user", + "content": "Say hello in one word." + } + ], + "model": "claude-sonnet-4-20250514" + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + anthropic-version: + - '2023-06-01' + connection: + - keep-alive + content-length: + - '117' + content-type: + - application/json + host: + - api.anthropic.com + user-agent: + - Anthropic/Python 0.75.0 + x-api-key: + - test_anthropic_api_key + x-stainless-arch: + - arm64 + x-stainless-async: + - 'false' + x-stainless-lang: + - python + x-stainless-os: + - MacOS + x-stainless-package-version: + - 0.75.0 + x-stainless-read-timeout: + - '600' + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.9.6 + x-stainless-timeout: + - '600' + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: |- + { + "model": "claude-sonnet-4-20250514", + "id": "msg_0176GK1qFwwpVM59jDYiKPjN", + "type": "message", + "role": "assistant", + "content": [ + { + "type": "text", + "text": "Hello!" + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 13, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": { + "ephemeral_5m_input_tokens": 0, + "ephemeral_1h_input_tokens": 0 + }, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available" + } + } + headers: + CF-RAY: + - 9d6567b84d8509ae-EWR + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Tue, 03 Mar 2026 03:02:57 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '450000' + anthropic-ratelimit-input-tokens-remaining: + - '450000' + anthropic-ratelimit-input-tokens-reset: + - '2026-03-03T03:02:57Z' + anthropic-ratelimit-output-tokens-limit: + - '90000' + anthropic-ratelimit-output-tokens-remaining: + - '90000' + anthropic-ratelimit-output-tokens-reset: + - '2026-03-03T03:02:57Z' + anthropic-ratelimit-requests-limit: + - '1000' + anthropic-ratelimit-requests-remaining: + - '999' + anthropic-ratelimit-requests-reset: + - '2026-03-03T03:02:56Z' + anthropic-ratelimit-tokens-limit: + - '540000' + anthropic-ratelimit-tokens-remaining: + - '540000' + anthropic-ratelimit-tokens-reset: + - '2026-03-03T03:02:57Z' + cf-cache-status: + - DYNAMIC + content-length: + - '441' + request-id: + - req_011CYfQM6TP1iFTVWNrJQJcn + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + vary: + - Accept-Encoding + x-envoy-upstream-service-time: + - '1056' + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling-conformance.yaml b/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling-conformance.yaml new file mode 100644 index 00000000..85d6bc4d --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling-conformance.yaml @@ -0,0 +1,168 @@ +interactions: +- request: + body: |- + { + "max_tokens": 256, + "messages": [ + { + "role": "user", + "content": "What is the weather in SF?" + } + ], + "model": "claude-sonnet-4-20250514", + "tool_choice": { + "type": "tool", + "name": "get_weather" + }, + "tools": [ + { + "name": "get_weather", + "description": "Get weather by city", + "input_schema": { + "type": "object", + "properties": { + "city": { + "type": "string" + } + }, + "required": [ + "city" + ] + } + } + ] + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + anthropic-version: + - '2023-06-01' + connection: + - keep-alive + content-length: + - '334' + content-type: + - application/json + host: + - api.anthropic.com + user-agent: + - Anthropic/Python 0.75.0 + x-api-key: + - test_anthropic_api_key + x-stainless-arch: + - arm64 + x-stainless-async: + - 'false' + x-stainless-lang: + - python + x-stainless-os: + - MacOS + x-stainless-package-version: + - 0.75.0 + x-stainless-read-timeout: + - '600' + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.9.6 + x-stainless-timeout: + - '600' + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: |- + { + "model": "claude-sonnet-4-20250514", + "id": "msg_01VkeD2PaERGgjekk84zPSwr", + "type": "message", + "role": "assistant", + "content": [ + { + "type": "tool_use", + "id": "toolu_01UAcA2APHENDob6qJ8kmoaC", + "name": "get_weather", + "input": { + "city": "San Francisco" + }, + "caller": { + "type": "direct" + } + } + ], + "stop_reason": "tool_use", + "stop_sequence": null, + "usage": { + "input_tokens": 386, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": { + "ephemeral_5m_input_tokens": 0, + "ephemeral_1h_input_tokens": 0 + }, + "output_tokens": 34, + "service_tier": "standard", + "inference_geo": "not_available" + } + } + headers: + CF-RAY: + - 9d656813eddfae20-EWR + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Tue, 03 Mar 2026 03:03:11 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '450000' + anthropic-ratelimit-input-tokens-remaining: + - '450000' + anthropic-ratelimit-input-tokens-reset: + - '2026-03-03T03:03:11Z' + anthropic-ratelimit-output-tokens-limit: + - '90000' + anthropic-ratelimit-output-tokens-remaining: + - '90000' + anthropic-ratelimit-output-tokens-reset: + - '2026-03-03T03:03:11Z' + anthropic-ratelimit-requests-limit: + - '1000' + anthropic-ratelimit-requests-remaining: + - '999' + anthropic-ratelimit-requests-reset: + - '2026-03-03T03:03:10Z' + anthropic-ratelimit-tokens-limit: + - '540000' + anthropic-ratelimit-tokens-remaining: + - '540000' + anthropic-ratelimit-tokens-reset: + - '2026-03-03T03:03:11Z' + cf-cache-status: + - DYNAMIC + content-length: + - '550' + request-id: + - req_011CYfQNBARQegAkczG6kweQ + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + vary: + - Accept-Encoding + x-envoy-upstream-service-time: + - '1256' + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/__init__.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/__init__.py new file mode 100644 index 00000000..e57cf4ab --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/__init__.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py new file mode 100644 index 00000000..f5d8c2ec --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py @@ -0,0 +1,61 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: anthropic chat (inference).""" + +from __future__ import annotations + +import os +from typing import Any +from unittest import mock + +from anthropic import Anthropic + +from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + + +class InferenceScenario(Scenario): + expected_spans = ("chat",) + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + key_override = ( + {} + if os.getenv("ANTHROPIC_API_KEY") + else {"ANTHROPIC_API_KEY": "test_anthropic_api_key"} + ) + with mock.patch.dict(os.environ, key_override): + with instrument( + AnthropicInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + semconv="gen_ai_latest_experimental", + content_capture="SPAN_ONLY", + ): + with vcr.use_cassette("inference-conformance.yaml"): + Anthropic().messages.create( + model="claude-sonnet-4-20250514", + max_tokens=100, + messages=[ + { + "role": "user", + "content": "Say hello in one word.", + } + ], + ) diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py new file mode 100644 index 00000000..971bfc81 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py @@ -0,0 +1,75 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: anthropic chat with tool calls.""" + +from __future__ import annotations + +import os +from typing import Any +from unittest import mock + +from anthropic import Anthropic + +from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + + +class ToolCallingScenario(Scenario): + expected_spans = ("chat",) + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + key_override = ( + {} + if os.getenv("ANTHROPIC_API_KEY") + else {"ANTHROPIC_API_KEY": "test_anthropic_api_key"} + ) + with mock.patch.dict(os.environ, key_override): + with instrument( + AnthropicInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + semconv="gen_ai_latest_experimental", + content_capture="SPAN_ONLY", + ): + with vcr.use_cassette("tool_calling-conformance.yaml"): + Anthropic().messages.create( + model="claude-sonnet-4-20250514", + max_tokens=256, + messages=[ + { + "role": "user", + "content": "What is the weather in SF?", + } + ], + tools=[ + { + "name": "get_weather", + "description": "Get weather by city", + "input_schema": { + "type": "object", + "properties": { + "city": {"type": "string"} + }, + "required": ["city"], + }, + } + ], + tool_choice={"type": "tool", "name": "get_weather"}, + ) diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conftest.py index 6e074fdc..f7d2d342 100644 --- a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conftest.py +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conftest.py @@ -13,7 +13,10 @@ from opentelemetry.test_util_genai.instrumentor import instrument from opentelemetry.test_util_genai.vcr import scrub_response_headers -pytest_plugins = ["opentelemetry.test_util_genai.fixtures"] +pytest_plugins = [ + "opentelemetry.test_util_genai.fixtures", + "opentelemetry.test_util_genai.vcr", +] @pytest.fixture(autouse=True) diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py new file mode 100644 index 00000000..3fedab59 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py @@ -0,0 +1,39 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Per-scenario conformance tests for anthropic.""" + +from __future__ import annotations + +from typing import Any + +import pytest + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck +from opentelemetry.test_util_genai.conformance import ( + Scenario, + run_conformance, +) + +from .conformance.inference import InferenceScenario +from .conformance.tool_calling import ToolCallingScenario + +pytestmark = pytest.mark.conformance + +_LEGACY_SYSTEM_SKIP = pytest.mark.skip( + reason="anthropic emits legacy gen_ai.system in experimental mode" +) + + +@pytest.mark.parametrize( + "scenario", + [ + pytest.param(InferenceScenario(), marks=_LEGACY_SYSTEM_SKIP), + pytest.param(ToolCallingScenario(), marks=_LEGACY_SYSTEM_SKIP), + ], + ids=lambda s: type(s).__name__, +) +def test_conformance( + scenario: Scenario, vcr: Any, weaver_live_check: WeaverLiveCheck +) -> None: + run_conformance(scenario, vcr=vcr, weaver=weaver_live_check) diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference-conformance.yaml b/instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference-conformance.yaml new file mode 100644 index 00000000..5bd76600 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference-conformance.yaml @@ -0,0 +1,161 @@ +interactions: +- request: + body: |- + { + "messages": [ + { + "content": "You are a helpful assistant!", + "role": "system" + }, + { + "content": "What is the capital of France?", + "role": "user" + } + ], + "model": "gpt-3.5-turbo", + "frequency_penalty": 0.5, + "max_completion_tokens": 100, + "presence_penalty": 0.5, + "seed": 100, + "stop": [ + "\n", + "Human:", + "AI:" + ], + "stream": false, + "temperature": 0.1, + "top_p": 0.9 + } + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '316' + Content-Type: + - application/json + Host: + - api.openai.com + User-Agent: + - OpenAI/Python 2.21.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.21.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.13.5 + authorization: + - Bearer test_openai_api_key + x-stainless-retry-count: + - '0' + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: |- + { + "id": "chatcmpl-DB5VKnX0DBvthDkYqZDgfZVAqhZUk", + "object": "chat.completion", + "created": 1771535138, + "model": "gpt-3.5-turbo-0125", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The capital of France is Paris.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 7, + "total_tokens": 31, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": null + } + headers: + CF-RAY: + - 9d08b930cee533ed-SJC + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 19 Feb 2026 21:05:38 GMT + Server: + - cloudflare + Set-Cookie: test_set_cookie + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + access-control-expose-headers: + - X-Request-ID + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + content-length: + - '822' + openai-organization: test_openai_org_id + openai-processing-ms: + - '170' + openai-project: + - proj_GLiYlAc06hF0Fm06IMReZLy4 + openai-version: + - '2020-10-01' + set-cookie: + - __cf_bm=tYjXaOj8KokJGc56XWDShqpm2zPWeq3Q19yhnJcqKqU-1771535137.4012983-1.0.1.1-k50ojuWx4sSPmgdu8QLKD3OmGYDMjKIDSqQcANN1wo1SBWNjIE.yAsOYOgaalvDiPrXObJN80xhnlcC9mXOXnOfGb9HRyT5un2ASAG29wbujzo_b9a3zQg9hHU024Nkz; + HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Thu, 19 Feb 2026 + 21:35:38 GMT + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - '10000' + x-ratelimit-limit-tokens: + - '200000' + x-ratelimit-remaining-requests: + - '9999' + x-ratelimit-remaining-tokens: + - '199982' + x-ratelimit-reset-requests: + - 8.64s + x-ratelimit-reset-tokens: + - 5ms + x-request-id: + - req_5f037f577c544db292661f8bbf12d569 + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/__init__.py b/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/__init__.py new file mode 100644 index 00000000..e57cf4ab --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/__init__.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py new file mode 100644 index 00000000..188345a6 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py @@ -0,0 +1,72 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: langchain chat (inference) via ChatOpenAI.""" + +from __future__ import annotations + +import os +from typing import Any +from unittest import mock + +from langchain_core.messages import HumanMessage, SystemMessage +from langchain_openai import ChatOpenAI + +from opentelemetry.instrumentation.langchain import LangChainInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + + +class InferenceScenario(Scenario): + expected_spans = ("chat",) + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + key_override = ( + {} + if os.getenv("OPENAI_API_KEY") + else {"OPENAI_API_KEY": "test_openai_api_key"} + ) + with mock.patch.dict(os.environ, key_override): + with instrument( + LangChainInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + semconv="gen_ai_latest_experimental", + content_capture="SPAN_ONLY", + ): + llm = ChatOpenAI( + model="gpt-3.5-turbo", + temperature=0.1, + max_tokens=100, + top_p=0.9, + frequency_penalty=0.5, + presence_penalty=0.5, + stop_sequences=["\n", "Human:", "AI:"], + seed=100, + ) + with vcr.use_cassette("inference-conformance.yaml"): + llm.invoke( + [ + SystemMessage( + content="You are a helpful assistant!" + ), + HumanMessage( + content="What is the capital of France?" + ), + ] + ) diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py new file mode 100644 index 00000000..436f482b --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py @@ -0,0 +1,33 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Per-scenario conformance tests for langchain.""" + +from __future__ import annotations + +from typing import Any + +import pytest + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck +from opentelemetry.test_util_genai.conformance import ( + Scenario, + run_conformance, +) + +from .conformance.inference import InferenceScenario + +pytestmark = pytest.mark.conformance + + +@pytest.mark.parametrize( + "scenario", + [ + InferenceScenario(), + ], + ids=lambda s: type(s).__name__, +) +def test_conformance( + scenario: Scenario, vcr: Any, weaver_live_check: WeaverLiveCheck +) -> None: + run_conformance(scenario, vcr=vcr, weaver=weaver_live_check) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding-conformance.yaml b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding-conformance.yaml new file mode 100644 index 00000000..d7177abf --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding-conformance.yaml @@ -0,0 +1,1652 @@ +interactions: +- request: + body: |- + { + "input": "This is a test for async embeddings", + "model": "text-embedding-3-small" + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + authorization: + - Bearer test_openai_api_key + connection: + - keep-alive + content-length: + - '83' + content-type: + - application/json + host: + - api.openai.com + user-agent: + - AsyncOpenAI/Python 1.26.0 + x-stainless-arch: + - arm64 + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - Linux + x-stainless-package-version: + - 1.26.0 + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.9.2 + method: POST + uri: https://api.openai.com/v1/embeddings + response: + body: + string: |- + { + "object": "list", + "data": [ + { + "object": "embedding", + "index": 0, + "embedding": [ + -0.0012588563, + -0.029314144, + -0.004568109, + -0.021721158, + -0.025343766, + -0.0004159207, + 0.04500728, + 0.03663181, + 0.009042029, + -0.0049231243, + 0.026416058, + -0.030574812, + 7.522572e-05, + -0.031241372, + -0.03683468, + 0.0045789764, + -0.017837722, + -0.0065569207, + 0.017272595, + -0.0049231243, + -0.008542109, + -0.047383714, + 0.015185973, + 0.042804737, + 0.0033654028, + -0.019634536, + 0.012171963, + 0.041471615, + 0.033994555, + -0.034690093, + 0.006172924, + -0.038370665, + 0.009599911, + -0.028618604, + -0.017069729, + 0.06578656, + -0.010759146, + 0.036747735, + -0.039819706, + -0.0077886074, + 0.0027314464, + -0.03750124, + -0.04993403, + -0.0045898445, + 0.013425386, + 0.05135409, + -0.03257449, + -0.01773629, + 0.018866543, + 0.034516208, + -0.048398044, + 0.012041549, + -0.0050209346, + 0.047876388, + -0.032081816, + -0.007237971, + -0.029792327, + 0.030429907, + -0.0102447355, + 0.0064736004, + 0.061787203, + -0.031212391, + -0.029256182, + -0.018881032, + 0.006412016, + -0.00872324, + -0.022416698, + 0.025285805, + -0.011730005, + -0.0064736004, + 0.05193371, + 0.023720838, + -0.009969417, + 0.0034740812, + -0.0029632933, + 0.021025617, + 0.012063284, + 0.016519092, + -0.016345207, + -0.034516208, + -0.030111117, + 0.027531821, + -0.029256182, + -0.019040428, + -0.01775078, + -0.013179048, + -0.07807445, + -0.009136218, + -0.0018765109, + 0.0011746306, + -0.020721318, + -0.028256342, + -0.07679929, + -0.029328635, + 0.029343124, + 0.011845929, + -0.001069575, + -0.04593467, + -0.03428436, + 0.021721158, + 0.01576559, + 0.02543071, + -0.017576894, + 0.008230565, + 0.0015187784, + -0.016475622, + 0.0012162906, + -0.00537595, + -0.04758658, + -0.003651589, + -0.05671555, + -0.014193378, + 0.0036751358, + 0.003187895, + 0.057150263, + -0.022576094, + -0.00452826, + -0.013323952, + -0.008563845, + -0.021156032, + -0.018576734, + -0.007031482, + 0.03628404, + -0.007491553, + -0.024590263, + -0.046166517, + -0.03553054, + -0.047064923, + -0.061787203, + 0.0005922964, + 0.02082275, + -0.028270833, + 0.0557302, + 0.039153147, + -0.06288847, + -0.011164878, + -0.077205025, + 0.027010165, + -0.0033291767, + 0.022981824, + -0.017910173, + -0.04660123, + 0.03654487, + -0.022720998, + -0.045673843, + -0.010708429, + -0.021996476, + 0.047905367, + 0.005970058, + -0.008643542, + -0.011338763, + -0.02548867, + -0.04494932, + 0.042456966, + -0.018953485, + -0.031734046, + -0.038370665, + 3.5575144e-05, + 0.010679448, + -0.0052346685, + -0.036515888, + 0.019938834, + 0.034139458, + -0.0284737, + 0.0017578705, + 0.03083564, + 0.01005636, + -0.005129613, + -0.022735488, + -0.062830515, + 0.004568109, + -0.03750124, + -0.054889757, + 0.000167206, + -0.012012568, + -0.014867184, + 0.028096948, + -0.06943815, + 0.012164718, + -0.011186614, + -0.014722279, + 0.024039626, + 0.022416698, + 0.00039848688, + -0.06074389, + 0.06584452, + 0.02246017, + 0.06404771, + 0.0010713863, + 0.0025285804, + -0.007006124, + 0.058599308, + 0.056918416, + -0.008607317, + 0.024213511, + -0.031212391, + 0.042891677, + 0.003068349, + 0.031618122, + -0.01223717, + 0.0075712507, + 0.03990665, + -0.0050173122, + 0.0057671918, + 0.05199167, + -0.0251409, + -0.023633895, + -0.042312063, + -0.009969417, + 0.0045572408, + 0.042456966, + -0.019388199, + 0.0028763507, + 0.010643222, + -0.015953965, + 0.007810343, + -0.034371305, + 0.013505083, + 0.037066527, + -0.018055078, + -0.030980544, + 0.043326393, + 0.054426063, + 0.0402834, + -0.026256664, + -0.0015142502, + -0.016026419, + -0.0013657232, + 0.017388519, + 0.00015962117, + -0.004473921, + -0.023648385, + -0.0016011928, + -0.01677992, + 0.03190793, + -0.015968457, + -0.001709871, + -0.0135558, + -0.02482211, + 0.0091144815, + -0.015838042, + -0.034690093, + 0.01391806, + -0.021953005, + -0.006654731, + 0.023083258, + -0.001220819, + -0.028401246, + 0.038167797, + -0.019069409, + -0.019344727, + 0.02218485, + -0.014570129, + 0.0020576413, + -0.04219614, + -0.023271633, + -0.030024175, + 0.03929805, + 0.0073176683, + 0.005618665, + -0.012910975, + 0.042341042, + -0.02146033, + 0.007448082, + 0.013968777, + -0.05158594, + 0.033009205, + -0.008317508, + -0.006031642, + -0.047180846, + -0.00988972, + -0.0060026613, + 0.057440072, + -0.036747735, + -0.057816826, + 0.006129453, + -0.036370985, + -0.007364762, + -0.007926267, + 0.0067597865, + 0.004408714, + -0.046977982, + 0.010983747, + 0.0342264, + -0.011309782, + 0.007940757, + 0.0013113841, + -0.019518612, + -0.0016138719, + 0.011940116, + -0.0052093104, + -0.05868625, + 0.051209185, + 0.029009845, + 0.0051513487, + 0.004386978, + 0.033443917, + -0.010563525, + 0.016533583, + -0.010208509, + 0.05222352, + -0.04350028, + 0.0322557, + 0.02822736, + -0.018634696, + 0.033617802, + -0.04865887, + 0.040718116, + 0.040399324, + 0.001111235, + -0.028430227, + 0.01275158, + -0.035646465, + 0.023039786, + -0.046717152, + 0.008795693, + 0.02447434, + -0.015635176, + 0.034371305, + -0.047702502, + -0.008998558, + -0.036399964, + 0.011621326, + -0.045499958, + -0.0063830353, + -0.03118341, + -0.00072678574, + -0.035095826, + 0.015301896, + 0.029140258, + -0.0068902005, + 0.028444719, + 0.03663181, + -0.002318469, + 0.023691857, + -0.026633414, + -0.00048769361, + -0.023648385, + 0.0496732, + -0.0018620205, + -0.04121079, + -0.0017297954, + 0.04100792, + -0.025532141, + 0.005415799, + 0.052803133, + 0.027039146, + 0.030951563, + 0.031734046, + -0.017388519, + 0.013447121, + -0.0066112597, + -0.0068865777, + 0.003044802, + 0.057845805, + -0.05767192, + -0.020243134, + -0.0077596265, + -0.010222999, + -0.019634536, + 0.025749497, + -0.0053723278, + -0.009962172, + 0.066655986, + 0.013505083, + -0.031994876, + -0.007803098, + 0.021851571, + -0.002628202, + -0.015562724, + -0.016982786, + 0.049876068, + 0.004289168, + 0.009353574, + -0.02586542, + 0.02182259, + -0.026705867, + 0.03990665, + 0.04590569, + 0.054976698, + 0.03153118, + -0.032284684, + -0.039182127, + -0.07488655, + -0.02143135, + 0.005129613, + -0.014657072, + -0.01912737, + -0.026213191, + -0.011476423, + 0.0125849405, + -0.031994876, + -0.025169881, + -0.00569474, + 0.024300454, + 0.027604273, + 0.058077652, + -0.025720516, + 0.009382554, + -0.0035429106, + -0.0051404806, + -0.045876708, + -0.010273716, + 0.0016645883, + 0.0022170362, + 0.023097748, + 0.02819838, + -0.0016274566, + 0.025271313, + -0.0093898, + -0.005988171, + -0.0011338763, + 0.044021934, + -0.05630982, + -0.0009980286, + 0.019011447, + 0.012758825, + -0.043703143, + 0.010976503, + 0.06729357, + -0.036747735, + -0.0584544, + -0.024445359, + -0.013512328, + 0.024039626, + -0.010447602, + 0.075929865, + 0.0060859816, + 0.018315906, + -0.06132351, + -0.043674164, + -0.018996956, + 0.043413334, + 0.038428627, + -0.021054598, + -0.022938354, + 0.036689773, + 0.019272275, + -0.029212711, + -0.018489791, + -0.0052165557, + -0.007237971, + -0.0584544, + -0.010527299, + -0.009462252, + -0.011222839, + -0.026024817, + 0.0037566444, + -0.006346809, + -0.01291822, + -0.008143622, + -0.067931145, + 0.009599911, + -0.029256182, + -0.009027539, + -0.027415898, + 0.010143302, + 0.0031208768, + 0.06735153, + 0.007861059, + 0.019388199, + -0.050484665, + -0.06010631, + 0.035878308, + 0.06004835, + 0.017374028, + -0.0028093325, + 0.010947522, + 0.045528937, + 0.0018131153, + -0.008237811, + 0.04636938, + -0.0013901758, + 0.027357936, + 0.037530217, + -0.035443597, + 0.024010645, + -0.021532781, + -0.00030226135, + -0.022039948, + -0.012106756, + -0.021040108, + -0.039124165, + -0.036313023, + -0.00093463284, + 0.14397693, + -0.043065563, + -0.019359218, + 0.008773956, + -0.012505243, + -0.026503, + 0.017794251, + -0.012222679, + -0.018533263, + 0.034371305, + -0.047238808, + -0.01676543, + -0.05094836, + 0.03950092, + -0.027560802, + -0.012824032, + 0.0063721677, + -0.020170681, + 0.021547273, + 0.01776527, + -0.0010795372, + -0.041761424, + 0.009650628, + -0.014033983, + 0.0171132, + -0.014041228, + 0.01191838, + -0.020243134, + -0.010831598, + -0.012592185, + -0.004285545, + -0.036168117, + 0.054918736, + 0.005593307, + -0.04184837, + -0.009230405, + -0.01914186, + -0.0036443437, + -0.041529577, + 0.012512488, + 0.013193538, + -0.01375142, + -0.057208225, + -0.034139458, + -0.0052708946, + -0.018084059, + -0.015910495, + 0.028430227, + -0.026430547, + -0.027937554, + -0.00047275034, + -0.020735808, + 0.017243614, + 0.018402848, + -0.014772995, + 0.03883436, + 0.0044884114, + 0.034719076, + -0.02112705, + -0.022836922, + 0.043413334, + 0.023488991, + 0.015026578, + -0.020243134, + 0.0152439345, + 0.022720998, + -0.018996956, + 0.028430227, + -0.017388519, + 0.01225166, + 0.013722439, + 0.04500728, + -0.016895844, + -0.018156512, + -0.022228323, + 0.021445839, + 0.03686366, + 0.06706172, + 0.035008885, + -0.033067167, + 0.03689264, + 0.017808741, + -0.0019073031, + 0.044050913, + -0.0050245575, + -0.05801969, + 0.010317188, + 0.021590743, + 0.02143135, + 0.014533903, + 0.01982291, + -0.023517972, + 0.018852051, + -0.034342322, + -0.037385315, + -0.017069729, + -0.010817108, + 0.02279345, + 0.0118241925, + -0.00887539, + 0.054049313, + 0.004546373, + -0.019170841, + -0.010679448, + 0.032516528, + 0.02882147, + 0.0019471518, + 0.019764949, + -0.038109835, + 0.025995836, + -0.010715675, + 0.048484985, + 0.0021337161, + -0.03263245, + 0.010578016, + 0.011266311, + 0.0018746996, + -0.008607317, + -0.005437535, + 0.02987927, + 0.006506204, + -0.035066847, + 0.016519092, + 0.04019646, + -0.014041228, + -0.009143462, + -0.030806659, + 0.017939154, + -0.0146136, + -0.0031353673, + -0.007006124, + 0.008795693, + 0.0080277, + 0.028096948, + -0.020909693, + 0.014780241, + -0.03184997, + -0.00056014577, + 0.019735968, + -0.024068607, + 0.0015857967, + 0.0045318827, + 0.00562591, + 0.0029614822, + 0.025720516, + -0.015229444, + 0.0052346685, + 0.014910654, + -0.037153468, + -0.037877988, + -0.0160554, + -0.02754631, + 0.039442956, + 0.011382234, + -0.024126569, + -0.0106939385, + 0.0001393572, + 0.02315571, + 0.0080277, + -0.010998238, + -0.010933031, + 0.014316547, + 0.0033961951, + -0.004571731, + -0.013425386, + 0.0059773033, + -0.032313664, + 0.003635287, + -0.010462092, + 0.02586542, + -0.07088719, + -0.019837402, + -0.011650307, + -0.013381914, + -0.016649507, + 0.0073973658, + 0.00247243, + -0.013476102, + 0.0129544465, + 0.008216075, + 0.043094546, + -0.043703143, + 0.04636938, + -0.0017823231, + -0.008636298, + 0.010027379, + 0.012983427, + 0.04384805, + -0.02047498, + 0.023329595, + -0.039182127, + -0.029560482, + -0.016635016, + 0.01743199, + -0.017475462, + -0.0052093104, + 0.020706827, + -0.008360979, + -0.026314626, + 0.036805697, + -0.0044232043, + 0.03889232, + 0.0016365132, + 0.0021463952, + -0.01844632, + -0.046804097, + -0.028125929, + 0.052542306, + -0.0029940854, + -0.0065170717, + 0.035762385, + 0.010911295, + 0.02987927, + -0.018866543, + 0.036428947, + 0.007650948, + 0.017837722, + 0.008201584, + -0.025923382, + -0.004933992, + -0.02987927, + 0.015881514, + 0.029096788, + 0.030024175, + -0.005339724, + -0.016707469, + -0.035095826, + 0.011701024, + 0.026387077, + -0.007455327, + -0.01409919, + 0.0060461327, + -0.012548714, + -0.029966213, + -0.038022894, + -0.036660794, + 0.0026734846, + -0.0030647265, + -0.0086145615, + -0.0077234004, + -0.042312063, + -0.010063605, + 0.0073901205, + -0.013628251, + 0.003169782, + -0.010483827, + 0.00019460198, + -0.016649507, + -0.011259066, + -0.018736128, + 0.00089478417, + 0.001361195, + -0.010672203, + -0.040428307, + -0.011925626, + 0.01712769, + 0.009643382, + 0.011483667, + -0.0012733467, + -0.03019806, + 0.048484985, + 0.02751733, + 0.0006565977, + 0.0149541255, + -0.011498158, + -0.022923864, + 0.012700864, + -0.012027059, + 0.022880392, + -0.041819386, + -0.036370985, + 0.024054118, + -0.022445679, + -0.0124545265, + 0.013635497, + 0.02147482, + -0.007089444, + -0.012440036, + 0.017953645, + 0.015316387, + -0.0112445755, + -0.018562244, + -0.0052817627, + 0.045470975, + 0.024995996, + 0.0036207966, + -0.023720838, + 0.016519092, + 0.002394544, + 0.051701862, + -0.006810503, + -0.02214138, + 0.017200142, + -0.034081496, + 0.018576734, + -0.0155047625, + 0.021909533, + -0.00032105364, + -0.026126249, + -0.010606997, + -0.015490272, + -0.01744648, + 0.01673645, + -0.0028147665, + -0.043529257, + -0.057874784, + -0.0042638094, + 0.037820026, + -0.028575132, + 0.00652794, + -0.0021645082, + -0.044833396, + -0.0630044, + -0.018721638, + 0.029140258, + -0.023648385, + -0.0044232043, + 0.018518772, + -0.0029687274, + 0.01543231, + 0.00313899, + 0.020214153, + 0.038428627, + -0.041326713, + -0.035878308, + -0.029705387, + 0.03683468, + -0.009882474, + 0.024039626, + -0.01843183, + 0.0031317447, + -0.0113749895, + -0.02714058, + 0.008998558, + 0.03156016, + 0.012374829, + -0.036950603, + -0.0088246735, + 0.0077234004, + 0.008759466, + -0.010143302, + -0.007948002, + -0.018808581, + -0.0038218515, + 0.012679128, + 0.01257045, + -0.0077523813, + 0.0023818647, + 0.002454317, + -0.00063622056, + 0.025981344, + -0.017939154, + -0.003948643, + -0.028415738, + -0.010672203, + -0.024923543, + 0.054628927, + 0.010447602, + 0.017156672, + 0.013693458, + -0.003807361, + -0.030893601, + 0.012613921, + 0.0013177237, + 0.0074082334, + -0.023228163, + -0.00011943286, + 0.026358096, + 0.005850512, + 0.027024657, + 0.0057092304, + 0.023691857, + -0.026894242, + 0.014512167, + 0.008527619, + -0.00301401, + 0.0292272, + 0.005165839, + -0.0052056876, + 0.021025617, + -5.7905127e-05, + -0.02009823, + 0.025937874, + -0.008578336, + 0.061613318, + 0.017895684, + -0.017968135, + 0.007549515, + 0.013816627, + 0.035675444, + 0.011295292, + 0.019156352, + 0.050745495, + 0.015707629, + 0.021300934, + 0.017649347, + -0.023387557, + -0.010049115, + -0.03127035, + -0.052252498, + -0.031357296, + 0.027749177, + 0.043703143, + -0.03663181, + -0.0052455366, + 0.014809222, + 0.004223961, + -0.00049176905, + 0.014983106, + -0.03083564, + 0.045036264, + -0.013765911, + 0.02822736, + -0.007585741, + -0.02583644, + -0.011215595, + -0.030140098, + -0.014577375, + 0.008962332, + 0.036805697, + 0.0023365822, + -0.015359858, + 0.00755676, + 0.024923543, + -0.020953165, + -0.037414297, + -0.011505403, + 0.011845929, + 0.017692817, + 0.037964933, + 0.022213832, + -0.0044050915, + -0.0018837561, + 0.04836906, + -0.015577215, + -0.00789004, + -0.04663021, + 0.0025901648, + 0.0047999555, + -0.019562082, + -0.0153743485, + 0.011309782, + -0.016504603, + 0.03118341, + 0.0110562, + -0.0428627, + 0.008071171, + 6.022586e-05, + -0.008339244, + 0.0013747797, + -0.035675444, + 0.0030574813, + 0.022373227, + -0.041036904, + -0.014475942, + -0.021866063, + -0.028908413, + 0.02547418, + -0.02282243, + 0.020417018, + -0.014910654, + 0.0027785404, + 0.028082456, + 0.0051151225, + -0.021286445, + 0.022039948, + 0.04428276, + -0.0054592704, + -0.019054918, + -0.017475462, + -0.021909533, + 0.0218081, + 0.004785465, + 0.034979902, + -0.0042203385, + 0.0055462127, + 0.030053155, + 0.0023076013, + -0.040776078, + 0.01912737, + -0.026560962, + -0.023083258, + -0.030748697, + 0.023271633, + 0.008549355, + 0.017316066, + 0.022054438, + 0.016330717, + 0.0055751936, + 0.027604273, + 0.021286445, + 0.008933351, + 0.027705707, + 0.046977982, + -0.015330877, + 0.007984228, + 0.015591705, + 0.012657393, + -0.013200783, + 0.0046985224, + -0.008085661, + 0.008752221, + 0.0062055276, + 0.036428947, + -0.0012008946, + 0.016577054, + -0.015519253, + -0.036168117, + 0.0041189054, + -0.002626391, + -0.020706827, + -0.0050318027, + 0.0502818, + -0.02882147, + 0.010346169, + -0.0019471518, + -0.020257624, + -0.0055860616, + 0.004187735, + 0.0048035784, + -0.022692017, + -0.0020413396, + -0.01612785, + -0.008491393, + 0.029299654, + 0.014287566, + -0.02985029, + 0.008092906, + -0.060512044, + -0.028386757, + -0.02282243, + 0.0048289364, + -0.023054278, + 0.02415555, + -0.020561922, + -0.01205604, + -0.02543071, + 0.026705867, + 0.010947522, + -0.010317188, + -0.017808741, + -0.005165839, + -0.032806337, + 0.01193287, + 0.028676566, + -0.010353413, + 0.014005003, + -0.0075929863, + -0.025952363, + -0.026169721, + 0.045326073, + -0.0023039787, + 0.015881514, + 0.009628892, + -0.030893601, + -0.023851251, + -0.0017651158, + -0.0004333545, + 0.030342964, + 0.04494932, + -0.01777976, + 0.015403329, + 0.004571731, + 0.010085341, + 0.02511192, + -0.018924505, + 0.022010967, + -0.0013892702, + 0.0022061684, + 0.0018122096, + 0.023604915, + 0.0018457188, + 0.010338923, + 0.011664798, + 0.0064265067, + -0.03863149, + -0.00028822376, + 0.010215755, + -0.013063124, + -0.0027332578, + -0.009462252, + 0.010266471, + 0.025416218, + 0.008252301, + 0.029415578, + 0.0032023855, + -0.013294972, + 0.014142661, + -0.0006253527, + 0.027952043, + 0.013968777, + -0.012258906, + -0.025242332, + -0.0147440145, + 0.003050236, + -0.01343263, + 0.006248999, + -0.0076002316, + -0.004633316, + 0.021011127, + 0.007520534, + 0.008049435, + -0.0061040944, + 0.025575612, + -0.0024995995, + -0.017649347, + -0.017808741, + 0.028806979, + 0.0019036805, + -0.016533583, + 0.016794411, + -0.017997116, + -0.0153743485, + 0.018562244, + -0.007216235, + -0.02854615, + 0.01123733, + -0.007962492, + 0.020953165, + 0.0063612997, + 0.025952363, + -0.013947041, + -0.0009142557, + 0.0015830797, + 0.032226723, + -0.012773315, + 0.015707629, + 0.030371945, + -0.009925946, + -0.02586542, + -0.025198862, + 0.01875062, + -0.04500728, + -0.023706347, + -0.037617162, + 0.032081816, + 0.005821531, + 0.025648065, + 0.027386917, + -0.0136644775, + 0.008715995, + 0.028111437, + 0.005158594, + -0.020547433, + 0.013287726, + -0.006136698, + -0.037240412, + 0.0160554, + -0.026343606, + 0.004075434, + -0.04364518, + 0.0040066047, + -0.01473677, + 0.014925145, + -0.011541629, + 0.015953965, + -0.011816948, + 0.0036316644, + 0.0055208546, + 0.032980222, + -0.0036968715, + 0.025633574, + 0.10792474, + -0.0030701603, + 0.002318469, + 0.00044671286, + 0.016692977, + -0.021924024, + -0.027126089, + -0.0036425323, + -0.01914186, + -0.025937874, + -0.0026535604, + 0.032023855, + 0.010259226, + -0.016229283, + 0.0039341524, + 0.008433431, + 0.0010949332, + 0.002121037, + -0.001087688, + -0.00042044895, + 0.010201264, + 0.025387237, + -0.0027332578, + 0.016504603, + -0.053440712, + -0.009788287, + -0.025242332, + 0.010882314, + 0.014830957, + 0.043790087, + -0.013773155, + 0.03663181, + -0.03118341, + 0.0101143215, + 0.00050942926, + 0.023373067, + -0.053759504, + 0.008411696, + 0.023561442, + -0.013215274, + 0.005379573, + -0.009541949, + -0.010128812, + -0.017287085, + -0.009715835, + -0.04257289, + -0.0140847, + -0.020764789, + -0.0054665157, + -0.006690957, + 0.0024271475, + 0.027604273, + -0.028560642, + 0.024532301, + 0.042833716, + -0.030603793, + 0.008752221, + 0.02954599, + 0.05129613, + -0.023271633, + 0.017533423, + 0.025691535, + -0.0402834, + 0.023416538, + 0.005202065, + -0.022634055, + -0.02543071, + -0.0071365377, + -0.00060678687, + 0.03176303, + -0.015953965, + 0.021735648, + -0.014635337, + -0.050687533, + -0.000110319736, + 0.02080826, + 0.01914186, + -0.012302377, + -0.025343766, + 0.027357936, + -0.018518772, + 0.0054013086, + 0.033791687, + 0.033646785, + -0.016287245, + 0.0044340724, + 0.002318469, + -0.001212668, + -0.0008449733, + 0.04523913, + -0.035675444, + -0.021677686, + 0.011838683, + -0.02882147, + 0.002878162, + -0.00016143247, + 0.0021898665, + -0.03376271, + 0.012838523, + 0.010447602, + 0.013447121, + 0.03054583, + -0.007839324, + 0.016577054, + 0.016171321, + 0.015185973, + -0.054078292, + 0.04126875, + 0.014758505, + 0.036457926, + 0.011208349, + -0.028357776, + 0.013606516, + -0.012353093, + -0.016939316, + 0.012077775, + 3.0763866e-05, + 0.001561344, + 0.0073973658, + -0.028270833, + 0.0075277793, + 0.0025847307, + 0.0046079573, + -0.016359698, + 0.0045173923, + -0.043877028, + 0.0052093104, + -0.00045237318, + -0.014193378, + -0.021373387, + 0.037762064, + -0.0061765467, + 0.005745456, + -0.0018837561, + 0.039703783, + 0.008194339, + 0.014367264, + -0.027923062, + -0.01373693, + 0.02314122, + 0.018996956, + 0.024662714, + 0.012222679, + -0.0046152025, + 0.014381754, + -0.016997278, + 0.010396885, + 0.0035229863, + -0.03292226, + 0.008744976, + -0.0056150425, + -0.041181806, + 0.0016229284, + -0.029024335, + 0.026198702, + 0.0039595105, + 0.020286605, + 0.008252301, + 0.004473921, + -0.039442956, + -0.011295292, + -0.002979595, + -0.03990665, + 0.016533583, + 0.024532301, + 0.0045173923, + 0.013577535, + 0.016620526, + 0.014055719, + 0.02277896, + 0.028415738, + -0.025735008, + -0.0045789764, + -0.0008984068, + -0.00048135404, + -0.024083098, + 0.0006316923, + 0.020764789, + -0.05674453, + -0.0098245125, + 0.015403329, + -0.029705387, + -0.017634856, + 0.036023214, + -0.002251451, + -0.00789004, + 0.0067344285, + -0.016533583, + -0.004506524, + -0.00176421, + -0.009578176, + -0.00029682743, + -0.034835, + -0.0073720072, + -0.017707309, + -0.017953645, + -0.026285645, + -0.034168437, + 0.0020141702, + 0.036718756, + -0.0012244415, + -0.014120926, + 0.011382234, + -0.002466996, + 0.032052837, + 0.05129613, + -0.020243134, + 0.0147440145, + -0.013476102, + -0.019562082, + 0.039471935, + -0.0047999555, + 0.006321451, + 0.0026734846, + 0.055237528, + -0.008629052, + 0.0076944195, + -0.004137018, + -0.0033454786, + 0.015852533, + 0.0052056876, + 0.012193698, + 0.012729845, + -0.033733726, + -0.047412694, + 0.020895204, + 0.024083098, + 0.009512968, + -0.021648705, + 0.0016174945, + -0.060859814, + -0.047035944, + -0.0221124, + -0.0013412706, + -0.0034106853, + -0.02046049, + -0.017301576, + 0.019170841, + 0.026372585, + 9.8433055e-05, + -0.031936914, + -0.011215595, + 0.015041068, + 0.06004835, + -0.0091144815, + 0.005531722, + -0.0069517847, + 0.02175014, + -0.02918373, + -0.0032512906, + -0.00060905097, + 0.046079572, + -0.009433271, + -0.020692337, + -0.027444879, + -0.0026426925, + -0.0058613797, + -0.019866383, + -0.0096651185, + -0.012766071, + -0.020214153, + 0.002615523, + 0.049702182, + 0.008237811, + 0.007679929, + -0.038080856, + 0.013265991, + 0.011193858, + -0.0069083134, + 0.008049435, + 0.005165839, + -0.0035084959, + -0.030111117, + -0.0058831153, + -0.0035247975, + 0.012526979, + -0.010578016, + -0.014041228, + -0.0122444155, + -0.03721143, + -0.0057418337, + -0.0076002316, + 0.0023836761, + 0.0056440234, + 0.0015993814, + -0.006495336, + -0.0028799733, + -0.0044123367, + -0.01576559, + -0.021315426, + 0.01911288, + -0.022068929, + -0.037617162, + -0.001587608, + -0.0063794125, + 0.017605875, + 0.0054918737, + -0.019866383, + -0.041471615, + -0.007274197, + -0.032516528, + 0.026416058, + 0.020040268, + -0.011882154, + -0.0008101057, + 0.009911455, + -0.017272595, + 0.028053477, + -0.002573863, + 0.05468689, + -0.03689264, + 0.004408714, + -0.0013965154, + -0.021286445, + 0.017852213, + 0.019214313, + -0.04121079, + 0.029908251, + 0.003461402, + 0.038515568, + -0.009353574, + 0.029125769, + -0.0027459369, + 0.02985029, + -0.0030339342, + -0.018678168, + 0.040689133, + -0.006488091, + 0.029676406, + 0.03625506, + -0.009788287, + -0.019083899, + 0.012744335, + -0.01090405, + 0.044137858, + -0.005995416, + -0.016837882, + 0.022025457, + 0.012389319, + -0.046253458, + -0.018388359, + 0.017316066, + -0.012171963, + 0.00987523, + 0.0040500755, + 0.001626551, + -0.009440516, + -0.028879432, + -0.002937935, + -0.017316066, + -0.005951945, + 0.011983587, + 0.04094996, + -0.01975046, + -0.016649507, + 0.013715194, + 0.029343124, + -0.00313899, + 0.013381914, + -0.041181806, + -0.0321108, + -0.011317028, + 0.033414938, + -0.011230085, + -0.022605075, + -0.008049435, + -0.013483347, + -0.0008010492, + 0.0010125189, + -0.0443697, + -0.034690093, + 0.011990832, + 0.0013385536, + 0.0040283403, + -0.008629052, + -0.044137858, + -0.04828212, + -0.022213832, + -0.024677206, + -0.069206305, + 0.018214474, + -0.0010704807, + 0.0005184858, + 0.009773796, + 0.013519573, + 0.018721638, + 0.003521175, + -0.0237788, + -0.012831277 + ] + } + ], + "model": "text-embedding-3-small", + "usage": { + "prompt_tokens": 7, + "total_tokens": 7 + } + } + headers: + CF-RAY: + - 939c1708fdf87961-NRT + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Sat, 03 May 2025 01:47:23 GMT + Server: + - cloudflare + Set-Cookie: test_set_cookie + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + access-control-allow-origin: + - '*' + access-control-expose-headers: + - X-Request-ID + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + content-length: + - '33338' + openai-model: + - text-embedding-3-small + openai-organization: test_openai_org_id + openai-processing-ms: + - '89' + openai-version: + - '2020-10-01' + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + via: + - envoy-router-6546dd5b5b-cgzc4 + x-envoy-upstream-service-time: + - '27' + x-ratelimit-limit-requests: + - '5000' + x-ratelimit-limit-tokens: + - '5000000' + x-ratelimit-remaining-requests: + - '4999' + x-ratelimit-remaining-tokens: + - '4999992' + x-ratelimit-reset-requests: + - 12ms + x-ratelimit-reset-tokens: + - 0s + x-request-id: + - req_3db89a0fc1f707874dd19823da0aab4b + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference-conformance.yaml b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference-conformance.yaml new file mode 100644 index 00000000..2abb443f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference-conformance.yaml @@ -0,0 +1,134 @@ +interactions: +- request: + body: |- + { + "messages": [ + { + "role": "user", + "content": "Say this is a test" + } + ], + "model": "gpt-4o-mini", + "stream": false + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + authorization: + - Bearer test_openai_api_key + connection: + - keep-alive + content-length: + - '106' + content-type: + - application/json + host: + - api.openai.com + user-agent: + - OpenAI/Python 1.54.3 + x-stainless-arch: + - arm64 + x-stainless-async: + - 'false' + x-stainless-lang: + - python + x-stainless-os: + - MacOS + x-stainless-package-version: + - 1.54.3 + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.6 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: |- + { + "id": "chatcmpl-ASYMQRl3A3DXL9FWCK9tnGRcKIO7q", + "object": "chat.completion", + "created": 1731368630, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "This is a test.", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 12, + "completion_tokens": 5, + "total_tokens": 17, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": "fp_0ba0d124f1" + } + headers: + CF-Cache-Status: + - DYNAMIC + CF-RAY: + - 8e122593ff368bc8-SIN + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Mon, 11 Nov 2024 23:43:50 GMT + Server: + - cloudflare + Set-Cookie: test_set_cookie + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + access-control-expose-headers: + - X-Request-ID + alt-svc: + - h3=":443"; ma=86400 + content-length: + - '765' + openai-organization: test_openai_org_id + openai-processing-ms: + - '287' + openai-version: + - '2020-10-01' + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-ratelimit-limit-requests: + - '10000' + x-ratelimit-limit-tokens: + - '200000' + x-ratelimit-remaining-requests: + - '9999' + x-ratelimit-remaining-tokens: + - '199977' + x-ratelimit-reset-requests: + - 8.64s + x-ratelimit-reset-tokens: + - 6ms + x-request-id: + - req_58cff97afd0e7c0bba910ccf0b044a6f + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling-conformance.yaml b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling-conformance.yaml new file mode 100644 index 00000000..ebebb206 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling-conformance.yaml @@ -0,0 +1,342 @@ +interactions: +- request: + body: |- + { + "messages": [ + { + "role": "system", + "content": "You're a helpful assistant." + }, + { + "role": "user", + "content": "What's the weather in Seattle and San Francisco today?" + } + ], + "model": "gpt-4o-mini", + "tool_choice": "auto", + "tools": [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + } + }, + "required": [ + "location" + ], + "additionalProperties": false + } + } + } + ] + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + authorization: + - Bearer test_openai_api_key + connection: + - keep-alive + content-length: + - '543' + content-type: + - application/json + host: + - api.openai.com + user-agent: + - AsyncOpenAI/Python 1.26.0 + x-stainless-arch: + - arm64 + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - MacOS + x-stainless-package-version: + - 1.26.0 + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.5 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: |- + { + "id": "chatcmpl-ASv9ZqgNAOJAOLYMgdmxouatKXJlk", + "object": "chat.completion", + "created": 1731456245, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_O8NOz8VlxosSASEsOY7LDUcP", + "type": "function", + "function": { + "name": "get_current_weather", + "arguments": "{\"location\": \"Seattle, WA\"}" + } + }, + { + "id": "call_3m7cyuckijnpiWr6tq0Tl8Mg", + "type": "function", + "function": { + "name": "get_current_weather", + "arguments": "{\"location\": \"San Francisco, CA\"}" + } + } + ], + "refusal": null + }, + "logprobs": null, + "finish_reason": "tool_calls" + } + ], + "usage": { + "prompt_tokens": 75, + "completion_tokens": 51, + "total_tokens": 126, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": "fp_0ba0d124f1" + } + headers: + CF-Cache-Status: + - DYNAMIC + CF-RAY: + - 8e1a8098ac5ae167-MRS + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Wed, 13 Nov 2024 00:04:06 GMT + Server: + - cloudflare + Set-Cookie: test_set_cookie + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + access-control-expose-headers: + - X-Request-ID + alt-svc: + - h3=":443"; ma=86400 + content-length: + - '1308' + openai-organization: test_openai_org_id + openai-processing-ms: + - '937' + openai-version: + - '2020-10-01' + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-ratelimit-limit-requests: + - '30000' + x-ratelimit-limit-tokens: + - '150000000' + x-ratelimit-remaining-requests: + - '29999' + x-ratelimit-remaining-tokens: + - '149999960' + x-ratelimit-reset-requests: + - 2ms + x-ratelimit-reset-tokens: + - 0s + x-request-id: + - req_3cd7152d2c8c10b4f354b27165f6c2b5 + status: + code: 200 + message: OK +- request: + body: |- + { + "messages": [ + { + "role": "system", + "content": "You're a helpful assistant." + }, + { + "role": "user", + "content": "What's the weather in Seattle and San Francisco today?" + }, + { + "role": "assistant", + "tool_calls": [ + { + "id": "call_O8NOz8VlxosSASEsOY7LDUcP", + "function": { + "arguments": "{\"location\": \"Seattle, WA\"}", + "name": "get_current_weather" + }, + "type": "function" + }, + { + "id": "call_3m7cyuckijnpiWr6tq0Tl8Mg", + "function": { + "arguments": "{\"location\": \"San Francisco, CA\"}", + "name": "get_current_weather" + }, + "type": "function" + } + ] + }, + { + "role": "tool", + "content": "50 degrees and raining", + "tool_call_id": "call_O8NOz8VlxosSASEsOY7LDUcP" + }, + { + "role": "tool", + "content": "70 degrees and sunny", + "tool_call_id": "call_3m7cyuckijnpiWr6tq0Tl8Mg" + } + ], + "model": "gpt-4o-mini" + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + authorization: + - Bearer test_openai_api_key + connection: + - keep-alive + content-length: + - '746' + content-type: + - application/json + cookie: + - test_cookie + host: + - api.openai.com + user-agent: + - AsyncOpenAI/Python 1.26.0 + x-stainless-arch: + - arm64 + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - MacOS + x-stainless-package-version: + - 1.26.0 + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.5 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: |- + { + "id": "chatcmpl-ASv9aQnGndy04lqKoPRagym1eEaQK", + "object": "chat.completion", + "created": 1731456246, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Today, Seattle is experiencing 50 degrees and raining, while San Francisco has a pleasant 70 degrees and sunny weather.", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 99, + "completion_tokens": 24, + "total_tokens": 123, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": "fp_f59a81427f" + } + headers: + CF-Cache-Status: + - DYNAMIC + CF-RAY: + - 8e1a80a39c71e167-MRS + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Wed, 13 Nov 2024 00:04:07 GMT + Server: + - cloudflare + Set-Cookie: test_set_cookie + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + access-control-expose-headers: + - X-Request-ID + alt-svc: + - h3=":443"; ma=86400 + content-length: + - '871' + openai-organization: test_openai_org_id + openai-processing-ms: + - '477' + openai-version: + - '2020-10-01' + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-ratelimit-limit-requests: + - '30000' + x-ratelimit-limit-tokens: + - '150000000' + x-ratelimit-remaining-requests: + - '29999' + x-ratelimit-remaining-tokens: + - '149999948' + x-ratelimit-reset-requests: + - 2ms + x-ratelimit-reset-tokens: + - 0s + x-request-id: + - req_193c74758ea30e77e55afe931e89fd6c + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/__init__.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/__init__.py new file mode 100644 index 00000000..e57cf4ab --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/__init__.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py new file mode 100644 index 00000000..7445a737 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py @@ -0,0 +1,46 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: openai-v2 embeddings.""" + +from __future__ import annotations + +from typing import Any + +from openai import OpenAI + +from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + +class EmbeddingScenario(Scenario): + expected_spans = ("embeddings",) + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + with instrument( + OpenAIInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + semconv="gen_ai_latest_experimental", + content_capture="SPAN_ONLY", + ): + with vcr.use_cassette("embedding-conformance.yaml"): + OpenAI().embeddings.create( + input="The quick brown fox jumps over the lazy dog", + model="text-embedding-3-small", + ) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py new file mode 100644 index 00000000..72bb1b13 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py @@ -0,0 +1,47 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: openai-v2 chat completion (inference).""" + +from __future__ import annotations + +from typing import Any + +from openai import OpenAI + +from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + +class InferenceScenario(Scenario): + expected_spans = ("chat",) + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + with instrument( + OpenAIInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + semconv="gen_ai_latest_experimental", + content_capture="SPAN_ONLY", + ): + with vcr.use_cassette("inference-conformance.yaml"): + OpenAI().chat.completions.create( + messages=[{"role": "user", "content": "Say this is a test"}], + model="gpt-4o-mini", + stream=False, + ) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py new file mode 100644 index 00000000..cd0bfb3d --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py @@ -0,0 +1,127 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: openai-v2 chat completion with tool calls.""" + +from __future__ import annotations + +import json +from typing import Any + +from openai import OpenAI + +from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test.weaver_live_check import LiveCheckReport +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + +DEFAULT_MODEL = "gpt-4o-mini" +WEATHER_TOOL_PROMPT = [ + {"role": "system", "content": "You're a helpful assistant."}, + { + "role": "user", + "content": "What's the weather in Seattle and San Francisco today?", + }, +] +# Tool outputs are pinned to the recorded cassette's second request body. +WEATHER_BY_LOCATION: dict[str, str] = { + "Seattle, WA": "50 degrees and raining", + "San Francisco, CA": "70 degrees and sunny", +} + + +def _get_current_weather_tool_definition() -> dict[str, Any]: + return { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA", + }, + }, + "required": ["location"], + "additionalProperties": False, + }, + }, + } + + +def _execute_weather_tool(arguments: str) -> str: + location = json.loads(arguments)["location"] + return WEATHER_BY_LOCATION[location] + + +class ToolCallingScenario(Scenario): + expected_spans = ("chat",) + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + with instrument( + OpenAIInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + semconv="gen_ai_latest_experimental", + content_capture="SPAN_ONLY", + ): + with vcr.use_cassette("tool_calling-conformance.yaml"): + client = OpenAI() + messages: list[Any] = list(WEATHER_TOOL_PROMPT) + + first = client.chat.completions.create( + messages=messages, + model=DEFAULT_MODEL, + tool_choice="auto", + tools=[_get_current_weather_tool_definition()], + ) + + assistant_message = first.choices[0].message + messages.append( + assistant_message.model_dump(exclude_none=True) + ) + for tc in assistant_message.tool_calls or []: + messages.append( + { + "role": "tool", + "content": _execute_weather_tool( + tc.function.arguments + ), + "tool_call_id": tc.id, + } + ) + + client.chat.completions.create( + messages=messages, + model=DEFAULT_MODEL, + ) + + def validate(self, report: LiveCheckReport) -> None: + super().validate(report) + operations = [ + attr["value"] + for entry in report["samples"] + for attr in entry["span"]["attributes"] + if attr["name"] == "gen_ai.operation.name" + ] + assert operations == ["chat", "chat"], ( + "Tool calling exercises two chat completions (initial request and " + f"follow-up with tool results); saw spans {operations}" + ) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py index 7c90a736..a7338743 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py @@ -15,7 +15,10 @@ from opentelemetry.test_util_genai.instrumentor import instrument from opentelemetry.test_util_genai.vcr import scrub_response_headers_overwrite -pytest_plugins = ["opentelemetry.test_util_genai.fixtures"] +pytest_plugins = [ + "opentelemetry.test_util_genai.fixtures", + "opentelemetry.test_util_genai.vcr", +] @pytest.fixture(autouse=True) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py new file mode 100644 index 00000000..ed2ae561 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py @@ -0,0 +1,47 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Per-scenario conformance tests for openai-v2. + +Each scenario runs the instrumentation against a recorded API call and +validates the emitted telemetry against the GenAI semantic conventions via +Weaver live-check. +""" + +from __future__ import annotations + +from typing import Any + +import pytest + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck +from opentelemetry.test_util_genai.conformance import ( + Scenario, + run_conformance, +) + +from .conformance.embedding import EmbeddingScenario +from .conformance.inference import InferenceScenario +from .conformance.tool_calling import ToolCallingScenario + +pytestmark = pytest.mark.conformance + + +@pytest.mark.parametrize( + "scenario", + [ + InferenceScenario(), + pytest.param( + EmbeddingScenario(), + marks=pytest.mark.skip( + reason="openai-v2 embeddings emit legacy gen_ai.system in experimental mode" + ), + ), + ToolCallingScenario(), + ], + ids=lambda s: type(s).__name__, +) +def test_conformance( + scenario: Scenario, vcr: Any, weaver_live_check: WeaverLiveCheck +) -> None: + run_conformance(scenario, vcr=vcr, weaver=weaver_live_check) diff --git a/policies/genai_content_validation.rego b/policies/genai_content_validation.rego new file mode 100644 index 00000000..f5a4c89d --- /dev/null +++ b/policies/genai_content_validation.rego @@ -0,0 +1,53 @@ +# Validates the JSON payload of GenAI content attributes against the +# semconv JSON schemas. Schema constants (_schema_*) are defined in +# _schemas.rego, which is generated at test-run time from the semconv +# repository (docs/gen-ai/*.json) and placed alongside this file. +# Weaver only loads .rego files from --advice-policies, so schemas are +# inlined as Rego constants rather than loaded as OPA data documents. + +package live_check_advice + +import rego.v1 + +_genai_content_schemas := { + "gen_ai.input.messages": _schema_input_messages, + "gen_ai.output.messages": _schema_output_messages, + "gen_ai.system_instructions": _schema_system_instructions, + "gen_ai.tool.definitions": _schema_tool_definitions, + "gen_ai.retrieval.documents": _schema_retrieval_documents, +} + +deny contains result if { + input.sample.attribute + attr_name := input.sample.attribute.name + attr_value := input.sample.attribute.value + is_string(attr_value) + + schema := _genai_content_schemas[attr_name] + # Skip when the schema constant isn't present in the pinned semconv + # version yet (the script emits `null` stubs for forward-looking + # attributes like `gen_ai.tool.definitions` until upstream catches up). + schema != null + + parsed := json.unmarshal(attr_value) + + [matched, errors] := json.match_schema(parsed, schema) + not matched + + # PolicyFinding format per + # https://github.com/open-telemetry/weaver/blob/main/crates/weaver_live_check/README.md#policyfinding + # (id / level / context / message; signal_* omitted because the sample + # is attribute-level and weaver doesn't surface the parent span here). + result := { + "id": "genai_content_schema", + "level": "violation", + "context": { + "attribute": attr_name, + "errors": errors, + }, + "message": sprintf( + "Attribute '%v' value does not conform to the GenAI schema: %v", + [attr_name, errors], + ), + } +} diff --git a/policies/genai_span_validation.rego b/policies/genai_span_validation.rego new file mode 100644 index 00000000..e85c8453 --- /dev/null +++ b/policies/genai_span_validation.rego @@ -0,0 +1,246 @@ +# Validates GenAI span shape beyond what weaver's semconv-registry-driven +# checks already enforce. The registry validates per-attribute requirements +# (name, type, presence) for spans matching its definitions; this file adds +# cross-cutting span-level invariants the registry can't easily express. +# +# Two classes of rules, both keyed on `gen_ai.operation.name`: +# +# 1. Span name format → `violation` +# (`{operation_name} {request_model}` for inference / embeddings, +# `{operation_name} {agent_name}` for invoke_agent / create_agent, +# `{operation_name} {tool_name}` for execute_tool). +# +# 2. Per-operation expected attributes → `violation` +# Combines `Required` (always must be set) and the always-emit subset +# of `Recommended` (e.g. response model/id, token usage on inference) +# into one manifest per operation. Sourced from the rendered tables in +# semantic-conventions/docs/gen-ai/gen-ai-spans.md and +# gen-ai-agent-spans.md (the MD flattens the YAML inheritance chain +# via `extends:`, so it's the right place to source from). +# +# The "set when known" Recommended subset (sampling parameters like +# `frequency_penalty`, `max_tokens`; provider-side caches; conditionally- +# emitted things like `gen_ai.response.time_to_first_chunk` for streaming) +# is deliberately NOT flagged here — those depend on user input or on the +# request shape and would produce noisy false positives. Cross-attribute +# conditional rules (e.g. "if streaming, response.time_to_first_chunk +# SHOULD be set") would also belong here. +# +# Required attributes are also flagged by weaver's registry-driven +# validation. Listing them here too is intentional: rego rules give us +# stable advice ids to grep for in reports and let us tighten the check +# regardless of how the registry classifies the gap. +# +# Attribute access: weaver hands rego a span sample where `attributes` is a +# **list** of `{name, value, type}` objects, not a dict — `_attr(name)` +# walks that list and returns the value (or `null` if absent). + +package live_check_advice + +import rego.v1 + +# ─── Operation classification ─────────────────────────────────────────────── +# +# Mirrors the semconv `gen_ai.operation.name` enum +# (model/gen-ai/registry.yaml). When semconv adds a new operation, append it +# to the matching set below — or leave it out if the new operation has its +# own span definition with different conventions. + +_inference_ops := {"chat", "generate_content", "text_completion"} + +_embeddings_ops := {"embeddings"} + +_tool_ops := {"execute_tool"} + +_invoke_agent_ops := {"invoke_agent"} + +_create_agent_ops := {"create_agent"} + +# ─── Span name format (violation) ─────────────────────────────────────────── + +_span_name_keyed_attr["chat"] := "gen_ai.request.model" +_span_name_keyed_attr["generate_content"] := "gen_ai.request.model" +_span_name_keyed_attr["text_completion"] := "gen_ai.request.model" +_span_name_keyed_attr["embeddings"] := "gen_ai.request.model" +_span_name_keyed_attr["execute_tool"] := "gen_ai.tool.name" +_span_name_keyed_attr["invoke_agent"] := "gen_ai.agent.name" +_span_name_keyed_attr["create_agent"] := "gen_ai.agent.name" + +# Span name SHOULD be `{op}` (when the keyed attribute is absent) or +# `{op} {value}` (when present). Mirrors the "SHOULD append when known" +# guidance in semconv. +# +# Avoid `%v ` patterns in sprintf: weaver 0.22.1's OPA-based sprintf +# consumes a single space character immediately following any verb (`%v`, +# `%s`, `%d`) — interpreting it as Go's space-flag — so `%v %v` produces +# `` instead of ` `. We use `concat` for the literal-space +# joins below. +deny contains _span_finding( + "genai_span_name_format", + "violation", + input.sample.span, + { + "operation": op, + "keyed_attr": keyed_attr, + "expected_form": concat("", [op, " or '", op, " <", keyed_attr, ">'"]), + }, + concat("", [ + op, " span name should be '", + op, "' or '", + op, " ', got '", + input.sample.span.name, "'", + ]), +) if { + input.sample.span + op := _attr_value(input.sample.span, "gen_ai.operation.name") + keyed_attr := _span_name_keyed_attr[op] + not _valid_op_and_attr_span_name(input.sample.span, op, keyed_attr) +} + +# ─── Per-operation expected attributes (violation) ────────────────────────── + +_expected_for_op["chat"] := _inference_expected + +_expected_for_op["generate_content"] := _inference_expected + +_expected_for_op["text_completion"] := _inference_expected + +_expected_for_op["embeddings"] := _embeddings_expected + +_expected_for_op["execute_tool"] := _execute_tool_expected + +_expected_for_op["invoke_agent"] := _invoke_agent_expected + +_expected_for_op["create_agent"] := _create_agent_expected + +_expected_for_op["retrieval"] := _retrieval_expected + +# Inference (chat / generate_content / text_completion). +# Required: gen_ai.operation.name, gen_ai.provider.name. +# Always-emit Recommended: response model/id, finish reasons, token usage, +# server.address. Sampling parameters (frequency_penalty, max_tokens, …), +# cache counters, and `gen_ai.response.time_to_first_chunk` (streaming-only) +# are conditional and not flagged here. +_inference_expected := { + "gen_ai.operation.name", + "gen_ai.provider.name", + "gen_ai.response.model", + "gen_ai.response.id", + "gen_ai.response.finish_reasons", + "gen_ai.usage.input_tokens", + "gen_ai.usage.output_tokens", + # "server.address", sometimes not available +} + +# Embeddings. +# Required: gen_ai.operation.name, gen_ai.provider.name. +# Always-emit Recommended: dimension.count, response.model, input tokens, +# server.address. (`gen_ai.request.encoding_formats` is conditional.) +_embeddings_expected := { + "gen_ai.operation.name", + "gen_ai.provider.name", + "gen_ai.embeddings.dimension.count", + "gen_ai.response.model", + "gen_ai.usage.input_tokens", + # "server.address", sometimes not available +} + +# Tool execution. +# Required: gen_ai.operation.name, gen_ai.tool.name. +# Recommended-when-available: gen_ai.tool.call.id, gen_ai.tool.type. (Tool +# description is genuinely optional per provider — not flagged.) +_execute_tool_expected := { + "gen_ai.operation.name", + "gen_ai.tool.name", + "gen_ai.tool.call.id", + "gen_ai.tool.type", +} + +# Invoke agent. +# Required: gen_ai.operation.name, gen_ai.provider.name. +# Most instrumentations should have agent.id; flag it as always-emit. +_invoke_agent_expected := { + "gen_ai.operation.name", + "gen_ai.provider.name", + "gen_ai.agent.id", +} + +# Create agent. After creation completes the provider returns an agent.id; +# flag it as always-emit on create_agent. +_create_agent_expected := { + "gen_ai.operation.name", + "gen_ai.provider.name", + "gen_ai.agent.id", +} + +# Retrieval. Only gen_ai.operation.name is unconditionally required. +_retrieval_expected := { + "gen_ai.operation.name", + # "server.address", sometimes not available +} + +# Per expected attribute, one violation if missing. +deny contains _span_finding( + "genai_expected_attribute_missing", + "violation", + input.sample.span, + { + "operation": op, + "missing_attribute": attr_name, + }, + sprintf( + "Span '%v' (operation '%v') is missing expected attribute '%v'", + [input.sample.span.name, op, attr_name], + ), +) if { + input.sample.span + op := _attr_value(input.sample.span, "gen_ai.operation.name") + expected := _expected_for_op[op] + some attr_name in expected + not _has_attr(input.sample.span, attr_name) +} + +# ─── Helpers ──────────────────────────────────────────────────────────────── + +# Span attributes arrive as `[{"name": ..., "value": ..., "type": ...}]`. + +# True when the span has an attribute named `name`. +_has_attr(span, name) if { + some attr in span.attributes + attr.name == name +} + +# Returns the value of the named attribute. Undefined (rule body fails) when +# the attribute isn't present — callers must guard with `_has_attr` first if +# they need to distinguish "absent" from "set to a falsy value". +_attr_value(span, name) := value if { + some attr in span.attributes + attr.name == name + value := attr.value +} + +# A valid span name is either exactly `{op}` (when the keyed attribute is +# absent) or `{op} {value}` (when present). +_valid_op_and_attr_span_name(span, op, attr_key) if { + span.name == op + not _has_attr(span, attr_key) +} + +_valid_op_and_attr_span_name(span, op, attr_key) if { + value := _attr_value(span, attr_key) + # concat (not sprintf): see the note above the deny rule. sprintf("%v %v", ...) + # silently produces "" with no space, so every span with a `{op} {value}` + # name would be reported as a violation. + span.name == concat(" ", [op, value]) +} + +# PolicyFinding format per +# https://github.com/open-telemetry/weaver/blob/main/crates/weaver_live_check/README.md#policyfinding +_span_finding(id, level, span, context, message) := { + "id": id, + "level": level, + "signal_type": "span", + "signal_name": span.name, + "context": context, + "message": message, +} diff --git a/pyproject.toml b/pyproject.toml index 332c3760..99dcd7e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,19 @@ opentelemetry-instrumentation-openai-v2 = { workspace = true } opentelemetry-instrumentation-openai-agents-v2 = { workspace = true } opentelemetry-instrumentation-weaviate = { workspace = true } +# `opentelemetry.test.weaver_live_check` (used by conformance tests) is on +# main but not yet on PyPI (latest opentelemetry-test-utils is 0.62b1). Pin +# the whole otel-core stack to git+main so versions resolve coherently; +# drop once the file ships. +opentelemetry-api = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-api" } +opentelemetry-sdk = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-sdk" } +opentelemetry-semantic-conventions = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-semantic-conventions" } +opentelemetry-test-utils = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "tests/opentelemetry-test-utils" } +opentelemetry-instrumentation = { git = "https://github.com/open-telemetry/opentelemetry-python-contrib", branch = "main", subdirectory = "opentelemetry-instrumentation" } +opentelemetry-exporter-otlp-proto-grpc = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "exporter/opentelemetry-exporter-otlp-proto-grpc" } +opentelemetry-exporter-otlp-proto-common = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "exporter/opentelemetry-exporter-otlp-proto-common" } +opentelemetry-proto = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-proto" } + # https://docs.astral.sh/uv/reference/settings/#workspace [tool.uv.workspace] members = [ diff --git a/pytest.ini b/pytest.ini index 013d2c55..4e8b8a74 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,3 +2,5 @@ addopts = -rs -v log_cli = true log_cli_level = warning +markers = + conformance: GenAI semconv conformance scenario (run via the *-conformance tox envs) diff --git a/tox.ini b/tox.ini index e2195879..facb4e0a 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,7 @@ envlist = ; instrumentation-openai py3{10,11,12,13,14}-test-instrumentation-openai-v2-{oldest,latest} pypy3-test-instrumentation-openai-v2-{oldest,latest} + py3{12,13}-test-instrumentation-openai-v2-conformance lint-instrumentation-openai-v2 ; instrumentation-openai-agents @@ -25,6 +26,7 @@ envlist = ; instrumentation-anthropic py3{10,11,12,13,14}-test-instrumentation-anthropic-{oldest,latest} # Disabling pypy3 as jiter (anthropic dep) requires PyPy 3.11+ + py3{12,13}-test-instrumentation-anthropic-conformance lint-instrumentation-anthropic ; instrumentation-claude-agent-sdk @@ -36,6 +38,7 @@ envlist = ; TODO: add tests/requirements.{oldest,latest}.txt and langchain-{oldest,latest} ; factors below; declare opentelemetry-util-genai in the package pyproject.toml ; (latent bug — code imports it but it's not in runtime deps). + py3{12,13}-test-instrumentation-langchain-conformance lint-instrumentation-langchain ; instrumentation-weaviate @@ -70,6 +73,7 @@ pytest_deps = pytest-vcr -e {toxinidir}/util/opentelemetry-test-util-genai deps = + conformance: -r {toxinidir}/dev-requirements-conformance.txt lint: -r dev-requirements.txt coverage: pytest coverage: pytest-cov @@ -81,6 +85,8 @@ deps = openai-latest: {[testenv]test_deps} openai-latest: {[testenv]pytest_deps} openai-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests/requirements.latest.txt + openai-conformance: {[testenv]pytest_deps} + openai-conformance: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests/requirements.latest.txt lint-instrumentation-openai-v2: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests/requirements.oldest.txt openai_agents-oldest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-agents-v2/tests/requirements.oldest.txt @@ -102,6 +108,8 @@ deps = anthropic-latest: {[testenv]test_deps} anthropic-latest: {[testenv]pytest_deps} anthropic-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests/requirements.latest.txt + anthropic-conformance: {[testenv]pytest_deps} + anthropic-conformance: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests/requirements.latest.txt lint-instrumentation-anthropic: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests/requirements.oldest.txt claude-agent-sdk-oldest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-claude-agent-sdk/tests/requirements.oldest.txt @@ -111,6 +119,14 @@ deps = claude-agent-sdk-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-claude-agent-sdk/tests/requirements.latest.txt lint-instrumentation-claude-agent-sdk: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-claude-agent-sdk/tests/requirements.oldest.txt + ; Langchain has no oldest/latest matrix yet (TODO above); pin the client + ; libs the conftest imports inline. + langchain-conformance: {[testenv]pytest_deps} + langchain-conformance: {toxinidir}/instrumentation/opentelemetry-instrumentation-langchain[instruments] + langchain-conformance: langchain-openai + langchain-conformance: langchain-aws + langchain-conformance: langchain-google-genai + langchain-conformance: boto3 util-genai: {[testenv]test_deps} util-genai: {[testenv]pytest_deps} @@ -130,7 +146,8 @@ commands_pre = coverage: python {toxinidir}/scripts/eachdist.py install --editable commands = - test-instrumentation-openai-v2: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests {posargs} + test-instrumentation-openai-v2-{oldest,latest}: pytest -m "not conformance" {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests {posargs} + test-instrumentation-openai-v2-conformance: pytest -m conformance {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests --vcr-record=none {posargs} lint-instrumentation-openai-v2: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-openai-v2" test-instrumentation-openai_agents-v2: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-agents-v2/tests {posargs} lint-instrumentation-openai_agents-v2: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-openai-agents-v2" @@ -138,12 +155,14 @@ commands = test-instrumentation-google-genai: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-google-genai/tests --vcr-record=none {posargs} lint-instrumentation-google-genai: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-google-genai" - test-instrumentation-anthropic: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests --vcr-record=none {posargs} + test-instrumentation-anthropic-{oldest,latest}: pytest -m "not conformance" {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests --vcr-record=none {posargs} + test-instrumentation-anthropic-conformance: pytest -m conformance {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests --vcr-record=none {posargs} lint-instrumentation-anthropic: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-anthropic" test-instrumentation-claude-agent-sdk: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-claude-agent-sdk/tests --vcr-record=none {posargs} lint-instrumentation-claude-agent-sdk: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-claude-agent-sdk" + test-instrumentation-langchain-conformance: pytest -m conformance {toxinidir}/instrumentation/opentelemetry-instrumentation-langchain/tests --vcr-record=none {posargs} lint-instrumentation-langchain: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-langchain" lint-instrumentation-weaviate: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-weaviate" diff --git a/util/opentelemetry-test-util-genai/pyproject.toml b/util/opentelemetry-test-util-genai/pyproject.toml index 2cbe24f4..7c79206d 100644 --- a/util/opentelemetry-test-util-genai/pyproject.toml +++ b/util/opentelemetry-test-util-genai/pyproject.toml @@ -15,9 +15,12 @@ dependencies = [ "opentelemetry-instrumentation", "opentelemetry-sdk", "opentelemetry-semantic-conventions", + "opentelemetry-test-utils", "opentelemetry-util-genai", "pytest", "PyYAML", + # PyPy lacks grpcio wheels; the weaver fixture skips when this import fails. + 'opentelemetry-exporter-otlp-proto-grpc; implementation_name != "pypy"', ] [tool.hatch.build.targets.wheel] diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py new file mode 100644 index 00000000..9e05315d --- /dev/null +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py @@ -0,0 +1,164 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Provision advice policies and the semconv registry for weaver. + +The weaver binary is installed by CI (see ``.github/workflows/test.yml``) +or locally by the contributor — this module only handles the schema / registry +side. Both ``policies_dir()`` and ``semconv_registry()`` read the +``SEMCONV_VERSION`` pin from ``versions.env`` and share one cached +semantic-conventions tarball. +""" + +from __future__ import annotations + +import json +import logging +import os +import shutil +import tarfile +import tempfile +import urllib.request +from pathlib import Path +from typing import Any + +logger = logging.getLogger(__name__) + + +def _workspace_root() -> Path: + here = Path(__file__).resolve() + for ancestor in here.parents: + if (ancestor / "versions.env").is_file() and ( + ancestor / "policies" + ).is_dir(): + return ancestor + raise RuntimeError( + f"Could not locate the genai workspace root (walked up from {here} " + "looking for versions.env + policies/)." + ) + + +def _load_version_pins() -> dict[str, str]: + content = (_workspace_root() / "versions.env").read_text(encoding="utf-8") + pins: dict[str, str] = {} + for raw_line in content.splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + key, sep, value = line.partition("=") + if not sep: + raise RuntimeError( + f"Invalid version pin in versions.env: {raw_line!r}" + ) + pins[key.strip()] = value.strip().strip('"').strip("'") + return pins + + +def _cache_dir() -> Path: + override = os.environ.get("SEMCONV_CACHE") + if override: + return Path(override) + return Path.home() / ".cache" / "otel-conformance" / "semconv" + + +def _fetch_semconv(version: str) -> Path: + """Download `semantic-conventions` at ``version`` and return the extracted root.""" + cache_root = _cache_dir() + safe = version.replace("/", "_") + target = cache_root / safe + if (target / "model").is_dir() and (target / "docs" / "gen-ai").is_dir(): + return target + + cache_root.mkdir(parents=True, exist_ok=True) + url = ( + "https://github.com/open-telemetry/semantic-conventions/" + f"archive/refs/tags/{version}.tar.gz" + ) + with tempfile.TemporaryDirectory( + dir=str(cache_root), prefix=f"semconv-{safe}-" + ) as tmp: + tmp_path = Path(tmp) + archive_path = tmp_path / "src.tar.gz" + extract_dir = tmp_path / "extract" + extract_dir.mkdir() + + logger.info("Fetching semantic-conventions @ %s", version) + with ( + urllib.request.urlopen(url) as response, + archive_path.open("wb") as out, + ): + shutil.copyfileobj(response, out) + with tarfile.open(archive_path, "r:gz") as archive: + archive.extractall(extract_dir, filter="data") + + entries = [p for p in extract_dir.iterdir() if p.is_dir()] + if len(entries) != 1: + raise RuntimeError( + "Unexpected layout in semantic-conventions archive: " + f"{[p.name for p in entries]}" + ) + if target.exists(): + shutil.rmtree(target) + shutil.move(str(entries[0]), str(target)) + return target + + +def _semconv_root() -> Path: + return _fetch_semconv(_load_version_pins()["SEMCONV_VERSION"]) + + +# `_schema_` constants referenced from +# policies/genai_content_validation.rego. +_GENAI_SCHEMA_FILES: dict[str, str] = { + "input_messages": "gen-ai-input-messages.json", + "output_messages": "gen-ai-output-messages.json", + "system_instructions": "gen-ai-system-instructions.json", + "tool_definitions": "gen-ai-tool-definitions.json", + "retrieval_documents": "gen-ai-retrieval-documents.json", +} + + +def _generate_schemas_rego(schemas: dict[str, Any]) -> str: + lines = [ + "# Auto-generated from semantic-conventions. Do not edit.", + "# Re-generated each time _setup_weaver.policies_dir() runs.", + "package live_check_advice", + "", + "import rego.v1", + "", + ] + for key, schema in schemas.items(): + if schema is None: + lines.append(f"_schema_{key} := null") + else: + # indent=2 to stay under weaver's 1024-char-per-line rego limit. + lines.append(f"_schema_{key} := {json.dumps(schema, indent=2)}") + lines.append("") + return "\n".join(lines) + + +def policies_dir() -> Path: + """Write ``policies/_schemas.rego`` and return the policies directory.""" + docs_genai = _semconv_root() / "docs" / "gen-ai" + + schemas: dict[str, Any] = {} + for key, filename in _GENAI_SCHEMA_FILES.items(): + schema_path = docs_genai / filename + if schema_path.exists(): + schemas[key] = json.loads(schema_path.read_text(encoding="utf-8")) + else: + logger.warning( + "GenAI schema not found: %s (emitting null stub)", schema_path + ) + schemas[key] = None + + policies = _workspace_root() / "policies" + (policies / "_schemas.rego").write_text( + _generate_schemas_rego(schemas), encoding="utf-8" + ) + return policies + + +def semconv_registry() -> Path: + """Return the path to ``/model`` for the pinned tag.""" + return _semconv_root() / "model" diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py new file mode 100644 index 00000000..1fd40eac --- /dev/null +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py @@ -0,0 +1,189 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Per-scenario conformance runner for GenAI instrumentations. + +Intended call shape from a per-package ``tests/test_conformance.py``:: + + pytestmark = pytest.mark.conformance + + @pytest.mark.parametrize( + "scenario", [InferenceScenario(), ToolCallingScenario()] + ) + def test_conformance(scenario, vcr, weaver_live_check): + report = run_conformance(scenario, vcr=vcr, weaver=weaver_live_check) + # Optionally layer lib-specific assertions on `report` here. + +The module-level ``pytestmark = pytest.mark.conformance`` is required: the +``*-conformance`` tox envs select these tests via ``-m conformance``, and the +regular ``*-{oldest,latest}`` envs deselect them via ``-m "not conformance"``. + +Each ``tests/conformance/.py`` defines a :class:`Scenario` subclass with: + +- ``expected_spans`` — ``gen_ai.operation.name`` values that must appear in + the report's span samples. +- ``expected_metrics`` — metric names that must appear in + ``statistics.seen_registry_metrics``. +- ``run(*, tracer_provider, meter_provider, logger_provider, vcr)`` — wires + the instrumentor against the providers and exercises one semconv operation + type's happy path inside ``vcr.use_cassette(...)``. +- ``validate(report)`` — asserts the emitted telemetry matches the scenario. + The base implementation enforces ``expected_spans`` / ``expected_metrics`` + presence; per-scenario overrides call ``super().validate(report)`` and + layer on additional checks against the weaver report. +""" + +from __future__ import annotations + +import json +from abc import ABC, abstractmethod +from pathlib import Path +from typing import Any, ClassVar + +from opentelemetry._logs import set_logger_provider +from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( + OTLPLogExporter, +) +from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( + OTLPMetricExporter, +) +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( + OTLPSpanExporter, +) +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk._logs.export import SimpleLogRecordProcessor +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import SimpleSpanProcessor +from opentelemetry.test.weaver_live_check import ( + LiveCheckReport, + WeaverLiveCheck, +) + + +class Scenario(ABC): + """Base class every ``tests/conformance/.py`` scenario must subclass.""" + + expected_spans: ClassVar[tuple[str, ...]] = () + expected_metrics: ClassVar[tuple[str, ...]] = () + + @abstractmethod + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: ... + + def validate(self, report: LiveCheckReport) -> None: + """Assert the weaver live-check report matches the scenario. + + The base implementation enforces that every ``expected_spans`` and + ``expected_metrics`` entry appears at least once. Subclasses should + override and call ``super().validate(report)`` to layer on extra + scenario-specific checks against the report. + """ + expected_spans = set(self.expected_spans) + seen_spans = _seen_span_operations(report) + missing_spans = expected_spans - seen_spans + assert not missing_spans, ( + f"Expected span operations {sorted(expected_spans)} but weaver " + f"only saw {sorted(seen_spans)} — missing {sorted(missing_spans)}" + ) + + expected_metrics = set(self.expected_metrics) + seen_metrics = _seen_metric_names(report) + missing_metrics = expected_metrics - seen_metrics + assert not missing_metrics, ( + f"Expected metrics {sorted(expected_metrics)} but weaver only " + f"saw {sorted(seen_metrics)} — missing {sorted(missing_metrics)}" + ) + + +def _build_providers( + endpoint: str, +) -> tuple[TracerProvider, MeterProvider, LoggerProvider]: + tracer_provider = TracerProvider() + tracer_provider.add_span_processor( + SimpleSpanProcessor(OTLPSpanExporter(endpoint=endpoint, insecure=True)) + ) + + # Disable periodic export — metrics flush via the explicit force_flush() + # at the end of the scenario, so the report is deterministic. + metric_reader = PeriodicExportingMetricReader( + OTLPMetricExporter(endpoint=endpoint, insecure=True), + export_interval_millis=2**31 - 1, + ) + meter_provider = MeterProvider(metric_readers=[metric_reader]) + + logger_provider = LoggerProvider() + logger_provider.add_log_record_processor( + SimpleLogRecordProcessor( + OTLPLogExporter(endpoint=endpoint, insecure=True) + ) + ) + # Some instrumentations resolve the logger off the module-level global + # instead of the per-instrumentor provider. + set_logger_provider(logger_provider) + + return tracer_provider, meter_provider, logger_provider + + +def _seen_metric_names(report: LiveCheckReport) -> set[str]: + """Names of metrics weaver observed at least one data point for.""" + seen = report["statistics"]["seen_registry_metrics"] + return {name for name, count in seen.items() if count} + + +def _seen_span_operations(report: LiveCheckReport) -> set[str]: + """`gen_ai.operation.name` values observed across the report's span samples.""" + return { + attr["value"] + for entry in report["samples"] + for attr in entry["span"]["attributes"] + if attr["name"] == "gen_ai.operation.name" + } + + +def _dump_report(report: LiveCheckReport) -> None: + out = Path("weaver_reports") / "full.json" + out.parent.mkdir(parents=True, exist_ok=True) + out.write_text(json.dumps(report, indent=2, sort_keys=True)) + + +def run_conformance( + scenario: Scenario, + *, + vcr: Any, + weaver: WeaverLiveCheck, +) -> LiveCheckReport: + """Run one conformance scenario and return the weaver report. + + Raises :class:`LiveCheckError` on semconv violations. + """ + tracer_provider, meter_provider, logger_provider = _build_providers( + weaver.otlp_endpoint + ) + + try: + scenario.run( + tracer_provider=tracer_provider, + meter_provider=meter_provider, + logger_provider=logger_provider, + vcr=vcr, + ) + tracer_provider.force_flush() + meter_provider.force_flush() + logger_provider.force_flush() + + report = weaver.end_and_check() + _dump_report(report) + scenario.validate(report) + return report + finally: + tracer_provider.shutdown() + meter_provider.shutdown() + logger_provider.shutdown() diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py index d633acb5..69c81667 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py @@ -18,22 +18,34 @@ friends) are deliberately **not** set so tests stay isolated and don't leak across the session. -Two-mode parametrization ------------------------- +Parametrized fixtures +--------------------- -``content_capture`` is a parametrized fixture that yields each -``ContentCapturingMode`` enum value in ``CONTENT_CAPTURE_MODES`` in turn -(``NO_CONTENT`` and ``SPAN_ONLY``). It sets +``content_capture`` yields each ``ContentCapturingMode`` enum value in +``CONTENT_CAPTURE_MODES`` in turn (``NO_CONTENT`` and ``SPAN_ONLY``). It sets ``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`` for the duration of the test and restores the previous value afterwards. ``SPAN_AND_EVENT`` and ``EVENT_ONLY`` coverage lives in targeted per-package tests rather than the default matrix. + +Conformance fixture +------------------- + +``weaver_live_check`` yields a started ``WeaverLiveCheck`` for a single +conformance scenario. Consumed by ``tests/test_conformance.py`` via +``opentelemetry.test_util_genai.conformance.run_conformance``. Auto-skips +when the OTLP/gRPC exporter or the ``weaver`` binary aren't available — +local runs typically skip; CI installs ``weaver`` ahead of the +``*-conformance`` tox envs. """ from __future__ import annotations import os +import shutil +import tarfile from collections.abc import Iterator +from typing import Any import pytest @@ -51,6 +63,10 @@ from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) +from opentelemetry.test_util_genai._setup_weaver import ( + policies_dir, + semconv_registry, +) from opentelemetry.util.genai.environment_variables import ( OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, ) @@ -156,3 +172,42 @@ def content_capture( os.environ[OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT] = ( previous ) + + +# ─── Weaver live-check ────────────────────────────────────────────────────── + + +@pytest.fixture +def weaver_live_check() -> Iterator[Any]: + """Yield a started ``WeaverLiveCheck`` for one conformance scenario. + + Function-scoped so violations don't leak across scenarios. Auto-skips + when the OTLP/gRPC exporter, the ``weaver`` binary, or the + semantic-conventions registry can't be resolved. + """ + try: + import opentelemetry.exporter.otlp.proto.grpc.trace_exporter # noqa: F401, PLC0415 + except ImportError: + pytest.skip("opentelemetry-exporter-otlp-proto-grpc not installed") + + if shutil.which("weaver") is None: + pytest.skip( + "weaver binary not on PATH — install it from " + "https://github.com/open-telemetry/weaver/releases (CI installs " + "it via the test.yml conformance setup step)" + ) + + # WeaverLiveCheck transitively imports the OTLP/gRPC exporter, so it + # stays inside the function body — the probe above is what gates this. + from opentelemetry.test.weaver_live_check import ( # noqa: PLC0415 + WeaverLiveCheck, + ) + + try: + policies = str(policies_dir()) + registry = str(semconv_registry()) + except (OSError, RuntimeError, ValueError, tarfile.TarError) as exc: + pytest.skip(f"could not provision semantic-conventions: {exc}") + + with WeaverLiveCheck(registry=registry, policies_dir=policies) as weaver: + yield weaver diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/vcr.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/vcr.py index 654ad9e2..78f4632b 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/vcr.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/vcr.py @@ -130,20 +130,6 @@ def fixture_vcr(vcr: Any) -> Any: return vcr -@pytest.fixture -def vcr_cassette_name(request: pytest.FixtureRequest) -> str: - """Cassette name = the test function name, without parametrize suffix. - - Override of pytest-vcr's default, which uses ``request.node.name`` and - so includes the ``[...]`` parametrize ID — causing tests that fan out - via the shared ``content_capture`` matrix to look for cassettes named - ``test_foo[NO_CONTENT].yaml`` instead of ``test_foo.yaml``. The actual - HTTP request is identical across capture-mode cells, so all cells - share the same cassette. - """ - return request.node.originalname or request.node.name - - def scrub_response_headers( headers_to_scrub: Iterable[str], ) -> Callable[[dict[str, Any]], dict[str, Any]]: diff --git a/uv.lock b/uv.lock index bc79288e..491f59d9 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,11 @@ version = 1 revision = 3 requires-python = ">=3.10" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version < '3.13'", +] [manifest] members = [ @@ -19,7 +24,7 @@ members = [ [[package]] name = "annotated-types" version = "0.7.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, @@ -28,7 +33,7 @@ wheels = [ [[package]] name = "anthropic" version = "0.101.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -47,7 +52,7 @@ wheels = [ [[package]] name = "anyio" version = "4.13.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, @@ -61,7 +66,7 @@ wheels = [ [[package]] name = "asgiref" version = "3.11.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -73,7 +78,7 @@ wheels = [ [[package]] name = "attrs" version = "26.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, @@ -82,7 +87,7 @@ wheels = [ [[package]] name = "authlib" version = "1.7.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "joserfc" }, @@ -95,7 +100,7 @@ wheels = [ [[package]] name = "cachetools" version = "7.1.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ff/e2/85f227594656000ff4d8adadae91a21f536d4a84c6c716a86bd6685874be/cachetools-7.1.1.tar.gz", hash = "sha256:27bdf856d68fd3c71c26c01b5edc312124ed427524d1ddb31aa2b7746fe20d4b", size = 40202, upload-time = "2026-05-03T20:00:29.391Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/bf/0f/f897abe4ea0a8c408ae65c8c83bffab4936ad65d6032d4fb4cd35bbdc3ee/cachetools-7.1.1-py3-none-any.whl", hash = "sha256:0335cd7a0952d2b22327441fb0628139e234c565559eeb91a8a4ac7551c5353d", size = 16775, upload-time = "2026-05-03T20:00:27.857Z" }, @@ -104,7 +109,7 @@ wheels = [ [[package]] name = "certifi" version = "2026.4.22" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, @@ -113,7 +118,7 @@ wheels = [ [[package]] name = "cffi" version = "2.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] @@ -195,7 +200,7 @@ wheels = [ [[package]] name = "cfgv" version = "3.5.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, @@ -204,7 +209,7 @@ wheels = [ [[package]] name = "charset-normalizer" version = "3.4.7" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, @@ -309,7 +314,7 @@ wheels = [ [[package]] name = "claude-agent-sdk" version = "0.1.81" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "mcp" }, @@ -328,7 +333,7 @@ wheels = [ [[package]] name = "click" version = "8.3.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -340,7 +345,7 @@ wheels = [ [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -349,7 +354,7 @@ wheels = [ [[package]] name = "cryptography" version = "48.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, @@ -409,7 +414,7 @@ wheels = [ [[package]] name = "distlib" version = "0.4.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, @@ -418,7 +423,7 @@ wheels = [ [[package]] name = "distro" version = "1.9.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, @@ -427,7 +432,7 @@ wheels = [ [[package]] name = "docstring-parser" version = "0.18.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, @@ -436,7 +441,7 @@ wheels = [ [[package]] name = "exceptiongroup" version = "1.3.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] @@ -448,7 +453,7 @@ wheels = [ [[package]] name = "filelock" version = "3.29.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, @@ -457,7 +462,7 @@ wheels = [ [[package]] name = "fsspec" version = "2026.4.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" }, @@ -466,7 +471,7 @@ wheels = [ [[package]] name = "google-auth" version = "2.52.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, @@ -484,7 +489,7 @@ requests = [ [[package]] name = "google-genai" version = "2.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -502,10 +507,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/1d/a9080b9d03a106d4ebc95ac5667b094b9765abd3ee0564b1bd8a19b0a3f1/google_genai-2.1.0-py3-none-any.whl", hash = "sha256:7d0d6759fb1bc8ca3ee3ef1025cc796a4341d4d22ca5fa36c254161882545e9a", size = 803814, upload-time = "2026-05-12T13:46:20.463Z" }, ] +[[package]] +name = "googleapis-common-protos" +version = "1.75.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b5/c8/f439cffde755cffa462bfbb156278fa6f9d09119719af9814b858fd4f81f/googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd", size = 151035, upload-time = "2026-05-07T08:04:49.423Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/c8/e2645aa8ed02fd4c7a2f59d68783b65b1f3cbdfe39a6308e156509d1fee8/googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed", size = 300631, upload-time = "2026-05-07T08:03:30.345Z" }, +] + [[package]] name = "griffelib" version = "2.0.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, @@ -514,7 +531,7 @@ wheels = [ [[package]] name = "grpcio" version = "1.78.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -575,7 +592,7 @@ wheels = [ [[package]] name = "h11" version = "0.16.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, @@ -584,7 +601,7 @@ wheels = [ [[package]] name = "httpcore" version = "1.0.9" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "h11" }, @@ -597,7 +614,7 @@ wheels = [ [[package]] name = "httpx" version = "0.28.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "certifi" }, @@ -612,7 +629,7 @@ wheels = [ [[package]] name = "httpx-sse" version = "0.4.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, @@ -621,7 +638,7 @@ wheels = [ [[package]] name = "identify" version = "2.6.19" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, @@ -630,7 +647,7 @@ wheels = [ [[package]] name = "idna" version = "3.14" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/b1/efac073e0c297ecf2fb33c346989a529d4e19164f1759102dee5953ee17e/idna-3.14.tar.gz", hash = "sha256:466d810d7a2cc1022bea9b037c39728d51ae7dad40d480fc9b7d7ecf98ba8ee3", size = 198272, upload-time = "2026-05-10T20:32:15.935Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/6c/3c/3f62dee257eb3d6b2c1ef2a09d36d9793c7111156a73b5654d2c2305e5ce/idna-3.14-py3-none-any.whl", hash = "sha256:e677eaf072e290f7b725f9acf0b3a2bd55f9fd6f7c70abe5f0e34823d0accf69", size = 72184, upload-time = "2026-05-10T20:32:14.295Z" }, @@ -639,7 +656,7 @@ wheels = [ [[package]] name = "importlib-metadata" version = "8.7.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] @@ -651,7 +668,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.3.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, @@ -660,7 +677,7 @@ wheels = [ [[package]] name = "jiter" version = "0.14.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/2e/a9959997739c403378d0a4a3a1c4ed80b60aeace216c4d37b303a9fc60a4/jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531", size = 316927, upload-time = "2026-04-10T14:25:40.753Z" }, @@ -763,7 +780,7 @@ wheels = [ [[package]] name = "joserfc" version = "1.6.5" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] @@ -775,7 +792,7 @@ wheels = [ [[package]] name = "jsonpatch" version = "1.33" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpointer" }, ] @@ -787,7 +804,7 @@ wheels = [ [[package]] name = "jsonpointer" version = "3.1.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, @@ -796,7 +813,7 @@ wheels = [ [[package]] name = "jsonschema" version = "4.26.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, @@ -811,7 +828,7 @@ wheels = [ [[package]] name = "jsonschema-specifications" version = "2025.9.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "referencing" }, ] @@ -823,7 +840,7 @@ wheels = [ [[package]] name = "langchain" version = "1.3.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph" }, @@ -837,7 +854,7 @@ wheels = [ [[package]] name = "langchain-core" version = "1.4.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, { name = "langchain-protocol" }, @@ -857,7 +874,7 @@ wheels = [ [[package]] name = "langchain-protocol" version = "0.0.15" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -869,7 +886,7 @@ wheels = [ [[package]] name = "langgraph" version = "1.2.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -886,7 +903,7 @@ wheels = [ [[package]] name = "langgraph-checkpoint" version = "4.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, @@ -899,7 +916,7 @@ wheels = [ [[package]] name = "langgraph-prebuilt" version = "1.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -912,7 +929,7 @@ wheels = [ [[package]] name = "langgraph-sdk" version = "0.3.14" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson" }, @@ -925,7 +942,7 @@ wheels = [ [[package]] name = "langsmith" version = "0.8.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, @@ -945,7 +962,7 @@ wheels = [ [[package]] name = "mcp" version = "1.27.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "httpx" }, @@ -970,7 +987,7 @@ wheels = [ [[package]] name = "nodeenv" version = "1.10.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, @@ -979,7 +996,7 @@ wheels = [ [[package]] name = "openai" version = "2.36.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -998,7 +1015,7 @@ wheels = [ [[package]] name = "openai-agents" version = "0.17.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, { name = "mcp" }, @@ -1016,31 +1033,45 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.41.1" -source = { registry = "https://pypi.org/simple/" } +version = "1.42.0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } dependencies = [ { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/fc/b7564cbef36601aef0d6c9bc01f7badb64be8e862c2e1c3c5c3b43b53e4f/opentelemetry_api-1.41.1.tar.gz", hash = "sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621", size = 71416, upload-time = "2026-04-24T13:15:38.262Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/29/59/3e7118ed140f76b0982ba4321bdaed1997a0473f9720de2d10788a577033/opentelemetry_api-1.41.1-py3-none-any.whl", hash = "sha256:a22df900e75c76dc08440710e51f52f1aa6b451b429298896023e60db5b3139f", size = 69007, upload-time = "2026-04-24T13:15:15.662Z" }, + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.42.0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=exporter%2Fopentelemetry-exporter-otlp-proto-common&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +dependencies = [ + { name = "opentelemetry-proto" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.42.0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=exporter%2Fopentelemetry-exporter-otlp-proto-grpc&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "typing-extensions" }, ] [[package]] name = "opentelemetry-instrumentation" -version = "0.62b1" -source = { registry = "https://pypi.org/simple/" } +version = "0.63b0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main#d2f396de68a969dfb74b8afc247e1d0dc6739b67" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "packaging" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/cb/0523b92c112a6cc70be43724343dc45225d3af134419844d7879a07755d4/opentelemetry_instrumentation-0.62b1.tar.gz", hash = "sha256:90e92a905ba4f84db06ac3aec96701df6c079b2d66e9379f8739f0a1bdcc7f45", size = 34043, upload-time = "2026-04-24T13:22:31.997Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/0f/45adbaea1f81b847cffdcee4f4b5f89297e42facf7fac78c7aaac4c38e75/opentelemetry_instrumentation-0.62b1-py3-none-any.whl", hash = "sha256:976fc6e640f2006599e97429c949e622c108d0c17c2059347d1e6c93c707f257", size = 34163, upload-time = "2026-04-24T13:21:31.722Z" }, -] [[package]] name = "opentelemetry-instrumentation-anthropic" @@ -1060,9 +1091,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "anthropic", marker = "extra == 'instruments'", specifier = ">=0.51.0" }, - { name = "opentelemetry-api", specifier = "~=1.40" }, - { name = "opentelemetry-instrumentation", specifier = "~=0.61b0" }, - { name = "opentelemetry-semantic-conventions", specifier = "~=0.61b0" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1085,9 +1116,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "claude-agent-sdk", marker = "extra == 'instruments'", specifier = ">=0.1.14" }, - { name = "opentelemetry-api", specifier = "~=1.39" }, - { name = "opentelemetry-instrumentation", specifier = "~=0.60b0" }, - { name = "opentelemetry-semantic-conventions", specifier = "~=0.60b0" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1110,9 +1141,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "google-genai", marker = "extra == 'instruments'", specifier = ">=1.32.0" }, - { name = "opentelemetry-api", specifier = "~=1.40" }, - { name = "opentelemetry-instrumentation", specifier = ">=0.61b0,<2" }, - { name = "opentelemetry-semantic-conventions", specifier = ">=0.61b0,<2" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1132,7 +1163,7 @@ instruments = [ [package.metadata] requires-dist = [ { name = "langchain", marker = "extra == 'instruments'", specifier = ">=0.3.21" }, - { name = "opentelemetry-instrumentation", specifier = "~=0.57b0" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, ] provides-extras = ["instruments"] @@ -1154,9 +1185,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "openai-agents", marker = "extra == 'instruments'", specifier = ">=0.3.3" }, - { name = "opentelemetry-api", specifier = ">=1.40" }, - { name = "opentelemetry-instrumentation", specifier = ">=0.61b0" }, - { name = "opentelemetry-semantic-conventions", specifier = ">=0.61b0" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1179,9 +1210,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "openai", marker = "extra == 'instruments'", specifier = ">=1.26.0" }, - { name = "opentelemetry-api", specifier = "~=1.40" }, - { name = "opentelemetry-instrumentation", specifier = "~=0.61b0" }, - { name = "opentelemetry-semantic-conventions", specifier = "~=0.61b0" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1202,13 +1233,21 @@ instruments = [ [package.metadata] requires-dist = [ - { name = "opentelemetry-api", specifier = "~=1.30" }, - { name = "opentelemetry-instrumentation", specifier = "~=0.51b0" }, - { name = "opentelemetry-semantic-conventions", specifier = "~=0.51b0" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "weaviate-client", marker = "extra == 'instruments'", specifier = ">=3.0" }, ] provides-extras = ["instruments"] +[[package]] +name = "opentelemetry-proto" +version = "1.42.0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-proto&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +dependencies = [ + { name = "protobuf" }, +] + [[package]] name = "opentelemetry-python-genai" version = "0.0.0" @@ -1239,8 +1278,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "opentelemetry-api" }, - { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, { name = "opentelemetry-instrumentation-anthropic", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-anthropic" }, { name = "opentelemetry-instrumentation-claude-agent-sdk", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-claude-agent-sdk" }, { name = "opentelemetry-instrumentation-google-genai", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-google-genai" }, @@ -1248,10 +1287,10 @@ requires-dist = [ { name = "opentelemetry-instrumentation-openai-agents-v2", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-openai-agents-v2" }, { name = "opentelemetry-instrumentation-openai-v2", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-openai-v2" }, { name = "opentelemetry-instrumentation-weaviate", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-weaviate" }, - { name = "opentelemetry-sdk" }, - { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-sdk", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "opentelemetry-test-util-genai", editable = "util/opentelemetry-test-util-genai" }, - { name = "opentelemetry-test-utils" }, + { name = "opentelemetry-test-utils", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=tests%2Fopentelemetry-test-utils&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] @@ -1264,30 +1303,22 @@ dev = [ [[package]] name = "opentelemetry-sdk" -version = "1.41.1" -source = { registry = "https://pypi.org/simple/" } +version = "1.42.0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/d0/54ee30dab82fb0acda23d144502771ff76ef8728459c83c3e89ef9fb1825/opentelemetry_sdk-1.41.1.tar.gz", hash = "sha256:724b615e1215b5aeacda0abb8a6a8922c9a1853068948bd0bd225a56d0c792e6", size = 230180, upload-time = "2026-04-24T13:15:50.991Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/e7/a1420b698aad018e1cf60fdbaaccbe49021fb415e2a0d81c242f4c518f54/opentelemetry_sdk-1.41.1-py3-none-any.whl", hash = "sha256:edee379c126c1bce952b0c812b48fe8ff35b30df0eecf17e98afa4d598b7d85d", size = 180213, upload-time = "2026-04-24T13:15:33.767Z" }, -] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.62b1" -source = { registry = "https://pypi.org/simple/" } +version = "0.63b0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9e/de/911ac9e309052aca1b20b2d5549d3db45d1011e1a610e552c6ccdd1b64f8/opentelemetry_semantic_conventions-0.62b1.tar.gz", hash = "sha256:c5cc6e04a7f8c7cdd30be2ed81499fa4e75bfbd52c9cb70d40af1f9cd3619802", size = 145750, upload-time = "2026-04-24T13:15:52.236Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/a6/83dc2ab6fa397ee66fba04fe2e74bdf7be3b3870005359ceb7689103c058/opentelemetry_semantic_conventions-0.62b1-py3-none-any.whl", hash = "sha256:cf506938103d331fbb78eded0d9788095f7fd59016f2bda813c3324e5a74a93c", size = 231620, upload-time = "2026-04-24T13:15:35.454Z" }, -] [[package]] name = "opentelemetry-test-util-genai" @@ -1295,37 +1326,40 @@ version = "0.0.0" source = { editable = "util/opentelemetry-test-util-genai" } dependencies = [ { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "implementation_name != 'pypy'" }, { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-sdk" }, { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-test-utils" }, { name = "opentelemetry-util-genai" }, { name = "pytest" }, { name = "pyyaml" }, + { name = "requests" }, ] [package.metadata] requires-dist = [ - { name = "opentelemetry-api" }, - { name = "opentelemetry-instrumentation" }, - { name = "opentelemetry-sdk" }, - { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "implementation_name != 'pypy'", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=exporter%2Fopentelemetry-exporter-otlp-proto-grpc&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-sdk", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-test-utils", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=tests%2Fopentelemetry-test-utils&branch=main" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, { name = "pytest" }, { name = "pyyaml" }, + { name = "requests" }, ] [[package]] name = "opentelemetry-test-utils" -version = "0.62b1" -source = { registry = "https://pypi.org/simple/" } +version = "0.63b0.dev0" +source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=tests%2Fopentelemetry-test-utils&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } dependencies = [ { name = "asgiref" }, { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/cb/0d/555b86a209da4b6ed716320359a38c88ac2981f258ea44303ea84297e346/opentelemetry_test_utils-0.62b1.tar.gz", hash = "sha256:26dc0bcbb6ba953ee964a9c23f3d28f979af52c2bbf7cf49cf0c8548634c40cd", size = 8845, upload-time = "2026-04-24T13:15:53.412Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/65/2f365677d1ded6fabfe563ddb03d619b16dcb6b6a5d26035911c3a7ad420/opentelemetry_test_utils-0.62b1-py3-none-any.whl", hash = "sha256:060b4bf85e6175f99e340a78d99b80a51286786296f9e584c5f99de2a35bc7ff", size = 15406, upload-time = "2026-04-24T13:15:36.89Z" }, + { name = "requests" }, ] [[package]] @@ -1349,9 +1383,9 @@ upload = [ [package.metadata] requires-dist = [ { name = "fsspec", marker = "extra == 'upload'", specifier = ">=2025.9.0" }, - { name = "opentelemetry-api", specifier = "~=1.40" }, - { name = "opentelemetry-instrumentation", specifier = "~=0.61b0" }, - { name = "opentelemetry-semantic-conventions", specifier = "~=0.61b0" }, + { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, + { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=7.0.0" }, { name = "wrapt", specifier = ">=1.0.0,<3.0.0" }, ] @@ -1360,7 +1394,7 @@ provides-extras = ["test", "upload"] [[package]] name = "orjson" version = "3.11.9" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/10/5d/b95ca542a001135cc250a49370f282f578c8f4e46cc8617d73775297eea8/orjson-3.11.9-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:135869ef917b8704ea0a94e01620e0c05021c15c52036e4663baffe75e72f8ce", size = 228986, upload-time = "2026-05-06T15:09:14.765Z" }, @@ -1441,7 +1475,7 @@ wheels = [ [[package]] name = "ormsgpack" version = "1.12.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" }, @@ -1497,7 +1531,7 @@ wheels = [ [[package]] name = "packaging" version = "26.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, @@ -1506,7 +1540,7 @@ wheels = [ [[package]] name = "platformdirs" version = "4.9.6" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, @@ -1515,7 +1549,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.6.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, @@ -1524,7 +1558,7 @@ wheels = [ [[package]] name = "pre-commit" version = "4.6.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, { name = "identify" }, @@ -1540,7 +1574,7 @@ wheels = [ [[package]] name = "protobuf" version = "6.33.6" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, @@ -1555,7 +1589,7 @@ wheels = [ [[package]] name = "pyasn1" version = "0.6.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, @@ -1564,7 +1598,7 @@ wheels = [ [[package]] name = "pyasn1-modules" version = "0.4.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyasn1" }, ] @@ -1576,7 +1610,7 @@ wheels = [ [[package]] name = "pycparser" version = "3.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, @@ -1585,7 +1619,7 @@ wheels = [ [[package]] name = "pydantic" version = "2.13.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, @@ -1600,7 +1634,7 @@ wheels = [ [[package]] name = "pydantic-core" version = "2.46.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -1716,7 +1750,7 @@ wheels = [ [[package]] name = "pydantic-settings" version = "2.14.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, @@ -1730,7 +1764,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -1739,7 +1773,7 @@ wheels = [ [[package]] name = "pyjwt" version = "2.12.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -1756,7 +1790,7 @@ crypto = [ [[package]] name = "pyproject-api" version = "1.10.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -1769,7 +1803,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -1787,7 +1821,7 @@ wheels = [ [[package]] name = "python-discovery" version = "1.3.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, @@ -1800,7 +1834,7 @@ wheels = [ [[package]] name = "python-dotenv" version = "1.2.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, @@ -1809,7 +1843,7 @@ wheels = [ [[package]] name = "python-multipart" version = "0.0.28" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/54/a85eb421fbdd5007bc5af39d0f4ed9fa609e0fedbfdc2adcf0b34526870e/python_multipart-0.0.28.tar.gz", hash = "sha256:8550da197eac0f7ab748961fc9509b999fa2662ea25cef857f05249f6893c0f8", size = 45314, upload-time = "2026-05-10T11:05:16.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f3/a2/43bbc5860b5034e2af4ef99a0e04d726ff329c43e192ef3abaa8d7ecfce5/python_multipart-0.0.28-py3-none-any.whl", hash = "sha256:10faac07eb966c3f48dc415f9dee46c04cb10d58d30a35677db8027c825ed9b6", size = 29438, upload-time = "2026-05-10T11:05:15.052Z" }, @@ -1818,7 +1852,7 @@ wheels = [ [[package]] name = "pywin32" version = "311" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } wheels = [ { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, @@ -1840,7 +1874,7 @@ wheels = [ [[package]] name = "pyyaml" version = "6.0.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, @@ -1904,7 +1938,7 @@ wheels = [ [[package]] name = "referencing" version = "0.37.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, @@ -1918,7 +1952,7 @@ wheels = [ [[package]] name = "requests" version = "2.34.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, @@ -1933,7 +1967,7 @@ wheels = [ [[package]] name = "requests-toolbelt" version = "1.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "requests" }, ] @@ -1945,7 +1979,7 @@ wheels = [ [[package]] name = "rpds-py" version = "0.30.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, @@ -2067,7 +2101,7 @@ wheels = [ [[package]] name = "sniffio" version = "1.3.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, @@ -2076,7 +2110,7 @@ wheels = [ [[package]] name = "sse-starlette" version = "3.4.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "starlette" }, @@ -2089,7 +2123,7 @@ wheels = [ [[package]] name = "starlette" version = "1.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, @@ -2102,7 +2136,7 @@ wheels = [ [[package]] name = "tenacity" version = "9.1.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, @@ -2111,7 +2145,7 @@ wheels = [ [[package]] name = "tomli" version = "2.4.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, @@ -2165,7 +2199,7 @@ wheels = [ [[package]] name = "tomli-w" version = "1.2.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, @@ -2174,7 +2208,7 @@ wheels = [ [[package]] name = "tox" version = "4.54.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachetools" }, { name = "colorama" }, @@ -2197,7 +2231,7 @@ wheels = [ [[package]] name = "tox-uv" version = "1.35.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tox-uv-bare" }, { name = "uv" }, @@ -2209,7 +2243,7 @@ wheels = [ [[package]] name = "tox-uv-bare" version = "1.35.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -2223,7 +2257,7 @@ wheels = [ [[package]] name = "tqdm" version = "4.67.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -2235,7 +2269,7 @@ wheels = [ [[package]] name = "types-requests" version = "2.33.0.20260508" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] @@ -2247,7 +2281,7 @@ wheels = [ [[package]] name = "typing-extensions" version = "4.15.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, @@ -2256,7 +2290,7 @@ wheels = [ [[package]] name = "typing-inspection" version = "0.4.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -2268,7 +2302,7 @@ wheels = [ [[package]] name = "urllib3" version = "2.7.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, @@ -2277,7 +2311,7 @@ wheels = [ [[package]] name = "uuid-utils" version = "0.15.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0b/f6/1856dc5935a947a062fb8fefd8a26e0f9f6694320e7203c7e85bd291dc93/uuid_utils-0.15.0.tar.gz", hash = "sha256:f182733e3d88edd2ceeca292627e2b1d5fa8693abe00b160de5517616ed399ea", size = 42182, upload-time = "2026-05-11T12:07:01.82Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/19/428d181d89678be61f30eb812c66f42e6dfe4f9aee911f4db4450b55459c/uuid_utils-0.15.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:87b999e827a01681015068ae54c6c6ab8076b0f8bff6b4139eabdb2cd079d267", size = 564690, upload-time = "2026-05-11T12:08:27.97Z" }, @@ -2390,7 +2424,7 @@ wheels = [ [[package]] name = "uv" version = "0.11.14" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/30/a3/be4a946c7c2fc4094c020c8f7d8bd0a739bad55ebe4e2817d6e2b1bc6bff/uv-0.11.14.tar.gz", hash = "sha256:0ea006a117b586b2681b6dfd9703a540d2ad2a136ec0f48d272767e599cc3dfb", size = 4130699, upload-time = "2026-05-12T18:00:37.321Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f7/15/9b2138b16eb1fa8c2cd84b1037ad10c38b3acc36ce96c6d27000bfb7e716/uv-0.11.14-py3-none-linux_armv6l.whl", hash = "sha256:78411a883f230a710af19f2ac6e6f0ba8eae90f0e5af4605f923fd367539fff4", size = 23545199, upload-time = "2026-05-12T18:01:34.526Z" }, @@ -2416,7 +2450,7 @@ wheels = [ [[package]] name = "uvicorn" version = "0.46.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, @@ -2430,7 +2464,7 @@ wheels = [ [[package]] name = "validators" version = "0.35.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/53/66/a435d9ae49850b2f071f7ebd8119dd4e84872b01630d6736761e6e7fd847/validators-0.35.0.tar.gz", hash = "sha256:992d6c48a4e77c81f1b4daba10d16c3a9bb0dbb79b3a19ea847ff0928e70497a", size = 73399, upload-time = "2025-05-01T05:42:06.7Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl", hash = "sha256:e8c947097eae7892cb3d26868d637f79f47b4a0554bc6b80065dfe5aac3705dd", size = 44712, upload-time = "2025-05-01T05:42:04.203Z" }, @@ -2439,7 +2473,7 @@ wheels = [ [[package]] name = "virtualenv" version = "21.3.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, @@ -2455,7 +2489,7 @@ wheels = [ [[package]] name = "weaviate-client" version = "4.21.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "authlib" }, { name = "grpcio" }, @@ -2472,7 +2506,7 @@ wheels = [ [[package]] name = "websockets" version = "16.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, @@ -2540,7 +2574,7 @@ wheels = [ [[package]] name = "wrapt" version = "2.1.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/2e/64/925f213fdcbb9baeb1530449ac71a4d57fc361c053d06bf78d0c5c7cd80c/wrapt-2.1.2.tar.gz", hash = "sha256:3996a67eecc2c68fd47b4e3c564405a5777367adfd9b8abb58387b63ee83b21e", size = 81678, upload-time = "2026-03-06T02:53:25.134Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a86d99a14f76facb269dc148590c01aaf47584071809a70da30555228158c", size = 60669, upload-time = "2026-03-06T02:52:40.671Z" }, @@ -2626,7 +2660,7 @@ wheels = [ [[package]] name = "xxhash" version = "3.7.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/92/49/e4b575b4ed170a7f640c8bd69cfadfa81c7b700191fde5e72228762b9f73/xxhash-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd8ab85c916a58d5c8656ea15e3ce9df836fe2f120a74c296e01d69fab2614b4", size = 33426, upload-time = "2026-04-25T11:05:15.702Z" }, @@ -2783,7 +2817,7 @@ wheels = [ [[package]] name = "zipp" version = "3.23.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, @@ -2792,7 +2826,7 @@ wheels = [ [[package]] name = "zstandard" version = "0.25.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/56/7a/28efd1d371f1acd037ac64ed1c5e2b41514a6cc937dd6ab6a13ab9f0702f/zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd", size = 795256, upload-time = "2025-09-14T22:15:56.415Z" }, diff --git a/versions.env b/versions.env new file mode 100644 index 00000000..089a4c43 --- /dev/null +++ b/versions.env @@ -0,0 +1,8 @@ +# Version pins for conformance tooling. Renovate manages this file via the +# customManagers block in .github/renovate.json5. + +# renovate: datasource=github-releases depName=open-telemetry/weaver versioning=semver-coerced +WEAVER_VERSION=v0.23.0 + +# renovate: datasource=github-releases depName=open-telemetry/semantic-conventions versioning=semver-coerced +SEMCONV_VERSION=v1.41.1 From dd1ead8fa1358593126d40724cae3beaaf18c91d Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 13 May 2026 18:37:30 -0700 Subject: [PATCH 02/10] fix some lint --- .../tests/conformance/tool_calling.py | 4 +- .../tests/test_conformance.py | 7 +- .../tests/test_conformance.py | 7 +- .../tests/conformance/embedding.py | 1 + .../tests/conformance/inference.py | 5 +- .../tests/test_conformance.py | 7 +- uv.lock | 208 +++++++++--------- 7 files changed, 124 insertions(+), 115 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py index 971bfc81..a762fe99 100644 --- a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py @@ -64,9 +64,7 @@ def run( "description": "Get weather by city", "input_schema": { "type": "object", - "properties": { - "city": {"type": "string"} - }, + "properties": {"city": {"type": "string"}}, "required": ["city"], }, } diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py index 3fedab59..5e6535e9 100644 --- a/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py @@ -9,8 +9,11 @@ import pytest -from opentelemetry.test.weaver_live_check import WeaverLiveCheck -from opentelemetry.test_util_genai.conformance import ( +# Skip collection when weaver_live_check isn't installed (non-conformance envs). +pytest.importorskip("opentelemetry.test.weaver_live_check") + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck # noqa: E402 +from opentelemetry.test_util_genai.conformance import ( # noqa: E402 Scenario, run_conformance, ) diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py index 436f482b..77128a53 100644 --- a/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py +++ b/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py @@ -9,8 +9,11 @@ import pytest -from opentelemetry.test.weaver_live_check import WeaverLiveCheck -from opentelemetry.test_util_genai.conformance import ( +# Skip collection when weaver_live_check isn't installed (non-conformance envs). +pytest.importorskip("opentelemetry.test.weaver_live_check") + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck # noqa: E402 +from opentelemetry.test_util_genai.conformance import ( # noqa: E402 Scenario, run_conformance, ) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py index 7445a737..307666b6 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py @@ -16,6 +16,7 @@ from opentelemetry.test_util_genai.conformance import Scenario from opentelemetry.test_util_genai.instrumentor import instrument + class EmbeddingScenario(Scenario): expected_spans = ("embeddings",) expected_metrics = ( diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py index 72bb1b13..70e5eeb6 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py @@ -16,6 +16,7 @@ from opentelemetry.test_util_genai.conformance import Scenario from opentelemetry.test_util_genai.instrumentor import instrument + class InferenceScenario(Scenario): expected_spans = ("chat",) expected_metrics = ( @@ -41,7 +42,9 @@ def run( ): with vcr.use_cassette("inference-conformance.yaml"): OpenAI().chat.completions.create( - messages=[{"role": "user", "content": "Say this is a test"}], + messages=[ + {"role": "user", "content": "Say this is a test"} + ], model="gpt-4o-mini", stream=False, ) diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py index ed2ae561..c2c8abe3 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py @@ -14,8 +14,11 @@ import pytest -from opentelemetry.test.weaver_live_check import WeaverLiveCheck -from opentelemetry.test_util_genai.conformance import ( +# Skip collection when weaver_live_check isn't installed (non-conformance envs). +pytest.importorskip("opentelemetry.test.weaver_live_check") + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck # noqa: E402 +from opentelemetry.test_util_genai.conformance import ( # noqa: E402 Scenario, run_conformance, ) diff --git a/uv.lock b/uv.lock index 491f59d9..a3a0cf0e 100644 --- a/uv.lock +++ b/uv.lock @@ -24,7 +24,7 @@ members = [ [[package]] name = "annotated-types" version = "0.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, @@ -33,7 +33,7 @@ wheels = [ [[package]] name = "anthropic" version = "0.101.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -52,7 +52,7 @@ wheels = [ [[package]] name = "anyio" version = "4.13.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, @@ -66,7 +66,7 @@ wheels = [ [[package]] name = "asgiref" version = "3.11.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -78,7 +78,7 @@ wheels = [ [[package]] name = "attrs" version = "26.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, @@ -87,7 +87,7 @@ wheels = [ [[package]] name = "authlib" version = "1.7.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cryptography" }, { name = "joserfc" }, @@ -100,7 +100,7 @@ wheels = [ [[package]] name = "cachetools" version = "7.1.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/ff/e2/85f227594656000ff4d8adadae91a21f536d4a84c6c716a86bd6685874be/cachetools-7.1.1.tar.gz", hash = "sha256:27bdf856d68fd3c71c26c01b5edc312124ed427524d1ddb31aa2b7746fe20d4b", size = 40202, upload-time = "2026-05-03T20:00:29.391Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/bf/0f/f897abe4ea0a8c408ae65c8c83bffab4936ad65d6032d4fb4cd35bbdc3ee/cachetools-7.1.1-py3-none-any.whl", hash = "sha256:0335cd7a0952d2b22327441fb0628139e234c565559eeb91a8a4ac7551c5353d", size = 16775, upload-time = "2026-05-03T20:00:27.857Z" }, @@ -109,7 +109,7 @@ wheels = [ [[package]] name = "certifi" version = "2026.4.22" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, @@ -118,7 +118,7 @@ wheels = [ [[package]] name = "cffi" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] @@ -200,7 +200,7 @@ wheels = [ [[package]] name = "cfgv" version = "3.5.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, @@ -209,7 +209,7 @@ wheels = [ [[package]] name = "charset-normalizer" version = "3.4.7" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, @@ -314,7 +314,7 @@ wheels = [ [[package]] name = "claude-agent-sdk" version = "0.1.81" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "mcp" }, @@ -333,7 +333,7 @@ wheels = [ [[package]] name = "click" version = "8.3.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -345,7 +345,7 @@ wheels = [ [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -354,7 +354,7 @@ wheels = [ [[package]] name = "cryptography" version = "48.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, @@ -414,7 +414,7 @@ wheels = [ [[package]] name = "distlib" version = "0.4.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, @@ -423,7 +423,7 @@ wheels = [ [[package]] name = "distro" version = "1.9.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, @@ -432,7 +432,7 @@ wheels = [ [[package]] name = "docstring-parser" version = "0.18.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, @@ -441,7 +441,7 @@ wheels = [ [[package]] name = "exceptiongroup" version = "1.3.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] @@ -453,7 +453,7 @@ wheels = [ [[package]] name = "filelock" version = "3.29.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, @@ -462,7 +462,7 @@ wheels = [ [[package]] name = "fsspec" version = "2026.4.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" }, @@ -471,7 +471,7 @@ wheels = [ [[package]] name = "google-auth" version = "2.52.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, @@ -489,7 +489,7 @@ requests = [ [[package]] name = "google-genai" version = "2.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -510,7 +510,7 @@ wheels = [ [[package]] name = "googleapis-common-protos" version = "1.75.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "protobuf" }, ] @@ -522,7 +522,7 @@ wheels = [ [[package]] name = "griffelib" version = "2.0.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, @@ -531,7 +531,7 @@ wheels = [ [[package]] name = "grpcio" version = "1.78.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -592,7 +592,7 @@ wheels = [ [[package]] name = "h11" version = "0.16.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, @@ -601,7 +601,7 @@ wheels = [ [[package]] name = "httpcore" version = "1.0.9" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "certifi" }, { name = "h11" }, @@ -614,7 +614,7 @@ wheels = [ [[package]] name = "httpx" version = "0.28.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "certifi" }, @@ -629,7 +629,7 @@ wheels = [ [[package]] name = "httpx-sse" version = "0.4.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, @@ -638,7 +638,7 @@ wheels = [ [[package]] name = "identify" version = "2.6.19" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, @@ -647,7 +647,7 @@ wheels = [ [[package]] name = "idna" version = "3.14" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/05/b1/efac073e0c297ecf2fb33c346989a529d4e19164f1759102dee5953ee17e/idna-3.14.tar.gz", hash = "sha256:466d810d7a2cc1022bea9b037c39728d51ae7dad40d480fc9b7d7ecf98ba8ee3", size = 198272, upload-time = "2026-05-10T20:32:15.935Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/6c/3c/3f62dee257eb3d6b2c1ef2a09d36d9793c7111156a73b5654d2c2305e5ce/idna-3.14-py3-none-any.whl", hash = "sha256:e677eaf072e290f7b725f9acf0b3a2bd55f9fd6f7c70abe5f0e34823d0accf69", size = 72184, upload-time = "2026-05-10T20:32:14.295Z" }, @@ -656,7 +656,7 @@ wheels = [ [[package]] name = "importlib-metadata" version = "8.7.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "zipp" }, ] @@ -668,7 +668,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.3.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, @@ -677,7 +677,7 @@ wheels = [ [[package]] name = "jiter" version = "0.14.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/2e/a9959997739c403378d0a4a3a1c4ed80b60aeace216c4d37b303a9fc60a4/jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531", size = 316927, upload-time = "2026-04-10T14:25:40.753Z" }, @@ -780,7 +780,7 @@ wheels = [ [[package]] name = "joserfc" version = "1.6.5" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cryptography" }, ] @@ -792,7 +792,7 @@ wheels = [ [[package]] name = "jsonpatch" version = "1.33" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "jsonpointer" }, ] @@ -804,7 +804,7 @@ wheels = [ [[package]] name = "jsonpointer" version = "3.1.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, @@ -813,7 +813,7 @@ wheels = [ [[package]] name = "jsonschema" version = "4.26.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, @@ -828,7 +828,7 @@ wheels = [ [[package]] name = "jsonschema-specifications" version = "2025.9.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "referencing" }, ] @@ -840,7 +840,7 @@ wheels = [ [[package]] name = "langchain" version = "1.3.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "langgraph" }, @@ -854,7 +854,7 @@ wheels = [ [[package]] name = "langchain-core" version = "1.4.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "jsonpatch" }, { name = "langchain-protocol" }, @@ -874,7 +874,7 @@ wheels = [ [[package]] name = "langchain-protocol" version = "0.0.15" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -886,7 +886,7 @@ wheels = [ [[package]] name = "langgraph" version = "1.2.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -903,7 +903,7 @@ wheels = [ [[package]] name = "langgraph-checkpoint" version = "4.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, @@ -916,7 +916,7 @@ wheels = [ [[package]] name = "langgraph-prebuilt" version = "1.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -929,7 +929,7 @@ wheels = [ [[package]] name = "langgraph-sdk" version = "0.3.14" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "httpx" }, { name = "orjson" }, @@ -942,7 +942,7 @@ wheels = [ [[package]] name = "langsmith" version = "0.8.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "httpx" }, { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, @@ -962,7 +962,7 @@ wheels = [ [[package]] name = "mcp" version = "1.27.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "httpx" }, @@ -987,7 +987,7 @@ wheels = [ [[package]] name = "nodeenv" version = "1.10.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, @@ -996,7 +996,7 @@ wheels = [ [[package]] name = "openai" version = "2.36.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -1015,7 +1015,7 @@ wheels = [ [[package]] name = "openai-agents" version = "0.17.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "griffelib" }, { name = "mcp" }, @@ -1334,7 +1334,6 @@ dependencies = [ { name = "opentelemetry-util-genai" }, { name = "pytest" }, { name = "pyyaml" }, - { name = "requests" }, ] [package.metadata] @@ -1348,7 +1347,6 @@ requires-dist = [ { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, { name = "pytest" }, { name = "pyyaml" }, - { name = "requests" }, ] [[package]] @@ -1394,7 +1392,7 @@ provides-extras = ["test", "upload"] [[package]] name = "orjson" version = "3.11.9" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/10/5d/b95ca542a001135cc250a49370f282f578c8f4e46cc8617d73775297eea8/orjson-3.11.9-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:135869ef917b8704ea0a94e01620e0c05021c15c52036e4663baffe75e72f8ce", size = 228986, upload-time = "2026-05-06T15:09:14.765Z" }, @@ -1475,7 +1473,7 @@ wheels = [ [[package]] name = "ormsgpack" version = "1.12.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" }, @@ -1531,7 +1529,7 @@ wheels = [ [[package]] name = "packaging" version = "26.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, @@ -1540,7 +1538,7 @@ wheels = [ [[package]] name = "platformdirs" version = "4.9.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, @@ -1549,7 +1547,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.6.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, @@ -1558,7 +1556,7 @@ wheels = [ [[package]] name = "pre-commit" version = "4.6.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cfgv" }, { name = "identify" }, @@ -1574,7 +1572,7 @@ wheels = [ [[package]] name = "protobuf" version = "6.33.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, @@ -1589,7 +1587,7 @@ wheels = [ [[package]] name = "pyasn1" version = "0.6.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, @@ -1598,7 +1596,7 @@ wheels = [ [[package]] name = "pyasn1-modules" version = "0.4.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "pyasn1" }, ] @@ -1610,7 +1608,7 @@ wheels = [ [[package]] name = "pycparser" version = "3.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, @@ -1619,7 +1617,7 @@ wheels = [ [[package]] name = "pydantic" version = "2.13.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, @@ -1634,7 +1632,7 @@ wheels = [ [[package]] name = "pydantic-core" version = "2.46.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -1750,7 +1748,7 @@ wheels = [ [[package]] name = "pydantic-settings" version = "2.14.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, @@ -1764,7 +1762,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -1773,7 +1771,7 @@ wheels = [ [[package]] name = "pyjwt" version = "2.12.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -1790,7 +1788,7 @@ crypto = [ [[package]] name = "pyproject-api" version = "1.10.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -1803,7 +1801,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -1821,7 +1819,7 @@ wheels = [ [[package]] name = "python-discovery" version = "1.3.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, @@ -1834,7 +1832,7 @@ wheels = [ [[package]] name = "python-dotenv" version = "1.2.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, @@ -1843,7 +1841,7 @@ wheels = [ [[package]] name = "python-multipart" version = "0.0.28" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/82/54/a85eb421fbdd5007bc5af39d0f4ed9fa609e0fedbfdc2adcf0b34526870e/python_multipart-0.0.28.tar.gz", hash = "sha256:8550da197eac0f7ab748961fc9509b999fa2662ea25cef857f05249f6893c0f8", size = 45314, upload-time = "2026-05-10T11:05:16.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f3/a2/43bbc5860b5034e2af4ef99a0e04d726ff329c43e192ef3abaa8d7ecfce5/python_multipart-0.0.28-py3-none-any.whl", hash = "sha256:10faac07eb966c3f48dc415f9dee46c04cb10d58d30a35677db8027c825ed9b6", size = 29438, upload-time = "2026-05-10T11:05:15.052Z" }, @@ -1852,7 +1850,7 @@ wheels = [ [[package]] name = "pywin32" version = "311" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } wheels = [ { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, @@ -1874,7 +1872,7 @@ wheels = [ [[package]] name = "pyyaml" version = "6.0.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, @@ -1938,7 +1936,7 @@ wheels = [ [[package]] name = "referencing" version = "0.37.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, @@ -1952,7 +1950,7 @@ wheels = [ [[package]] name = "requests" version = "2.34.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, @@ -1967,7 +1965,7 @@ wheels = [ [[package]] name = "requests-toolbelt" version = "1.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "requests" }, ] @@ -1979,7 +1977,7 @@ wheels = [ [[package]] name = "rpds-py" version = "0.30.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, @@ -2101,7 +2099,7 @@ wheels = [ [[package]] name = "sniffio" version = "1.3.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, @@ -2110,7 +2108,7 @@ wheels = [ [[package]] name = "sse-starlette" version = "3.4.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "starlette" }, @@ -2123,7 +2121,7 @@ wheels = [ [[package]] name = "starlette" version = "1.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, @@ -2136,7 +2134,7 @@ wheels = [ [[package]] name = "tenacity" version = "9.1.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, @@ -2145,7 +2143,7 @@ wheels = [ [[package]] name = "tomli" version = "2.4.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, @@ -2199,7 +2197,7 @@ wheels = [ [[package]] name = "tomli-w" version = "1.2.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, @@ -2208,7 +2206,7 @@ wheels = [ [[package]] name = "tox" version = "4.54.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cachetools" }, { name = "colorama" }, @@ -2231,7 +2229,7 @@ wheels = [ [[package]] name = "tox-uv" version = "1.35.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "tox-uv-bare" }, { name = "uv" }, @@ -2243,7 +2241,7 @@ wheels = [ [[package]] name = "tox-uv-bare" version = "1.35.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -2257,7 +2255,7 @@ wheels = [ [[package]] name = "tqdm" version = "4.67.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -2269,7 +2267,7 @@ wheels = [ [[package]] name = "types-requests" version = "2.33.0.20260508" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "urllib3" }, ] @@ -2281,7 +2279,7 @@ wheels = [ [[package]] name = "typing-extensions" version = "4.15.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, @@ -2290,7 +2288,7 @@ wheels = [ [[package]] name = "typing-inspection" version = "0.4.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -2302,7 +2300,7 @@ wheels = [ [[package]] name = "urllib3" version = "2.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, @@ -2311,7 +2309,7 @@ wheels = [ [[package]] name = "uuid-utils" version = "0.15.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/0b/f6/1856dc5935a947a062fb8fefd8a26e0f9f6694320e7203c7e85bd291dc93/uuid_utils-0.15.0.tar.gz", hash = "sha256:f182733e3d88edd2ceeca292627e2b1d5fa8693abe00b160de5517616ed399ea", size = 42182, upload-time = "2026-05-11T12:07:01.82Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/19/428d181d89678be61f30eb812c66f42e6dfe4f9aee911f4db4450b55459c/uuid_utils-0.15.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:87b999e827a01681015068ae54c6c6ab8076b0f8bff6b4139eabdb2cd079d267", size = 564690, upload-time = "2026-05-11T12:08:27.97Z" }, @@ -2424,7 +2422,7 @@ wheels = [ [[package]] name = "uv" version = "0.11.14" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/30/a3/be4a946c7c2fc4094c020c8f7d8bd0a739bad55ebe4e2817d6e2b1bc6bff/uv-0.11.14.tar.gz", hash = "sha256:0ea006a117b586b2681b6dfd9703a540d2ad2a136ec0f48d272767e599cc3dfb", size = 4130699, upload-time = "2026-05-12T18:00:37.321Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f7/15/9b2138b16eb1fa8c2cd84b1037ad10c38b3acc36ce96c6d27000bfb7e716/uv-0.11.14-py3-none-linux_armv6l.whl", hash = "sha256:78411a883f230a710af19f2ac6e6f0ba8eae90f0e5af4605f923fd367539fff4", size = 23545199, upload-time = "2026-05-12T18:01:34.526Z" }, @@ -2450,7 +2448,7 @@ wheels = [ [[package]] name = "uvicorn" version = "0.46.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "click" }, { name = "h11" }, @@ -2464,7 +2462,7 @@ wheels = [ [[package]] name = "validators" version = "0.35.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/53/66/a435d9ae49850b2f071f7ebd8119dd4e84872b01630d6736761e6e7fd847/validators-0.35.0.tar.gz", hash = "sha256:992d6c48a4e77c81f1b4daba10d16c3a9bb0dbb79b3a19ea847ff0928e70497a", size = 73399, upload-time = "2025-05-01T05:42:06.7Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl", hash = "sha256:e8c947097eae7892cb3d26868d637f79f47b4a0554bc6b80065dfe5aac3705dd", size = 44712, upload-time = "2025-05-01T05:42:04.203Z" }, @@ -2473,7 +2471,7 @@ wheels = [ [[package]] name = "virtualenv" version = "21.3.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "distlib" }, { name = "filelock" }, @@ -2489,7 +2487,7 @@ wheels = [ [[package]] name = "weaviate-client" version = "4.21.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "authlib" }, { name = "grpcio" }, @@ -2506,7 +2504,7 @@ wheels = [ [[package]] name = "websockets" version = "16.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, @@ -2574,7 +2572,7 @@ wheels = [ [[package]] name = "wrapt" version = "2.1.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/2e/64/925f213fdcbb9baeb1530449ac71a4d57fc361c053d06bf78d0c5c7cd80c/wrapt-2.1.2.tar.gz", hash = "sha256:3996a67eecc2c68fd47b4e3c564405a5777367adfd9b8abb58387b63ee83b21e", size = 81678, upload-time = "2026-03-06T02:53:25.134Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a86d99a14f76facb269dc148590c01aaf47584071809a70da30555228158c", size = 60669, upload-time = "2026-03-06T02:52:40.671Z" }, @@ -2660,7 +2658,7 @@ wheels = [ [[package]] name = "xxhash" version = "3.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/92/49/e4b575b4ed170a7f640c8bd69cfadfa81c7b700191fde5e72228762b9f73/xxhash-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd8ab85c916a58d5c8656ea15e3ce9df836fe2f120a74c296e01d69fab2614b4", size = 33426, upload-time = "2026-04-25T11:05:15.702Z" }, @@ -2817,7 +2815,7 @@ wheels = [ [[package]] name = "zipp" version = "3.23.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, @@ -2826,7 +2824,7 @@ wheels = [ [[package]] name = "zstandard" version = "0.25.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/56/7a/28efd1d371f1acd037ac64ed1c5e2b41514a6cc937dd6ab6a13ab9f0702f/zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd", size = 795256, upload-time = "2025-09-14T22:15:56.415Z" }, From 9234580bc27b109445291f118b5d651834f29750 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 13 May 2026 20:07:27 -0700 Subject: [PATCH 03/10] fix live test --- AGENTS.md | 6 +----- .../tests/conformance/tool_calling.py | 1 + .../tests/conftest.py | 5 ++++- .../src/opentelemetry/test_util_genai/_setup_weaver.py | 9 ++++++++- .../src/opentelemetry/test_util_genai/conformance.py | 9 +++------ 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 649d8a9d..7180c388 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -110,11 +110,7 @@ via Weaver live-check. Each scenario module defines a subclass of `run(*, tracer_provider, meter_provider, logger_provider, vcr)`. `tests/test_conformance.py` must set `pytestmark = pytest.mark.conformance` at -module level. The `*-conformance` tox envs select these tests via -`-m conformance`; the regular `*-{oldest,latest}` envs deselect them via -`-m "not conformance"`. Without the marker the test won't run under the -conformance env and will leak into the regular suite (where `weaver` isn't -installed). +module level. Run via `tox -e py312-test-instrumentation--conformance`. diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py index cd0bfb3d..3cb3a4b4 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py @@ -118,6 +118,7 @@ def validate(self, report: LiveCheckReport) -> None: operations = [ attr["value"] for entry in report["samples"] + if "span" in entry for attr in entry["span"]["attributes"] if attr["name"] == "gen_ai.operation.name" ] diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py index a7338743..f8ec4714 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conftest.py @@ -13,7 +13,6 @@ from opentelemetry.sdk.trace.export import SimpleSpanProcessor from opentelemetry.sdk.trace.sampling import ALWAYS_OFF from opentelemetry.test_util_genai.instrumentor import instrument -from opentelemetry.test_util_genai.vcr import scrub_response_headers_overwrite pytest_plugins = [ "opentelemetry.test_util_genai.fixtures", @@ -39,6 +38,10 @@ def async_openai_client(): @pytest.fixture(scope="module") def vcr_config(): + from opentelemetry.test_util_genai.vcr import ( # noqa: PLC0415 + scrub_response_headers_overwrite, + ) + return { "filter_headers": [ ("cookie", "test_cookie"), diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py index 9e05315d..5d272724 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py @@ -145,7 +145,14 @@ def policies_dir() -> Path: for key, filename in _GENAI_SCHEMA_FILES.items(): schema_path = docs_genai / filename if schema_path.exists(): - schemas[key] = json.loads(schema_path.read_text(encoding="utf-8")) + # OPA's json.match_schema can't fetch the draft-07 meta-schema at + # eval time; swap the external $ref for a local "must be an object". + schemas[key] = json.loads( + schema_path.read_text(encoding="utf-8").replace( + '"$ref": "http://json-schema.org/draft-07/schema#"', + '"type": "object"', + ) + ) else: logger.warning( "GenAI schema not found: %s (emitting null stub)", schema_path diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py index 1fd40eac..784d10c2 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py @@ -40,7 +40,6 @@ def test_conformance(scenario, vcr, weaver_live_check): from pathlib import Path from typing import Any, ClassVar -from opentelemetry._logs import set_logger_provider from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( OTLPLogExporter, ) @@ -125,9 +124,6 @@ def _build_providers( OTLPLogExporter(endpoint=endpoint, insecure=True) ) ) - # Some instrumentations resolve the logger off the module-level global - # instead of the per-instrumentor provider. - set_logger_provider(logger_provider) return tracer_provider, meter_provider, logger_provider @@ -143,6 +139,7 @@ def _seen_span_operations(report: LiveCheckReport) -> set[str]: return { attr["value"] for entry in report["samples"] + if "span" in entry for attr in entry["span"]["attributes"] if attr["name"] == "gen_ai.operation.name" } @@ -151,7 +148,7 @@ def _seen_span_operations(report: LiveCheckReport) -> set[str]: def _dump_report(report: LiveCheckReport) -> None: out = Path("weaver_reports") / "full.json" out.parent.mkdir(parents=True, exist_ok=True) - out.write_text(json.dumps(report, indent=2, sort_keys=True)) + out.write_text(json.dumps(report._report, indent=2, sort_keys=True)) # noqa: SLF001 def run_conformance( @@ -179,7 +176,7 @@ def run_conformance( meter_provider.force_flush() logger_provider.force_flush() - report = weaver.end_and_check() + report = weaver.end_and_check(timeout=120) _dump_report(report) scenario.validate(report) return report From 0ae89de73311a9d06861762dc52834f2fb38e795 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 13 May 2026 20:36:55 -0700 Subject: [PATCH 04/10] address copilot --- dev-requirements-conformance.txt | 20 +- .../pyproject.toml | 2 - .../test_util_genai/_setup_weaver.py | 23 +- .../test_util_genai/conformance.py | 6 +- uv.lock | 248 +++++++----------- 5 files changed, 134 insertions(+), 165 deletions(-) diff --git a/dev-requirements-conformance.txt b/dev-requirements-conformance.txt index e3618215..40b4f495 100644 --- a/dev-requirements-conformance.txt +++ b/dev-requirements-conformance.txt @@ -1,12 +1,14 @@ # Conformance tests use `opentelemetry.test.weaver_live_check`, not yet on -# PyPI. Pin the whole stack from git+main so versions stay coherent. Mirrors +# PyPI. Pin the whole stack from git so versions stay coherent. Mirrors # pyproject.toml's [tool.uv.sources]. Drop once the file ships to PyPI. +# +# TODO: switch to PyPI versions once the test utils are released -opentelemetry-api @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-api -opentelemetry-sdk @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-sdk -opentelemetry-semantic-conventions @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-semantic-conventions -opentelemetry-test-utils @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=tests/opentelemetry-test-utils -opentelemetry-instrumentation @ git+https://github.com/open-telemetry/opentelemetry-python-contrib#subdirectory=opentelemetry-instrumentation -opentelemetry-exporter-otlp-proto-grpc @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=exporter/opentelemetry-exporter-otlp-proto-grpc -opentelemetry-exporter-otlp-proto-common @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=exporter/opentelemetry-exporter-otlp-proto-common -opentelemetry-proto @ git+https://github.com/open-telemetry/opentelemetry-python#subdirectory=opentelemetry-proto +opentelemetry-api @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-api +opentelemetry-sdk @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-sdk +opentelemetry-semantic-conventions @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-semantic-conventions +opentelemetry-test-utils @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=tests/opentelemetry-test-utils +opentelemetry-instrumentation @ git+https://github.com/open-telemetry/opentelemetry-python-contrib@d2f396de68a969dfb74b8afc247e1d0dc6739b67#subdirectory=opentelemetry-instrumentation +opentelemetry-exporter-otlp-proto-grpc @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=exporter/opentelemetry-exporter-otlp-proto-grpc +opentelemetry-exporter-otlp-proto-common @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=exporter/opentelemetry-exporter-otlp-proto-common +opentelemetry-proto @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-proto diff --git a/util/opentelemetry-test-util-genai/pyproject.toml b/util/opentelemetry-test-util-genai/pyproject.toml index 7c79206d..4979dde1 100644 --- a/util/opentelemetry-test-util-genai/pyproject.toml +++ b/util/opentelemetry-test-util-genai/pyproject.toml @@ -19,8 +19,6 @@ dependencies = [ "opentelemetry-util-genai", "pytest", "PyYAML", - # PyPy lacks grpcio wheels; the weaver fixture skips when this import fails. - 'opentelemetry-exporter-otlp-proto-grpc; implementation_name != "pypy"', ] [tool.hatch.build.targets.wheel] diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py index 5d272724..625afb09 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py @@ -18,10 +18,15 @@ import shutil import tarfile import tempfile +import urllib.error import urllib.request from pathlib import Path from typing import Any +# Bounds the fetch of the semantic-conventions tarball so a slow/unreachable +# GitHub doesn't hang conformance runs until the OS-level socket timeout. +_FETCH_TIMEOUT_SECONDS = 60 + logger = logging.getLogger(__name__) @@ -83,11 +88,19 @@ def _fetch_semconv(version: str) -> Path: extract_dir.mkdir() logger.info("Fetching semantic-conventions @ %s", version) - with ( - urllib.request.urlopen(url) as response, - archive_path.open("wb") as out, - ): - shutil.copyfileobj(response, out) + try: + with ( + urllib.request.urlopen( + url, timeout=_FETCH_TIMEOUT_SECONDS + ) as response, + archive_path.open("wb") as out, + ): + shutil.copyfileobj(response, out) + except (TimeoutError, urllib.error.URLError) as exc: + raise RuntimeError( + f"Failed to fetch semantic-conventions @ {version} from {url}: " + f"{exc}" + ) from exc with tarfile.open(archive_path, "r:gz") as archive: archive.extractall(extract_dir, filter="data") diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py index 784d10c2..99037340 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py @@ -145,8 +145,8 @@ def _seen_span_operations(report: LiveCheckReport) -> set[str]: } -def _dump_report(report: LiveCheckReport) -> None: - out = Path("weaver_reports") / "full.json" +def _dump_report(scenario: Scenario, report: LiveCheckReport) -> None: + out = Path("weaver_reports") / f"{type(scenario).__name__}.json" out.parent.mkdir(parents=True, exist_ok=True) out.write_text(json.dumps(report._report, indent=2, sort_keys=True)) # noqa: SLF001 @@ -177,7 +177,7 @@ def run_conformance( logger_provider.force_flush() report = weaver.end_and_check(timeout=120) - _dump_report(report) + _dump_report(scenario, report) scenario.validate(report) return report finally: diff --git a/uv.lock b/uv.lock index a3a0cf0e..f4c95381 100644 --- a/uv.lock +++ b/uv.lock @@ -24,7 +24,7 @@ members = [ [[package]] name = "annotated-types" version = "0.7.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, @@ -33,7 +33,7 @@ wheels = [ [[package]] name = "anthropic" version = "0.101.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -52,7 +52,7 @@ wheels = [ [[package]] name = "anyio" version = "4.13.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, @@ -66,7 +66,7 @@ wheels = [ [[package]] name = "asgiref" version = "3.11.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -78,7 +78,7 @@ wheels = [ [[package]] name = "attrs" version = "26.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, @@ -87,7 +87,7 @@ wheels = [ [[package]] name = "authlib" version = "1.7.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "joserfc" }, @@ -100,7 +100,7 @@ wheels = [ [[package]] name = "cachetools" version = "7.1.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ff/e2/85f227594656000ff4d8adadae91a21f536d4a84c6c716a86bd6685874be/cachetools-7.1.1.tar.gz", hash = "sha256:27bdf856d68fd3c71c26c01b5edc312124ed427524d1ddb31aa2b7746fe20d4b", size = 40202, upload-time = "2026-05-03T20:00:29.391Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/bf/0f/f897abe4ea0a8c408ae65c8c83bffab4936ad65d6032d4fb4cd35bbdc3ee/cachetools-7.1.1-py3-none-any.whl", hash = "sha256:0335cd7a0952d2b22327441fb0628139e234c565559eeb91a8a4ac7551c5353d", size = 16775, upload-time = "2026-05-03T20:00:27.857Z" }, @@ -109,7 +109,7 @@ wheels = [ [[package]] name = "certifi" version = "2026.4.22" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, @@ -118,7 +118,7 @@ wheels = [ [[package]] name = "cffi" version = "2.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] @@ -200,7 +200,7 @@ wheels = [ [[package]] name = "cfgv" version = "3.5.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, @@ -209,7 +209,7 @@ wheels = [ [[package]] name = "charset-normalizer" version = "3.4.7" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, @@ -314,7 +314,7 @@ wheels = [ [[package]] name = "claude-agent-sdk" version = "0.1.81" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "mcp" }, @@ -333,7 +333,7 @@ wheels = [ [[package]] name = "click" version = "8.3.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -345,7 +345,7 @@ wheels = [ [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -354,7 +354,7 @@ wheels = [ [[package]] name = "cryptography" version = "48.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, @@ -414,7 +414,7 @@ wheels = [ [[package]] name = "distlib" version = "0.4.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, @@ -423,7 +423,7 @@ wheels = [ [[package]] name = "distro" version = "1.9.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, @@ -432,7 +432,7 @@ wheels = [ [[package]] name = "docstring-parser" version = "0.18.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, @@ -441,7 +441,7 @@ wheels = [ [[package]] name = "exceptiongroup" version = "1.3.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] @@ -453,7 +453,7 @@ wheels = [ [[package]] name = "filelock" version = "3.29.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, @@ -462,7 +462,7 @@ wheels = [ [[package]] name = "fsspec" version = "2026.4.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" }, @@ -471,7 +471,7 @@ wheels = [ [[package]] name = "google-auth" version = "2.52.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, @@ -489,7 +489,7 @@ requests = [ [[package]] name = "google-genai" version = "2.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -507,22 +507,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/1d/a9080b9d03a106d4ebc95ac5667b094b9765abd3ee0564b1bd8a19b0a3f1/google_genai-2.1.0-py3-none-any.whl", hash = "sha256:7d0d6759fb1bc8ca3ee3ef1025cc796a4341d4d22ca5fa36c254161882545e9a", size = 803814, upload-time = "2026-05-12T13:46:20.463Z" }, ] -[[package]] -name = "googleapis-common-protos" -version = "1.75.0" -source = { registry = "https://pypi.org/simple/" } -dependencies = [ - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b5/c8/f439cffde755cffa462bfbb156278fa6f9d09119719af9814b858fd4f81f/googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd", size = 151035, upload-time = "2026-05-07T08:04:49.423Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/c8/e2645aa8ed02fd4c7a2f59d68783b65b1f3cbdfe39a6308e156509d1fee8/googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed", size = 300631, upload-time = "2026-05-07T08:03:30.345Z" }, -] - [[package]] name = "griffelib" version = "2.0.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, @@ -531,7 +519,7 @@ wheels = [ [[package]] name = "grpcio" version = "1.78.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -592,7 +580,7 @@ wheels = [ [[package]] name = "h11" version = "0.16.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, @@ -601,7 +589,7 @@ wheels = [ [[package]] name = "httpcore" version = "1.0.9" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "h11" }, @@ -614,7 +602,7 @@ wheels = [ [[package]] name = "httpx" version = "0.28.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "certifi" }, @@ -629,7 +617,7 @@ wheels = [ [[package]] name = "httpx-sse" version = "0.4.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, @@ -638,7 +626,7 @@ wheels = [ [[package]] name = "identify" version = "2.6.19" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, @@ -647,7 +635,7 @@ wheels = [ [[package]] name = "idna" version = "3.14" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/b1/efac073e0c297ecf2fb33c346989a529d4e19164f1759102dee5953ee17e/idna-3.14.tar.gz", hash = "sha256:466d810d7a2cc1022bea9b037c39728d51ae7dad40d480fc9b7d7ecf98ba8ee3", size = 198272, upload-time = "2026-05-10T20:32:15.935Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/6c/3c/3f62dee257eb3d6b2c1ef2a09d36d9793c7111156a73b5654d2c2305e5ce/idna-3.14-py3-none-any.whl", hash = "sha256:e677eaf072e290f7b725f9acf0b3a2bd55f9fd6f7c70abe5f0e34823d0accf69", size = 72184, upload-time = "2026-05-10T20:32:14.295Z" }, @@ -656,7 +644,7 @@ wheels = [ [[package]] name = "importlib-metadata" version = "8.7.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] @@ -668,7 +656,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.3.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, @@ -677,7 +665,7 @@ wheels = [ [[package]] name = "jiter" version = "0.14.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/2e/a9959997739c403378d0a4a3a1c4ed80b60aeace216c4d37b303a9fc60a4/jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531", size = 316927, upload-time = "2026-04-10T14:25:40.753Z" }, @@ -780,7 +768,7 @@ wheels = [ [[package]] name = "joserfc" version = "1.6.5" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] @@ -792,7 +780,7 @@ wheels = [ [[package]] name = "jsonpatch" version = "1.33" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpointer" }, ] @@ -804,7 +792,7 @@ wheels = [ [[package]] name = "jsonpointer" version = "3.1.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, @@ -813,7 +801,7 @@ wheels = [ [[package]] name = "jsonschema" version = "4.26.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, @@ -828,7 +816,7 @@ wheels = [ [[package]] name = "jsonschema-specifications" version = "2025.9.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "referencing" }, ] @@ -840,7 +828,7 @@ wheels = [ [[package]] name = "langchain" version = "1.3.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph" }, @@ -854,7 +842,7 @@ wheels = [ [[package]] name = "langchain-core" version = "1.4.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, { name = "langchain-protocol" }, @@ -874,7 +862,7 @@ wheels = [ [[package]] name = "langchain-protocol" version = "0.0.15" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -886,7 +874,7 @@ wheels = [ [[package]] name = "langgraph" version = "1.2.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -903,7 +891,7 @@ wheels = [ [[package]] name = "langgraph-checkpoint" version = "4.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, @@ -916,7 +904,7 @@ wheels = [ [[package]] name = "langgraph-prebuilt" version = "1.1.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -929,7 +917,7 @@ wheels = [ [[package]] name = "langgraph-sdk" version = "0.3.14" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson" }, @@ -942,7 +930,7 @@ wheels = [ [[package]] name = "langsmith" version = "0.8.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, @@ -962,7 +950,7 @@ wheels = [ [[package]] name = "mcp" version = "1.27.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "httpx" }, @@ -987,7 +975,7 @@ wheels = [ [[package]] name = "nodeenv" version = "1.10.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, @@ -996,7 +984,7 @@ wheels = [ [[package]] name = "openai" version = "2.36.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -1015,7 +1003,7 @@ wheels = [ [[package]] name = "openai-agents" version = "0.17.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, { name = "mcp" }, @@ -1040,28 +1028,6 @@ dependencies = [ { name = "typing-extensions" }, ] -[[package]] -name = "opentelemetry-exporter-otlp-proto-common" -version = "1.42.0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=exporter%2Fopentelemetry-exporter-otlp-proto-common&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } -dependencies = [ - { name = "opentelemetry-proto" }, -] - -[[package]] -name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.42.0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=exporter%2Fopentelemetry-exporter-otlp-proto-grpc&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "grpcio" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-exporter-otlp-proto-common" }, - { name = "opentelemetry-proto" }, - { name = "opentelemetry-sdk" }, - { name = "typing-extensions" }, -] - [[package]] name = "opentelemetry-instrumentation" version = "0.63b0.dev0" @@ -1240,14 +1206,6 @@ requires-dist = [ ] provides-extras = ["instruments"] -[[package]] -name = "opentelemetry-proto" -version = "1.42.0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-proto&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } -dependencies = [ - { name = "protobuf" }, -] - [[package]] name = "opentelemetry-python-genai" version = "0.0.0" @@ -1326,7 +1284,6 @@ version = "0.0.0" source = { editable = "util/opentelemetry-test-util-genai" } dependencies = [ { name = "opentelemetry-api" }, - { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "implementation_name != 'pypy'" }, { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-sdk" }, { name = "opentelemetry-semantic-conventions" }, @@ -1339,7 +1296,6 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "implementation_name != 'pypy'", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=exporter%2Fopentelemetry-exporter-otlp-proto-grpc&branch=main" }, { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, { name = "opentelemetry-sdk", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main" }, { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, @@ -1392,7 +1348,7 @@ provides-extras = ["test", "upload"] [[package]] name = "orjson" version = "3.11.9" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/10/5d/b95ca542a001135cc250a49370f282f578c8f4e46cc8617d73775297eea8/orjson-3.11.9-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:135869ef917b8704ea0a94e01620e0c05021c15c52036e4663baffe75e72f8ce", size = 228986, upload-time = "2026-05-06T15:09:14.765Z" }, @@ -1473,7 +1429,7 @@ wheels = [ [[package]] name = "ormsgpack" version = "1.12.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" }, @@ -1529,7 +1485,7 @@ wheels = [ [[package]] name = "packaging" version = "26.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, @@ -1538,7 +1494,7 @@ wheels = [ [[package]] name = "platformdirs" version = "4.9.6" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, @@ -1547,7 +1503,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.6.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, @@ -1556,7 +1512,7 @@ wheels = [ [[package]] name = "pre-commit" version = "4.6.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, { name = "identify" }, @@ -1572,7 +1528,7 @@ wheels = [ [[package]] name = "protobuf" version = "6.33.6" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, @@ -1587,7 +1543,7 @@ wheels = [ [[package]] name = "pyasn1" version = "0.6.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, @@ -1596,7 +1552,7 @@ wheels = [ [[package]] name = "pyasn1-modules" version = "0.4.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyasn1" }, ] @@ -1608,7 +1564,7 @@ wheels = [ [[package]] name = "pycparser" version = "3.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, @@ -1617,7 +1573,7 @@ wheels = [ [[package]] name = "pydantic" version = "2.13.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, @@ -1632,7 +1588,7 @@ wheels = [ [[package]] name = "pydantic-core" version = "2.46.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -1748,7 +1704,7 @@ wheels = [ [[package]] name = "pydantic-settings" version = "2.14.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, @@ -1762,7 +1718,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -1771,7 +1727,7 @@ wheels = [ [[package]] name = "pyjwt" version = "2.12.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -1788,7 +1744,7 @@ crypto = [ [[package]] name = "pyproject-api" version = "1.10.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -1801,7 +1757,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -1819,7 +1775,7 @@ wheels = [ [[package]] name = "python-discovery" version = "1.3.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, @@ -1832,7 +1788,7 @@ wheels = [ [[package]] name = "python-dotenv" version = "1.2.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, @@ -1841,7 +1797,7 @@ wheels = [ [[package]] name = "python-multipart" version = "0.0.28" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/54/a85eb421fbdd5007bc5af39d0f4ed9fa609e0fedbfdc2adcf0b34526870e/python_multipart-0.0.28.tar.gz", hash = "sha256:8550da197eac0f7ab748961fc9509b999fa2662ea25cef857f05249f6893c0f8", size = 45314, upload-time = "2026-05-10T11:05:16.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f3/a2/43bbc5860b5034e2af4ef99a0e04d726ff329c43e192ef3abaa8d7ecfce5/python_multipart-0.0.28-py3-none-any.whl", hash = "sha256:10faac07eb966c3f48dc415f9dee46c04cb10d58d30a35677db8027c825ed9b6", size = 29438, upload-time = "2026-05-10T11:05:15.052Z" }, @@ -1850,7 +1806,7 @@ wheels = [ [[package]] name = "pywin32" version = "311" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } wheels = [ { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, @@ -1872,7 +1828,7 @@ wheels = [ [[package]] name = "pyyaml" version = "6.0.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, @@ -1936,7 +1892,7 @@ wheels = [ [[package]] name = "referencing" version = "0.37.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, @@ -1950,7 +1906,7 @@ wheels = [ [[package]] name = "requests" version = "2.34.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, @@ -1965,7 +1921,7 @@ wheels = [ [[package]] name = "requests-toolbelt" version = "1.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "requests" }, ] @@ -1977,7 +1933,7 @@ wheels = [ [[package]] name = "rpds-py" version = "0.30.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, @@ -2099,7 +2055,7 @@ wheels = [ [[package]] name = "sniffio" version = "1.3.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, @@ -2108,7 +2064,7 @@ wheels = [ [[package]] name = "sse-starlette" version = "3.4.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "starlette" }, @@ -2121,7 +2077,7 @@ wheels = [ [[package]] name = "starlette" version = "1.0.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, @@ -2134,7 +2090,7 @@ wheels = [ [[package]] name = "tenacity" version = "9.1.4" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, @@ -2143,7 +2099,7 @@ wheels = [ [[package]] name = "tomli" version = "2.4.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, @@ -2197,7 +2153,7 @@ wheels = [ [[package]] name = "tomli-w" version = "1.2.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, @@ -2206,7 +2162,7 @@ wheels = [ [[package]] name = "tox" version = "4.54.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachetools" }, { name = "colorama" }, @@ -2229,7 +2185,7 @@ wheels = [ [[package]] name = "tox-uv" version = "1.35.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tox-uv-bare" }, { name = "uv" }, @@ -2241,7 +2197,7 @@ wheels = [ [[package]] name = "tox-uv-bare" version = "1.35.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -2255,7 +2211,7 @@ wheels = [ [[package]] name = "tqdm" version = "4.67.3" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -2267,7 +2223,7 @@ wheels = [ [[package]] name = "types-requests" version = "2.33.0.20260508" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] @@ -2279,7 +2235,7 @@ wheels = [ [[package]] name = "typing-extensions" version = "4.15.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, @@ -2288,7 +2244,7 @@ wheels = [ [[package]] name = "typing-inspection" version = "0.4.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] @@ -2300,7 +2256,7 @@ wheels = [ [[package]] name = "urllib3" version = "2.7.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, @@ -2309,7 +2265,7 @@ wheels = [ [[package]] name = "uuid-utils" version = "0.15.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0b/f6/1856dc5935a947a062fb8fefd8a26e0f9f6694320e7203c7e85bd291dc93/uuid_utils-0.15.0.tar.gz", hash = "sha256:f182733e3d88edd2ceeca292627e2b1d5fa8693abe00b160de5517616ed399ea", size = 42182, upload-time = "2026-05-11T12:07:01.82Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/19/428d181d89678be61f30eb812c66f42e6dfe4f9aee911f4db4450b55459c/uuid_utils-0.15.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:87b999e827a01681015068ae54c6c6ab8076b0f8bff6b4139eabdb2cd079d267", size = 564690, upload-time = "2026-05-11T12:08:27.97Z" }, @@ -2422,7 +2378,7 @@ wheels = [ [[package]] name = "uv" version = "0.11.14" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/30/a3/be4a946c7c2fc4094c020c8f7d8bd0a739bad55ebe4e2817d6e2b1bc6bff/uv-0.11.14.tar.gz", hash = "sha256:0ea006a117b586b2681b6dfd9703a540d2ad2a136ec0f48d272767e599cc3dfb", size = 4130699, upload-time = "2026-05-12T18:00:37.321Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f7/15/9b2138b16eb1fa8c2cd84b1037ad10c38b3acc36ce96c6d27000bfb7e716/uv-0.11.14-py3-none-linux_armv6l.whl", hash = "sha256:78411a883f230a710af19f2ac6e6f0ba8eae90f0e5af4605f923fd367539fff4", size = 23545199, upload-time = "2026-05-12T18:01:34.526Z" }, @@ -2448,7 +2404,7 @@ wheels = [ [[package]] name = "uvicorn" version = "0.46.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, @@ -2462,7 +2418,7 @@ wheels = [ [[package]] name = "validators" version = "0.35.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/53/66/a435d9ae49850b2f071f7ebd8119dd4e84872b01630d6736761e6e7fd847/validators-0.35.0.tar.gz", hash = "sha256:992d6c48a4e77c81f1b4daba10d16c3a9bb0dbb79b3a19ea847ff0928e70497a", size = 73399, upload-time = "2025-05-01T05:42:06.7Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl", hash = "sha256:e8c947097eae7892cb3d26868d637f79f47b4a0554bc6b80065dfe5aac3705dd", size = 44712, upload-time = "2025-05-01T05:42:04.203Z" }, @@ -2471,7 +2427,7 @@ wheels = [ [[package]] name = "virtualenv" version = "21.3.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, @@ -2487,7 +2443,7 @@ wheels = [ [[package]] name = "weaviate-client" version = "4.21.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "authlib" }, { name = "grpcio" }, @@ -2504,7 +2460,7 @@ wheels = [ [[package]] name = "websockets" version = "16.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, @@ -2572,7 +2528,7 @@ wheels = [ [[package]] name = "wrapt" version = "2.1.2" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/2e/64/925f213fdcbb9baeb1530449ac71a4d57fc361c053d06bf78d0c5c7cd80c/wrapt-2.1.2.tar.gz", hash = "sha256:3996a67eecc2c68fd47b4e3c564405a5777367adfd9b8abb58387b63ee83b21e", size = 81678, upload-time = "2026-03-06T02:53:25.134Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a86d99a14f76facb269dc148590c01aaf47584071809a70da30555228158c", size = 60669, upload-time = "2026-03-06T02:52:40.671Z" }, @@ -2658,7 +2614,7 @@ wheels = [ [[package]] name = "xxhash" version = "3.7.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/92/49/e4b575b4ed170a7f640c8bd69cfadfa81c7b700191fde5e72228762b9f73/xxhash-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd8ab85c916a58d5c8656ea15e3ce9df836fe2f120a74c296e01d69fab2614b4", size = 33426, upload-time = "2026-04-25T11:05:15.702Z" }, @@ -2815,7 +2771,7 @@ wheels = [ [[package]] name = "zipp" version = "3.23.1" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, @@ -2824,7 +2780,7 @@ wheels = [ [[package]] name = "zstandard" version = "0.25.0" -source = { registry = "https://pypi.org/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/56/7a/28efd1d371f1acd037ac64ed1c5e2b41514a6cc937dd6ab6a13ab9f0702f/zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd", size = 795256, upload-time = "2025-09-14T22:15:56.415Z" }, From bd7d350376f077a2b56962d35dd1dc93e6487071 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 13 May 2026 21:04:39 -0700 Subject: [PATCH 05/10] up --- pyproject.toml | 12 -- uv.lock | 309 ++++++++++++++++++++++++++----------------------- 2 files changed, 164 insertions(+), 157 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 99dcd7e0..66d6eeaf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,18 +38,6 @@ opentelemetry-instrumentation-openai-v2 = { workspace = true } opentelemetry-instrumentation-openai-agents-v2 = { workspace = true } opentelemetry-instrumentation-weaviate = { workspace = true } -# `opentelemetry.test.weaver_live_check` (used by conformance tests) is on -# main but not yet on PyPI (latest opentelemetry-test-utils is 0.62b1). Pin -# the whole otel-core stack to git+main so versions resolve coherently; -# drop once the file ships. -opentelemetry-api = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-api" } -opentelemetry-sdk = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-sdk" } -opentelemetry-semantic-conventions = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-semantic-conventions" } -opentelemetry-test-utils = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "tests/opentelemetry-test-utils" } -opentelemetry-instrumentation = { git = "https://github.com/open-telemetry/opentelemetry-python-contrib", branch = "main", subdirectory = "opentelemetry-instrumentation" } -opentelemetry-exporter-otlp-proto-grpc = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "exporter/opentelemetry-exporter-otlp-proto-grpc" } -opentelemetry-exporter-otlp-proto-common = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "exporter/opentelemetry-exporter-otlp-proto-common" } -opentelemetry-proto = { git = "https://github.com/open-telemetry/opentelemetry-python", branch = "main", subdirectory = "opentelemetry-proto" } # https://docs.astral.sh/uv/reference/settings/#workspace [tool.uv.workspace] diff --git a/uv.lock b/uv.lock index f4c95381..08c0efa5 100644 --- a/uv.lock +++ b/uv.lock @@ -24,7 +24,7 @@ members = [ [[package]] name = "annotated-types" version = "0.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, @@ -33,7 +33,7 @@ wheels = [ [[package]] name = "anthropic" version = "0.101.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -52,7 +52,7 @@ wheels = [ [[package]] name = "anyio" version = "4.13.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, @@ -66,7 +66,7 @@ wheels = [ [[package]] name = "asgiref" version = "3.11.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -78,7 +78,7 @@ wheels = [ [[package]] name = "attrs" version = "26.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, @@ -87,7 +87,7 @@ wheels = [ [[package]] name = "authlib" version = "1.7.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cryptography" }, { name = "joserfc" }, @@ -100,7 +100,7 @@ wheels = [ [[package]] name = "cachetools" version = "7.1.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/ff/e2/85f227594656000ff4d8adadae91a21f536d4a84c6c716a86bd6685874be/cachetools-7.1.1.tar.gz", hash = "sha256:27bdf856d68fd3c71c26c01b5edc312124ed427524d1ddb31aa2b7746fe20d4b", size = 40202, upload-time = "2026-05-03T20:00:29.391Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/bf/0f/f897abe4ea0a8c408ae65c8c83bffab4936ad65d6032d4fb4cd35bbdc3ee/cachetools-7.1.1-py3-none-any.whl", hash = "sha256:0335cd7a0952d2b22327441fb0628139e234c565559eeb91a8a4ac7551c5353d", size = 16775, upload-time = "2026-05-03T20:00:27.857Z" }, @@ -109,7 +109,7 @@ wheels = [ [[package]] name = "certifi" version = "2026.4.22" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, @@ -118,7 +118,7 @@ wheels = [ [[package]] name = "cffi" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] @@ -200,7 +200,7 @@ wheels = [ [[package]] name = "cfgv" version = "3.5.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, @@ -209,7 +209,7 @@ wheels = [ [[package]] name = "charset-normalizer" version = "3.4.7" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, @@ -314,7 +314,7 @@ wheels = [ [[package]] name = "claude-agent-sdk" version = "0.1.81" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "mcp" }, @@ -333,7 +333,7 @@ wheels = [ [[package]] name = "click" version = "8.3.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -345,7 +345,7 @@ wheels = [ [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -354,7 +354,7 @@ wheels = [ [[package]] name = "cryptography" version = "48.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, @@ -414,7 +414,7 @@ wheels = [ [[package]] name = "distlib" version = "0.4.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, @@ -423,7 +423,7 @@ wheels = [ [[package]] name = "distro" version = "1.9.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, @@ -432,7 +432,7 @@ wheels = [ [[package]] name = "docstring-parser" version = "0.18.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, @@ -441,7 +441,7 @@ wheels = [ [[package]] name = "exceptiongroup" version = "1.3.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] @@ -453,7 +453,7 @@ wheels = [ [[package]] name = "filelock" version = "3.29.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, @@ -462,7 +462,7 @@ wheels = [ [[package]] name = "fsspec" version = "2026.4.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" }, @@ -471,7 +471,7 @@ wheels = [ [[package]] name = "google-auth" version = "2.52.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, @@ -489,7 +489,7 @@ requests = [ [[package]] name = "google-genai" version = "2.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -510,7 +510,7 @@ wheels = [ [[package]] name = "griffelib" version = "2.0.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, @@ -519,7 +519,7 @@ wheels = [ [[package]] name = "grpcio" version = "1.78.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -580,7 +580,7 @@ wheels = [ [[package]] name = "h11" version = "0.16.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, @@ -589,7 +589,7 @@ wheels = [ [[package]] name = "httpcore" version = "1.0.9" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "certifi" }, { name = "h11" }, @@ -602,7 +602,7 @@ wheels = [ [[package]] name = "httpx" version = "0.28.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "certifi" }, @@ -617,7 +617,7 @@ wheels = [ [[package]] name = "httpx-sse" version = "0.4.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, @@ -626,7 +626,7 @@ wheels = [ [[package]] name = "identify" version = "2.6.19" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, @@ -635,7 +635,7 @@ wheels = [ [[package]] name = "idna" version = "3.14" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/05/b1/efac073e0c297ecf2fb33c346989a529d4e19164f1759102dee5953ee17e/idna-3.14.tar.gz", hash = "sha256:466d810d7a2cc1022bea9b037c39728d51ae7dad40d480fc9b7d7ecf98ba8ee3", size = 198272, upload-time = "2026-05-10T20:32:15.935Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/6c/3c/3f62dee257eb3d6b2c1ef2a09d36d9793c7111156a73b5654d2c2305e5ce/idna-3.14-py3-none-any.whl", hash = "sha256:e677eaf072e290f7b725f9acf0b3a2bd55f9fd6f7c70abe5f0e34823d0accf69", size = 72184, upload-time = "2026-05-10T20:32:14.295Z" }, @@ -644,7 +644,7 @@ wheels = [ [[package]] name = "importlib-metadata" version = "8.7.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "zipp" }, ] @@ -656,7 +656,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.3.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, @@ -665,7 +665,7 @@ wheels = [ [[package]] name = "jiter" version = "0.14.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/2e/a9959997739c403378d0a4a3a1c4ed80b60aeace216c4d37b303a9fc60a4/jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531", size = 316927, upload-time = "2026-04-10T14:25:40.753Z" }, @@ -768,7 +768,7 @@ wheels = [ [[package]] name = "joserfc" version = "1.6.5" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cryptography" }, ] @@ -780,7 +780,7 @@ wheels = [ [[package]] name = "jsonpatch" version = "1.33" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "jsonpointer" }, ] @@ -792,7 +792,7 @@ wheels = [ [[package]] name = "jsonpointer" version = "3.1.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, @@ -801,7 +801,7 @@ wheels = [ [[package]] name = "jsonschema" version = "4.26.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, @@ -816,7 +816,7 @@ wheels = [ [[package]] name = "jsonschema-specifications" version = "2025.9.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "referencing" }, ] @@ -828,7 +828,7 @@ wheels = [ [[package]] name = "langchain" version = "1.3.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "langgraph" }, @@ -842,7 +842,7 @@ wheels = [ [[package]] name = "langchain-core" version = "1.4.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "jsonpatch" }, { name = "langchain-protocol" }, @@ -862,7 +862,7 @@ wheels = [ [[package]] name = "langchain-protocol" version = "0.0.15" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -874,7 +874,7 @@ wheels = [ [[package]] name = "langgraph" version = "1.2.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -891,7 +891,7 @@ wheels = [ [[package]] name = "langgraph-checkpoint" version = "4.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, @@ -904,7 +904,7 @@ wheels = [ [[package]] name = "langgraph-prebuilt" version = "1.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -917,7 +917,7 @@ wheels = [ [[package]] name = "langgraph-sdk" version = "0.3.14" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "httpx" }, { name = "orjson" }, @@ -930,7 +930,7 @@ wheels = [ [[package]] name = "langsmith" version = "0.8.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "httpx" }, { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, @@ -950,7 +950,7 @@ wheels = [ [[package]] name = "mcp" version = "1.27.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "httpx" }, @@ -975,7 +975,7 @@ wheels = [ [[package]] name = "nodeenv" version = "1.10.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, @@ -984,7 +984,7 @@ wheels = [ [[package]] name = "openai" version = "2.36.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -1003,7 +1003,7 @@ wheels = [ [[package]] name = "openai-agents" version = "0.17.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "griffelib" }, { name = "mcp" }, @@ -1021,23 +1021,31 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.42.0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +version = "1.41.1" +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "importlib-metadata" }, { name = "typing-extensions" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/fa/fc/b7564cbef36601aef0d6c9bc01f7badb64be8e862c2e1c3c5c3b43b53e4f/opentelemetry_api-1.41.1.tar.gz", hash = "sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621", size = 71416, upload-time = "2026-04-24T13:15:38.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/59/3e7118ed140f76b0982ba4321bdaed1997a0473f9720de2d10788a577033/opentelemetry_api-1.41.1-py3-none-any.whl", hash = "sha256:a22df900e75c76dc08440710e51f52f1aa6b451b429298896023e60db5b3139f", size = 69007, upload-time = "2026-04-24T13:15:15.662Z" }, +] [[package]] name = "opentelemetry-instrumentation" -version = "0.63b0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main#d2f396de68a969dfb74b8afc247e1d0dc6739b67" } +version = "0.62b1" +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "packaging" }, { name = "wrapt" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/52/cb/0523b92c112a6cc70be43724343dc45225d3af134419844d7879a07755d4/opentelemetry_instrumentation-0.62b1.tar.gz", hash = "sha256:90e92a905ba4f84db06ac3aec96701df6c079b2d66e9379f8739f0a1bdcc7f45", size = 34043, upload-time = "2026-04-24T13:22:31.997Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/0f/45adbaea1f81b847cffdcee4f4b5f89297e42facf7fac78c7aaac4c38e75/opentelemetry_instrumentation-0.62b1-py3-none-any.whl", hash = "sha256:976fc6e640f2006599e97429c949e622c108d0c17c2059347d1e6c93c707f257", size = 34163, upload-time = "2026-04-24T13:21:31.722Z" }, +] [[package]] name = "opentelemetry-instrumentation-anthropic" @@ -1057,9 +1065,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "anthropic", marker = "extra == 'instruments'", specifier = ">=0.51.0" }, - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = "~=1.40" }, + { name = "opentelemetry-instrumentation", specifier = "~=0.61b0" }, + { name = "opentelemetry-semantic-conventions", specifier = "~=0.61b0" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1082,9 +1090,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "claude-agent-sdk", marker = "extra == 'instruments'", specifier = ">=0.1.14" }, - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = "~=1.39" }, + { name = "opentelemetry-instrumentation", specifier = "~=0.60b0" }, + { name = "opentelemetry-semantic-conventions", specifier = "~=0.60b0" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1107,9 +1115,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "google-genai", marker = "extra == 'instruments'", specifier = ">=1.32.0" }, - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = "~=1.40" }, + { name = "opentelemetry-instrumentation", specifier = ">=0.61b0,<2" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.61b0,<2" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1129,7 +1137,7 @@ instruments = [ [package.metadata] requires-dist = [ { name = "langchain", marker = "extra == 'instruments'", specifier = ">=0.3.21" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-instrumentation", specifier = "~=0.57b0" }, ] provides-extras = ["instruments"] @@ -1151,9 +1159,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "openai-agents", marker = "extra == 'instruments'", specifier = ">=0.3.3" }, - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = ">=1.40" }, + { name = "opentelemetry-instrumentation", specifier = ">=0.61b0" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.61b0" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1176,9 +1184,9 @@ instruments = [ [package.metadata] requires-dist = [ { name = "openai", marker = "extra == 'instruments'", specifier = ">=1.26.0" }, - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = "~=1.40" }, + { name = "opentelemetry-instrumentation", specifier = "~=0.61b0" }, + { name = "opentelemetry-semantic-conventions", specifier = "~=0.61b0" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] provides-extras = ["instruments"] @@ -1199,9 +1207,9 @@ instruments = [ [package.metadata] requires-dist = [ - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = "~=1.30" }, + { name = "opentelemetry-instrumentation", specifier = "~=0.51b0" }, + { name = "opentelemetry-semantic-conventions", specifier = "~=0.51b0" }, { name = "weaviate-client", marker = "extra == 'instruments'", specifier = ">=3.0" }, ] provides-extras = ["instruments"] @@ -1236,8 +1244,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-instrumentation-anthropic", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-anthropic" }, { name = "opentelemetry-instrumentation-claude-agent-sdk", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-claude-agent-sdk" }, { name = "opentelemetry-instrumentation-google-genai", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-google-genai" }, @@ -1245,10 +1253,10 @@ requires-dist = [ { name = "opentelemetry-instrumentation-openai-agents-v2", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-openai-agents-v2" }, { name = "opentelemetry-instrumentation-openai-v2", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-openai-v2" }, { name = "opentelemetry-instrumentation-weaviate", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-weaviate" }, - { name = "opentelemetry-sdk", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-semantic-conventions" }, { name = "opentelemetry-test-util-genai", editable = "util/opentelemetry-test-util-genai" }, - { name = "opentelemetry-test-utils", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=tests%2Fopentelemetry-test-utils&branch=main" }, + { name = "opentelemetry-test-utils" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, ] @@ -1261,22 +1269,30 @@ dev = [ [[package]] name = "opentelemetry-sdk" -version = "1.42.0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +version = "1.41.1" +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/58/d0/54ee30dab82fb0acda23d144502771ff76ef8728459c83c3e89ef9fb1825/opentelemetry_sdk-1.41.1.tar.gz", hash = "sha256:724b615e1215b5aeacda0abb8a6a8922c9a1853068948bd0bd225a56d0c792e6", size = 230180, upload-time = "2026-04-24T13:15:50.991Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/e7/a1420b698aad018e1cf60fdbaaccbe49021fb415e2a0d81c242f4c518f54/opentelemetry_sdk-1.41.1-py3-none-any.whl", hash = "sha256:edee379c126c1bce952b0c812b48fe8ff35b30df0eecf17e98afa4d598b7d85d", size = 180213, upload-time = "2026-04-24T13:15:33.767Z" }, +] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.63b0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +version = "0.62b1" +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/9e/de/911ac9e309052aca1b20b2d5549d3db45d1011e1a610e552c6ccdd1b64f8/opentelemetry_semantic_conventions-0.62b1.tar.gz", hash = "sha256:c5cc6e04a7f8c7cdd30be2ed81499fa4e75bfbd52c9cb70d40af1f9cd3619802", size = 145750, upload-time = "2026-04-24T13:15:52.236Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/a6/83dc2ab6fa397ee66fba04fe2e74bdf7be3b3870005359ceb7689103c058/opentelemetry_semantic_conventions-0.62b1-py3-none-any.whl", hash = "sha256:cf506938103d331fbb78eded0d9788095f7fd59016f2bda813c3324e5a74a93c", size = 231620, upload-time = "2026-04-24T13:15:35.454Z" }, +] [[package]] name = "opentelemetry-test-util-genai" @@ -1295,11 +1311,11 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-sdk", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-sdk&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, - { name = "opentelemetry-test-utils", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=tests%2Fopentelemetry-test-utils&branch=main" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-test-utils" }, { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, { name = "pytest" }, { name = "pyyaml" }, @@ -1307,13 +1323,16 @@ requires-dist = [ [[package]] name = "opentelemetry-test-utils" -version = "0.63b0.dev0" -source = { git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=tests%2Fopentelemetry-test-utils&branch=main#f67bb8472eb76115ed29d433ec0798c801df57b6" } +version = "0.62b1" +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "asgiref" }, { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, - { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/0d/555b86a209da4b6ed716320359a38c88ac2981f258ea44303ea84297e346/opentelemetry_test_utils-0.62b1.tar.gz", hash = "sha256:26dc0bcbb6ba953ee964a9c23f3d28f979af52c2bbf7cf49cf0c8548634c40cd", size = 8845, upload-time = "2026-04-24T13:15:53.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/65/2f365677d1ded6fabfe563ddb03d619b16dcb6b6a5d26035911c3a7ad420/opentelemetry_test_utils-0.62b1-py3-none-any.whl", hash = "sha256:060b4bf85e6175f99e340a78d99b80a51286786296f9e584c5f99de2a35bc7ff", size = 15406, upload-time = "2026-04-24T13:15:36.89Z" }, ] [[package]] @@ -1337,9 +1356,9 @@ upload = [ [package.metadata] requires-dist = [ { name = "fsspec", marker = "extra == 'upload'", specifier = ">=2025.9.0" }, - { name = "opentelemetry-api", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-api&branch=main" }, - { name = "opentelemetry-instrumentation", git = "https://github.com/open-telemetry/opentelemetry-python-contrib?subdirectory=opentelemetry-instrumentation&branch=main" }, - { name = "opentelemetry-semantic-conventions", git = "https://github.com/open-telemetry/opentelemetry-python?subdirectory=opentelemetry-semantic-conventions&branch=main" }, + { name = "opentelemetry-api", specifier = "~=1.40" }, + { name = "opentelemetry-instrumentation", specifier = "~=0.61b0" }, + { name = "opentelemetry-semantic-conventions", specifier = "~=0.61b0" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=7.0.0" }, { name = "wrapt", specifier = ">=1.0.0,<3.0.0" }, ] @@ -1348,7 +1367,7 @@ provides-extras = ["test", "upload"] [[package]] name = "orjson" version = "3.11.9" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/10/5d/b95ca542a001135cc250a49370f282f578c8f4e46cc8617d73775297eea8/orjson-3.11.9-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:135869ef917b8704ea0a94e01620e0c05021c15c52036e4663baffe75e72f8ce", size = 228986, upload-time = "2026-05-06T15:09:14.765Z" }, @@ -1429,7 +1448,7 @@ wheels = [ [[package]] name = "ormsgpack" version = "1.12.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" }, @@ -1485,7 +1504,7 @@ wheels = [ [[package]] name = "packaging" version = "26.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, @@ -1494,7 +1513,7 @@ wheels = [ [[package]] name = "platformdirs" version = "4.9.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, @@ -1503,7 +1522,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.6.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, @@ -1512,7 +1531,7 @@ wheels = [ [[package]] name = "pre-commit" version = "4.6.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cfgv" }, { name = "identify" }, @@ -1528,7 +1547,7 @@ wheels = [ [[package]] name = "protobuf" version = "6.33.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, @@ -1543,7 +1562,7 @@ wheels = [ [[package]] name = "pyasn1" version = "0.6.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, @@ -1552,7 +1571,7 @@ wheels = [ [[package]] name = "pyasn1-modules" version = "0.4.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "pyasn1" }, ] @@ -1564,7 +1583,7 @@ wheels = [ [[package]] name = "pycparser" version = "3.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, @@ -1573,7 +1592,7 @@ wheels = [ [[package]] name = "pydantic" version = "2.13.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, @@ -1588,7 +1607,7 @@ wheels = [ [[package]] name = "pydantic-core" version = "2.46.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -1704,7 +1723,7 @@ wheels = [ [[package]] name = "pydantic-settings" version = "2.14.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, @@ -1718,7 +1737,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -1727,7 +1746,7 @@ wheels = [ [[package]] name = "pyjwt" version = "2.12.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -1744,7 +1763,7 @@ crypto = [ [[package]] name = "pyproject-api" version = "1.10.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -1757,7 +1776,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -1775,7 +1794,7 @@ wheels = [ [[package]] name = "python-discovery" version = "1.3.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, @@ -1788,7 +1807,7 @@ wheels = [ [[package]] name = "python-dotenv" version = "1.2.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, @@ -1797,7 +1816,7 @@ wheels = [ [[package]] name = "python-multipart" version = "0.0.28" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/82/54/a85eb421fbdd5007bc5af39d0f4ed9fa609e0fedbfdc2adcf0b34526870e/python_multipart-0.0.28.tar.gz", hash = "sha256:8550da197eac0f7ab748961fc9509b999fa2662ea25cef857f05249f6893c0f8", size = 45314, upload-time = "2026-05-10T11:05:16.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f3/a2/43bbc5860b5034e2af4ef99a0e04d726ff329c43e192ef3abaa8d7ecfce5/python_multipart-0.0.28-py3-none-any.whl", hash = "sha256:10faac07eb966c3f48dc415f9dee46c04cb10d58d30a35677db8027c825ed9b6", size = 29438, upload-time = "2026-05-10T11:05:15.052Z" }, @@ -1806,7 +1825,7 @@ wheels = [ [[package]] name = "pywin32" version = "311" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } wheels = [ { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, @@ -1828,7 +1847,7 @@ wheels = [ [[package]] name = "pyyaml" version = "6.0.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, @@ -1892,7 +1911,7 @@ wheels = [ [[package]] name = "referencing" version = "0.37.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, @@ -1906,7 +1925,7 @@ wheels = [ [[package]] name = "requests" version = "2.34.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, @@ -1921,7 +1940,7 @@ wheels = [ [[package]] name = "requests-toolbelt" version = "1.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "requests" }, ] @@ -1933,7 +1952,7 @@ wheels = [ [[package]] name = "rpds-py" version = "0.30.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, @@ -2055,7 +2074,7 @@ wheels = [ [[package]] name = "sniffio" version = "1.3.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, @@ -2064,7 +2083,7 @@ wheels = [ [[package]] name = "sse-starlette" version = "3.4.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "starlette" }, @@ -2077,7 +2096,7 @@ wheels = [ [[package]] name = "starlette" version = "1.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, @@ -2090,7 +2109,7 @@ wheels = [ [[package]] name = "tenacity" version = "9.1.4" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, @@ -2099,7 +2118,7 @@ wheels = [ [[package]] name = "tomli" version = "2.4.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, @@ -2153,7 +2172,7 @@ wheels = [ [[package]] name = "tomli-w" version = "1.2.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, @@ -2162,7 +2181,7 @@ wheels = [ [[package]] name = "tox" version = "4.54.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "cachetools" }, { name = "colorama" }, @@ -2185,7 +2204,7 @@ wheels = [ [[package]] name = "tox-uv" version = "1.35.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "tox-uv-bare" }, { name = "uv" }, @@ -2197,7 +2216,7 @@ wheels = [ [[package]] name = "tox-uv-bare" version = "1.35.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, @@ -2211,7 +2230,7 @@ wheels = [ [[package]] name = "tqdm" version = "4.67.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] @@ -2223,7 +2242,7 @@ wheels = [ [[package]] name = "types-requests" version = "2.33.0.20260508" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "urllib3" }, ] @@ -2235,7 +2254,7 @@ wheels = [ [[package]] name = "typing-extensions" version = "4.15.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, @@ -2244,7 +2263,7 @@ wheels = [ [[package]] name = "typing-inspection" version = "0.4.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "typing-extensions" }, ] @@ -2256,7 +2275,7 @@ wheels = [ [[package]] name = "urllib3" version = "2.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, @@ -2265,7 +2284,7 @@ wheels = [ [[package]] name = "uuid-utils" version = "0.15.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/0b/f6/1856dc5935a947a062fb8fefd8a26e0f9f6694320e7203c7e85bd291dc93/uuid_utils-0.15.0.tar.gz", hash = "sha256:f182733e3d88edd2ceeca292627e2b1d5fa8693abe00b160de5517616ed399ea", size = 42182, upload-time = "2026-05-11T12:07:01.82Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/19/428d181d89678be61f30eb812c66f42e6dfe4f9aee911f4db4450b55459c/uuid_utils-0.15.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:87b999e827a01681015068ae54c6c6ab8076b0f8bff6b4139eabdb2cd079d267", size = 564690, upload-time = "2026-05-11T12:08:27.97Z" }, @@ -2378,7 +2397,7 @@ wheels = [ [[package]] name = "uv" version = "0.11.14" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/30/a3/be4a946c7c2fc4094c020c8f7d8bd0a739bad55ebe4e2817d6e2b1bc6bff/uv-0.11.14.tar.gz", hash = "sha256:0ea006a117b586b2681b6dfd9703a540d2ad2a136ec0f48d272767e599cc3dfb", size = 4130699, upload-time = "2026-05-12T18:00:37.321Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f7/15/9b2138b16eb1fa8c2cd84b1037ad10c38b3acc36ce96c6d27000bfb7e716/uv-0.11.14-py3-none-linux_armv6l.whl", hash = "sha256:78411a883f230a710af19f2ac6e6f0ba8eae90f0e5af4605f923fd367539fff4", size = 23545199, upload-time = "2026-05-12T18:01:34.526Z" }, @@ -2404,7 +2423,7 @@ wheels = [ [[package]] name = "uvicorn" version = "0.46.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "click" }, { name = "h11" }, @@ -2418,7 +2437,7 @@ wheels = [ [[package]] name = "validators" version = "0.35.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/53/66/a435d9ae49850b2f071f7ebd8119dd4e84872b01630d6736761e6e7fd847/validators-0.35.0.tar.gz", hash = "sha256:992d6c48a4e77c81f1b4daba10d16c3a9bb0dbb79b3a19ea847ff0928e70497a", size = 73399, upload-time = "2025-05-01T05:42:06.7Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl", hash = "sha256:e8c947097eae7892cb3d26868d637f79f47b4a0554bc6b80065dfe5aac3705dd", size = 44712, upload-time = "2025-05-01T05:42:04.203Z" }, @@ -2427,7 +2446,7 @@ wheels = [ [[package]] name = "virtualenv" version = "21.3.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "distlib" }, { name = "filelock" }, @@ -2443,7 +2462,7 @@ wheels = [ [[package]] name = "weaviate-client" version = "4.21.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "authlib" }, { name = "grpcio" }, @@ -2460,7 +2479,7 @@ wheels = [ [[package]] name = "websockets" version = "16.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, @@ -2528,7 +2547,7 @@ wheels = [ [[package]] name = "wrapt" version = "2.1.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/2e/64/925f213fdcbb9baeb1530449ac71a4d57fc361c053d06bf78d0c5c7cd80c/wrapt-2.1.2.tar.gz", hash = "sha256:3996a67eecc2c68fd47b4e3c564405a5777367adfd9b8abb58387b63ee83b21e", size = 81678, upload-time = "2026-03-06T02:53:25.134Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a86d99a14f76facb269dc148590c01aaf47584071809a70da30555228158c", size = 60669, upload-time = "2026-03-06T02:52:40.671Z" }, @@ -2614,7 +2633,7 @@ wheels = [ [[package]] name = "xxhash" version = "3.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/92/49/e4b575b4ed170a7f640c8bd69cfadfa81c7b700191fde5e72228762b9f73/xxhash-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd8ab85c916a58d5c8656ea15e3ce9df836fe2f120a74c296e01d69fab2614b4", size = 33426, upload-time = "2026-04-25T11:05:15.702Z" }, @@ -2771,7 +2790,7 @@ wheels = [ [[package]] name = "zipp" version = "3.23.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, @@ -2780,7 +2799,7 @@ wheels = [ [[package]] name = "zstandard" version = "0.25.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi.org/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/56/7a/28efd1d371f1acd037ac64ed1c5e2b41514a6cc937dd6ab6a13ab9f0702f/zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd", size = 795256, upload-time = "2025-09-14T22:15:56.415Z" }, From b15240cdb7ec1dcc36d1800cfbdfd60b5158af83 Mon Sep 17 00:00:00 2001 From: liudmila molkova Date: Mon, 18 May 2026 10:12:10 -0700 Subject: [PATCH 06/10] rename files --- .../{inference-conformance.yaml => inference_conformance.yaml} | 0 ...l_calling-conformance.yaml => tool_calling_conformance.yaml} | 0 .../tests/conformance/inference.py | 2 +- .../tests/conformance/tool_calling.py | 2 +- .../{inference-conformance.yaml => inference_conformance.yaml} | 0 .../tests/conformance/inference.py | 2 +- .../{embedding-conformance.yaml => embedding_conformance.yaml} | 0 .../{inference-conformance.yaml => inference_conformance.yaml} | 0 ...l_calling-conformance.yaml => tool_calling_conformance.yaml} | 0 .../tests/conformance/embedding.py | 2 +- .../tests/conformance/inference.py | 2 +- .../tests/conformance/tool_calling.py | 2 +- 12 files changed, 6 insertions(+), 6 deletions(-) rename instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/{inference-conformance.yaml => inference_conformance.yaml} (100%) rename instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/{tool_calling-conformance.yaml => tool_calling_conformance.yaml} (100%) rename instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/{inference-conformance.yaml => inference_conformance.yaml} (100%) rename instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/{embedding-conformance.yaml => embedding_conformance.yaml} (100%) rename instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/{inference-conformance.yaml => inference_conformance.yaml} (100%) rename instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/{tool_calling-conformance.yaml => tool_calling_conformance.yaml} (100%) diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference-conformance.yaml b/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference_conformance.yaml similarity index 100% rename from instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference-conformance.yaml rename to instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/inference_conformance.yaml diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling-conformance.yaml b/instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling_conformance.yaml similarity index 100% rename from instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling-conformance.yaml rename to instrumentation/opentelemetry-instrumentation-anthropic/tests/cassettes/tool_calling_conformance.yaml diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py index f5d8c2ec..1c5e59ad 100644 --- a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/inference.py @@ -48,7 +48,7 @@ def run( semconv="gen_ai_latest_experimental", content_capture="SPAN_ONLY", ): - with vcr.use_cassette("inference-conformance.yaml"): + with vcr.use_cassette("inference_conformance.yaml"): Anthropic().messages.create( model="claude-sonnet-4-20250514", max_tokens=100, diff --git a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py index a762fe99..75f42098 100644 --- a/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py +++ b/instrumentation/opentelemetry-instrumentation-anthropic/tests/conformance/tool_calling.py @@ -48,7 +48,7 @@ def run( semconv="gen_ai_latest_experimental", content_capture="SPAN_ONLY", ): - with vcr.use_cassette("tool_calling-conformance.yaml"): + with vcr.use_cassette("tool_calling_conformance.yaml"): Anthropic().messages.create( model="claude-sonnet-4-20250514", max_tokens=256, diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference-conformance.yaml b/instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference_conformance.yaml similarity index 100% rename from instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference-conformance.yaml rename to instrumentation/opentelemetry-instrumentation-langchain/tests/cassettes/inference_conformance.yaml diff --git a/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py index 188345a6..b42b324e 100644 --- a/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py +++ b/instrumentation/opentelemetry-instrumentation-langchain/tests/conformance/inference.py @@ -59,7 +59,7 @@ def run( stop_sequences=["\n", "Human:", "AI:"], seed=100, ) - with vcr.use_cassette("inference-conformance.yaml"): + with vcr.use_cassette("inference_conformance.yaml"): llm.invoke( [ SystemMessage( diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding-conformance.yaml b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding_conformance.yaml similarity index 100% rename from instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding-conformance.yaml rename to instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/embedding_conformance.yaml diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference-conformance.yaml b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference_conformance.yaml similarity index 100% rename from instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference-conformance.yaml rename to instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/inference_conformance.yaml diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling-conformance.yaml b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling_conformance.yaml similarity index 100% rename from instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling-conformance.yaml rename to instrumentation/opentelemetry-instrumentation-openai-v2/tests/cassettes/tool_calling_conformance.yaml diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py index 307666b6..f18cae22 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/embedding.py @@ -40,7 +40,7 @@ def run( semconv="gen_ai_latest_experimental", content_capture="SPAN_ONLY", ): - with vcr.use_cassette("embedding-conformance.yaml"): + with vcr.use_cassette("embedding_conformance.yaml"): OpenAI().embeddings.create( input="The quick brown fox jumps over the lazy dog", model="text-embedding-3-small", diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py index 70e5eeb6..b5efb333 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/inference.py @@ -40,7 +40,7 @@ def run( semconv="gen_ai_latest_experimental", content_capture="SPAN_ONLY", ): - with vcr.use_cassette("inference-conformance.yaml"): + with vcr.use_cassette("inference_conformance.yaml"): OpenAI().chat.completions.create( messages=[ {"role": "user", "content": "Say this is a test"} diff --git a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py index 3cb3a4b4..174d2928 100644 --- a/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py +++ b/instrumentation/opentelemetry-instrumentation-openai-v2/tests/conformance/tool_calling.py @@ -82,7 +82,7 @@ def run( semconv="gen_ai_latest_experimental", content_capture="SPAN_ONLY", ): - with vcr.use_cassette("tool_calling-conformance.yaml"): + with vcr.use_cassette("tool_calling_conformance.yaml"): client = OpenAI() messages: list[Any] = list(WEATHER_TOOL_PROMPT) From 77e5d70c8f14d48c72544e8802c8e6d93279f642 Mon Sep 17 00:00:00 2001 From: liudmila molkova Date: Mon, 18 May 2026 10:46:12 -0700 Subject: [PATCH 07/10] add section on recordings in contrib.md --- CONTRIBUTING.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 90576015..17de655e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,6 +66,23 @@ Run type checking across the workspace: uv run tox -e typecheck ``` +#### Managing cassettes (test recordings) + +GenAI tests replay recorded HTTP interactions (cassettes) stored under each +package's `tests/cassettes/`. + +- **Run**: nothing extra — cassettes replay automatically when present. Tests + that need a cassette skip if it is missing and no real API key is set. +- **Record**: delete the target `tests/cassettes/.yaml`, export a + real provider API key (e.g. `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`), and + rerun the test. `pytest-vcr` writes the cassette on the live call. +- **Sanitize**: every package's `vcr_config()` in `tests/conftest.py` must + scrub auth via `filter_headers` and strip identifying response headers via + `scrub_response_headers(...)` from `opentelemetry.test_util_genai.vcr`. + Diff each new cassette before committing — leaked API keys, org ids, or + `Set-Cookie` values block the PR. +- **CI**: replay-only; recording in CI is a future improvement. + ### 4. Update the changelog This repo uses [towncrier](https://towncrier.readthedocs.io/) to manage @@ -136,3 +153,4 @@ For more information about the maintainer role, see the [community repository](h - [Leighton Chen](https://github.com/lzchen), Microsoft For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver). + From f56d48854805978f54a0db58d8b0526f23415cce Mon Sep 17 00:00:00 2001 From: liudmila molkova Date: Mon, 18 May 2026 10:49:27 -0700 Subject: [PATCH 08/10] generate workflows --- .github/workflows/test.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 05015eec..d3f5bc7c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -258,10 +258,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout repo @ SHA - ${{ github.sha }} - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.12 - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" @@ -293,10 +293,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout repo @ SHA - ${{ github.sha }} - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.13 - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" @@ -898,10 +898,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout repo @ SHA - ${{ github.sha }} - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.12 - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" @@ -933,10 +933,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout repo @ SHA - ${{ github.sha }} - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.13 - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" @@ -1120,10 +1120,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout repo @ SHA - ${{ github.sha }} - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.12 - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" @@ -1155,10 +1155,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout repo @ SHA - ${{ github.sha }} - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.13 - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" From 1ca2a33903a62fa6c3bdddf2f893960f6271b304 Mon Sep 17 00:00:00 2001 From: liudmila molkova Date: Mon, 18 May 2026 11:56:01 -0700 Subject: [PATCH 09/10] run live-check against semconv-genai --- .github/renovate.json5 | 4 +- dev-requirements-conformance.txt | 14 +- .../test_util_genai/_setup_weaver.py | 184 ++++++++++++++---- .../opentelemetry/test_util_genai/fixtures.py | 6 +- versions.env | 5 +- 5 files changed, 165 insertions(+), 48 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 2c0d8fe0..4a0cf6a7 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -13,7 +13,7 @@ // requirements.latest.txt files are skipped without this. "managerFilePatterns": ["/(^|/)requirements\\.latest\\.txt$/"] }, - // Manage WEAVER_VERSION and SEMCONV_VERSION in versions.env via their + // Manage WEAVER_VERSION and SEMCONV_GENAI_REF in versions.env via their // `# renovate:` annotations. "customManagers": [ { @@ -21,7 +21,7 @@ "managerFilePatterns": ["/^versions\\.env$/"], "matchStrings": [ "# renovate: datasource=(?\\S+) depName=(?\\S+) versioning=(?\\S+)\\s+WEAVER_VERSION=(?\\S+)", - "# renovate: datasource=(?\\S+) depName=(?\\S+) versioning=(?\\S+)\\s+SEMCONV_VERSION=(?\\S+)" + "# renovate: datasource=(?\\S+) depName=(?\\S+) packageName=(?\\S+) versioning=(?\\S+)\\s+SEMCONV_GENAI_REF=(?\\S+)" ] } ], diff --git a/dev-requirements-conformance.txt b/dev-requirements-conformance.txt index 40b4f495..3045a308 100644 --- a/dev-requirements-conformance.txt +++ b/dev-requirements-conformance.txt @@ -4,11 +4,11 @@ # # TODO: switch to PyPI versions once the test utils are released -opentelemetry-api @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-api -opentelemetry-sdk @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-sdk -opentelemetry-semantic-conventions @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-semantic-conventions -opentelemetry-test-utils @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=tests/opentelemetry-test-utils +opentelemetry-api @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=opentelemetry-api +opentelemetry-sdk @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=opentelemetry-sdk +opentelemetry-semantic-conventions @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=opentelemetry-semantic-conventions +opentelemetry-test-utils @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=tests/opentelemetry-test-utils opentelemetry-instrumentation @ git+https://github.com/open-telemetry/opentelemetry-python-contrib@d2f396de68a969dfb74b8afc247e1d0dc6739b67#subdirectory=opentelemetry-instrumentation -opentelemetry-exporter-otlp-proto-grpc @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=exporter/opentelemetry-exporter-otlp-proto-grpc -opentelemetry-exporter-otlp-proto-common @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=exporter/opentelemetry-exporter-otlp-proto-common -opentelemetry-proto @ git+https://github.com/open-telemetry/opentelemetry-python@f67bb8472eb76115ed29d433ec0798c801df57b6#subdirectory=opentelemetry-proto +opentelemetry-exporter-otlp-proto-grpc @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=exporter/opentelemetry-exporter-otlp-proto-grpc +opentelemetry-exporter-otlp-proto-common @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=exporter/opentelemetry-exporter-otlp-proto-common +opentelemetry-proto @ git+https://github.com/open-telemetry/opentelemetry-python@1731583b4e7bc6ec6a33345aa19706fc83acc8d5#subdirectory=opentelemetry-proto diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py index 625afb09..9db6dd5d 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/_setup_weaver.py @@ -3,11 +3,16 @@ """Provision advice policies and the semconv registry for weaver. -The weaver binary is installed by CI (see ``.github/workflows/test.yml``) -or locally by the contributor — this module only handles the schema / registry -side. Both ``policies_dir()`` and ``semconv_registry()`` read the -``SEMCONV_VERSION`` pin from ``versions.env`` and share one cached -semantic-conventions tarball. +The registry source is ``open-telemetry/semantic-conventions-genai``, +whose ``model/manifest.yaml`` depends on a filtered copy of the upstream +``open-telemetry/semantic-conventions`` registry with the migrated GenAI +subdirectories and groups stripped out (so Weaver doesn't see duplicate +group ids). This module reproduces the genai repo's ``make filter-upstream`` +target in Python. + +Once https://github.com/open-telemetry/weaver/issues/1455 is fixed and the +genai repo drops its ``.build/sc-upstream-filtered`` workaround, the +filter step and migration tables below become dead code. """ from __future__ import annotations @@ -15,6 +20,7 @@ import json import logging import os +import re import shutil import tarfile import tempfile @@ -23,10 +29,16 @@ from pathlib import Path from typing import Any -# Bounds the fetch of the semantic-conventions tarball so a slow/unreachable +# Bounds the fetch of the registry tarballs so a slow/unreachable # GitHub doesn't hang conformance runs until the OS-level socket timeout. _FETCH_TIMEOUT_SECONDS = 60 +# Mirrors `SC_UPSTREAM_MIGRATED_{DIRS,GROUPS}` in the genai repo's Makefile. +_MIGRATED_DIRS: tuple[str, ...] = ("gen-ai", "mcp", "openai") +_MIGRATED_GROUPS: tuple[tuple[str, str], ...] = ( + ("aws/registry.yaml", "registry.aws.bedrock"), +) + logger = logging.getLogger(__name__) @@ -43,18 +55,15 @@ def _workspace_root() -> Path: ) -def _load_version_pins() -> dict[str, str]: - content = (_workspace_root() / "versions.env").read_text(encoding="utf-8") +def _load_version_pins(path: Path) -> dict[str, str]: pins: dict[str, str] = {} - for raw_line in content.splitlines(): + for raw_line in path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#"): continue key, sep, value = line.partition("=") if not sep: - raise RuntimeError( - f"Invalid version pin in versions.env: {raw_line!r}" - ) + raise RuntimeError(f"Invalid version pin in {path}: {raw_line!r}") pins[key.strip()] = value.strip().strip('"').strip("'") return pins @@ -66,28 +75,18 @@ def _cache_dir() -> Path: return Path.home() / ".cache" / "otel-conformance" / "semconv" -def _fetch_semconv(version: str) -> Path: - """Download `semantic-conventions` at ``version`` and return the extracted root.""" - cache_root = _cache_dir() - safe = version.replace("/", "_") - target = cache_root / safe - if (target / "model").is_dir() and (target / "docs" / "gen-ai").is_dir(): - return target - - cache_root.mkdir(parents=True, exist_ok=True) - url = ( - "https://github.com/open-telemetry/semantic-conventions/" - f"archive/refs/tags/{version}.tar.gz" - ) +def _download_and_extract(url: str, target: Path, label: str) -> None: + """Download ``url`` (a .tar.gz) and extract its single top-level dir into ``target``.""" + target.parent.mkdir(parents=True, exist_ok=True) with tempfile.TemporaryDirectory( - dir=str(cache_root), prefix=f"semconv-{safe}-" + dir=str(target.parent), prefix=f"{label}-" ) as tmp: tmp_path = Path(tmp) archive_path = tmp_path / "src.tar.gz" extract_dir = tmp_path / "extract" extract_dir.mkdir() - logger.info("Fetching semantic-conventions @ %s", version) + logger.info("Fetching %s from %s", label, url) try: with ( urllib.request.urlopen( @@ -98,8 +97,7 @@ def _fetch_semconv(version: str) -> Path: shutil.copyfileobj(response, out) except (TimeoutError, urllib.error.URLError) as exc: raise RuntimeError( - f"Failed to fetch semantic-conventions @ {version} from {url}: " - f"{exc}" + f"Failed to fetch {label} from {url}: {exc}" ) from exc with tarfile.open(archive_path, "r:gz") as archive: archive.extractall(extract_dir, filter="data") @@ -107,17 +105,131 @@ def _fetch_semconv(version: str) -> Path: entries = [p for p in extract_dir.iterdir() if p.is_dir()] if len(entries) != 1: raise RuntimeError( - "Unexpected layout in semantic-conventions archive: " + f"Unexpected layout in {label} archive: " f"{[p.name for p in entries]}" ) if target.exists(): shutil.rmtree(target) shutil.move(str(entries[0]), str(target)) - return target -def _semconv_root() -> Path: - return _fetch_semconv(_load_version_pins()["SEMCONV_VERSION"]) +def _strip_group_block(text: str, group_id: str) -> str: + """Drop the YAML block for ``- id: `` from a Weaver registry file.""" + keep: list[str] = [] + skip = False + prefix = " - id: " + target_line = prefix + group_id + for line in text.splitlines(keepends=True): + if line.startswith(prefix): + skip = line.rstrip("\r\n") == target_line + if not skip: + keep.append(line) + return "".join(keep) + + +def _materialize_filtered_upstream( + genai_root: Path, upstream_root: Path +) -> Path: + """Build ``/.build/sc-upstream-filtered`` from ``upstream_root``.""" + filtered = genai_root / ".build" / "sc-upstream-filtered" + filtered.parent.mkdir(parents=True, exist_ok=True) + if filtered.exists(): + shutil.rmtree(filtered) + shutil.copytree(upstream_root / "model", filtered) + + for migrated in _MIGRATED_DIRS: + migrated_path = filtered / migrated + if migrated_path.exists(): + shutil.rmtree(migrated_path) + + for relative_file, group_id in _MIGRATED_GROUPS: + target = filtered / relative_file + if not target.is_file(): + continue + original = target.read_text(encoding="utf-8") + stripped = _strip_group_block(original, group_id) + if stripped == original: + logger.warning( + "Migrated group %r not found in %s — list may be stale", + group_id, + relative_file, + ) + target.write_text(stripped, encoding="utf-8") + return filtered + + +def _rewrite_manifest_dependency(genai_root: Path, filtered: Path) -> None: + """Bake an absolute ``registry_path`` into ``model/manifest.yaml``. + + Weaver resolves the manifest's relative ``./.build/sc-upstream-filtered`` + against the *current working directory*, not the manifest file, so a + relative path only works when weaver is invoked from the genai repo root. + """ + manifest = genai_root / "model" / "manifest.yaml" + pattern = re.compile( + r"^(\s*registry_path:\s*)\./\.build/sc-upstream-filtered\s*$", + re.MULTILINE, + ) + abs_path = filtered.resolve().as_posix() + new_text, count = pattern.subn( + lambda m: f"{m.group(1)}{abs_path}", + manifest.read_text(encoding="utf-8"), + ) + if count != 1: + raise RuntimeError( + f"Expected exactly one filtered-upstream registry_path entry in " + f"{manifest}, found {count}." + ) + manifest.write_text(new_text, encoding="utf-8") + + +def _provision_genai_root() -> Path: + """Fetch the pinned genai registry, materialize its upstream dependency, return its root.""" + pins = _load_version_pins(_workspace_root() / "versions.env") + try: + genai_ref = pins["SEMCONV_GENAI_REF"] + except KeyError as missing: + raise RuntimeError( + f"versions.env is missing required pin {missing!s}" + ) from missing + + cache_root = _cache_dir() + genai_target = cache_root / f"genai-{genai_ref}" + stamp = genai_target / ".provisioned" + if stamp.is_file(): + return genai_target + + cache_root.mkdir(parents=True, exist_ok=True) + genai_archive_url = ( + "https://github.com/open-telemetry/semantic-conventions-genai/" + f"archive/{genai_ref}.tar.gz" + ) + _download_and_extract( + genai_archive_url, genai_target, label="genai-semconv" + ) + + upstream_pins = _load_version_pins(genai_target / "versions.env") + try: + upstream_version = upstream_pins["SEMCONV_VERSION"] + except KeyError as missing: + raise RuntimeError( + f"genai repo's versions.env is missing {missing!s}" + ) from missing + + upstream_target = cache_root / f"upstream-{upstream_version}" + if not (upstream_target / "model").is_dir(): + upstream_archive_url = ( + "https://github.com/open-telemetry/semantic-conventions/" + f"archive/refs/tags/{upstream_version}.tar.gz" + ) + _download_and_extract( + upstream_archive_url, upstream_target, label="upstream-semconv" + ) + + filtered = _materialize_filtered_upstream(genai_target, upstream_target) + _rewrite_manifest_dependency(genai_target, filtered) + stamp.touch() + return genai_target # `_schema_` constants referenced from @@ -152,7 +264,7 @@ def _generate_schemas_rego(schemas: dict[str, Any]) -> str: def policies_dir() -> Path: """Write ``policies/_schemas.rego`` and return the policies directory.""" - docs_genai = _semconv_root() / "docs" / "gen-ai" + docs_genai = _provision_genai_root() / "docs" / "gen-ai" schemas: dict[str, Any] = {} for key, filename in _GENAI_SCHEMA_FILES.items(): @@ -180,5 +292,5 @@ def policies_dir() -> Path: def semconv_registry() -> Path: - """Return the path to ``/model`` for the pinned tag.""" - return _semconv_root() / "model" + """Return the path to ``/model`` for the pinned ref.""" + return _provision_genai_root() / "model" diff --git a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py index 69c81667..6ecbbc37 100644 --- a/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py +++ b/util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/fixtures.py @@ -209,5 +209,9 @@ def weaver_live_check() -> Iterator[Any]: except (OSError, RuntimeError, ValueError, tarfile.TarError) as exc: pytest.skip(f"could not provision semantic-conventions: {exc}") - with WeaverLiveCheck(registry=registry, policies_dir=policies) as weaver: + with WeaverLiveCheck( + registry=registry, + policies_dir=policies, + extra_args=["--include-unreferenced"], + ) as weaver: yield weaver diff --git a/versions.env b/versions.env index 089a4c43..d08850cd 100644 --- a/versions.env +++ b/versions.env @@ -4,5 +4,6 @@ # renovate: datasource=github-releases depName=open-telemetry/weaver versioning=semver-coerced WEAVER_VERSION=v0.23.0 -# renovate: datasource=github-releases depName=open-telemetry/semantic-conventions versioning=semver-coerced -SEMCONV_VERSION=v1.41.1 +# The genai semconv registry has no tagged releases yet, so we pin a SHA on `main`. +# renovate: datasource=git-refs depName=open-telemetry/semantic-conventions-genai packageName=https://github.com/open-telemetry/semantic-conventions-genai.git versioning=git +SEMCONV_GENAI_REF=8508fbfa5189ae50c7e95aa2fcd90c5c4998cbc7 From f636193b28e2f1e7ea9d855283ab792589b8ffc7 Mon Sep 17 00:00:00 2001 From: liudmila molkova Date: Mon, 18 May 2026 13:30:23 -0700 Subject: [PATCH 10/10] add point on temp generating cassettes with AI --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17de655e..c6b54437 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,6 +81,10 @@ package's `tests/cassettes/`. `scrub_response_headers(...)` from `opentelemetry.test_util_genai.vcr`. Diff each new cassette before committing — leaked API keys, org ids, or `Set-Cookie` values block the PR. +- **AI-generated cassettes**: if you lack provider access, you may + synthesize a cassette from the provider's API reference via AI. Make sure + to mention it in the PR and open a follow-up issue to re-record it in CI + against the real provider. - **CI**: replay-only; recording in CI is a future improvement. ### 4. Update the changelog