diff --git a/CLAUDE.md b/CLAUDE.md index 69f0f2ab..5abc0ee1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -124,7 +124,6 @@ libraries/ └── Framework Extensions (integrate with specific AI frameworks) ├── Observability Extensions │ ├── *-observability-extensions-openai - │ ├── *-observability-extensions-langchain │ ├── *-observability-extensions-semantickernel │ └── *-observability-extensions-agentframework │ diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index ee572d02..739972b4 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -7,7 +7,6 @@ graph LR %% Package Nodes microsoft_agents_a365_notifications["microsoft-agents-a365-notifications"] microsoft_agents_a365_observability_core["microsoft-agents-a365-observability-core"] - microsoft_agents_a365_observability_extensions_langchain["microsoft-agents-a365-observability-extensions-langchain"] microsoft_agents_a365_observability_extensions_openai["microsoft-agents-a365-observability-extensions-openai"] microsoft_agents_a365_observability_extensions_semantic_kernel["microsoft-agents-a365-observability-extensions-semantic-kernel"] microsoft_agents_a365_observability_extensions_agent_framework["microsoft-agents-a365-observability-extensions-agent-framework"] @@ -20,7 +19,6 @@ graph LR %% Dependencies microsoft_agents_a365_observability_core --> microsoft_agents_a365_runtime - microsoft_agents_a365_observability_extensions_langchain --> microsoft_agents_a365_observability_core microsoft_agents_a365_observability_extensions_openai --> microsoft_agents_a365_observability_core microsoft_agents_a365_observability_extensions_semantic_kernel --> microsoft_agents_a365_observability_core microsoft_agents_a365_observability_extensions_agent_framework --> microsoft_agents_a365_observability_core @@ -37,7 +35,7 @@ graph LR classDef observability fill:#c8e6c9,stroke:#2e7d32,color:#142a14,stroke-width:2px class microsoft_agents_a365_observability_core observability classDef observability_extensions fill:#e8f5e9,stroke:#66bb6a,color:#1f3d1f,stroke-width:2px - class microsoft_agents_a365_observability_extensions_langchain,microsoft_agents_a365_observability_extensions_openai,microsoft_agents_a365_observability_extensions_semantic_kernel,microsoft_agents_a365_observability_extensions_agent_framework observability_extensions + class microsoft_agents_a365_observability_extensions_openai,microsoft_agents_a365_observability_extensions_semantic_kernel,microsoft_agents_a365_observability_extensions_agent_framework observability_extensions classDef tooling fill:#ffe0b2,stroke:#e65100,color:#331a00,stroke-width:2px class microsoft_agents_a365_tooling tooling classDef tooling_extensions fill:#fff3e0,stroke:#fb8c00,color:#4d2600,stroke-width:2px diff --git a/README.md b/README.md index 0e616e8c..1a0abfe9 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,6 @@ The best way to consume this SDK is via our PyPI packages found here: [pypi.org] - **libraries/microsoft-agents-a365-notifications**: Microsoft Agent 365 Notifications SDK - Agent notification services and models - **libraries/microsoft-agents-a365-observability-core**: Microsoft Agent 365 Observability Core - Core observability functionality - **libraries/microsoft-agents-a365-observability-extensions-agentframework**: Agent Framework observability extensions -- **libraries/microsoft-agents-a365-observability-extensions-langchain**: LangChain observability extensions - **libraries/microsoft-agents-a365-observability-extensions-openai**: OpenAI observability extensions - **libraries/microsoft-agents-a365-observability-extensions-semantickernel**: Semantic Kernel observability extensions - **libraries/microsoft-agents-a365-runtime**: Microsoft Agent 365 Runtime - Core runtime utilities and extensions diff --git a/docs/design.md b/docs/design.md index fea18970..f81ae66e 100644 --- a/docs/design.md +++ b/docs/design.md @@ -17,11 +17,10 @@ The SDK supports production deployment across Microsoft 365, Teams, Copilot Stud ``` Agent365-python/ -├── libraries/ # Core packages (13 total) +├── libraries/ # Core packages (12 total) │ ├── microsoft-agents-a365-notifications/ │ ├── microsoft-agents-a365-observability-core/ │ ├── microsoft-agents-a365-observability-extensions-agentframework/ -│ ├── microsoft-agents-a365-observability-extensions-langchain/ │ ├── microsoft-agents-a365-observability-extensions-openai/ │ ├── microsoft-agents-a365-observability-extensions-semantickernel/ │ ├── microsoft-agents-a365-observability-hosting/ @@ -129,7 +128,6 @@ Framework-specific instrumentations that integrate with the observability core: | Package | Purpose | Design Doc | |---------|---------|------------| | `extensions-openai` | Instrument OpenAI SDK client calls | [design.md](../libraries/microsoft-agents-a365-observability-extensions-openai/docs/design.md) | -| `extensions-langchain` | LangChain callback integration | [design.md](../libraries/microsoft-agents-a365-observability-extensions-langchain/docs/design.md) | | `extensions-agentframework` | Microsoft Agents SDK integration | [design.md](../libraries/microsoft-agents-a365-observability-extensions-agentframework/docs/design.md) | | `extensions-semantickernel` | Semantic Kernel instrumentation | [design.md](../libraries/microsoft-agents-a365-observability-extensions-semantickernel/docs/design.md) | | `hosting` | Hosting-specific observability utilities | — | @@ -461,7 +459,6 @@ tests/ │ │ └── test_baggage_builder.py # Context propagation tests │ └── extensions/ │ ├── openai/ -│ ├── langchain/ │ └── agentframework/ ├── runtime/ │ ├── test_power_platform_api_discovery.py diff --git a/docs/integrating-with-existing-opentelemetry.md b/docs/integrating-with-existing-opentelemetry.md index 9e3fb123..4e53c516 100644 --- a/docs/integrating-with-existing-opentelemetry.md +++ b/docs/integrating-with-existing-opentelemetry.md @@ -73,7 +73,6 @@ The OTel **backend** (where spans go) and the **instrumentation style** (how spa For auto-instrumentation, install the framework-specific extension package — for example: - OpenAI Agents SDK → `microsoft-agents-a365-observability-extensions-openai` -- LangChain → `microsoft-agents-a365-observability-extensions-langchain` - Semantic Kernel → `microsoft-agents-a365-observability-extensions-semantickernel` - Microsoft Agent Framework → `microsoft-agents-a365-observability-extensions-agentframework` diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/CHANGELOG.md b/libraries/microsoft-agents-a365-observability-extensions-langchain/CHANGELOG.md deleted file mode 100644 index 1452eaa5..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# Changelog — microsoft-agents-a365-observability-extensions-langchain - -All notable changes to this package will be documented in this file. - -## [Unreleased] - -### Changed - -- Removed `set_execution_type()` function and all `ExecutionType` / `GEN_AI_EXECUTION_TYPE_KEY` usage. diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/README.md b/libraries/microsoft-agents-a365-observability-extensions-langchain/README.md deleted file mode 100644 index 9b63a953..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# microsoft-agents-a365-observability-extensions-langchain - -[![PyPI](https://img.shields.io/pypi/v/microsoft-agents-a365-observability-extensions-langchain?label=PyPI&logo=pypi)](https://pypi.org/project/microsoft-agents-a365-observability-extensions-langchain) -[![PyPI Downloads](https://img.shields.io/pypi/dm/microsoft-agents-a365-observability-extensions-langchain?label=Downloads&logo=pypi)](https://pypi.org/project/microsoft-agents-a365-observability-extensions-langchain) - -Observability extensions for LangChain framework. This package provides OpenTelemetry tracing integration for LangChain-based AI applications with automatic instrumentation for chains, agents, and tools. - -## Installation - -```bash -pip install microsoft-agents-a365-observability-extensions-langchain -``` - -## Usage - -For usage examples and detailed documentation, see the [Observability documentation](https://learn.microsoft.com/microsoft-agent-365/developer/observability?tabs=python) on Microsoft Learn. - -## Support - -For issues, questions, or feedback: - -- File issues in the [GitHub Issues](https://github.com/microsoft/Agent365-python/issues) section -- See the [main documentation](../../README.md) for more information - -## Trademarks - -*Microsoft, Windows, Microsoft Azure and/or other Microsoft products and services referenced in the documentation may be either trademarks or registered trademarks of Microsoft in the United States and/or other countries. The licenses for this project do not grant you rights to use any Microsoft names, logos, or trademarks. Microsoft's general trademark guidelines can be found at http://go.microsoft.com/fwlink/?LinkID=254653.* - -## License - -Copyright (c) Microsoft Corporation. All rights reserved. - -Licensed under the MIT License - see the [LICENSE](../../LICENSE.md) file for details. diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/docs/design.md b/libraries/microsoft-agents-a365-observability-extensions-langchain/docs/design.md deleted file mode 100644 index fc848fdd..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/docs/design.md +++ /dev/null @@ -1,69 +0,0 @@ -# Observability Extensions - LangChain - Design Document - -This document describes the architecture and design of the `microsoft-agents-a365-observability-extensions-langchain` package. - -## Overview - -This extension integrates the Agent365 observability infrastructure with LangChain, enabling automatic tracing of LangChain chain executions, LLM calls, and tool invocations. - -## Key Components - -### LangChainTracerInstrumentor - -The main instrumentor class that integrates with LangChain's callback system. - -```python -from microsoft_agents_a365.observability.extensions.langchain import LangChainTracerInstrumentor - -# Initialize and instrument -instrumentor = LangChainTracerInstrumentor() -instrumentor.instrument() -``` - -### Tracer Callback - -Custom LangChain callback handler that creates Agent365 spans for: -- Chain executions -- LLM calls (with token tracking) -- Tool executions - -### Integration Flow - -``` -LangChain Execution - │ - ▼ -Callback Handler (on_llm_start, on_tool_start, etc.) - │ - ▼ -InferenceScope / ExecuteToolScope - │ - ▼ -Agent365 Backend -``` - -## File Structure - -``` -microsoft_agents_a365/observability/extensions/langchain/ -├── __init__.py # Public API -├── tracer.py # LangChain tracer callback -├── tracer_instrumentor.py # Main instrumentor -└── utils.py # Utility functions -``` - -## LangChain Callback Events - -| Event | Agent365 Scope | -|-------|----------------| -| `on_llm_start` | `InferenceScope` | -| `on_llm_end` | Records tokens, finish reason | -| `on_tool_start` | `ExecuteToolScope` | -| `on_tool_end` | Records tool result | -| `on_chain_start` | `InvokeAgentScope` | -| `on_chain_end` | Records chain output | - -## Dependencies - -- `langchain-core` - LangChain core framework (tracers, callbacks, message types) -- `microsoft-agents-a365-observability-core` - Core observability diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/__init__.py b/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/__init__.py deleted file mode 100644 index 2c25c81b..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -""" -Wraps the Langchain Agents SDK tracer to integrate with our Telemetry Solution. -""" - -from .tracer_instrumentor import CustomLangChainInstrumentor - -__all__ = ["CustomLangChainInstrumentor"] - -# This is a namespace package -__path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/message_mapper.py b/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/message_mapper.py deleted file mode 100644 index 73c21d1a..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/message_mapper.py +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -"""Maps LangChain messages to A365 versioned message format. - -LangChain provides ``BaseMessage`` objects (``HumanMessage``, ``AIMessage``, -``SystemMessage``, ``ToolMessage``) in ``run.inputs["messages"]`` and -``run.outputs["generations"]``. This mapper converts them to the A365 -versioned format (``InputMessages`` / ``OutputMessages``). -""" - -from __future__ import annotations - -import logging -from collections.abc import Iterable, Mapping -from typing import Any - -from langchain_core.messages import BaseMessage - -from microsoft_agents_a365.observability.core.message_utils import serialize_messages -from microsoft_agents_a365.observability.core.models.messages import ( - ChatMessage, - InputMessages, - MessagePart, - MessageRole, - OutputMessage, - OutputMessages, - TextPart, - ToolCallRequestPart, - ToolCallResponsePart, -) - -logger = logging.getLogger(__name__) - -_ROLE_MAP: dict[str, MessageRole] = { - "human": MessageRole.USER, - "user": MessageRole.USER, - "ai": MessageRole.ASSISTANT, - "assistant": MessageRole.ASSISTANT, - "system": MessageRole.SYSTEM, - "tool": MessageRole.TOOL, -} - - -def map_input_messages(inputs: Mapping[str, Any] | None) -> str | None: - """Map LangChain input messages to a serialized A365 InputMessages JSON string. - - Args: - inputs: The ``run.inputs`` mapping from a LangChain run. - - Returns: - Serialized InputMessages JSON string, or None if no messages found. - """ - if not inputs or not isinstance(inputs, Mapping): - return None - - multiple_messages = inputs.get("messages") - if not multiple_messages or not isinstance(multiple_messages, Iterable): - return None - - first_messages = next(iter(multiple_messages), None) - if not first_messages: - return None - - # Normalize to a list - if isinstance(first_messages, BaseMessage): - first_messages = [first_messages] - elif not isinstance(first_messages, list): - return None - - chat_messages: list[ChatMessage] = [] - for msg in first_messages: - mapped = _map_base_message(msg) - if mapped is not None: - chat_messages.append(mapped) - - if not chat_messages: - return None - - return serialize_messages(InputMessages(messages=chat_messages)) - - -def map_output_messages(outputs: Mapping[str, Any] | None) -> str | None: - """Map LangChain output messages to a serialized A365 OutputMessages JSON string. - - Args: - outputs: The ``run.outputs`` mapping from a LangChain run. - - Returns: - Serialized OutputMessages JSON string, or None if no messages found. - """ - if not outputs or not isinstance(outputs, Mapping): - return None - - multiple_generations = outputs.get("generations") - if not multiple_generations or not isinstance(multiple_generations, Iterable): - return None - - first_generations = next(iter(multiple_generations), None) - if not first_generations or not isinstance(first_generations, Iterable): - return None - - output_messages: list[OutputMessage] = [] - for generation in first_generations: - if not isinstance(generation, Mapping): - continue - message_data = generation.get("message") - if message_data is None: - continue - - mapped = _map_to_output_message(message_data, generation) - if mapped is not None: - output_messages.append(mapped) - - if not output_messages: - return None - - return serialize_messages(OutputMessages(messages=output_messages)) - - -# --------------------------------------------------------------------------- -# Internal helpers -# --------------------------------------------------------------------------- - - -def _map_role( - msg: BaseMessage | Mapping[str, Any], default: MessageRole = MessageRole.USER -) -> MessageRole: - """Extract the role from a LangChain message.""" - if isinstance(msg, BaseMessage): - role_str = msg.type - elif isinstance(msg, Mapping): - # Direct type field (e.g. "human", "ai", "system", "tool") - role_str = msg.get("type", "") - # LC serialization uses "constructor" as type with role in kwargs - if role_str == "constructor": - kwargs = msg.get("kwargs", {}) - role_str = kwargs.get("type", "") if isinstance(kwargs, Mapping) else "" - # Also check "role" field - if not role_str or role_str not in _ROLE_MAP: - role_str = msg.get("role", role_str) - else: - role_str = "" - return _ROLE_MAP.get(role_str.lower(), default) - - -def _extract_parts(msg: BaseMessage | Mapping[str, Any]) -> list[MessagePart]: - """Extract message parts from a LangChain message.""" - parts: list[MessagePart] = [] - - # Extract content and tool_calls - if isinstance(msg, BaseMessage): - content = msg.content - tool_calls = getattr(msg, "tool_calls", None) - msg_type = msg.type - tool_call_id = getattr(msg, "tool_call_id", None) - elif isinstance(msg, Mapping): - # Handle LC serialization: {"type": "constructor", "kwargs": {content, type, ...}} - kwargs = msg.get("kwargs", {}) if msg.get("type") == "constructor" else msg - if not isinstance(kwargs, Mapping): - kwargs = msg - content = kwargs.get("content", "") or msg.get("content", "") - tool_calls = kwargs.get("tool_calls") or msg.get("tool_calls") - msg_type = kwargs.get("type", "") or msg.get("type", "") - tool_call_id = kwargs.get("tool_call_id") or msg.get("tool_call_id") - else: - return parts - - # Tool response (from ToolMessage) — handle before text to avoid double-counting - if msg_type == "tool": - response = content if isinstance(content, str) else str(content) if content else "" - if response or tool_call_id: - parts.append(ToolCallResponsePart(id=tool_call_id, response=response)) - return parts - - # Text content - if content and isinstance(content, str) and content.strip(): - parts.append(TextPart(content=content)) - - # Tool calls (from AIMessage.tool_calls) - if tool_calls and isinstance(tool_calls, list): - for tc in tool_calls: - if not isinstance(tc, Mapping): - continue - name = tc.get("name") - if not name: - continue - args = tc.get("args") - args_str = None - if args is not None: - import json - - try: - args_str = json.dumps(args) if not isinstance(args, str) else args - except (TypeError, ValueError): - logger.debug("Failed to serialize tool call args for '%s': %s", name, args) - args_str = str(args) - - parts.append( - ToolCallRequestPart( - name=name, - id=tc.get("id"), - arguments=args_str, - ) - ) - - return parts - - -def _map_base_message(msg: BaseMessage | Mapping[str, Any]) -> ChatMessage | None: - """Map a single LangChain message to an A365 ChatMessage.""" - role = _map_role(msg) - parts = _extract_parts(msg) - if not parts: - return None - - name = None - if isinstance(msg, BaseMessage): - name = getattr(msg, "name", None) - - return ChatMessage(role=role, parts=parts, name=name) - - -def _map_to_output_message( - message_data: BaseMessage | Mapping[str, Any], - generation: Mapping[str, Any], -) -> OutputMessage | None: - """Map a LangChain generation to an A365 OutputMessage.""" - role = _map_role(message_data, default=MessageRole.ASSISTANT) - parts = _extract_parts(message_data) - if not parts: - return None - - # Extract finish_reason from generation metadata - finish_reason = None - gen_info = generation.get("generation_info") - if isinstance(gen_info, Mapping): - finish_reason = gen_info.get("finish_reason") - - return OutputMessage(role=role, parts=parts, finish_reason=finish_reason) diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/tracer.py b/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/tracer.py deleted file mode 100644 index 4cbc2a00..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/tracer.py +++ /dev/null @@ -1,279 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -import logging -import re -from collections import OrderedDict -from collections.abc import Iterator -from itertools import chain -from threading import RLock -from typing import ( - TYPE_CHECKING, - Any, - cast, -) -from uuid import UUID - -from langchain_core.tracers import BaseTracer, LangChainTracer -from langchain_core.tracers.schemas import Run -from microsoft_agents_a365.observability.core.constants import ( - GEN_AI_AGENT_NAME_KEY, - INVOKE_AGENT_OPERATION_NAME, -) -from microsoft_agents_a365.observability.core.inference_operation_type import InferenceOperationType -from microsoft_agents_a365.observability.core.utils import ( - DictWithLock, - as_utc_nano, - flatten, - record_exception, -) -from opentelemetry import context as context_api -from opentelemetry import trace as trace_api -from opentelemetry.context import ( - _SUPPRESS_INSTRUMENTATION_KEY, - get_value, -) -from opentelemetry.trace import Span -from opentelemetry.util.types import AttributeValue - -from microsoft_agents_a365.observability.extensions.langchain.utils import ( - IGNORED_EXCEPTION_PATTERNS, - add_operation_type, - function_calls, - input_messages, - invocation_parameters, - invoke_agent_input_message, - invoke_agent_output_message, - llm_provider, - metadata, - model_name, - output_messages, - prompts, - token_counts, - tools, -) - -logger = logging.getLogger(__name__) -logger.addHandler(logging.NullHandler()) - - -CONTEXT_ATTRIBUTES = ( - "session.id", - "user.id", - "metadata", - "tag.tags", - "llm.prompt_template.template", - "llm.prompt_template.variables", - "llm.prompt_template.version", -) - - -class CustomLangChainTracer(BaseTracer): - _MAX_TRACKED_RUNS = 10000 - - __slots__ = ( - "_tracer", - "_separate_trace_from_runtime_context", - "_spans_by_run", - ) - - def __init__( - self, - tracer: trace_api.Tracer, - separate_trace_from_runtime_context: bool, - *args: Any, - **kwargs: Any, - ) -> None: - """Initialize the CustomLangChainTracer. - - Args: - tracer: The OpenTelemetry tracer for creating spans. - separate_trace_from_runtime_context: When True, always start a new - trace for each span without a parent, isolating it from any - existing trace in the runtime context. - *args: Positional arguments forwarded to BaseTracer. - **kwargs: Keyword arguments forwarded to BaseTracer. - """ - super().__init__(*args, **kwargs) - if TYPE_CHECKING: - # check that `run_map` still exists in parent class - assert self.run_map - self.run_map = DictWithLock[str, Run](self.run_map) - self._tracer = tracer - self._separate_trace_from_runtime_context = separate_trace_from_runtime_context - self._spans_by_run: OrderedDict[UUID, Span] = OrderedDict() - self._lock = RLock() # handlers may be run in a thread by langchain - - def get_span(self, run_id: UUID) -> Span | None: - with self._lock: - return self._spans_by_run.get(run_id) - - @staticmethod - def _cap_ordered_dict(d: OrderedDict, max_size: int) -> None: - """Evict oldest entries from an OrderedDict to stay within max_size.""" - while len(d) > max_size: - d.popitem(last=False) - - def _start_trace(self, run: Run) -> None: - self.run_map[str(run.id)] = run - if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY): - return - with self._lock: - parent_context = ( - trace_api.set_span_in_context(parent) - if (parent_run_id := run.parent_run_id) - and (parent := self._spans_by_run.get(parent_run_id)) - else (context_api.Context() if self._separate_trace_from_runtime_context else None) - ) - # We can't use real time because the handler may be - # called in a background thread. - start_time_utc_nano = as_utc_nano(run.start_time) - - # Determine span name based on run type - if run.run_type == "chain" and run.name == "LangGraph": - span_name = f"invoke_agent {run.name}" - elif run.run_type.lower() == "tool": - span_name = f"execute_tool {run.name}" - else: - span_name = run.name - - span = self._tracer.start_span( - name=span_name, - context=parent_context, - start_time=start_time_utc_nano, - ) - - # The following line of code is commented out to serve as a reminder that in a system - # of callbacks, attaching the context can be hazardous because there is no guarantee - # that the context will be detached. An error could happen between callbacks leaving - # the context attached forever, and all future spans will use it as parent. What's - # worse is that the error could have also prevented the span from being exported, - # leaving all future spans as orphans. That is a very bad scenario. - # token = context_api.attach(context) - with self._lock: - self._spans_by_run[run.id] = span - self._cap_ordered_dict(self._spans_by_run, self._MAX_TRACKED_RUNS) - - def _end_trace(self, run: Run) -> None: - self.run_map.pop(str(run.id), None) - if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY): - return - with self._lock: - span = self._spans_by_run.pop(run.id, None) - if span: - try: - _update_span(span, run) - except Exception: - logger.exception("Failed to update span with run data.") - # We can't use real time because the handler may be - # called in a background thread. - end_time_utc_nano = as_utc_nano(run.end_time) if run.end_time else None - span.end(end_time=end_time_utc_nano) - - def _persist_run(self, run: Run) -> None: - pass - - def on_llm_error(self, error: BaseException, *args: Any, run_id: UUID, **kwargs: Any) -> Run: - with self._lock: - span = self._spans_by_run.get(run_id) - if span: - record_exception(span, error) - return super().on_llm_error(error, *args, run_id=run_id, **kwargs) - - def on_chain_error(self, error: BaseException, *args: Any, run_id: UUID, **kwargs: Any) -> Run: - with self._lock: - span = self._spans_by_run.get(run_id) - if span: - record_exception(span, error) - return super().on_chain_error(error, *args, run_id=run_id, **kwargs) - - def on_retriever_error( - self, error: BaseException, *args: Any, run_id: UUID, **kwargs: Any - ) -> Run: - with self._lock: - span = self._spans_by_run.get(run_id) - if span: - record_exception(span, error) - return super().on_retriever_error(error, *args, run_id=run_id, **kwargs) - - def on_tool_error(self, error: BaseException, *args: Any, run_id: UUID, **kwargs: Any) -> Run: - with self._lock: - span = self._spans_by_run.get(run_id) - if span: - record_exception(span, error) - return super().on_tool_error(error, *args, run_id=run_id, **kwargs) - - def on_chat_model_start(self, *args: Any, **kwargs: Any) -> Run: - """Handle chat model start events. - - Delegates to ``LangChainTracer.on_chat_model_start`` to obtain correct - chat-formatted spans. The ``BaseTracer`` implementation requires setting - an internal ``_schema_format`` flag; delegating to ``LangChainTracer`` - avoids depending on that private attribute. - """ - return LangChainTracer.on_chat_model_start(self, *args, **kwargs) # type: ignore - - -def get_attributes_from_context() -> Iterator[tuple[str, AttributeValue]]: - for ctx_attr in CONTEXT_ATTRIBUTES: - if (val := get_value(ctx_attr)) is not None: - yield ctx_attr, cast(AttributeValue, val) - - -def _update_span(span: Span, run: Run) -> None: - # If there is no error or if there is an agent control exception, set the span to OK - if run.error is None or any( - re.match(pattern, run.error) for pattern in IGNORED_EXCEPTION_PATTERNS - ): - span.set_status(trace_api.StatusCode.OK) - else: - span.set_status(trace_api.Status(trace_api.StatusCode.ERROR, run.error)) - - span.set_attributes(dict(get_attributes_from_context())) - - if run.run_type == "llm" and run.outputs.get("llm_output").get("id").startswith("chat"): - span.update_name(f"{InferenceOperationType.CHAT.value.lower()} {span.name}") - is_invoke_agent = span.name.startswith(INVOKE_AGENT_OPERATION_NAME) - - # If this is an invoke_agent span, update span name with agent name - if is_invoke_agent: - agent_name = None - if hasattr(span, "_attributes") and span._attributes: - agent_name = span._attributes.get(GEN_AI_AGENT_NAME_KEY) - if agent_name: - span.update_name(f"{INVOKE_AGENT_OPERATION_NAME} {agent_name}") - - # For invoke_agent spans, add input/output messages - if is_invoke_agent: - span.set_attributes( - dict( - flatten( - chain( - add_operation_type(run), - invoke_agent_input_message(run.inputs), - invoke_agent_output_message(run.outputs), - metadata(run), - ) - ) - ) - ) - else: - span.set_attributes( - dict( - flatten( - chain( - add_operation_type(run), - prompts(run.inputs), - input_messages(run.inputs), - output_messages(run.outputs), - invocation_parameters(run), - llm_provider(run.extra), - model_name(run.outputs, run.extra), - token_counts(run.outputs), - function_calls(run.outputs), - tools(run), - metadata(run), - ) - ) - ) - ) diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/tracer_instrumentor.py b/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/tracer_instrumentor.py deleted file mode 100644 index 948ee59c..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/tracer_instrumentor.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -from __future__ import annotations - -import logging -from collections.abc import Callable, Collection -from typing import Any -from uuid import UUID - -import langchain_core -import opentelemetry.trace as optel_trace -from langchain_core.callbacks import BaseCallbackManager -from microsoft_agents_a365.observability.core.config import ( - get_tracer, - get_tracer_provider, - is_configured, -) -from opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.trace import Span -from wrapt import wrap_function_wrapper - -from microsoft_agents_a365.observability.extensions.langchain.tracer import CustomLangChainTracer - -logger = logging.getLogger(__name__) - -_INSTRUMENTS: str = "langchain_core >= 1.2.0" - - -class CustomLangChainInstrumentor(BaseInstrumentor): - """ - Minimal instrumentor that attaches a TraceForLangChain to every new - LangChain BaseCallbackManager so runs produce OpenTelemetry spans. - """ - - def __init__(self) -> None: - if not is_configured(): - raise RuntimeError( - "Tracing SDK is not configured. Configure it before using this instrumentor." - ) - super().__init__() - self._tracer: CustomLangChainTracer | None = None - self._original_cb_init: Callable[..., None] | None = None - self.instrument() - - # ---- BaseInstrumentor API ------------------------------------------------- - - def instrumentation_dependencies(self) -> Collection[str]: - return (_INSTRUMENTS,) - - def _instrument(self, **kwargs: Any) -> None: - tracer_name: str | None = kwargs.get("tracer_name") - tracer_version: str | None = kwargs.get("tracer_version") - - # Prefer the Agent 365 tracer; fall back to OpenTelemetry’s default if needed. - try: - tracer = get_tracer(tracer_name, tracer_version) - except Exception: - tracer = optel_trace.get_tracer(tracer_name, tracer_version) - - # Ensure tracer provider exists (ignore returned value; side-effect is enough). - try: - get_tracer_provider() - except Exception: - optel_trace.get_tracer_provider() - - self._tracer = CustomLangChainTracer( - tracer, - bool(kwargs.get("separate_trace_from_runtime_context")), - ) - - # Save and wrap BaseCallbackManager.__init__ to attach the processor once per instance. - self._original_cb_init = langchain_core.callbacks.BaseCallbackManager.__init__ - wrap_function_wrapper( - module="langchain_core.callbacks", - name="BaseCallbackManager.__init__", - wrapper=_BaseCallbackManagerInit(self._tracer), - ) - - def _uninstrument(self, **kwargs: Any) -> None: - # Restore original constructor if we wrapped it. - if self._original_cb_init is not None: - langchain_core.callbacks.BaseCallbackManager.__init__ = self._original_cb_init # type: ignore[assignment] - self._original_cb_init = None - self._tracer = None - - # ---- Helpers used by module-level functions ------------------------------- - - def get_span(self, run_id: UUID) -> Span | None: - """Return the span for a specific LangChain run_id, if available.""" - if not self._tracer: - logger.warning("Missing tracer; call InstrumentorForLangChain().instrument() first.") - return None - # TraceForLangChain is expected to expose get_span(run_id). - get_span_fn = getattr(self._tracer, "get_span", None) - return get_span_fn(run_id) if callable(get_span_fn) else None - - def get_ancestors(self, run_id: UUID) -> list[Span]: - """Return ancestor spans from the run’s parent up to the root (nearest first).""" - if not self._tracer: - logger.warning("Missing tracer; call InstrumentorForLangChain().instrument() first.") - return [] - - # Expect the processor to keep a run_map with parent linkage (string keys). - run_map = getattr(self._tracer, "run_map", {}) or {} - ancestors: list[Span] = [] - - run = run_map.get(str(run_id)) - if not run: - return ancestors - - ancestor_id = getattr(run, "parent_run_id", None) - while ancestor_id: - span = self.get_span(ancestor_id) - if span: - ancestors.append(span) - run = run_map.get(str(ancestor_id)) - ancestor_id = getattr(run, "parent_run_id", None) if run else None - - return ancestors - - -class _BaseCallbackManagerInit: - """Post-constructor hook that adds the TraceProcessor once (inheritable).""" - - __slots__ = ("_processor",) - - def __init__(self, processor: CustomLangChainTracer): - self._processor = processor - - def __call__( - self, - wrapped: Callable[..., None], - instance: BaseCallbackManager, - args: tuple[Any, ...], - kwargs: dict[str, Any], - ) -> None: - wrapped(*args, **kwargs) # run original __init__ - # Avoid duplicates: only add if a handler of the same type isn’t present. - if not any(isinstance(h, type(self._processor)) for h in instance.inheritable_handlers): - instance.add_handler(self._processor, inherit=True) - - -# ------------------------------ Convenience APIs ------------------------------ - - -def _current_parent_run_id() -> UUID | None: - """Best-effort: fetch current parent run_id from langchain runtime context.""" - config = langchain_core.runnables.config.var_child_runnable_config.get() - if not isinstance(config, dict): - return None - for v in config.values(): - if isinstance(v, langchain_core.callbacks.BaseCallbackManager): - if v.parent_run_id: - return v.parent_run_id - return None - - -def get_current_span() -> Span | None: - """Return the current context’s parent span, if any.""" - run_id = _current_parent_run_id() - if not run_id: - return None - return CustomLangChainInstrumentor().get_span(run_id) - - -def get_ancestor_spans() -> list[Span]: - """ - Return ancestor spans for the current context (immediate parent → root). - """ - run_id = _current_parent_run_id() - if not run_id: - return [] - return CustomLangChainInstrumentor().get_ancestors(run_id) diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/utils.py b/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/utils.py deleted file mode 100644 index 6114dba7..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/utils.py +++ /dev/null @@ -1,646 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -import json -from collections.abc import Iterable, Iterator, Mapping -from copy import deepcopy -from typing import Any - -from langchain_core.messages import BaseMessage -from langchain_core.tracers.schemas import Run -from microsoft_agents_a365.observability.core.constants import ( - EXECUTE_TOOL_OPERATION_NAME, - GEN_AI_INPUT_MESSAGES_KEY, - GEN_AI_OPERATION_NAME_KEY, - GEN_AI_OUTPUT_MESSAGES_KEY, - GEN_AI_PROVIDER_NAME_KEY, - GEN_AI_REQUEST_MODEL_KEY, - GEN_AI_RESPONSE_FINISH_REASONS_KEY, - GEN_AI_RESPONSE_ID_KEY, - GEN_AI_SYSTEM_INSTRUCTIONS_KEY, - GEN_AI_TOOL_ARGS_KEY, - GEN_AI_TOOL_CALL_ID_KEY, - GEN_AI_TOOL_CALL_RESULT_KEY, - GEN_AI_TOOL_DESCRIPTION_KEY, - GEN_AI_TOOL_NAME_KEY, - GEN_AI_TOOL_TYPE_KEY, - GEN_AI_USAGE_INPUT_TOKENS_KEY, - GEN_AI_USAGE_OUTPUT_TOKENS_KEY, - INVOKE_AGENT_OPERATION_NAME, - SESSION_ID_KEY, -) -from microsoft_agents_a365.observability.core.inference_operation_type import InferenceOperationType -from microsoft_agents_a365.observability.core.utils import ( - get_first_value, - safe_json_dumps, - stop_on_exception, -) - -from .message_mapper import map_input_messages as _map_input -from .message_mapper import map_output_messages as _map_output - -IGNORED_EXCEPTION_PATTERNS = [ - r"^Command\(", - r"^ParentCommand\(", -] - -LANGCHAIN_SESSION_ID = "session_id" -LANGCHAIN_CONVERSATION_ID = "conversation_id" -LANGCHAIN_THREAD_ID = "thread_id" - - -@stop_on_exception -def prompts(inputs: Mapping[str, Any] | None) -> Iterator[tuple[str, list[str]]]: - """Yields prompts if present.""" - if not inputs: - return - if not isinstance(inputs, Mapping): - return - if prompts := inputs.get("prompts"): - yield GEN_AI_SYSTEM_INSTRUCTIONS_KEY, prompts - - -@stop_on_exception -def _extract_message_kwargs(message_data: Mapping[str, Any] | None) -> Iterator[[str, Any]]: - if not message_data: - return - if not isinstance(message_data, Mapping): - return - if kwargs := message_data.get("kwargs"): - if not isinstance(kwargs, Mapping): - return - if content := kwargs.get("content"): - # Just yield as-is (string or list) - yield "message.content", content - if tool_call_id := kwargs.get("tool_call_id"): - if isinstance(tool_call_id, str): - yield GEN_AI_TOOL_CALL_ID_KEY, tool_call_id - if name := kwargs.get("name"): - if isinstance(name, str): - yield "message.name", name - - -@stop_on_exception -def _extract_message_additional_kwargs( - message_data: Mapping[str, Any] | None, -) -> Iterator[tuple[str, Any]]: - if not message_data: - return - if not isinstance(message_data, Mapping): - return - if kwargs := message_data.get("kwargs"): - if not isinstance(kwargs, Mapping): - return - if additional_kwargs := kwargs.get("additional_kwargs"): - if not isinstance(additional_kwargs, Mapping): - return - if function_call := additional_kwargs.get("function_call"): - if not isinstance(function_call, Mapping): - return - if name := function_call.get("name"): - if isinstance(name, str): - yield GEN_AI_TOOL_NAME_KEY, name - if arguments := function_call.get("arguments"): - if isinstance(arguments, str): - yield GEN_AI_TOOL_ARGS_KEY, arguments - else: - yield GEN_AI_TOOL_ARGS_KEY, safe_json_dumps(arguments) - - -@stop_on_exception -def _get_tool_call(tool_call: Mapping[str, Any] | None) -> Iterator[tuple[str, Any]]: - if not tool_call: - return - if not isinstance(tool_call, Mapping): - return - - # id - id_ = tool_call.get("id") - if id_ is not None: - yield GEN_AI_TOOL_CALL_ID_KEY, id_ - - fn = tool_call.get("function") - name = None - arguments = None - - if isinstance(fn, Mapping): - name = fn.get("name") - arguments = fn.get("arguments") - else: - name = tool_call.get("name") - arguments = tool_call.get("args") - - # name - if name is not None and isinstance(name, str): - yield GEN_AI_TOOL_NAME_KEY, name - - # arguments -> always emit a JSON string - if arguments is not None: - if isinstance(arguments, str): - args_json = arguments - else: - args_json = safe_json_dumps(arguments) - yield GEN_AI_TOOL_ARGS_KEY, args_json - - -def _process_tool_calls(tool_calls: Any) -> str: - """Return all tool calls as a single compact string (JSON-joined), or '' if none.""" - if not tool_calls: - return "" - if not isinstance(tool_calls, Iterable): - return "" - - parts: list[str] = [] - for tool_call in tool_calls: - data = dict(_get_tool_call(tool_call)) - if data: - # Compact, stable representation - parts.append(safe_json_dumps(data, separators=(",", ":"), sort_keys=True)) - - return "; ".join(parts) - - -@stop_on_exception -def _extract_message_tool_calls( - message_data: Mapping[str, Any] | None, -) -> Iterator[tuple[str, str]]: - if not message_data: - return - if not isinstance(message_data, Mapping): - return - - # Collect tool_calls from multiple possible locations - all_tool_calls: list[str] = [] - - def collect(calls: Any) -> None: - if calls: - processed = _process_tool_calls(calls) - if processed: - if isinstance(processed, list): - all_tool_calls.extend(map(str, processed)) - else: - all_tool_calls.append(str(processed)) - - collect(message_data.get("tool_calls")) - - if kwargs := message_data.get("kwargs"): - if not isinstance(kwargs, Mapping): - return - collect(kwargs.get("tool_calls")) - - if additional_kwargs := kwargs.get("additional_kwargs"): - if not isinstance(additional_kwargs, Mapping): - return - collect(additional_kwargs.get("tool_calls")) - - if all_tool_calls: - # Return all as a single string (comma-separated) - yield "message.tool_calls", ", ".join(all_tool_calls) - - -@stop_on_exception -def _parse_message_data(message_data: Mapping[str, Any] | None) -> Iterator[tuple[str, Any]]: - """Parses message data to grab message role, content, etc.""" - yield from _extract_message_kwargs(message_data) - yield from _extract_message_additional_kwargs(message_data) - yield from _extract_message_tool_calls(message_data) - - -@stop_on_exception -def input_messages( - inputs: Mapping[str, Any] | None, -) -> Iterator[tuple[str, str]]: - """Yields input messages in A365 versioned format.""" - if not inputs: - return - - mapped = _map_input(inputs) - if mapped is not None: - yield GEN_AI_INPUT_MESSAGES_KEY, mapped - - -@stop_on_exception -def metadata(run: Run) -> Iterator[tuple[str, str]]: - """ - Takes the LangChain chain metadata and adds it to the trace - """ - if not run.extra or not (metadata := run.extra.get("metadata")): - return - if not isinstance(metadata, Mapping): - return - if session_id := ( - metadata.get(LANGCHAIN_SESSION_ID) - or metadata.get(LANGCHAIN_CONVERSATION_ID) - or metadata.get(LANGCHAIN_THREAD_ID) - ): - yield SESSION_ID_KEY, session_id - - -@stop_on_exception -def output_messages( - outputs: Mapping[str, Any] | None, -) -> Iterator[tuple[str, str]]: - """Yields output messages in A365 versioned format.""" - if not outputs: - return - if not isinstance(outputs, Mapping): - return - # Preserve response ID extraction - output_type = outputs.get("type") - if output_type and output_type.lower() == "llmresult": - llm_output = outputs.get("llm_output") - if llm_output and hasattr(llm_output, "get"): - response_id = llm_output.get("id") - if response_id: - yield GEN_AI_RESPONSE_ID_KEY, response_id - - mapped = _map_output(outputs) - if mapped is not None: - yield GEN_AI_OUTPUT_MESSAGES_KEY, mapped - - -@stop_on_exception -def invocation_parameters(run: Run) -> Iterator[tuple[str, str]]: - """Yields invocation parameters if present.""" - if run.run_type.lower() != "llm": - return - if not (extra := run.extra): - return - if not isinstance(extra, Mapping): - return - if invocation_parameters := extra.get("invocation_params"): - if not isinstance(invocation_parameters, Mapping): - return - tools = invocation_parameters.get("tools", []) - for idx, tool in enumerate(tools): - yield f"{GEN_AI_TOOL_ARGS_KEY}.{idx}", safe_json_dumps(tool) - - -@stop_on_exception -def llm_provider(extra: Mapping[str, Any] | None) -> Iterator[tuple[str, str]]: - if not extra: - return - if (meta := extra.get("metadata")) and (ls_provider := meta.get("ls_provider")): - ls_provider_lower = ls_provider.lower() - yield GEN_AI_PROVIDER_NAME_KEY, ls_provider_lower - - -@stop_on_exception -def model_name( - outputs: Mapping[str, Any] | None, - extra: Mapping[str, Any] | None, -) -> Iterator[tuple[str, str]]: - """Yields model name if present.""" - if ( - outputs - and hasattr(outputs, "get") - and (llm_output := outputs.get("llm_output")) - and hasattr(llm_output, "get") - ): - for key in "model_name", "model": - if name := str(llm_output.get(key) or "").strip(): - yield GEN_AI_REQUEST_MODEL_KEY, name - return - if not extra: - return - if not isinstance(extra, Mapping): - return - if ( - (metadata := extra.get("metadata")) - and hasattr(metadata, "get") - and (ls_model_name := str(metadata.get("ls_model_name") or "").strip()) - ): - yield GEN_AI_REQUEST_MODEL_KEY, ls_model_name - return - if not (invocation_params := extra.get("invocation_params")): - return - for key in ["model_name", "model"]: - if name := invocation_params.get(key): - yield GEN_AI_REQUEST_MODEL_KEY, name - return - - -@stop_on_exception -def token_counts(outputs: Mapping[str, Any] | None) -> Iterator[tuple[str, int]]: - """Yields token count information if present.""" - if not (token_usage := (parse_token_usage_for_non_streaming_outputs(outputs))): - return - for attribute_name, keys in [ - ( - GEN_AI_USAGE_INPUT_TOKENS_KEY, - ( - "prompt_tokens", - "input_tokens", # Anthropic-specific key - "prompt_token_count", # Gemini-specific key - https://ai.google.dev/gemini-api/docs/tokens?lang=python - ), - ), - ( - GEN_AI_USAGE_OUTPUT_TOKENS_KEY, - ( - "completion_tokens", - "output_tokens", # Anthropic-specific key - "candidates_token_count", # Gemini-specific key - ), - ), - ]: - if (token_count := get_first_value(token_usage, keys)) is not None: - yield attribute_name, token_count - - # OpenAI - for attribute_name, details_key, keys in [ - ( - GEN_AI_RESPONSE_FINISH_REASONS_KEY, - "completion_tokens_details", - ("reasoning_tokens",), - ), - ]: - if (details := token_usage.get(details_key)) is not None: - if (token_count := get_first_value(details, keys)) is not None: - yield attribute_name, token_count - - # maps langchain_core.messages.ai.UsageMetadata object - for attribute_name, details_key_or_none, keys in [ - (GEN_AI_USAGE_INPUT_TOKENS_KEY, None, ("input_tokens",)), - (GEN_AI_USAGE_OUTPUT_TOKENS_KEY, None, ("output_tokens",)), - ( - GEN_AI_RESPONSE_FINISH_REASONS_KEY, - "output_token_details", - ("reasoning",), - ), - ]: - details = token_usage.get(details_key_or_none) if details_key_or_none else token_usage - if details is not None: - if (token_count := get_first_value(details, keys)) is not None: - yield attribute_name, token_count - - -def parse_token_usage_for_non_streaming_outputs( - outputs: Mapping[str, Any] | None, -) -> Any: - """ - Parses output to get token usage information for non-streaming LLMs, i.e., - when `stream_usage` is set to false. - """ - if ( - outputs - and hasattr(outputs, "get") - and (llm_output := outputs.get("llm_output")) - and hasattr(llm_output, "get") - and ( - token_usage := get_first_value( - llm_output, - ( - "token_usage", - "usage", # Anthropic-specific key - ), - ) - ) - ): - return token_usage - return None - - -@stop_on_exception -def function_calls(outputs: Mapping[str, Any] | None) -> Iterator[tuple[str, str]]: - """ - Extract a single OpenAI-style function call from model outputs and emit - GenAI tool attributes as (key, value) pairs. Arguments/result are JSON strings. - - """ - if not outputs: - return - if not isinstance(outputs, Mapping): - return - - try: - # Typical OpenAI LangChain shape: - # outputs["generations"][0][0]["message"]["kwargs"]["additional_kwargs"]["function_call"] - fc = deepcopy( - outputs["generations"][0][0]["message"]["kwargs"]["additional_kwargs"]["function_call"] - ) - except Exception: - return - - if not isinstance(fc, dict): - return - - # Tool type (explicit) - yield GEN_AI_OPERATION_NAME_KEY, EXECUTE_TOOL_OPERATION_NAME - yield GEN_AI_TOOL_TYPE_KEY, "function" - - name = fc.get("name") - if isinstance(name, str): - yield GEN_AI_TOOL_NAME_KEY, name - - desc = fc.get("description") - if isinstance(desc, str): - yield GEN_AI_TOOL_DESCRIPTION_KEY, desc - - call_id = fc.get("id") - if isinstance(call_id, str): - yield GEN_AI_TOOL_CALL_ID_KEY, call_id - - args = fc.get("arguments") - if args is not None: - if isinstance(args, str): - # If it's a JSON string, try to parse then re-dump for normalization - try: - args_json = safe_json_dumps(json.loads(args)) - except Exception: - # Not valid JSON; store raw string - args_json = safe_json_dumps(args) - else: - args_json = safe_json_dumps(args) - yield GEN_AI_TOOL_ARGS_KEY, args_json - - result = fc.get("result") - if result is not None: - yield GEN_AI_TOOL_CALL_RESULT_KEY, safe_json_dumps(result) - - -@stop_on_exception -def tools(run: Run) -> Iterator[tuple[str, str]]: - """Yields tool attributes if present.""" - if run.run_type.lower() != "tool": - return - if not (serialized := run.serialized): - return - if not isinstance(serialized, Mapping): - return - yield GEN_AI_TOOL_TYPE_KEY, "extension" - if name := serialized.get("name"): - yield GEN_AI_TOOL_NAME_KEY, name - if description := serialized.get("description"): - yield GEN_AI_TOOL_DESCRIPTION_KEY, description - - # Extract tool call ID from run.extra (LangGraph stores it there) - if run.extra and hasattr(run.extra, "get"): - if tool_call_id := run.extra.get("tool_call_id"): - yield GEN_AI_TOOL_CALL_ID_KEY, tool_call_id - - # Extract tool arguments from inputs - if run.inputs and hasattr(run.inputs, "get"): - # LangGraph wraps args in 'input' key as a string - if input_val := run.inputs.get("input"): - if isinstance(input_val, str): - yield GEN_AI_TOOL_ARGS_KEY, input_val - else: - yield GEN_AI_TOOL_ARGS_KEY, safe_json_dumps(input_val) - - # Extract tool result from outputs - if run.outputs and hasattr(run.outputs, "get"): - if result := run.outputs.get("output"): - # Handle ToolMessage or BaseMessage objects - if isinstance(result, BaseMessage): - result_content = result.content if hasattr(result, "content") else str(result) - elif hasattr(result, "content"): - result_content = result.content - elif isinstance(result, str): - result_content = result - else: - result_content = safe_json_dumps(result) - yield GEN_AI_TOOL_CALL_RESULT_KEY, result_content - - -def add_operation_type(run: Run) -> Iterator[tuple[str, str]]: - """Yields operation type based on run type.""" - run_type = run.run_type.lower() - if run_type == "llm": - yield GEN_AI_OPERATION_NAME_KEY, InferenceOperationType.CHAT.value.lower() - elif run_type == "chat_model": - yield GEN_AI_OPERATION_NAME_KEY, InferenceOperationType.CHAT.value.lower() - elif run_type == "tool": - yield GEN_AI_OPERATION_NAME_KEY, EXECUTE_TOOL_OPERATION_NAME - elif run_type == "chain" and run.name.startswith(INVOKE_AGENT_OPERATION_NAME): - yield GEN_AI_OPERATION_NAME_KEY, INVOKE_AGENT_OPERATION_NAME - - -def _extract_content_from_message(message: Any) -> str | None: - """Extract content from a LangChain message object or dict.""" - if message is None: - return None - - # Handle BaseMessage objects - if isinstance(message, BaseMessage): - return message.content if hasattr(message, "content") else None - - # Handle dict-like messages - if hasattr(message, "get"): - # Direct content field - if content := message.get("content"): - return content - # Nested in kwargs - if kwargs := message.get("kwargs"): - if hasattr(kwargs, "get") and (content := kwargs.get("content")): - return content - - return None - - -def _get_message_role(message: Any) -> str | None: - """Extract role from a LangChain message object or dict.""" - if message is None: - return None - - # Handle BaseMessage objects - if isinstance(message, BaseMessage): - return message.type if hasattr(message, "type") else None - - # Handle dict-like messages - if hasattr(message, "get"): - # Check various role indicators - if role := message.get("role"): - return role - if msg_type := message.get("type"): - return msg_type - # Check id field for type info (e.g., "HumanMessage", "AIMessage") - if id_field := message.get("id"): - if isinstance(id_field, list) and len(id_field) > 0: - type_name = id_field[-1] - if "Human" in type_name: - return "human" - elif "AI" in type_name or "Assistant" in type_name: - return "ai" - elif "System" in type_name: - return "system" - - return None - - -@stop_on_exception -def invoke_agent_input_message( - inputs: Mapping[str, Any] | None, -) -> Iterator[tuple[str, str]]: - """ - Extract the user input message for invoke_agent spans (LangGraph root). - We want to find the first user/human message content. - """ - if not inputs: - return - - if not isinstance(inputs, Mapping): - return - - messages = inputs.get("messages") - if not messages: - return - - # Handle nested list structure: [[msg1, msg2, ...]] - if isinstance(messages, list) and len(messages) > 0: - first_item = messages[0] - # If first item is also a list, unwrap it - if isinstance(first_item, list): - messages = first_item - - # Find the first user/human message - if isinstance(messages, list): - for message in messages: - role = _get_message_role(message) - if role and role.lower() in ("human", "user"): - content = _extract_content_from_message(message) - if content: - yield GEN_AI_INPUT_MESSAGES_KEY, content - return - - # If no human message found, just get first message content - if len(messages) > 0: - content = _extract_content_from_message(messages[0]) - if content: - yield GEN_AI_INPUT_MESSAGES_KEY, content - - -@stop_on_exception -def invoke_agent_output_message( - outputs: Mapping[str, Any] | None, -) -> Iterator[tuple[str, str]]: - """ - Extract the final output message for invoke_agent spans (LangGraph root). - We want the last AI/assistant message content. - """ - if not outputs: - return - - if not isinstance(outputs, Mapping): - return - - messages = outputs.get("messages") - if not messages: - return - - # Handle nested list structure if present - if isinstance(messages, list) and len(messages) > 0: - first_item = messages[0] - if isinstance(first_item, list): - messages = first_item - - # Find the last AI/assistant message with content (not tool calls) - if isinstance(messages, list): - # Iterate in reverse to find the last AI message - for message in reversed(messages): - role = _get_message_role(message) - if role and role.lower() in ("ai", "assistant"): - content = _extract_content_from_message(message) - # Make sure it has actual content, not just tool calls - if content and isinstance(content, str) and content.strip(): - yield GEN_AI_OUTPUT_MESSAGES_KEY, content - return diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/pyproject.toml b/libraries/microsoft-agents-a365-observability-extensions-langchain/pyproject.toml deleted file mode 100644 index 4ed21eea..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/pyproject.toml +++ /dev/null @@ -1,82 +0,0 @@ -[build-system] -requires = ["setuptools>=68", "wheel", "tzdata", "tomlkit", "packaging"] -build-backend = "build_backend" - -[project] -name = "microsoft-agents-a365-observability-extensions-langchain" -dynamic = ["version"] -authors = [ - { name = "Microsoft", email = "support@microsoft.com" }, -] -description = "LangChain observability and tracing extensions for Microsoft Agent 365" -readme = "README.md" -requires-python = ">=3.11" -classifiers = [ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Operating System :: OS Independent", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Scientific/Engineering :: Artificial Intelligence", - "Topic :: System :: Monitoring", -] -license = {text = "MIT"} -keywords = ["observability", "telemetry", "tracing", "opentelemetry", "langchain", "agents", "ai"] -dependencies = [ - "microsoft-agents-a365-observability-core", - "langchain-core", - "opentelemetry-api", - "opentelemetry-sdk", - "opentelemetry-instrumentation", - "wrapt", -] - -[project.urls] -Homepage = "https://github.com/microsoft/Agent365-python" -Repository = "https://github.com/microsoft/Agent365-python" -Issues = "https://github.com/microsoft/Agent365-python/issues" -Documentation = "https://github.com/microsoft/Agent365-python/tree/main/libraries/microsoft-agents-a365-observability-extensions-langchain" - -[project.optional-dependencies] -dev = [ - "pytest", - "pytest-asyncio", - "ruff", - "black", - "mypy", -] -test = [ - "pytest", - "pytest-asyncio", -] - -[tool.setuptools.packages.find] -where = ["."] -namespaces = true - -[tool.setuptools] -license-files = ["../../LICENSE"] -include-package-data = true - -[tool.setuptools.package-data] -"*" = ["../../LICENSE"] - -[tool.black] -line-length = 100 -target-version = ['py311'] - -[tool.ruff] -line-length = 100 -target-version = "py311" - -[tool.ruff.lint.flake8-copyright] -notice-rgx = "# Copyright \\(c\\) Microsoft Corporation\\.\\r?\\n# Licensed under the MIT License\\." -min-file-size = 1 - -[tool.mypy] -python_version = "3.11" -strict = true -warn_return_any = true -warn_unused_configs = true diff --git a/libraries/microsoft-agents-a365-observability-extensions-langchain/setup.py b/libraries/microsoft-agents-a365-observability-extensions-langchain/setup.py deleted file mode 100644 index 8fbb2a49..00000000 --- a/libraries/microsoft-agents-a365-observability-extensions-langchain/setup.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -import sys -from pathlib import Path -from os import environ -from setuptools import setup - -# Get version from environment variable set by CI/CD -package_version = environ.get("AGENT365_PYTHON_SDK_PACKAGE_VERSION", "0.0.0") - -# Add versioning helper to path -helper_path = Path(__file__).parent.parent.parent / "versioning" / "helper" -sys.path.insert(0, str(helper_path)) - -from setup_utils import get_dynamic_dependencies # noqa: E402 - -# Use exact version matching for internal dependencies: -# - Internal packages get: == current_version (e.g., == 1.2.3) -# - Ensures all SDK packages must be at the same version -# - Prevents incompatibility issues from version mismatches -setup( - version=package_version, - install_requires=get_dynamic_dependencies( - use_exact_match=True, - ), -) diff --git a/pyproject.toml b/pyproject.toml index 34c1150f..30cf73c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,6 @@ build-backend = "setuptools.build_meta" members = [ "libraries/microsoft-agents-a365-notifications", "libraries/microsoft-agents-a365-observability-core", - "libraries/microsoft-agents-a365-observability-extensions-langchain", "libraries/microsoft-agents-a365-observability-extensions-openai", "libraries/microsoft-agents-a365-observability-extensions-semantickernel", "libraries/microsoft-agents-a365-observability-extensions-agentframework", @@ -29,7 +28,6 @@ exclude = [ microsoft-agents-a365-notifications = { workspace = true } microsoft-agents-a365-observability-core = { workspace = true } microsoft-agents-a365-observability-extensions-agentframework = { workspace = true } -microsoft-agents-a365-observability-extensions-langchain = { workspace = true } microsoft-agents-a365-observability-extensions-openai = { workspace = true } microsoft-agents-a365-observability-extensions-semantickernel = { workspace = true } microsoft-agents-a365-observability-hosting = { workspace = true } @@ -57,7 +55,6 @@ dev-dependencies = [ "agent-framework", "azure-identity", "openai-agents", - "langchain-openai", ] # azure-ai-projects is capped at <2.0.0 because: @@ -89,7 +86,6 @@ constraint-dependencies = [ # --- AI Frameworks --- "agent-framework >= 1.0.0", "agent-framework-core >= 1.0.0", - "langchain-core >= 0.1.0", "openai-agents >= 0.2.6", "semantic-kernel >= 1.39.3", # google-adk >=1.28.1,<2.0.0 - security remediation. Fixes CVE-2026-4810 diff --git a/tests/observability/extensions/langchain/__init__.py b/tests/observability/extensions/langchain/__init__.py deleted file mode 100644 index 1d8b4766..00000000 --- a/tests/observability/extensions/langchain/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. diff --git a/tests/observability/extensions/langchain/integration/__init__.py b/tests/observability/extensions/langchain/integration/__init__.py deleted file mode 100644 index 59e481eb..00000000 --- a/tests/observability/extensions/langchain/integration/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. diff --git a/tests/observability/extensions/langchain/integration/conftest.py b/tests/observability/extensions/langchain/integration/conftest.py deleted file mode 100644 index 1df58995..00000000 --- a/tests/observability/extensions/langchain/integration/conftest.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -"""Fixtures for LangChain observability integration tests.""" - -import os -from pathlib import Path -from typing import Any - -import pytest - -try: - from dotenv import load_dotenv - - current_file = Path(__file__) - tests_dir = current_file.parent.parent.parent.parent.parent - env_file = tests_dir / ".env" - if env_file.exists(): - load_dotenv(env_file) -except ImportError: - pass - - -def pytest_configure(config: pytest.Config) -> None: - """Add integration marker.""" - config.addinivalue_line("markers", "integration: marks tests as integration tests") - - -@pytest.fixture(scope="session") -def azure_openai_config() -> dict[str, Any]: - """Azure OpenAI configuration for integration tests.""" - api_key = os.getenv("AZURE_OPENAI_API_KEY") - endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") - deployment = os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o-mini") - api_version = os.getenv("AZURE_OPENAI_API_VERSION", "2024-08-01-preview") - - if not api_key or not endpoint: - pytest.skip("Integration tests require AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINT") - - return { - "api_key": api_key, - "endpoint": endpoint, - "deployment": deployment, - "api_version": api_version, - } - - -@pytest.fixture(scope="session") -def agent365_config() -> dict[str, Any]: - """Microsoft Agent 365 configuration for integration tests.""" - tenant_id = os.getenv("AGENT365_TEST_TENANT_ID", "4d44f041-f91e-4d00-b107-61e47b26f5a8") - agent_id = os.getenv("AGENT365_TEST_AGENT_ID", "3bccd52b-daaa-4b11-af40-47443852137c") - - if not tenant_id: - pytest.skip("Integration tests require AGENT365_TEST_TENANT_ID") - - return {"tenant_id": tenant_id, "agent_id": agent_id} diff --git a/tests/observability/extensions/langchain/integration/test_message_format.py b/tests/observability/extensions/langchain/integration/test_message_format.py deleted file mode 100644 index ae85762f..00000000 --- a/tests/observability/extensions/langchain/integration/test_message_format.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -"""Integration tests for LangChain message format mapping. - -These tests use the real A365 observability pipeline: - configure() → get_tracer_provider() → CustomLangChainInstrumentor -with a SpanCapturingExporter inside _EnrichingBatchSpanProcessor, then make -real Azure OpenAI calls via LangChain and capture the span attributes. - -These tests verify the serialized gen_ai.input.messages / gen_ai.output.messages -structured array format emitted by the observability pipeline. -""" - -import json -import time -from typing import Any - -import pytest -from opentelemetry.sdk.trace import ReadableSpan -from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult - -try: - from langchain_openai import AzureChatOpenAI -except ImportError: - pytest.skip( - "langchain-openai required for LangChain integration tests", - allow_module_level=True, - ) - -from microsoft_agents_a365.observability.core import configure, get_tracer_provider -from microsoft_agents_a365.observability.core.constants import ( - GEN_AI_INPUT_MESSAGES_KEY, - GEN_AI_OPERATION_NAME_KEY, - GEN_AI_OUTPUT_MESSAGES_KEY, -) -from microsoft_agents_a365.observability.core.exporters.enriching_span_processor import ( - _EnrichingBatchSpanProcessor, -) -from microsoft_agents_a365.observability.extensions.langchain import ( - CustomLangChainInstrumentor, -) - - -class SpanCapturingExporter(SpanExporter): - """Exporter that collects spans in-memory after enrichment.""" - - def __init__(self) -> None: - self.spans: list[ReadableSpan] = [] - - def export(self, spans: list[ReadableSpan]) -> SpanExportResult: - self.spans.extend(spans) - return SpanExportResult.SUCCESS - - def shutdown(self) -> None: - pass - - def force_flush(self, timeout_millis: int = 30000) -> bool: - return True - - -@pytest.mark.integration -class TestLangChainMessageFormat: - """Capture real LangChain span attributes and verify message structure.""" - - @pytest.fixture(autouse=True) - def setup_observability(self) -> None: - """Set up A365 observability with CustomLangChainInstrumentor.""" - if not hasattr(TestLangChainMessageFormat, "_exporter"): - configure( - service_name="integration-test-langchain", - service_namespace="agent365-tests", - logger_name="test-logger", - ) - - exporter = SpanCapturingExporter() - provider = get_tracer_provider() - provider.add_span_processor( - _EnrichingBatchSpanProcessor( - exporter, - max_queue_size=100, - schedule_delay_millis=100, - max_export_batch_size=100, - ) - ) - - # CustomLangChainInstrumentor calls instrument() in __init__ - instrumentor = CustomLangChainInstrumentor() - - TestLangChainMessageFormat._exporter = exporter - TestLangChainMessageFormat._instrumentor = instrumentor - - self.exporter = TestLangChainMessageFormat._exporter - self.exporter.spans.clear() - - @pytest.fixture - def llm(self, azure_openai_config: dict[str, Any]) -> AzureChatOpenAI: - """Create a real Azure OpenAI LangChain chat model.""" - return AzureChatOpenAI( - azure_endpoint=azure_openai_config["endpoint"], - api_key=azure_openai_config["api_key"], - azure_deployment=azure_openai_config["deployment"], - api_version=azure_openai_config["api_version"], - ) - - def _find_chat_spans(self) -> list[ReadableSpan]: - """Find exported spans that have gen_ai.input.messages.""" - get_tracer_provider().force_flush() - time.sleep(0.5) - return [ - s - for s in self.exporter.spans - if s.attributes and GEN_AI_INPUT_MESSAGES_KEY in s.attributes - ] - - @pytest.mark.asyncio - async def test_simple_chat_message_mapping(self, llm: AzureChatOpenAI) -> None: - """Simple chat: capture LangChain message format on exported spans.""" - from langchain_core.messages import HumanMessage, SystemMessage - - messages = [ - SystemMessage(content="You are a helpful assistant. Reply in one sentence."), - HumanMessage(content="What is the capital of France?"), - ] - - result = await llm.ainvoke(messages) - assert result is not None - assert len(result.content) > 0 - - chat_spans = self._find_chat_spans() - assert len(chat_spans) > 0, ( - f"No chat spans found. All spans: {[s.name for s in self.exporter.spans]}" - ) - - print(f"\n=== All exported spans ({len(self.exporter.spans)}) ===") - for s in self.exporter.spans: - attrs = dict(s.attributes or {}) - print(f" {s.name} | attrs: {list(attrs.keys())}") - - attrs = dict(chat_spans[-1].attributes or {}) - - # --- Input messages --- - raw_input = attrs[GEN_AI_INPUT_MESSAGES_KEY] - print(f"\n=== gen_ai.input.messages ===\n{raw_input}") - input_data = json.loads(raw_input) - - # Verify structured array format - assert isinstance(input_data, list) - messages_list = input_data - for msg in messages_list: - assert "role" in msg - assert "parts" in msg - print("\n ✓ Structured array format detected") - - # --- Output messages --- - raw_output = attrs.get(GEN_AI_OUTPUT_MESSAGES_KEY) - assert raw_output is not None, "gen_ai.output.messages not found" - print(f"\n=== gen_ai.output.messages ===\n{raw_output}") - output_data = json.loads(raw_output) - - assert isinstance(output_data, list) - for msg in output_data: - assert msg["role"] == "assistant" - assert any(p["type"] == "text" for p in msg["parts"]) - print("\n ✓ Structured array format detected") - - @pytest.mark.asyncio - async def test_tool_call_message_mapping(self, llm: AzureChatOpenAI) -> None: - """Tool-calling chat: capture tool_call parts in LangChain spans.""" - from langchain_core.messages import HumanMessage, SystemMessage - from langchain_core.tools import tool - - @tool - def get_weather(city: str) -> str: - """Get the current weather for a city.""" - return f"The weather in {city} is sunny, 22°C." - - llm_with_tools = llm.bind_tools([get_weather]) - - messages = [ - SystemMessage(content="You are a weather assistant. Always use the get_weather tool."), - HumanMessage(content="What's the weather in Seattle?"), - ] - - result = await llm_with_tools.ainvoke(messages) - assert result is not None - - chat_spans = self._find_chat_spans() - assert len(chat_spans) > 0 - - print(f"\n=== All exported spans ({len(self.exporter.spans)}) ===") - for s in self.exporter.spans: - attrs = dict(s.attributes or {}) - op = attrs.get(GEN_AI_OPERATION_NAME_KEY, "(none)") - print(f" {s.name} | op={op} | attrs: {list(attrs.keys())}") - - # Check all spans for message content - for span in chat_spans: - attrs = dict(span.attributes or {}) - for key in (GEN_AI_INPUT_MESSAGES_KEY, GEN_AI_OUTPUT_MESSAGES_KEY): - raw = attrs.get(key) - if raw: - print(f"\n--- {span.name} | {key} ---\n{raw}") diff --git a/tests/observability/extensions/langchain/integration/test_observability_pipeline.py b/tests/observability/extensions/langchain/integration/test_observability_pipeline.py deleted file mode 100644 index fd4551c1..00000000 --- a/tests/observability/extensions/langchain/integration/test_observability_pipeline.py +++ /dev/null @@ -1,422 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -"""End-to-end pipeline integration tests for LangChain observability. - -These tests verify the full A365 observability pipeline: - InvokeAgentScope → Inference (auto-instrumented) → ToolExecution (auto-instrumented) - -The CustomLangChainInstrumentor automatically creates inference spans for LLM -calls and execute_tool spans for tool runs. Its built-in message mapper -converts LangChain messages into the structured array A365 message format -(``[...]``) on ``gen_ai.input.messages`` and ``gen_ai.output.messages`` -span attributes. - -Wrapping the entire call in InvokeAgentScope makes all auto-instrumented spans -children of the invoke_agent span (since ``separate_trace_from_runtime_context`` -defaults to ``False``). -""" - -import json -import os -import time - -import pytest -from opentelemetry.sdk.trace import ReadableSpan -from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult - -try: - from langchain_core.messages import HumanMessage, SystemMessage - from langchain_core.tools import tool - from langchain_openai import AzureChatOpenAI -except ImportError: - pytest.skip( - "langchain-openai required for LangChain integration tests", - allow_module_level=True, - ) - -from microsoft_agents_a365.observability.core import configure, get_tracer_provider -from microsoft_agents_a365.observability.core.agent_details import AgentDetails -from microsoft_agents_a365.observability.core.constants import ( - GEN_AI_INPUT_MESSAGES_KEY, - GEN_AI_OPERATION_NAME_KEY, - GEN_AI_OUTPUT_MESSAGES_KEY, - INVOKE_AGENT_OPERATION_NAME, - TENANT_ID_KEY, -) -from microsoft_agents_a365.observability.core.exporters.enriching_span_processor import ( - _EnrichingBatchSpanProcessor, -) -from microsoft_agents_a365.observability.core.invoke_agent_details import InvokeAgentScopeDetails -from microsoft_agents_a365.observability.core.invoke_agent_scope import InvokeAgentScope -from microsoft_agents_a365.observability.core.request import Request -from microsoft_agents_a365.observability.extensions.langchain import ( - CustomLangChainInstrumentor, -) - -# Ensure A365 observability scopes are active for tests -os.environ["ENABLE_A365_OBSERVABILITY"] = "true" - - -@tool -def add_numbers(a: float, b: float) -> str: - """Add two numbers together. - - Args: - a: First number - b: Second number - - Returns: - A string describing the sum. - """ - return f"The sum of {a} and {b} is {a + b}" - - -class SpanCapturingExporter(SpanExporter): - """Exporter that collects spans in-memory after enrichment.""" - - def __init__(self) -> None: - self.spans: list[ReadableSpan] = [] - - def export(self, spans: list[ReadableSpan]) -> SpanExportResult: - self.spans.extend(spans) - return SpanExportResult.SUCCESS - - def shutdown(self) -> None: - pass - - def force_flush(self, timeout_millis: int = 30000) -> bool: - return True - - -def _get_span_attr(span: ReadableSpan, key: str) -> str | None: - """Safely get an attribute from a span.""" - attrs = span.attributes or {} - return attrs.get(key) - - -def _find_spans_by_name_prefix(spans: list[ReadableSpan], prefix: str) -> list[ReadableSpan]: - """Find spans whose name starts with a given prefix.""" - return [s for s in spans if s.name.startswith(prefix)] - - -@pytest.mark.integration -class TestLangChainObservabilityPipeline: - """End-to-end pipeline tests: InvokeAgent → Inference → ToolExecution. - - Verifies that wrapping LangChain calls inside InvokeAgentScope - produces a single trace with correct parent-child span hierarchy, - operation names, and A365 structured array message format attributes. - """ - - @pytest.fixture(autouse=True) - def setup_observability(self) -> None: - """Set up A365 observability with CustomLangChainInstrumentor.""" - if not hasattr(TestLangChainObservabilityPipeline, "_exporter"): - configure( - service_name="integration-test-langchain-pipeline", - service_namespace="agent365-tests", - logger_name="test-logger", - ) - - exporter = SpanCapturingExporter() - provider = get_tracer_provider() - provider.add_span_processor( - _EnrichingBatchSpanProcessor( - exporter, - max_queue_size=100, - schedule_delay_millis=100, - max_export_batch_size=100, - ) - ) - - # CustomLangChainInstrumentor instruments on init - instrumentor = CustomLangChainInstrumentor() - - TestLangChainObservabilityPipeline._exporter = exporter - TestLangChainObservabilityPipeline._instrumentor = instrumentor - - self.exporter = TestLangChainObservabilityPipeline._exporter - self.exporter.spans.clear() - - @pytest.fixture - def llm(self, azure_openai_config: dict) -> AzureChatOpenAI: - """Create a real Azure OpenAI LangChain chat model.""" - return AzureChatOpenAI( - azure_endpoint=azure_openai_config["endpoint"], - api_key=azure_openai_config["api_key"], - azure_deployment=azure_openai_config["deployment"], - api_version=azure_openai_config["api_version"], - ) - - @pytest.fixture - def agent_details(self) -> AgentDetails: - """Create AgentDetails for the test agent.""" - tenant_id = os.getenv("AGENT365_TEST_TENANT_ID", "4d44f041-f91e-4d00-b107-61e47b26f5a8") - agent_id = os.getenv("AGENT365_TEST_AGENT_ID", "3bccd52b-daaa-4b11-af40-47443852137c") - return AgentDetails( - agent_id=agent_id, - agent_name="langchain-pipeline-test-agent", - agent_description="Integration test agent for LangChain pipeline verification", - tenant_id=tenant_id, - ) - - def _flush_and_collect(self) -> list[ReadableSpan]: - """Force flush and return all captured spans.""" - get_tracer_provider().force_flush() - time.sleep(0.5) - return list(self.exporter.spans) - - # ------------------------------------------------------------------ - # Test: Full pipeline with tool execution loop - # ------------------------------------------------------------------ - - @pytest.mark.asyncio - async def test_pipeline_invoke_agent_with_tool_call( - self, - llm: AzureChatOpenAI, - agent_details: AgentDetails, - ) -> None: - """Full pipeline: InvokeAgentScope wraps LangChain with tool execution. - - Uses a manual tool loop: LLM call → tool execution → LLM call. - This ensures both inference and tool execution spans are created. - - Verifies: - 1. All spans share the same trace_id - 2. invoke_agent span is the root (no parent) - 3. Inference spans are descendants of invoke_agent - 4. Tool execution spans are descendants of invoke_agent - 5. A365 message format on inference spans - """ - from langchain_core.messages import ToolMessage - - request = Request(content="What is 15 + 27?", session_id="test-langchain-pipeline") - - llm_with_tools = llm.bind_tools([add_numbers]) - - with InvokeAgentScope.start( - request=request, - scope_details=InvokeAgentScopeDetails(), - agent_details=agent_details, - ): - messages = [ - SystemMessage( - content=( - "You are a math assistant. You MUST use the add_numbers tool " - "for any arithmetic. Never compute in your head." - ) - ), - HumanMessage(content="What is 15 + 27?"), - ] - - # First LLM call — should produce a tool_calls response - ai_response = await llm_with_tools.ainvoke(messages) - messages.append(ai_response) - - # Execute tool calls if present - if hasattr(ai_response, "tool_calls") and ai_response.tool_calls: - for tc in ai_response.tool_calls: - tool_result = add_numbers.invoke(tc) - messages.append(ToolMessage(content=str(tool_result), tool_call_id=tc["id"])) - - # Second LLM call with tool results - final_response = await llm_with_tools.ainvoke(messages) - else: - final_response = ai_response - - assert final_response is not None - assert len(str(final_response.content)) > 0 - - spans = self._flush_and_collect() - assert len(spans) > 0, "No spans were captured" - - # --- Print span tree for debugging --- - print(f"\n=== Captured {len(spans)} spans ===") - for s in spans: - op = _get_span_attr(s, GEN_AI_OPERATION_NAME_KEY) or "(none)" - parent_id = f"{s.parent.span_id:016x}" if s.parent else "None" - print( - f" {s.name} | op={op} | trace={s.context.trace_id:032x} " - f"| span={s.context.span_id:016x} | parent={parent_id}" - ) - - # --- 1. Find invoke_agent span --- - invoke_spans = _find_spans_by_name_prefix(spans, "invoke_agent") - assert len(invoke_spans) >= 1, ( - f"Expected at least 1 invoke_agent span, got: {[s.name for s in spans]}" - ) - invoke_span = invoke_spans[0] - trace_id = invoke_span.context.trace_id - - # --- 2. All spans share the same trace_id --- - for s in spans: - assert s.context.trace_id == trace_id, ( - f"Span '{s.name}' has different trace_id: " - f"{s.context.trace_id:032x} vs {trace_id:032x}" - ) - - # --- 3. invoke_agent span is the root --- - assert invoke_span.parent is None, ( - f"invoke_agent should be root but has parent: {invoke_span.parent.span_id:016x}" - ) - - # --- 4. invoke_agent has correct operation name --- - assert _get_span_attr(invoke_span, GEN_AI_OPERATION_NAME_KEY) == INVOKE_AGENT_OPERATION_NAME - - # --- 5. Tenant ID is set --- - assert _get_span_attr(invoke_span, TENANT_ID_KEY) == agent_details.tenant_id - - # --- 6. Inference spans are descendants of invoke_agent --- - # LangChain inference spans typically have chat operation or input messages - inference_spans = [ - s - for s in spans - if s != invoke_span - and ( - _get_span_attr(s, GEN_AI_OPERATION_NAME_KEY) == "chat" - or _get_span_attr(s, GEN_AI_INPUT_MESSAGES_KEY) is not None - ) - and not s.name.startswith("execute_tool") - ] - assert len(inference_spans) >= 1, ( - f"Expected at least 1 inference span, got: {[s.name for s in spans]}" - ) - - invoke_span_id = invoke_span.context.span_id - for inf_span in inference_spans: - self._assert_ancestor( - inf_span, - invoke_span_id, - spans, - f"Inference span '{inf_span.name}' is not a descendant of invoke_agent", - ) - - # --- 7. Tool execution spans are descendants of invoke_agent --- - tool_spans = _find_spans_by_name_prefix(spans, "execute_tool") - # Tool execution spans may or may not appear depending on whether - # the LangChain tracer emits them. If present, verify hierarchy. - if tool_spans: - for tool_span in tool_spans: - self._assert_ancestor( - tool_span, - invoke_span_id, - spans, - f"Tool span '{tool_span.name}' is not a descendant of invoke_agent", - ) - print(f"\n✓ Found {len(tool_spans)} tool execution spans") - - # --- 8. A365 message format on inference spans --- - # The A365 mapper emits the structured array format [...]. - for inf_span in inference_spans: - attrs = dict(inf_span.attributes or {}) - if GEN_AI_INPUT_MESSAGES_KEY in attrs: - input_data = json.loads(attrs[GEN_AI_INPUT_MESSAGES_KEY]) - if isinstance(input_data, list): - for msg in input_data: - assert "role" in msg - assert "parts" in msg - - if GEN_AI_OUTPUT_MESSAGES_KEY in attrs: - output_data = json.loads(attrs[GEN_AI_OUTPUT_MESSAGES_KEY]) - if isinstance(output_data, list): - for msg in output_data: - assert "role" in msg - assert "parts" in msg - - print( - f"\n✓ All pipeline assertions passed: " - f"{len(spans)} spans, {len(inference_spans)} inference, " - f"{len(tool_spans)} tool" - ) - - # ------------------------------------------------------------------ - # Test: Pipeline without tools (simple inference only) - # ------------------------------------------------------------------ - - @pytest.mark.asyncio - async def test_pipeline_invoke_agent_simple_inference( - self, - llm: AzureChatOpenAI, - agent_details: AgentDetails, - ) -> None: - """Pipeline with InvokeAgentScope + simple inference (no tools). - - Verifies invoke_agent → inference span hierarchy. - """ - request = Request(content="Say hello", session_id="test-langchain-simple") - - with InvokeAgentScope.start( - request=request, - scope_details=InvokeAgentScopeDetails(), - agent_details=agent_details, - ): - messages = [ - SystemMessage(content="You are a helpful assistant. Reply in one sentence."), - HumanMessage(content="Say hello in exactly 5 words."), - ] - result = await llm.ainvoke(messages) - - assert result is not None - assert len(str(result.content)) > 0 - - spans = self._flush_and_collect() - assert len(spans) > 0, "No spans were captured" - - # All spans share the same trace_id - invoke_spans = _find_spans_by_name_prefix(spans, "invoke_agent") - assert len(invoke_spans) >= 1 - invoke_span = invoke_spans[0] - trace_id = invoke_span.context.trace_id - - for s in spans: - assert s.context.trace_id == trace_id - - # invoke_agent is root - assert invoke_span.parent is None - - # Inference spans are descendants - inference_spans = [ - s - for s in spans - if s != invoke_span and _get_span_attr(s, GEN_AI_INPUT_MESSAGES_KEY) is not None - ] - assert len(inference_spans) >= 1 - - invoke_span_id = invoke_span.context.span_id - for inf_span in inference_spans: - self._assert_ancestor( - inf_span, - invoke_span_id, - spans, - f"Inference span '{inf_span.name}' not a descendant of invoke_agent", - ) - - print(f"\n✓ Simple pipeline: {len(spans)} spans, hierarchy verified") - - # ------------------------------------------------------------------ - # Helper: assert ancestor relationship - # ------------------------------------------------------------------ - - def _assert_ancestor( - self, - span: ReadableSpan, - ancestor_span_id: int, - all_spans: list[ReadableSpan], - message: str, - ) -> None: - """Walk up the parent chain and assert that ancestor_span_id is found.""" - span_map = {s.context.span_id: s for s in all_spans} - current = span - visited: set[int] = set() - while current.parent is not None: - parent_id = current.parent.span_id - if parent_id == ancestor_span_id: - return - if parent_id in visited: - break - visited.add(parent_id) - current = span_map.get(parent_id) - if current is None: - break - raise AssertionError(message) diff --git a/tests/observability/extensions/langchain/test_tracer_bounded.py b/tests/observability/extensions/langchain/test_tracer_bounded.py deleted file mode 100644 index b70c920b..00000000 --- a/tests/observability/extensions/langchain/test_tracer_bounded.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -"""Tests for bounded collections in the LangChain tracer.""" - -import unittest -from collections import OrderedDict -from unittest.mock import MagicMock, patch -from uuid import uuid4 - -from microsoft_agents_a365.observability.extensions.langchain.tracer import ( - CustomLangChainTracer, -) - - -class TestLangChainTracerBounded(unittest.TestCase): - """Tests that LangChain tracer collections are properly bounded.""" - - def _make_tracer(self) -> CustomLangChainTracer: - """Create a tracer with a mock OTel tracer.""" - mock_otel_tracer = MagicMock() - mock_span = MagicMock() - mock_otel_tracer.start_span.return_value = mock_span - return CustomLangChainTracer( - tracer=mock_otel_tracer, - separate_trace_from_runtime_context=True, - ) - - def test_spans_by_run_is_ordered_dict(self): - """_spans_by_run should be an OrderedDict for bounded eviction.""" - tracer = self._make_tracer() - self.assertIsInstance(tracer._spans_by_run, OrderedDict) - - def test_cap_ordered_dict_evicts_oldest(self): - """_cap_ordered_dict should evict oldest entries (FIFO).""" - d: OrderedDict[str, int] = OrderedDict() - for i in range(15): - d[f"key_{i}"] = i - CustomLangChainTracer._cap_ordered_dict(d, 10) - - self.assertEqual(len(d), 10) - # oldest 5 should be gone - for i in range(5): - self.assertNotIn(f"key_{i}", d) - # newest 10 should remain - for i in range(5, 15): - self.assertIn(f"key_{i}", d) - self.assertEqual(d[f"key_{i}"], i) - - def test_cap_ordered_dict_noop_when_under_limit(self): - """_cap_ordered_dict should be a no-op when size is under limit.""" - d: OrderedDict[str, int] = OrderedDict() - for i in range(5): - d[f"key_{i}"] = i - CustomLangChainTracer._cap_ordered_dict(d, 10) - self.assertEqual(len(d), 5) - - def test_spans_by_run_bounded_on_start_trace(self): - """_spans_by_run should be bounded when _start_trace adds entries.""" - tracer = self._make_tracer() - # Use a small cap for testing - original_max = CustomLangChainTracer._MAX_TRACKED_RUNS - try: - CustomLangChainTracer._MAX_TRACKED_RUNS = 5 - - # Add more runs than the cap - for i in range(10): - run = MagicMock() - run.id = uuid4() - run.parent_run_id = None - run.run_type = "llm" - run.name = f"test_run_{i}" - run.start_time = MagicMock() - - with patch( - "microsoft_agents_a365.observability.extensions.langchain.tracer" - ".context_api.get_value", - return_value=None, - ): - tracer._start_trace(run) - - # Should be capped at 5 - self.assertLessEqual(len(tracer._spans_by_run), 5) - finally: - CustomLangChainTracer._MAX_TRACKED_RUNS = original_max - - def test_get_span_returns_none_for_missing(self): - """get_span should return None for non-existent run_id.""" - tracer = self._make_tracer() - result = tracer.get_span(uuid4()) - self.assertIsNone(result) - - def test_get_span_returns_span_for_existing(self): - """get_span should return the span for existing run_id.""" - tracer = self._make_tracer() - run_id = uuid4() - mock_span = MagicMock() - with tracer._lock: - tracer._spans_by_run[run_id] = mock_span - result = tracer.get_span(run_id) - self.assertEqual(result, mock_span) - - def test_max_tracked_runs_default(self): - """Default _MAX_TRACKED_RUNS should be 10000.""" - self.assertEqual(CustomLangChainTracer._MAX_TRACKED_RUNS, 10000) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/observability/extensions/langchain/test_wrapper_langchain.py b/tests/observability/extensions/langchain/test_wrapper_langchain.py deleted file mode 100644 index 0a9c1116..00000000 --- a/tests/observability/extensions/langchain/test_wrapper_langchain.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -import unittest -from unittest.mock import MagicMock -from uuid import uuid4 - -from microsoft_agents_a365.observability.core import configure -from microsoft_agents_a365.observability.extensions.langchain.tracer_instrumentor import ( - CustomLangChainInstrumentor, -) - - -class TestInstrumentorLangChain(unittest.TestCase): - """Unit tests for InstrumentorForLangChain class.""" - - @classmethod - def setUpClass(cls): - """Set up test environment once for all tests.""" - configure( - service_name="test-service-langchain", - service_namespace="test-namespace-langchain", - ) - - def setUp(self): - """Reset instrumentation state before each test.""" - # Clear the global instrumentation state - CustomLangChainInstrumentor._instance = None - if hasattr(CustomLangChainInstrumentor, "_instrumented"): - CustomLangChainInstrumentor._instrumented = False - - def tearDown(self): - """Clean up after each test.""" - try: - instrumentor = getattr(self, "_test_instrumentor", None) - if instrumentor: - instrumentor._uninstrument() - except Exception: - pass - - def test_instrumentor_initialization_and_Agent365_integration(self): - """Test 1: Verify InstrumentorForLangChain initializes and integrates with Microsoft Agent 365.""" - from microsoft_agents_a365.observability.core.config import get_tracer, is_configured - - # Verify Microsoft Agent 365 is configured - self.assertTrue(is_configured(), "Microsoft Agent 365 should be configured") - - # Get tracer to ensure it works - tracer = get_tracer() - self.assertIsNotNone(tracer, "Microsoft Agent 365 tracer should be available") - - # Create instrumentor - self._test_instrumentor = CustomLangChainInstrumentor() - - # Verify the object was created - self.assertIsNotNone(self._test_instrumentor) - self.assertIsInstance(self._test_instrumentor, CustomLangChainInstrumentor) - - # Check if it has expected attributes/methods - self.assertTrue(hasattr(self._test_instrumentor, "_instrument")) - self.assertTrue(hasattr(self._test_instrumentor, "_uninstrument")) - self.assertTrue(hasattr(self._test_instrumentor, "get_span")) - self.assertTrue(hasattr(self._test_instrumentor, "get_ancestors")) - - # Check that tracer was created during initialization - self.assertIsNotNone( - self._test_instrumentor._tracer, "Tracer should be created after initialization" - ) - - print( - "✅ Test 1: InstrumentorForLangChain initialization and Microsoft Agent 365 integration works" - ) - - def test_instrumentor_get_span_functionality(self): - """Test 2: Verify get_span method works correctly with mock data.""" - self._test_instrumentor = CustomLangChainInstrumentor() - - # Test with non-existent run_id - test_run_id = uuid4() - span = self._test_instrumentor.get_span(test_run_id) - self.assertIsNone(span, "get_span should return None for non-existent run_id") - - # Test with mock span data - if self._test_instrumentor._tracer is not None: - # Mock the internal _spans_by_run dict - mock_span = MagicMock() - self._test_instrumentor._tracer._spans_by_run[test_run_id] = mock_span - - result_span = self._test_instrumentor.get_span(test_run_id) - self.assertEqual(result_span, mock_span, "get_span should return the correct span") - - # Clean up the mock data - del self._test_instrumentor._tracer._spans_by_run[test_run_id] - - print("✅ Test 2: get_span functionality works correctly") - - def test_instrumentor_wrapping_mechanism(self): - """Test 3: Verify instrumentor properly wraps LangChain BaseCallbackManager.""" - self._test_instrumentor = CustomLangChainInstrumentor() - - # Verify instrumentor has internal tracer - self.assertIsNotNone( - self._test_instrumentor._tracer, "Tracer should be created during instrumentation" - ) - - # Verify original callback init was saved - self.assertIsNotNone( - self._test_instrumentor._original_cb_init, "Original callback init should be saved" - ) - - # Verify get_span and get_ancestors methods work - self.assertTrue(callable(self._test_instrumentor.get_span)) - self.assertTrue(callable(self._test_instrumentor.get_ancestors)) - - # Test get_ancestors with empty result - test_run_id = uuid4() - ancestors = self._test_instrumentor.get_ancestors(test_run_id) - self.assertEqual( - ancestors, [], "get_ancestors should return empty list for non-existent run" - ) - - print("✅ Test 3: LangChain BaseCallbackManager wrapping works correctly") - - -def run_langchain_tests(): - """Run all LangChain wrapper tests with detailed output.""" - print("🧪 Running Microsoft Agent 365 LangChain Instrumentor tests...") - print("=" * 80) - - # Create test suite - loader = unittest.TestLoader() - suite = unittest.TestSuite() - - # Add test class - suite.addTests(loader.loadTestsFromTestCase(TestInstrumentorLangChain)) - - # Run tests - runner = unittest.TextTestRunner(verbosity=2) - result = runner.run(suite) - - # Summary - print("\n" + "=" * 80) - print("🏁 LangChain Test Summary:") - print(f"Tests run: {result.testsRun}") - print(f"Failures: {len(result.failures)}") - print(f"Errors: {len(result.errors)}") - - if result.wasSuccessful(): - print("🎉 All LangChain tests passed!") - return True - else: - print("🔧 Some LangChain tests failed. Check output above.") - return False - - -if __name__ == "__main__": - success = run_langchain_tests() - exit(0 if success else 1) diff --git a/uv.lock b/uv.lock index 6db581d4..1e298e95 100644 --- a/uv.lock +++ b/uv.lock @@ -13,7 +13,6 @@ members = [ "microsoft-agents-a365-notifications", "microsoft-agents-a365-observability-core", "microsoft-agents-a365-observability-extensions-agent-framework", - "microsoft-agents-a365-observability-extensions-langchain", "microsoft-agents-a365-observability-extensions-openai", "microsoft-agents-a365-observability-extensions-semantic-kernel", "microsoft-agents-a365-observability-hosting", @@ -38,7 +37,6 @@ constraints = [ { name = "black", specifier = ">=23.0.0" }, { name = "google-adk", specifier = ">=1.28.1,<2.0.0" }, { name = "httpx", specifier = ">=0.27.0" }, - { name = "langchain-core", specifier = ">=0.1.0" }, { name = "microsoft-agents-activity", specifier = ">=0.4.0" }, { name = "microsoft-agents-hosting-core", specifier = ">=0.4.0" }, { name = "mypy", specifier = ">=1.0.0" }, @@ -69,7 +67,6 @@ overrides = [{ name = "azure-ai-projects", specifier = ">=1.0.0b12,<2.0.0" }] dev = [ { name = "agent-framework" }, { name = "azure-identity" }, - { name = "langchain-openai" }, { name = "openai" }, { name = "openai-agents" }, { name = "pytest" }, @@ -2579,18 +2576,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jmespath/1.1/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64" }, ] -[[package]] -name = "jsonpatch" -version = "1.33" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -dependencies = [ - { name = "jsonpointer" }, -] -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jsonpatch/1.33/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jsonpatch/1.33/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade" }, -] - [[package]] name = "jsonpath-ng" version = "1.8.0" @@ -2600,15 +2585,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jsonpath-ng/1.8/jsonpath_ng-1.8.0-py3-none-any.whl", hash = "sha256:b8dde192f8af58d646fc031fac9c99fe4d00326afc4148f1f043c601a8cfe138" }, ] -[[package]] -name = "jsonpointer" -version = "3.0.0" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jsonpointer/3/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jsonpointer/3/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942" }, -] - [[package]] name = "jsonschema" version = "4.26.0" @@ -2651,59 +2627,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/jsonschema-specifications/2025.9.1/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe" }, ] -[[package]] -name = "langchain-core" -version = "1.2.28" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -dependencies = [ - { name = "jsonpatch" }, - { name = "langsmith" }, - { name = "packaging" }, - { name = "pydantic" }, - { name = "pyyaml" }, - { name = "tenacity" }, - { name = "typing-extensions" }, - { name = "uuid-utils" }, -] -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/langchain-core/1.2.28/langchain_core-1.2.28.tar.gz", hash = "sha256:271a3d8bd618f795fdeba112b0753980457fc90537c46a0c11998516a74dc2cb" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/langchain-core/1.2.28/langchain_core-1.2.28-py3-none-any.whl", hash = "sha256:80764232581eaf8057bcefa71dbf8adc1f6a28d257ebd8b95ba9b8b452e8c6ac" }, -] - -[[package]] -name = "langchain-openai" -version = "1.1.12" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -dependencies = [ - { name = "langchain-core" }, - { name = "openai" }, - { name = "tiktoken" }, -] -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/langchain-openai/1.1.12/langchain_openai-1.1.12.tar.gz", hash = "sha256:ccf5ef02c896f6807b4d0e51aaf678a72ce81ae41201cae8d65e11eeff9ecb79" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/langchain-openai/1.1.12/langchain_openai-1.1.12-py3-none-any.whl", hash = "sha256:da71ca3f2d18c16f7a2443cc306aa195ad2a07054335ac9b0626dcae02b6a0c5" }, -] - -[[package]] -name = "langsmith" -version = "0.7.31" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -dependencies = [ - { name = "httpx" }, - { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, - { name = "packaging" }, - { name = "pydantic" }, - { name = "requests" }, - { name = "requests-toolbelt" }, - { name = "uuid-utils" }, - { name = "xxhash" }, - { name = "zstandard" }, -] -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/langsmith/0.7.31/langsmith-0.7.31.tar.gz", hash = "sha256:331ee4f7c26bb5be4022b9859b7d7b122cbf8c9d01d9f530114c1914b0349ffb" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/langsmith/0.7.31/langsmith-0.7.31-py3-none-any.whl", hash = "sha256:0291d49203f6e80dda011af1afda61eb0595a4d697adb684590a8805e1d61fb6" }, -] - [[package]] name = "lazy-object-proxy" version = "1.12.0" @@ -3070,49 +2993,6 @@ requires-dist = [ ] provides-extras = ["dev", "test"] -[[package]] -name = "microsoft-agents-a365-observability-extensions-langchain" -source = { editable = "libraries/microsoft-agents-a365-observability-extensions-langchain" } -dependencies = [ - { name = "langchain-core" }, - { name = "microsoft-agents-a365-observability-core" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-instrumentation" }, - { name = "opentelemetry-sdk" }, - { name = "wrapt" }, -] - -[package.optional-dependencies] -dev = [ - { name = "black" }, - { name = "mypy" }, - { name = "pytest" }, - { name = "pytest-asyncio" }, - { name = "ruff" }, -] -test = [ - { name = "pytest" }, - { name = "pytest-asyncio" }, -] - -[package.metadata] -requires-dist = [ - { name = "black", marker = "extra == 'dev'" }, - { name = "langchain-core" }, - { name = "microsoft-agents-a365-observability-core", editable = "libraries/microsoft-agents-a365-observability-core" }, - { name = "mypy", marker = "extra == 'dev'" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-instrumentation" }, - { name = "opentelemetry-sdk" }, - { name = "pytest", marker = "extra == 'dev'" }, - { name = "pytest", marker = "extra == 'test'" }, - { name = "pytest-asyncio", marker = "extra == 'dev'" }, - { name = "pytest-asyncio", marker = "extra == 'test'" }, - { name = "ruff", marker = "extra == 'dev'" }, - { name = "wrapt" }, -] -provides-extras = ["dev", "test"] - [[package]] name = "microsoft-agents-a365-observability-extensions-openai" source = { editable = "libraries/microsoft-agents-a365-observability-extensions-openai" } @@ -4312,74 +4192,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orderedmultidict/1.0.2/orderedmultidict-1.0.2-py2.py3-none-any.whl", hash = "sha256:ab5044c1dca4226ae4c28524cfc5cc4c939f0b49e978efa46a6ad6468049f79b" }, ] -[[package]] -name = "orjson" -version = "3.11.7" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/orjson/3.11.7/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d" }, -] - [[package]] name = "packaging" version = "26.0" @@ -5240,110 +5052,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/referencing/0.36.2/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0" }, ] -[[package]] -name = "regex" -version = "2026.4.4" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4.tar.gz", hash = "sha256:e08270659717f6973523ce3afbafa53515c4dc5dcad637dc215b6fd50f689423" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4c36a85b00fadb85db9d9e90144af0a980e1a3d2ef9cd0f8a5bef88054657c6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5453ecf9cd58b562967badd1edbf092b0588a3af9e32ee3d05c985077ce87" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6aa809ed4dc3706cc38594d67e641601bd2f36d5555b2780ff074edfcb136cf8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33424f5188a7db12958246a54f59a435b6cb62c5cf9c8d71f7cc49475a5fdada" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d346fccdde28abba117cc9edc696b9518c3307fbfcb689e549d9b5979018c6d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:415a994b536440f5011aa77e50a4274d15da3245e876e5c7f19da349caaedd87" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21e5eb86179b4c67b5759d452ea7c48eb135cd93308e7a260aa489ed2eb423a4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:312ec9dd1ae7d96abd8c5a36a552b2139931914407d26fba723f9e53c8186f86" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0d2b28aa1354c7cd7f71b7658c4326f7facac106edd7f40eda984424229fd59" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:349d7310eddff40429a099c08d995c6d4a4bfaf3ff40bd3b5e5cb5a5a3c7d453" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e7ab63e9fe45a9ec3417509e18116b367e89c9ceb6219222a3396fa30b147f80" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fe896e07a5a2462308297e515c0054e9ec2dd18dfdc9427b19900b37dfe6f40b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb59c65069498dbae3c0ef07bbe224e1eaa079825a437fb47a479f0af11f774f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-win32.whl", hash = "sha256:2a5d273181b560ef8397c8825f2b9d57013de744da9e8257b8467e5da8599351" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:9542ccc1e689e752594309444081582f7be2fdb2df75acafea8a075108566735" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:b5f9fb784824a042be3455b53d0b112655686fdb7a91f88f095f3fee1e2a2a54" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c07ab8794fa929e58d97a0e1796b8b76f70943fa39df225ac9964615cf1f9d52" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c785939dc023a1ce4ec09599c032cc9933d258a998d16ca6f2b596c010940eb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1ce5c81c9114f1ce2f9288a51a8fd3aeea33a0cc440c415bf02da323aa0a76" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:760ef21c17d8e6a4fe8cf406a97cf2806a4df93416ccc82fc98d25b1c20425be" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7088fcdcb604a4417c208e2169715800d28838fefd7455fbe40416231d1d47c1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07edca1ba687998968f7db5bc355288d0c6505caa7374f013d27356d93976d13" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f657a7c1c6ec51b5e0ba97c9817d06b84ea5fa8d82e43b9405de0defdc2b9" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b69102a743e7569ebee67e634a69c4cb7e59d6fa2e1aa7d3bdbf3f61435f62d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dac006c8b6dda72d86ea3d1333d45147de79a3a3f26f10c1cf9287ca4ca0ac3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50a766ee2010d504554bfb5f578ed2e066898aa26411d57e6296230627cdefa0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9e2f5217648f68e3028c823df58663587c1507a5ba8419f4fdfc8a461be76043" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39d8de85a08e32632974151ba59c6e9140646dcc36c80423962b1c5c0a92e244" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55d9304e0e7178dfb1e106c33edf834097ddf4a890e2f676f6c5118f84390f73" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-win32.whl", hash = "sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:db0ac18435a40a2543dbb3d21e161a6c78e33e8159bd2e009343d224bb03bb1b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:4ce255cc05c1947a12989c6db801c96461947adb7a59990f1360b5983fab4983" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:62f5519042c101762509b1d717b45a69c0139d60414b3c604b81328c01bd1943" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3790ba9fb5dd76715a7afe34dbe603ba03f8820764b1dc929dd08106214ed031" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fae3c6e795d7678963f2170152b0d892cf6aee9ee8afc8c45e6be38d5107fe7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:298c3ec2d53225b3bf91142eb9691025bab610e0c0c51592dde149db679b3d17" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9638791082eaf5b3ac112c587518ee78e083a11c4b28012d8fe2a0f536dfb17" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae3e764bd4c5ff55035dc82a8d49acceb42a5298edf6eb2fc4d328ee5dd7afae" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa81f81b80047ba89a3c69ae6a0f78d06f4a42ce5126b0eb2a0a10ad44e0b2e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f56ebf9d70305307a707911b88469213630aba821e77de7d603f9d2f0730687d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:773d1dfd652bbffb09336abf890bfd64785c7463716bf766d0eb3bc19c8b7f27" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d51d20befd5275d092cdffba57ded05f3c436317ee56466c8928ac32d960edaf" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0a51cdb3c1e9161154f976cb2bef9894bc063ac82f31b733087ffb8e880137d0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ae5266a82596114e41fb5302140e9630204c1b5f325c770bec654b95dd54b0aa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c882cd92ec68585e9c1cf36c447ec846c0d94edd706fe59e0c198e65822fd23b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-win32.whl", hash = "sha256:05568c4fbf3cb4fa9e28e3af198c40d3237cf6041608a9022285fe567ec3ad62" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:3384df51ed52db0bea967e21458ab0a414f67cdddfd94401688274e55147bb81" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:acd38177bd2c8e69a411d6521760806042e244d0ef94e2dd03ecdaa8a3c99427" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f94a11a9d05afcfcfa640e096319720a19cc0c9f7768e1a61fceee6a3afc6c7c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:36bcb9d6d1307ab629edc553775baada2aefa5c50ccc0215fbfd2afcfff43141" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261c015b3e2ed0919157046d768774ecde57f03d8fa4ba78d29793447f70e717" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c228cf65b4a54583763645dcd73819b3b381ca8b4bb1b349dee1c135f4112c07" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd2630faeb6876fb0c287f664d93ddce4d50cd46c6e88e60378c05c9047e08ca" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a50ab11b7779b849472337191f3a043e27e17f71555f98d0092fa6d73364520" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0734f63afe785138549fbe822a8cfeaccd1bae814c5057cc0ed5b9f2de4fc883" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4ee50606cb1967db7e523224e05f32089101945f859928e65657a2cbb3d278b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6c1818f37be3ca02dcb76d63f2c7aaba4b0dc171b579796c6fbe00148dfec6b1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f5bfc2741d150d0be3e4a0401a5c22b06e60acb9aa4daa46d9e79a6dcd0f135b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:504ffa8a03609a087cad81277a629b6ce884b51a24bd388a7980ad61748618ff" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70aadc6ff12e4b444586e57fc30771f86253f9f0045b29016b9605b4be5f7dfb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f4f83781191007b6ef43b03debc35435f10cad9b96e16d147efe84a1d48bdde4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-win32.whl", hash = "sha256:e014a797de43d1847df957c0a2a8e861d1c17547ee08467d1db2c370b7568baa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b15b88b0d52b179712632832c1d6e58e5774f93717849a41096880442da41ab0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:586b89cdadf7d67bf86ae3342a4dcd2b8d70a832d90c18a0ae955105caf34dbe" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2da82d643fa698e5e5210e54af90181603d5853cf469f5eedf9bfc8f59b4b8c7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:54a1189ad9d9357760557c91103d5e421f0a2dabe68a5cdf9103d0dcf4e00752" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:76d67d5afb1fe402d10a6403bae668d000441e2ab115191a804287d53b772951" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7cd3e4ee8d80447a83bbc9ab0c8459781fa77087f856c3e740d7763be0df27f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e19e18c568d2866d8b6a6dfad823db86193503f90823a8f66689315ba28fbe8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7698a6f38730fd1385d390d1ed07bb13dce39aa616aca6a6d89bea178464b9a4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:173a66f3651cdb761018078e2d9487f4cf971232c990035ec0eb1cdc6bf929a9" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa7922bbb2cc84fa062d37723f199d4c0cd200245ce269c05db82d904db66b83" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:59f67cd0a0acaf0e564c20bbd7f767286f23e91e2572c5703bf3e56ea7557edb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:475e50f3f73f73614f7cba5524d6de49dee269df00272a1b85e3d19f6d498465" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a1c0c7d67b64d85ac2e1879923bad2f08a08f3004055f2f406ef73c850114bd4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:1371c2ccbb744d66ee63631cc9ca12aa233d5749972626b68fe1a649dd98e566" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59968142787042db793348a3f5b918cf24ced1f23247328530e063f89c128a95" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-win32.whl", hash = "sha256:59efe72d37fd5a91e373e5146f187f921f365f4abc1249a5ab446a60f30dd5f8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:e0aab3ff447845049d676827d2ff714aab4f73f340e155b7de7458cf53baa5a4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:a7a5bb6aa0cf62208bb4fa079b0c756734f8ad0e333b425732e8609bd51ee22f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:97850d0638391bdc7d35dc1c1039974dcb921eaafa8cc935ae4d7f272b1d60b3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ee7337f88f2a580679f7bbfe69dc86c043954f9f9c541012f49abc554a962f2e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7429f4e6192c11d659900c0648ba8776243bf396ab95558b8c51a345afeddde6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4f10fbd5dd13dcf4265b4cc07d69ca70280742870c97ae10093e3d66000359" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a152560af4f9742b96f3827090f866eeec5becd4765c8e0d3473d9d280e76a5a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54170b3e95339f415d54651f97df3bff7434a663912f9358237941bbf9143f55" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:07f190d65f5a72dcb9cf7106bfc3d21e7a49dd2879eda2207b683f32165e4d99" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9a2741ce5a29d3c84b0b94261ba630ab459a1b847a0d6beca7d62d188175c790" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b26c30df3a28fd9793113dac7385a4deb7294a06c0f760dd2b008bd49a9139bc" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:421439d1bee44b19f4583ccf42670ca464ffb90e9fdc38d37f39d1ddd1e44f1f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b40379b53ecbc747fd9bdf4a0ea14eb8188ca1bd0f54f78893a39024b28f4863" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:08c55c13d2eef54f73eeadc33146fb0baaa49e7335eb1aff6ae1324bf0ddbe4a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9776b85f510062f5a75ef112afe5f494ef1635607bf1cc220c1391e9ac2f5e81" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-win32.whl", hash = "sha256:385edaebde5db5be103577afc8699fea73a0e36a734ba24870be7ffa61119d74" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:5d354b18839328927832e2fa5f7c95b7a3ccc39e7a681529e1685898e6436d45" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/regex/2026.4.4/regex-2026.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:af0384cb01a33600c49505c27c6c57ab0b27bf84a74e28524c92ca897ebdac9d" }, -] - [[package]] name = "requests" version = "2.33.0" @@ -5372,18 +5080,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/requests-oauthlib/2/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36" }, ] -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -dependencies = [ - { name = "requests" }, -] -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/requests-toolbelt/1/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/requests-toolbelt/1/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06" }, -] - [[package]] name = "rfc3339-validator" version = "0.1.4" @@ -5788,60 +5484,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tenacity/9.1.4/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55" }, ] -[[package]] -name = "tiktoken" -version = "0.12.0" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -dependencies = [ - { name = "regex" }, - { name = "requests" }, -] -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/tiktoken/0.12/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71" }, -] - [[package]] name = "tomli-w" version = "1.2.0" @@ -5990,35 +5632,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/urllib3/2.6.3/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4" }, ] -[[package]] -name = "uuid-utils" -version = "0.14.0" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0.tar.gz", hash = "sha256:fc5bac21e9933ea6c590433c11aa54aaca599f690c08069e364eb13a12f670b4" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f6695c0bed8b18a904321e115afe73b34444bc8451d0ce3244a1ec3b84deb0e5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4f0a730bbf2d8bb2c11b93e1005e91769f2f533fa1125ed1f00fd15b6fcc732b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40ce3fd1a4fdedae618fc3edc8faf91897012469169d600133470f49fd699ed3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ae4a98416a440e78f7d9543d11b11cae4bab538b7ed94ec5da5221481748f2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:971e8c26b90d8ae727e7f2ac3ee23e265971d448b3672882f2eb44828b2b8c3e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5cde1fa82804a8f9d2907b7aec2009d440062c63f04abbdb825fce717a5e860" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c7343862a2359e0bd48a7f3dfb5105877a1728677818bb694d9f40703264a2db" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c51e4818fdb08ccec12dc7083a01f49507b4608770a0ab22368001685d59381b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:181bbcccb6f93d80a8504b5bd47b311a1c31395139596edbc47b154b0685b533" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:5c8ae96101c3524ba8dbf762b6f05e9e9d896544786c503a727c5bf5cb9af1a7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00ac3c6edfdaff7e1eed041f4800ae09a3361287be780d7610a90fdcde9befdc" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-win32.whl", hash = "sha256:ec2fd80adf8e0e6589d40699e6f6df94c93edcc16dd999be0438dd007c77b151" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-win_amd64.whl", hash = "sha256:efe881eb43a5504fad922644cb93d725fd8a6a6d949bd5a4b4b7d1a1587c7fd1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-cp39-abi3-win_arm64.whl", hash = "sha256:32b372b8fd4ebd44d3a219e093fe981af4afdeda2994ee7db208ab065cfcd080" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:762e8d67992ac4d2454e24a141a1c82142b5bde10409818c62adbe9924ebc86d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:40be5bf0b13aa849d9062abc86c198be6a25ff35316ce0b89fc25f3bac6d525e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:191a90a6f3940d1b7322b6e6cceff4dd533c943659e0a15f788674407856a515" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4aa4525f4ad82f9d9c842f9a3703f1539c1808affbaec07bb1b842f6b8b96aa5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdbd82ff20147461caefc375551595ecf77ebb384e46267f128aca45a0f2cdfc" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff57e8a5d540006ce73cf0841a643d445afe78ba12e75ac53a95ca2924a56be" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/uuid-utils/0.14/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3fd9112ca96978361201e669729784f26c71fecc9c13a7f8a07162c31bd4d1e2" }, -] - [[package]] name = "uv" version = "0.11.6" @@ -6349,109 +5962,6 @@ wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/wrapt/1.17.3/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22" }, ] -[[package]] -name = "xxhash" -version = "3.6.0" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b47bbd8cf2d72797f3c2772eaaac0ded3d3af26481a26d7d7d41dc2d3c46b04a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2b6821e94346f96db75abaa6e255706fb06ebd530899ed76d32cd99f20dc52fa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d0a9751f71a1a65ce3584e9cae4467651c7e70c9d31017fa57574583a4540248" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b29ee68625ab37b04c0b40c3fafdf24d2f75ccd778333cfb698f65f6c463f62" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6812c25fe0d6c36a46ccb002f40f27ac903bf18af9f6dd8f9669cb4d176ab18f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4ccbff013972390b51a18ef1255ef5ac125c92dc9143b2d1909f59abc765540e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:297b7fbf86c82c550e12e8fb71968b3f033d27b874276ba3624ea868c11165a8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dea26ae1eb293db089798d3973a5fc928a18fdd97cc8801226fae705b02b14b0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7a0b169aafb98f4284f73635a8e93f0735f9cbde17bd5ec332480484241aaa77" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:08d45aef063a4531b785cd72de4887766d01dc8f362a515693df349fdb825e0c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:929142361a48ee07f09121fe9e96a84950e8d4df3bb298ca5d88061969f34d7b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:51312c768403d8540487dbbfb557454cfc55589bbde6424456951f7fcd4facb3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-win32.whl", hash = "sha256:d1927a69feddc24c987b337ce81ac15c4720955b667fe9b588e02254b80446fd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:26734cdc2d4ffe449b41d186bbeac416f704a482ed835d375a5c0cb02bc63fef" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp311-cp311-win_arm64.whl", hash = "sha256:d72f67ef8bf36e05f5b6c65e8524f265bd61071471cd4cf1d36743ebeeeb06b7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a40a3d35b204b7cc7643cbcf8c9976d818cb47befcfac8bbefec8038ac363f3e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a54844be970d3fc22630b32d515e79a90d0a3ddb2644d8d7402e3c4c8da61405" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:016e9190af8f0a4e3741343777710e3d5717427f175adfdc3e72508f59e2a7f3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f6f72232f849eb9d0141e2ebe2677ece15adfd0fa599bc058aad83c714bb2c6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:63275a8aba7865e44b1813d2177e0f5ea7eadad3dd063a21f7cf9afdc7054063" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cd01fa2aa00d8b017c97eb46b9a794fbdca53fc14f845f5a328c71254b0abb7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0226aa89035b62b6a86d3c68df4d7c1f47a342b8683da2b60cedcddb46c4d95b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c6e193e9f56e4ca4923c61238cdaced324f0feac782544eb4c6d55ad5cc99ddd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9176dcaddf4ca963d4deb93866d739a343c01c969231dbe21680e13a5d1a5bf0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c1ce4009c97a752e682b897aa99aef84191077a9433eb237774689f14f8ec152" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:8cb2f4f679b01513b7adbb9b1b2f0f9cdc31b70007eaf9d59d0878809f385b11" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:653a91d7c2ab54a92c19ccf43508b6a555440b9be1bc8be553376778be7f20b5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-win32.whl", hash = "sha256:a756fe893389483ee8c394d06b5ab765d96e68fbbfe6fde7aa17e11f5720559f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:39be8e4e142550ef69629c9cd71b88c90e9a5db703fecbcf265546d9536ca4ad" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314-win_arm64.whl", hash = "sha256:25915e6000338999236f1eb68a02a32c3275ac338628a7eaa5a269c401995679" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5294f596a9017ca5a3e3f8884c00b91ab2ad2933cf288f4923c3fd4346cf3d4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1cf9dcc4ab9cff01dfbba78544297a3a01dafd60f3bde4e2bfd016cf7e4ddc67" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51a73fb7cb3a3ead9f7a8b583ffd9b8038e277cdb8cb87cf890e88b3456afa0b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b9c6df83594f7df8f7f708ce5ebeacfc69f72c9fbaaababf6cf4758eaada0c9b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:627f0af069b0ea56f312fd5189001c24578868643203bca1abbc2c52d3a6f3ca" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa912c62f842dfd013c5f21a642c9c10cd9f4c4e943e0af83618b4a404d9091a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b465afd7909db30168ab62afe40b2fcf79eedc0b89a6c0ab3123515dc0df8b99" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a881851cf38b0a70e7c4d3ce81fc7afd86fbc2a024f4cfb2a97cf49ce04b75d3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9b3222c686a919a0f3253cfc12bb118b8b103506612253b5baeaac10d8027cf6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:c5aa639bc113e9286137cec8fadc20e9cd732b2cc385c0b7fa673b84fc1f2a93" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5c1343d49ac102799905e115aee590183c3921d475356cb24b4de29a4bc56518" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-win32.whl", hash = "sha256:5851f033c3030dd95c086b4a36a2683c2ff4a799b23af60977188b057e467119" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0444e7967dac37569052d2409b00a8860c2135cff05502df4da80267d384849f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:bb79b1e63f6fd84ec778a4b1916dfe0a7c3fdb986c06addd5db3a0d413819d95" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0f7b7e2ec26c1666ad5fc9dbfa426a6a3367ceaf79db5dd76264659d509d73b0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5dc1e14d14fa0f5789ec29a7062004b5933964bb9b02aae6622b8f530dc40296" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:881b47fc47e051b37d94d13e7455131054b56749b91b508b0907eb07900d1c13" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6dc31591899f5e5666f04cc2e529e69b4072827085c1ef15294d91a004bc1bd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/xxhash/3.6/xxhash-3.6.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:15e0dac10eb9309508bfc41f7f9deaa7755c69e35af835db9cb10751adebc35d" }, -] - [[package]] name = "yarl" version = "1.22.0" @@ -6570,77 +6080,3 @@ sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934 wheels = [ { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zipp/3.23/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e" }, ] - -[[package]] -name = "zstandard" -version = "0.25.0" -source = { registry = "https://packagefeedproxy.microsoft.io/pypi/simple/" } -sdist = { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b" } -wheels = [ - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-win32.whl", hash = "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp311-cp311-win_arm64.whl", hash = "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-win32.whl", hash = "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp313-cp313-win_arm64.whl", hash = "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-win32.whl", hash = "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2" }, - { url = "https://ms-feed-25.pkgs.visualstudio.com/6f084628-a36d-42cb-934d-057357e379dc/_packaging/49d7402f-07bb-4b18-a9ce-086e6e98a554/pypi/download/zstandard/0.25/zstandard-0.25.0-cp314-cp314-win_arm64.whl", hash = "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d" }, -]