From 8e4861538fcf36807c1a523cbd825687cd1e2492 Mon Sep 17 00:00:00 2001 From: Nik-Reddy Date: Sun, 14 Jun 2026 02:01:24 -0700 Subject: [PATCH] Add Cohere instrumentation package scaffolding --- eachdist.ini | 1 + instrumentation/README.md | 1 + .../.changelog/.gitignore | 1 + .../.changelog/102.added | 1 + .../LICENSE | 201 ++++++++++++++ .../README.rst | 62 +++++ .../examples/manual/.env | 11 + .../examples/manual/README.rst | 38 +++ .../examples/manual/main.py | 71 +++++ .../examples/manual/requirements.txt | 5 + .../examples/zero-code/.env | 14 + .../examples/zero-code/README.rst | 45 ++++ .../examples/zero-code/main.py | 26 ++ .../examples/zero-code/requirements.txt | 6 + .../pyproject.toml | 88 +++++++ .../instrumentation/genai/cohere/__init__.py | 120 +++++++++ .../instrumentation/genai/cohere/package.py | 4 + .../instrumentation/genai/cohere/patch.py | 2 + .../instrumentation/genai/cohere/version.py | 4 + .../tests/__init__.py | 2 + .../tests/conftest.py | 39 +++ .../tests/requirements.latest.txt | 45 ++++ .../tests/requirements.oldest.txt | 26 ++ .../tests/test_instrumentor.py | 107 ++++++++ ...ini-2.5-flash-enable_completion_hook].yaml | 102 ++++++++ ...ini-2.5-flash-enable_completion_hook].yaml | 102 ++++++++ ...ini-2.5-flash-enable_completion_hook].yaml | 102 ++++++++ ...ini-2.5-flash-enable_completion_hook].yaml | 102 ++++++++ pyproject.toml | 5 + tox.ini | 15 ++ uv.lock | 246 ++++++++++++++++++ 31 files changed, 1594 insertions(+) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/.gitignore create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/102.added create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/LICENSE create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/.env create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/main.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/requirements.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/.env create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/main.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/requirements.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/pyproject.toml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/package.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/patch.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/version.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/tests/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/tests/conftest.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.latest.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.oldest.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-cohere/tests/test_instrumentor.py create mode 100644 instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml create mode 100644 instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml create mode 100644 instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml create mode 100644 instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml diff --git a/eachdist.ini b/eachdist.ini index 7bdb949b..65a7ceba 100644 --- a/eachdist.ini +++ b/eachdist.ini @@ -17,6 +17,7 @@ packages= packages= opentelemetry-instrumentation-genai-anthropic opentelemetry-instrumentation-genai-claude-agent-sdk + opentelemetry-instrumentation-genai-cohere opentelemetry-instrumentation-google-genai opentelemetry-instrumentation-genai-langchain opentelemetry-instrumentation-genai-openai diff --git a/instrumentation/README.md b/instrumentation/README.md index 48ee952f..61981d9c 100644 --- a/instrumentation/README.md +++ b/instrumentation/README.md @@ -3,6 +3,7 @@ | --------------- | ------------------ | --------------- | -------------- | | [opentelemetry-instrumentation-genai-anthropic](./opentelemetry-instrumentation-genai-anthropic) | anthropic >= 0.16.0 | No | development | [opentelemetry-instrumentation-genai-claude-agent-sdk](./opentelemetry-instrumentation-genai-claude-agent-sdk) | claude-agent-sdk >= 0.1.14 | No | development +| [opentelemetry-instrumentation-genai-cohere](./opentelemetry-instrumentation-genai-cohere) | cohere >= 5.13.0 | No | development | [opentelemetry-instrumentation-genai-langchain](./opentelemetry-instrumentation-genai-langchain) | langchain >= 0.3.21 | No | development | [opentelemetry-instrumentation-genai-openai](./opentelemetry-instrumentation-genai-openai) | openai >= 1.26.0 | Yes | development | [opentelemetry-instrumentation-genai-openai-agents](./opentelemetry-instrumentation-genai-openai-agents) | openai-agents >= 0.3.3 | No | development diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/.gitignore b/instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/.gitignore new file mode 100644 index 00000000..f935021a --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/102.added b/instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/102.added new file mode 100644 index 00000000..cc499d0b --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/.changelog/102.added @@ -0,0 +1 @@ +Add Cohere instrumentation package scaffolding diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/LICENSE b/instrumentation/opentelemetry-instrumentation-genai-cohere/LICENSE new file mode 100644 index 00000000..4f0c128f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Support. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright The OpenTelemetry Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/README.rst b/instrumentation/opentelemetry-instrumentation-genai-cohere/README.rst new file mode 100644 index 00000000..1a96c0e9 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/README.rst @@ -0,0 +1,62 @@ +OpenTelemetry Cohere Instrumentation +==================================== + +This library allows tracing LLM requests made by the +`Cohere Python SDK `_. + +Installation +------------ + +:: + + pip install opentelemetry-instrumentation-genai-cohere + +If you don't have a Cohere application yet, try our `examples `_ +which only need a valid Cohere API key. + +Check out the `zero-code example `_ for a quick start. + +Usage +----- + +This section describes how to set up Cohere instrumentation if you're setting OpenTelemetry up manually. +Check out the `manual example `_ for more details. + +.. code-block:: python + + from opentelemetry.instrumentation.genai.cohere import CohereInstrumentor + import cohere + + # Instrument Cohere + CohereInstrumentor().instrument() + + # Use the Cohere V2 client as normal + co = cohere.ClientV2() + response = co.chat( + model="command-r-plus-08-2024", + messages=[{"role": "user", "content": "hello world!"}], + ) + print(response) + + +Configuration +------------- + +Capture Message Content +*********************** + +By default, prompts and completions are not captured. To enable message content capture, +set the environment variable: + +:: + + export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true + + +References +---------- + +* `OpenTelemetry Project `_ +* `OpenTelemetry GenAI semantic conventions `_ +* `Cohere Python SDK `_ +* `Cohere Documentation `_ diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/.env b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/.env new file mode 100644 index 00000000..ababe00f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/.env @@ -0,0 +1,11 @@ +# Update this with your real Cohere API key +CO_API_KEY=YOUR_COHERE_API_KEY + +# Uncomment and change to your OTLP endpoint +# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +# OTEL_EXPORTER_OTLP_PROTOCOL=grpc + +OTEL_SERVICE_NAME=opentelemetry-python-cohere + +# Change to 'false' to hide prompt and completion content +OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/README.rst b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/README.rst new file mode 100644 index 00000000..a78d3c29 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/README.rst @@ -0,0 +1,38 @@ +OpenTelemetry Cohere Instrumentation Example +============================================ + +This is a placeholder for an example showing how to instrument Cohere +calls when configuring OpenTelemetry SDK and Instrumentations manually. + +The ``CohereInstrumentor`` shipped in this release is scaffold-only: +calling ``.instrument()`` sets up tracer, logger, and meter providers +but does not yet wrap any Cohere client methods. Chat completions and +streaming wrapping land in a follow-up PR. + +Setup +----- + +Minimally, update the `.env <.env>`_ file with your ``CO_API_KEY``. An +OTLP compatible endpoint should be listening for traces and logs on +http://localhost:4317. If not, update ``OTEL_EXPORTER_OTLP_ENDPOINT`` as well. + +Next, set up a virtual environment like this: + +:: + + python3 -m venv .venv + source .venv/bin/activate + pip install "python-dotenv[cli]" + pip install -r requirements.txt + +Run +--- + +Run the example like this: + +:: + + dotenv run -- python main.py + +Once the follow-up PR lands, you will see Cohere chat completions +exported as spans and logs to your configured observability tool. diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/main.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/main.py new file mode 100644 index 00000000..e0c38449 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/main.py @@ -0,0 +1,71 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# pylint: skip-file +"""Placeholder example for Cohere instrumentation with manual OpenTelemetry setup. + +The CohereInstrumentor shipped in this release is scaffold-only; it does +not yet wrap any client methods. Chat completions wrapping lands in a +follow-up PR. This file shows the planned wiring shape so the example +directory mirrors other instrumentation packages. +""" + +import cohere + +# NOTE: OpenTelemetry Python Logs and Events APIs are in beta +from opentelemetry import _logs, metrics, trace +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.instrumentation.genai.cohere import CohereInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk._logs.export import BatchLogRecordProcessor +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 BatchSpanProcessor + +# configure tracing +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( + BatchSpanProcessor(OTLPSpanExporter()) +) + +# configure logging and events +_logs.set_logger_provider(LoggerProvider()) +_logs.get_logger_provider().add_log_record_processor( + BatchLogRecordProcessor(OTLPLogExporter()) +) + +# configure metrics +metrics.set_meter_provider( + MeterProvider( + metric_readers=[ + PeriodicExportingMetricReader( + OTLPMetricExporter(), + ), + ] + ) +) + +# instrument Cohere (no-op until the chat completions wrapping PR lands) +CohereInstrumentor().instrument() + + +def main() -> None: + co = cohere.ClientV2() + response = co.chat( + model="command-r-plus-08-2024", + messages=[{"role": "user", "content": "hello world!"}], + ) + print(response) + + +if __name__ == "__main__": + main() diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/requirements.txt b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/requirements.txt new file mode 100644 index 00000000..61022161 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/manual/requirements.txt @@ -0,0 +1,5 @@ +cohere>=5.13.0 + +opentelemetry-sdk~=1.42.0 +opentelemetry-exporter-otlp-proto-grpc~=1.42.0 +opentelemetry-instrumentation-genai-cohere diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/.env b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/.env new file mode 100644 index 00000000..0911767e --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/.env @@ -0,0 +1,14 @@ +# Update this with your real Cohere API key +CO_API_KEY=YOUR_COHERE_API_KEY + +# Uncomment and change to your OTLP endpoint +# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +# OTEL_EXPORTER_OTLP_PROTOCOL=grpc + +OTEL_SERVICE_NAME=opentelemetry-python-cohere + +# Uncomment if your OTLP endpoint doesn't support logs +# OTEL_LOGS_EXPORTER=console + +# Change to 'false' to hide prompt and completion content +OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/README.rst b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/README.rst new file mode 100644 index 00000000..09d64196 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/README.rst @@ -0,0 +1,45 @@ +OpenTelemetry Cohere Zero-Code Instrumentation Example +====================================================== + +This is a placeholder for an example showing how to instrument Cohere +calls with zero code changes, using ``opentelemetry-instrument``. + +The ``CohereInstrumentor`` shipped in this release is scaffold-only: +the entry point is registered under ``opentelemetry_instrumentor`` so +``opentelemetry-instrument`` discovers it, but no Cohere client methods +are wrapped yet. Chat completions wrapping lands in a follow-up PR. + +Setup +----- + +Minimally, update the `.env <.env>`_ file with your ``CO_API_KEY``. An +OTLP compatible endpoint should be listening for traces and logs on +http://localhost:4317. If not, update ``OTEL_EXPORTER_OTLP_ENDPOINT`` as well. + +Next, set up a virtual environment like this: + +:: + + python3 -m venv .venv + source .venv/bin/activate + pip install "python-dotenv[cli]" + pip install -r requirements.txt + +Run +--- + +Run the example with zero-code instrumentation like this: + +:: + + dotenv run -- opentelemetry-instrument python main.py + +Once the follow-up PR lands, you will see Cohere chat completions +exported as spans and logs without any changes to ``main.py``. + +Learn More +---------- + +See the `OpenTelemetry Python automatic instrumentation docs +`_ for more +information about zero-code instrumentation. diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/main.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/main.py new file mode 100644 index 00000000..70d9090b --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/main.py @@ -0,0 +1,26 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# pylint: skip-file +"""Placeholder example for Cohere instrumentation via opentelemetry-instrument. + +The CohereInstrumentor shipped in this release is scaffold-only; it does +not yet wrap any client methods. Chat completions wrapping lands in a +follow-up PR. This file shows the planned client surface so the example +directory mirrors other instrumentation packages. +""" + +import cohere + + +def main() -> None: + co = cohere.ClientV2() + response = co.chat( + model="command-r-plus-08-2024", + messages=[{"role": "user", "content": "hello world!"}], + ) + print(response) + + +if __name__ == "__main__": + main() diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/requirements.txt b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/requirements.txt new file mode 100644 index 00000000..440fd909 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/examples/zero-code/requirements.txt @@ -0,0 +1,6 @@ +cohere>=5.13.0 + +opentelemetry-sdk~=1.42.0 +opentelemetry-exporter-otlp-proto-grpc~=1.42.0 +opentelemetry-distro~=0.57b0 +opentelemetry-instrumentation-genai-cohere diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/pyproject.toml b/instrumentation/opentelemetry-instrumentation-genai-cohere/pyproject.toml new file mode 100644 index 00000000..5d70ae9f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/pyproject.toml @@ -0,0 +1,88 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "opentelemetry-instrumentation-genai-cohere" +dynamic = ["version"] +description = "OpenTelemetry Cohere instrumentation" +readme = "README.rst" +license = "Apache-2.0" +requires-python = ">=3.10" +authors = [ + { name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] +dependencies = [ + "opentelemetry-api ~= 1.40", + "opentelemetry-instrumentation ~= 0.61b0", + "opentelemetry-semantic-conventions ~= 0.61b0", + "opentelemetry-util-genai >= 1.0b0.dev", +] + +[project.optional-dependencies] +instruments = ["cohere >= 5.13.0"] + +[project.entry-points.opentelemetry_instrumentor] +cohere = "opentelemetry.instrumentation.genai.cohere:CohereInstrumentor" + +[project.urls] +Homepage = "https://github.com/open-telemetry/opentelemetry-python-genai/tree/main/instrumentation/opentelemetry-instrumentation-genai-cohere" +Repository = "https://github.com/open-telemetry/opentelemetry-python-genai" + +[tool.hatch.version] +path = "src/opentelemetry/instrumentation/genai/cohere/version.py" + +[tool.hatch.build.targets.sdist] +include = ["/src", "/tests", "/examples"] + +[tool.hatch.build.targets.wheel] +packages = ["src/opentelemetry"] + +[tool.pytest.ini_options] +testpaths = ["tests"] + +[tool.towncrier] +directory = ".changelog" +filename = "CHANGELOG.md" +start_string = "\n" +template = "../../scripts/changelog_template.j2" +issue_format = "[#{issue}](https://github.com/open-telemetry/opentelemetry-python-genai/pull/{issue})" +wrap = true +issue_pattern = "^(\\d+)" + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/__init__.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/__init__.py new file mode 100644 index 00000000..dd35873c --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/__init__.py @@ -0,0 +1,120 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +""" +OpenTelemetry Cohere Instrumentation +==================================== + +Instrumentation for the `Cohere Python SDK +`_. + +Usage +----- + +.. code-block:: python + + from opentelemetry.instrumentation.genai.cohere import CohereInstrumentor + import cohere + + # Enable instrumentation + CohereInstrumentor().instrument() + + # Use the Cohere V2 client normally + co = cohere.ClientV2() + response = co.chat( + model="command-r-plus-08-2024", + messages=[{"role": "user", "content": "hello world!"}], + ) + print(response) + +Configuration +------------- + +Message content capture can be enabled by setting the environment variable: +``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true`` + +API +--- +""" + +from typing import Any, Collection + +from opentelemetry._logs import get_logger +from opentelemetry.instrumentation.genai.cohere.package import ( + _instruments, +) +from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.metrics import get_meter +from opentelemetry.semconv.schemas import Schemas +from opentelemetry.trace import get_tracer + + +class CohereInstrumentor(BaseInstrumentor): + """An instrumentor for the Cohere Python SDK. + + This instrumentor will automatically trace Cohere API calls and + optionally capture message content as events. + """ + + def __init__(self) -> None: + super().__init__() + self._tracer = None + self._logger = None + self._meter = None + + # pylint: disable=no-self-use + def instrumentation_dependencies(self) -> Collection[str]: + return _instruments + + def _instrument(self, **kwargs: Any) -> None: + """Enable Cohere instrumentation. + + Args: + **kwargs: Optional arguments + - tracer_provider: TracerProvider instance + - meter_provider: MeterProvider instance + - logger_provider: LoggerProvider instance + """ + + # Get providers from kwargs + tracer_provider = kwargs.get("tracer_provider") + logger_provider = kwargs.get("logger_provider") + meter_provider = kwargs.get("meter_provider") + + # Initialize tracer + tracer = get_tracer( + __name__, + "", + tracer_provider, + schema_url=Schemas.V1_28_0.value, + ) + + # Initialize logger for events + logger = get_logger( + __name__, + "", + schema_url=Schemas.V1_28_0.value, + logger_provider=logger_provider, + ) + + # Initialize meter for metrics + meter = get_meter( + __name__, + "", + meter_provider, + schema_url=Schemas.V1_28_0.value, + ) + + # Store for later use in _uninstrument + self._tracer = tracer + self._logger = logger + self._meter = meter + + # Patching will be added in a follow-up PR + + def _uninstrument(self, **kwargs: Any) -> None: + """Disable Cohere instrumentation. + + This removes all patches applied during instrumentation. + """ + # Unpatching will be added in a follow-up PR diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/package.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/package.py new file mode 100644 index 00000000..30db8937 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/package.py @@ -0,0 +1,4 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +_instruments = ("cohere >= 5.13.0",) diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/patch.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/patch.py new file mode 100644 index 00000000..e57cf4ab --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/patch.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/version.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/version.py new file mode 100644 index 00000000..cefb388f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/src/opentelemetry/instrumentation/genai/cohere/version.py @@ -0,0 +1,4 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +__version__ = "1.0b0.dev" diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/__init__.py new file mode 100644 index 00000000..e57cf4ab --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/__init__.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/conftest.py new file mode 100644 index 00000000..923a24a3 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/conftest.py @@ -0,0 +1,39 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Test configuration and fixtures for Cohere instrumentation tests.""" +# pylint: disable=redefined-outer-name + +import pytest + +pytest_plugins = ["opentelemetry.test_util_genai.fixtures"] + + +@pytest.fixture +def instrument_cohere(tracer_provider, logger_provider, meter_provider): + """Fixture to instrument Cohere with test providers.""" + # pylint: disable=import-outside-toplevel + from opentelemetry.instrumentation.genai.cohere import ( # noqa: PLC0415 + CohereInstrumentor, + ) + + instrumentor = CohereInstrumentor() + instrumentor.instrument( + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + ) + yield instrumentor + instrumentor.uninstrument() + + +@pytest.fixture +def uninstrument_cohere(): + """Fixture to ensure Cohere is uninstrumented after test.""" + yield + # pylint: disable=import-outside-toplevel + from opentelemetry.instrumentation.genai.cohere import ( # noqa: PLC0415 + CohereInstrumentor, + ) + + CohereInstrumentor().uninstrument() diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.latest.txt b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.latest.txt new file mode 100644 index 00000000..6aa80ebe --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.latest.txt @@ -0,0 +1,45 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# ******************************** +# WARNING: NOT HERMETIC !!!!!!!!!! +# ******************************** +# +# This "requirements.txt" is installed in conjunction +# with multiple other dependencies in the top-level "tox.ini" +# file. In particular, please see: +# +# cohere-latest: {[testenv]test_deps} +# cohere-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.latest.txt +# +# This provides additional dependencies, namely: +# +# opentelemetry-api +# opentelemetry-sdk +# opentelemetry-semantic-conventions +# opentelemetry-instrumentation +# +# ... with a "dev" version based on the latest distribution. +# +# +# This variant of the requirements aims to test the system using +# the newest supported version of external dependencies. + +cohere +wrapt==2.2.1 +# test with the latest version of opentelemetry-api, sdk, semantic conventions, and instrumentation + +-e util/opentelemetry-util-genai +-e instrumentation/opentelemetry-instrumentation-genai-cohere diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.oldest.txt b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.oldest.txt new file mode 100644 index 00000000..4a648d01 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.oldest.txt @@ -0,0 +1,26 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This variant of the requirements aims to test the system using +# the oldest supported version of external dependencies. + +cohere==5.13.0 +wrapt==1.16.0 +opentelemetry-api==1.40 # when updating, also update in pyproject.toml +opentelemetry-sdk==1.40 # when updating, also update in pyproject.toml +opentelemetry-semantic-conventions==0.61b0 # when updating, also update in pyproject.toml +opentelemetry-instrumentation==0.61b0 # when updating, also update in pyproject.toml + +-e util/opentelemetry-util-genai # TODO update to 1.0b0 when released +-e instrumentation/opentelemetry-instrumentation-genai-cohere diff --git a/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/test_instrumentor.py b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/test_instrumentor.py new file mode 100644 index 00000000..e645dfb9 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/test_instrumentor.py @@ -0,0 +1,107 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Tests for the CohereInstrumentor class.""" + +from opentelemetry.instrumentation.genai.cohere import ( + CohereInstrumentor, +) + + +def test_instrumentor_instantiation(): + """Test that the instrumentor can be instantiated.""" + instrumentor = CohereInstrumentor() + assert instrumentor is not None + assert isinstance(instrumentor, CohereInstrumentor) + + +def test_instrumentation_dependencies(): + """Test that instrumentation dependencies are correctly reported.""" + instrumentor = CohereInstrumentor() + dependencies = instrumentor.instrumentation_dependencies() + + assert dependencies is not None + assert len(dependencies) > 0 + assert "cohere >= 5.13.0" in dependencies + + +def test_instrument_uninstrument_cycle( + tracer_provider, logger_provider, meter_provider +): + """Test that instrument() and uninstrument() can be called multiple times.""" + instrumentor = CohereInstrumentor() + + # First instrumentation + instrumentor.instrument( + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + ) + + # First uninstrumentation + instrumentor.uninstrument() + + # Second instrumentation (should work) + instrumentor.instrument( + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + ) + + # Second uninstrumentation + instrumentor.uninstrument() + + +def test_multiple_instrumentation_calls( + tracer_provider, logger_provider, meter_provider +): + """Test that multiple instrument() calls don't cause issues.""" + instrumentor = CohereInstrumentor() + + # First call + instrumentor.instrument( + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + ) + + # Second call (should be idempotent or handle gracefully) + instrumentor.instrument( + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + ) + + # Clean up + instrumentor.uninstrument() + + +def test_uninstrument_without_instrument(): + """Test that uninstrument() can be called without prior instrument().""" + instrumentor = CohereInstrumentor() + + # This should not raise an error + instrumentor.uninstrument() + + +def test_instrument_with_no_providers(): + """Test that instrument() works without explicit providers.""" + instrumentor = CohereInstrumentor() + + # Should use global providers + instrumentor.instrument() + + # Clean up + instrumentor.uninstrument() + + +def test_instrumentor_has_required_attributes(): + """Test that the instrumentor has the required methods.""" + instrumentor = CohereInstrumentor() + + assert hasattr(instrumentor, "instrument") + assert hasattr(instrumentor, "uninstrument") + assert hasattr(instrumentor, "instrumentation_dependencies") + assert callable(instrumentor.instrument) + assert callable(instrumentor.uninstrument) + assert callable(instrumentor.instrumentation_dependencies) diff --git a/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml new file mode 100644 index 00000000..60077ccb --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml @@ -0,0 +1,102 @@ +interactions: +- request: + body: |- + { + "contents": [ + { + "parts": [ + { + "text": "Create a haiku about Open Telemetry." + } + ], + "role": "user" + } + ] + } + headers: + accept: + - '*/*' + accept-encoding: + - identity + connection: + - keep-alive + content-length: + - '93' + content-type: + - application/json + host: + - us-central1-aiplatform.googleapis.com + user-agent: + - google-genai-sdk/1.32.0 gl-python/3.10.18 + x-goog-api-client: + - + x-goog-user-project: + - + method: POST + uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-2.5-flash:generateContent + response: + body: + string: |- + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [ + { + "text": "Open data streams,\nMetrics, logs, and traces flow,\nClearly see inside." + } + ] + }, + "finishReason": "STOP", + "avgLogprobs": -5.934557172987196 + } + ], + "usageMetadata": { + "promptTokenCount": 8, + "candidatesTokenCount": 18, + "totalTokenCount": 459, + "trafficType": "ON_DEMAND", + "promptTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 8 + } + ], + "candidatesTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 18 + } + ], + "thoughtsTokenCount": 433 + }, + "modelVersion": "gemini-2.5-flash", + "createTime": "2025-10-10T16:32:45.350496Z", + "responseId": "LTXpaKCyFdPlnvgPuajSiQQ" + } + headers: + Accept-Ranges: + - none + Content-Type: + - application/json; charset=UTF-8 + Date: + - Fri, 10 Oct 2025 16:32:59 GMT + Server: + - scaffolding on HTTPServer2 + Transfer-Encoding: + - chunked + Vary: + - X-Origin + - Referer + - Origin,Accept-Encoding + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml new file mode 100644 index 00000000..53b23d81 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[NO_CONTENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml @@ -0,0 +1,102 @@ +interactions: +- request: + body: |- + { + "contents": [ + { + "parts": [ + { + "text": "Create a haiku about Open Telemetry." + } + ], + "role": "user" + } + ] + } + headers: + accept: + - '*/*' + accept-encoding: + - identity + connection: + - keep-alive + content-length: + - '93' + content-type: + - application/json + host: + - us-central1-aiplatform.googleapis.com + user-agent: + - google-genai-sdk/1.32.0 gl-python/3.10.18 + x-goog-api-client: + - + x-goog-user-project: + - + method: POST + uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-2.5-flash:generateContent + response: + body: + string: |- + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [ + { + "text": "Open data streams,\nMetrics, logs, and traces flow,\nClearly see inside." + } + ] + }, + "finishReason": "STOP", + "avgLogprobs": -28.687652587890625 + } + ], + "usageMetadata": { + "promptTokenCount": 8, + "candidatesTokenCount": 20, + "totalTokenCount": 1341, + "trafficType": "ON_DEMAND", + "promptTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 8 + } + ], + "candidatesTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 20 + } + ], + "thoughtsTokenCount": 1313 + }, + "modelVersion": "gemini-2.5-flash", + "createTime": "2025-10-10T16:32:34.499409Z", + "responseId": "IjXpaNG9HoC4nvgPk77D6Ak" + } + headers: + Accept-Ranges: + - none + Content-Type: + - application/json; charset=UTF-8 + Date: + - Fri, 10 Oct 2025 16:32:42 GMT + Server: + - scaffolding on HTTPServer2 + Transfer-Encoding: + - chunked + Vary: + - X-Origin + - Referer + - Origin,Accept-Encoding + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml new file mode 100644 index 00000000..31af6679 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-async-gemini-2.5-flash-enable_completion_hook].yaml @@ -0,0 +1,102 @@ +interactions: +- request: + body: |- + { + "contents": [ + { + "parts": [ + { + "text": "Create a haiku about Open Telemetry." + } + ], + "role": "user" + } + ] + } + headers: + accept: + - '*/*' + accept-encoding: + - identity + connection: + - keep-alive + content-length: + - '93' + content-type: + - application/json + host: + - us-central1-aiplatform.googleapis.com + user-agent: + - google-genai-sdk/1.32.0 gl-python/3.10.18 + x-goog-api-client: + - + x-goog-user-project: + - + method: POST + uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-2.5-flash:generateContent + response: + body: + string: |- + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [ + { + "text": "Open data streams,\nMetrics, logs, and traces flow,\nClearly see inside." + } + ] + }, + "finishReason": "STOP", + "avgLogprobs": -6.327557373046875 + } + ], + "usageMetadata": { + "promptTokenCount": 8, + "candidatesTokenCount": 20, + "totalTokenCount": 475, + "trafficType": "ON_DEMAND", + "promptTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 8 + } + ], + "candidatesTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 20 + } + ], + "thoughtsTokenCount": 447 + }, + "modelVersion": "gemini-2.5-flash", + "createTime": "2025-10-10T16:32:28.805463Z", + "responseId": "HDXpaNeUMaeBnvgPiJ6P-Ao" + } + headers: + Accept-Ranges: + - none + Content-Type: + - application/json; charset=UTF-8 + Date: + - Fri, 10 Oct 2025 16:32:31 GMT + Server: + - scaffolding on HTTPServer2 + Transfer-Encoding: + - chunked + Vary: + - X-Origin + - Referer + - Origin,Accept-Encoding + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml new file mode 100644 index 00000000..1c0a0275 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-google-genai/tests/generate_content/cassettes/test_upload_hook_non_streaming[SPAN_AND_EVENT-vertexaiapi-sync-gemini-2.5-flash-enable_completion_hook].yaml @@ -0,0 +1,102 @@ +interactions: +- request: + body: |- + { + "contents": [ + { + "parts": [ + { + "text": "Create a haiku about Open Telemetry." + } + ], + "role": "user" + } + ] + } + headers: + accept: + - '*/*' + accept-encoding: + - identity + connection: + - keep-alive + content-length: + - '93' + content-type: + - application/json + host: + - us-central1-aiplatform.googleapis.com + user-agent: + - google-genai-sdk/1.32.0 gl-python/3.10.18 + x-goog-api-client: + - + x-goog-user-project: + - + method: POST + uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-2.5-flash:generateContent + response: + body: + string: |- + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [ + { + "text": "Open data streams,\nMetrics, logs, and traces flow,\nClearly see inside." + } + ] + }, + "finishReason": "STOP", + "avgLogprobs": -10.948673672146267 + } + ], + "usageMetadata": { + "promptTokenCount": 8, + "candidatesTokenCount": 18, + "totalTokenCount": 663, + "trafficType": "ON_DEMAND", + "promptTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 8 + } + ], + "candidatesTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 18 + } + ], + "thoughtsTokenCount": 637 + }, + "modelVersion": "gemini-2.5-flash", + "createTime": "2025-10-10T16:32:22.100847Z", + "responseId": "FjXpaO-TBoC4nvgPk77D6Ak" + } + headers: + Accept-Ranges: + - none + Content-Type: + - application/json; charset=UTF-8 + Date: + - Fri, 10 Oct 2025 16:32:25 GMT + Server: + - scaffolding on HTTPServer2 + Transfer-Encoding: + - chunked + Vary: + - X-Origin + - Referer + - Origin,Accept-Encoding + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/pyproject.toml b/pyproject.toml index 537181ee..67397b24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ "opentelemetry-util-genai", "opentelemetry-instrumentation-genai-anthropic[instruments]", "opentelemetry-instrumentation-genai-claude-agent-sdk[instruments]", + "opentelemetry-instrumentation-genai-cohere[instruments]", "opentelemetry-instrumentation-google-genai[instruments]", "opentelemetry-instrumentation-genai-langchain[instruments]", "opentelemetry-instrumentation-genai-openai[instruments]", @@ -32,6 +33,7 @@ opentelemetry-test-util-genai = { workspace = true } opentelemetry-util-genai = { workspace = true } opentelemetry-instrumentation-genai-anthropic = { workspace = true } opentelemetry-instrumentation-genai-claude-agent-sdk = { workspace = true } +opentelemetry-instrumentation-genai-cohere = { workspace = true } opentelemetry-instrumentation-google-genai = { workspace = true } opentelemetry-instrumentation-genai-langchain = { workspace = true } opentelemetry-instrumentation-genai-openai = { workspace = true } @@ -95,6 +97,7 @@ reportPrivateUsage = false # Ignore private attributes added by instrumentation include = [ "instrumentation/opentelemetry-instrumentation-genai-anthropic", "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk", + "instrumentation/opentelemetry-instrumentation-genai-cohere", "instrumentation/opentelemetry-instrumentation-genai-langchain", "instrumentation/opentelemetry-instrumentation-genai-weaviate-client", "util/opentelemetry-util-genai", @@ -106,6 +109,8 @@ exclude = [ "instrumentation/opentelemetry-instrumentation-genai-anthropic/examples/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/examples/**/*.py", + "instrumentation/opentelemetry-instrumentation-genai-cohere/tests/**/*.py", + "instrumentation/opentelemetry-instrumentation-genai-cohere/examples/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-langchain/tests/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-langchain/examples/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-weaviate-client/tests/**/*.py", diff --git a/tox.ini b/tox.ini index 6f1a4db9..f34c7bb4 100644 --- a/tox.ini +++ b/tox.ini @@ -35,6 +35,10 @@ envlist = # Disabling pypy3 as jiter (anthropic dep) requires PyPy 3.11+ lint-instrumentation-genai-claude-agent-sdk + ; instrumentation-genai-cohere + py3{10,11,12,13,14}-test-instrumentation-genai-cohere-{oldest,latest} + lint-instrumentation-genai-cohere + ; instrumentation-genai-langchain ; TODO: split into oldest/latest once a version matrix is defined. py3{12,13}-test-instrumentation-genai-langchain @@ -120,6 +124,13 @@ deps = claude-agent-sdk-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests/requirements.latest.txt lint-instrumentation-genai-claude-agent-sdk: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests/requirements.oldest.txt + cohere-oldest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.oldest.txt + cohere-oldest: {[testenv]pytest_deps} + cohere-latest: {[testenv]test_deps} + cohere-latest: {[testenv]pytest_deps} + cohere-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.latest.txt + lint-instrumentation-genai-cohere: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-cohere/tests/requirements.oldest.txt + ; Langchain unit tests: single pinned requirements until oldest/latest is defined. langchain: {[testenv]test_deps} langchain: {[testenv]pytest_deps} @@ -169,6 +180,9 @@ commands = test-instrumentation-genai-claude-agent-sdk: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests --vcr-record=none {posargs} lint-instrumentation-genai-claude-agent-sdk: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-claude-agent-sdk" + test-instrumentation-genai-cohere-{oldest,latest}: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-cohere/tests --vcr-record=none {posargs} + lint-instrumentation-genai-cohere: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-cohere" + test-instrumentation-genai-langchain: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-langchain/tests --vcr-record=none {posargs} test-instrumentation-genai-langchain-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_conformance.py --vcr-record=none {posargs} lint-instrumentation-genai-langchain: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-langchain" @@ -251,6 +265,7 @@ deps = {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-anthropic[instruments] {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk[instruments] + {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-cohere[instruments] {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-weaviate-client[instruments] commands = diff --git a/uv.lock b/uv.lock index 69d7da58..fd3ca0f8 100644 --- a/uv.lock +++ b/uv.lock @@ -10,6 +10,7 @@ resolution-markers = [ members = [ "opentelemetry-instrumentation-genai-anthropic", "opentelemetry-instrumentation-genai-claude-agent-sdk", + "opentelemetry-instrumentation-genai-cohere", "opentelemetry-instrumentation-genai-langchain", "opentelemetry-instrumentation-genai-openai", "opentelemetry-instrumentation-genai-openai-agents", @@ -20,6 +21,15 @@ members = [ "opentelemetry-util-genai", ] +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple/" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -341,6 +351,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" }, ] +[[package]] +name = "cohere" +version = "7.0.2" +source = { registry = "https://pypi.org/simple/" } +dependencies = [ + { name = "fastavro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "pydantic-core" }, + { name = "requests" }, + { name = "tokenizers" }, + { name = "types-requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/18/37fe97d764acc9e7c9c51e77797e8cb9b12074d5d30988e4dda21f0256cd/cohere-7.0.2.tar.gz", hash = "sha256:18961c06b717d102ac4dde4d12a3664f55af9714a311bd3de55f30f815ec94ee", size = 208688, upload-time = "2026-05-29T13:59:26Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/43/96f0ebf59605227cb02a577b77870c0f9ef9b5464e29af91dad27f5933a8/cohere-7.0.2-py3-none-any.whl", hash = "sha256:4b07b191e9a89d5a942a10246c11b7c22e7e81a356d1220e768e259568f1495b", size = 351937, upload-time = "2026-05-29T13:59:24.512Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -449,6 +478,58 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] +[[package]] +name = "fastavro" +version = "1.12.2" +source = { registry = "https://pypi.org/simple/" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/5b/ccb338db71f347e3bc031d268bf6dc41e5ead63b6997b8e72af92f05e18e/fastavro-1.12.2.tar.gz", hash = "sha256:3c79502d56cf6b76210032e1c53494ddfbc73c140bccf2ef4092b3f0825323ab", size = 1030127, upload-time = "2026-04-24T14:36:01.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/91/16c3508447e7cf9f413a6a01792a990ed94d17505fc80a7fb76027078aed/fastavro-1.12.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7c6d26c731a0e1e8e7d4ae8f13ae524eb6ec0e90d99c8147a19fdbae14eb807", size = 976824, upload-time = "2026-04-24T14:36:04.233Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3a/97534561a1b4615366345ac066ad1f54698a59aa510eece3153c3a603d29/fastavro-1.12.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7caeecf519eff50f007ca4bee16b6e0a8252e5fe682c94432192a20867239888", size = 3185186, upload-time = "2026-04-24T14:36:06.395Z" }, + { url = "https://files.pythonhosted.org/packages/ee/e4/26512b52f58305b9d2194169de2e82c16d5131f0a0b6359e50d34faf4021/fastavro-1.12.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:731aefe6c4bf2bafa0798ef83927676d06e44d1d18202cfb56d63b40422ab900", size = 3196799, upload-time = "2026-04-24T14:36:09.028Z" }, + { url = "https://files.pythonhosted.org/packages/58/69/22f3b29a4555eb805a26f209f12532df8aafa48685d1cd1879aa42758d04/fastavro-1.12.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f089f24225a28ddafa5cfad7c41cfa84db1a55f2d473370769a95c0e3bac60c9", size = 3112396, upload-time = "2026-04-24T14:36:11.401Z" }, + { url = "https://files.pythonhosted.org/packages/e9/2a/fc61ef522050e1079ccf1aee07192881f3b11129f5e2b76811fd4fc3bb2f/fastavro-1.12.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:653c4f90dd21d8a1e74309919e08934e420d9aef51d051d14bf5a1c0e8293c22", size = 3180452, upload-time = "2026-04-24T14:36:13.634Z" }, + { url = "https://files.pythonhosted.org/packages/a6/6a/43ce9d713e9f1122e19c80d94d0dc0a356b8562d33eea90081dac781dd97/fastavro-1.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:030f17eb4c7978538a31b55dea451ceace851a88dc9816b1923f8fb8a260db4c", size = 445396, upload-time = "2026-04-24T14:36:15.243Z" }, + { url = "https://files.pythonhosted.org/packages/89/77/058f3c93348624cb695399b27f3f0c1c3d1190586065797e4a48f75d4147/fastavro-1.12.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d48cd7094598a7e9d4297e8bf4bbe0dc9dc2ba4367d83dbb603e3b3c6aa35566", size = 974559, upload-time = "2026-04-24T14:36:17.172Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ef/08bbfa643addd2b98a9ce536613e2098928aa5e3ca098fd5b74f3c03b96a/fastavro-1.12.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:070c6134604bd7b6fd44409406ac50445339682b2e872885db2e859f92d22e93", size = 3352777, upload-time = "2026-04-24T14:36:19.679Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ec/55c11108529bdb59e635899f737651f729485ea5af36e128fb6560969c3d/fastavro-1.12.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b73d50978d5e57416fa68461f9f3c8f39ea39e761cb1e12f919745adefe26a7", size = 3387036, upload-time = "2026-04-24T14:36:21.794Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b3/4459f7c61804e9b42b49f02fba8fbbb041af76c7cab43cee4018532ecd00/fastavro-1.12.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c57a9920400166398695d92580eca21fd7a79f3c67d691ac7e20a7d1b5300735", size = 3284780, upload-time = "2026-04-24T14:36:24.193Z" }, + { url = "https://files.pythonhosted.org/packages/5d/e3/d7f510b9b8c7b73409a6232a9a8d282faa8560f85d024d7212e4c5dff3df/fastavro-1.12.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:81f6108f3ac292fb6cd05758c9e531389d8fc5e94e8c949b9298f4fb0a239662", size = 3368557, upload-time = "2026-04-24T14:36:26.667Z" }, + { url = "https://files.pythonhosted.org/packages/cb/10/14fa0abf8e7da07258393ae2b783dd4bb60d1fb93ad790296d27561f33ce/fastavro-1.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:eec44256856fd59d29d1f1d0950ace18a58e4228e7d49de5d5e1b1875b227dde", size = 446499, upload-time = "2026-04-24T14:36:28.547Z" }, + { url = "https://files.pythonhosted.org/packages/86/d2/c36f646296794c05d29a07bec84a6c56bfd285203e389a8954987ec1c515/fastavro-1.12.2-cp311-cp311-win_arm64.whl", hash = "sha256:ecd1b23ea7f9af09c865ac8503d07afd7e6bf782d76bb83cbbdba15b7a0db807", size = 388198, upload-time = "2026-04-24T14:36:29.791Z" }, + { url = "https://files.pythonhosted.org/packages/0e/bc/fe5731d6724d978694fbd3196bc1c0d7cab3fd0766e9551c40c39f798b52/fastavro-1.12.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0e331896e8efffc72fa03e63b87ebfc37960113127da8e0f5152d91664ffed68", size = 964331, upload-time = "2026-04-24T14:36:31.297Z" }, + { url = "https://files.pythonhosted.org/packages/98/36/50abf1145e4f1c4f418cd4b5f2ac806643d0b14e360b60e953826edf1b34/fastavro-1.12.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f01ebaada59d74fdf6d28e5031a961a413b3752e9edb0c03866fa18480cf4c8", size = 3340170, upload-time = "2026-04-24T14:36:33.364Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8c/76ef4641e6c1c1aa3e6bb3c9efb5533ffda5dd975c8b5ae54e794322d9e3/fastavro-1.12.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25ef6855935f67582740ffa6bb978e40ec51be876117a3555c36fa2488dcdf25", size = 3425061, upload-time = "2026-04-24T14:36:35.497Z" }, + { url = "https://files.pythonhosted.org/packages/31/10/379ff23425b2b470d5209cbc6736a6e5cbc34392ff17bb7355b8fd4aa0ca/fastavro-1.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:84a4f76a0aece0aa72b5ed8162ba2ff8c78908b8361b5a5d92ddd161977ccb74", size = 3243618, upload-time = "2026-04-24T14:36:37.969Z" }, + { url = "https://files.pythonhosted.org/packages/88/29/4c8f9e7cd78f932f0d82823899e67a6d7f7e8f2524992db03956f9d9f5ef/fastavro-1.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:81e8da77d201916f6771fc357fda8267c2a256d7aa11923d43bc5f2fc155878b", size = 3378427, upload-time = "2026-04-24T14:36:40.278Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a1/eafeb302aaaea6055d4a9c11272b4aeaf713e43fe8eaf782f43a1fee2b44/fastavro-1.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:1924349c74666c89417bd5cc2749f598e2f15f1d56ee81428b2317ab02c88aae", size = 441077, upload-time = "2026-04-24T14:36:41.791Z" }, + { url = "https://files.pythonhosted.org/packages/56/9d/67e831041ba8efc16265c65bd71ba92e1095bba19b91be99e102f19d9be6/fastavro-1.12.2-cp312-cp312-win_arm64.whl", hash = "sha256:4c346cf449baf3b113e997c34151ad205e7135bc429469b005b180ade7e65e28", size = 378205, upload-time = "2026-04-24T14:36:43.679Z" }, + { url = "https://files.pythonhosted.org/packages/83/39/f489a441d41cc9c0a8449fb1325d7a9c9eb57a5634e6ab19dfb0a1105324/fastavro-1.12.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:57bb6b908cb2e05baab63b04c3a31be3b4545a10bfab9748b8763016b5256704", size = 958566, upload-time = "2026-04-24T14:36:45.49Z" }, + { url = "https://files.pythonhosted.org/packages/31/69/776cc025aee2d02acacb734cf690d2fbc295eaadde1b5d47caf8c77a6a2b/fastavro-1.12.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a007f95cc682f56e6d83f1d17c29c00bf719d6fe8e003282b535af3a1ba09c0", size = 3276390, upload-time = "2026-04-24T14:36:47.875Z" }, + { url = "https://files.pythonhosted.org/packages/8c/bc/b7e15fa788f42cbe65827af2ec06c9ad91bb9f72c213110dbef61b53a5b0/fastavro-1.12.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e90460b0cd21f62be3cb26087e706e2cebb7b3fcef9e05b4473b61bb0415b5e", size = 3372779, upload-time = "2026-04-24T14:36:50.122Z" }, + { url = "https://files.pythonhosted.org/packages/79/c2/98993ca810231fc1397212f48c3d46626983722a24bbaaa5c27ee0963751/fastavro-1.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ccd15966b8218d41b06ec3e7c2556be89a8a693026c771e6564d2e40bbaf8ea", size = 3187591, upload-time = "2026-04-24T14:36:52.451Z" }, + { url = "https://files.pythonhosted.org/packages/c6/bb/c180f340eba6478f1b20deccdd17e2b4a4d5074dafd812e3c4254fd035f7/fastavro-1.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06b6971d3dae10cb34353b857d16ad21ebd6f0ea394e86c96abdcad109005d6e", size = 3320589, upload-time = "2026-04-24T14:36:54.647Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e9/aca0456216b5b8992e7b0a8542711b66799c05bfe24c8e32ef6f56e7eb93/fastavro-1.12.2-cp313-cp313-win_amd64.whl", hash = "sha256:98dfcdfaf1498ae2f0e2fafe900a82e8320cc81d8ae5a95b8b8879eaa3298c39", size = 440883, upload-time = "2026-04-24T14:36:56.585Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7e/984896e716af504927be71b80a1e9661aa96c6f9e1e777d52823aacb99f2/fastavro-1.12.2-cp313-cp313-win_arm64.whl", hash = "sha256:3888ef7a51adc77cdf07251bc762566a1be36211e1cff689f13980f3776a2f36", size = 377536, upload-time = "2026-04-24T14:36:58.274Z" }, + { url = "https://files.pythonhosted.org/packages/e9/42/09a1e1f8d9998d73848a6ff0aad6713ae6abf0dbf99918776f8ef33344a7/fastavro-1.12.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:283dcd3129b632021894425974bedd0eb6db3bbf5994e448ccad10db4d803d31", size = 1049506, upload-time = "2026-04-24T14:36:59.797Z" }, + { url = "https://files.pythonhosted.org/packages/52/ef/80cc16f43919d532f25a707f34b275cccc09dca87a05b000fbbfc8e8f255/fastavro-1.12.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d125e210d5a0a1f701f12c0ecad9a03f1b04b5eddbce6ca36a1fc217da977ef", size = 3495899, upload-time = "2026-04-24T14:37:02.306Z" }, + { url = "https://files.pythonhosted.org/packages/c1/54/a0817d1d0236e9e0233f5c996f450cc795b056b8e06edb531f24b9df82ed/fastavro-1.12.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2d4d66afad78e8f47feaa307728a6b71fe3effc63ba2b9eeb109ee687c9bd397", size = 3399232, upload-time = "2026-04-24T14:37:04.837Z" }, + { url = "https://files.pythonhosted.org/packages/38/0a/650f256c15f5875b6081544b9ba7ed8254329213e7e49e3db0aec68b5bee/fastavro-1.12.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2328ec07925c04c89719e3971c9068a165c7fd474ea87675b1204de0440e71ff", size = 3320222, upload-time = "2026-04-24T14:37:07.281Z" }, + { url = "https://files.pythonhosted.org/packages/f5/54/8351d388f94fbb0870e8cffaae41d3cc607acc8d6a8a6a217e2794829593/fastavro-1.12.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:55dea7e74b834d4b70467fc19c5b9ccb5509fe39abc4d26891187c1b22176423", size = 3337096, upload-time = "2026-04-24T14:37:09.452Z" }, + { url = "https://files.pythonhosted.org/packages/da/eb/b36ba9a88826e8c272df02e2f8b5da717e88b6eb508fddca3ca450043731/fastavro-1.12.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8d37c87826ae7195cfbd20fcd448801f2f563bb38f2691ec6574e39cb9eca6c8", size = 963119, upload-time = "2026-04-24T14:37:11.557Z" }, + { url = "https://files.pythonhosted.org/packages/e1/02/3d7f540fb26ba4ea1f4ebd2783c586614da9ac00906a3092e92fd3f104a2/fastavro-1.12.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c463a3701f293e30d3d62e71e1989f112028d07f87432baf4507eeb57ec3831", size = 3266238, upload-time = "2026-04-24T14:37:13.84Z" }, + { url = "https://files.pythonhosted.org/packages/4c/0b/b77be56c5109da0fc7dcfd7e6b6752fe0a61d0a5c58c6a65e38b4501946a/fastavro-1.12.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f604ba83498e209fff4c7ecc5063a39421dc538dace694bc592f9f338254f3dc", size = 3324020, upload-time = "2026-04-24T14:37:16.096Z" }, + { url = "https://files.pythonhosted.org/packages/e7/6e/951d41f244107e91bf2f59245b71783c03eaab4bdbc960d58316c19652bb/fastavro-1.12.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bfac2dada8ddc002e8b7d8289d6fad4f070bc1fec20371cec684a7d10d932e96", size = 3170160, upload-time = "2026-04-24T14:37:18.168Z" }, + { url = "https://files.pythonhosted.org/packages/94/6f/2adb571fda448d4afd2466e1cef2963fefdc6b37847da05249983e415f17/fastavro-1.12.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bc44ba6289fb1f5ee318335958dde6ad6d742dcb4bb8930de843e9024c64b68c", size = 3281842, upload-time = "2026-04-24T14:37:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/17/07/4bad2e96c4c6bae40253be2573cc09c1e5b9ccf821e1ff74e0d33b64bf90/fastavro-1.12.2-cp314-cp314-win_amd64.whl", hash = "sha256:a475418f71c5aed69899813ecccf392429c08c3a63df3030129db71760b0db8f", size = 450903, upload-time = "2026-04-24T14:37:23.059Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b7/180f67ba9a46ba23a1ff6432f48d3087d4f2048579ecc262b00426cb1c63/fastavro-1.12.2-cp314-cp314-win_arm64.whl", hash = "sha256:daec9f9655a1d4636613c47d6d3343f6e039150d66cdce62543e20ca36612a8a", size = 391076, upload-time = "2026-04-24T14:37:24.756Z" }, + { url = "https://files.pythonhosted.org/packages/dd/8f/18f60329b627d2118a4a2b19e8741fbd807d60bf0470554e1bbfb7f1bca3/fastavro-1.12.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:57594b72cf663bbd0f3ad8a319a999fc3d7c71065a6799b2c1d1a6a137894c5b", size = 1055430, upload-time = "2026-05-09T21:53:14.364Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ac/a1fa1fc29df0efc89d4946a743b09bdc9500591b5b92083eaf8e93664916/fastavro-1.12.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74412132bbfb153cbf704517f2c89f7d3e170feb681b13bceace690f66f8d5fa", size = 3503075, upload-time = "2026-04-24T14:37:26.826Z" }, + { url = "https://files.pythonhosted.org/packages/82/bf/4f669e10b6bc38a731ee3400aed1a1e2d0a3e3cf411e72f6b320d3af0eaf/fastavro-1.12.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e367a84c9133018e0a3bc822abe78d7f1f9a6092991a0ec409468cf4ef260282", size = 3410900, upload-time = "2026-04-24T14:37:29.233Z" }, + { url = "https://files.pythonhosted.org/packages/10/39/ecb19fdae4158a7730b5963fbf1b6d38d74678392d73083be518642af0c1/fastavro-1.12.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:044fafca0853e9ae14009de7763ac9e8e8f8b96f8a4e90bd58b695443266a370", size = 3335637, upload-time = "2026-04-24T14:37:31.472Z" }, + { url = "https://files.pythonhosted.org/packages/32/f1/f21bd5319113e89ceceed2df840df21e9c5150d181db74b6ba80400f9f48/fastavro-1.12.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afede7324822800e4f90e96b9514188a237a60f35e8e7a10b2129c10c78f6e4d", size = 3356664, upload-time = "2026-04-24T14:37:34.231Z" }, +] + [[package]] name = "filelock" version = "3.29.1" @@ -585,6 +666,38 @@ 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" }, ] +[[package]] +name = "hf-xet" +version = "1.5.0" +source = { registry = "https://pypi.org/simple/" } +sdist = { url = "https://files.pythonhosted.org/packages/74/d8/5c06fc76461418326a7decf8367480c35be11a41fd938633929c60a9ec6b/hf_xet-1.5.0.tar.gz", hash = "sha256:e0fb0a34d9f406eed88233e829a67ec016bec5af19e480eac65a233ea289a948", size = 837196, upload-time = "2026-05-06T06:18:15.583Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/9b/6912c99070915a4f28119e3c5b52a9abd1eec0ad5cb293b8c967a0c6f5a2/hf_xet-1.5.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:7d70fe2ce97b9db73b9c9b9c81fe3693640aec83416a966c446afea54acfae3c", size = 4023383, upload-time = "2026-05-06T06:17:53.947Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6d/9563cfde59b5d8128a9c7ec972a087f4c782e4f7bac5a85234edfd5d5e49/hf_xet-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:73a0dae8c71de3b0633a45c73f4a4a5ed09e94b43441d82981a781d4f12baa42", size = 3792751, upload-time = "2026-05-06T06:17:51.791Z" }, + { url = "https://files.pythonhosted.org/packages/07/a5/ed5a0cf35b49a0571af5a8f53416dad1877a718c021c9937c3a53cb45781/hf_xet-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a60290ec57e9b71767fba7c3645ddafdd0759974b540441510c629c6db6db24a", size = 4456058, upload-time = "2026-05-06T06:17:40.735Z" }, + { url = "https://files.pythonhosted.org/packages/60/fb/3ae8bf2a7a37a4197d0195d7247fd25b3952e15cb8a599e285dfaa6f52b3/hf_xet-1.5.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:e5de0f6deada0dada870bb376a11bcd1f08abf3a968a6d118f33e72d1b1eb480", size = 4250783, upload-time = "2026-05-06T06:17:38.412Z" }, + { url = "https://files.pythonhosted.org/packages/a2/9b/8bae40d4d91525085137196e84eb0ed49cf65b5e96e5c3ecdadd8bd0fac2/hf_xet-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c799d49f1a5544a0ef7591c0ee75e0d6b93d6f56dc7a4979f59f7518d2872216", size = 4445594, upload-time = "2026-05-06T06:18:04.219Z" }, + { url = "https://files.pythonhosted.org/packages/13/59/c74efbbd4e8728172b2cc72a2bc014d2947a4b7bdced932fbd3f5da1a4e5/hf_xet-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2baea1b0b989e5c152fe81425f7745ddc8901280ba3d97c98d8cdece7b706c60", size = 4663995, upload-time = "2026-05-06T06:18:06.1Z" }, + { url = "https://files.pythonhosted.org/packages/73/32/8e1e0410af64cda9b139d1dcebdc993a8ff9c8c7c0e2696ae356d75ccc0d/hf_xet-1.5.0-cp313-cp313t-win_amd64.whl", hash = "sha256:526345b3ed45f374f6317349df489167606736c876241ba984105afe7fd4839d", size = 3966608, upload-time = "2026-05-06T06:18:19.74Z" }, + { url = "https://files.pythonhosted.org/packages/fc/34/a8febc8f4edbea8b3e21b02ebc8b628679b84ba7e45cde624a7736b51500/hf_xet-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:786d28e2eb8315d5035544b9d137b4a842d600c434bb91bf7d0d953cce906ad4", size = 3796946, upload-time = "2026-05-06T06:18:17.568Z" }, + { url = "https://files.pythonhosted.org/packages/2a/20/8fc8996afe5815fa1a6be8e9e5c02f24500f409d599e905800d498a4e14d/hf_xet-1.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:872d5601e6deea30d15865ede55d29eac6daf5a534ab417b99b6ef6b076dd96c", size = 4023495, upload-time = "2026-05-06T06:18:01.94Z" }, + { url = "https://files.pythonhosted.org/packages/32/6a/93d84463c00cecb561a7508aa6303e35ee2894294eac14245526924415fe/hf_xet-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9929561f5abf4581c8ea79587881dfef6b8abb2a0d8a51915936fc2a614f4e73", size = 3792731, upload-time = "2026-05-06T06:18:00.021Z" }, + { url = "https://files.pythonhosted.org/packages/9d/5a/8ec8e0c863b382d00b3c2e2af6ded6b06371be617144a625903a6d562f4b/hf_xet-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f7b7bbae318e583a86fb21e5a4a175d6721d628a2874f4bd022d0e660c32a682", size = 4456738, upload-time = "2026-05-06T06:17:49.574Z" }, + { url = "https://files.pythonhosted.org/packages/c5/ca/f7effa1a67717da2bcc6b6c28f71c6ca648c77acaec4e2c32f40cbe16d85/hf_xet-1.5.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:cf7b2dc6f31a4ea754bb50f74cde482dcf5d366d184076d8530b9872787f3761", size = 4251622, upload-time = "2026-05-06T06:17:47.096Z" }, + { url = "https://files.pythonhosted.org/packages/65/f2/19247dba3e231cf77dec59ddfb878f00057635ff773d099c9b59d37812c3/hf_xet-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8dbcbab554c9ef158ef2c991545c3e970ddd8cc7acdcd0a78c5a41095dab4ded", size = 4445667, upload-time = "2026-05-06T06:18:11.983Z" }, + { url = "https://files.pythonhosted.org/packages/7f/64/6f116801a3bcfb6f59f5c251f48cadc47ea54026441c4a385079286a94fa/hf_xet-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5906bf7718d3636dc13402914736abe723492cb730f744834f5f5b67d3a12702", size = 4664619, upload-time = "2026-05-06T06:18:13.771Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e8/069542d37946ed08669b127e1496fa99e78196d71de8d41eda5e9f1b7a58/hf_xet-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:5f3dc2248fc01cc0a00cd392ab497f1ca373fcbc7e3f2da1f452480b384e839e", size = 3966802, upload-time = "2026-05-06T06:18:28.162Z" }, + { url = "https://files.pythonhosted.org/packages/f9/91/fc6fdec27b14d04e88c386ac0a0129732b53fa23f7c4a78f4b83a039c567/hf_xet-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:b285cea1b5bab46b758772716ba8d6854a1a0310fed1c249d678a8b38601e5a0", size = 3797168, upload-time = "2026-05-06T06:18:26.287Z" }, + { url = "https://files.pythonhosted.org/packages/3d/fb/69ff198a82cae7eb1a69fb84d93b3a3e4816564d76817fe541ddc96874eb/hf_xet-1.5.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dad0dc84e941b8ba3c860659fe1fdc35c049d47cce293f003287757e971a8f56", size = 4030814, upload-time = "2026-05-06T06:17:57.933Z" }, + { url = "https://files.pythonhosted.org/packages/9b/ff/edcc2b40162bef3ff78e14ab637e5f3b89243d6aee72f5949d3bb6a5af83/hf_xet-1.5.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:fd6e5a9b0fdac4ed03ed45ef79254a655b1aaab514a02202617fbf643f5fdf7a", size = 3798444, upload-time = "2026-05-06T06:17:55.79Z" }, + { url = "https://files.pythonhosted.org/packages/49/4d/103f76b04310e5e57656696cc184690d20c466af0bca3ca88f8c8ea5d4f3/hf_xet-1.5.0-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3531b1823a0e6d77d80f9ed15ca0e00f0d115094f8ac033d5cae88f4564cc949", size = 4465986, upload-time = "2026-05-06T06:17:44.886Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a2/546f47f464737b3edbab6f8ddb57f2599b93d2cbb66f06abb475ccb48651/hf_xet-1.5.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:9a0ee58cd18d5ea799f7ed11290bbccbe56bdd8b1d97ca74b9cc49a3945d7a3b", size = 4259865, upload-time = "2026-05-06T06:17:42.639Z" }, + { url = "https://files.pythonhosted.org/packages/95/7f/1be593c1f28613be2e196473481cd81bfc5910795e30a34e8f744f6cac4f/hf_xet-1.5.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1e60df5a42e9bed8628b6416af2cba4cba57ae9f02de226a06b020d98e1aab18", size = 4459835, upload-time = "2026-05-06T06:18:08.026Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b2/703569fc881f3284487e68cda7b42179978480da3c438042a6bbbb4a671c/hf_xet-1.5.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4b35549ce62601b84da4ff9b24d970032ace3d4430f52d91bcbb26c901d6c690", size = 4672414, upload-time = "2026-05-06T06:18:09.864Z" }, + { url = "https://files.pythonhosted.org/packages/af/37/1b6def445c567286b50aa3b33828158e135b1be44938dde59f11382a500c/hf_xet-1.5.0-cp37-abi3-win_amd64.whl", hash = "sha256:2806c7c17b4d23f8d88f7c4814f838c3b6150773fe339c20af23e1cfaf2797e4", size = 3977238, upload-time = "2026-05-06T06:18:23.621Z" }, + { url = "https://files.pythonhosted.org/packages/62/94/3b66b148778ee100dcfd69c2ca22b57b41b44d3063ceec934f209e9184ce/hf_xet-1.5.0-cp37-abi3-win_arm64.whl", hash = "sha256:b6c9df403040248c76d808d3e047d64db2d923bae593eb244c41e425cf6cd7be", size = 3806916, upload-time = "2026-05-06T06:18:21.7Z" }, +] + [[package]] name = "httpcore" version = "1.0.9" @@ -622,6 +735,27 @@ 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" }, ] +[[package]] +name = "huggingface-hub" +version = "1.17.0" +source = { registry = "https://pypi.org/simple/" } +dependencies = [ + { name = "click" }, + { name = "filelock" }, + { name = "fsspec" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "httpx" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "tqdm" }, + { name = "typer" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/65/9826515abb600b5722bcf53f8b4a2fb58340b1f8bfcaee19f83561c13a44/huggingface_hub-1.17.0.tar.gz", hash = "sha256:fad842b6763ef70ebc3919665b1b9273645203185400a7d6c5eddc2323cc3435", size = 797082, upload-time = "2026-05-28T15:12:13.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/28/d7cef5e477b855c25d415b8f57e5bc7347c7a90cad3acf1725d0c92ca294/huggingface_hub-1.17.0-py3-none-any.whl", hash = "sha256:3b8156d23118e87f6a587648bfbc04f04a12a757ccb4ed298b35c4ae638bf24c", size = 671546, upload-time = "2026-05-28T15:12:11.441Z" }, +] + [[package]] name = "identify" version = "2.6.19" @@ -951,6 +1085,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/65/f9c9dc19b21a9076286fafdb0ab732c9019ddf71aa7e7d720a830a98fe2a/langsmith-0.8.11-py3-none-any.whl", hash = "sha256:08aa5e84b00703ecc11dbeafda78d84b92da4e8c6114e0be9b59df9e71afc59b", size = 478985, upload-time = "2026-06-08T22:54:42.349Z" }, ] +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple/" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -1061,6 +1207,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c9/11/252c6f971dc4f16af1d98a1c469d8ba523aab00d1bb76b4d3bc1ff32eacc/mcp-1.27.2-py3-none-any.whl", hash = "sha256:d6ff5160c6ca65d93013626efb3fc249de683c30b2d8570755ceddd490344de5", size = 220498, upload-time = "2026-05-29T17:16:02.442Z" }, ] +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple/" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + [[package]] name = "nodeenv" version = "1.10.0" @@ -1185,6 +1340,31 @@ requires-dist = [ ] provides-extras = ["instruments"] +[[package]] +name = "opentelemetry-instrumentation-genai-cohere" +source = { editable = "instrumentation/opentelemetry-instrumentation-genai-cohere" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-genai" }, +] + +[package.optional-dependencies] +instruments = [ + { name = "cohere" }, +] + +[package.metadata] +requires-dist = [ + { name = "cohere", marker = "extra == 'instruments'", specifier = ">=5.13.0" }, + { 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"] + [[package]] name = "opentelemetry-instrumentation-genai-langchain" source = { editable = "instrumentation/opentelemetry-instrumentation-genai-langchain" } @@ -1313,6 +1493,7 @@ dependencies = [ { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-instrumentation-genai-anthropic", extra = ["instruments"] }, { name = "opentelemetry-instrumentation-genai-claude-agent-sdk", extra = ["instruments"] }, + { name = "opentelemetry-instrumentation-genai-cohere", extra = ["instruments"] }, { name = "opentelemetry-instrumentation-genai-langchain", extra = ["instruments"] }, { name = "opentelemetry-instrumentation-genai-openai", extra = ["instruments"] }, { name = "opentelemetry-instrumentation-genai-openai-agents", extra = ["instruments"] }, @@ -1339,6 +1520,7 @@ requires-dist = [ { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-instrumentation-genai-anthropic", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-genai-anthropic" }, { name = "opentelemetry-instrumentation-genai-claude-agent-sdk", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk" }, + { name = "opentelemetry-instrumentation-genai-cohere", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-genai-cohere" }, { name = "opentelemetry-instrumentation-genai-langchain", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-genai-langchain" }, { name = "opentelemetry-instrumentation-genai-openai", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-genai-openai" }, { name = "opentelemetry-instrumentation-genai-openai-agents", extras = ["instruments"], editable = "instrumentation/opentelemetry-instrumentation-genai-openai-agents" }, @@ -2046,6 +2228,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple/" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + [[package]] name = "rpds-py" version = "0.30.0" @@ -2311,6 +2506,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/ea/e7b0251441da9adfeaebcf29601d10f2a1455fcf0772fae9e7e19032bd96/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8c43a8a973270fd173bf48cdf80bbe66312421cba68d40845034f174f2389049", size = 586326, upload-time = "2026-05-28T12:02:11.47Z" }, ] +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple/" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -2355,6 +2559,33 @@ 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" }, ] +[[package]] +name = "tokenizers" +version = "0.23.1" +source = { registry = "https://pypi.org/simple/" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/60/21f715d9faba5f5407ff759472ade058ec4a507ad62bcea47cb847239a73/tokenizers-0.23.1.tar.gz", hash = "sha256:1feeeadf865a7915adc25445dea30e9933e593c31bb96c277cee36de227c8bfa", size = 365748, upload-time = "2026-04-27T14:43:25.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/39/b87a87d5bb9470610b80a2d31df42fcffeaf35118b8b97952b2aff598cc7/tokenizers-0.23.1-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e03d6ffcbe0d56ee9c1ccd070e70a13fa750727c0277e138152acbc0252c2224", size = 3146732, upload-time = "2026-04-27T14:43:15.427Z" }, + { url = "https://files.pythonhosted.org/packages/e2/6a/068ed9f6e444c9d7e9d55ce134181325700f3d7f30410721bdc8f848d727/tokenizers-0.23.1-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:e0948bbb1ac1d7cdfc9fb6d62c596e3b7550036ad60ecd654a66ad273326324e", size = 3054954, upload-time = "2026-04-27T14:43:13.745Z" }, + { url = "https://files.pythonhosted.org/packages/6c/36/e006edf031154cba92b8416057d92c3abe3635e4c4b0aa0b5b9bb39dde70/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bf13402aff9bc533c89cb849ec3b412dc3fbeacc9744840e423d7bf3f7dc0e3", size = 3374081, upload-time = "2026-04-27T14:43:01.241Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ef/7735d226f9c7f874a6bee5e3f27fb25ecabdf207d37b8cf45286d0795893/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f836ca703b89ae07919a309f9651f7a88fd5a33d5f718ba5ad0870ec0256bad6", size = 3247641, upload-time = "2026-04-27T14:43:03.856Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d9/24827036f6e21297bfffda0768e58eb6096a4f411e932964a01707857931/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae848657742035523fdf261773630cb819a26995fcd3d9ecae0c1daf6e5a4959", size = 3585624, upload-time = "2026-04-27T14:43:10.664Z" }, + { url = "https://files.pythonhosted.org/packages/0c/9a/22f3582b3a4f49358293a5206e25317621ee4526bfe9cdaa0f07a12e770e/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53b09e85775d5187941e7bab30e941b4134ab4a7dd8c68e783d231fb7ca27c51", size = 3844062, upload-time = "2026-04-27T14:43:05.643Z" }, + { url = "https://files.pythonhosted.org/packages/7e/65/b8f8814eef95800f20721384136d9a1d22241d50b2874357cb70542c392f/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea5a0ce170074329faaa8ea3f6400ecde604b6678192688533af80980daae71a", size = 3460098, upload-time = "2026-04-27T14:43:08.854Z" }, + { url = "https://files.pythonhosted.org/packages/0d/d5/1353e5f677ec27c2494fb6a6725e82d56c985f53e90ec511369e7e4f02c6/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b405006415ea148a992d093699c66eb01952bf59f4d5727089a98bda45a4", size = 3346235, upload-time = "2026-04-27T14:43:12.377Z" }, + { url = "https://files.pythonhosted.org/packages/71/89/39b6b8fc073fb6d413d0147aa333dc7eff7be65639ac9d19930a0b21bf33/tokenizers-0.23.1-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:56f3a77de629917652f876294dc9fe6bad4a0c43bc229dc72e59bb23a0f4729a", size = 3426398, upload-time = "2026-04-27T14:43:07.264Z" }, + { url = "https://files.pythonhosted.org/packages/0f/80/127c854da64827e5b79264ce524993a90dddcb320e5cd42412c5c02f9e8a/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9d10a6d957ef01896dc274e890eee27d41bd0e74ef31e60616f0fc311345184e", size = 9823279, upload-time = "2026-04-27T14:43:17.222Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ba/44c2502feb1a058f096ddfb4e0996ef3225a01a388e1a9b094e91689fe93/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1974288a609c343774f1b897c8b482c791ab17b75ab5c8c2b1737565c1d82288", size = 9644986, upload-time = "2026-04-27T14:43:19.45Z" }, + { url = "https://files.pythonhosted.org/packages/9e/c1/464019a9fb059870bfe4eebb4ba12208f3042035e258bf5e782906bd3847/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:120468fb4c24faf0543c835a4fabafa4deb3f20a035c9b6e83d0b553a97615d4", size = 9976181, upload-time = "2026-04-27T14:43:21.463Z" }, + { url = "https://files.pythonhosted.org/packages/79/94/3ac1432bda31626071e9b6a12709b97ae05131c804b94c8f3ac622c5da32/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e3d8f40ea6268047de7046906326abed5134f27d4e8447b23763afe5808c8a96", size = 10113853, upload-time = "2026-04-27T14:43:23.617Z" }, + { url = "https://files.pythonhosted.org/packages/6a/dd/631b21433c771b1382535326f0eca80b9c9cee2e64961dd993bc9ac4669e/tokenizers-0.23.1-cp310-abi3-win32.whl", hash = "sha256:93120a930b919416da7cd10a2f606ac9919cc69cacae7980fa2140e277660948", size = 2536263, upload-time = "2026-04-27T14:43:29.888Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/2553f72aaf65a2797d4229e37fa7fbe38ffbf3e32912d31bdd78b3323e59/tokenizers-0.23.1-cp310-abi3-win_amd64.whl", hash = "sha256:e7bfaf995c1bdbbd21d13539decb6650967013759318627d85daeb7881af16b7", size = 2798223, upload-time = "2026-04-27T14:43:28.51Z" }, + { url = "https://files.pythonhosted.org/packages/cd/2b/2be299bab55fc595e3d38567edb1a87f86e594842968fa9515a07bdcf422/tokenizers-0.23.1-cp310-abi3-win_arm64.whl", hash = "sha256:a26197957d8e4425dfba746315f3c425ea00cfa8367c5fbc4ec73447893dcea9", size = 2664127, upload-time = "2026-04-27T14:43:26.949Z" }, +] + [[package]] name = "tomli" version = "2.4.1" @@ -2493,6 +2724,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/75/1a0392bcc21c44dcdf87b3cf2d137e7829be2c083a1e38d44efca3d57a16/tqdm-4.68.2-py3-none-any.whl", hash = "sha256:d4240441fb5353290b87d6a85968c9decc131a99b8c7faa28269d829de669ede", size = 78578, upload-time = "2026-06-09T13:26:40.731Z" }, ] +[[package]] +name = "typer" +version = "0.25.1" +source = { registry = "https://pypi.org/simple/" } +dependencies = [ + { name = "annotated-doc" }, + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/51/9aed62104cea109b820bbd6c14245af756112017d309da813ef107d42e7e/typer-0.25.1.tar.gz", hash = "sha256:9616eb8853a09ffeabab1698952f33c6f29ffdbceb4eaeecf571880e8d7664cc", size = 122276, upload-time = "2026-04-30T19:32:16.964Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl", hash = "sha256:75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89", size = 58409, upload-time = "2026-04-30T19:32:18.271Z" }, +] + [[package]] name = "types-requests" version = "2.33.0.20260518"