diff --git a/agent_sdks/python/a2ui_agent/README.md b/agent_sdks/python/a2ui_agent/README.md index e18deb7db0..7f26d935db 100644 --- a/agent_sdks/python/a2ui_agent/README.md +++ b/agent_sdks/python/a2ui_agent/README.md @@ -28,6 +28,13 @@ The following directories contain the base protocol logic, parsing, and schema o - **`provider.py`**: Implementation of `BasicCatalog` for handling the basic A2UI components. +## Experimental Templates (`src/a2ui/inference_formats/experimental/template`) + +- **`models.py`**: Typed models (`StaticTemplate`, `DynamicTemplate`, `Param`, `ParamType`, AST expressions) and signature-based parameter inference. +- **`processor.py`**: `TemplateProcessor` for generating synthetic inference catalogs and expanding template invocations into A2UI primitives. +- **`format.py`**: `TemplateInferenceFormat` integrating template-aware prompt generation and synchronous parsing. +- Reference schema: Located at `specification/proposals/templates/schema/template_definition.json`. + ## A2A (`src/a2ui/a2a`) - **`extension.py`**: Utilities for managing the A2UI extension URI and activation logic. diff --git a/agent_sdks/python/a2ui_agent/pyproject.toml b/agent_sdks/python/a2ui_agent/pyproject.toml index 0ef8ab3358..ef4e4d572b 100644 --- a/agent_sdks/python/a2ui_agent/pyproject.toml +++ b/agent_sdks/python/a2ui_agent/pyproject.toml @@ -25,7 +25,9 @@ dependencies = [ "google-adk>=1.28.1", "google-genai>=1.27.0", "httpx>=0.27.0", - "jsonschema>=4.0.0" + "jsonschema>=4.0.0", + "nest-asyncio>=1.6.0", + "pyyaml>=6.0" ] [project.scripts] @@ -65,4 +67,5 @@ dev = [ "antlr4-tools>=0.2.1", "hatchling>=1.30.1", "types-jsonschema", + "types-pyyaml", ] diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/README.md b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/README.md new file mode 100644 index 0000000000..81d8f2c70e --- /dev/null +++ b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/README.md @@ -0,0 +1,124 @@ +# A2UI Python Template Engine (`a2ui.inference_formats.experimental.template`) + +The `a2ui.inference_formats.experimental.template` package provides server-side UI template expansion and synthetic catalog compilation for the A2UI Python Agent SDK. + +For the language-agnostic protocol specification, JSON schemas, and multi-platform design guidelines, see: +👉 **[`specification/proposals/templates/README.md`](../../../../../../../../specification/proposals/templates/README.md)** + +--- + +## Python API Reference + +### 1. `StaticTemplate` + +Represents a declarative, immutable UI template parsed from YAML or a dictionary. + +```python +from a2ui.inference_formats.experimental.template import StaticTemplate + +# Load from single or multi-document ('---') YAML files +templates = StaticTemplate.from_yaml_file("path/to/templates.yaml") + +# Load directly from a YAML string +single_template = StaticTemplate.from_yaml(yaml_string) +``` + +### 2. `DynamicTemplate` + +Extends templates with server-side execution. Supports two modes: + +#### A. Data-Binding Mode (`resolver + layout`) + +Takes a lookup argument (e.g. `employeeId`), runs a resolver callback, and injects the result into a static YAML presentation layout: + +```python +from a2ui.inference_formats.experimental.template import DynamicTemplate, StaticTemplate + +layout = StaticTemplate.from_yaml_file("salary_card.yaml")[0] + +def resolve_compensation(employeeId: str) -> dict: + return db.fetch_employee_salary(employeeId) + +dynamic_salary = DynamicTemplate( + template_id="EmployeeSalaryCard", + resolver=resolve_compensation, + layout=layout, + description="Verified compensation. Pass only employeeId.", + sample_data={"employeeId": "emp_101"}, +) +``` + +#### B. Programmatic Render Mode (`render`) + +Bypasses static layouts and runs native Python logic (loops, arithmetic, conditionals) returning a component AST: + +```python +from a2ui.inference_formats.experimental.template import DynamicTemplate + +def render_server_health(serverId: str, includeDisks: bool = True) -> dict: + status_icon = "check_circle" if serverId == "srv_01" else "warning" + return { + "component": "Card", + "child": { + "component": "Column", + "children": [ + {"component": "Text", "text": f"Server {serverId}", "variant": "h3"}, + {"component": "Icon", "name": status_icon}, + ] + } + } + +server_template = DynamicTemplate( + template_id="ServerHealthCard", + render=render_server_health, + description="Live server diagnostics.", + sample_data={"serverId": "srv_01", "includeDisks": True}, +) +``` + +### 3. `TemplateProcessor` + +The core synchronous template expansion and catalog generation engine. + +```python +from a2ui.inference_formats.experimental.template import ( + TemplateProcessor, + TemplateId, + A2UIComponentList, +) + +processor = TemplateProcessor(templates=[user_profile, dynamic_salary, server_template]) + +# 1. Synthesize virtual A2UI component catalog for LLMs +synthetic_catalog = processor.generate_inference_catalog() + +# 2. Synchronously expand template invocations into standard A2UI primitives +expanded_components: A2UIComponentList = processor.expand_template( + instance_id="root", + template_id="ServerHealthCard", + passed_params={"serverId": "srv_01", "includeDisks": True}, +) +``` + +### 4. `TemplateInferenceFormat` + +Integrates templates seamlessly with LLM prompting and parsing. + +```python +from a2ui.inference_formats.experimental.template import TemplateInferenceFormat + +format_instance = TemplateInferenceFormat( + templates=[user_profile, dynamic_salary], + surface_id="main", + version="0.9.1", +) + +# Generate system prompt instructions with template signatures +system_prompt = format_instance.prompt_generator.generate( + role_description="You are an A2UI assistant.", + include_schema=True, +) + +# Parse response & synchronously expand templates to standard A2UI messages +messages = format_instance.parser.parse_response(llm_response_text) +``` diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/__init__.py b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/__init__.py new file mode 100644 index 0000000000..976321b584 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/__init__.py @@ -0,0 +1,81 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A2UI Template module providing parameterized component expansion and dynamic resolvers.""" + +from .models import ( + Template, + StaticTemplate, + DynamicTemplate, + dynamic_template, + BaseTemplate, + Param, + ParamType, + ParamRef, + Concat, + FormatExpr, + TemplateLoop, + TemplateComponent, + normalize_a2ui_type_to_jsonschema, + flatten_nested_layout, + normalize_node, +) +from .processor import ( + TemplateProcessor, + TemplateId, + InstanceId, + ComponentId, + ParamPath, + TemplateParams, + TemplateNodeDict, + A2UIComponent, + A2UIComponentList, + A2UIMessage, + CatalogSchema, + JSONSchemaDict, +) +from .format import TemplateInferenceFormat, A2uiTemplateManager, TemplateParser + +__all__ = [ + "Template", + "StaticTemplate", + "DynamicTemplate", + "dynamic_template", + "BaseTemplate", + "Param", + "ParamType", + "ParamRef", + "Concat", + "FormatExpr", + "TemplateLoop", + "TemplateComponent", + "normalize_a2ui_type_to_jsonschema", + "flatten_nested_layout", + "normalize_node", + "TemplateProcessor", + "TemplateId", + "InstanceId", + "ComponentId", + "ParamPath", + "TemplateParams", + "TemplateNodeDict", + "A2UIComponent", + "A2UIComponentList", + "A2UIMessage", + "CatalogSchema", + "JSONSchemaDict", + "TemplateInferenceFormat", + "A2uiTemplateManager", + "TemplateParser", +] diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/format.py b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/format.py new file mode 100644 index 0000000000..e1a91e2561 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/format.py @@ -0,0 +1,257 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Inference format coordinating prompt generation and parsing of LLM responses using templates.""" + +from __future__ import annotations + +from typing import Any, Callable, Dict, List, Optional, Sequence, Union +from a2ui.core.catalog import Catalog +from a2ui.inference_format import InferenceFormat +from a2ui.parser.parser import Parser +from a2ui.parser.response_part import ResponsePart +from a2ui.prompt import PromptGenerator +from a2ui.schema.catalog import A2uiCatalog +from a2ui.schema.constants import ( + COMMON_TYPES_SCHEMA_KEY, + SERVER_TO_CLIENT_SCHEMA_KEY, + SPEC_VERSION_MAP, +) +from a2ui.schema.utils import load_from_bundled_resource +from google.adk.utils.feature_decorator import experimental + +from .models import Template, StaticTemplate, DynamicTemplate, BaseTemplate +from .processor import TemplateProcessor + + +def _clean_version(version: str) -> str: + """Normalizes version string by removing leading 'v' if present.""" + return version.lstrip("v") + + +class TemplateParser(Parser): + """Parser decorator that runs template expansion on compiled A2UI messages.""" + + def __init__(self, underlying_parser: Parser, processor: TemplateProcessor): + """Initializes the TemplateParser. + + Args: + underlying_parser: The underlying inference format parser (e.g. + ExpressParser). + processor: The TemplateProcessor instance to expand templates. + """ + self.underlying_parser = underlying_parser + self.processor = processor + + def has_format_content(self, content: str, *, complete: bool = False) -> bool: + """Checks if the content contains blocks belonging to the underlying parser.""" + return self.underlying_parser.has_format_content(content, complete=complete) + + def unwrap(self, content: str) -> List[ResponsePart]: + """Tokenizes response content into raw format-content parts.""" + return self.underlying_parser.unwrap(content) + + def compile( + self, format_content: str, *, is_final: bool = True + ) -> List[Dict[str, Any]]: + """Compiles raw format content and expands all template components.""" + raw_msgs = self.underlying_parser.compile(format_content, is_final=is_final) + expanded = self.processor.process_message(raw_msgs) + if isinstance(expanded, list): + return expanded + elif isinstance(expanded, dict): + return [expanded] + return [] + + def parse_response(self, content: str) -> List[ResponsePart]: + """Parses full response content into standard JSON payload parts by unwrapping and expanding templates.""" + parts = self.unwrap(content) + parsed_so_far: List[ResponsePart] = [] + for part in parts: + if part.a2ui_raw is not None: + try: + part.a2ui_json = self.compile(part.a2ui_raw, is_final=part.is_final) + except Exception as e: + from a2ui.parser.errors import A2uiCompilationError + + if isinstance(e, A2uiCompilationError): + e.partial_results = parsed_so_far + raise e + raise A2uiCompilationError( + message=str(e), + raw_content=part.a2ui_raw, + partial_results=parsed_so_far, + ) from e + parsed_so_far.append(part) + return parts + + @property + def supports_streaming(self) -> bool: + """Streaming is intentionally disabled for template expansion to keep architectures simple.""" + return False + + def decompile(self, val: Any) -> str: + """Decompiles structured A2UI payloads into raw format notation.""" + return self.underlying_parser.decompile(val) + + def wrap_decompiled_blocks(self, blocks: List[str]) -> str: + """Wraps multiple decompiled blocks with the format's enclosing tags.""" + return self.underlying_parser.wrap_decompiled_blocks(blocks) + + +@experimental +class TemplateInferenceFormat(InferenceFormat): + """Inference format providing template generation and synchronous expansion.""" + + def __init__( + self, + templates: Sequence[ + Union[BaseTemplate, Template, StaticTemplate, DynamicTemplate] + ], + catalog: Optional[Union[Catalog[Any, Any], A2uiCatalog, Dict[str, Any]]] = None, + allowed_primitives: Optional[List[str]] = None, + surface_id: str = "main", + version: str = "0.9.1", + underlying_format_factory: Optional[ + Callable[[A2uiCatalog, str, str], InferenceFormat] + ] = None, + ): + """Initializes the TemplateInferenceFormat with registered templates and base catalog. + + Args: + templates: List of registered Template definitions. + catalog: Optional base catalog instance or schema dictionary. + allowed_primitives: List of primitive components from the base + catalog to allow. + surface_id: Surface identifier for layout targeting. + version: Target A2UI protocol version ("0.9", "0.9.1", or "1.0"). + underlying_format_factory: Optional custom factory for underlying + InferenceFormat. + """ + self.templates = templates + self.surface_id = surface_id + self.version = _clean_version(version) + self.allowed_primitives = allowed_primitives + + # 1. Resolve base catalog + if catalog is None: + from a2ui.basic_catalog.provider import BasicCatalog + + config = BasicCatalog.get_config(self.version) + schema = config.provider.load() + s2c = load_from_bundled_resource( + self.version, SERVER_TO_CLIENT_SCHEMA_KEY, SPEC_VERSION_MAP + ) + common_types = load_from_bundled_resource( + self.version, COMMON_TYPES_SCHEMA_KEY, SPEC_VERSION_MAP + ) + self.base_catalog = A2uiCatalog( + version=self.version, + name="basic", + catalog_schema=schema, + s2c_schema=s2c, + common_types_schema=common_types, + ) + elif isinstance(catalog, A2uiCatalog): + self.base_catalog = catalog + elif hasattr(catalog, "catalog_schema"): + s2c = getattr(catalog, "s2c_schema", None) or load_from_bundled_resource( + self.version, SERVER_TO_CLIENT_SCHEMA_KEY, SPEC_VERSION_MAP + ) + common_types = getattr( + catalog, "common_types_schema", None + ) or load_from_bundled_resource( + self.version, COMMON_TYPES_SCHEMA_KEY, SPEC_VERSION_MAP + ) + self.base_catalog = A2uiCatalog( + version=self.version, + name="custom", + catalog_schema=getattr(catalog, "catalog_schema"), + s2c_schema=s2c, + common_types_schema=common_types, + ) + else: + s2c = load_from_bundled_resource( + self.version, SERVER_TO_CLIENT_SCHEMA_KEY, SPEC_VERSION_MAP + ) + common_types = load_from_bundled_resource( + self.version, COMMON_TYPES_SCHEMA_KEY, SPEC_VERSION_MAP + ) + self.base_catalog = A2uiCatalog( + version=self.version, + name="custom", + catalog_schema=catalog if isinstance(catalog, dict) else {}, + s2c_schema=s2c, + common_types_schema=common_types, + ) + + if self.allowed_primitives is None and hasattr( + self.base_catalog, "catalog_schema" + ): + schema_dict = getattr(self.base_catalog, "catalog_schema", {}) + if isinstance(schema_dict, dict) and "components" in schema_dict: + self.allowed_primitives = list(schema_dict["components"].keys()) + + # 2. Initialize TemplateProcessor + self.processor = TemplateProcessor( + templates=self.templates, + catalogs=self.base_catalog, + version=self.version, + ) + + # 3. Construct synthetic A2uiCatalog containing allowed primitives + templates + self.synthetic_catalog_schema = self.processor.generate_inference_catalog( + allowed_primitives=self.allowed_primitives + ) + self.synthetic_catalog = A2uiCatalog( + version=self.version, + name="synthetic", + catalog_schema=self.synthetic_catalog_schema, + s2c_schema=self.base_catalog.s2c_schema, + common_types_schema=self.base_catalog.common_types_schema, + ) + + # 4. Initialize underlying inference format + express_version = f"v{self.version}" + if underlying_format_factory: + self._underlying_format = underlying_format_factory( + self.synthetic_catalog, self.surface_id, express_version + ) + else: + from a2ui.inference_formats.experimental.express.format import ( + ExpressFormat, + ) + + self._underlying_format = ExpressFormat( + catalog=self.synthetic_catalog, + surface_id=self.surface_id, + version=express_version, + ) + + # 5. Wrap parser with TemplateParser + self._parser = TemplateParser(self._underlying_format.parser, self.processor) + + @property + def parser(self) -> TemplateParser: + """The parser instance associated with the template inference format.""" + return self._parser + + @property + def prompt_generator(self) -> PromptGenerator: + """The prompt generator instance associated with the template inference format.""" + return self._underlying_format.prompt_generator + + +# Backward-compatibility alias +A2uiTemplateManager = TemplateInferenceFormat diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/models.py b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/models.py new file mode 100644 index 0000000000..36268835ee --- /dev/null +++ b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/models.py @@ -0,0 +1,1009 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Data models for A2UI Template definitions, typed parameters, expressions, and dynamic resolvers.""" + +from __future__ import annotations + +import asyncio +from enum import Enum +import functools +import inspect +import json +import os +from pathlib import Path +import re +from dataclasses import dataclass, field +from typing import Any, Callable, Dict, List, Optional, Tuple, Union +import jsonschema +import yaml + + +def _find_template_schema_path() -> Optional[Path]: + """Finds the template definition JSON schema in specification/proposals/templates/schema/.""" + current = Path(__file__).resolve() + for parent in current.parents: + candidate = ( + parent + / "specification" + / "proposals" + / "templates" + / "schema" + / "template_definition.json" + ) + if candidate.is_file(): + return candidate + return None + + +SCHEMA_PATH = _find_template_schema_path() +TEMPLATE_DEFINITION_SCHEMA: Optional[Dict[str, Any]] = None +if SCHEMA_PATH and SCHEMA_PATH.is_file(): + with open(SCHEMA_PATH, "r", encoding="utf-8") as _f: + TEMPLATE_DEFINITION_SCHEMA = json.load(_f) + + +class ParamType(str, Enum): + """Supported A2UI semantic parameter types.""" + + STRING = "string" + NUMBER = "number" + INTEGER = "integer" + BOOLEAN = "boolean" + ENUM = "enum" + OBJECT = "object" + ARRAY = "array" + CHILD = "child" + CHILDREN = "children" + ACTION = "action" + + +@dataclass +class Param: + """Strongly typed template parameter definition.""" + + type: Union[ParamType, str] + title: Optional[str] = None + description: Optional[str] = None + default: Optional[Any] = None + values: Optional[List[str]] = None + properties: Optional[Dict[str, Any]] = None + items: Optional[Union[Param, Dict[str, Any], str]] = None + required: bool = True + minimum: Optional[float] = None + maximum: Optional[float] = None + + @classmethod + def string( + cls, + description: Optional[str] = None, + title: Optional[str] = None, + default: Optional[str] = None, + ) -> Param: + return cls( + type=ParamType.STRING, + description=description, + title=title, + default=default, + ) + + @classmethod + def number( + cls, + description: Optional[str] = None, + title: Optional[str] = None, + default: Optional[float] = None, + ) -> Param: + return cls( + type=ParamType.NUMBER, + description=description, + title=title, + default=default, + ) + + @classmethod + def integer( + cls, + description: Optional[str] = None, + title: Optional[str] = None, + default: Optional[int] = None, + ) -> Param: + return cls( + type=ParamType.INTEGER, + description=description, + title=title, + default=default, + ) + + @classmethod + def boolean( + cls, + description: Optional[str] = None, + title: Optional[str] = None, + default: Optional[bool] = None, + ) -> Param: + return cls( + type=ParamType.BOOLEAN, + description=description, + title=title, + default=default, + ) + + @classmethod + def enum( + cls, + values: List[str], + description: Optional[str] = None, + title: Optional[str] = None, + default: Optional[str] = None, + ) -> Param: + return cls( + type=ParamType.ENUM, + values=values, + description=description, + title=title, + default=default, + ) + + @classmethod + def child( + cls, description: Optional[str] = None, title: Optional[str] = None + ) -> Param: + return cls(type=ParamType.CHILD, description=description, title=title) + + @classmethod + def children( + cls, description: Optional[str] = None, title: Optional[str] = None + ) -> Param: + return cls( + type=ParamType.CHILDREN, + description=description, + title=title, + default=[], + ) + + @classmethod + def action( + cls, description: Optional[str] = None, title: Optional[str] = None + ) -> Param: + return cls(type=ParamType.ACTION, description=description, title=title) + + @classmethod + def array( + cls, + items: Union[Param, Dict[str, Any], str], + description: Optional[str] = None, + title: Optional[str] = None, + ) -> Param: + return cls( + type=ParamType.ARRAY, items=items, description=description, title=title + ) + + @classmethod + def object( + cls, + properties: Dict[str, Any], + description: Optional[str] = None, + title: Optional[str] = None, + ) -> Param: + return cls( + type=ParamType.OBJECT, + properties=properties, + description=description, + title=title, + ) + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> Param: + raw_type = data.get("type", "string") + p_type = ( + ParamType(raw_type) + if raw_type in ParamType._value2member_map_ + else raw_type + ) + return cls( + type=p_type, + title=data.get("title"), + description=data.get("description"), + default=data.get("default"), + values=data.get("values"), + properties=data.get("properties"), + items=data.get("items"), + required=data.get("required", True), + minimum=data.get("minimum"), + maximum=data.get("maximum"), + ) + + def to_dict(self) -> Dict[str, Any]: + res: Dict[str, Any] = { + "type": ( + self.type.value if isinstance(self.type, ParamType) else str(self.type) + ) + } + if self.title: + res["title"] = self.title + if self.description: + res["description"] = self.description + if self.default is not None: + res["default"] = self.default + if self.values is not None: + res["values"] = self.values + if self.properties is not None: + res["properties"] = { + k: v.to_dict() if isinstance(v, Param) else v + for k, v in self.properties.items() + } + if self.items is not None: + res["items"] = ( + self.items.to_dict() if isinstance(self.items, Param) else self.items + ) + if self.minimum is not None: + res["minimum"] = self.minimum + if self.maximum is not None: + res["maximum"] = self.maximum + return res + + +@dataclass +class ParamRef: + """Direct reference to a parameter or dot path.""" + + param: str + default: Optional[Any] = None + + def to_dict(self) -> Dict[str, Any]: + res: Dict[str, Any] = {"param": self.param} + if self.default is not None: + res["default"] = self.default + return res + + +@dataclass +class Concat: + """String concatenation expression of literals and parameter references.""" + + concat: List[Union[str, ParamRef, Dict[str, Any]]] + + def to_dict(self) -> Dict[str, Any]: + return { + "concat": [ + (p.to_dict() if isinstance(p, ParamRef) else p) for p in self.concat + ] + } + + +@dataclass +class FormatExpr: + """String formatting expression with {key} arguments.""" + + format: str + args: Dict[str, Union[str, ParamRef, Dict[str, Any]]] + + def to_dict(self) -> Dict[str, Any]: + return { + "format": self.format, + "args": { + k: v.to_dict() if isinstance(v, ParamRef) else v + for k, v in self.args.items() + }, + } + + +@dataclass +class TemplateLoop: + """Array mapping parameter to child template instances or inline item layouts.""" + + param: str + template: Optional[str] = None + item: Optional[List[Union[TemplateComponent, Dict[str, Any]]]] = None + as_var: Optional[str] = None + + def to_dict(self) -> Dict[str, Any]: + res: Dict[str, Any] = {"param": self.param} + if self.template: + res["template"] = self.template + if self.item: + res["item"] = [ + (c.to_dict() if isinstance(c, TemplateComponent) else c) + for c in self.item + ] + if self.as_var: + res["as"] = self.as_var + return res + + +@dataclass +class TemplateComponent: + """Strongly typed template component definition.""" + + id: str + component: str + properties: Dict[str, Any] = field(default_factory=dict) + child: Optional[Union[str, ParamRef, Dict[str, Any]]] = None + children: Optional[Union[List[Any], ParamRef, TemplateLoop, Dict[str, Any]]] = None + catalog_id: Optional[str] = None + + def to_dict(self) -> Dict[str, Any]: + res: Dict[str, Any] = {"id": self.id, "component": self.component} + if self.catalog_id is not None: + res["catalogId"] = self.catalog_id + if self.child is not None: + res["child"] = ( + self.child.to_dict() if isinstance(self.child, ParamRef) else self.child + ) + if self.children is not None: + if isinstance(self.children, (ParamRef, TemplateLoop)): + res["children"] = self.children.to_dict() + else: + res["children"] = self.children + for k, v in self.properties.items(): + if isinstance(v, (ParamRef, Concat, FormatExpr, TemplateLoop)): + res[k] = v.to_dict() + else: + res[k] = v + return res + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> TemplateComponent: + data_copy = dict(data) + c_id = data_copy.pop("id") + c_type = data_copy.pop("component") + c_cat = data_copy.pop("catalogId", None) or data_copy.pop("catalog_id", None) + child = data_copy.pop("child", None) + children = data_copy.pop("children", None) + return cls( + id=c_id, + component=c_type, + catalog_id=c_cat, + properties=data_copy, + child=child, + children=children, + ) + + +def normalize_node(node: Any) -> Any: + """Polymorphically converts builder objects, dataclasses, or Pydantic models into dicts.""" + if node is None: + return None + if hasattr(node, "to_dict") and callable(node.to_dict): + return node.to_dict() + if hasattr(node, "model_dump") and callable(node.model_dump): + return node.model_dump(exclude_none=True, by_alias=True) + import dataclasses + + if dataclasses.is_dataclass(node) and not isinstance(node, type): + return dataclasses.asdict(node) + return node + + +def flatten_nested_layout( + node: Any, + parent_id: Optional[str] = None, + slot_name: Optional[str] = None, + index: Optional[int] = None, +) -> Tuple[str, List[Dict[str, Any]]]: + """Recursively flattens a nested layout tree (dicts, builder objects) into a flat component graph with synthetic IDs. + + Returns: + Tuple of (assigned_component_id, list_of_flattened_components) + """ + node = normalize_node(node) + if not isinstance(node, dict): + return str(node), [] + + node_copy = dict(node) + comp_type = node_copy.get("component", "Node").lower() + + # 1. Determine or generate synthetic component ID + if "id" in node_copy and node_copy["id"]: + node_id = str(node_copy["id"]) + elif parent_id is None: + node_id = "root" + elif slot_name and index is not None: + node_id = f"{parent_id}_{slot_name}_{index}_{comp_type}" + elif slot_name: + node_id = f"{parent_id}_{slot_name}_{comp_type}" + elif index is not None: + node_id = f"{parent_id}_{index}_{comp_type}" + else: + node_id = f"{parent_id}_{comp_type}" + + node_copy["id"] = node_id + flat_components: List[Dict[str, Any]] = [] + + # 2. Process nested 'child' + if "child" in node_copy: + child_val = normalize_node(node_copy["child"]) + if isinstance(child_val, dict) and "component" in child_val: + child_id, sub_comps = flatten_nested_layout( + child_val, parent_id=node_id, slot_name="child" + ) + node_copy["child"] = child_id + flat_components.extend(sub_comps) + else: + node_copy["child"] = child_val + + # 3. Process nested 'children' + if "children" in node_copy: + children_val = normalize_node(node_copy["children"]) + if isinstance(children_val, list): + flattened_child_ids: List[Any] = [] + for idx, raw_item in enumerate(children_val): + item = normalize_node(raw_item) + if isinstance(item, dict) and "component" in item: + item_id, sub_comps = flatten_nested_layout( + item, parent_id=node_id, slot_name="child", index=idx + ) + flattened_child_ids.append(item_id) + flat_components.extend(sub_comps) + elif isinstance(item, dict) and "loop" in item: + # Loop inside children list + loop_cfg = item["loop"] + loop_dict: Dict[str, Any] = {"param": loop_cfg.get("param")} + if "as" in loop_cfg: + loop_dict["as"] = loop_cfg["as"] + if "item" in loop_cfg and isinstance(loop_cfg["item"], dict): + _, item_sub_comps = flatten_nested_layout(loop_cfg["item"]) + loop_dict["item"] = item_sub_comps + elif "template" in loop_cfg: + loop_dict["template"] = loop_cfg["template"] + flattened_child_ids.append(loop_dict) + else: + flattened_child_ids.append(item) + node_copy["children"] = flattened_child_ids + elif isinstance(children_val, dict) and "loop" in children_val: + loop_cfg = children_val["loop"] + loop_dict = {"param": loop_cfg.get("param")} + if "as" in loop_cfg: + loop_dict["as"] = loop_cfg["as"] + if "item" in loop_cfg and isinstance(loop_cfg["item"], dict): + _, item_sub_comps = flatten_nested_layout(loop_cfg["item"]) + loop_dict["item"] = item_sub_comps + elif "template" in loop_cfg: + loop_dict["template"] = loop_cfg["template"] + node_copy["children"] = loop_dict + else: + node_copy["children"] = children_val + + flat_components.insert(0, node_copy) + return node_id, flat_components + + +def normalize_a2ui_type_to_jsonschema(meta: Any) -> Any: + """Recursively converts an A2UI parameter type schema into standard JSON Schema.""" + if isinstance(meta, Param): + meta = meta.to_dict() + if not isinstance(meta, dict): + return meta + schema = dict(meta) + p_type = schema.get("type") + if p_type == "enum" and "values" in schema: + schema["type"] = "string" + schema["enum"] = schema.pop("values") + elif p_type in ["child", "action"]: + schema["type"] = "string" + elif p_type == "children": + schema["type"] = "array" + schema["items"] = {"type": "string"} + + if "properties" in schema and isinstance(schema["properties"], dict): + schema["properties"] = { + k: normalize_a2ui_type_to_jsonschema(v) + for k, v in schema["properties"].items() + } + if "items" in schema: + if isinstance(schema["items"], (dict, Param)): + schema["items"] = normalize_a2ui_type_to_jsonschema(schema["items"]) + elif isinstance(schema["items"], str): + schema["items"] = {"type": schema["items"]} + return schema + + +@dataclass +class BaseTemplate: + """Base class for all templates.""" + + name: str = "" + catalogs: List[str] = field(default_factory=list) + id: Optional[str] = None + imports: Union[List[str], Dict[str, str]] = field(default_factory=list) + version: str = "0.1" + description: Optional[str] = None + sample_data: Optional[Dict[str, Any]] = None + is_dynamic: bool = False + template_id: str = "" + + def __post_init__(self): + if not self.name and self.template_id: + self.name = self.template_id + elif not self.template_id and self.name: + self.template_id = self.name + if isinstance(self.catalogs, str): + self.catalogs = [self.catalogs] + + +@dataclass +class StaticTemplate(BaseTemplate): + """Declarative A2UI template definition authored in YAML with layout trees and parameter substitutions.""" + + parameters: Dict[str, Union[Param, Dict[str, Any]]] = field(default_factory=dict) + components: List[Union[TemplateComponent, Dict[str, Any]]] = field( + default_factory=list + ) + raw_layout: Optional[Dict[str, Any]] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> StaticTemplate: + """Constructs a StaticTemplate instance from a dictionary payload.""" + name = data.get("name") or data.get("templateId") or data.get("template_id") + if not name: + raise ValueError( + "Template dictionary must contain 'name' (or 'templateId')." + ) + + version = data.get("version") + if not version: + raise ValueError(f"Template '{name}' missing required 'version' attribute.") + if version != "0.1": + raise ValueError( + f"Unsupported template version '{version}'. Currently only '0.1' is" + " supported." + ) + + catalogs_raw = data.get("catalogs", []) + if isinstance(catalogs_raw, str): + catalogs = [catalogs_raw] + elif isinstance(catalogs_raw, (list, tuple)): + catalogs = list(catalogs_raw) + else: + catalogs = [] + + id_val = data.get("id") + imports = data.get("imports", []) + + raw_params = data.get("parameters", {}) + parsed_params: Dict[str, Union[Param, Dict[str, Any]]] = {} + for k, v in raw_params.items(): + parsed_params[k] = Param.from_dict(v) if isinstance(v, dict) else v + + # Flatten nested layout if provided + raw_layout = data.get("layout") + components: List[Union[TemplateComponent, Dict[str, Any]]] = [] + if raw_layout and isinstance(raw_layout, dict): + _, flat_comps = flatten_nested_layout(raw_layout) + components = list(flat_comps) + elif "components" in data and isinstance(data["components"], list): + components = list(data["components"]) + else: + raise ValueError( + f"Template '{name}' must declare a 'layout' tree definition." + ) + + instance = cls( + name=name, + catalogs=catalogs, + id=id_val, + imports=imports, + template_id=name, + version=version, + parameters=parsed_params, + components=components, + raw_layout=raw_layout, + sample_data=data.get("sampleData") or data.get("sample_data"), + description=data.get("description"), + is_dynamic=False, + ) + instance.validate_definition() + return instance + + @classmethod + def from_yaml_string(cls, yaml_content: str) -> List[StaticTemplate]: + """Parses a YAML string containing one or more '---' separated template documents.""" + docs = list(yaml.safe_load_all(yaml_content)) + templates: List[StaticTemplate] = [] + for doc in docs: + if not doc or not isinstance(doc, dict): + continue + templates.append(cls.from_dict(doc)) + if not templates: + raise ValueError("No valid template definitions found in YAML content.") + return templates + + @classmethod + def from_yaml_file(cls, file_path: Union[str, Path]) -> List[StaticTemplate]: + """Loads and parses all Template definitions from a YAML file.""" + with open(file_path, "r", encoding="utf-8") as f: + content = f.read() + return cls.from_yaml_string(content) + + @classmethod + def from_yaml(cls, yaml_content: str) -> StaticTemplate: + """Convenience method to load a single template definition from YAML.""" + templates = cls.from_yaml_string(yaml_content) + return templates[0] + + def to_dict(self) -> Dict[str, Any]: + """Serializes the template instance to a dictionary.""" + params_dict: Dict[str, Any] = {} + for k, v in self.parameters.items(): + params_dict[k] = v.to_dict() if isinstance(v, Param) else v + + comps_list: List[Dict[str, Any]] = [] + for c in self.components: + comps_list.append(c.to_dict() if isinstance(c, TemplateComponent) else c) + + res: Dict[str, Any] = { + "version": self.version, + "name": self.name, + "templateId": self.name, + "catalogs": self.catalogs, + "parameters": params_dict, + } + if self.id is not None: + res["id"] = self.id + if self.imports: + res["imports"] = self.imports + if self.raw_layout is not None: + res["layout"] = self.raw_layout + else: + res["components"] = comps_list + + if self.description: + res["description"] = self.description + if self.sample_data is not None: + res["sampleData"] = self.sample_data + return res + + def to_yaml(self) -> str: + """Serializes the template instance to a clean YAML string.""" + return yaml.dump(self.to_dict(), sort_keys=False) + + @staticmethod + def _collect_loop_vars(val: Any, loop_vars: set) -> None: + if isinstance(val, dict): + if "as" in val and isinstance(val["as"], str): + loop_vars.add(val["as"]) + for v in val.values(): + StaticTemplate._collect_loop_vars(v, loop_vars) + elif isinstance(val, list): + for item in val: + StaticTemplate._collect_loop_vars(item, loop_vars) + + def _check_val(self, val: Any, loop_vars: set) -> None: + expr_pattern = re.compile(r"(? None: + parts = path.split(".") + root = parts[0] + if root not in self.parameters: + if root.startswith("__") or root in loop_vars: + return + raise ValueError( + f"Template '{self.template_id}': Component references parameter" + f" '{root}' in '{path}', but it is not declared in template" + " parameters." + ) + + curr_schema = self.parameters[root] + if isinstance(curr_schema, Param): + curr_schema = curr_schema.to_dict() + for part in parts[1:]: + if isinstance(curr_schema, dict) and "properties" in curr_schema: + props = curr_schema.get("properties", {}) + if part not in props: + raise ValueError( + f"Template '{self.template_id}': Component references" + f" property '{part}' in '{path}', but it is not declared in" + f" parameter '{root}' properties." + ) + curr_schema = props[part] + + def validate_definition(self) -> None: + """Statically validates the template against the JSON Schema, verifies parameter references, and validates sampleData.""" + if TEMPLATE_DEFINITION_SCHEMA is not None: + raw_dict = self.to_dict() + try: + jsonschema.validate( + instance=raw_dict, schema=TEMPLATE_DEFINITION_SCHEMA + ) + except jsonschema.ValidationError as err: + raise ValueError( + f"Template '{self.template_id}' fails template_definition.json" + f" schema: {err.message}" + ) from err + + loop_vars = {"item"} + for comp in self.components: + comp_dict = comp.to_dict() if isinstance(comp, TemplateComponent) else comp + self._collect_loop_vars(comp_dict, loop_vars) + + for comp in self.components: + comp_dict = comp.to_dict() if isinstance(comp, TemplateComponent) else comp + self._check_val(comp_dict, loop_vars) + + if self.sample_data and isinstance(self.sample_data, dict): + for p_name, p_val in self.sample_data.items(): + if p_name in self.parameters: + p_meta = self.parameters[p_name] + if isinstance(p_meta, Param): + p_type = ( + p_meta.type.value + if isinstance(p_meta.type, ParamType) + else str(p_meta.type) + ) + else: + p_type = str(p_meta.get("type", "string")) + if p_type in ["child", "children", "action"]: + continue + + val_schema = normalize_a2ui_type_to_jsonschema(p_meta) + try: + jsonschema.validate(instance=p_val, schema=val_schema) + except jsonschema.ValidationError as err: + raise ValueError( + f"Template '{self.template_id}': sampleData for parameter" + f" '{p_name}' fails validation: {err.message}" + ) from err + + +# Retain Template alias for backward compatibility +Template = StaticTemplate + + +class DynamicTemplate(BaseTemplate): + """Programmatic template that either executes a data resolver for a static layout or runs a render function returning an AST.""" + + def __init__( + self, + name: Optional[str] = None, + catalogs: Optional[Union[List[str], str]] = None, + id: Optional[str] = None, + imports: Optional[Union[List[str], Dict[str, str]]] = None, + render: Optional[Callable[..., Any]] = None, + resolver: Optional[Callable[..., Any]] = None, + layout: Optional[Union[StaticTemplate, str, Dict[str, Any]]] = None, + parameters: Optional[Dict[str, Union[Param, Dict[str, Any]]]] = None, + description: Optional[str] = None, + sample_data: Optional[Dict[str, Any]] = None, + render_fn: Optional[Callable[..., Any]] = None, + version: str = "0.1", + template_id: Optional[str] = None, + ): + template_name = name or template_id + if not template_name: + raise ValueError("DynamicTemplate must provide 'name' (or 'template_id').") + + self.layout: Optional[StaticTemplate] = None + if layout is not None: + if isinstance(layout, str): + if os.path.exists(layout): + self.layout = StaticTemplate.from_yaml_file(layout)[0] + else: + self.layout = StaticTemplate.from_yaml(layout) + elif isinstance(layout, dict): + self.layout = StaticTemplate.from_dict(layout) + else: + self.layout = layout + + catalogs_list: List[str] = [] + if catalogs is not None: + catalogs_list = [catalogs] if isinstance(catalogs, str) else list(catalogs) + elif self.layout is not None and self.layout.catalogs: + catalogs_list = list(self.layout.catalogs) + + super().__init__( + name=template_name, + catalogs=catalogs_list, + id=id, + imports=imports or [], + template_id=template_name, + version=version, + description=description, + sample_data=sample_data, + is_dynamic=True, + ) + self.render_fn = render or render_fn + self.resolver = resolver + + target_fn = self.render_fn or self.resolver + if target_fn is None and self.layout is None: + raise ValueError( + f"DynamicTemplate '{template_name}' must provide either a 'render'" + " function or a ('resolver', 'layout') pair." + ) + + if parameters is not None: + self.parameters = parameters + elif target_fn is not None: + self.parameters = self._infer_parameters_from_resolver(target_fn) + else: + self.parameters = {} + + @staticmethod + def _infer_parameters_from_resolver( + fn: Callable[..., Any], + ) -> Dict[str, Union[Param, Dict[str, Any]]]: + """Automatically derives parameter definitions from the Python function signature.""" + sig = inspect.signature(fn) + inferred: Dict[str, Union[Param, Dict[str, Any]]] = {} + type_map = { + str: ParamType.STRING, + int: ParamType.INTEGER, + float: ParamType.NUMBER, + bool: ParamType.BOOLEAN, + } + for name, p in sig.parameters.items(): + if name in ["self", "context"] or p.kind in ( + inspect.Parameter.VAR_POSITIONAL, + inspect.Parameter.VAR_KEYWORD, + ): + continue + p_type = type_map.get(p.annotation, ParamType.STRING) + default = p.default if p.default is not inspect.Parameter.empty else None + inferred[name] = Param( + type=p_type, + default=default, + description=f"Input parameter '{name}' for dynamic resolver.", + ) + return inferred + + def resolve(self, passed_params: Dict[str, Any]) -> Dict[str, Any]: + """Executes the resolver synchronously or asynchronously.""" + if self.resolver is None: + return {} + if isinstance(passed_params, dict): + sig = inspect.signature(self.resolver) + has_kwargs = any( + p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values() + ) + if has_kwargs: + filtered_params = passed_params + else: + filtered_params = { + k: v for k, v in passed_params.items() if k in sig.parameters + } + res = self.resolver(**filtered_params) + elif isinstance(passed_params, list): + res = self.resolver(*passed_params) + else: + res = self.resolver(passed_params) + + if asyncio.iscoroutine(res): + try: + loop = asyncio.get_event_loop() + if loop.is_running(): + try: + import nest_asyncio # type: ignore + + nest_asyncio.apply() + except ImportError as err: + raise RuntimeError( + "An event loop is already running. Please install" + " 'nest-asyncio' to run async resolvers synchronously." + ) from err + res_val = loop.run_until_complete(res) + else: + res_val = loop.run_until_complete(res) + except RuntimeError as err: + if "already running" in str(err) or "run_until_complete" in str(err): + raise + res_val = asyncio.run(res) + except Exception: + res_val = asyncio.run(res) + return dict(res_val) if isinstance(res_val, dict) else {} + return dict(res) if isinstance(res, dict) else {} + + def to_dict(self) -> Dict[str, Any]: + params_dict: Dict[str, Any] = {} + for k, v in self.parameters.items(): + params_dict[k] = v.to_dict() if isinstance(v, Param) else v + + comps_list = [] + if self.layout is not None: + comps_list = [ + (c.to_dict() if isinstance(c, TemplateComponent) else c) + for c in self.layout.components + ] + + res: Dict[str, Any] = { + "version": self.version, + "templateId": self.template_id, + "parameters": params_dict, + "components": comps_list, + "isDynamic": True, + } + if self.description: + res["description"] = self.description + if self.sample_data is not None: + res["sampleData"] = self.sample_data + return res + + def __call__(self, *args: Any, **kwargs: Any) -> Any: + """Allows the DynamicTemplate instance to remain directly callable in unit tests or user code.""" + if self.render_fn is not None: + return self.render_fn(*args, **kwargs) + if self.resolver is not None: + return self.resolve(kwargs if kwargs else (args[0] if args else {})) + raise TypeError(f"DynamicTemplate '{self.name}' is not callable.") + + def to_yaml(self) -> str: + """Serializes the dynamic template or underlying layout to a clean YAML string.""" + if self.layout is not None: + return self.layout.to_yaml() + return yaml.dump(self.to_dict(), sort_keys=False) + + +def dynamic_template( + name_or_fn: Optional[Union[str, Callable[..., Any]]] = None, + *, + name: Optional[str] = None, + catalogs: Optional[Union[List[str], str]] = None, + id: Optional[str] = None, + imports: Optional[Union[List[str], Dict[str, str]]] = None, + description: Optional[str] = None, + sample_data: Optional[Dict[str, Any]] = None, + version: str = "0.1", + **kwargs: Any, +) -> Union[DynamicTemplate, Callable[[Callable[..., Any]], DynamicTemplate]]: + """Decorator to declare an A2UI DynamicTemplate directly on a Python render function. + + Can be used with or without arguments: + @dynamic_template(catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"]) + def user_card(title: str): ... + + @dynamic_template + def user_card(title: str): ... + """ + + def _decorator(fn: Callable[..., Any]) -> DynamicTemplate: + explicit_name = name or (name_or_fn if isinstance(name_or_fn, str) else None) + tmpl_name = explicit_name or "".join( + word.capitalize() for word in fn.__name__.split("_") + ) + desc = description or (fn.__doc__.strip() if fn.__doc__ else None) + + tmpl = DynamicTemplate( + name=tmpl_name, + catalogs=catalogs, + id=id, + imports=imports, + render=fn, + description=desc, + sample_data=sample_data, + version=version, + **kwargs, + ) + functools.update_wrapper(tmpl, fn) + return tmpl + + if callable(name_or_fn): + return _decorator(name_or_fn) + return _decorator diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/processor.py b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/processor.py new file mode 100644 index 0000000000..4bf4d57949 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/template/processor.py @@ -0,0 +1,1111 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Core processing, expansion engine, and dynamic resolver execution for A2UI Templates.""" + +from __future__ import annotations + +import asyncio +import inspect +import re +from typing import ( + Any, + Dict, + List, + Mapping, + Optional, + Sequence, + Tuple, + TypeAlias, + Union, +) +import jsonschema +from .models import ( + Template, + StaticTemplate, + DynamicTemplate, + BaseTemplate, + Param, + ParamType, + ParamRef, + Concat, + FormatExpr, + TemplateLoop, + TemplateComponent, + normalize_a2ui_type_to_jsonschema, + flatten_nested_layout, +) + +# --------------------------------------------------------------------------- +# Strong Semantic Type Aliases +# --------------------------------------------------------------------------- + +# 1. Identifier Types +TemplateId: TypeAlias = str +InstanceId: TypeAlias = str +ComponentId: TypeAlias = str +ParamPath: TypeAlias = str + +# 2. Template Evaluation Types +TemplateParams: TypeAlias = Mapping[str, Any] +TemplateNodeDict: TypeAlias = Dict[str, Any] + +# 3. Standard A2UI Wire-Format Output Types +A2UIComponent: TypeAlias = Dict[str, Any] +A2UIComponentList: TypeAlias = List[A2UIComponent] +A2UIMessage: TypeAlias = Dict[str, Any] + +# 4. Catalog and Schema Types +CatalogSchema: TypeAlias = Dict[str, Any] +JSONSchemaDict: TypeAlias = Dict[str, Any] + +# 5. Safety & Recursion Limits +MAX_EXPANSION_DEPTH: int = 50 + +__all__ = [ + "MAX_EXPANSION_DEPTH", + "TemplateProcessor", + "TemplateId", + "InstanceId", + "ComponentId", + "ParamPath", + "TemplateParams", + "TemplateNodeDict", + "A2UIComponent", + "A2UIComponentList", + "A2UIMessage", + "CatalogSchema", + "JSONSchemaDict", +] + + +def _resolve_param_path(path: ParamPath, params: TemplateParams) -> Tuple[bool, Any]: + """Resolves a dot-separated parameter path (e.g. 'user.name' or 'user.metrics.count') from params dict.""" + parts = path.split(".") + curr: Any = params + for part in parts: + if isinstance(curr, (dict, Mapping)) and part in curr: + curr = curr[part] + elif ( + isinstance(curr, (list, tuple)) and part.isdigit() and int(part) < len(curr) + ): + curr = curr[int(part)] + else: + return False, None + return True, curr + + +def _substitute_params(val: Any, params: TemplateParams) -> Any: + """Recursively replaces parameter references with their resolved values.""" + if isinstance(val, (ParamRef, Concat, FormatExpr, TemplateLoop)): + val = val.to_dict() + + if isinstance(val, dict): + # 1. Direct param reference: {"param": "userName", "default": ...} + if ( + "param" in val + and isinstance(val["param"], str) + and "template" not in val + and "item" not in val + ): + param_path = val["param"] + found, res = _resolve_param_path(param_path, params) + if found and res is not None: + return res + if "default" in val: + return val["default"] + return None + + # 2. String concatenation: {"concat": ["Strategic Objectives: ", {"param": "teamName"}]} + if "concat" in val and isinstance(val["concat"], list): + parts = [] + for item in val["concat"]: + sub = _substitute_params(item, params) + if sub is not None: + parts.append(str(sub)) + return "".join(parts) + + # 3. String formatting: {"format": "Competency: {name}", "args": {...}} + if "format" in val and "args" in val and isinstance(val["args"], dict): + fmt_str = str(val["format"]) + args_sub = { + k: _substitute_params(v, params) for k, v in val["args"].items() + } + try: + return fmt_str.format(**args_sub) + except Exception: + return fmt_str + + # 4. Standard dictionary traversal + return {k: _substitute_params(v, params) for k, v in val.items()} + + elif isinstance(val, list): + return [_substitute_params(x, params) for x in val] + + elif isinstance(val, str): + # 1. Exact parameter match preserving type: e.g. "{{ user }}", "{{user}}", "${user}" + match = re.match(r"^(?:\{\{\s*|\$\{)([\w\.]+)(?:\s*\}\}|\})$", val) + if match: + param_path = match.group(1) + found, res = _resolve_param_path(param_path, params) + if found: + return res + + # 2. Check for exact escaped token match: e.g. r"\{{ user }}" -> "{{ user }}" or r"\${user}" -> "${user}" + escaped_match = re.match(r"^\\((?:\{\{|\$\{)[^}]*(?:\}\}|\}))$", val) + if escaped_match: + return escaped_match.group(1) + + # 3. In-string replacement with escape handling: + def replacer(m: re.Match[str]) -> str: + path = m.group(1) + found, res = _resolve_param_path(path, params) + if found and res is not None: + return str(res) + return str(m.group(0)) + + # Replace unescaped Mustache tokens: (? "{{...}}" and r"\${...}" -> "${...}" + final_str = re.sub(r"\\(\{\{.*?\}\}|\$\{.*?\})", r"\1", substituted) + return final_str + + return val + + +# Private aliases for internal backwards-compatibility if referenced +resolve_param_path = _resolve_param_path +substitute_params = _substitute_params + + +class TemplateProcessor: + """Manages template registration, synthetic catalog compilation, and payload expansion.""" + + def __init__( + self, + templates: Sequence[ + Union[BaseTemplate, Template, StaticTemplate, DynamicTemplate] + ], + catalogs: Optional[ + Union[ + CatalogSchema, Sequence[CatalogSchema], Mapping[str, CatalogSchema], Any + ] + ] = None, + base_catalog: Optional[Union[CatalogSchema, Any]] = None, + version: str = "v0.9.1", + ): + """Initializes the TemplateProcessor. + + Args: + templates: List of registered Template definitions. + catalogs: Mandatory catalog schema(s) or A2uiCatalog instance(s) that templates + are validated and resolved against. No default to basic catalog is assumed. + base_catalog: Backwards-compatible alias for catalogs. + version: Target A2UI protocol version ("v0.9", "v0.9.1", or "v1.0"). + """ + raw_catalogs = catalogs if catalogs is not None else base_catalog + if raw_catalogs is None: + raise ValueError( + "TemplateProcessor requires explicit catalog(s) to be provided via" + " 'catalogs'. No defaults to the basic catalog are assumed." + ) + + self.version = version + self.catalogs: Dict[str, CatalogSchema] = {} + + def _extract_catalog(c: Any) -> Tuple[str, CatalogSchema]: + if hasattr(c, "catalog_schema") and isinstance(c.catalog_schema, dict): + schema = c.catalog_schema + elif isinstance(c, dict): + schema = c + else: + raise ValueError(f"Invalid catalog object: {type(c)}") + c_id = ( + schema.get("catalogId") + or schema.get("$id") + or schema.get("id") + or "default" + ) + return str(c_id), schema + + def _register_catalog(c_id: str, schema: CatalogSchema) -> None: + self.catalogs[c_id] = schema + if "v0_9/catalogs/basic/catalog.json" in c_id: + self.catalogs[c_id.replace("v0_9/", "v0_9_1/")] = schema + elif "v0_9_1/catalogs/basic/catalog.json" in c_id: + self.catalogs[c_id.replace("v0_9_1/", "v0_9/")] = schema + + if isinstance(raw_catalogs, (list, tuple, set)): + for item in raw_catalogs: + c_id, s = _extract_catalog(item) + _register_catalog(c_id, s) + elif isinstance(raw_catalogs, dict): + if ( + "components" in raw_catalogs + or "$id" in raw_catalogs + or "catalogId" in raw_catalogs + ): + c_id, s = _extract_catalog(raw_catalogs) + _register_catalog(c_id, s) + else: + for k, v in raw_catalogs.items(): + _, s = _extract_catalog(v) + _register_catalog(str(k), s) + else: + c_id, s = _extract_catalog(raw_catalogs) + _register_catalog(c_id, s) + + if not self.catalogs: + raise ValueError( + "TemplateProcessor requires at least one catalog. Empty catalog" + " collection provided." + ) + + self.base_catalog_id = next(iter(self.catalogs.keys())) + self.base_catalog = self.catalogs[self.base_catalog_id] + + self.templates: Dict[ + TemplateId, Union[BaseTemplate, Template, StaticTemplate, DynamicTemplate] + ] = {} + self.templates_by_id: Dict[ + str, Union[BaseTemplate, Template, StaticTemplate, DynamicTemplate] + ] = {} + + for t in templates: + t_name = getattr(t, "name", None) or getattr(t, "template_id", None) + if not t_name: + continue + self.templates[t_name] = t + self.templates[t.template_id] = t + t_id = getattr(t, "id", None) + if t_id: + self.templates_by_id[t_id] = t + self.templates[t_id] = t + + self._validate_templates() + + def generate_inference_catalog( + self, + allowed_primitives: Optional[Sequence[str]] = None, + ) -> CatalogSchema: + """Generates a synthetic JSON catalog containing allowed primitives and all registered templates.""" + if allowed_primitives is None: + allowed_primitives = [] + for cat in self.catalogs.values(): + for comp_k in cat.get("components", {}).keys(): + if comp_k not in allowed_primitives: + allowed_primitives.append(comp_k) + + catalog_id = ( + self.base_catalog_id + if self.base_catalog_id + else "https://a2ui.org/catalog/synthetic" + ) + + synthetic_catalog: CatalogSchema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": catalog_id, + "catalogId": catalog_id, + "title": "A2UI Synthetic Inference Catalog", + "components": {}, + "functions": ( + self.base_catalog.get("functions", {}) + if self.base_catalog is not None + else {} + ), + "$defs": { + "anyComponent": { + "oneOf": [], + "discriminator": {"propertyName": "component"}, + }, + "anyFunction": ( + self.base_catalog.get("$defs", {}).get("anyFunction", {}) + if self.base_catalog is not None + else {} + ), + }, + } + + # 1. Copy over allowed primitives from registered catalogs + for cat in self.catalogs.values(): + base_components = cat.get("components", {}) + for prim in allowed_primitives: + if ( + prim in base_components + and prim not in synthetic_catalog["components"] + ): + synthetic_catalog["components"][prim] = base_components[prim] + synthetic_catalog["$defs"]["anyComponent"]["oneOf"].append( + {"$ref": f"#/components/{prim}"} + ) + + # 2. Add registered custom templates as high-level component schemas + common_types_url = ( + "https://a2ui.org/specification/v0_9/common_types.json" + if "0.9" in self.version + else "https://a2ui.org/specification/v1_0/common_types.json" + ) + + seen_templates = set() + for template in self.templates.values(): + t_id = getattr(template, "name", template.template_id) + if t_id in seen_templates: + continue + seen_templates.add(t_id) + + param_required = [] + properties_dict: Dict[str, Any] = {"component": {"const": t_id}} + + raw_params = ( + template.parameters.items() if hasattr(template, "parameters") else {} + ) + + for p_name, p_meta in raw_params: + p_meta_dict = p_meta.to_dict() if isinstance(p_meta, Param) else p_meta + properties_dict[p_name] = self._promote_parameter(p_meta_dict) + p_type = ( + p_meta.type.value + if isinstance(p_meta, Param) and isinstance(p_meta.type, ParamType) + else ( + p_meta.get("type") + if isinstance(p_meta, dict) + else getattr(p_meta, "type", None) + ) + ) + has_default = ( + p_meta.default is not None + if isinstance(p_meta, Param) + else (isinstance(p_meta, dict) and "default" in p_meta) + ) + if not has_default and p_type != "array": + param_required.append(p_name) + + template_schema = { + "type": "object", + "allOf": [ + {"$ref": f"{common_types_url}#/$defs/ComponentCommon"}, + { + "type": "object", + "properties": properties_dict, + "required": ["component"] + param_required, + }, + ], + "unevaluatedProperties": False, + } + if template.description: + template_schema["description"] = template.description + + synthetic_catalog["components"][t_id] = template_schema + synthetic_catalog["$defs"]["anyComponent"]["oneOf"].append( + {"$ref": f"#/components/{t_id}"} + ) + + return synthetic_catalog + + def expand_template( + self, + instance_id: InstanceId, + template_id: TemplateId, + passed_params: TemplateParams, + _depth: int = 0, + _call_stack: Optional[List[TemplateId]] = None, + ) -> A2UIComponentList: + """Recursively expands a template instance into standard primitive components.""" + if _call_stack is None: + _call_stack = [] + + template = self.templates.get(template_id) + if not template: + available = list(self.templates.keys()) + raise ValueError( + f"Template '{template_id}' is not registered. Available: {available}" + ) + + if template_id in _call_stack: + raise ValueError( + f"Circular template reference detected: {' -> '.join(_call_stack)} ->" + f" {template_id}" + ) + + if _depth > MAX_EXPANSION_DEPTH: + raise RecursionError( + f"Maximum template expansion depth exceeded ({_depth}) at" + f" '{template_id}'. Call stack: {' -> '.join(_call_stack)}" + ) + + current_stack = _call_stack + [template_id] + + # 1. Handle DynamicTemplate execution + if getattr(template, "is_dynamic", False): + dynamic_tmpl: DynamicTemplate = template # type: ignore + + # Mode A: Programmatic Render Function (returns AST tree or list directly) + if dynamic_tmpl.render_fn is not None: + if isinstance(passed_params, (dict, Mapping)): + sig = inspect.signature(dynamic_tmpl.render_fn) + has_kwargs = any( + p.kind == inspect.Parameter.VAR_KEYWORD + for p in sig.parameters.values() + ) + if has_kwargs: + filtered_params = dict(passed_params) + else: + filtered_params = { + k: v + for k, v in passed_params.items() + if k in sig.parameters + } + res = dynamic_tmpl.render_fn(**filtered_params) + elif isinstance(passed_params, list): + res = dynamic_tmpl.render_fn(*passed_params) + else: + res = dynamic_tmpl.render_fn(passed_params) + if asyncio.iscoroutine(res): + try: + loop = asyncio.get_event_loop() + if loop.is_running(): + try: + import nest_asyncio # type: ignore + + nest_asyncio.apply() + except ImportError as err: + raise RuntimeError( + "An event loop is already running. Please install" + " 'nest-asyncio' to run async render functions" + " synchronously." + ) from err + res_tree = loop.run_until_complete(res) + else: + res_tree = loop.run_until_complete(res) + except RuntimeError as err: + if "already running" in str(err) or "run_until_complete" in str( + err + ): + raise + res_tree = asyncio.run(res) + except Exception: + res_tree = asyncio.run(res) + else: + res_tree = res + + if isinstance(res_tree, list): + flattened_list: A2UIComponentList = [] + for item in res_tree: + _, comps = flatten_nested_layout(item, parent_id=instance_id) + flattened_list.extend(comps) + return flattened_list + else: + _, flat_components = flatten_nested_layout(res_tree) + # Normalize root ID to instance_id + result: A2UIComponentList = [] + for c in flat_components: + c_copy = dict(c) + if c_copy["id"] == "root": + c_copy["id"] = instance_id + elif c_copy["id"].startswith("root_"): + c_copy["id"] = f"{instance_id}_{c_copy['id'][5:]}" + if "child" in c_copy and isinstance(c_copy["child"], str): + if c_copy["child"] == "root": + c_copy["child"] = instance_id + elif c_copy["child"].startswith("root_"): + c_copy["child"] = f"{instance_id}_{c_copy['child'][5:]}" + if "children" in c_copy and isinstance( + c_copy["children"], list + ): + c_copy["children"] = [ + ( + instance_id + if ch == "root" + else ( + f"{instance_id}_{ch[5:]}" + if isinstance(ch, str) + and ch.startswith("root_") + else ch + ) + ) + for ch in c_copy["children"] + ] + result.append(c_copy) + return result + + # Mode B: Resolver + Static Layout Binding + elif dynamic_tmpl.layout is not None: + resolved_data = dynamic_tmpl.resolve(dict(passed_params)) + combined_params = {**dict(passed_params), **resolved_data} + layout = dynamic_tmpl.layout + return self._expand_static_layout( + instance_id, + layout, + combined_params, + _depth=_depth + 1, + _call_stack=current_stack, + ) + + # 2. Handle StaticTemplate execution + return self._expand_static_layout( + instance_id, + template, + passed_params, + _depth=_depth + 1, + _call_stack=current_stack, + ) + + @staticmethod + def _map_id(internal_id: str, instance_id: InstanceId) -> ComponentId: + if internal_id == "root": + return instance_id + if internal_id.startswith("root_"): + return f"{instance_id}_{internal_id[5:]}" + return f"{instance_id}_{internal_id}" + + @staticmethod + def _resolve_slot(val: Any, params: TemplateParams) -> Tuple[bool, Any]: + if isinstance(val, (ParamRef, TemplateLoop)): + val = val.to_dict() + if ( + isinstance(val, dict) + and "param" in val + and "template" not in val + and "item" not in val + ): + p_path = val["param"] + found, res = _resolve_param_path(p_path, params) + if found: + return True, res + if "default" in val: + return True, val["default"] + elif isinstance(val, str): + s = val.strip() + if s.startswith("{{") and s.endswith("}}"): + p_path = s[2:-2].strip() + found, res = _resolve_param_path(p_path, params) + if found: + return True, res + return True, None + elif val.startswith("${") and val.endswith("}"): + p_path = val[2:-1] + found, res = _resolve_param_path(p_path, params) + if found: + return True, res + return True, None + elif val.startswith("__PARAM__"): + p_name = val[9:] + found, res = _resolve_param_path(p_name, params) + if found: + return True, res + return True, None + return False, val + + @classmethod + def _map_child_list( + cls, child_list: Any, instance_id: InstanceId, params: TemplateParams + ) -> Any: + if isinstance(child_list, list): + res_list: List[Any] = [] + for c_id in child_list: + is_slot, slot_val = cls._resolve_slot(c_id, params) + if is_slot: + if isinstance(slot_val, list): + res_list.extend(slot_val) + elif slot_val is not None: + res_list.append(slot_val) + else: + res_list.append( + cls._map_id(c_id, instance_id) + if isinstance(c_id, str) + else c_id + ) + return res_list + elif isinstance(child_list, (str, dict, ParamRef, TemplateLoop)): + is_slot, slot_val = cls._resolve_slot(child_list, params) + if is_slot: + return slot_val + if isinstance(child_list, str): + return cls._map_id(child_list, instance_id) + return child_list + return child_list + + def _expand_static_layout( + self, + instance_id: InstanceId, + layout: Union[StaticTemplate, Template, Any], + passed_params: TemplateParams, + _depth: int = 0, + _call_stack: Optional[List[TemplateId]] = None, + ) -> A2UIComponentList: + template_id = getattr(layout, "template_id", "AnonymousTemplate") + + # 1. Resolve parameters and assign default values + params: Dict[str, Any] = {} + layout_params = getattr(layout, "parameters", {}) + for p_name, p_meta in layout_params.items(): + if isinstance(p_meta, Param): + p_meta_dict = p_meta.to_dict() + p_type = ( + p_meta.type.value + if isinstance(p_meta.type, ParamType) + else str(p_meta.type) + ) + else: + p_meta_dict = p_meta + p_type = str(p_meta.get("type", "string")) + + if p_name in passed_params: + val = passed_params[p_name] + if p_type == "children": + if isinstance(val, list): + params[p_name] = val + elif isinstance(val, (dict, str)): + params[p_name] = [val] + elif val == p_name or val is None: + params[p_name] = p_meta_dict.get("default", []) + else: + params[p_name] = [val] + else: + params[p_name] = val + + # Validate parameter value if data type + is_expression = isinstance(params[p_name], dict) and any( + k in params[p_name] for k in ["path", "concat", "format", "param"] + ) + if ( + isinstance(p_meta_dict, dict) + and p_type not in ["child", "children", "action"] + and not is_expression + and not ( + isinstance(params[p_name], str) + and ( + params[p_name].strip().startswith("{{") + or params[p_name].startswith("${") + or params[p_name].startswith("__") + ) + ) + ): + val_schema = normalize_a2ui_type_to_jsonschema(p_meta_dict) + if val_schema: + try: + jsonschema.validate( + instance=params[p_name], schema=val_schema + ) + except jsonschema.ValidationError as err: + raise ValueError( + f"Template '{template_id}': Parameter '{p_name}'" + f" failed validation: {err.message}" + ) from err + elif "default" in p_meta_dict and p_meta_dict["default"] is not None: + params[p_name] = p_meta_dict["default"] + elif p_type in ["array", "children"]: + params[p_name] = [] + elif p_meta_dict.get("required") is False or ( + isinstance(p_meta, Param) and not p_meta.required + ): + pass + else: + raise ValueError( + f"Missing required parameter '{p_name}' for template" + f" '{template_id}'" + ) + + # Merge in passed params that may not be in schema + for k, v in passed_params.items(): + if k not in params: + params[k] = v + + expanded_components: List[Dict[str, Any]] = [] + + # 2. First pass: Map internal component IDs, handle slots & loop unrolling + components_list = getattr(layout, "components", []) + for comp in components_list: + comp_copy = ( + comp.to_dict() if isinstance(comp, TemplateComponent) else dict(comp) + ) + comp_copy["id"] = self._map_id(comp_copy["id"], instance_id) + + if "child" in comp_copy: + is_slot, slot_val = self._resolve_slot(comp_copy["child"], params) + if is_slot: + if slot_val is None: + comp_copy.pop("child", None) + else: + comp_copy["child"] = slot_val + else: + if isinstance(comp_copy["child"], str): + comp_copy["child"] = self._map_id( + comp_copy["child"], instance_id + ) + + if "children" in comp_copy: + is_slot, slot_val = self._resolve_slot(comp_copy["children"], params) + if is_slot: + if slot_val is None: + comp_copy["children"] = [] + elif isinstance(slot_val, list): + comp_copy["children"] = slot_val + else: + comp_copy["children"] = [slot_val] + elif ( + isinstance(comp_copy["children"], dict) + and "param" in comp_copy["children"] + and ( + "template" in comp_copy["children"] + or "item" in comp_copy["children"] + ) + ): + children_meta = comp_copy["children"] + param_name = children_meta["param"] + array_data = params.get(param_name, []) + + if not isinstance(array_data, list): + raise ValueError( + f"Template '{template_id}': Parameter '{param_name}'" + " must be an array/list for loop unrolling." + ) + + unrolled_child_ids = [] + + # Case A: Inline item layout loop + if "item" in children_meta and isinstance( + children_meta["item"], list + ): + item_comps = children_meta["item"] + as_var = children_meta.get("as") + for idx, item in enumerate(array_data): + sub_instance_id = f"{comp_copy['id']}_item_{idx}" + unrolled_child_ids.append(sub_instance_id) + + item_dict = ( + dict(item) + if isinstance(item, dict) + else {"value": item} + ) + sub_params = {**params, **item_dict} + if as_var: + sub_params[as_var] = item_dict + + inline_template = StaticTemplate( + name=f"{template_id}_inline_{idx}", + template_id=f"{template_id}_inline_{idx}", + catalogs=getattr( + layout, "catalogs", list(self.catalogs.keys()) + ), + parameters={}, + components=item_comps, + ) + sub_expanded = self._expand_static_layout( + sub_instance_id, + inline_template, + sub_params, + _depth=_depth + 1, + _call_stack=_call_stack, + ) + expanded_components.extend(sub_expanded) + + # Case B: Named template loop + elif "template" in children_meta: + item_template_id = children_meta["template"] + for idx, item in enumerate(array_data): + sub_instance_id = f"{comp_copy['id']}_item_{idx}" + unrolled_child_ids.append(sub_instance_id) + sub_params = ( + item if isinstance(item, dict) else {"value": item} + ) + sub_expanded = self.expand_template( + sub_instance_id, + item_template_id, + sub_params, + _depth=_depth + 1, + _call_stack=_call_stack, + ) + expanded_components.extend(sub_expanded) + + comp_copy["children"] = unrolled_child_ids + else: + comp_copy["children"] = self._map_child_list( + comp_copy["children"], instance_id, params + ) + + comp_final = _substitute_params(comp_copy, params) + expanded_components.append(comp_final) + + # 4. Second pass: Flatten any nested template invocations + final_list: A2UIComponentList = [] + for c in expanded_components: + c_type = c.get("component") + if c_type in self.templates: + nested_instance_id = c["id"] + nested_template_id = c_type + nested_params = self._get_template_params( + c, self.templates[nested_template_id] + ) + nested_expanded = self.expand_template( + nested_instance_id, + nested_template_id, + nested_params, + _depth=_depth + 1, + _call_stack=_call_stack, + ) + final_list.extend(nested_expanded) + else: + comp_out = dict(c) + if "0.9" in self.version: + comp_out.pop("catalogId", None) + elif "1.0" in self.version: + if "catalogId" not in comp_out: + matching = [ + cat + for cat in getattr(layout, "catalogs", []) + if c_type + in self.catalogs.get(cat, {}).get("components", {}) + ] + if matching and matching[0] != self.base_catalog_id: + comp_out["catalogId"] = matching[0] + final_list.append(comp_out) + + return final_list + + def process_message( + self, message: Union[A2UIMessage, Sequence[A2UIMessage]] + ) -> Union[A2UIMessage, List[A2UIMessage]]: + """Intercepts A2UI server-to-client messages and unwraps any embedded template components.""" + if isinstance(message, list): + return [self.process_message(m) for m in message] + + if not isinstance(message, dict): + return message + + msg_copy = dict(message) + + for envelope_key in ["createSurface", "updateComponents"]: + if envelope_key in msg_copy: + payload = dict(msg_copy[envelope_key]) + if ( + envelope_key == "createSurface" + and "catalogId" not in payload + and self.base_catalog_id is not None + ): + payload["catalogId"] = self.base_catalog_id + if "components" in payload: + components = payload["components"] + + # Normalize single top-level template instances to root ID in createSurface + if envelope_key == "createSurface" and len(components) == 1: + single_comp = components[0] + if ( + isinstance(single_comp, dict) + and single_comp.get("component") in self.templates + ): + fixed_comp = dict(single_comp) + fixed_comp["id"] = "root" + components = [fixed_comp] + + expanded_list: A2UIComponentList = [] + for comp in components: + comp_type = comp.get("component") + if comp_type in self.templates: + instance_id = comp.get("id", "root") + params = self._get_template_params( + comp, self.templates[comp_type] + ) + expanded = self.expand_template( + instance_id, comp_type, params + ) + expanded_list.extend(expanded) + else: + expanded_list.append(comp) + + payload["components"] = expanded_list + msg_copy[envelope_key] = payload + + return msg_copy + + def _promote_parameter(self, p_meta: Dict[str, Any]) -> JSONSchemaDict: + """Promotes a template parameter to an A2UI catalog schema property.""" + if not isinstance(p_meta, dict): + return p_meta + + common_types_url = ( + "https://a2ui.org/specification/v0_9/common_types.json" + if "0.9" in self.version + else "https://a2ui.org/specification/v1_0/common_types.json" + ) + + p_type = p_meta.get("type") + if p_type == "child": + res = {"$ref": f"{common_types_url}#/$defs/ComponentId"} + for k in ["title", "description", "default"]: + if k in p_meta: + res[k] = p_meta[k] + return res + if p_type == "children": + res = {"$ref": f"{common_types_url}#/$defs/ChildList"} + for k in ["title", "description", "default"]: + if k in p_meta: + res[k] = p_meta[k] + return res + if p_type == "action": + res = {"$ref": f"{common_types_url}#/$defs/Action"} + for k in ["title", "description", "default"]: + if k in p_meta: + res[k] = p_meta[k] + return res + if p_type == "enum" and "values" in p_meta: + res = { + "type": "string", + "enum": p_meta["values"], + } + for k in ["title", "description", "default"]: + if k in p_meta: + res[k] = p_meta[k] + return res + + ref_map = { + "string": f"{common_types_url}#/$defs/DynamicString", + "number": f"{common_types_url}#/$defs/DynamicNumber", + "integer": f"{common_types_url}#/$defs/DynamicNumber", + "boolean": f"{common_types_url}#/$defs/DynamicBoolean", + } + + target_ref = ref_map.get(str(p_type)) + if target_ref: + promoted: JSONSchemaDict = {"allOf": [{"$ref": target_ref}]} + metadata = {} + for k in ["title", "description", "default"]: + if k in p_meta: + metadata[k] = p_meta[k] + if metadata: + promoted["allOf"].append(metadata) + return promoted + + return dict(p_meta) + + def _validate_templates(self) -> None: + """Validates all registered templates against declared catalogs and component references.""" + for t_key, template in list(self.templates.items()): + t_name = getattr(template, "name", template.template_id) + if t_key != t_name: + continue + + # 1. Resolve declared catalogs on template + t_catalogs = getattr(template, "catalogs", []) + if isinstance(t_catalogs, str): + t_catalogs = [t_catalogs] + template.catalogs = t_catalogs + + if not t_catalogs: + if len(self.catalogs) == 1: + t_catalogs = list(self.catalogs.keys()) + template.catalogs = t_catalogs + else: + raise ValueError( + f"Template '{t_name}' must declare which catalog(s) it is" + " written against via 'catalogs'. Registered catalogs:" + f" {list(self.catalogs.keys())}" + ) + + for c_uri in t_catalogs: + if c_uri not in self.catalogs: + raise ValueError( + f"Template '{t_name}' declares catalog '{c_uri}', which is not" + " registered in TemplateProcessor. Available catalogs:" + f" {list(self.catalogs.keys())}" + ) + + # In v0.9, a template cannot span multiple catalogs + if "0.9" in self.version and len(t_catalogs) > 1: + raise ValueError( + f"Template '{t_name}' declares multiple catalogs {t_catalogs}, but" + f" A2UI {self.version} only supports a single catalog." + ) + + # 2. Validate template definition schema if static + if isinstance(template, StaticTemplate): + template.validate_definition() + + # 3. Validate components in layout + layout = getattr(template, "layout", None) or template + comps = getattr(layout, "components", []) + for comp in comps: + comp_dict = ( + comp.to_dict() if isinstance(comp, TemplateComponent) else comp + ) + comp_type = comp_dict.get("component") + if not comp_type: + raise ValueError( + f"Component in template '{t_name}' is missing 'component' type." + ) + + # Check if component is a sub-template invocation + if ( + comp_type in self.templates + or comp_type in self.templates_by_id + or comp_type in getattr(template, "imports", []) + ): + continue + + # Otherwise it must be a primitive in the declared catalogs + matching_cats = [ + cat_uri + for cat_uri in t_catalogs + if comp_type in self.catalogs[cat_uri].get("components", {}) + ] + + explicit_cat = comp_dict.get("catalogId") or getattr( + comp, "catalog_id", None + ) + if explicit_cat: + if explicit_cat not in t_catalogs: + raise ValueError( + f"Component '{comp_type}' in template '{t_name}' specifies" + f" catalogId '{explicit_cat}', which is not in template's" + f" declared catalogs: {t_catalogs}" + ) + if comp_type not in self.catalogs[explicit_cat].get( + "components", {} + ): + raise ValueError( + f"Component '{comp_type}' not found in catalog" + f" '{explicit_cat}'" + ) + else: + if len(matching_cats) == 0: + raise ValueError( + f"Component '{comp_type}' in template '{t_name}' was not" + f" found in any declared catalog: {t_catalogs}" + ) + elif len(matching_cats) > 1: + raise ValueError( + f"Component '{comp_type}' in template '{t_name}' is" + " ambiguous across multiple declared catalogs:" + f" {matching_cats}. Specify 'catalogId' on the component." + ) + + def validate_templates(self) -> None: + """Deprecated alias for _validate_templates.""" + self._validate_templates() + + def _get_template_params( + self, + comp: A2UIComponent, + template: Union[BaseTemplate, Template, StaticTemplate, DynamicTemplate], + ) -> Dict[str, Any]: + """Extracts passed parameters from a component dictionary.""" + params: Dict[str, Any] = {} + raw_keys = template.parameters.keys() if hasattr(template, "parameters") else [] + for p_name in raw_keys: + if p_name in comp: + params[p_name] = comp[p_name] + return params diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/template/manager.py b/agent_sdks/python/a2ui_agent/src/a2ui/template/manager.py deleted file mode 100644 index 3b34254b45..0000000000 --- a/agent_sdks/python/a2ui_agent/src/a2ui/template/manager.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import Optional, Any, Union -from a2ui.inference_format import InferenceFormat -from a2ui.core.schema.client_capabilities import V09Capabilities - - -class A2uiTemplateManager(InferenceFormat): - """Manages prompt compilation and payload processing for template definitions.""" - - @property - def parser(self) -> Any: - """The parser instance associated with the template manager.""" - raise NotImplementedError("This method is not yet implemented.") - - @property - def prompt_generator(self) -> Any: - """The prompt generator instance associated with the template manager.""" - raise NotImplementedError("This method is not yet implemented.") - - def generate_system_prompt( - self, - role_description: str, - workflow_description: str = "", - ui_description: str = "", - client_ui_capabilities: Optional[Union[dict[str, Any], V09Capabilities]] = None, - allowed_components: Optional[list[str]] = None, - allowed_messages: Optional[list[str]] = None, - include_schema: bool = False, - include_examples: bool = False, - validate_examples: bool = False, - ) -> str: - """Generates a system prompt for requests (not yet implemented).""" - # TODO: Implementation logic for Template Manager - raise NotImplementedError("This method is not yet implemented.") diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/README.md b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/README.md new file mode 100644 index 0000000000..0e63eeaedb --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/README.md @@ -0,0 +1,63 @@ +# A2UI Template Conformance Test Suite + +This directory contains the language-agnostic, data-driven conformance test suite for A2UI Templates. + +While currently maintained within the Python Agent SDK (`agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/`), the suite is defined entirely in declarative YAML and JSON Schema to enable seamless graduation to the root `conformance/templates/` directory as cross-platform SDKs (Dart, TypeScript, Kotlin) add template engines. + +--- + +## Directory Structure + +``` +conformance/ +├── schema/ +│ └── template_conformance_schema.json <-- JSON Schema validating all YAML test suites +├── suites/ +│ ├── 01_substitution.yaml <-- Exact match, interpolation, AST expressions, token escaping +│ ├── 02_static_expansion.yaml <-- Single/multi-child expansion, slots, data bindings +│ ├── 03_loop_unrolling.yaml <-- Inline loops, named loops, empty arrays, 2D unrolling +│ ├── 04_parameter_validation.yaml <-- Parameter type enforcement, enum validation, required fields +│ ├── 05_message_interception.yaml <-- createSurface, updateComponents, multi-envelope streams +│ └── 06_error_invariants.yaml <-- Unregistered templates, cycle guards, recursion limits +├── test_template_conformance.py <-- Pytest harness running the entire suite +└── README.md +``` + +--- + +## Action Runners + +Each test case declares an `action` attribute: + +1. **`substitute_params`**: + - Tests `_substitute_params(val, params)` directly. + - Asserts exact value and type preservation (integers, booleans, objects, arrays), string interpolation, AST expressions (`format`, `concat`), and literal escaping (`\${token}`). + +2. **`expand_template`**: + - Registers defined template(s) with `TemplateProcessor`. + - Executes `processor.expand_template(instance_id, template_id, args)`. + - Asserts exact component list structure and synthetic ID generation. + +3. **`process_message`**: + - Intercepts A2UI messages (`createSurface`, `updateComponents`). + - Asserts unrolling of template instances into standard primitive components. + +4. **`validate_template`**: + - Tests template ingestion and version validation (`version: "0.1"`). + - Asserts validation errors on invalid or missing version fields. + +--- + +## Graduation to Cross-Platform + +When A2UI Templates graduate from experimental to standard protocol: + +1. Move the entire `conformance/` directory to root: + ```bash + mv agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/ conformance/templates/ + ``` +2. The `suites/*.yaml` test definitions require **zero modifications**. +3. Implement standard harnesses in other target languages: + - **TypeScript / React / Lit**: Vitest harness reading `suites/*.yaml`. + - **Dart / Flutter**: `package:test` harness reading `suites/*.yaml`. + - **Kotlin**: JUnit5 harness reading `suites/*.yaml`. diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/schema/template_conformance_schema.json b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/schema/template_conformance_schema.json new file mode 100644 index 0000000000..d68f8a11ac --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/schema/template_conformance_schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://a2ui.org/conformance/template_conformance_schema.json", + "title": "A2UI Template Conformance Test Suite Schema", + "type": "array", + "items": { + "type": "object", + "required": ["name", "action"], + "properties": { + "name": { + "type": "string", + "description": "Unique name of the test case." + }, + "description": { + "type": "string", + "description": "Human-readable description of what this test case asserts." + }, + "action": { + "type": "string", + "enum": [ + "substitute_params", + "expand_template", + "process_message", + "validate_template", + "generate_catalog" + ], + "description": "The template engine action being tested." + }, + "templates": { + "type": "array", + "description": "List of template definitions registered with the processor." + }, + "template": { + "type": "object", + "description": "Single template definition registered with the processor." + }, + "instance_id": { + "type": "string", + "description": "Target component instance ID for expansion." + }, + "template_id": { + "type": "string", + "description": "Identifier of the template being expanded." + }, + "base_catalog": { + "type": ["object", "null"], + "description": "Optional base catalog schema provided to processor." + }, + "catalogs": { + "description": "Optional catalogs schema provided to processor." + }, + "args": { + "description": "Arguments/parameters passed to the action." + }, + "message": { + "description": "Message payload passed to process_message." + }, + "expect": { + "description": "Expected result matching the action return value." + }, + "expect_error": { + "type": "object", + "properties": { + "category": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "description": "Expected error category and error substring." + } + } + } +} diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/01_substitution.yaml b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/01_substitution.yaml new file mode 100644 index 0000000000..dc8bbfb471 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/01_substitution.yaml @@ -0,0 +1,218 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: test_exact_integer_preservation + description: Verifies that exact token match preserves integer type without string + coercion. + action: substitute_params + args: + value: ${count} + params: + count: 42 + expect: 42 +- name: test_exact_boolean_preservation + description: Verifies that exact token match preserves boolean type. + action: substitute_params + args: + value: ${isEnabled} + params: + isEnabled: true + expect: true +- name: test_exact_array_preservation + description: Verifies that exact token match preserves array data structure. + action: substitute_params + args: + value: ${tags} + params: + tags: + - admin + - developer + - tester + expect: + - admin + - developer + - tester +- name: test_exact_object_preservation + description: Verifies that exact token match preserves nested dictionary structure. + action: substitute_params + args: + value: ${binding} + params: + binding: + path: /session/user/name + expect: + path: /session/user/name +- name: test_in_string_interpolation + description: Verifies string interpolation when token appears with surrounding text. + action: substitute_params + args: + value: Hello, ${name}! + params: + name: Alice + expect: Hello, Alice! +- name: test_multiple_in_string_interpolations + description: Verifies multiple tokens interpolated in a single string. + action: substitute_params + args: + value: ${dept} - Grade ${grade} (${active}) + params: + dept: Engineering + grade: 7 + active: true + expect: Engineering - Grade 7 (True) +- name: test_token_escaping_exact + description: Verifies that leading backslash prevents substitution of exact token. + action: substitute_params + args: + value: \${keep_literal} + params: + keep_literal: not_used + expect: ${keep_literal} +- name: test_token_escaping_in_string + description: Verifies escaping in mixed string preserves literal token while substituting + unescaped token. + action: substitute_params + args: + value: Literal \${keep} and dynamic ${replace} + params: + keep: ignored + replace: substituted + expect: Literal ${keep} and dynamic substituted +- name: test_deep_dot_notation_nested_dict + description: Verifies resolving multi-level dot-separated path in nested dictionary. + action: substitute_params + args: + value: ${user.profile.details.tier} + params: + user: + profile: + details: + tier: Enterprise + expect: Enterprise +- name: test_deep_dot_notation_array_index + description: Verifies resolving dot-separated path with numeric array indices. + action: substitute_params + args: + value: ${teams.0.members.1.name} + params: + teams: + - members: + - name: First + - name: Second + expect: Second +- name: test_format_expression_ast + description: Verifies evaluating format expression dictionary with arguments. + action: substitute_params + args: + value: + format: "Progress: {current} of {total} ({pct}%)" + args: + current: ${metrics.completed} + total: ${metrics.total} + pct: 75 + params: + metrics: + completed: 15 + total: 20 + expect: "Progress: 15 of 20 (75%)" +- name: test_concat_expression_ast + description: Verifies evaluating concat expression combining string literals and + param references. + action: substitute_params + args: + value: + concat: + - "Status: " + - param: state + - " (" + - param: code + - ) + params: + state: OK + code: 200 + expect: "Status: OK (200)" +- name: test_concat_with_none_omits_part + description: Verifies that None or unresolved parts in concat do not insert 'None' + strings. + action: substitute_params + args: + value: + concat: + - Prefix- + - param: missing + - -Suffix + params: {} + expect: Prefix--Suffix +- name: test_param_ref_with_default + description: Verifies that direct param ref uses explicit default when param missing. + action: substitute_params + args: + value: + param: role + default: Contributor + params: {} + expect: Contributor +- name: test_mustache_exact_integer_preservation + description: Verifies that exact Mustache token match preserves integer type. + action: substitute_params + args: + value: "{{ count }}" + params: + count: 42 + expect: 42 +- name: test_mustache_exact_boolean_preservation + description: Verifies that exact Mustache token match preserves boolean type. + action: substitute_params + args: + value: "{{ isEnabled }}" + params: + isEnabled: true + expect: true +- name: test_mustache_exact_array_preservation + description: Verifies that exact Mustache token match preserves array data structure. + action: substitute_params + args: + value: "{{ tags }}" + params: + tags: + - admin + - developer + expect: + - admin + - developer +- name: test_mustache_string_interpolation + description: Verifies multiple Mustache tokens interpolated inside string. + action: substitute_params + args: + value: "{{ dept }} - Grade {{ grade }}" + params: + dept: Eng + grade: 9 + expect: "Eng - Grade 9" +- name: test_mustache_escaping + description: Verifies that escaped Mustache syntax is emitted as a literal. + action: substitute_params + args: + value: 'Literal \{{ keep }} and dynamic {{ replace }}' + params: + replace: substituted + expect: "Literal {{ keep }} and dynamic substituted" +- name: test_mustache_client_data_binding_passthrough + description: Verifies that client ${/data/path} bindings are preserved untouched. + action: substitute_params + args: + value: "Client: ${/user/name}, Server: {{ serverVal }}" + params: + serverVal: local + expect: "Client: ${/user/name}, Server: local" diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/02_static_expansion.yaml b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/02_static_expansion.yaml new file mode 100644 index 0000000000..33fb8a0295 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/02_static_expansion.yaml @@ -0,0 +1,230 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: test_single_child_card_expansion + description: Verifies expanding card container with single child and deterministic + ID prefixing. + action: expand_template + template: + version: "0.1" + templateId: SimpleCard + parameters: + title: + type: string + layout: + component: Card + child: + component: Text + text: ${title} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: SimpleCard + instance_id: card_inst + template_id: SimpleCard + args: + title: Welcome + expect: + - id: card_inst + component: Card + child: card_inst_child_text + - id: card_inst_child_text + component: Text + text: Welcome +- name: test_default_param_values + description: Verifies default value is assigned when argument is omitted. + action: expand_template + template: + version: "0.1" + templateId: ProfileHeader + parameters: + name: + type: string + role: + type: string + default: Team Member + layout: + component: Column + children: + - component: Text + text: ${name} + - component: Text + text: ${role} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: ProfileHeader + instance_id: prof_1 + template_id: ProfileHeader + args: + name: Bob + expect: + - id: prof_1 + component: Column + children: + - prof_1_child_0_text + - prof_1_child_1_text + - id: prof_1_child_0_text + component: Text + text: Bob + - id: prof_1_child_1_text + component: Text + text: Team Member +- name: test_higher_order_child_slot + description: Verifies passing a component ID into a child slot parameter. + action: expand_template + template: + version: "0.1" + templateId: ContainerSlot + parameters: + content: + type: child + layout: + component: Card + child: ${content} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: ContainerSlot + instance_id: slot_inst + template_id: ContainerSlot + args: + content: custom_chart_comp_id + expect: + - id: slot_inst + component: Card + child: custom_chart_comp_id +- name: test_unfilled_optional_child_slot_omitted + description: Verifies that when an optional child slot parameter is omitted, the + child property is omitted from output. + action: expand_template + template: + version: "0.1" + templateId: OptionalChildCard + parameters: + optionalChild: + type: child + required: false + layout: + component: Card + child: ${optionalChild} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: OptionalChildCard + instance_id: opt_card + template_id: OptionalChildCard + args: {} + expect: + - id: opt_card + component: Card +- name: test_higher_order_action_slot + description: Verifies binding an Action object to a button action slot via parameter. + action: expand_template + template: + version: "0.1" + templateId: ActionButton + parameters: + label: + type: string + onPress: + type: action + layout: + component: Button + text: ${label} + action: ${onPress} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: ActionButton + instance_id: btn_inst + template_id: ActionButton + args: + label: Deploy + onPress: + name: triggerDeployment + parameters: + env: production + expect: + - id: btn_inst + component: Button + text: Deploy + action: + name: triggerDeployment + parameters: + env: production +- name: test_data_binding_passthrough + description: Verifies passing a client DataBinding dictionary through a parameter + preserving dictionary structure. + action: expand_template + template: + version: "0.1" + templateId: BoundMetric + parameters: + label: + type: string + valueBinding: + type: object + layout: + component: Text + text: ${valueBinding} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: BoundMetric + instance_id: bound_txt + template_id: BoundMetric + args: + label: CPU + valueBinding: + path: /system/cpu/usage + expect: + - id: bound_txt + component: Text + text: + path: /system/cpu/usage +- name: test_nested_template_invocation + description: Verifies a parent template layout referencing a child template expanding + recursively. + action: expand_template + templates: + - version: "0.1" + templateId: Badge + parameters: + text: + type: string + layout: + component: Text + text: "[${text}]" + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: Badge + - version: "0.1" + templateId: BadgeCard + parameters: + tag: + type: string + layout: + component: Card + child: + component: Badge + text: ${tag} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: BadgeCard + instance_id: parent_inst + template_id: BadgeCard + args: + tag: PRO + expect: + - id: parent_inst + component: Card + child: parent_inst_child_badge + - id: parent_inst_child_badge + component: Text + text: "[PRO]" diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/03_loop_unrolling.yaml b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/03_loop_unrolling.yaml new file mode 100644 index 0000000000..b8c353925e --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/03_loop_unrolling.yaml @@ -0,0 +1,208 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: test_inline_item_loop_unrolling + description: Verifies inline component layout unrolling for each element of an array. + action: expand_template + template: + version: "0.1" + templateId: MemberList + parameters: + members: + type: array + layout: + component: Column + children: + loop: + param: members + as: m + item: + component: Row + children: + - component: Text + text: ${m.name} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: MemberList + instance_id: team_col + template_id: MemberList + args: + members: + - name: Alice + - name: Bob + expect: + - id: team_col + component: Column + children: + - team_col_item_0 + - team_col_item_1 + - id: team_col_item_0 + component: Row + children: + - team_col_item_0_child_0_text + - id: team_col_item_0_child_0_text + component: Text + text: Alice + - id: team_col_item_1 + component: Row + children: + - team_col_item_1_child_0_text + - id: team_col_item_1_child_0_text + component: Text + text: Bob +- name: test_named_template_loop_unrolling + description: Verifies unrolling an array by invoking another registered template + for each element. + action: expand_template + templates: + - version: "0.1" + templateId: TagBadge + parameters: + label: + type: string + layout: + component: Text + text: "#${label}" + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: TagBadge + - version: "0.1" + templateId: TagContainer + parameters: + tags: + type: array + layout: + component: Row + children: + loop: + param: tags + template: TagBadge + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: TagContainer + instance_id: row_tags + template_id: TagContainer + args: + tags: + - label: alpha + - label: beta + expect: + - id: row_tags + component: Row + children: + - row_tags_item_0 + - row_tags_item_1 + - id: row_tags_item_0 + component: Text + text: "#alpha" + - id: row_tags_item_1 + component: Text + text: "#beta" +- name: test_empty_loop_array_emits_empty_children + description: Verifies that an empty array parameter unrolls cleanly to empty children + list. + action: expand_template + template: + version: "0.1" + templateId: EmptyListChecker + parameters: + items: + type: array + layout: + component: Column + children: + loop: + param: items + item: + component: Text + text: Item + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: EmptyListChecker + instance_id: empty_col + template_id: EmptyListChecker + args: + items: [] + expect: + - id: empty_col + component: Column + children: [] +- name: test_primitive_list_iteration + description: Verifies iterating over primitive strings in an array using item.value + fallback. + action: expand_template + template: + version: "0.1" + templateId: ColorChips + parameters: + colors: + type: array + layout: + component: Row + children: + loop: + param: colors + as: c + item: + component: Text + text: ${c.value} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: ColorChips + instance_id: chip_row + template_id: ColorChips + args: + colors: + - Crimson + - Azure + expect: + - id: chip_row + component: Row + children: + - chip_row_item_0 + - chip_row_item_1 + - id: chip_row_item_0 + component: Text + text: Crimson + - id: chip_row_item_1 + component: Text + text: Azure +- name: test_non_array_loop_parameter_raises_error + description: Verifies that passing a non-array string value to a loop raises a clear + ValidationError. + action: expand_template + template: + version: "0.1" + templateId: FailingLoop + parameters: + items: + type: array + layout: + component: Column + children: + loop: + param: items + item: + component: Text + text: Fail + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: FailingLoop + instance_id: fail_inst + template_id: FailingLoop + args: + items: not_an_array + expect_error: + category: ValidationError + message: failed validation diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/04_parameter_validation.yaml b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/04_parameter_validation.yaml new file mode 100644 index 0000000000..8b309e4375 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/04_parameter_validation.yaml @@ -0,0 +1,116 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: test_parameter_type_validation_string_to_integer_fails + description: Verifies that passing a string to an integer parameter raises a validation + error. + action: expand_template + template: + version: "0.1" + templateId: IntegerParamCheck + parameters: + count: + type: integer + layout: + component: Text + text: "Count: ${count}" + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: IntegerParamCheck + instance_id: int_fail + template_id: IntegerParamCheck + args: + count: non_integer_string + expect_error: + category: ValidationError + message: failed validation +- name: test_parameter_enum_validation_invalid_value_fails + description: Verifies that passing an unexpected value to an enum parameter raises + validation error. + action: expand_template + template: + version: "0.1" + templateId: EnumParamCheck + parameters: + status: + type: enum + values: + - ACTIVE + - SUSPENDED + - PENDING + layout: + component: Text + text: "Status: ${status}" + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: EnumParamCheck + instance_id: enum_fail + template_id: EnumParamCheck + args: + status: DELETED + expect_error: + category: ValidationError + message: failed validation +- name: test_missing_required_parameter_raises_error + description: Verifies that omitting a required parameter with no default raises + an error. + action: expand_template + template: + version: "0.1" + templateId: RequiredParamCheck + parameters: + mandatory: + type: string + layout: + component: Text + text: ${mandatory} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: RequiredParamCheck + instance_id: req_fail + template_id: RequiredParamCheck + args: {} + expect_error: + category: ValidationError + message: Missing required parameter 'mandatory' +- name: test_unsupported_template_version_raises_error + description: Verifies that loading a template with unsupported version format raises + error. + action: validate_template + template: + version: "0.2" + templateId: FutureVersionTemplate + parameters: {} + layout: + component: Text + text: Future + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: FutureVersionTemplate + expect_error: + category: ValidationError + message: Unsupported template version '0.2' +- name: test_missing_template_version_raises_error + description: Verifies that omitting version attribute completely raises error. + action: validate_template + template: + templateId: MissingVersionTemplate + parameters: {} + layout: + component: Text + text: No Version + name: MissingVersionTemplate + expect_error: + category: ValidationError + message: missing required 'version' attribute diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/05_message_interception.yaml b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/05_message_interception.yaml new file mode 100644 index 0000000000..23fe2d0e44 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/05_message_interception.yaml @@ -0,0 +1,170 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: test_create_surface_envelope_unwrapping + description: Verifies that createSurface message wraps template instance and unwraps + into primitive components. + action: process_message + template: + version: "0.1" + templateId: SimpleCard + parameters: + title: + type: string + layout: + component: Card + child: + component: Text + text: ${title} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: SimpleCard + message: + createSurface: + surfaceId: main + catalogId: https://a2ui.org/custom.json + components: + - id: root + component: SimpleCard + title: Unwrapped + expect: + createSurface: + surfaceId: main + catalogId: https://a2ui.org/custom.json + components: + - id: root + component: Card + child: root_child_text + - id: root_child_text + component: Text + text: Unwrapped +- name: test_update_components_envelope_unwrapping + description: Verifies that updateComponents message with template instance expands + correctly. + action: process_message + template: + version: "0.1" + templateId: SimpleCard + parameters: + title: + type: string + layout: + component: Card + child: + component: Text + text: ${title} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: SimpleCard + message: + updateComponents: + surfaceId: main + components: + - id: card_2 + component: SimpleCard + title: Updated + expect: + updateComponents: + surfaceId: main + components: + - id: card_2 + component: Card + child: card_2_child_text + - id: card_2_child_text + component: Text + text: Updated +- name: test_mixed_primitives_and_templates_in_message + description: Verifies that non-template primitive components pass through untouched + alongside expanded templates. + action: process_message + template: + version: "0.1" + templateId: SimpleCard + parameters: + title: + type: string + layout: + component: Card + child: + component: Text + text: ${title} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: SimpleCard + message: + updateComponents: + surfaceId: main + components: + - id: div_1 + component: Divider + axis: horizontal + - id: card_mixed + component: SimpleCard + title: Mixed Content + expect: + updateComponents: + surfaceId: main + components: + - id: div_1 + component: Divider + axis: horizontal + - id: card_mixed + component: Card + child: card_mixed_child_text + - id: card_mixed_child_text + component: Text + text: Mixed Content +- name: test_batch_messages_stream_passthrough + description: Verifies processing a list of messages passing dataModel updates through + unaltered. + action: process_message + template: + version: "0.1" + templateId: SimpleCard + parameters: + title: + type: string + layout: + component: Card + child: + component: Text + text: ${title} + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: SimpleCard + message: + - updateDataModel: + path: /session/user + value: + name: Alice + - updateComponents: + surfaceId: main + components: + - id: batch_c + component: SimpleCard + title: Batch + expect: + - updateDataModel: + path: /session/user + value: + name: Alice + - updateComponents: + surfaceId: main + components: + - id: batch_c + component: Card + child: batch_c_child_text + - id: batch_c_child_text + component: Text + text: Batch diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/06_error_invariants.yaml b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/06_error_invariants.yaml new file mode 100644 index 0000000000..c8bb843bec --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/conformance/suites/06_error_invariants.yaml @@ -0,0 +1,70 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: test_unregistered_template_raises_error + description: Verifies expanding an unregistered template ID raises a clear ValueError. + action: expand_template + templates: [] + instance_id: inst_1 + template_id: UnknownTemplate + args: {} + expect_error: + category: ValidationError + message: Template 'UnknownTemplate' is not registered +- name: test_circular_reference_a_b_a + description: Verifies immediate detection of circular template references A -> B + -> A. + action: expand_template + templates: + - version: "0.1" + templateId: NodeA + parameters: {} + layout: + component: NodeB + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: NodeA + - version: "0.1" + templateId: NodeB + parameters: {} + layout: + component: NodeA + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: NodeB + instance_id: root_circ + template_id: NodeA + args: {} + expect_error: + category: ValidationError + message: Circular template reference detected +- name: test_circular_reference_self + description: Verifies that a template referencing itself is immediately caught by + the cycle guard. + action: expand_template + templates: + - version: "0.1" + templateId: SelfLoop + parameters: {} + layout: + component: SelfLoop + catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json + name: SelfLoop + instance_id: root_self + template_id: SelfLoop + args: {} + expect_error: + category: ValidationError + message: Circular template reference detected diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_format.py b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_format.py new file mode 100644 index 0000000000..e0d7c63c4a --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_format.py @@ -0,0 +1,64 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit tests for A2UI Template Inference Format (format.py) focusing on ADK framework integration.""" + +from a2ui.inference_formats.experimental.template import ( + StaticTemplate, + TemplateInferenceFormat, +) + + +def test_template_inference_format_end_to_end(): + """Verifies that TemplateInferenceFormat wraps ExpressFormat, generates prompts, and unrolls streaming chunks.""" + yaml_tmpl = """ +version: "0.1" +name: UserProfile +catalogs: + - "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json" +parameters: + userId: {type: string} + userName: {type: string} + role: {type: string} +layout: + component: Card + child: + component: Text + text: ${userName} +""" + tmpl = StaticTemplate.from_yaml(yaml_tmpl) + manager = TemplateInferenceFormat( + templates=[tmpl], + surface_id="main_surface", + version="0.9.1", + ) + + # 1. Check prompt generation includes UserProfile signature when include_schema=True + prompt = manager.prompt_generator.generate( + role_description="Test Agent", include_schema=True + ) + assert "UserProfile" in prompt + + # 2. Check parsing and expansion of Express DSL response + llm_output = """ + Here is your profile card: + + root = UserProfile("usr_99", "Sarah Jenkins", "Lead Designer") + + """ + + parts = manager.parser.parse_response(llm_output) + assert len(parts) == 1 + assert "Here is your profile card:" in parts[0].text + assert parts[0].a2ui_json is not None diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_models.py b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_models.py new file mode 100644 index 0000000000..cba1466cb7 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_models.py @@ -0,0 +1,129 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit tests for A2UI Template Models (models.py) focusing on Python runtime integration.""" + +from dataclasses import dataclass + +from a2ui.inference_formats.experimental.template.models import ( + DynamicTemplate, + dynamic_template, + ParamType, + normalize_node, +) + + +def test_normalize_node_dataclass_support(): + """Verifies that Python dataclass instances are normalized to plain dictionaries.""" + + @dataclass + class TextComponent: + component: str + text: str + + node = TextComponent(component="Text", text="Hello Dataclass") + normalized = normalize_node(node) + assert isinstance(normalized, dict) + assert normalized == {"component": "Text", "text": "Hello Dataclass"} + + +def test_normalize_node_duck_typing(): + """Verifies that objects implementing to_dict() are properly normalized.""" + + class CustomNode: + + def to_dict(self): + return {"component": "CustomCard", "score": 99} + + node = CustomNode() + normalized = normalize_node(node) + assert isinstance(normalized, dict) + assert normalized == {"component": "CustomCard", "score": 99} + + +def test_dynamic_template_signature_inference(): + """Verifies that DynamicTemplate infers typed parameters and defaults from Python callable annotations.""" + + def my_resolver(userId: str, count: int = 5, active: bool = True) -> dict: + return {} + + tmpl = DynamicTemplate(template_id="InferredTmpl", resolver=my_resolver) + params = tmpl.parameters + + assert "userId" in params + assert params["userId"].type == ParamType.STRING + assert params["userId"].default is None + + assert "count" in params + assert params["count"].type == ParamType.INTEGER + assert params["count"].default == 5 + + assert "active" in params + assert params["active"].type == ParamType.BOOLEAN + assert params["active"].default is True + + +def test_dynamic_template_decorator_and_callability(): + """Verifies that @dynamic_template decorates a function, infers metadata, and preserves callability.""" + + @dynamic_template( + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + description="Generates a user badge with custom status.", + ) + def user_badge(user_name: str, status: str = "Active", score: int = 100): + """Generates a user badge.""" + return { + "component": "Card", + "child": { + "component": "Text", + "text": f"{user_name}: {status} ({score})", + }, + } + + # 1. Verify it acts as a DynamicTemplate instance + assert isinstance(user_badge, DynamicTemplate) + assert user_badge.name == "UserBadge" + assert user_badge.description == "Generates a user badge with custom status." + assert user_badge.catalogs == [ + "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" + ] + assert "user_name" in user_badge.parameters + assert user_badge.parameters["user_name"].type == ParamType.STRING + assert user_badge.parameters["status"].default == "Active" + assert user_badge.parameters["score"].type == ParamType.INTEGER + assert user_badge.parameters["score"].default == 100 + + # 2. Verify it remains directly callable as a standard Python function + rendered = user_badge("Alice", status="Online", score=150) + assert isinstance(rendered, dict) + assert rendered["component"] == "Card" + assert rendered["child"]["text"] == "Alice: Online (150)" + + +def test_dynamic_template_decorator_no_args(): + """Verifies @dynamic_template works without parenthesis, extracting docstring and PascalCase name.""" + + @dynamic_template + def metric_tile(label: str, value: float = 0.0): + """KPI metric display tile.""" + return {"component": "Text", "text": f"{label}: {value}"} + + assert isinstance(metric_tile, DynamicTemplate) + assert metric_tile.name == "MetricTile" + assert metric_tile.description == "KPI metric display tile." + assert "label" in metric_tile.parameters + assert metric_tile.parameters["value"].type == ParamType.NUMBER + + res = metric_tile("CPU", 99.4) + assert res == {"component": "Text", "text": "CPU: 99.4"} diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_processor.py b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_processor.py new file mode 100644 index 0000000000..0b5668a1c5 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_processor.py @@ -0,0 +1,495 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit tests for A2UI Template Processor (processor.py) focusing on Python runtime execution and typing.""" + +import asyncio +import json +from pathlib import Path +from typing import Any, Dict +import pytest + +from a2ui.inference_formats.experimental.template import ( + DynamicTemplate, + dynamic_template, + StaticTemplate, + TemplateProcessor, + TemplateId, + InstanceId, + ComponentId, + ParamPath, + TemplateParams, +) +from a2ui.inference_formats.experimental.template.processor import ( + _resolve_param_path, + _substitute_params, +) + +BASIC_CATALOG_PATH = ( + Path(__file__).resolve().parents[7] + / "specification" + / "v0_9_1" + / "catalogs" + / "basic" + / "catalog.json" +) +BASIC_CATALOG: Dict[str, Any] = {} +if BASIC_CATALOG_PATH.is_file(): + with open(BASIC_CATALOG_PATH, "r", encoding="utf-8") as f: + BASIC_CATALOG = json.load(f) + + +def test_dynamic_template_with_resolver(): + """Verifies Mode B dynamic template where a native Python resolver fetches data and binds it to a static layout.""" + layout_yaml = """ +version: "0.1" +name: LiveStockCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +parameters: + ticker: {type: string} + price: {type: number, required: false} + changePct: {type: string, required: false} +layout: + component: Card + child: + component: Column + children: + - component: Text + text: "Stock: ${ticker}" + - component: Text + text: "Price: $${price}" + - component: Text + text: "Change: ${changePct}%" +""" + + mock_db = { + "GOOG": {"price": 175.50, "changePct": "+1.8"}, + "AAPL": {"price": 220.10, "changePct": "-0.4"}, + } + + async def fetch_stock_data(ticker: str) -> Dict[str, Any]: + await asyncio.sleep(0.01) + return mock_db.get(ticker, {"price": 0.0, "changePct": "0.0"}) + + tmpl = DynamicTemplate( + name="LiveStockCard", + template_id="LiveStockCard", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + layout=layout_yaml, + resolver=fetch_stock_data, + description="Displays live stock pricing.", + ) + + processor = TemplateProcessor(templates=[tmpl], catalogs=BASIC_CATALOG) + expanded = processor.expand_template( + "stock_goog", "LiveStockCard", {"ticker": "GOOG"} + ) + + assert len(expanded) == 5 + price_comp = next((c for c in expanded if c.get("text") == "Price: $175.5"), None) + assert price_comp is not None + + +def test_programmatic_dynamic_template_render(): + """Verifies Mode A dynamic template where a native Python callable directly constructs the component tree.""" + + def render_payroll(department: str = "Engineering", includeBonus: bool = True): + employees = [ + {"name": "Alice", "salary": 150000, "bonus": 20000}, + {"name": "Bob", "salary": 140000, "bonus": 15000}, + ] + rows = [] + for emp in employees: + cols = [{"component": "Text", "text": emp["name"]}] + if includeBonus: + cols.append({"component": "Text", "text": f"Bonus: ${emp['bonus']}"}) + rows.append({"component": "Row", "children": cols}) + + return { + "component": "Card", + "child": { + "component": "Column", + "children": [ + {"component": "Text", "text": f"Payroll: {department}"}, + *rows, + ], + }, + } + + tmpl = DynamicTemplate( + name="PayrollSummary", + template_id="PayrollSummary", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + render=render_payroll, + description="Dynamic payroll summary calculation.", + ) + + processor = TemplateProcessor(templates=[tmpl], catalogs=BASIC_CATALOG) + expanded = processor.expand_template( + "payroll_root", "PayrollSummary", {"department": "AI Research"} + ) + + assert any(c.get("text") == "Payroll: AI Research" for c in expanded) + assert any(c.get("text") == "Bonus: $20000" for c in expanded) + + +def test_programmatic_dynamic_template_extra_params_filtered(): + """Verifies that dynamic render functions with explicit signatures do not break when receiving unexpected kwargs.""" + + def render_card(title: str): + return {"component": "Text", "text": title} + + tmpl = DynamicTemplate( + name="SimpleCard", + template_id="SimpleCard", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + render=render_card, + ) + processor = TemplateProcessor(templates=[tmpl], catalogs=BASIC_CATALOG) + + expanded = processor.expand_template( + "inst", + "SimpleCard", + {"title": "Filtered", "extra1": "drop_me", "extra2": 42}, + ) + assert len(expanded) == 1 + assert expanded[0]["text"] == "Filtered" + + +def test_dynamic_template_resolve_non_dict_fallback(): + """Verifies graceful fallback when a resolver returns a non-dict value.""" + layout_yaml = """ +version: "0.1" +name: NonDictLayout +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +parameters: + paramA: {type: string} +layout: + component: Text + text: ${paramA} +""" + + def bad_resolver(paramA: str): + return "not a dict" + + tmpl = DynamicTemplate( + name="NonDictLayout", + template_id="NonDictLayout", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + layout=layout_yaml, + resolver=bad_resolver, + ) + processor = TemplateProcessor(templates=[tmpl], catalogs=BASIC_CATALOG) + expanded = processor.expand_template("root", "NonDictLayout", {"paramA": "safe"}) + assert len(expanded) == 1 + assert expanded[0]["text"] == "safe" + + +def test_dynamic_template_loop_custom_as_variable(): + """Verifies dynamic template expansion utilizing custom loop variable naming.""" + layout_yaml = """ +version: "0.1" +name: CustomAsList +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +parameters: + items: {type: array} +layout: + component: Column + children: + loop: + param: items + as: item_var + item: + component: Text + text: ${item_var.label} +""" + tmpl = StaticTemplate.from_yaml(layout_yaml) + processor = TemplateProcessor(templates=[tmpl], catalogs=BASIC_CATALOG) + expanded = processor.expand_template( + "root", + "CustomAsList", + {"items": [{"label": "First"}, {"label": "Second"}]}, + ) + texts = [c["text"] for c in expanded if c.get("component") == "Text"] + assert "First" in texts + assert "Second" in texts + + +def test_template_processor_requires_catalogs(): + """Verifies that TemplateProcessor requires explicit catalogs and rejects default assumptions.""" + t = StaticTemplate( + name="StandaloneTemplate", + template_id="StandaloneTemplate", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + parameters={}, + components=[], + ) + with pytest.raises(ValueError, match="TemplateProcessor requires explicit catalog"): + TemplateProcessor(templates=[t]) + + +def test_template_processor_with_custom_domain_catalog(): + """Verifies TemplateProcessor when initialized with a custom domain catalog.""" + custom_catalog = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://company.org/custom_medical_catalog.json", + "title": "Medical Component Catalog", + "components": { + "PatientChart": {"type": "object"}, + "VitalsGauge": {"type": "object"}, + }, + "functions": {}, + } + + layout_yaml = """ +version: "0.1" +name: MedicalReport +catalogs: + - "https://company.org/custom_medical_catalog.json" +parameters: + patientName: {type: string} +layout: + component: PatientChart + properties: + name: ${patientName} +""" + tmpl = StaticTemplate.from_yaml(layout_yaml) + processor = TemplateProcessor(templates=[tmpl], catalogs=custom_catalog) + + assert ( + processor.base_catalog_id == "https://company.org/custom_medical_catalog.json" + ) + + cat = processor.generate_inference_catalog() + assert "PatientChart" in cat["components"] + assert "VitalsGauge" in cat["components"] + assert "MedicalReport" in cat["components"] + assert "Card" not in cat["components"] + assert "Button" not in cat["components"] + + +def test_multi_catalog_resolution_and_disambiguation(): + """Verifies multi-catalog resolution, collision detection, and explicit catalogId disambiguation.""" + catalog_a = { + "$id": "https://a2ui.org/cat_a.json", + "catalogId": "https://a2ui.org/cat_a.json", + "components": { + "SharedBox": {"type": "object"}, + "CompA": {"type": "object"}, + }, + } + catalog_b = { + "$id": "https://a2ui.org/cat_b.json", + "catalogId": "https://a2ui.org/cat_b.json", + "components": { + "SharedBox": {"type": "object"}, + "CompB": {"type": "object"}, + }, + } + + # Case 1: Ambiguous component without disambiguation raises ValueError + ambiguous_yaml = """ +version: "0.1" +name: AmbiguousTemplate +catalogs: + - "https://a2ui.org/cat_a.json" + - "https://a2ui.org/cat_b.json" +parameters: {} +layout: + component: SharedBox +""" + tmpl_ambiguous = StaticTemplate.from_yaml(ambiguous_yaml) + with pytest.raises(ValueError, match="ambiguous across multiple declared catalogs"): + TemplateProcessor( + templates=[tmpl_ambiguous], + catalogs=[catalog_a, catalog_b], + version="v1.0", + ) + + # Case 2: Disambiguated component with catalogId resolves successfully + disambiguated_yaml = """ +version: "0.1" +name: DisambiguatedTemplate +catalogs: + - "https://a2ui.org/cat_a.json" + - "https://a2ui.org/cat_b.json" +parameters: {} +layout: + component: SharedBox + catalogId: "https://a2ui.org/cat_b.json" +""" + tmpl_ok = StaticTemplate.from_yaml(disambiguated_yaml) + proc = TemplateProcessor( + templates=[tmpl_ok], + catalogs=[catalog_a, catalog_b], + version="v1.0", + ) + expanded = proc.expand_template("inst_1", "DisambiguatedTemplate", {}) + assert len(expanded) == 1 + assert expanded[0]["component"] == "SharedBox" + assert expanded[0]["catalogId"] == "https://a2ui.org/cat_b.json" + + +def test_v09_rejects_multi_catalog_template(): + """Verifies that A2UI v0.9 strictly rejects templates declaring multiple catalogs.""" + catalog_a = { + "$id": "https://a2ui.org/cat_a.json", + "components": {"CompA": {}}, + } + catalog_b = { + "$id": "https://a2ui.org/cat_b.json", + "components": {"CompB": {}}, + } + multi_yaml = """ +version: "0.1" +name: MultiCatTemplate +catalogs: + - "https://a2ui.org/cat_a.json" + - "https://a2ui.org/cat_b.json" +parameters: {} +layout: + component: CompA +""" + tmpl = StaticTemplate.from_yaml(multi_yaml) + with pytest.raises(ValueError, match="only supports a single catalog"): + TemplateProcessor( + templates=[tmpl], + catalogs=[catalog_a, catalog_b], + version="v0.9.1", + ) + + +def test_type_aliases_and_private_helpers(): + """Verifies that semantic type aliases and backwards-compatible private functions are available.""" + assert TemplateId is str + assert InstanceId is str + assert ComponentId is str + assert ParamPath is str + + params: TemplateParams = {"user": {"profile": {"tier": "Pro"}}} + found, val = _resolve_param_path("user.profile.tier", params) + assert found is True + assert val == "Pro" + + sub = _substitute_params("${user.profile.tier}", params) + assert sub == "Pro" + + t = StaticTemplate( + name="Dummy", + template_id="Dummy", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + version="0.1", + parameters={}, + components=[], + ) + p = TemplateProcessor(templates=[t], catalogs=BASIC_CATALOG) + p._validate_templates() + p.validate_templates() + + +def test_dynamic_template_decorator_processor_expansion(): + """Verifies that @dynamic_template can be directly registered and expanded by TemplateProcessor.""" + + @dynamic_template( + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + description="Renders a KPI metric display.", + ) + def kpi_metric(label: str, value: str, change: str = "+0.0%"): + return { + "component": "Card", + "child": { + "component": "Column", + "children": [ + {"component": "Text", "text": f"{label}: {value}"}, + {"component": "Text", "text": f"Change: {change}"}, + ], + }, + } + + processor = TemplateProcessor(templates=[kpi_metric], catalogs=BASIC_CATALOG) + expanded = processor.expand_template( + "inst_kpi", + "KpiMetric", + {"label": "Revenue", "value": "$1.2M", "change": "+12%"}, + ) + assert len(expanded) == 4 + assert any(c.get("text") == "Revenue: $1.2M" for c in expanded) + assert any(c.get("text") == "Change: +12%" for c in expanded) + + +def test_mustache_substitution_syntax(): + """Verifies that double-curly Mustache syntax {{ param }} is supported for substitutions, + preserves exact types, allows whitespace, and leaves client ${/data/path} bindings intact. + """ + layout_yaml = """ +version: "0.1" +name: MustacheCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +parameters: + count: {type: integer} + isActive: {type: boolean} + user: {type: object} + tags: {type: array} + dept: {type: string} +layout: + component: Card + child: + component: Column + children: + - component: Text + text: "{{ count }}" + - component: Text + text: "{{ isActive }}" + - component: Text + text: "Hello, {{ user.profile.name }}! Dept: {{ dept }}" + - component: Text + text: "Literal: \\\\{{ escaped }}" + - component: Text + text: + call: formatString + args: + value: "Live: ${/metrics/cpu}, Dept: {{ dept }}" +""" + tmpl = StaticTemplate.from_yaml(layout_yaml) + processor = TemplateProcessor(templates=[tmpl], catalogs=BASIC_CATALOG) + expanded = processor.expand_template( + "inst_1", + "MustacheCard", + { + "count": 42, + "isActive": True, + "user": {"profile": {"name": "Alice"}}, + "tags": ["a", "b"], + "dept": "Engineering", + }, + ) + + texts = [c for c in expanded if c.get("component") == "Text"] + # 1. Exact match integer type preserved + assert texts[0]["text"] == 42 + # 2. Exact match boolean with whitespace preserved + assert texts[1]["text"] is True + # 3. Embedded interpolation with dot-notation + assert texts[2]["text"] == "Hello, Alice! Dept: Engineering" + # 4. Escaped literal unescaped + assert texts[3]["text"] == "Literal: {{ escaped }}" + # 5. Client data-model path ${/metrics/cpu} preserved untouched while {{ dept }} substituted + assert texts[4]["text"] == { + "call": "formatString", + "args": {"value": "Live: ${/metrics/cpu}, Dept: Engineering"}, + } diff --git a/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_template_conformance.py b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_template_conformance.py new file mode 100644 index 0000000000..e489852806 --- /dev/null +++ b/agent_sdks/python/a2ui_agent/tests/inference_formats/experimental/template/test_template_conformance.py @@ -0,0 +1,174 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Conformance test runner for A2UI Templates executing declarative YAML suites.""" + +import json +from pathlib import Path +from typing import Any, Dict, List, Tuple +import jsonschema +import pytest +import yaml + +from a2ui.inference_formats.experimental.template import ( + StaticTemplate, + TemplateProcessor, +) +from a2ui.inference_formats.experimental.template.processor import ( + _substitute_params, +) + + +BASIC_CATALOG_PATH = ( + Path(__file__).resolve().parents[7] + / "specification" + / "v0_9_1" + / "catalogs" + / "basic" + / "catalog.json" +) +BASIC_CATALOG: Dict[str, Any] = {} +if BASIC_CATALOG_PATH.is_file(): + with open(BASIC_CATALOG_PATH, "r", encoding="utf-8") as f: + BASIC_CATALOG = json.load(f) + + +def get_conformance_dir() -> Path: + """Dynamically resolves the conformance directory regardless of nesting.""" + curr = Path(__file__).resolve().parent + return curr / "conformance" + + +def load_conformance_schema() -> Dict[str, Any]: + schema_path = get_conformance_dir() / "schema" / "template_conformance_schema.json" + with open(schema_path, "r", encoding="utf-8") as f: + return json.load(f) + + +def load_all_conformance_cases() -> List[Tuple[str, str, Dict[str, Any]]]: + """Loads and validates all test cases across conformance suite YAML files.""" + schema = load_conformance_schema() + cases: List[Tuple[str, str, Dict[str, Any]]] = [] + suites_dir = get_conformance_dir() / "suites" + + for yaml_path in sorted(suites_dir.glob("*.yaml")): + suite_name = yaml_path.name + with open(yaml_path, "r", encoding="utf-8") as f: + raw_cases = yaml.safe_load(f) or [] + + # Validate the suite file against conformance JSON Schema + jsonschema.validate(instance=raw_cases, schema=schema) + + for case in raw_cases: + cases.append((suite_name, case["name"], case)) + + return cases + + +CONFORMANCE_CASES = load_all_conformance_cases() + + +def _execute_case(case: Dict[str, Any]) -> Any: + action = case["action"] + + if action == "substitute_params": + val = case["args"]["value"] + params = case["args"]["params"] + return _substitute_params(val, params) + + elif action == "expand_template": + templates: List[StaticTemplate] = [] + if "template" in case: + templates.append(StaticTemplate.from_dict(case["template"])) + elif "templates" in case: + for t_dict in case["templates"]: + templates.append(StaticTemplate.from_dict(t_dict)) + + base_catalog = case.get("base_catalog", None) + catalogs = case.get("catalogs", None) or base_catalog + if catalogs is None and BASIC_CATALOG: + catalogs = [BASIC_CATALOG] + processor = TemplateProcessor(templates=templates, catalogs=catalogs) + + template_id = case.get( + "template_id", + templates[0].template_id if templates else "Unknown", + ) + instance_id = case.get("instance_id", "root") + args = case.get("args", {}) + + return processor.expand_template( + instance_id=instance_id, + template_id=template_id, + passed_params=args, + ) + + elif action == "process_message": + templates = [] + if "template" in case: + templates.append(StaticTemplate.from_dict(case["template"])) + elif "templates" in case: + for t_dict in case["templates"]: + templates.append(StaticTemplate.from_dict(t_dict)) + + base_catalog = case.get("base_catalog", None) + catalogs = case.get("catalogs", None) or base_catalog + if catalogs is None and BASIC_CATALOG: + catalogs = [BASIC_CATALOG] + processor = TemplateProcessor(templates=templates, catalogs=catalogs) + + return processor.process_message(case["message"]) + + elif action == "validate_template": + return StaticTemplate.from_dict(case["template"]) + + raise ValueError(f"Unknown conformance test action: '{action}'") + + +@pytest.mark.parametrize("suite_name,case_name,case", CONFORMANCE_CASES) +def test_template_conformance( + suite_name: str, case_name: str, case: Dict[str, Any] +) -> None: + """Executes a single declarative conformance test case.""" + if "expect_error" in case: + expected_msg = case["expect_error"].get("message", "") + with pytest.raises(Exception) as excinfo: + _execute_case(case) + if expected_msg: + assert expected_msg.lower() in str(excinfo.value).lower(), ( + f"[{suite_name}::{case_name}] Expected error containing" + f" '{expected_msg}', got: {str(excinfo.value)}" + ) + else: + actual = _execute_case(case) + expected = case["expect"] + if ( + isinstance(actual, list) + and isinstance(expected, list) + and all(isinstance(x, dict) and "id" in x for x in actual) + and all(isinstance(x, dict) and "id" in x for x in expected) + ): + actual_sorted = sorted(actual, key=lambda x: str(x["id"])) + expected_sorted = sorted(expected, key=lambda x: str(x["id"])) + assert actual_sorted == expected_sorted, ( + f"[{suite_name}::{case_name}] Result mismatch:\n" + f"Expected: {expected_sorted}\n" + f"Actual: {actual_sorted}" + ) + else: + assert actual == expected, ( + f"[{suite_name}::{case_name}] Result mismatch:\n" + f"Expected: {expected}\n" + f"Actual: {actual}" + ) diff --git a/samples/community/package.json b/samples/community/package.json index 8664559263..f71174a455 100644 --- a/samples/community/package.json +++ b/samples/community/package.json @@ -11,7 +11,8 @@ "mcp/*", "mcp/*/client", "mcp/*/apps/src", - "mcp/a2ui-in-mcpapps/server/apps/*" + "mcp/a2ui-in-mcpapps/server/apps/*", + "templates/client" ], "scripts": { "build:web": "yarn workspace angular-a2ui run build && yarn workspace @a2ui/mcp-apps-in-a2ui-sample run build && yarn workspace personalized-learning-demo run build && yarn workspace a2ui-in-mcpapps-client run build && yarn workspace a2ui-in-mcpapps-client run build:sandbox && yarn workspace basic-mcp-app-angular run build:all && yarn workspace basic-mcp-app-angular-editor run build:all && yarn workspace a2ui-over-mcp-recipe-client run build && yarn workspace mcp-calculator-app run build" diff --git a/samples/community/templates/README.md b/samples/community/templates/README.md new file mode 100644 index 0000000000..a05f8146b0 --- /dev/null +++ b/samples/community/templates/README.md @@ -0,0 +1,50 @@ +# A2UI templates community demo + +This sample demonstrates server-side template expansion in the A2UI Python Agent SDK using the standard Basic Catalog and React client renderer. + +--- + +## Overview + +- **Static declarative templates**: Parameterized layout subtrees (such as `UserProfile`, `TeamCard`, `TeamRoster`, `TeamGoalList`, `TeamFeedbackBoard`) defined in JSON and expanded into Basic Catalog primitives (`Card`, `Column`, `Row`, `Text`, `Divider`, `Icon`, `Button`). +- **Dynamic server resolvers**: Programmatic templates (such as `EmployeeSalaryCard`) that run Python resolver callbacks to query internal databases. The model only receives and passes identifiers, while sensitive numbers are injected server-side. +- **Express DSL & synchronous expansion**: The language model outputs concise Express DSL. The backend parser expands templates synchronously without requiring custom client components. +- **Interactive studio & library**: The React client includes an Interactive Chat with suggested prompt chips and latency/token metrics, alongside a 3-Stage Dynamic Template Studio showing input arguments, underlying blueprint JSON, and live rendered output. + +--- + +## Running the demo + +### 1. Start the backend server + +```bash +cd samples/community/templates +uv run uvicorn server:app --reload --port 8000 +``` + +To test live Gemini generation in addition to the preset templates, set your API key and optional model: + +```bash +export GEMINI_API_KEY="your-api-key" +export GEMINI_MODEL="gemini-flash-latest" # Optional, defaults to gemini-flash-latest +``` + +### 2. Start the frontend client + +```bash +cd samples/community/templates/client +yarn install +yarn dev +``` + +Open [http://localhost:5173](http://localhost:5173) in your browser. + +--- + +## Testing + +Run the Playwright end-to-end integration test suite: + +```bash +node samples/community/templates/test_e2e.mjs +``` diff --git a/samples/community/templates/client/.prettierignore b/samples/community/templates/client/.prettierignore new file mode 100644 index 0000000000..5e71162a6b --- /dev/null +++ b/samples/community/templates/client/.prettierignore @@ -0,0 +1,2 @@ +dist/ +.wireit/ diff --git a/samples/community/templates/client/eslint.config.mjs b/samples/community/templates/client/eslint.config.mjs new file mode 100644 index 0000000000..ba401290a5 --- /dev/null +++ b/samples/community/templates/client/eslint.config.mjs @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import tseslint from 'typescript-eslint'; +import reactPlugin from 'eslint-plugin-react'; +import reactHooksPlugin from 'eslint-plugin-react-hooks'; + +export default tseslint.config( + { + ignores: ['dist/**', 'vite.config.*', '**/node_modules/**', '**/.yarn/**'], + }, + { + files: ['src/**/*.{ts,tsx}'], + extends: [tseslint.configs.recommended], + plugins: { + react: reactPlugin, + 'react-hooks': reactHooksPlugin, + }, + rules: { + 'react/react-in-jsx-scope': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, + }, +); diff --git a/samples/community/templates/client/index.html b/samples/community/templates/client/index.html new file mode 100644 index 0000000000..3570cc797f --- /dev/null +++ b/samples/community/templates/client/index.html @@ -0,0 +1,60 @@ + + + + + + + + A2UI Templates - Community Demo + + + + + + + + +
+ + + diff --git a/samples/community/templates/client/package.json b/samples/community/templates/client/package.json new file mode 100644 index 0000000000..691df47443 --- /dev/null +++ b/samples/community/templates/client/package.json @@ -0,0 +1,51 @@ +{ + "name": "@a2ui/templates-community-demo", + "private": true, + "version": "0.1.0", + "description": "A2UI Templates Community Demo Client", + "type": "module", + "scripts": { + "dev": "vite", + "build": "wireit", + "preview": "vite preview", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "format": "prettier --write .", + "format:check": "prettier --check .", + "test": "node -e 'console.log(\"Workspace has no tests.\");'" + }, + "dependencies": { + "@a2ui/react": "^0.10.2", + "@a2ui/web_core": "^0.10.6", + "react": "^19.2.7", + "react-dom": "^19.2.7" + }, + "devDependencies": { + "@types/node": "^25.9.3", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.2", + "eslint": "^10.4.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.1.1", + "typescript": "5.9.3", + "typescript-eslint": "^8.61.0", + "vite": "^8.0.16", + "wireit": "^0.15.0-pre.2" + }, + "wireit": { + "build": { + "command": "tsc -b && vite build", + "files": [ + "src/**/*", + "index.html", + "tsconfig.json", + "vite.config.*" + ], + "output": [ + "dist/" + ] + } + } +} diff --git a/samples/community/templates/client/src/App.tsx b/samples/community/templates/client/src/App.tsx new file mode 100644 index 0000000000..e82f584c98 --- /dev/null +++ b/samples/community/templates/client/src/App.tsx @@ -0,0 +1,2027 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, {useState, useEffect, useRef} from 'react'; +import {MessageProcessor} from '@a2ui/web_core/v0_9'; +import {A2uiSurface, basicCatalog} from '@a2ui/react/v0_9'; + +interface FeedItem { + id: string; + type: 'user' | 'assistant'; + text?: string; + surfaceId?: string; + raw?: string; + messages?: any[]; + metrics?: { + latency?: number; + thinkingTokens?: number; + outputTokens?: number; + promptTokens?: number; + totalTokens?: number; + isPreset?: boolean; + }; +} + +interface TemplateDefinition { + version?: string; + templateId: string; + parameters: Record; + components?: any[]; + layout?: Record; + yamlContent?: string; + description?: string; + sampleData?: Record; + sampleMessages?: any[]; + isDynamic?: boolean; + isProgrammatic?: boolean; + isDataBinding?: boolean; + renderSource?: string; + layoutTemplate?: Record; + layoutTemplateYaml?: string; + resolvedData?: Record; + availablePresets?: Array<{label: string; value: string}>; +} + +const A2UI_THEME_VARS: React.CSSProperties = { + // Card & Container + ['--a2ui-card-border-radius' as any]: '16px', + ['--a2ui-card-background' as any]: '#ffffff', + ['--a2ui-card-border' as any]: '1px solid #e2e8f0', + ['--a2ui-card-box-shadow' as any]: + '0 4px 12px -2px rgba(15, 23, 42, 0.06), 0 2px 6px -1px rgba(15, 23, 42, 0.03)', + ['--a2ui-card-padding' as any]: '18px 22px', + ['--a2ui-card-margin' as any]: '8px 0', + + // Primitives & General + ['--a2ui-border-radius' as any]: '12px', + ['--a2ui-color-border' as any]: '#e2e8f0', + ['--a2ui-color-surface' as any]: '#ffffff', + ['--a2ui-color-on-surface' as any]: '#0f172a', + + // Primary Action & Button + ['--a2ui-color-primary' as any]: '#2563eb', + ['--a2ui-color-primary-hover' as any]: '#1d4ed8', + ['--a2ui-color-on-primary' as any]: '#ffffff', + ['--a2ui-button-border-radius' as any]: '10px', + ['--a2ui-button-background' as any]: '#2563eb', + ['--a2ui-button-padding' as any]: '8px 18px', + ['--a2ui-button-font-weight' as any]: '600', + ['--a2ui-button-box-shadow' as any]: '0 1px 2px rgba(37, 99, 235, 0.2)', + + // Spacing & Icons + ['--a2ui-spacing-s' as any]: '6px', + ['--a2ui-spacing-m' as any]: '12px', + ['--a2ui-spacing-l' as any]: '20px', + ['--a2ui-icon-size' as any]: '22px', + ['--a2ui-icon-color' as any]: '#2563eb', + + // Typography & Dividers + ['--a2ui-divider-color' as any]: '#f1f5f9', + ['--a2ui-text-caption-color' as any]: '#64748b', +}; + +export default function App() { + const [currentView, setCurrentView] = useState<'chat' | 'library'>('chat'); + + // Chat State + const [chatProcessor] = useState(() => new MessageProcessor([basicCatalog])); + const [, setChatTick] = useState(0); + const [feed, setFeed] = useState([]); + const [input, setInput] = useState(''); + const [loading, setLoading] = useState(false); + const [activeInspector, setActiveInspector] = useState(null); + const [inspectorTab, setInspectorTab] = useState<'express' | 'json'>('express'); + const [copiedTurn, setCopiedTurn] = useState(false); + const chatBottomRef = useRef(null); + + // Library State + const [libraryProcessor] = useState(() => new MessageProcessor([basicCatalog])); + const [, setLibraryTick] = useState(0); + const [templates, setTemplates] = useState([]); + const [selectedTemplateId, setSelectedTemplateId] = useState('UserProfile'); + const [libraryLoading, setLibraryLoading] = useState(false); + const [copiedTemplate, setCopiedTemplate] = useState(false); + + // Dynamic Template Interactive State + const [selectedDynamicEmpId, setSelectedDynamicEmpId] = useState('emp_101'); + const [payrollDept, setPayrollDept] = useState('Global Engineering'); + const [payrollIncludeBonus, setPayrollIncludeBonus] = useState(true); + const [dynamicResolvedData, setDynamicResolvedData] = useState | null>(null); + const [dynamicTab, setDynamicTab] = useState<'input' | 'layout' | 'resolved'>('input'); + const [dynamicResolving, setDynamicResolving] = useState(false); + + // Subscriptions + useEffect(() => { + const forceUpdate = () => setChatTick(t => t + 1); + const subCreated = chatProcessor.onSurfaceCreated(forceUpdate); + const subDeleted = chatProcessor.onSurfaceDeleted(forceUpdate); + return () => { + subCreated.unsubscribe(); + subDeleted.unsubscribe(); + }; + }, [chatProcessor]); + + useEffect(() => { + const forceUpdate = () => setLibraryTick(t => t + 1); + const subCreated = libraryProcessor.onSurfaceCreated(forceUpdate); + const subDeleted = libraryProcessor.onSurfaceDeleted(forceUpdate); + return () => { + subCreated.unsubscribe(); + subDeleted.unsubscribe(); + }; + }, [libraryProcessor]); + + useEffect(() => { + if (currentView === 'chat') { + chatBottomRef.current?.scrollIntoView({behavior: 'smooth'}); + } + }, [feed, loading, currentView]); + + useEffect(() => { + const fetchTemplates = async () => { + setLibraryLoading(true); + try { + const res = await fetch('http://127.0.0.1:8000/templates'); + if (res.ok) { + const list: TemplateDefinition[] = await res.json(); + setTemplates(list); + if (list.length > 0) { + setSelectedTemplateId(prev => + list.find(t => t.templateId === prev) ? prev : list[0].templateId, + ); + for (const item of list) { + if (item.sampleMessages && item.sampleMessages.length > 0) { + libraryProcessor.processMessages(item.sampleMessages); + if (item.isDynamic) { + const empId = item.sampleData?.employeeId || 'emp_101'; + const dynamicSurfaceId = `preview_${item.templateId}_${empId}`; + const dynamicMsgs = item.sampleMessages.map((m: any) => { + if (m.createSurface) { + return { + ...m, + createSurface: { + ...m.createSurface, + surfaceId: dynamicSurfaceId, + }, + }; + } + if (m.updateComponents) { + return { + ...m, + updateComponents: { + ...m.updateComponents, + surfaceId: dynamicSurfaceId, + }, + }; + } + return m; + }); + libraryProcessor.processMessages(dynamicMsgs); + } + } + } + } + } + } catch (e) { + console.error('Failed to load templates list:', e); + } finally { + setLibraryLoading(false); + } + }; + if (currentView === 'library' || templates.length === 0) { + fetchTemplates(); + } + }, [libraryProcessor, currentView]); + + const selectedTemplate = templates.find(t => t.templateId === selectedTemplateId); + + // When dynamic template selection changes, sync initial state + useEffect(() => { + if (selectedTemplate?.isDynamic) { + if (selectedTemplate.resolvedData) { + setDynamicResolvedData(selectedTemplate.resolvedData); + } + if (selectedTemplate.sampleData?.employeeId) { + setSelectedDynamicEmpId(selectedTemplate.sampleData.employeeId); + } + if (selectedTemplate.sampleData?.department) { + setPayrollDept(selectedTemplate.sampleData.department); + } + if (selectedTemplate.sampleData?.includeBonus !== undefined) { + setPayrollIncludeBonus(selectedTemplate.sampleData.includeBonus); + } + } + }, [selectedTemplate]); + + const handleResolveDynamicTemplate = async (paramInput?: any) => { + if (!selectedTemplate) return; + setDynamicResolving(true); + let sendParams: Record = {}; + let surfaceSuffix = 'default'; + + if (selectedTemplate.templateId === 'PayrollSummary') { + const dept = + typeof paramInput === 'object' && paramInput.department !== undefined + ? paramInput.department + : payrollDept; + const bonus = + typeof paramInput === 'object' && paramInput.includeBonus !== undefined + ? paramInput.includeBonus + : payrollIncludeBonus; + sendParams = {department: dept, includeBonus: bonus}; + surfaceSuffix = `${dept.replace(/\s+/g, '_')}_${bonus}`; + } else { + const empId = typeof paramInput === 'string' ? paramInput : selectedDynamicEmpId; + setSelectedDynamicEmpId(empId); + sendParams = {employeeId: empId}; + surfaceSuffix = empId; + } + + try { + const res = await fetch( + `http://127.0.0.1:8000/templates/${selectedTemplate.templateId}/resolve`, + { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({params: sendParams}), + }, + ); + if (!res.ok) { + throw new Error(`Server returned status ${res.status}`); + } + const data = await res.json(); + setDynamicResolvedData(data.resolvedData); + if (data.sampleMessages) { + const dynamicSurfaceId = `preview_${selectedTemplate.templateId}_${surfaceSuffix}`; + const updatedMessages = data.sampleMessages.map((m: any) => { + if (m.createSurface) { + return { + ...m, + createSurface: { + ...m.createSurface, + surfaceId: dynamicSurfaceId, + }, + }; + } + if (m.updateComponents) { + return { + ...m, + updateComponents: { + ...m.updateComponents, + surfaceId: dynamicSurfaceId, + }, + }; + } + return m; + }); + libraryProcessor.processMessages(updatedMessages); + setLibraryTick(t => t + 1); + } + } catch (err) { + console.error('Failed to resolve dynamic template:', err); + } finally { + setDynamicResolving(false); + } + }; + + const copyToClipboard = (text: string, isTemplate = false) => { + navigator.clipboard.writeText(text); + if (isTemplate) { + setCopiedTemplate(true); + setTimeout(() => setCopiedTemplate(false), 2000); + } else { + setCopiedTurn(true); + setTimeout(() => setCopiedTurn(false), 2000); + } + }; + + const sendPrompt = async (promptText: string) => { + const text = promptText.trim(); + if (!text || loading) return; + + setInput(''); + const surfaceId = `surface_${Date.now()}`; + setFeed(prev => [...prev, {id: `user_${Date.now()}`, type: 'user', text}]); + setLoading(true); + + try { + const res = await fetch('http://127.0.0.1:8000/interact', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + prompt: text, + surfaceId, + }), + }); + + if (!res.ok) { + throw new Error(`Server returned status ${res.status}`); + } + + const data = await res.json(); + if (data.messages && data.messages.length > 0) { + chatProcessor.processMessages(data.messages); + } + + let actualSurfaceId = data.surfaceId || surfaceId; + if (data.messages && data.messages.length > 0) { + const found = + data.messages.find((m: any) => m.createSurface?.surfaceId)?.createSurface?.surfaceId || + data.messages.find((m: any) => m.updateComponents?.surfaceId)?.updateComponents + ?.surfaceId; + if (found) { + actualSurfaceId = found; + } + } + + setFeed(prev => [ + ...prev, + { + id: `assistant_${Date.now()}`, + type: 'assistant', + text: data.text, + surfaceId: actualSurfaceId, + raw: data.raw, + messages: data.messages, + metrics: data.metrics, + }, + ]); + } catch (err: any) { + setFeed(prev => [ + ...prev, + { + id: `assistant_${Date.now()}`, + type: 'assistant', + text: `Error contacting server: ${err.message}. Make sure the FastAPI server is running on http://127.0.0.1:8000.`, + surfaceId, + }, + ]); + } finally { + setLoading(false); + } + }; + + return ( +
+ {/* Top Header */} +
+
+
+ + dashboard_customize + +
+
+

+ A2UI Templates +

+

+ Static & Dynamic Server Expansion · Basic Catalog +

+
+
+ + {/* View Switcher Tabs */} +
+ + +
+
+ + {/* Main Content View */} + {currentView === 'chat' ? ( +
+ {/* Presets Sidebar */} +
+
+

+ Example Presets +

+
+ {[ + { + label: '🔒 Verified Salary', + prompt: 'show verified salary', + desc: 'Dynamic server-resolved compensation', + }, + { + label: '💰 Payroll Summary', + prompt: 'show payroll summary', + desc: 'Programmatic dynamic template table', + }, + { + label: '📊 User Evaluation', + prompt: 'show user evaluation', + desc: 'Composite review & goals dashboard', + }, + { + label: '👤 User Profile', + prompt: 'show user profile', + desc: 'Single card profile', + }, + { + label: '👥 Team Roster', + prompt: 'show team roster', + desc: 'Nested team member cards', + }, + { + label: '🎯 Team Goals', + prompt: 'show team goals', + desc: 'Unrolled objectives list', + }, + { + label: '💬 Feedback Board', + prompt: 'show feedback board', + desc: 'Review cards with ratings', + }, + { + label: '⭐ Competency Panel', + prompt: 'show competency panel', + desc: 'Metrics & stats summary', + }, + ].map(btn => ( + + ))} +
+
+ +
+ Template Inference Format +
+ Click the ℹ️ Inspect button + on any turn to view the raw LLM Express DSL and expanded JSON. +
+
+ + {/* Chat Feed */} +
+
+ {feed.length === 0 && ( +
+
+ + auto_awesome + +
+

+ A2UI Templates Explorer +

+

+ Click a preset or select a suggested prompt below to observe static and dynamic + templates expanded server-side into standard A2UI primitives. +

+ +
+
+ Suggested Prompts +
+
+ {[ + { + icon: 'lock', + text: 'Show verified salary for Marcus Vance', + badge: 'Dynamic', + }, + { + icon: 'person', + text: 'Show user profile for Alice Smith', + badge: 'Template', + }, + { + icon: 'flag', + text: 'Show team goals for Core Protocol Engineering', + badge: 'Template', + }, + { + icon: 'reviews', + text: 'Show feedback board for Frontend Guild', + badge: 'Template', + }, + { + icon: 'groups', + text: 'Show team roster with Core Architecture', + badge: 'Template', + }, + { + icon: 'monitoring', + text: 'Show user evaluation for Alice Smith', + badge: 'Composite', + }, + ].map(chip => ( + + ))} +
+
+
+ )} + + {feed.map(item => { + const targetSurfaceId = + item.surfaceId || + item.messages?.find((m: any) => m.createSurface?.surfaceId)?.createSurface + ?.surfaceId || + item.messages?.find((m: any) => m.updateComponents?.surfaceId)?.updateComponents + ?.surfaceId; + const surface = targetSurfaceId + ? chatProcessor.model.getSurface(targetSurfaceId) + : undefined; + const isInspectorOpen = activeInspector === item.id; + const hasInspectionData = Boolean( + item.raw || (item.messages && item.messages.length > 0), + ); + + return ( +
+ {item.type === 'user' ? ( +
+ {item.text} +
+ ) : ( +
+
+ {item.text && ( +
+ {item.text} +
+ )} + +
+ {item.metrics && ( +
+ + ⏱️ + {item.metrics.latency}s + + + {item.metrics.thinkingTokens !== undefined && + item.metrics.thinkingTokens > 0 && ( + <> + + + 🧠 + {item.metrics.thinkingTokens} think + + + )} + + {item.metrics.outputTokens !== undefined && + item.metrics.outputTokens > 0 && ( + <> + + + 📝 + {item.metrics.outputTokens} out + + + )} +
+ )} + + {hasInspectionData && ( + + )} +
+
+ + {/* Inspector Drawer */} + {isInspectorOpen && ( +
+
+
+ + +
+ + +
+ +
+ {inspectorTab === 'express' ? ( +
+                                  {item.raw || '// No raw Express DSL received'}
+                                
+ ) : ( +
+                                  {JSON.stringify(item.messages || [], null, 2)}
+                                
+ )} +
+
+ )} + + {/* Rendered A2UI Surface */} + {surface ? ( +
+ +
+ ) : null} +
+ )} +
+ ); + })} + + {loading && ( +
+ + progress_activity + + Expanding template... +
+ )} +
+
+ + {/* Input Bar */} +
+ setInput(e.target.value)} + onKeyDown={e => e.key === 'Enter' && sendPrompt(input)} + placeholder="Type a template prompt (e.g. 'Show verified salary' or 'Show user profile')..." + disabled={loading} + style={{ + flex: 1, + padding: '14px 18px', + borderRadius: '12px', + border: '1px solid #cbd5e1', + fontSize: '14px', + outline: 'none', + transition: 'border-color 0.15s ease', + }} + onFocus={e => (e.target.style.borderColor = '#2563eb')} + onBlur={e => (e.target.style.borderColor = '#cbd5e1')} + /> + +
+
+
+ ) : ( + /* Template Library View */ +
+ {/* Library Sidebar List */} +
+
+

+ Registered Templates +

+

+ Inspect static declarative templates and dynamic server resolvers. +

+
+ + {templates.map(tmpl => { + const isSelected = tmpl.templateId === selectedTemplateId; + const paramCount = Object.keys(tmpl.parameters || {}).length; + const compCount = (tmpl.components || []).length; + + return ( + + ); + })} +
+ + {/* Studio Content */} + {selectedTemplate ? ( + selectedTemplate.isDynamic ? ( + /* Dynamic Template 3-Stage Inspector Studio */ +
+ {/* Header Banner */} +
+
+
+

+ {selectedTemplate.templateId} +

+ + ⚡ Dynamic Server Resolver + +
+

+ {selectedTemplate.description} +

+
+ + {/* Stage Switcher */} +
+ {[ + {id: 'input', label: '1. Input Interface'}, + { + id: 'layout', + label: selectedTemplate.isProgrammatic + ? '2. Python AST Generator' + : '2. Static Blueprint', + }, + {id: 'resolved', label: '3. Resolved Output'}, + ].map(tab => ( + + ))} +
+
+ + {/* 3-Stage Body */} +
+ {/* Left Column: Interactive Stages */} +
+ {dynamicTab === 'input' && ( +
+
+

+ Step 1: Simple LLM Input Interface +

+

+ The LLM generates only simple identifiers. Confidential figures are + never exposed in prompt context. +

+
+ + {/* Input Selector Form */} + {selectedTemplate.templateId === 'PayrollSummary' ? ( +
+
+ + { + setPayrollDept(e.target.value); + handleResolveDynamicTemplate({department: e.target.value}); + }} + style={{ + width: '100%', + padding: '8px 12px', + borderRadius: '8px', + border: '1px solid #cbd5e1', + fontSize: '13px', + boxSizing: 'border-box', + }} + /> +
+ + + +
+
+ Generated Express DSL by LLM: +
+
+                                {`\nroot = PayrollSummary("${payrollDept}", ${payrollIncludeBonus})\n`}
+                              
+
+
+ ) : ( +
+ + + +
+
+ Generated Express DSL by LLM: +
+
+                                {`\nroot = EmployeeSalaryCard("${selectedDynamicEmpId}")\n`}
+                              
+
+
+ )} + +
+ + + {selectedTemplate.isProgrammatic + ? '✓ Python execution engine active' + : '✓ Server resolver connected'} + +
+
+ )} + + {dynamicTab === 'layout' && ( +
+
+

+ {selectedTemplate.isProgrammatic + ? 'Step 2: Python Render Function (Programmatic AST Generator)' + : 'Step 2: Underlying Layout Template (Static Blueprint)'} +

+

+ {selectedTemplate.isProgrammatic + ? 'This template is generated directly by a Python render function using loops, conditionals, and math to construct the component AST.' + : 'The visual layout is declared once in YAML (salary_card.yaml). Parameter placeholders like baseSalary and annualBonus are populated by the server callback.'} +

+
+ +
+                          {selectedTemplate.isProgrammatic
+                            ? selectedTemplate.renderSource || '# Python render function'
+                            : selectedTemplate.layoutTemplateYaml ||
+                              selectedTemplate.yamlContent ||
+                              ''}
+                        
+
+ )} + + {dynamicTab === 'resolved' && ( +
+
+

+ Step 3: Server-Resolved Injected Data +

+

+ Live record retrieved from the internal HR database for{' '} + {selectedDynamicEmpId}. +

+
+ +
+                          {JSON.stringify(dynamicResolvedData || {}, null, 2)}
+                        
+
+ )} +
+ + {/* Right Column: Live Inflated Preview */} +
+
+

+ Inflated Output Preview +

+ + ✓ Live Inflated + +
+ +
+ {(() => { + const dynSurface = + libraryProcessor.model.getSurface( + `preview_${selectedTemplate.templateId}_${selectedDynamicEmpId}`, + ) || + libraryProcessor.model.getSurface( + `preview_${selectedTemplate.templateId}`, + ); + return dynSurface ? ( + + ) : ( +
+ No preview surface available for this template. +
+ ); + })()} +
+
+
+
+ ) : ( + /* Standard Static Template Studio */ +
+ {/* Left: Live Inflated Preview */} +
+
+
+

+ Inflated UI Preview +

+

+ Rendered via @a2ui/react using declared sampleData +

+
+ + ✓ Live Inflated + +
+ +
+ {libraryProcessor.model.getSurface(`preview_${selectedTemplate.templateId}`) ? ( + + ) : ( +
+ No preview surface available for this template. +
+ )} +
+ + {selectedTemplate.sampleData && ( +
+

+ Sample Data Inputs +

+
+                        {JSON.stringify(selectedTemplate.sampleData, null, 2)}
+                      
+
+ )} +
+ + {/* Right: Code with Line Numbers & Monospace Font */} +
+
+
+

+ Template Declaration (YAML) +

+

+ Parameterized YAML layout definition +

+
+ + +
+ +
+
+ {selectedTemplate.templateId.toLowerCase()}.yaml + YAML Schema draft 2020-12 +
+ +
+ {(() => { + const yamlText = selectedTemplate.yamlContent || ''; + const lines = yamlText.split('\n'); + + return ( + <> +
+ {lines.map((_, idx) => ( +
{idx + 1}
+ ))} +
+ +
+ {lines.map((line, idx) => ( +
{line || ' '}
+ ))} +
+ + ); + })()} +
+
+
+
+ ) + ) : ( +
+ {libraryLoading ? 'Loading templates...' : 'No templates available.'} +
+ )} +
+ )} +
+ ); +} diff --git a/samples/community/templates/client/src/main.tsx b/samples/community/templates/client/src/main.tsx new file mode 100644 index 0000000000..6d92e4f429 --- /dev/null +++ b/samples/community/templates/client/src/main.tsx @@ -0,0 +1,25 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + , +); diff --git a/samples/community/templates/client/tsconfig.json b/samples/community/templates/client/tsconfig.json new file mode 100644 index 0000000000..0426f7bb8e --- /dev/null +++ b/samples/community/templates/client/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/samples/community/templates/client/vite.config.ts b/samples/community/templates/client/vite.config.ts new file mode 100644 index 0000000000..95c8497c8d --- /dev/null +++ b/samples/community/templates/client/vite.config.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {defineConfig} from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + server: { + port: 5173, + open: false, + }, +}); diff --git a/agent_sdks/python/a2ui_agent/src/a2ui/template/__init__.py b/samples/community/templates/pyproject.toml similarity index 50% rename from agent_sdks/python/a2ui_agent/src/a2ui/template/__init__.py rename to samples/community/templates/pyproject.toml index 10c96753bb..c2dd8b8164 100644 --- a/agent_sdks/python/a2ui_agent/src/a2ui/template/__init__.py +++ b/samples/community/templates/pyproject.toml @@ -4,10 +4,27 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +[project] +name = "a2ui-templates-demo-server" +version = "0.1.0" +description = "A2UI Templates Community Demo Server" +requires-python = ">=3.10" +dependencies = [ + "fastapi>=0.115.0", + "uvicorn>=0.30.0", + "google-genai>=1.0.0", + "a2ui-agent-sdk", + "a2ui-core" +] + +[tool.uv.sources] +a2ui-agent-sdk = { path = "../../../agent_sdks/python/a2ui_agent", editable = true } +a2ui-core = { path = "../../../agent_sdks/python/a2ui_core", editable = true } diff --git a/samples/community/templates/server.py b/samples/community/templates/server.py new file mode 100644 index 0000000000..abd1d6c2a5 --- /dev/null +++ b/samples/community/templates/server.py @@ -0,0 +1,642 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Concise FastAPI server demonstrating A2UI Static and Dynamic Templates with Agent SDK.""" + +from __future__ import annotations + +import glob +import inspect +import os +from pathlib import Path +import time +from typing import Any, Dict, List +from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from google import genai +from google.genai import types +from pydantic import BaseModel + +from a2ui.inference_formats.experimental.template import ( + StaticTemplate, + DynamicTemplate, + dynamic_template, + TemplateInferenceFormat, +) + +app = FastAPI(title="A2UI Templates Community Demo Server") + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_headers=["*"], + allow_methods=["*"], +) + +MODEL_NAME = os.environ.get("GEMINI_MODEL", "gemini-flash-latest") +BASIC_CATALOG_ID = "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json" + +# Mock Secure HR / Compensation Database +EMPLOYEE_COMPENSATION_DB = { + "emp_101": { + "employeeName": "Dr. Elena Vance", + "role": "Principal Systems Architect", + "baseSalary": "$215,000", + "annualBonus": "$45,000", + "equity": "3,500 RSUs", + "clearanceLevel": "Level 5 - Confidential", + "verifiedAt": "2026-08-13", + }, + "emp_102": { + "employeeName": "Marcus Vance", + "role": "Streaming & Protocols Lead", + "baseSalary": "$195,000", + "annualBonus": "$38,000", + "equity": "2,800 RSUs", + "clearanceLevel": "Level 4 - Confidential", + "verifiedAt": "2026-08-13", + }, + "emp_103": { + "employeeName": "Aria Chen", + "role": "Head of Design Systems", + "baseSalary": "$205,000", + "annualBonus": "$42,000", + "equity": "3,100 RSUs", + "clearanceLevel": "Level 5 - Confidential", + "verifiedAt": "2026-08-13", + }, + "emp_104": { + "employeeName": "Liam Kjell", + "role": "Senior Framework Engineer", + "baseSalary": "$180,000", + "annualBonus": "$32,000", + "equity": "2,200 RSUs", + "clearanceLevel": "Level 3 - Internal", + "verifiedAt": "2026-08-13", + }, +} + + +def fetch_employee_compensation(employeeId: str) -> Dict[str, Any]: + """Fetches verified confidential compensation package from internal HR database.""" + if employeeId not in EMPLOYEE_COMPENSATION_DB: + raise ValueError( + f"Employee ID '{employeeId}' not found in HR compensation records." + f" Available: {list(EMPLOYEE_COMPENSATION_DB.keys())}" + ) + return EMPLOYEE_COMPENSATION_DB[employeeId] + + +@dynamic_template( + name="PayrollSummary", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + description=( + "Programmatic dynamic template that aggregates company payroll, sums" + " employee base salaries and bonuses using server Python logic, and builds" + " an interactive summary table. Pass department (default 'Engineering') and" + " includeBonus (default True)." + ), + sample_data={"department": "Global Engineering", "includeBonus": True}, +) +def render_payroll_summary( + department: str = "Global Engineering", includeBonus: bool = True +) -> Dict[str, Any]: + """Programmatic dynamic template: performs Python math, loops, formatting, and builds an AST table.""" + total_base = 0 + total_bonus = 0 + rows: List[Dict[str, Any]] = [] + + for emp_id, record in EMPLOYEE_COMPENSATION_DB.items(): + base_int = int(record["baseSalary"].replace("$", "").replace(",", "")) + bonus_int = int(record["annualBonus"].replace("$", "").replace(",", "")) + total_base += base_int + total_bonus += bonus_int + + cols = [ + {"component": "Text", "text": record["employeeName"], "variant": "body"}, + {"component": "Text", "text": record["role"], "variant": "caption"}, + {"component": "Text", "text": record["baseSalary"], "variant": "body"}, + ] + if includeBonus: + cols.append( + {"component": "Text", "text": record["annualBonus"], "variant": "body"} + ) + + rows.append({ + "component": "Row", + "justify": "spaceBetween", + "align": "center", + "children": cols, + }) + rows.append({"component": "Divider", "axis": "horizontal"}) + + # Header Row + header_cols = [ + {"component": "Text", "text": "Employee", "variant": "caption"}, + {"component": "Text", "text": "Role", "variant": "caption"}, + {"component": "Text", "text": "Base Salary", "variant": "caption"}, + ] + if includeBonus: + header_cols.append( + {"component": "Text", "text": "Annual Bonus", "variant": "caption"} + ) + + # Total Row + total_cols = [ + {"component": "Text", "text": "TOTAL PAYROLL", "variant": "h4"}, + { + "component": "Text", + "text": f"{len(EMPLOYEE_COMPENSATION_DB)} Employees", + "variant": "caption", + }, + {"component": "Text", "text": f"${total_base:,}", "variant": "h4"}, + ] + if includeBonus: + total_cols.append( + {"component": "Text", "text": f"${total_bonus:,}", "variant": "h4"} + ) + + total_budget = total_base + (total_bonus if includeBonus else 0) + + return { + "component": "Card", + "child": { + "component": "Column", + "children": [ + { + "component": "Row", + "justify": "spaceBetween", + "align": "center", + "children": [ + { + "component": "Row", + "align": "center", + "children": [ + {"component": "Icon", "name": "lock"}, + { + "component": "Text", + "text": ( + f"Payroll & Compensation Summary: {department}" + ), + "variant": "h3", + }, + ], + }, + { + "component": "Text", + "text": "Confidential HR Record", + "variant": "caption", + }, + ], + }, + {"component": "Divider", "axis": "horizontal"}, + { + "component": "Row", + "justify": "spaceBetween", + "align": "center", + "children": header_cols, + }, + {"component": "Divider", "axis": "horizontal"}, + *rows, + { + "component": "Row", + "justify": "spaceBetween", + "align": "center", + "children": total_cols, + }, + {"component": "Divider", "axis": "horizontal"}, + { + "component": "Row", + "justify": "spaceBetween", + "align": "center", + "children": [ + { + "component": "Text", + "text": ( + "🔒 Computed live by server Python execution engine" + ), + "variant": "caption", + }, + { + "component": "Text", + "text": f"Total Budget: ${total_budget:,}", + "variant": "caption", + }, + ], + }, + ], + }, + } + + +def load_templates() -> List[Any]: + """Loads all static templates and registers dynamic resolver templates.""" + current_file = Path(__file__).resolve() + templates_dir = current_file.parent / "templates" + templates_pattern = str(templates_dir / "*.yaml") + + templates_list = [] + salary_layout = None + + for path in glob.glob(templates_pattern): + loaded_templates = StaticTemplate.from_yaml_file(path) + for tmpl in loaded_templates: + if tmpl.name == "SalaryCard" or tmpl.template_id == "SalaryCard": + salary_layout = tmpl + else: + templates_list.append(tmpl) + + if salary_layout is not None: + # Register DynamicTemplate for EmployeeSalaryCard (Data Binding Mode) + dynamic_salary = DynamicTemplate( + version="0.1", + name="EmployeeSalaryCard", + template_id="EmployeeSalaryCard", + catalogs=[ + "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" + ], + resolver=fetch_employee_compensation, + layout=salary_layout, + description=( + "Secure verified employee compensation card. Pass only the" + " employeeId ('emp_101', 'emp_102', 'emp_103', 'emp_104');" + " compensation data is securely fetched server-side from the" + " HR database." + ), + sample_data={"employeeId": "emp_101"}, + ) + templates_list.append(dynamic_salary) + + # Register DynamicTemplate for PayrollSummary (Programmatic Render Mode via decorator) + templates_list.append(render_payroll_summary) + + return templates_list + + +templates = load_templates() +format_instance = TemplateInferenceFormat( + templates=templates, + surface_id="main", + version="0.9.1", +) + +ROLE_DESCRIPTION = """You are an A2UI interface assistant. When helpful, respond with visual UI using the compact A2UI Express DSL inside `` tags. + +Select and present only the UI components that are directly relevant to the user's request. Depending on the query, this may be a single template, a standard primitive, or a custom composed layout that you invent to address the query. + +You can compose high-level templates and primitive components together: +- Layout & Containers: `Column`, `Row`, `Card`, `SectionCard(title, description, headerAction, children)`, `TwoColumnLayout(headerChild, leftChildren, rightChildren)`. +- Reusable & Dynamic Templates: + - `UserProfile(userId, userName, role)` for individual identity cards. + - `EmployeeSalaryCard(employeeId)` for verified employee compensation. Pass only the employeeId (e.g. "emp_101" for Dr. Elena Vance, "emp_102" for Marcus Vance, "emp_103" for Aria Chen, "emp_104" for Liam Kjell). Confidential compensation data is securely resolved server-side from the HR database. + - `TeamMemberKnowledgePanel(userName, role, experienceYears, completedTasks)` for stats and skill summaries. + - `TeamGoalList(teamName, goals)` or `GoalItem(title, priority, targetDate)` for objective tracking. + - `TeamFeedbackBoard(teamName, feedbacks)` or `FeedbackItem(author, note, rating)` for reviews and retrospectives. + - `TeamCard(teamName, members)` and `TeamRoster(directoryTitle, children)` for organizational hierarchies. + +For complex queries requiring multiple sections (such as a performance review or project status), you can invent appropriate composite layouts—for instance, grouping a `TeamMemberKnowledgePanel`, `TeamFeedbackBoard`, and `TeamGoalList` within a `Column` or `TwoColumnLayout`.""" + +SYSTEM_PROMPT = format_instance.prompt_generator.generate( + role_description=ROLE_DESCRIPTION, + include_schema=True, +) + + +class ChatRequest(BaseModel): + prompt: str + surfaceId: str = "surface_1" + conversationId: str = "default_conv" + + +class DynamicResolveRequest(BaseModel): + params: Dict[str, Any] + + +PRESET_RESPONSES = { + "show user profile": ( + """ + + root = UserProfile("usr_101", "Alice Smith", "Lead Architect") + + """ + ), + "show verified salary": ( + """ + + root = EmployeeSalaryCard("emp_102") + + """ + ), + "show payroll summary": ( + """ + + root = PayrollSummary("Global Engineering", true) + + """ + ), + "show user evaluation": ( + """ + + knowledge = TeamMemberKnowledgePanel("Alice Smith", "Lead Systems Architect", 9, 142) + feedbacks = TeamFeedbackBoard("Peer Reviews & Feedback", [ + {author: "Dr. Elena Vance", note: "Exceptional architecture design and synchronous template engine.", rating: 5}, + {author: "Marcus Vance", note: "Great mentor on A2UI streaming and component catalogs.", rating: 5} + ]) + goals = TeamGoalList("2026 Objectives", [ + {title: "Finalize A2UI Protocol Specification", priority: "High", targetDate: "2026-09-30"}, + {title: "Publish Community Template Studio", priority: "High", targetDate: "2026-10-15"} + ]) + root = Column([knowledge, feedbacks, goals]) + + """ + ), + "show team roster": ( + """ + + team1 = TeamCard("Core Architecture", [ + {userId: "u1", userName: "Dr. Elena Vance", role: "Principal Architect"}, + {userId: "u2", userName: "Marcus Vance", role: "Streaming Lead"} + ]) + team2 = TeamCard("Design Systems", [ + {userId: "u3", userName: "Aria Chen", role: "Head of Design"}, + {userId: "u4", userName: "Liam Kjell", role: "Senior Engineer"} + ]) + root = TeamRoster("Organization Directory", [team1, team2]) + + """ + ), + "show team goals": ( + """ + + root = TeamGoalList("Core Protocol Engineering", [ + {title: "Deliver synchronous template expansion engine", priority: "High", targetDate: "2026-08-30"}, + {title: "Redesign templates for Basic Catalog", priority: "High", targetDate: "2026-08-15"}, + {title: "Simplify community demo architectures", priority: "Medium", targetDate: "2026-09-01"} + ]) + + """ + ), + "show feedback board": ( + """ + + root = TeamFeedbackBoard("Frontend & Protocols Guild", [ + {author: "Dr. Elena Vance", note: "Synchronous template expansion eliminated all streaming race conditions.", rating: 5}, + {author: "Marcus Vance", note: "Standard Basic Catalog components ensure 100% cross-renderer compatibility.", rating: 5} + ]) + + """ + ), + "show competency panel": ( + """ + + root = TeamMemberKnowledgePanel("Alice Smith", "Lead Systems Architect", 9, 142) + + """ + ), +} + + +@app.get("/templates") +@app.get("/api/templates") +def list_templates(): + res = [] + for t in templates: + t_dict = t.to_dict() + t_dict["yamlContent"] = t.to_yaml() + sample_params = t.sample_data or {} + try: + expanded_components = format_instance.processor.expand_template( + "root", t.template_id, sample_params + ) + sample_messages = [ + { + "version": "v0.9.1", + "createSurface": { + "surfaceId": f"preview_{t.template_id}", + "catalogId": BASIC_CATALOG_ID, + }, + }, + { + "version": "v0.9.1", + "updateComponents": { + "surfaceId": f"preview_{t.template_id}", + "components": expanded_components, + }, + }, + ] + except Exception: + sample_messages = [] + t_dict["sampleMessages"] = sample_messages + + if getattr(t, "is_dynamic", False): + dynamic_tmpl: DynamicTemplate = t # type: ignore + t_dict["isDynamic"] = True + if getattr(dynamic_tmpl, "render_fn", None) is not None: + t_dict["isProgrammatic"] = True + try: + t_dict["renderSource"] = inspect.getsource(dynamic_tmpl.render_fn) + except Exception: + t_dict["renderSource"] = "" + if dynamic_tmpl.layout is not None: + t_dict["isDataBinding"] = True + t_dict["layoutTemplate"] = dynamic_tmpl.layout.to_dict() + t_dict["layoutTemplateYaml"] = dynamic_tmpl.layout.to_yaml() + # Run resolver on sampleData to show resolved state + try: + t_dict["resolvedData"] = dynamic_tmpl.resolve(sample_params) + except Exception: + t_dict["resolvedData"] = {} + if dynamic_tmpl.template_id == "EmployeeSalaryCard": + t_dict["availablePresets"] = [ + {"label": f"{v['employeeName']} ({k})", "value": k} + for k, v in EMPLOYEE_COMPENSATION_DB.items() + ] + + res.append(t_dict) + return res + + +@app.post("/templates/{template_id}/resolve") +@app.post("/api/templates/{template_id}/resolve") +def resolve_template(template_id: str, req: DynamicResolveRequest): + tmpl = format_instance.processor.templates.get(template_id) + if not tmpl: + raise HTTPException(status_code=404, detail="Template not found") + + try: + expanded_components = format_instance.processor.expand_template( + "root", template_id, req.params + ) + sample_messages = [ + { + "version": "v0.9.1", + "createSurface": { + "surfaceId": f"preview_{template_id}", + "catalogId": BASIC_CATALOG_ID, + }, + }, + { + "version": "v0.9.1", + "updateComponents": { + "surfaceId": f"preview_{template_id}", + "components": expanded_components, + }, + }, + ] + resolved_data = {} + if getattr(tmpl, "is_dynamic", False): + if getattr(tmpl, "render_fn", None) is not None: + resolved_data = { + "execution": "Python Programmatic Render Function", + "generatedComponentCount": len(expanded_components), + "appliedParams": req.params, + } + else: + resolved_data = tmpl.resolve(req.params) # type: ignore + + return { + "expandedComponents": expanded_components, + "sampleMessages": sample_messages, + "resolvedData": resolved_data, + } + except Exception as e: + raise HTTPException(status_code=400, detail=str(e)) + + +@app.post("/interact") +@app.post("/api/chat") +async def chat(req: ChatRequest): + start_time = time.perf_counter() + prompt_lower = req.prompt.strip().lower() + + # 1. Preset shortcut responses for instant offline evaluation + if prompt_lower in PRESET_RESPONSES: + dsl = PRESET_RESPONSES[prompt_lower] + target_format = TemplateInferenceFormat( + templates=templates, + surface_id=req.surfaceId, + version="0.9.1", + ) + parts = target_format.parser.parse_response(dsl) + messages = parts[0].a2ui_json if parts and parts[0].a2ui_json else [] + latency = round(time.perf_counter() - start_time, 3) + return { + "messages": messages, + "raw": dsl.strip(), + "text": f"Here is the rendered {req.prompt}:", + "surfaceId": req.surfaceId, + "metrics": { + "latency": latency, + "thinkingTokens": 0, + "outputTokens": len(dsl.split()), + "isPreset": True, + }, + } + + # 2. Live Gemini inference if API key is provided + api_key = os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY") + if api_key: + try: + client = genai.Client(api_key=api_key) + response = await client.aio.models.generate_content( + model=MODEL_NAME, + contents=[req.prompt], + config=types.GenerateContentConfig( + system_instruction=SYSTEM_PROMPT, + response_mime_type="text/plain", + ), + ) + latency = round(time.perf_counter() - start_time, 2) + raw_text = response.text or "" + target_format = TemplateInferenceFormat( + templates=templates, + surface_id=req.surfaceId, + version="0.9.1", + ) + parts = target_format.parser.parse_response(raw_text) + + messages = [] + text_parts = [] + for part in parts: + if part.text: + text_parts.append(part.text) + if part.a2ui_json: + messages.extend(part.a2ui_json) + + thinking_tokens = 0 + candidates_tokens = 0 + if response.usage_metadata: + thinking_tokens = ( + getattr(response.usage_metadata, "thoughts_token_count", 0) or 0 + ) + candidates_tokens = ( + getattr(response.usage_metadata, "candidates_token_count", 0) or 0 + ) + + actual_surface_id = req.surfaceId + for msg in messages: + if isinstance(msg, dict): + if "createSurface" in msg and "surfaceId" in msg["createSurface"]: + actual_surface_id = msg["createSurface"]["surfaceId"] + break + elif ( + "updateComponents" in msg + and "surfaceId" in msg["updateComponents"] + ): + actual_surface_id = msg["updateComponents"]["surfaceId"] + break + + return { + "messages": messages, + "raw": raw_text.strip(), + "text": "\n".join(text_parts).strip() or "UI generated successfully.", + "surfaceId": actual_surface_id, + "metrics": { + "latency": latency, + "thinkingTokens": thinking_tokens, + "outputTokens": candidates_tokens, + "isPreset": False, + }, + } + except Exception as e: + return { + "messages": [], + "raw": f"Error: {str(e)}", + "text": f"Error generating template UI: {str(e)}", + "surfaceId": req.surfaceId, + "metrics": { + "latency": round(time.perf_counter() - start_time, 2), + "thinkingTokens": 0, + "outputTokens": 0, + "isPreset": False, + }, + } + + # 3. Fallback when no Gemini API key is configured + return { + "messages": [], + "raw": "", + "text": ( + "Gemini API key is not configured on the server. Please click one of the" + " preset buttons above or set the GEMINI_API_KEY environment variable." + ), + "surfaceId": req.surfaceId, + "metrics": { + "latency": 0.0, + "thinkingTokens": 0, + "outputTokens": 0, + "isPreset": True, + }, + } diff --git a/samples/community/templates/templates/feedback_item.yaml b/samples/community/templates/templates/feedback_item.yaml new file mode 100644 index 0000000000..a68544221a --- /dev/null +++ b/samples/community/templates/templates/feedback_item.yaml @@ -0,0 +1,62 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: FeedbackItem +description: Card showing feedback note, author, and rating. +parameters: + author: + type: string + title: Author Name + description: The name of the colleague or customer providing feedback. + note: + type: string + title: Feedback Note + description: The written feedback or retrospective comment. + rating: + type: number + title: Feedback Rating + description: Score from 1 to 5. + minimum: 1 + maximum: 5 + default: 5 +layout: + component: Card + child: + component: Column + children: + - component: Text + text: "{{ note }}" + + variant: body + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ author }}" + + variant: caption + - component: Text + text: "Rating: {{ rating }}/5" + variant: caption +sampleData: + author: Dr. Elena Vance + note: A2UI templates are fast and easy to compose. + rating: 5 +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: FeedbackItem diff --git a/samples/community/templates/templates/goal_item.yaml b/samples/community/templates/templates/goal_item.yaml new file mode 100644 index 0000000000..c04b39a99d --- /dev/null +++ b/samples/community/templates/templates/goal_item.yaml @@ -0,0 +1,75 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: GoalItem +description: Card showing an individual objective with priority, title, target date, + and action button. +parameters: + title: + type: string + title: Goal Title + description: Summary title of the objective. + priority: + type: enum + title: Priority Level + description: Urgency rating for the objective. + values: + - High + - Medium + - Low + default: Medium + targetDate: + type: string + title: Target Date + description: Target completion date in YYYY-MM-DD format. + default: "2026-12-31" +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "Priority: {{ priority }}" + variant: caption + - component: Icon + name: star + - component: Text + text: "{{ title }}" + + variant: h4 + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "Due: {{ targetDate }}" + variant: caption + - component: Button + child: + component: Text + text: View Details +sampleData: + title: Launch A2UI SDK v1.0 + priority: High + targetDate: "2026-09-30" +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: GoalItem diff --git a/samples/community/templates/templates/salary_card.yaml b/samples/community/templates/templates/salary_card.yaml new file mode 100644 index 0000000000..7add7d2838 --- /dev/null +++ b/samples/community/templates/templates/salary_card.yaml @@ -0,0 +1,137 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: SalaryCard +description: Layout card for employee compensation package with security verification + badge. +parameters: + employeeName: + type: string + title: Employee Full Name + description: Full name of the verified employee. + role: + type: string + title: Job Title + description: Official company role. + baseSalary: + type: string + title: Base Salary + description: Annual base compensation. + annualBonus: + type: string + title: Annual Bonus + description: Target annual incentive bonus. + equity: + type: string + title: Equity Grants + description: Stock units or RSU package. + clearanceLevel: + type: string + title: Security Clearance + description: Confidentiality level. + default: Level 4 - Confidential + verifiedAt: + type: string + title: Verification Date + description: Timestamp of record retrieval. + default: "2026-08-13" +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Row + align: center + children: + - component: Icon + name: lock + - component: Text + text: Verified Compensation + variant: caption + - component: Text + text: "{{ clearanceLevel }}" + + variant: caption + - component: Column + children: + - component: Text + text: "{{ employeeName }}" + + variant: h3 + id: name_txt + - component: Text + text: "{{ role }}" + + variant: body + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + children: + - component: Column + children: + - component: Text + text: Base Salary + variant: caption + - component: Text + text: "{{ baseSalary }}" + + variant: h4 + id: sal_val + - component: Column + children: + - component: Text + text: Annual Bonus + variant: caption + - component: Text + text: "{{ annualBonus }}" + + variant: h4 + - component: Column + children: + - component: Text + text: Equity Grants + variant: caption + - component: Text + text: "{{ equity }}" + + variant: h4 + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "\U0001F512 Fetched live from secure HR database" + variant: caption + - component: Text + text: "Verified: {{ verifiedAt }}" + variant: caption +sampleData: + employeeName: Dr. Elena Vance + role: Principal Systems Architect + baseSalary: $215,000 + annualBonus: $45,000 + equity: 3,500 RSUs + clearanceLevel: Level 5 - Confidential + verifiedAt: "2026-08-13" +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: SalaryCard diff --git a/samples/community/templates/templates/section_card.yaml b/samples/community/templates/templates/section_card.yaml new file mode 100644 index 0000000000..6083919f7a --- /dev/null +++ b/samples/community/templates/templates/section_card.yaml @@ -0,0 +1,71 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: SectionCard +description: Standard container card with title, description, optional action, and + child components. +parameters: + title: + type: string + title: Section Title + description: Heading text displayed at the top of the section card. + description: + type: string + title: Section Description + description: Subordinate descriptive text beneath the title. + default: "" + headerAction: + type: child + title: Header Action Component + description: Single child component placed in the right side of the header. + children: + type: children + title: Section Children + description: Child component IDs rendered in the section body. + default: [] +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ title }}" + + variant: h3 + - component: Column + id: action_slot + children: "{{ headerAction }}" + + - component: Text + text: "{{ description }}" + + variant: caption + - component: Divider + axis: horizontal + - component: Column + id: body_container + children: "{{ children }}" + +sampleData: + title: Protocol Overview + description: High-level summary of the streaming architecture. + children: [] +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: SectionCard diff --git a/samples/community/templates/templates/team_card.yaml b/samples/community/templates/templates/team_card.yaml new file mode 100644 index 0000000000..31811857a0 --- /dev/null +++ b/samples/community/templates/templates/team_card.yaml @@ -0,0 +1,83 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: TeamCard +description: Card showing team header and unrolled member cards. +parameters: + teamName: + type: string + title: Team Name + description: The display name of the team. + members: + type: array + title: Team Members List + description: Array of team member objects. + items: + type: object + title: Team Member + properties: + userId: + type: string + title: User ID + description: Unique identifier of the user. + userName: + type: string + title: User Name + description: Full name of the user. + role: + type: string + title: Role Name + description: Role or title of the user. + default: Member + required: + - userId + - userName +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ teamName }}" + + variant: h3 + - component: Icon + name: person + - component: Divider + axis: horizontal + - component: Column + children: + loop: + param: members + template: UserProfile +sampleData: + teamName: Antigravity Devs + members: + - userId: usr_101 + userName: Alice Smith + role: Lead Architect + - userId: usr_102 + userName: Bob Jones + role: Senior Engineer + - userId: usr_103 + userName: Charlie Brown + role: Product Manager +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: TeamCard diff --git a/samples/community/templates/templates/team_feedback_board.yaml b/samples/community/templates/templates/team_feedback_board.yaml new file mode 100644 index 0000000000..75e4b5d6ca --- /dev/null +++ b/samples/community/templates/templates/team_feedback_board.yaml @@ -0,0 +1,80 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: TeamFeedbackBoard +description: Feedback board showing team header and feedback items. +parameters: + teamName: + type: string + title: Team Name + description: The display name of the team whose feedback board is being rendered. + feedbacks: + type: array + title: Feedbacks List + description: Array of feedback objects with author, note, and rating. + items: + type: object + title: Feedback Review + properties: + author: + type: string + title: Author Name + description: Full name of the person giving feedback. + note: + type: string + title: Feedback Note + description: Textual comment or recommendation. + rating: + type: number + title: Rating Score + minimum: 1 + maximum: 5 + default: 5 + required: + - author + - note +layout: + component: Column + children: + - component: Card + child: + component: Row + align: center + children: + - component: Icon + name: mail + - component: Text + text: "Feedback & Retrospective: {{ teamName }}" + variant: h2 + - component: Column + id: feedbacks_container + children: + loop: + param: feedbacks + template: FeedbackItem +sampleData: + teamName: Streaming & Protocols Guild + feedbacks: + - author: Dr. Elena Vance + note: Splitting createSurface and updateComponents cleanly unblocked sequential + stream processing. + rating: 5 + - author: Marcus Vance + note: Unrolling nested lists statically in Python enables instant frontend mounting + with zero runtime recursion. + rating: 5 +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: TeamFeedbackBoard diff --git a/samples/community/templates/templates/team_goal_list.yaml b/samples/community/templates/templates/team_goal_list.yaml new file mode 100644 index 0000000000..dc652ce577 --- /dev/null +++ b/samples/community/templates/templates/team_goal_list.yaml @@ -0,0 +1,79 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: TeamGoalList +description: List of team goals with header banner. +parameters: + teamName: + type: string + title: Team Name + description: The display name of the team whose goals are being listed. + goals: + type: array + title: Goals List + description: Array of goal objects with title, priority, and targetDate. + items: + type: object + title: Goal Definition + properties: + title: + type: string + title: Goal Title + description: Summary title of the objective + priority: + type: enum + title: Priority Level + values: + - High + - Medium + - Low + default: Medium + targetDate: + type: string + title: Target Date + description: Target completion date (YYYY-MM-DD) + required: + - title +layout: + component: Column + children: + - component: Card + child: + component: Row + align: center + children: + - component: Icon + name: star + - component: Text + text: "Strategic Objectives: {{ teamName }}" + variant: h2 + - component: Column + id: goals_container + children: + loop: + param: goals + template: GoalItem +sampleData: + teamName: A2UI Core Team + goals: + - title: Implement bidirectional child/children container resolution + priority: High + targetDate: "2026-07-15" + - title: Upgrade all templates to standard Basic Catalog components + priority: High + targetDate: "2026-07-10" +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: TeamGoalList diff --git a/samples/community/templates/templates/team_member_knowledge_panel.yaml b/samples/community/templates/templates/team_member_knowledge_panel.yaml new file mode 100644 index 0000000000..bbc4ca7e1f --- /dev/null +++ b/samples/community/templates/templates/team_member_knowledge_panel.yaml @@ -0,0 +1,96 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: TeamMemberKnowledgePanel +description: Card showing competency panel with user experience years and completed + task count. +parameters: + userName: + type: string + title: User Display Name + description: The full name of the team member. + role: + type: string + title: Role Name + description: The operational role of the team member. + experienceYears: + type: integer + title: Years of Experience + description: The number of years of professional experience. + minimum: 0 + completedTasks: + type: integer + title: Completed Tasks Count + description: The count of completed tasks or tickets. + minimum: 0 +layout: + component: Card + child: + component: Column + children: + - component: Row + align: center + children: + - component: Icon + name: check + - component: Text + text: "Competency: {{ userName }}" + variant: h4 + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + children: + - component: Column + align: center + children: + - component: Text + text: Role + variant: caption + - component: Text + text: "{{ role }}" + + variant: body + - component: Column + align: center + children: + - component: Text + text: Experience + variant: caption + - component: Text + text: "{{ experienceYears }} Yrs" + + variant: body + - component: Column + align: center + children: + - component: Text + text: Tasks + variant: caption + - component: Text + text: "{{ completedTasks }} Done" + + variant: body + - component: Text + text: Verified Core Contributor + variant: caption +sampleData: + userName: Alice Smith + role: Systems Architect + experienceYears: 9 + completedTasks: 142 +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: TeamMemberKnowledgePanel diff --git a/samples/community/templates/templates/team_roster.yaml b/samples/community/templates/templates/team_roster.yaml new file mode 100644 index 0000000000..3bf023c3a3 --- /dev/null +++ b/samples/community/templates/templates/team_roster.yaml @@ -0,0 +1,45 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: TeamRoster +description: Team directory roster with styled header banner and nested team lists. +parameters: + directoryTitle: + type: string + title: Directory Title + description: Title text for the team directory. + children: + type: children + title: Team Cards List + description: List of child TeamCard components. + default: [] +layout: + component: Column + children: + - component: Text + text: "{{ directoryTitle }}" + + variant: h1 + - component: Divider + axis: horizontal + - component: Column + children: "{{ children }}" + +sampleData: + directoryTitle: Global Engineering Directory + children: [] +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: TeamRoster diff --git a/samples/community/templates/templates/two_column_layout.yaml b/samples/community/templates/templates/two_column_layout.yaml new file mode 100644 index 0000000000..45aa31700f --- /dev/null +++ b/samples/community/templates/templates/two_column_layout.yaml @@ -0,0 +1,58 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: TwoColumnLayout +description: Responsive two-column dashboard layout with banner header and split content + regions. +parameters: + headerChild: + type: child + title: Header Component Slot + description: Single child component ID mounted at the top banner. + leftChildren: + type: children + title: Left Column Children + description: Child components placed in the left primary region. + default: [] + rightChildren: + type: children + title: Right Column Children + description: Child components placed in the right secondary region. + default: [] +layout: + component: Column + children: + - component: Column + children: "{{ headerChild }}" + + - component: Divider + axis: horizontal + - component: Row + children: + - component: Column + children: "{{ leftChildren }}" + + - component: Column + children: "{{ rightChildren }}" + +sampleData: + headerChild: + component: Text + text: Header Title + leftChildren: [] + rightChildren: [] +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: TwoColumnLayout diff --git a/samples/community/templates/templates/user_profile.yaml b/samples/community/templates/templates/user_profile.yaml new file mode 100644 index 0000000000..038c47f65c --- /dev/null +++ b/samples/community/templates/templates/user_profile.yaml @@ -0,0 +1,54 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +templateId: UserProfile +description: User profile card displaying avatar, full name, and role. +parameters: + userId: + type: string + title: User ID + description: Unique user account ID. + userName: + type: string + title: User Name + description: Full name of the user. + role: + type: string + title: Role + description: Job title or role. + default: Member +layout: + component: Card + child: + component: Column + align: center + children: + - component: Icon + name: person + - component: Text + text: "{{ userName }}" + + variant: h3 + - component: Text + text: "{{ role }}" + + variant: caption +sampleData: + userId: usr_101 + userName: Alice Smith + role: Lead Architect +catalogs: + - https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json +name: UserProfile diff --git a/samples/community/templates/test_e2e.mjs b/samples/community/templates/test_e2e.mjs new file mode 100644 index 0000000000..ec364cb3ab --- /dev/null +++ b/samples/community/templates/test_e2e.mjs @@ -0,0 +1,256 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {chromium} from 'playwright'; + +async function runE2ETest() { + console.log( + '🚀 Starting A2UI Templates End-to-End Test (Presets + Inspector + Template Library + Live LLM)...', + ); + + const browser = await chromium.launch({headless: true}); + const page = await browser.newPage(); + + const pageErrors = []; + page.on('pageerror', err => { + console.error('❌ Page Error:', err.message); + pageErrors.push(err.message); + }); + + try { + // 1. Navigate to client + console.log('🌐 Navigating to http://localhost:5173...'); + await page.goto('http://localhost:5173', {waitUntil: 'networkidle', timeout: 15000}); + + const title = await page.textContent('h1'); + console.log(`✅ Loaded application: "${title?.trim()}"`); + + // Helper to verify a preset button + async function testPreset(buttonText, expectedContents) { + console.log(`\n👉 Clicking preset: "${buttonText}"...`); + const btn = page.locator(`button:has-text("${buttonText}")`); + await btn.click(); + + // Wait for assistant response and surface to render + await page.waitForTimeout(1000); + + const bodyText = await page.textContent('body'); + if ( + bodyText.includes('Error contacting server:') || + bodyText.includes('Validation failed') || + bodyText.includes('Catalog not found') + ) { + throw new Error(`Client reported error after clicking "${buttonText}":\n${bodyText}`); + } + + for (const expected of expectedContents) { + if (!bodyText.includes(expected)) { + throw new Error( + `Expected text "${expected}" not found in rendered DOM for preset "${buttonText}".`, + ); + } + console.log(` ✓ Found rendered text: "${expected}"`); + } + console.log(`✅ Preset "${buttonText}" passed!`); + } + + // 2. Test Presets + await testPreset('🔒 Verified Salary', [ + 'Verified Compensation', + 'Marcus Vance', + '$195,000', + '$38,000', + '2,800 RSUs', + ]); + await testPreset('💰 Payroll Summary', [ + 'Payroll & Compensation Summary', + 'TOTAL PAYROLL', + '$795,000', + 'Total Budget: $952,000', + ]); + await testPreset('👤 User Profile', ['Alice Smith', 'Lead Architect']); + await testPreset('👥 Team Roster', [ + 'Organization Directory', + 'Core Architecture', + 'Dr. Elena Vance', + 'Design Systems', + 'Aria Chen', + ]); + await testPreset('🎯 Team Goals', [ + 'Strategic Objectives: Core Protocol Engineering', + 'Deliver synchronous template expansion engine', + 'High', + ]); + await testPreset('💬 Feedback Board', [ + 'Feedback & Retrospective: Frontend & Protocols Guild', + 'Dr. Elena Vance', + 'Marcus Vance', + ]); + await testPreset('⭐ Competency Panel', [ + 'Competency: Alice Smith', + 'Lead Systems Architect', + '9 Yrs', + '142 Done', + ]); + + // 3. Test Inspector UI on Turn + console.log('\n👉 Testing Format & JSON Inspector Drawer...'); + const inspectBtn = page.locator('button:has-text("Inspect Format")').last(); + await inspectBtn.click(); + await page.waitForTimeout(500); + + // Verify Express DSL is visible + let inspectorContent = await page.textContent('body'); + if ( + !inspectorContent.includes('') && + !inspectorContent.includes('UserProfile') && + !inspectorContent.includes('EmployeeSalaryCard') + ) { + throw new Error(`Expected Express DSL content in inspector drawer:\n${inspectorContent}`); + } + console.log(' ✓ Raw Express DSL displayed in inspector drawer'); + + // Switch to Expanded JSON Tab + const jsonTabBtn = page.locator('button:has-text("Expanded A2UI JSON")'); + await jsonTabBtn.click(); + await page.waitForTimeout(500); + + inspectorContent = await page.textContent('body'); + if ( + !inspectorContent.includes('createSurface') || + !inspectorContent.includes('updateComponents') + ) { + throw new Error(`Expected expanded JSON messages in inspector drawer:\n${inspectorContent}`); + } + console.log(' ✓ Expanded A2UI JSON displayed in inspector drawer'); + console.log('✅ Inspector Drawer Test Passed!'); + + // 4. Test Template Library Screen + console.log('\n👉 Testing Template Library Studio...'); + const libraryTabBtn = page.locator('button:has-text("Template Library")'); + await libraryTabBtn.click(); + await page.waitForTimeout(1000); + + let libraryBody = await page.textContent('body'); + if ( + !libraryBody.includes('Registered Templates') || + (!libraryBody.includes('Inflated UI Preview') && + !libraryBody.includes('Inflated Output Preview')) + ) { + throw new Error(`Template Library studio failed to load:\n${libraryBody}`); + } + console.log(' ✓ Template Library screen mounted'); + + // Click EmployeeSalaryCard dynamic template in library list + console.log('\n👉 Testing Dynamic Template 3-Stage Studio...'); + const salaryCardBtn = page.locator('button:has-text("EmployeeSalaryCard")').first(); + await salaryCardBtn.click(); + await page.waitForTimeout(600); + + libraryBody = await page.textContent('body'); + if ( + !libraryBody.includes('Dynamic Server Resolver') || + !libraryBody.includes('Step 1: Simple LLM Input Interface') + ) { + throw new Error(`Dynamic template studio failed to mount:\n${libraryBody}`); + } + console.log(' ✓ Dynamic Template 3-Stage Studio mounted'); + + // Test dropdown selection to Marcus Vance + const empSelect = page.locator('select'); + await Promise.all([ + page.waitForResponse(resp => resp.url().includes('/resolve') && resp.status() === 200), + empSelect.selectOption('emp_102'), + ]); + await page.waitForTimeout(800); + + libraryBody = await page.textContent('body'); + if (!libraryBody.includes('Marcus Vance') || !libraryBody.includes('$195,000')) { + throw new Error(`Dynamic resolver execution for emp_102 failed:\n${libraryBody}`); + } + console.log(' ✓ Dynamic server resolver executed and updated preview for Marcus Vance'); + + // Test Stage 2: Static Blueprint Tab + const layoutTabBtn = page.locator('button:has-text("2. Static Blueprint")'); + await layoutTabBtn.click(); + await page.waitForTimeout(400); + + libraryBody = await page.textContent('body'); + if (!libraryBody.includes('salary_card.yaml') && !libraryBody.includes('baseSalary')) { + throw new Error(`Static Blueprint stage failed to display:\n${libraryBody}`); + } + console.log(' ✓ Static Blueprint stage displayed underlying salary_card.yaml layout'); + + // Test Stage 3: Resolved Output Tab + const resolvedTabBtn = page.locator('button:has-text("3. Resolved Output")'); + await resolvedTabBtn.click(); + await page.waitForTimeout(400); + + libraryBody = await page.textContent('body'); + if (!libraryBody.includes('$195,000') || !libraryBody.includes('$38,000')) { + throw new Error(`Resolved Output stage failed to display injected record:\n${libraryBody}`); + } + console.log(' ✓ Resolved Output stage displayed live injected database figures'); + console.log('✅ Dynamic Template 3-Stage Studio Passed!'); + + // Switch back to Interactive Chat + const chatTabBtn = page.locator('button:has-text("Interactive Chat")'); + await chatTabBtn.click(); + await page.waitForTimeout(500); + + // 5. Test Live LLM Request + console.log('\n👉 Testing Live Gemini LLM Generation...'); + const input = page.locator('input[type="text"]'); + await input.fill('Create a team goal list for Cloud Platform team with 2 goals'); + const sendBtn = page.locator('button:has-text("Send")'); + await sendBtn.click(); + + // Wait for LLM generation and client mounting + console.log(' Waiting for live Gemini inference & template expansion...'); + await page.waitForTimeout(6000); + + const liveBodyText = await page.textContent('body'); + if ( + liveBodyText.includes('Error contacting server:') || + liveBodyText.includes('Validation failed') || + liveBodyText.includes('Catalog not found') + ) { + throw new Error(`Live LLM request failed with error in client:\n${liveBodyText}`); + } + + if ( + !liveBodyText.includes('Cloud Platform') && + !liveBodyText.includes('Strategic Objectives') + ) { + throw new Error( + `Expected live generated goal card not found in rendered DOM:\n${liveBodyText}`, + ); + } + console.log(' ✓ Live LLM generated card rendered cleanly in DOM!'); + console.log('✅ Live LLM Request Passed!'); + + if (pageErrors.length > 0) { + throw new Error(`Encountered ${pageErrors.length} unhandled page errors during test run.`); + } + + console.log('\n🎉 ALL PRESETS, INSPECTOR, TEMPLATE LIBRARY, AND LIVE LLM TESTS PASSED! 🎉\n'); + } finally { + await browser.close(); + } +} + +runE2ETest().catch(err => { + console.error('\n❌ E2E TEST FAILED:', err); + process.exit(1); +}); diff --git a/samples/community/templates/uv.lock b/samples/community/templates/uv.lock new file mode 100644 index 0000000000..4c605565f3 --- /dev/null +++ b/samples/community/templates/uv.lock @@ -0,0 +1,2231 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.11' and python_full_version < '3.14'", + "python_full_version < '3.11'", +] + +[[package]] +name = "a2a-sdk" +version = "0.3.26" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "google-api-core" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "protobuf" }, + { name = "pydantic" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/a2a-sdk/a2a_sdk-0.3.26.tar.gz", hash = "sha256:44068e2d037afbb07ab899267439e9bc7eaa7ac2af94f1e8b239933c993ad52d" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/a2a-sdk/a2a_sdk-0.3.26-py3-none-any.whl", hash = "sha256:754e0573f6d33b225c1d8d51f640efa69cbbed7bdfb06ce9c3540ea9f58d4a91" }, +] + +[[package]] +name = "a2ui-agent-sdk" +source = { editable = "../../../agent_sdks/python/a2ui_agent" } +dependencies = [ + { name = "a2a-sdk" }, + { name = "a2ui-core" }, + { name = "antlr4-python3-runtime" }, + { name = "google-adk" }, + { name = "google-genai" }, + { name = "jsonschema" }, + { name = "pyyaml" }, +] + +[package.metadata] +requires-dist = [ + { name = "a2a-sdk", specifier = ">=0.3.0,<0.4.0" }, + { name = "a2ui-core", editable = "../../../agent_sdks/python/a2ui_core" }, + { name = "antlr4-python3-runtime", specifier = ">=4.13.0,<4.14.0" }, + { name = "google-adk", specifier = ">=1.28.1" }, + { name = "google-genai", specifier = ">=1.27.0" }, + { name = "jsonschema", specifier = ">=4.0.0" }, + { name = "pyyaml", specifier = ">=6.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "antlr4-tools", specifier = ">=0.2.1" }, + { name = "hatchling", specifier = ">=1.30.1" }, + { name = "types-jsonschema" }, + { name = "types-pyyaml" }, +] + +[[package]] +name = "a2ui-core" +source = { editable = "../../../agent_sdks/python/a2ui_core" } +dependencies = [ + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "referencing" }, +] + +[package.metadata] +requires-dist = [ + { name = "jsonschema", specifier = ">=4.26.0" }, + { name = "pydantic", specifier = ">=2.10.0" }, + { name = "referencing", specifier = ">=0.37.0" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "pyyaml", specifier = ">=6.0.3" }] + +[[package]] +name = "a2ui-templates-demo-server" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "a2ui-agent-sdk" }, + { name = "a2ui-core" }, + { name = "fastapi" }, + { name = "google-genai" }, + { name = "uvicorn" }, +] + +[package.metadata] +requires-dist = [ + { name = "a2ui-agent-sdk", editable = "../../../agent_sdks/python/a2ui_agent" }, + { name = "a2ui-core", editable = "../../../agent_sdks/python/a2ui_core" }, + { name = "fastapi", specifier = ">=0.115.0" }, + { name = "google-genai", specifier = ">=1.0.0" }, + { name = "uvicorn", specifier = ">=0.30.0" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.7.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohappyeyeballs/aiohappyeyeballs-2.7.1.tar.gz", hash = "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohappyeyeballs/aiohappyeyeballs-2.7.1-py3-none-any.whl", hash = "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472" }, +] + +[[package]] +name = "aiohttp" +version = "3.14.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "yarl" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3.tar.gz", hash = "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eb0495d778817619273c108784292be161a924b9f5ae5cbbc70a2caa6838250b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3c200cf9757edd785051dc699c7ecbec22110dbfcb3fefc7a9f9695eda8ea7a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd51ebf9d3a00c074df4ede271023f4d2dba289bcc740b88191872716014e3c5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:134ac5ddcf61c6fad984b9a5727d83492ada43d63471db20fb73042c13fca62f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:70c987b27534f9ae1a723f47ae921571d616da21d3208282bf4c52af5164ac43" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1b59533861b70a2185c8f4f350f791f39d64358ef6944ce71c5240c9ec0982c9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1c5281acc88b92396f88c7e1e2748f8466689df22b80170e4f51efa712fb47a8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48d67b87db6279c044760787eb01f6413032c2e6f3ba1cafaa492b1c8e578479" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f53bcd52f585e1ac3e590d61434eb61f9a88c38df041b4ea126d97144344a77b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0fdea2281997af69da84c77ffa6f5938a0285f21fb3887c249d67419ca865b3d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cda5fd5c95ad7a125a2e8464acc78b98b94c475a3780d6aa0aa157c93f470f4d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6debfa7312ff9d4c124dc71d72e9a0a4b9e0879e48ba6fcb42bef5c3300289e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f4e05329faa0ea1a404b37de4f034fd2c2defcca06a68dc6745e4e56c88e8a48" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a3a8296e7ab5c295f53f1041487cb088e1480775aafbf7fe545d93b770a0f96f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5373dc80ad1aa2fb9ad95c83f24eef418bbda3a61375f128e5b0192e4f3f9b32" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-win32.whl", hash = "sha256:a3e22975f905b89a55a488c2a08f2fdb2186175349e917d48985cc468a3d4c6e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdd0e2834dce1a26c1bbe26464861e16bbe217042cbff619247c11594472518c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp310-cp310-win_arm64.whl", hash = "sha256:eac645b09bcfdf73df7536331f0678c1086ea250981118ddb5199e17ccef72bb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-win32.whl", hash = "sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:39aded8c7f3b935b54aab1d8d73c70ec0ee2d3ec3b943e0e86611bc150ba47f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5bcb6ff3fdab1258a192679ff1a05d44f59626430aa05cd1a9d2447423599228" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:617105e2c3018ee38d0c8ce5ee3c84f621a6d8b9f723202aacaff28449ca91ee" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f631fe87a6f30df5fbe6d79640b25e4cffb38c31c7fb6f10871517b84b0f8c1a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a94dbaae5ae27bd849c93570669bff91e0510f33a80805738e3de72a7be0447b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8f2f1c4c032c7cedd7d8da6f54c97b70266c6570c3108d3fdffee7188bb70529" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ea05e1f97ceea523942d9b2a7d7c0359d781d683d6b043f5943a602b14da4787" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:543906c127fb1d929b95076db19b83fa2d46751006ff1e23b093aa5ac4d8db42" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0a5ff2dfbb9ce645fa5b8ef3e02c6c0b9cc3f6030ff863d0c51fffc50cb5541b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:041badb8f84396357c4d3ad26de6afd7a32b112f43d3c63045c0c8278cfd2043" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:530125ee1163c4219af35dc3aa1206e541e7b31b6efc1a3f93b70a136f65d427" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8653fd547c93a61aadc612007790f5555cdd18946fa48cf45e26d8ea4ea473d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:89176250f686cb9853c0fb7ead90e639e915b84a6f43eedc2a4e7ec21f1037f0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3a26434dafe408229ff3403458ca58de24fb51936504decac49ce6755f77e59d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d1558173930a5a8d3069cee5c92fc91c87c4dbcb099debbb3622053717145a19" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-win32.whl", hash = "sha256:16100ad3ab8d649fdfbee87602d9d2dcdca9df0b9eda8a1b5fdc0d41f96da559" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:33a2d7c28d33797a2e99923dffa63f83d908a19b6bf26cfe80fa790aa5e1a75a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:362a3fd481769cac1a824514bcd86fda51c65e8fe6e051099e008fddde6db17c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:2e9878ae68e4a5f1c0abe4dd497dbc3d51946f5837b56759e2a02e78fa90ef86" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-android_21_x86_64.whl", hash = "sha256:f3d2669fe7dec7fc359ecdb5984b29b50d85d5d00f8c1cb61de4f4a24ee42627" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:cc7cb243a68167172f48c1fd43cee91ec4b1d40cefd190edd43369d1a6bc9c82" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:78253b573e6ffab5028924fc98bc281aae05445969982a10864bc360dea2016c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7041d52c3a7fa20c9e8c182b534704abb19502c8bdcbde7ab23bfda6f642394f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ac74facc01463f138b0da5580329cfcc82818dea5656e83ddcd11268fc12ff80" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d6218d92e450824e9b4881f44e8c09f1853b490f9a64130801024a4793b1b3b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:11fb37ef075669eee52ab1928fbf6e1741fada40409fa309ebde9607a962aebf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55bdcc472aafe2de4a253045cc128007a64f1e0264fb675791e132ea5edaa3bd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c39846c3aad97a8530c89d7a3869a8f8e9e3762c6ac0504481e5c80948f7e807" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5895ef58c4620afe02fa16044f023dc4dafec08158f9d08874a46a7dbc0341b8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa9467a8113aa69d3d7c55a70ef0b7c636010a40993f3df9d9d0d73b3eb7ef24" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d2deec16eeedf55f2c7cf75b521ea3856a5177e123844f8fd0f114ce252cb5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dd54d0e8717de95939766febac482ac0474d8ac3b048115f9f2b1d23a16e7db4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:df82f3787c940c94986b34222d59c9e38843fba85139f36e85255a82ad5355a9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:42a67efc36300d052fb4508a53e8b6901b9284b599ae63945c377569c5fcc1e1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7a75aa63cbf9b21cfaf60dc2657e19df2c2867d91707d653fee171ffeedd1371" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e92eb8acc45eb6a9f4935071a77edf5b85cc6f8dfad5cd99e97653c26593cdde" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b014a6ed7cf912e787149fdc529166d3ceabac23f26efeea3158c9aba2354e7e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d4f72af88ac2474bb5bca640030320e3d38a0163a1d7533500e87be458eef71" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-win32.whl", hash = "sha256:5f08ec777f35ee70720233b8b9811d3bb5d728137f30ac91b7457709c3261ac0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:dff9461ec275f22135650d5ba4b4931a11f3958df7dfbb8db630000d4dee0883" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:ddcac3c6b382e81f1dd0499199d4136b877beb4cb5ef770bbbfba56c4b8f55d2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:49f7325beb0f85ef4aef5f48f490269575f83e6e2acad00a1d80b807eb027062" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-android_24_x86_64.whl", hash = "sha256:e3be98a7c30b8c25d573dafba7171d66dfb05ee6a9070fc46535464ff97700a6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:614c61d478b83953e261d02bb2df750f17227cd33ef8002945bf5aebbde21919" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:1caa7b0d05f3e3a36f87788c59e970a7ee1cefcfcbb924a9f138c4a6551c9cb7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:dfa68deb2a443bdaa3ea5297b0699c1464f08aef3812b486d1348eee61b07dc0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:e72ee89e28d907a18f46959b4eb0bb06701cc7f8cf4366e00029e2ccfaaf5924" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ad4c8b7488d745d2ca4838ebd8ae5ba9b56341d30b1da43640e4ce87f9f49646" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:db332af25642007330fca8be5c4d194caf2bea7a7fc84415aff3497af5dfee6b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25bd2708db6bdf6a6630dd37bdcdfcb47c4434d22ac69c64665b802910140b30" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:cef89a58e628c4efcac3275c2d68083f82426dcdc89c1492a6f654f9f7ea6ab9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c23ec8ee9d5ab2f5421f9c7fffce208435607af27fd46d4a44e031954352838f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e2667f0bbe7eb6c74eae5e9691441ad186e5845ca3cff63230fc09c4e7514f5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18cb43369747b2ae007bd2655fb8e63a099c2ff1d207962943636dac989b3147" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d77640cc618c1d99fc4f8589c0f24a730adfa54eb1e57ef7bf0c8dfb78da898c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:53e5179d8abb5710f8e83ba207c41c8d1261fcffd4616500e15ca2b7a33be10a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:cd817772b2fcf2b8c0905795318485f9ec16eae60b29feb7f4c77085311637f0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4e3ac92d90e92773b2362d506068e9a948192bd553e743c5b2429e28527c8661" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3f42e9b78301f11c8f861746175d8b9c1ccef713fcad9eab396e2f6db8ed4a22" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9d9edccfe496b476db5f398d97b865e9a6752bcf8aec4eef8390ce20fb64bb41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c5ec8fb1bcc31a8466f74aaf26c345d5c386fa4bd08a3f0eb9c7a4a3fe8b5bf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-win32.whl", hash = "sha256:38901a84da3ce22249f6e860bf8f90d141bcab7da090cc398f8bb58c0e44b7da" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:8b3b60de05f3dcb6f6a00f818bb2ec781cee4de0645f59ccaf99b1d1823b6100" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:1576145bdceeb92382d899751e12743a3a5b8e460a841e3e50543859e54864dc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:8800c996b01c2772a783e3e46f3e1abd5823029adca0df54231960de9bfefa5b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ebe8e504f058fe91223351cecd2d9d6946c9d241bb0250d898ffbdf584cc72b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:30402d03a7c0ff52bce290b57e564e9079fd9d0cb545c8aba73f86a103162d2e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fc7b5bfec6573f3ae844f457fdde5adeb713f8b8e4a81ad64fc207b49383716" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8a5fd34f7f7410d1730d5c2ba873cacb2eed3fede366feb268a70ba22581ed8f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:270d3dace9ca2f10f0da5d8ebe519b7a310fc6112ed916e32df5866df0888553" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3ae5b3a59436d089b5395d910121a390feed4d00578eb95a0fd1a329fe963100" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2498f0fe69ead802f9675beca44a7c21c62fdaa4ec5145ea1c3ad6edbee29f85" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a0dc483c00da8b673abbb367eb6f8d8f4bcec30eb58529ea13cb42e7fd2dfa33" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c7d3a97c678d34fc5b59da671ee9cd630096ddc643e7b5a30d54a2a6f3574d3f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f8fb78a83c9e5f741ca3a68cfb455c1f5bb83b4e7249a3848b3cd78d0a8563b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:74ab5b6a9fb13e873e5a90946588baecaf488745e1db1a4a5c433f971f035098" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd52f811e65f6fb634b1047159657c98f52b407f8efec907bcfc09da9a4c0a25" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:f0f177d1b195b9e06376cfd7d308d8a1b920909a609d03ac82a8c73bbb16d3b9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:498c6c623134f8e09a3c4e60bcd607a0b4590dd7dbf08dd40851b27cbb520ccb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-win32.whl", hash = "sha256:b304db572b4368edd8dda8a2274f73156fe15558fca4a917cb8a09fc47af5963" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b20032766aedf6261c7a566585a40867d092ac03a0d81592d5370ef9b054f99b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiohttp/aiohttp-3.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:2e1161602f45a54de2ce0905243a95f58cb42dcd378402f3697f5e0b21e9d2e7" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiosignal/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiosignal/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e" }, +] + +[[package]] +name = "aiosqlite" +version = "0.22.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiosqlite/aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/aiosqlite/aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.5" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/annotated-doc/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/annotated-doc/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101" }, +] + +[[package]] +name = "annotated-types" +version = "0.8.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/annotated-types/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/annotated-types/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0" }, +] + +[[package]] +name = "antlr4-python3-runtime" +version = "4.13.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/antlr4-python3-runtime/antlr4_python3_runtime-4.13.2.tar.gz", hash = "sha256:909b647e1d2fc2b70180ac586df3933e38919c85f98ccc656a96cd3f25ef3916" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/antlr4-python3-runtime/antlr4_python3_runtime-4.13.2-py3-none-any.whl", hash = "sha256:fe3835eb8d33daece0e799090eda89719dbccee7aa39ef94eed3818cafa5a7e8" }, +] + +[[package]] +name = "anyio" +version = "4.14.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/anyio/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/anyio/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494" }, +] + +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/async-timeout/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/async-timeout/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/attrs/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/attrs/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309" }, +] + +[[package]] +name = "authlib" +version = "1.7.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "cryptography" }, + { name = "joserfc" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/authlib/authlib-1.7.2.tar.gz", hash = "sha256:2cea25fefcd4e7173bdf1372c0afc265c8034b23a8cd5dcb6a9164b826c64231" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/authlib/authlib-1.7.2-py2.py3-none-any.whl", hash = "sha256:3e1faedc9d87e7d56a164eca3ccb6ace0d61b94abe83e92242f8dc8bba9b4a9f" }, +] + +[[package]] +name = "certifi" +version = "2026.7.22" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/certifi/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/certifi/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775" }, +] + +[[package]] +name = "cffi" +version = "2.1.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-win32.whl", hash = "sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-win32.whl", hash = "sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-win32.whl", hash = "sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-win32.whl", hash = "sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-win_amd64.whl", hash = "sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315-win_arm64.whl", hash = "sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cffi/cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.5.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1.tar.gz", hash = "sha256:6117b84ea48435e5356dc737f5121485c30920ba43375fa7b434fd753df0eac3" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1ee1e296209fdce05b81b663250eefa02213a2da7b41bf26f7829b8ba3545aa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9fbdce1e47394b09bc9f26ab117dfc8d6491977a11d86f592bb42c779db2fda" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:00668ebb0609751758682eb0b5857e7c35b9f00e84dfdef062e103244ec94d45" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba2f37ee79e6338845261a3c5b1784e5d1acdff2c0785b284f1b633033d136ab" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ce854f5f478050ade5a238731c4ca985a7d3b3cb53ff600a9b5c3b689b5f0a7a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96eefc178f8636b9c760c5829345307fd81cfae9ab1e80997dbddeb0f54ee9a3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:366ec70f5547c640d3ce1985722490f23faf4eb5216a7eeba78277490e78dacb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:950f23cb393f85543777b0433f082cddd25b51ab398eac7971146495679efe5f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1dcc36dcb96abc02236e182d17e0f71430152a6c2c7447421da2d2dc144edea" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:07ffd07412fc5d5e84cd8952acf9ff7e4ed7a708e69d1bada19d8ba91711353f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f5542f9b941279d82d41eb0aa9f98eba36fe4df5c7086c651df7944935b37182" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a545775cfe815855ea32d7c27731d79da358ef2055b4a25830231b1622dd18aa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:494b70049a4d69aec6e8137c13af4cf8db8c9f9820a1392ac293b0dd2987a818" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-win32.whl", hash = "sha256:94fbf1c0c6cc0d3d5e50f9a9313a8cdca90dd696d34b381cd1704f8c9e939f20" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:be47f99644b208bff7766314013f9acf57b056b04191d570d68ad14022cf5b1d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp310-cp310-win_arm64.whl", hash = "sha256:a6d095662e73e74f0a49988e0593373e243e3a52e27bfeea0a859e88acf4a0f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eda059b6bc8bc0812d626fd91a7ce01bf583df0a61296eff390fd94141a34e30" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa2bb0b37202dca27175591f761108b5d34096ade1191ffe4808bdf6b1571488" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b2b1b3fa5670c127b246df1d0c059defd41f689a868a3b9d79df9b1cac42d22" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6e5e4d73d588ca5ed09df1b7dcd1b203d1df3c542e3f50d126c947d432b10731" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b54e7e13267d49ffbfe68e25b3cbd774dab38fa37238f71265e91b36146eb21c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7b742bf31c88566b4bb6335a7f393bb322e580b6bb98df7bd0c25e6e3519ce8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ba32c4d2abf1d2fe7cf27d280f4cca5664233b0f885549c7761719eb977f486" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0722590aabf9dc6a6c0343d523c05458fa2b5047dbe6302fd526bb570600753f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:aa1099b956fb795e686d073568f6dc002a0bb89765ea6d5b055dd7d9bf1b116c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd6c173f04743d483881bffa1478d5a4624475b8cd1d2194956a75548e191c18" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f298e218441525d3794428b4c8b8fb8662c6d3ea79925d4807ee6b9a96a3bca5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6e2912d4babbc65196ac13c2f53468dc57fb8b9c25ef913e8c59ddf7c6dc0e1b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3d27167433c0d5f18dc850f07d0b3816221984fecdc405d6c157a6f0b8f8e9e6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-win32.whl", hash = "sha256:ac00177c4831ffa650f8609e4bdddd5fe09c03b1c0c47acece7e6ea20421598b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:f9b1e28d0e8dbfa858abdba91d6b547beaf2df1a59bec6da6faae7b96a4991a9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:ae31a1a1db2ee6cc2942fccaf695c934bc7f3db9f2133a3fef1f367cf1a4ab10" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1d1c7a53a6c2103925cdd6d7229f8c567379f211c869793df679f2e9f738c369" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e6621fb2a4988d6e53eedc455e5903e2679f3967b8acb3d639f1b63c14a2e893" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c0c10730342b0c9b35dd1d619beb8214e520bd96a1f870f452680b238aab3e0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9f8405c2c758532c74fed975dbee57be1f31a6e865c031870c79a6ed3212ada" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:96fef3e886d6a9874b14f27fc193fbdc69d5d8035783d86aa4e1cea594e695f9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5d8531a6569d025f68e2321e7638fb7978f23db58e5f69f56913837aae03816e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:aae2ee51122d3ae968a3837d97dc24a0aeebb0dea23694422cd172bd30017cd6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7235dc28fc6dd9d832ac7c7bce95367dedb85929f17368a0c2bee1e080b9acbf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4abdc5f9ad448c1ecbfae2974b820535d6bc6e7eef63babbab3d81cf46968c71" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba501e667c17d8411f98e67a022d9604ef179aff0e459b7e292c796837c13573" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-win32.whl", hash = "sha256:cfa1c0cc3a8f9f53f1243a5a99ac36fd003880199383b37672e86ddda9cb07e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:3617ac3cfd8b9888f145ad89dd6e692285834b0201c6074a5eeaad3fd4d668c2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:88e85ab89cb822c1e635f51d6d32e488f94e002e70e2f492bdb8b945543f345a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:4f298bdadb8f0b9e5672877f647d1be9373ef5320c9e2f049795e26cad28b6a9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:88ca277405c2d3b71c4e1c2ee0e7966e807bcba86a69d11e19ba199d18ae4491" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9362dd90aa7dab48c0054a21187791ccf05473f7dba5d92b8033ae62164675e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:977cdbd483a9cff38179bea4fd754289a6f2195c7abd414aba85410b3e66cc5e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d59b75732e9b6f27388e10c14b0259cc5f2e48c78627d185e6a177b58ad3cffe" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0d929fc574b4d6fd9e7c0f5c2ede8716a41911923aa7fa5fce38e0818aa4a1ac" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:394fea06235c8543390050ed5f529187074b029fb027213f6c46ac11ab5d950e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa48b1b63d639f9483e0633e092f5851e2348c352f1f9bb6c8182f87884ef876" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c71fb0d56c920c269cd3e2e3fe7c610e3f1fdb21a6ce60efa6430ff63676cea6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:485a0d363cafefcd2538a73c7c838daa2035f09b2c9f9b5e3133f80c6aeb84c2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0ea61a470e070686aa30892fed79e297d2c8d0ab46b8bcdf027d38c51da591" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:90b7481fb62fbe172c558bc6fd1c4c98d82004a54a7551f20e11ac9bf0b8708c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:35fe081843b35aad20ffeccec3eeffbe637b15d14f3fb22cc1b59cd8ec17e93c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd0350afdc3aabd5576f60ea109228bd5538139713c7b094c5cd27c73a98bc6f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:9d9a0dc7cbe9bec24c3f767c9122c41fe5a1bc43f47cd099d00d393e09769de4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-win32.whl", hash = "sha256:d63600d620ad0064c3a748b950ac5ea38a80190e5498532efefa4b7b3f1da1f3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:aea996a6aba25260827c9ea511d1addfde2da9eb686ac961838509086188b7e6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:fd0a274c0e5f9a21565cd9d3dd749b61f96b7aa1e20a93aa1ba4029518f2e5c0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:774d157f112367ff4abd29019f38f023c24e00e56edc7829c20e358a5a913ad8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:26422d45fd13551cf564c58932f7d72b4f58b93b0fcf18c35ba6be12b46bb102" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:09a7bba9f739468c8e78c36a75c33768e53cb1959fc638f510454c14683f00d5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4c9548dc78002099910abaebc0a72ac58b7d30931869e0351c09b507dff4ece3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c428c6c31eb5f4277d7f8eccaf767fbd548ddd5ce3c8b4f4cbbfab3d96b5904c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f06b7eae9dbe77fe1d644ca244dad508de8d302870a43f3c559b521270938a0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b7430cf5728e68f6c462254009a6ef4086e1bea43cf2f57aa9c55fb4f50ff96" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab743e9bc90c1f73552ec33e10e3331315acd2c397b36065b591b0181de533cc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6f7deae3feb4edfa2efaf7c574fe88cbf055038a6abdb40188e4fff66d5699f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15f024313246a4ed976c60f440bb8d257815513a681d212ff74fd46f7d715a90" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:823f82903d189af463d7df250ef1f7f696f3cee08cc8d91deb565e8d425f6506" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:01e93745f7f219b703b60ba7afead36cfc4242782be5af484673fc500df12da5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:329fc3ccb63ad22d867d84c2adea759a64079a37ba4a343433b02c7a2816871e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:bb57753e36e4855b8ca375069482250a6246372331a3e4f3407eaebb007443f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fce8cbd4997efeb450bd298b54f755dcdff18d496f7a5ddbb4867c6d7c88fdc3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6c9cdde8becb25a7fde49924511aa2644d6f8081cc8df8e9452724303348d8e3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9ac4444d8d4fd4c4bd08bf451ed3167aa9e7ec6cdb41b648794f1d1103652e36" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:f03ac127268b43ef4fe9e6ab6794a6794b49485a0cc0c1db79876d2f33f75bc7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-win32.whl", hash = "sha256:1f5883d77fd409a261abb5dc8ccbe335720d798b1de4abb3b1d47ccbbc76b53b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:c658c50ac0c98cd755a2dd50b7977d3bca7df401dcc47fbdfa87db53ef7d4e8b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:4bea7f8ebe90bbd7f0e4a2de42ca6924ba23e3e76418c408ff82f1d46fabd687" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:fbc597639158fd7c14d55e808718848319540f51b0e6746e3eefa59723a4a348" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e71c909f353863b2b89c83de2ebed71ea6d0df8a6ef65a128193c5e650766bef" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7ac76cf9afd34929d76eb7fcb63be476a4853d8a96f0dcf2d0db68a0cbdf9885" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a3a370082ce34d0612f421e15fe011c53bb1feff21a26d06ad4fb244dab5a375" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:256dd4d85d9e4dc595e2bc983c980e73f62ddeb3165c58b4c3dfe78c5c8548c1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58d4aa13a59c969dbfdf9e6a9560e242cbfd9e8a8f50c2747714df1a423adf65" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0c6dfb5ca6723eeed15aa8e564a014d69fcb8812f94eef11fe3631e0508199f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c010f5581d9c612804cc59fcf7b524b707fbcb72828551237ab545bb5c7034af" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:52ec005752a56ae79547a05c0139ca2501a0c866390b6115008456b9f0e7cde1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2bced4061f000f7187254a02ad3433ae17eaf991747ceea2f478422590a5bba9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9eea3ab2597a5e65fe65296e2d6a84570845a6b55532d90333d740d48bbc850a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:496846868fea80e479324862fa877f02411f2fd0f83b79ccee2607aa68b2a032" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:85d5855daafc240cc045c026d7a15fd198a09b0fc8ff6f5ecbb5297b509cb11e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-win32.whl", hash = "sha256:58d3e12c88e0950bca850ae1f7c256055c097639c2edb9eb123af9807d8b15e4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:acaf604462bf330b0d07e7a07c1d6e4adac79e5fb13e9c5140590542cafacc00" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:fdb8a068947befafba9952162645dc2fecaeb400e64584829ed5e9b2fbe21a7f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:9085f87b0e38a2b92b8923059b4e8789fe40d9279712d15dcc670048d77079af" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2679de311c7946dde5d3b6f44941844133ff5c7cb86099c0061ab1e8901c20a8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:baf3775a2635e5a11fbd5e4e64ee69c7e86875d224a5c72aca4c141064589a90" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ac8c94b6539074e0f40899301273ac8402b9b3e01c7b7ba269ff30340aaaf20" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fe532b3c966d1fb794e0698e4589d0444017ae77fc0b31edea13c0e35bcc449" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5c84bec0ab5ae0c64bfe73a7d2adcb5ce73b467523fc27fd6a28ab2aa6cbe35a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:854066be00447fa8de2ccbbe893e2ffc4b123ef16d897af794c1e18bd4a714b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:21b82d8082f6f5e7f456ef0bd16323d08de1266efbfeb476e64b2a91d1471a4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:838648accb3a7fd9803fd45c87bce8509648eb0c11bc34e216141300977244f2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:195ce897c6153c0700078142cf8efe3e6454ca4cf4357499e4078dfd83396626" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:978eab16f55b4ab2c2a745be9a0a840bf8f09a7f227d9c76eb30214d078865a5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:cc0329df4caaceb950d2f580b5ac716a377f7059624a0bafaeaf8a218c6ed774" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:687c9ca3035544b113bea2055e180af96fb63c0c476e22a9180f51925186e7b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-win32.whl", hash = "sha256:706bfd38730a5ac7a365793269a00f4e988178cec121391f4248d84ad8c972e9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:92caef967d287a407085d61176fce4012b1dd62daed4eb6d5ceb26d3d2538712" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:5fc45d653ea8c9a20479167e11d4a0f8cb2fa3470737ab6f9c827532313187b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:59171c6e45bf07d0d5cab3b0bf81d945035530f6873398b3b531c31184d46663" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9dbdd9205662134957cf0c324f639bdc5031c0ca056e2369e238db75187c0f11" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4b018dc5a0eee4676e38fe84a47a427816c590b93b55d9025274ec4d6ffc2dc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced3fdd71aaa83ce593746c2edb42b7a59cb4c19c8b5c407781c72e493aae55a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:19a3dd5aa73cef1c99687c4fc57db016a9c17104ae1185da88ba566a5d3bebe4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc5d36d96478aa9c60654bd932525bf32964c62a7281eafdf16d85003a8d6004" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:04368edf83514385ffc3e1cfd4546e595f4f1272dd23ba437a93a9cc3741d47b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:9b5db6052055d34d41230fb78d7c439c23dc536a9896f6cb039e8dd92cfc1263" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:252d099029bcbea642f2a06c4ed5046bdf8b5a8150b64afa5e027e88b106e5ee" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:6199d5606e2bbf2b096cf64d03f8b6790c91081d5ac866b8e7bb6422738cc60c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:77efcff2b23071c349402ac1066667a3d011f62398d81408c9b88ad991747c9e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:a5cbd90ecf0fc62e64726917ad083b73001f0563657a87ec3c0b504e277dc90d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:4d26f14f041e83dd8edfd61f4cd4fa7285d31798b5bf1f28e70c367ba6c41d61" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-win32.whl", hash = "sha256:ac13b004224fb341e1e25a1ed5e19d32f57cdb2a403e01f003b46f051a550f6f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:35aea775dc2bd5f54cd84a1cd2696cc3207c479cb9cf0bd346f0d343e4300ddb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp315-cp315t-win_arm64.whl", hash = "sha256:fb78f6e7fcd8ad785d28cd577168bc1aaee827b25bb8755638f694794ea98f0a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:343fb4f2821043bd87095f7b08a1a181febc8e36ac64212143bbfd0a0e1bc235" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ae4a097991662cd4fff0ddc74e0fe7874f82e00042fa0ea00855645ed0c79598" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b599739b93b2cbeded49645ae3c8d1405c29ddfbceac1545c87a3f9580a9e96" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b39b69b347e5e47a3b5b8cfc005c68c1ba347474e3960236c4944a8ecd174962" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a2028475ba855475b8b4d3cfeb4994269c967aea8b9892dfba907f4263a863a3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:36047af20e17097c3bb9476c2b7655f2f7aa51322c0ba58c07695bedf755a950" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c4fb141a727957c93edfe5c32a26ceb6b5f6461d67146e2d39f51e16170bea8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:2f293479cce755c75f1697e87c409b7ae4c555c7dfecb6e988ad13abba943031" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:3588e376b3ea2eea84976f67273d679f229e24c66dce7b82ae45aef04ff6e072" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e199fb99720074809a7720f1c0b4d919eea8b87e88713e0f8f602f7bef543d9d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-win32.whl", hash = "sha256:dd732602a7009217f658d5863d12d79d373a4de0eebc111094bcdd3bb8e0a6cc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-win_amd64.whl", hash = "sha256:70055ff39b97c99e7ae40ea3e393fb62aa2e44dbd9b29f8d14f42fb0025c3959" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-cp37-abi3-win_arm64.whl", hash = "sha256:87e4f41d375c0b9be2fb5251aee4b8a689169e134535aed81bf085c3b647451e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/charset-normalizer/charset_normalizer-3.5.1-py3-none-any.whl", hash = "sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6" }, +] + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/click/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/click/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/colorama/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/colorama/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" }, +] + +[[package]] +name = "cryptography" +version = "50.0.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5e34edd123674534acd70147f0ca331eaa2c74e6325fb2028c886aa26ba0b68c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8eb5e1172eb569ea8a872796576e6a67c276351728b6455d5beb01242b027c6a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:910d11e1a385c654bf738bf3e6b8e6ed5de0f5610fcae2be9e5b398d8081d20e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:62598a8a57f815db4c6259a4e97d857dab56697e7de8e8ab02352ab74da1995d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:07479a1cb08219ab719147e742e76090c9c773321959bb94946fffdd397a6437" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/cryptography/cryptography-50.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9" }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/distro/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/distro/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/exceptiongroup/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/exceptiongroup/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598" }, +] + +[[package]] +name = "fastapi" +version = "0.141.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "annotated-doc" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/fastapi/fastapi-0.141.1.tar.gz", hash = "sha256:e8822fc40db1e1858054d7a949a888695bc9bdce70139178e33bd2871a453ca1" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/fastapi/fastapi-0.141.1-py3-none-any.whl", hash = "sha256:bfb91aa2d334c61cb35ba9a116fc123b3d3df31640b801cf57a7a78ec3f603b3" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/frozenlist/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d" }, +] + +[[package]] +name = "google-adk" +version = "2.7.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "aiohttp" }, + { name = "aiosqlite" }, + { name = "authlib" }, + { name = "click" }, + { name = "fastapi" }, + { name = "google-auth", extra = ["pyopenssl"] }, + { name = "google-genai" }, + { name = "graphviz" }, + { name = "httpx" }, + { name = "jsonschema" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-sdk" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "python-multipart" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "starlette" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "tzlocal" }, + { name = "uvicorn" }, + { name = "watchdog" }, + { name = "websockets" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/google-adk/google_adk-2.7.1.tar.gz", hash = "sha256:0485bfba1a04960a3784eb67531491475be1a3f8acefcc5c880a906857ecb3e2" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/google-adk/google_adk-2.7.1-py3-none-any.whl", hash = "sha256:cd21e37c9846a80086fd880924aa5548e625ef85178122b40cda81ef5316129f" }, +] + +[[package]] +name = "google-api-core" +version = "2.35.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "google-auth" }, + { name = "googleapis-common-protos" }, + { name = "proto-plus" }, + { name = "protobuf" }, + { name = "requests" }, +] +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/google-api-core/google_api_core-2.35.0-py3-none-any.whl", hash = "sha256:88ce7a11146e1ddd331f7d2fd379787eb7e9015c34c6ed681e4f5fb8af3615af" }, +] + +[[package]] +name = "google-auth" +version = "2.57.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "cryptography" }, + { name = "pyasn1-modules" }, +] +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/google-auth/google_auth-2.57.0-py3-none-any.whl", hash = "sha256:180dafe015cfb62193bea26b677500fab5b9fd51a1e825ebf3ad9b182047ae59" }, +] + +[package.optional-dependencies] +pyopenssl = [ + { name = "cryptography" }, +] +requests = [ + { name = "requests" }, +] + +[[package]] +name = "google-genai" +version = "2.19.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "google-auth", extra = ["requests"] }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "sniffio" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "websockets" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/google-genai/google_genai-2.19.0.tar.gz", hash = "sha256:d8f4126643793a7de230c396bcd142d21c948c8bb57507580e152549a7a41d9d" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/google-genai/google_genai-2.19.0-py3-none-any.whl", hash = "sha256:36e0326dd886b52ef765be4c46042732b46b21f637abbe060e3db7c3de23974c" }, +] + +[[package]] +name = "googleapis-common-protos" +version = "1.75.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/googleapis-common-protos/googleapis_common_protos-1.75.1.tar.gz", hash = "sha256:d3042c6c5a2d4e67113104d6b6818b59b6bd92a197f2a91508e801fe815cf071" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/googleapis-common-protos/googleapis_common_protos-1.75.1-py3-none-any.whl", hash = "sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79" }, +] + +[[package]] +name = "graphviz" +version = "0.21" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/graphviz/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/graphviz/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/h11/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/h11/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/httpcore/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/httpcore/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/httpx/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/httpx/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/httpx-sse/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/httpx-sse/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc" }, +] + +[[package]] +name = "idna" +version = "3.19" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/idna/idna-3.19.tar.gz", hash = "sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/idna/idna-3.19-py3-none-any.whl", hash = "sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4" }, +] + +[[package]] +name = "joserfc" +version = "1.7.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/joserfc/joserfc-1.7.4.tar.gz", hash = "sha256:b3bc561672ae541b17a9237053b48a03dacddd92d68047b3ecdfb4b5714a88ed" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/joserfc/joserfc-1.7.4-py3-none-any.whl", hash = "sha256:32d46c2cd5e3203c13e87a6c61333cab310b1ba80cd54b4c4f386a848a122463" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" }, marker = "python_full_version < '3.11'" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/jsonschema/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/jsonschema/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/jsonschema-specifications/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/jsonschema-specifications/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/multidict/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56" }, +] + +[[package]] +name = "opentelemetry-api" +version = "1.42.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/opentelemetry-api/opentelemetry_api-1.42.1.tar.gz", hash = "sha256:56c63bea9f77b62856be8c47600474acad853b2924b99b1687c4cb6297166716" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/opentelemetry-api/opentelemetry_api-1.42.1-py3-none-any.whl", hash = "sha256:51a69edacadbc03a8950ace1c4c21099cacc538820ac2c9e36277e78cebba714" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.42.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/opentelemetry-sdk/opentelemetry_sdk-1.42.1.tar.gz", hash = "sha256:8c834e8f8c9ba4171d4ec843d0cb8a67e4c7394d3f9e9297e582cbd9456ddbf7" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/opentelemetry-sdk/opentelemetry_sdk-1.42.1-py3-none-any.whl", hash = "sha256:083cd4bbfaa5aa7b5a9e552430d9951219967cfb27aa61feb13a77aba1fc839d" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.63b1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/opentelemetry-semantic-conventions/opentelemetry_semantic_conventions-0.63b1.tar.gz", hash = "sha256:3daf963611334b365e98a57438183eb012d3bfb40b2d931a9af613476b8701a9" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/opentelemetry-semantic-conventions/opentelemetry_semantic_conventions-0.63b1-py3-none-any.whl", hash = "sha256:dfe5ef4dee82586b746f522b818ceb298d00b3d59f660042bd79404bff8d0682" }, +] + +[[package]] +name = "packaging" +version = "26.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/packaging/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/packaging/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c" }, +] + +[[package]] +name = "propcache" +version = "0.5.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-win32.whl", hash = "sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/propcache/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe" }, +] + +[[package]] +name = "proto-plus" +version = "1.28.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/proto-plus/proto_plus-1.28.3.tar.gz", hash = "sha256:5f91b30dafa6bb38d432c5557a6ee1d35ffd40b4b1e0e3ca27260448560b91d9" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/proto-plus/proto_plus-1.28.3-py3-none-any.whl", hash = "sha256:dc76880b8ee951cca002098574376cf71e055f9f16d9ba6570fb8a06f726d281" }, +] + +[[package]] +name = "protobuf" +version = "7.36.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0.tar.gz", hash = "sha256:e8e09cb0d794c6687926fa558a8a6e72aa10edb997d5ca61da0765f12a3e00ea" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:9103532dffd80c6fab7e50c65a31007680a06eb57537d437bb1b35812c138a37" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:bf94a5917c71058262de683669bc0a797a7669d3de71f0b36d058e3194f47b44" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:3297e60abdff301e5f74393d87f6cc59dacab5f024a89548a6e8de1d26576b16" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:70f5ec8eb0da81a44360c0dc0beac99a0d78071d21956a7076bae8bd2051841b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-cp310-abi3-win32.whl", hash = "sha256:7326fd717bdc419162a735938d89d4032332bcc3408804012b24ff3a37086071" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-cp310-abi3-win_amd64.whl", hash = "sha256:1781cc1de61249b750848029bca452c0a8b7e990080316b9bbc2518b2117b488" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/protobuf/protobuf-7.36.0-py3-none-any.whl", hash = "sha256:53374d53fc29a67f7dbbf0ade47d7526a0f0137bf0f9c90e48d8a60790ef748c" }, +] + +[[package]] +name = "pyasn1" +version = "0.6.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyasn1/pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyasn1/pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyasn1-modules/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyasn1-modules/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pycparser/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pycparser/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/python-dotenv/python_dotenv-1.2.3.tar.gz", hash = "sha256:a20a594dabeaa385725aa239d5244871c143ecb356add8a20fcf23773a6c3a35" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/python-dotenv/python_dotenv-1.2.3-py3-none-any.whl", hash = "sha256:904552145e8bfed22162c09dab1c2b9b54fefa7b23ba780f4f26ca0316b0f0d9" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.32" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/python-multipart/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/python-multipart/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" }, marker = "python_full_version < '3.11'" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" }, marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/referencing/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/referencing/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/requests/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/requests/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e" }, +] + +[[package]] +name = "rpds-py" +version = "2026.6.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.11' and python_full_version < '3.14'", +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/rpds-py/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/sniffio/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/sniffio/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2" }, +] + +[[package]] +name = "starlette" +version = "1.6.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/starlette/starlette-1.6.0.tar.gz", hash = "sha256:d4e3ac5e546444960c710297a3c9fc3f7ebae1b7e963f3d36173b49da535be9b" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/starlette/starlette-1.6.0-py3-none-any.whl", hash = "sha256:a86dd39d14bb45f85a3d18525215a9ef0cfd1f192ac793220e72598c90335f0c" }, +] + +[[package]] +name = "tenacity" +version = "9.1.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/tenacity/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/tenacity/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/typing-extensions/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/typing-extensions/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/typing-inspection/typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/typing-inspection/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147" }, +] + +[[package]] +name = "tzdata" +version = "2026.3" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/tzdata/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/tzdata/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931" }, +] + +[[package]] +name = "tzlocal" +version = "5.4.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/tzlocal/tzlocal-5.4.4.tar.gz", hash = "sha256:8dbb8660838688a7b6ba4fed31d18dedf842afb4d47ca050d6d891c2c15f3be4" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/tzlocal/tzlocal-5.4.4-py3-none-any.whl", hash = "sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/urllib3/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/urllib3/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" }, +] + +[[package]] +name = "uvicorn" +version = "0.52.4" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/uvicorn/uvicorn-0.52.4.tar.gz", hash = "sha256:73acfee47a0b133c5de13d219492d62d8a31e935f4fe6e41a232451a15379f86" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/uvicorn/uvicorn-0.52.4-py3-none-any.whl", hash = "sha256:f86e41a149d7d05a9969337e3946a9c171c06a5d42680896daaba624aeac8da1" }, +] + +[[package]] +name = "watchdog" +version = "6.0.0" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/watchdog/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f" }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/websockets/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f" }, +] + +[[package]] +name = "yarl" +version = "1.24.5" +source = { registry = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5.tar.gz", hash = "sha256:e81b83143bee16329c23db3c1b2d82b29892fcbcb849186d2f6e98a5abe9a57f" } +wheels = [ + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88f50c94e21a0a7f14042c015b0eba1881af78562e7bf007e0033e624da59750" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6efbccc3d7f75d5b03105172a8dc86d82ba4da86817952529dd93185f4a88be2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0ebfaffe1a16cb72141c8e09f18cc76856dbe58639f393a4f2b26e474b96b871" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ac73abdc7ab75610f95a8fd994c6457e87752b02a63987e188f937a1fc180f0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d97a951a81039050e45f04e96689b58b8243fa5e62aa14fe67cb6075300885e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fe7b7bb170daccbba19ad33012d2b15f1e7942296fd4d45fc1b79013da8cc0f2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:89a1bbb58e0e3f7a283653d854b1e95d65e5cfd4af224dac5f02629ec1a3e621" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fa5e51397466ea7e98de493fa2ff1b8193cfef8a7b0f9b4842f92d342df0dba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4103b77b8a8225e413107d2349b65eb3c1c52627b5cc5c3c4c1c6a798b218950" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9f3e9c8a9ecffa57bef8fb4fa19e5fa4d2d8307cf6bac5b1fca5e5860f4ba00" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0ebc836c47a6477e182169c6a476fc691d12b518894bf7dd2572f0d59f1c7ed" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:96d30286dd02679e32a39aa8f0b7498fc847fcda46cfc09df5513e82ce252440" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:fd8c81f346b58f45818d09ea11db69a8d5fd34a224b79871f6d44f12cd7977b1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5c55256dee8f4b27bfbf636c8363383c7c8db7890c7cba5217d7bd5f5f21dab6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f4d8cf085a4c6a40fb97ea0f46938a8df43c85d31f9d45e2a8867ea9293790d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-win_amd64.whl", hash = "sha256:240cbec09667c1fed4c6cd0060b9ec57332427d7441289a2ed8875dc9fb2b224" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp310-cp310-win_arm64.whl", hash = "sha256:8a6987eaad834cb32dd57d9d582225f0054a5d1af706ccfbbdba735af4927e13" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2c1fe720934a16ea8e7146175cba2126f87f54912c8c5435e7f7c7a51ef808d3" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c687ed078e145f5fd53a14854beff320e1d2ab76df03e2009c98f39a0f68f39a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:709f1efed56c4a145793c046cd4939f9959bcd818979a787b77d8e09c57a0840" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874019bd513008b009f58657134e5d0c5e030b3559bd0553976837adf52fe966" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a4582acf7ef76482f6f511ebaf1946dae7f2e85ec4728b81a678c01df63bd723" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2cabe6546e41dabe439999a23fcb5246e0c3b595b4315b96ef755252be90caeb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:17f57620f5475b3c69109376cc87e42a7af5db13c9398e4292772a706ff10780" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:570fec8fbd22b032733625f03f10b7ff023bc399213db15e72a7acaef28c2f4e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5fede79c6f73ff2c3ef822864cb1ada23196e62756df53bc6231d351a49516a2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ccf9aca873b767977c73df497a85dbedee4ee086ae9ae49dc461333b9b79f58" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ad5d8201d310b031e6cd839d9bac2d4e5a01533ce5d3d5b50b7de1ef3af1de61" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:841f0852f48fefea3b12c9dfec00704dfa3aef5215d0e3ce564bb3d7cd8d57c6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:9baafc71b04f8f4bb0703b21d6fc9f0c30b346c636a532ff16ec8491a5ea4b1f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d897129df1a22b12aeed2c2c98df0785a2e8e6e0bde87b389491d0025c187077" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dd625535328fd9882374356269227670189adfcc6a2d90284f323c05862eecbd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-win_amd64.whl", hash = "sha256:f4239bbec5a3577ddb49e4b50aeb32d8e5792098262ae2f63723f916a29b1a25" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp311-cp311-win_arm64.whl", hash = "sha256:3ac6aff147deb9c09461b2d4bbdf6256831198f5d8a23f5d37138213090b6d8a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d693396e5aea78db03decd60aec9ece16c9b40ba00a587f089615ff4e718a81d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3363fcc96e665878946ad7a106b9a13eac0541766a690ef287c0232ac768b6ec" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9d399bdcfb4a0f659b9b3788bbc89babe63d9a6a65aacdf4d4e7065ff2e6316c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90333fd89b43c0d08ac85f3f1447593fc2c66de18c3d6378d7125ea118dc7a54" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:665b0a2c463cc9423dd647e0bfd9f4ccc9b50f768c55304d5e9f80b177c1de12" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e006d3a974c4ee19512e5f058abedb6eef36a5e553c14812bdeba1758d812e6d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7d42c531243450ef0d4d9c172e7ed6ef052640f195629065041b5add4e058d1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f08c7513ecef5aad65687bfdf6bc601ae9fccd04a42904501f8f7141abad9eb9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c95b17fe34ed802f17e205112e6e10db92275c34fee290aa9bdc55a9c724027" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:56b149b22de33b23b0c6077ab9518c6dcb538ad462e1830e68d06591ccf6e38b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a8fe66b8f300da93798025a785a5b90b42f3810dc2b72283ff84a41aaaebc293" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:377fe3732edbaf78ee74efdf2c9f49f6e99f20e7f9d2649fda3eb4badd77d76e" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e8ffa78582120024f476a611d7befc123cee59e47e8309d470cf667d806e613b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:daba5e594f06114e37db186efd2dd916609071e59daca901a0a2e71f02b142ce" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:65be18ec59496c13908f02a2472751d9ef840b4f3fb5726f129306bf6a2a7bba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-win_amd64.whl", hash = "sha256:a929d878fec099030c292803b31e5d5540a7b6a31e6a3cc76cb4685fc2a2f51b" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp312-cp312-win_arm64.whl", hash = "sha256:7ce27823052e2013b597e0c738b13e7e36b8ccb9400df8959417b052ab0fd92c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:79af890482fc94648e8cde4c68620378f7fef60932710fa17a66abc039244da2" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46c2f213e23a04b93a392942d782eb9e413e6ef6bf7c8c53884e599a5c174dcb" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92ab3e11448f2ff7bf53c5a26eff0edc086898ec8b21fb154b85839ce1d88075" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ebb0ec7f17803063d5aeb982f3b1bd2b2f4e4fae6751226cbd6ba1fcfe9e63ff" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:82632daed195dcc8ea664e8556dc9bdbd671960fb3776bd92806ce05792c2448" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:53e549287ef628fecba270045c9701b0c564563a9b0577d24a4ec75b8ab8040f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fcd3b77e2f17bbe4ca56ec7bcb07992647d19d0b9c05d84886dcd6f9eb810afd" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d46b86567dd4e248c6c159fcbcdcce01e0a5c8a7cd2334a0fff759d0fa075b16" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7f72c74aa99359e27a2ee8d6613fefa28b5f76a983c083074dfc2aaa4ab46213" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3f45789ce415a7ec0820dc4f82925f9b5f7732070be1dec1f5f23ec381435a24" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6e73e7fe93f17a7b191f52ec9da9dd8c06a8fe735a1ecbd13b97d1c723bff385" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4a36f9becdd4c5c52a20c3e9484128b070b1dcfc8944c006f3a528295a359a9c" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:7bcbe0fcf850eae67b6b01749815a4f7161c560a844c769ad7b48fcd99f791c4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:24e861e9630e0daddcb9191fb187f60f034e17a4426f8101279f0c475cd74144" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9335a099ad87287c37fe5d1a982ff392fa5efe5d14b40a730b1ec1d6a41382b4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-win_amd64.whl", hash = "sha256:2dbe06fc16bc91502bca713704022182e5729861ae00277c3a23354b40929740" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp313-cp313-win_arm64.whl", hash = "sha256:6b8536851f9f65e7f00c7a1d49ba7f2be0ffe2c11555367fc9f50d9f842410a1" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:2729fcfc4f6a596fb0c50f32090400aa9367774ac296a00387e65098c0befa76" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ff330d3c30db4eb6b01d79e29d2d0b407a7ecad39cfd9ec993ece57396a2ec0d" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e42d75862735da90e7fc5a7b23db0c976f737113a54b3c9777a9b665e9cbff75" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3732e66413163e72508da9eff9ce9d2846fde51fae45d3605393d3e6cd303e9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5b8ee53be440a0cffc991a27be3057e0530122548dbe7c0892df08822fce5ede" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:af3aefa655adb5869491fa907e652290386800ae99cc50095cba71e2c6aefdca" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2120b96872df4a117cde97d270bac96aea7cc52205d305cf4611df694a487027" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:66410eb6345d467151934b49bfa70fb32f5b35a6140baa40ad97d6436abea2e9" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4af7b7e1be0a69bee8210735fe6dcfc38879adfac6d62e789d53ba432d1ffa41" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa139875ff98ab97da323cfadfaff08900d1ad42f1b5087b0b812a55c5a06373" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:0055afc45e864b92729ac7600e2d102c17bef060647e74bca75fa84d66b9ff36" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f0e466ed7511fe9d459a819edbc6c2585c0b6eabde9fa8a8947552468a7a6ef0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f141474e85b7e54998ec5180530a7cda99ab29e282fa50e0756d89981a9b43c5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:e2935f8c39e3b03e83519292d78f075189978f3f4adc15a78144c7c8e2a1cba5" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9d1216a7f6f77836617dba35687c5b78a4170afc3c3f18fc788f785ba26565c4" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-win_amd64.whl", hash = "sha256:5ba4f78df2bcc19f764a4b26a8a4f5049c110090ad5825993aacb052bf8003ad" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314-win_arm64.whl", hash = "sha256:9e4e16c73d717c5cf27626c524d0a2e261ad20e46932b2670f64ad5dde23e26f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e1ae548a9d901adca07899a4147a7c826bbcc06239d3ce9a59f57886a28a4c88" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ff405d91509d88e8d44129cd87b18d70acd1f0c1aeabd7bc3c46792b1fe2acba" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:47e98aab9d8d82ff682e7b0b5dded33bf138a32b817fcf7fa3b27b2d7c412928" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f0a658a6d3fafee5c6f63c58f3e785c8c43c93fbc02bf9f2b6663f8185e0971f" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4377407001ca3c057773f44d8ddd6358fa5f691407c1ba92210bd3cf8d9e4c95" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7c0494a31a1ac5461a226e7947a9c9b78c44e1dc7185164fa7e9651557a5d9bc" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a7cff474ab7cd149765bb784cf6d78b32e18e20473fb7bda860bce98ab58e9da" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cbb833ccacdb5519eff9b8b71ee618cc2801c878e77e288775d77c3a2ced858a" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:82f75e05912e84b7a0fe57075d9c59de3cb352b928330f2eb69b2e1f54c3e1f0" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:16a2f5010280020e90f5330257e6944bc33e73593b136cc5a241e6c1dc292498" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ffcd54362564dc1a30fb74d8b8a6e5a6b11ebd5e27266adc3b7427a21a6c9104" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0465ec8cedc2349b97a6b595ace64084a50c6e839eca40aa0626f38b8350e331" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4db9aecb141cb7a5447171b57aa1ed3a8fee06af40b992ffc31206c0b0121550" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:f540c013589084679a6c7fac07096b10159737918174f5dfc5e11bf5bca4dfe6" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a61834fb15d81322d872eaafd333838ae7c9cea84067f232656f75965933d047" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-win_amd64.whl", hash = "sha256:5c88e5815a49d289e599f3513aa7fde0bc2092ff188f99c940f007f90f53d104" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-cp314-cp314t-win_arm64.whl", hash = "sha256:cf139c02f5f23ef6532040a30ff662c00a318c952334f211046b8e60b7f17688" }, + { url = "http://airlock-proxy.uplink.goog:999/python/artifact-foundry-prod/ah-3p-staging-python/yarl/yarl-1.24.5-py3-none-any.whl", hash = "sha256:a33700d13d9b7d84fd10947b09ff69fb9a792e519c8cb9764a3ca70baa6c23a7" }, +] diff --git a/samples/community/yarn.lock b/samples/community/yarn.lock index a5171ba747..4d98e596b0 100644 --- a/samples/community/yarn.lock +++ b/samples/community/yarn.lock @@ -129,6 +129,46 @@ __metadata: languageName: unknown linkType: soft +"@a2ui/react@npm:^0.10.2": + version: 0.10.2 + resolution: "@a2ui/react@npm:0.10.2" + dependencies: + "@a2ui/markdown-it": "npm:*" + "@a2ui/web_core": "npm:^0.10.5" + clsx: "npm:^2.1.1" + markdown-it: "npm:^14.2.0" + zod: "npm:^3.25.76" + peerDependencies: + react: ^19.2.7 + react-dom: ^19.2.7 + zod: ^3.25.76 + checksum: 10c0/61db572c7f57079052d452233f58cce68e9e35b72d7b004e702741304f866960d0045d976f354c15dfac223981b1a92550bbc6870ba1002df6ca9670ed45968e + languageName: node + linkType: hard + +"@a2ui/templates-community-demo@workspace:templates/client": + version: 0.0.0-use.local + resolution: "@a2ui/templates-community-demo@workspace:templates/client" + dependencies: + "@a2ui/react": "npm:^0.10.2" + "@a2ui/web_core": "npm:^0.10.6" + "@types/node": "npm:^25.9.3" + "@types/react": "npm:^19.2.17" + "@types/react-dom": "npm:^19.2.3" + "@vitejs/plugin-react": "npm:^6.0.2" + eslint: "npm:^10.4.1" + eslint-config-prettier: "npm:^10.1.8" + eslint-plugin-react: "npm:^7.37.5" + eslint-plugin-react-hooks: "npm:^7.1.1" + react: "npm:^19.2.7" + react-dom: "npm:^19.2.7" + typescript: "npm:5.9.3" + typescript-eslint: "npm:^8.61.0" + vite: "npm:^8.0.16" + wireit: "npm:^0.15.0-pre.2" + languageName: unknown + linkType: soft + "@a2ui/web_core@npm:^0.10.0": version: 0.10.0 resolution: "@a2ui/web_core@npm:0.10.0" @@ -141,6 +181,18 @@ __metadata: languageName: node linkType: hard +"@a2ui/web_core@npm:^0.10.5, @a2ui/web_core@npm:^0.10.6": + version: 0.10.6 + resolution: "@a2ui/web_core@npm:0.10.6" + dependencies: + "@preact/signals-core": "npm:^1.14.2" + date-fns: "npm:^4.4.0" + zod: "npm:^3.25.76" + zod-to-json-schema: "npm:^3.25.2" + checksum: 10c0/481b90b4caa1428b3fa8344ab0ef5a515545e8fa6ef62e2fa6121968f80a2aab329e48be002e4590f770bd479872aa5963a5db00b12e75e063e2c7846234654b + languageName: node + linkType: hard + "@algolia/abtesting@npm:1.14.1": version: 1.14.1 resolution: "@algolia/abtesting@npm:1.14.1" @@ -842,6 +894,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.24.4": + version: 7.29.8 + resolution: "@babel/parser@npm:7.29.8" + dependencies: + "@babel/types": "npm:^7.29.8" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/acc890c5e6a6dd40863a47b50bac111d7185ee6fbbe163ebe11d5214854ca2adb901462ad4d718a65090ef84bd2230e9e8ab45a2e0caccc685f1f57ab0bb1e28 + languageName: node + linkType: hard + "@babel/template@npm:^7.28.6, @babel/template@npm:^7.29.7": version: 7.29.7 resolution: "@babel/template@npm:7.29.7" @@ -878,6 +941,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.29.8": + version: 7.29.8 + resolution: "@babel/types@npm:7.29.8" + dependencies: + "@babel/helper-string-parser": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + checksum: 10c0/be7c279f0abf2a086c633e21b49c7ca80275d05283cc5a268b67a708c9914bd0c944f1422b3eb3cb37682a2af5d560abf520ccf9b01b53ecbfe6b71fbc3fdde6 + languageName: node + linkType: hard + "@bramus/specificity@npm:^2.4.2": version: 2.4.2 resolution: "@bramus/specificity@npm:2.4.2" @@ -1231,6 +1304,17 @@ __metadata: languageName: node linkType: hard +"@eslint-community/eslint-utils@npm:^4.9.1": + version: 4.10.1 + resolution: "@eslint-community/eslint-utils@npm:4.10.1" + dependencies: + eslint-visitor-keys: "npm:^3.4.3" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 10c0/b514586655698bc6b74db72a496c77e813c78b63e36a83429845ac7057dd77113b0b6c31e6e590d5baaeee2abae6ea22363a41209bcafa078d895ab83ce83011 + languageName: node + linkType: hard + "@eslint-community/regexpp@npm:^4.12.2": version: 4.12.2 resolution: "@eslint-community/regexpp@npm:4.12.2" @@ -3270,6 +3354,13 @@ __metadata: languageName: node linkType: hard +"@preact/signals-core@npm:^1.14.2": + version: 1.14.4 + resolution: "@preact/signals-core@npm:1.14.4" + checksum: 10c0/963622e5c1c98a6946ec1ad01e9901ebacf316ab0a7e3c56c6ebaefee5b2c8ea03c3bdb8ba74120612b5f8976f5dc94693134670e372dded79db9994045aadd1 + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -4249,7 +4340,7 @@ __metadata: languageName: node linkType: hard -"@rolldown/pluginutils@npm:^1.0.0": +"@rolldown/pluginutils@npm:^1.0.0, @rolldown/pluginutils@npm:^1.0.1": version: 1.0.1 resolution: "@rolldown/pluginutils@npm:1.0.1" checksum: 10c0/99d9b06d90196823e4d8c841f258db7a16e5dbba5824a2962b05d907b79f1ba929d56f22dd744fd530936e568c865ee56a719dc31e57e13bc0a8eb4764a8d8dd @@ -4796,6 +4887,24 @@ __metadata: languageName: node linkType: hard +"@types/react-dom@npm:^19.2.3": + version: 19.2.4 + resolution: "@types/react-dom@npm:19.2.4" + peerDependencies: + "@types/react": ^19.2.0 + checksum: 10c0/b7d854ce17bb51a3a067168268a90f0123d10dc490f63f1ff5409f07ac715febeb8f5b7b473404a9d437106571e0312fc2937a945634d590abfc9aa46a14b01b + languageName: node + linkType: hard + +"@types/react@npm:^19.2.17": + version: 19.2.18 + resolution: "@types/react@npm:19.2.18" + dependencies: + csstype: "npm:^3.2.2" + checksum: 10c0/d04216172b4b4362b310017c210dfbe019fb4f4e7dffd0313e70b3acb3051d5c3e76e7e84e3cf4c6a3c824993ffadfe3949e589a6398a09d4200e7670e2962de + languageName: node + linkType: hard + "@types/request@npm:^2.48.8": version: 2.48.13 resolution: "@types/request@npm:2.48.13" @@ -4857,6 +4966,141 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.67.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.12.2" + "@typescript-eslint/scope-manager": "npm:8.67.0" + "@typescript-eslint/type-utils": "npm:8.67.0" + "@typescript-eslint/utils": "npm:8.67.0" + "@typescript-eslint/visitor-keys": "npm:8.67.0" + ignore: "npm:^7.0.5" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + "@typescript-eslint/parser": ^8.67.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/5962baaa764cd6350dfdf51c9a09fdd9ee6be65982ac562ee9b732f851744158e5006bf8ce61556a93534d831be8300fd89d7b79b6b4d7170dc2381d987dc8d9 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/parser@npm:8.67.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:8.67.0" + "@typescript-eslint/types": "npm:8.67.0" + "@typescript-eslint/typescript-estree": "npm:8.67.0" + "@typescript-eslint/visitor-keys": "npm:8.67.0" + debug: "npm:^4.4.3" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/8f6f8fbea429509ca0c95c4d48a45da0c890172a590606d65587e75a3ca762c3e5678a20a63fc9e386b0b21b7aa643ba9724354ceaa75bc8f62d0b22cb0198c8 + languageName: node + linkType: hard + +"@typescript-eslint/project-service@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/project-service@npm:8.67.0" + dependencies: + "@typescript-eslint/tsconfig-utils": "npm:^8.67.0" + "@typescript-eslint/types": "npm:^8.67.0" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/d8f89dc209f2186c04fb1c42c1a5c69c21696a7a57c5f2be2222682a6440b49ec32687ae85cbd1c1c164431635fbc37bb9404b336e5748966e270ee1347e028c + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/scope-manager@npm:8.67.0" + dependencies: + "@typescript-eslint/types": "npm:8.67.0" + "@typescript-eslint/visitor-keys": "npm:8.67.0" + checksum: 10c0/8f1fe7dffcb6929ad66dcdca77dd1e4a703f18ab3ab1d685458af74dad10b9be05795e64bd58ff60b45cda8d45737240c84874674d39140c2689e00e3ee82bb9 + languageName: node + linkType: hard + +"@typescript-eslint/tsconfig-utils@npm:8.67.0, @typescript-eslint/tsconfig-utils@npm:^8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.67.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/c19161347ea3d7a0081653c4d399275a3e0d66f87a24131fb5a358e6b55bc27d709781dbda16382f3f721d790338dcf42c65c9e6c26077123e9f3d076d37a894 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/type-utils@npm:8.67.0" + dependencies: + "@typescript-eslint/types": "npm:8.67.0" + "@typescript-eslint/typescript-estree": "npm:8.67.0" + "@typescript-eslint/utils": "npm:8.67.0" + debug: "npm:^4.4.3" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/0970ea126f9b63a6eb9ca3525a6bf3065dffb3f61a00bd0ee84967140e7ecffe45cafda0cd2c90233dcc06b19c8fb98f4cd90ba8ebbb12deaf9501b9f5b54d8c + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:8.67.0, @typescript-eslint/types@npm:^8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/types@npm:8.67.0" + checksum: 10c0/b892a00d4cbea9604a0abf6eedd0ea019b27df4220a1d90e0035101cb4f846722c9e3eeadce40b423c1e0240709bbc787c6ca49bcc4f8c25ba23b4bd0436492a + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.67.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.67.0" + "@typescript-eslint/tsconfig-utils": "npm:8.67.0" + "@typescript-eslint/types": "npm:8.67.0" + "@typescript-eslint/visitor-keys": "npm:8.67.0" + debug: "npm:^4.4.3" + minimatch: "npm:^10.2.2" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/449350fcf4f4ee55a6bb7a73302c4eef072a1282d366344cb625c0f17231eb4088251e6ce61fb48d0d536febb9a28f3725b9bd78ac8d0dbf9c161cf51745870c + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/utils@npm:8.67.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.67.0" + "@typescript-eslint/types": "npm:8.67.0" + "@typescript-eslint/typescript-estree": "npm:8.67.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/cccaca1aeba52ec332ee95f3367b84eaf5dd9d60a0d1b4332ebe41b775fa7e8b8faf412de4d88b73a22f84b01f6ab48496c61863407b08fcbef9af429b6b89f1 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:8.67.0": + version: 8.67.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.67.0" + dependencies: + "@typescript-eslint/types": "npm:8.67.0" + eslint-visitor-keys: "npm:^5.0.0" + checksum: 10c0/d43e6151cd1cdbcfb2f9fa54946198baaebaf0b7a9057ccb2f1aeba1aa3eb46708a97cd7773dcfd0eba3bd45642a5520f4607001cd27d8958e41aa56b2fe7a35 + languageName: node + linkType: hard + "@vitejs/plugin-basic-ssl@npm:2.1.4": version: 2.1.4 resolution: "@vitejs/plugin-basic-ssl@npm:2.1.4" @@ -4866,6 +5110,24 @@ __metadata: languageName: node linkType: hard +"@vitejs/plugin-react@npm:^6.0.2": + version: 6.0.5 + resolution: "@vitejs/plugin-react@npm:6.0.5" + dependencies: + "@rolldown/pluginutils": "npm:^1.0.1" + peerDependencies: + "@rolldown/plugin-babel": ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + "@rolldown/plugin-babel": + optional: true + babel-plugin-react-compiler: + optional: true + checksum: 10c0/fb02246fe3652d7fb746190bdd098b9e29918dfcf8c67b9c0c37300ce789e82331b2ba761530ac6ac9a61390b774d44f401787bd1c87a6c866d1e74a745cc1a0 + languageName: node + linkType: hard + "@vitest/expect@npm:4.1.9": version: 4.1.9 resolution: "@vitest/expect@npm:4.1.9" @@ -5301,6 +5563,98 @@ __metadata: languageName: node linkType: hard +"array-buffer-byte-length@npm:^1.0.1, array-buffer-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "array-buffer-byte-length@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + is-array-buffer: "npm:^3.0.5" + checksum: 10c0/74e1d2d996941c7a1badda9cabb7caab8c449db9086407cad8a1b71d2604cc8abf105db8ca4e02c04579ec58b7be40279ddb09aea4784832984485499f48432d + languageName: node + linkType: hard + +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": + version: 3.1.9 + resolution: "array-includes@npm:3.1.9" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.24.0" + es-object-atoms: "npm:^1.1.1" + get-intrinsic: "npm:^1.3.0" + is-string: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/0235fa69078abeac05ac4250699c44996bc6f774a9cbe45db48674ce6bd142f09b327d31482ff75cf03344db4ea03eae23edb862d59378b484b47ed842574856 + languageName: node + linkType: hard + +"array.prototype.findlast@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10c0/ddc952b829145ab45411b9d6adcb51a8c17c76bf89c9dd64b52d5dffa65d033da8c076ed2e17091779e83bc892b9848188d7b4b33453c5565e65a92863cb2775 + languageName: node + linkType: hard + +"array.prototype.flat@npm:^1.3.1": + version: 1.3.3 + resolution: "array.prototype.flat@npm:1.3.3" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10c0/d90e04dfbc43bb96b3d2248576753d1fb2298d2d972e29ca7ad5ec621f0d9e16ff8074dae647eac4f31f4fb7d3f561a7ac005fb01a71f51705a13b5af06a7d8a + languageName: node + linkType: hard + +"array.prototype.flatmap@npm:^1.3.3": + version: 1.3.3 + resolution: "array.prototype.flatmap@npm:1.3.3" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10c0/ba899ea22b9dc9bf276e773e98ac84638ed5e0236de06f13d63a90b18ca9e0ec7c97d622d899796e3773930b946cd2413d098656c0c5d8cc58c6f25c21e6bd54 + languageName: node + linkType: hard + +"array.prototype.tosorted@npm:^1.1.4": + version: 1.1.4 + resolution: "array.prototype.tosorted@npm:1.1.4" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.3" + es-errors: "npm:^1.3.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10c0/eb3c4c4fc0381b0bf6dba2ea4d48d367c2827a0d4236a5718d97caaccc6b78f11f4cadf090736e86301d295a6aa4967ed45568f92ced51be8cbbacd9ca410943 + languageName: node + linkType: hard + +"arraybuffer.prototype.slice@npm:^1.0.4": + version: 1.0.4 + resolution: "arraybuffer.prototype.slice@npm:1.0.4" + dependencies: + array-buffer-byte-length: "npm:^1.0.1" + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + is-array-buffer: "npm:^3.0.4" + checksum: 10c0/2f2459caa06ae0f7f615003f9104b01f6435cc803e11bd2a655107d52a1781dc040532dc44d93026b694cc18793993246237423e13a5337e86b43ed604932c06 + languageName: node + linkType: hard + "arrify@npm:^2.0.0": version: 2.0.1 resolution: "arrify@npm:2.0.1" @@ -5345,6 +5699,15 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10c0/d07226ef4f87daa01bd0fe80f8f310982e345f372926da2e5296aecc25c41cab440916bbaa4c5e1034b453af3392f67df5961124e4b586df1e99793a1374bdb2 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -5616,7 +5979,19 @@ __metadata: languageName: node linkType: hard -"call-bound@npm:^1.0.2": +"call-bind@npm:^1.0.7, call-bind@npm:^1.0.8, call-bind@npm:^1.0.9": + version: 1.0.9 + resolution: "call-bind@npm:1.0.9" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + get-intrinsic: "npm:^1.3.0" + set-function-length: "npm:^1.2.2" + checksum: 10c0/a6621f6da1444481919ce3b4983dff725691e0754d3507ae483ce56e54985f2da7d6f1df512c56dbf28660745cf1ca52553f1fc9aef5557f3ce353ef14fab714 + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": version: 1.0.4 resolution: "call-bound@npm:1.0.4" dependencies: @@ -6043,6 +6418,13 @@ __metadata: languageName: node linkType: hard +"csstype@npm:^3.2.2": + version: 3.2.3 + resolution: "csstype@npm:3.2.3" + checksum: 10c0/cd29c51e70fa822f1cecd8641a1445bed7063697469d35633b516e60fe8c1bde04b08f6c5b6022136bb669b64c63d4173af54864510fbb4ee23281801841a3ce + languageName: node + linkType: hard + "custom-lit-components@workspace:custom-lit-components": version: 0.0.0-use.local resolution: "custom-lit-components@workspace:custom-lit-components" @@ -6074,7 +6456,40 @@ __metadata: languageName: node linkType: hard -"date-fns@npm:^4.1.0": +"data-view-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-buffer@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.2" + checksum: 10c0/7986d40fc7979e9e6241f85db8d17060dd9a71bd53c894fa29d126061715e322a4cd47a00b0b8c710394854183d4120462b980b8554012acc1c0fa49df7ad38c + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-byte-length@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.2" + checksum: 10c0/f8a4534b5c69384d95ac18137d381f18a5cfae1f0fc1df0ef6feef51ef0d568606d970b69e02ea186c6c0f0eac77fe4e6ad96fec2569cc86c3afcc7475068c55 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-offset@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10c0/fa7aa40078025b7810dcffc16df02c480573b7b53ef1205aa6a61533011005c1890e5ba17018c692ce7c900212b547262d33279fde801ad9843edc0863bf78c4 + languageName: node + linkType: hard + +"date-fns@npm:^4.1.0, date-fns@npm:^4.4.0": version: 4.4.0 resolution: "date-fns@npm:4.4.0" checksum: 10c0/988f0a13db183f5dfc85c36bbb6847a9c135a9225888bbea4005876ec15539a8613c21a07370a4e7ea543918d5a1cafb423c528b42cdbbde5fdfddb178126b21 @@ -6124,6 +6539,17 @@ __metadata: languageName: node linkType: hard +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.0.1" + checksum: 10c0/dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 + languageName: node + linkType: hard + "define-lazy-prop@npm:^3.0.0": version: 3.0.0 resolution: "define-lazy-prop@npm:3.0.0" @@ -6131,6 +6557,17 @@ __metadata: languageName: node linkType: hard +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.0" + object-keys: "npm:^1.1.1" + checksum: 10c0/88a152319ffe1396ccc6ded510a3896e77efac7a1bfbaa174a7b00414a1747377e0bb525d303794a47cf30e805c2ec84e575758512c6e44a993076d29fd4e6c3 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -6173,6 +6610,15 @@ __metadata: languageName: node linkType: hard +"doctrine@npm:^2.1.0": + version: 2.1.0 + resolution: "doctrine@npm:2.1.0" + dependencies: + esutils: "npm:^2.0.2" + checksum: 10c0/b6416aaff1f380bf56c3b552f31fdf7a69b45689368deca72d28636f41c16bb28ec3ebc40ace97db4c1afc0ceeb8120e8492fe0046841c94c2933b2e30a7d5ac + languageName: node + linkType: hard + "dom-serializer@npm:^2.0.0": version: 2.0.0 resolution: "dom-serializer@npm:2.0.0" @@ -6230,7 +6676,7 @@ __metadata: languageName: node linkType: hard -"dunder-proto@npm:^1.0.1": +"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": version: 1.0.1 resolution: "dunder-proto@npm:1.0.1" dependencies: @@ -6380,7 +6826,81 @@ __metadata: languageName: node linkType: hard -"es-define-property@npm:^1.0.1": +"es-abstract-get@npm:^1.0.0": + version: 1.0.0 + resolution: "es-abstract-get@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.2" + is-callable: "npm:^1.2.7" + object-inspect: "npm:^1.13.4" + checksum: 10c0/f9b4838ae719752207383a6d95a74590f891122bf26b92f5e72eeedbe53771029e4561f1cf75ea19330b71bcf3d4f536fb0c8f7e2b601fe24d284f46e488c7e3 + languageName: node + linkType: hard + +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0, es-abstract@npm:^1.24.2": + version: 1.24.2 + resolution: "es-abstract@npm:1.24.2" + dependencies: + array-buffer-byte-length: "npm:^1.0.2" + arraybuffer.prototype.slice: "npm:^1.0.4" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + data-view-buffer: "npm:^1.0.2" + data-view-byte-length: "npm:^1.0.2" + data-view-byte-offset: "npm:^1.0.1" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + es-set-tostringtag: "npm:^2.1.0" + es-to-primitive: "npm:^1.3.0" + function.prototype.name: "npm:^1.1.8" + get-intrinsic: "npm:^1.3.0" + get-proto: "npm:^1.0.1" + get-symbol-description: "npm:^1.1.0" + globalthis: "npm:^1.0.4" + gopd: "npm:^1.2.0" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + internal-slot: "npm:^1.1.0" + is-array-buffer: "npm:^3.0.5" + is-callable: "npm:^1.2.7" + is-data-view: "npm:^1.0.2" + is-negative-zero: "npm:^2.0.3" + is-regex: "npm:^1.2.1" + is-set: "npm:^2.0.3" + is-shared-array-buffer: "npm:^1.0.4" + is-string: "npm:^1.1.1" + is-typed-array: "npm:^1.1.15" + is-weakref: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + object-inspect: "npm:^1.13.4" + object-keys: "npm:^1.1.1" + object.assign: "npm:^4.1.7" + own-keys: "npm:^1.0.1" + regexp.prototype.flags: "npm:^1.5.4" + safe-array-concat: "npm:^1.1.3" + safe-push-apply: "npm:^1.0.0" + safe-regex-test: "npm:^1.1.0" + set-proto: "npm:^1.0.0" + stop-iteration-iterator: "npm:^1.1.0" + string.prototype.trim: "npm:^1.2.10" + string.prototype.trimend: "npm:^1.0.9" + string.prototype.trimstart: "npm:^1.0.8" + typed-array-buffer: "npm:^1.0.3" + typed-array-byte-length: "npm:^1.0.3" + typed-array-byte-offset: "npm:^1.0.4" + typed-array-length: "npm:^1.0.7" + unbox-primitive: "npm:^1.1.0" + which-typed-array: "npm:^1.1.19" + checksum: 10c0/67a5bf21ef5c7d775e6f6131a836323900b4d87194cf544394ac68fe31c57fa53828b978af4a4f551ef307f83a2f910a16b6b982760ad3ddc3dc471f98d5fd1b + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": version: 1.0.1 resolution: "es-define-property@npm:1.0.1" checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c @@ -6394,6 +6914,30 @@ __metadata: languageName: node linkType: hard +"es-iterator-helpers@npm:^1.2.1": + version: 1.4.0 + resolution: "es-iterator-helpers@npm:1.4.0" + dependencies: + call-bind: "npm:^1.0.9" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.24.2" + es-errors: "npm:^1.3.0" + es-set-tostringtag: "npm:^2.1.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.3.0" + globalthis: "npm:^1.0.4" + gopd: "npm:^1.2.0" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + internal-slot: "npm:^1.1.0" + iterator.prototype: "npm:^1.1.5" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/839a5e881446e1b4ab270a9ad5d01a23b83a38fadb9e526674df171357e90ad3111dc8c0b15e7d30db1958f2c3332dd963fab7d55f406a660d098b2b7eefb218 + languageName: node + linkType: hard + "es-module-lexer@npm:^2.0.0": version: 2.1.0 resolution: "es-module-lexer@npm:2.1.0" @@ -6401,7 +6945,7 @@ __metadata: languageName: node linkType: hard -"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1, es-object-atoms@npm:^1.1.2": version: 1.1.2 resolution: "es-object-atoms@npm:1.1.2" dependencies: @@ -6422,6 +6966,29 @@ __metadata: languageName: node linkType: hard +"es-shim-unscopables@npm:^1.0.2": + version: 1.1.0 + resolution: "es-shim-unscopables@npm:1.1.0" + dependencies: + hasown: "npm:^2.0.2" + checksum: 10c0/1b9702c8a1823fc3ef39035a4e958802cf294dd21e917397c561d0b3e195f383b978359816b1732d02b255ccf63e1e4815da0065b95db8d7c992037be3bbbcdb + languageName: node + linkType: hard + +"es-to-primitive@npm:^1.3.0": + version: 1.3.4 + resolution: "es-to-primitive@npm:1.3.4" + dependencies: + es-abstract-get: "npm:^1.0.0" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + is-callable: "npm:^1.2.7" + is-date-object: "npm:^1.1.0" + is-symbol: "npm:^1.1.1" + checksum: 10c0/b10029f8b0b13841bade224ff39005a13d76d9cb803cd1efb18cc96a24414e83e2e7ed15d7ad9d0d0bda66884afd211b7b579b8fa31940e05b060934aa7077d8 + languageName: node + linkType: hard + "es-toolkit@npm:^1.39.7": version: 1.47.1 resolution: "es-toolkit@npm:1.47.1" @@ -6546,8 +7113,62 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^9.1.2": - version: 9.1.2 +"eslint-config-prettier@npm:^10.1.8": + version: 10.1.8 + resolution: "eslint-config-prettier@npm:10.1.8" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 10c0/e1bcfadc9eccd526c240056b1e59c5cd26544fe59feb85f38f4f1f116caed96aea0b3b87868e68b3099e55caaac3f2e5b9f58110f85db893e83a332751192682 + languageName: node + linkType: hard + +"eslint-plugin-react-hooks@npm:^7.1.1": + version: 7.1.1 + resolution: "eslint-plugin-react-hooks@npm:7.1.1" + dependencies: + "@babel/core": "npm:^7.24.4" + "@babel/parser": "npm:^7.24.4" + hermes-parser: "npm:^0.25.1" + zod: "npm:^3.25.0 || ^4.0.0" + zod-validation-error: "npm:^3.5.0 || ^4.0.0" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 + checksum: 10c0/cee8454915d71ac5d70a0d8f4f260e76eaf45fcd4162747dd4282b792ee5616d187351dabe6cdcff9040c79d0cec625635c4fd0777276be119efa88ebe058525 + languageName: node + linkType: hard + +"eslint-plugin-react@npm:^7.37.5": + version: 7.37.5 + resolution: "eslint-plugin-react@npm:7.37.5" + dependencies: + array-includes: "npm:^3.1.8" + array.prototype.findlast: "npm:^1.2.5" + array.prototype.flatmap: "npm:^1.3.3" + array.prototype.tosorted: "npm:^1.1.4" + doctrine: "npm:^2.1.0" + es-iterator-helpers: "npm:^1.2.1" + estraverse: "npm:^5.3.0" + hasown: "npm:^2.0.2" + jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" + minimatch: "npm:^3.1.2" + object.entries: "npm:^1.1.9" + object.fromentries: "npm:^2.0.8" + object.values: "npm:^1.2.1" + prop-types: "npm:^15.8.1" + resolve: "npm:^2.0.0-next.5" + semver: "npm:^6.3.1" + string.prototype.matchall: "npm:^4.0.12" + string.prototype.repeat: "npm:^1.0.0" + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + checksum: 10c0/c850bfd556291d4d9234f5ca38db1436924a1013627c8ab1853f77cac73ec19b020e861e6c7b783436a48b6ffcdfba4547598235a37ad4611b6739f65fd8ad57 + languageName: node + linkType: hard + +"eslint-scope@npm:^9.1.2": + version: 9.1.2 resolution: "eslint-scope@npm:9.1.2" dependencies: "@types/esrecurse": "npm:^4.3.1" @@ -6565,7 +7186,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^5.0.1": +"eslint-visitor-keys@npm:^5.0.0, eslint-visitor-keys@npm:^5.0.1": version: 5.0.1 resolution: "eslint-visitor-keys@npm:5.0.1" checksum: 10c0/16190bdf2cbae40a1109384c94450c526a79b0b9c3cb21e544256ed85ac48a4b84db66b74a6561d20fe6ab77447f150d711c2ad5ad74df4fcc133736bce99678 @@ -6646,7 +7267,7 @@ __metadata: languageName: node linkType: hard -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": version: 5.3.0 resolution: "estraverse@npm:5.3.0" checksum: 10c0/1ff9447b96263dec95d6d67431c5e0771eb9776427421260a3e2f0fdd5d6bd4f8e37a7338f5ad2880c9f143450c9b1e4fc2069060724570a49cf9cf0312bd107 @@ -7030,6 +7651,15 @@ __metadata: languageName: node linkType: hard +"for-each@npm:^0.3.3, for-each@npm:^0.3.5": + version: 0.3.5 + resolution: "for-each@npm:0.3.5" + dependencies: + is-callable: "npm:^1.2.7" + checksum: 10c0/0e0b50f6a843a282637d43674d1fb278dda1dd85f4f99b640024cfb10b85058aac0cc781bf689d5fe50b4b7f638e91e548560723a4e76e04fe96ae35ef039cee + languageName: node + linkType: hard + "foreground-child@npm:^3.1.0": version: 3.3.1 resolution: "foreground-child@npm:3.3.1" @@ -7119,6 +7749,23 @@ __metadata: languageName: node linkType: hard +"function.prototype.name@npm:^1.1.6, function.prototype.name@npm:^1.1.8": + version: 1.2.0 + resolution: "function.prototype.name@npm:1.2.0" + dependencies: + call-bind: "npm:^1.0.9" + call-bound: "npm:^1.0.4" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + functions-have-names: "npm:^1.2.3" + has-property-descriptors: "npm:^1.0.2" + hasown: "npm:^2.0.4" + is-callable: "npm:^1.2.7" + is-document.all: "npm:^1.0.0" + checksum: 10c0/b20e6370ef4f7d56d0bedf5719f6684a517a8dd3334209b4d9f51e8834859302a584187156bf024cda9f50ba2479e4d6764ac34af9532ea47d2f4d9fa6bcf90d + languageName: node + linkType: hard + "functional-red-black-tree@npm:^1.0.1": version: 1.0.1 resolution: "functional-red-black-tree@npm:1.0.1" @@ -7126,6 +7773,13 @@ __metadata: languageName: node linkType: hard +"functions-have-names@npm:^1.2.3": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: 10c0/33e77fd29bddc2d9bb78ab3eb854c165909201f88c75faa8272e35899e2d35a8a642a15e7420ef945e1f64a9670d6aa3ec744106b2aa42be68ca5114025954ca + languageName: node + linkType: hard + "gaxios@npm:7.1.3": version: 7.1.3 resolution: "gaxios@npm:7.1.3" @@ -7223,7 +7877,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": version: 1.3.1 resolution: "get-intrinsic@npm:1.3.1" dependencies: @@ -7251,7 +7905,7 @@ __metadata: languageName: node linkType: hard -"get-proto@npm:^1.0.1": +"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": version: 1.0.1 resolution: "get-proto@npm:1.0.1" dependencies: @@ -7261,6 +7915,17 @@ __metadata: languageName: node linkType: hard +"get-symbol-description@npm:^1.1.0": + version: 1.1.0 + resolution: "get-symbol-description@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + checksum: 10c0/d6a7d6afca375779a4b307738c9e80dbf7afc0bdbe5948768d54ab9653c865523d8920e670991a925936eb524b7cb6a6361d199a760b21d0ca7620194455aa4b + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -7327,6 +7992,16 @@ __metadata: languageName: node linkType: hard +"globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" + dependencies: + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 10c0/9d156f313af79d80b1566b93e19285f481c591ad6d0d319b4be5e03750d004dde40a39a0f26f7e635f9007a3600802f53ecd85a759b86f109e80a5f705e01846 + languageName: node + linkType: hard + "google-auth-library@npm:10.5.0": version: 10.5.0 resolution: "google-auth-library@npm:10.5.0" @@ -7410,7 +8085,7 @@ __metadata: languageName: node linkType: hard -"gopd@npm:^1.2.0": +"gopd@npm:^1.0.1, gopd@npm:^1.2.0": version: 1.2.0 resolution: "gopd@npm:1.2.0" checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead @@ -7444,6 +8119,13 @@ __metadata: languageName: node linkType: hard +"has-bigints@npm:^1.0.2": + version: 1.1.0 + resolution: "has-bigints@npm:1.1.0" + checksum: 10c0/2de0cdc4a1ccf7a1e75ffede1876994525ac03cc6f5ae7392d3415dd475cd9eee5bceec63669ab61aa997ff6cceebb50ef75561c7002bed8988de2b9d1b40788 + languageName: node + linkType: hard + "has-flag@npm:^4.0.0": version: 4.0.0 resolution: "has-flag@npm:4.0.0" @@ -7451,6 +8133,24 @@ __metadata: languageName: node linkType: hard +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" + dependencies: + es-define-property: "npm:^1.0.0" + checksum: 10c0/253c1f59e80bb476cf0dde8ff5284505d90c3bdb762983c3514d36414290475fe3fd6f574929d84de2a8eec00d35cf07cb6776205ff32efd7c50719125f00236 + languageName: node + linkType: hard + +"has-proto@npm:^1.2.0": + version: 1.2.0 + resolution: "has-proto@npm:1.2.0" + dependencies: + dunder-proto: "npm:^1.0.0" + checksum: 10c0/46538dddab297ec2f43923c3d35237df45d8c55a6fc1067031e04c13ed8a9a8f94954460632fd4da84c31a1721eefee16d901cbb1ae9602bab93bb6e08f93b95 + languageName: node + linkType: hard + "has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" @@ -7476,6 +8176,22 @@ __metadata: languageName: node linkType: hard +"hermes-estree@npm:0.25.1": + version: 0.25.1 + resolution: "hermes-estree@npm:0.25.1" + checksum: 10c0/48be3b2fa37a0cbc77a112a89096fa212f25d06de92781b163d67853d210a8a5c3784fac23d7d48335058f7ed283115c87b4332c2a2abaaccc76d0ead1a282ac + languageName: node + linkType: hard + +"hermes-parser@npm:^0.25.1": + version: 0.25.1 + resolution: "hermes-parser@npm:0.25.1" + dependencies: + hermes-estree: "npm:0.25.1" + checksum: 10c0/3abaa4c6f1bcc25273f267297a89a4904963ea29af19b8e4f6eabe04f1c2c7e9abd7bfc4730ddb1d58f2ea04b6fee74053d8bddb5656ec6ebf6c79cc8d14202c + languageName: node + linkType: hard + "hono@npm:^4.11.4": version: 4.12.25 resolution: "hono@npm:4.12.25" @@ -7629,6 +8345,13 @@ __metadata: languageName: node linkType: hard +"ignore@npm:^7.0.5": + version: 7.0.6 + resolution: "ignore@npm:7.0.6" + checksum: 10c0/fc01ef1d14efbe003439b60538726351e81483d1b6f55bdbb3a4465c6346d9481afad5b350dfbd604ddd7049618ef9093ff26dc147984aabc303c56ba53ea3b5 + languageName: node + linkType: hard + "image-size@npm:~0.5.0": version: 0.5.5 resolution: "image-size@npm:0.5.5" @@ -7685,6 +8408,17 @@ __metadata: languageName: node linkType: hard +"internal-slot@npm:^1.1.0": + version: 1.1.0 + resolution: "internal-slot@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + hasown: "npm:^2.0.2" + side-channel: "npm:^1.1.0" + checksum: 10c0/03966f5e259b009a9bf1a78d60da920df198af4318ec004f57b8aef1dd3fe377fbc8cce63a96e8c810010302654de89f9e19de1cd8ad0061d15be28a695465c7 + languageName: node + linkType: hard + "interpret@npm:^1.0.0": version: 1.4.0 resolution: "interpret@npm:1.4.0" @@ -7706,6 +8440,39 @@ __metadata: languageName: node linkType: hard +"is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": + version: 3.0.5 + resolution: "is-array-buffer@npm:3.0.5" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.6" + checksum: 10c0/c5c9f25606e86dbb12e756694afbbff64bc8b348d1bc989324c037e1068695131930199d6ad381952715dad3a9569333817f0b1a72ce5af7f883ce802e49c83d + languageName: node + linkType: hard + +"is-async-function@npm:^2.0.0": + version: 2.1.1 + resolution: "is-async-function@npm:2.1.1" + dependencies: + async-function: "npm:^1.0.0" + call-bound: "npm:^1.0.3" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/d70c236a5e82de6fc4d44368ffd0c2fee2b088b893511ce21e679da275a5ecc6015ff59a7d7e1bdd7ca39f71a8dbdd253cf8cce5c6b3c91cdd5b42b5ce677298 + languageName: node + linkType: hard + +"is-bigint@npm:^1.1.0": + version: 1.1.0 + resolution: "is-bigint@npm:1.1.0" + dependencies: + has-bigints: "npm:^1.0.2" + checksum: 10c0/f4f4b905ceb195be90a6ea7f34323bf1c18e3793f18922e3e9a73c684c29eeeeff5175605c3a3a74cc38185fe27758f07efba3dbae812e5c5afbc0d2316b40e4 + languageName: node + linkType: hard + "is-binary-path@npm:~2.1.0": version: 2.1.0 resolution: "is-binary-path@npm:2.1.0" @@ -7715,7 +8482,24 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.16.1": +"is-boolean-object@npm:^1.2.1": + version: 1.2.2 + resolution: "is-boolean-object@npm:1.2.2" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/36ff6baf6bd18b3130186990026f5a95c709345c39cd368468e6c1b6ab52201e9fd26d8e1f4c066357b4938b0f0401e1a5000e08257787c1a02f3a719457001e + languageName: node + linkType: hard + +"is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f + languageName: node + linkType: hard + +"is-core-module@npm:^2.16.1, is-core-module@npm:^2.16.2": version: 2.16.2 resolution: "is-core-module@npm:2.16.2" dependencies: @@ -7724,6 +8508,27 @@ __metadata: languageName: node linkType: hard +"is-data-view@npm:^1.0.1, is-data-view@npm:^1.0.2": + version: 1.0.2 + resolution: "is-data-view@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + get-intrinsic: "npm:^1.2.6" + is-typed-array: "npm:^1.1.13" + checksum: 10c0/ef3548a99d7e7f1370ce21006baca6d40c73e9f15c941f89f0049c79714c873d03b02dae1c64b3f861f55163ecc16da06506c5b8a1d4f16650b3d9351c380153 + languageName: node + linkType: hard + +"is-date-object@npm:^1.1.0": + version: 1.1.0 + resolution: "is-date-object@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/1a4d199c8e9e9cac5128d32e6626fa7805175af9df015620ac0d5d45854ccf348ba494679d872d37301032e35a54fc7978fba1687e8721b2139aea7870cafa2f + languageName: node + linkType: hard + "is-docker@npm:^3.0.0": version: 3.0.0 resolution: "is-docker@npm:3.0.0" @@ -7733,6 +8538,15 @@ __metadata: languageName: node linkType: hard +"is-document.all@npm:^1.0.0": + version: 1.0.0 + resolution: "is-document.all@npm:1.0.0" + dependencies: + call-bound: "npm:^1.0.4" + checksum: 10c0/955c20ed5bf01d49da8243b4c714947a6ff64b6d9ba0e12bdbfa654a3e7c47f72cc01c6cd2905e85512d02bc3a1290edd73857bca8842566ff9dcfb7c3f92dae + languageName: node + linkType: hard + "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -7740,6 +8554,15 @@ __metadata: languageName: node linkType: hard +"is-finalizationregistry@npm:^1.1.0": + version: 1.1.1 + resolution: "is-finalizationregistry@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10c0/818dff679b64f19e228a8205a1e2d09989a98e98def3a817f889208cfcbf918d321b251aadf2c05918194803ebd2eb01b14fc9d0b2bea53d984f4137bfca5e97 + languageName: node + linkType: hard + "is-fullwidth-code-point@npm:^3.0.0": version: 3.0.0 resolution: "is-fullwidth-code-point@npm:3.0.0" @@ -7756,6 +8579,19 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.10": + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" + dependencies: + call-bound: "npm:^1.0.4" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/83da102e89c3e3b71d67b51d47c9f9bc862bceb58f87201727e27f7fa19d1d90b0ab223644ecaee6fc6e3d2d622bb25c966fbdaf87c59158b01ce7c0fe2fa372 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -7783,6 +8619,30 @@ __metadata: languageName: node linkType: hard +"is-map@npm:^2.0.3": + version: 2.0.3 + resolution: "is-map@npm:2.0.3" + checksum: 10c0/2c4d431b74e00fdda7162cd8e4b763d6f6f217edf97d4f8538b94b8702b150610e2c64961340015fe8df5b1fcee33ccd2e9b62619c4a8a3a155f8de6d6d355fc + languageName: node + linkType: hard + +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: 10c0/bcdcf6b8b9714063ffcfa9929c575ac69bfdabb8f4574ff557dfc086df2836cf07e3906f5bbc4f2a5c12f8f3ba56af640c843cdfc74da8caed86c7c7d66fd08e + languageName: node + linkType: hard + +"is-number-object@npm:^1.1.1": + version: 1.1.1 + resolution: "is-number-object@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/97b451b41f25135ff021d85c436ff0100d84a039bb87ffd799cbcdbea81ef30c464ced38258cdd34f080be08fc3b076ca1f472086286d2aa43521d6ec6a79f53 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -7804,6 +8664,34 @@ __metadata: languageName: node linkType: hard +"is-regex@npm:^1.2.1": + version: 1.2.1 + resolution: "is-regex@npm:1.2.1" + dependencies: + call-bound: "npm:^1.0.2" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10c0/1d3715d2b7889932349241680032e85d0b492cfcb045acb75ffc2c3085e8d561184f1f7e84b6f8321935b4aea39bc9c6ba74ed595b57ce4881a51dfdbc214e04 + languageName: node + linkType: hard + +"is-set@npm:^2.0.3": + version: 2.0.3 + resolution: "is-set@npm:2.0.3" + checksum: 10c0/f73732e13f099b2dc879c2a12341cfc22ccaca8dd504e6edae26484bd5707a35d503fba5b4daad530a9b088ced1ae6c9d8200fd92e09b428fe14ea79ce8080b7 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.4": + version: 1.0.4 + resolution: "is-shared-array-buffer@npm:1.0.4" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10c0/65158c2feb41ff1edd6bbd6fd8403a69861cf273ff36077982b5d4d68e1d59278c71691216a4a64632bd76d4792d4d1d2553901b6666d84ade13bba5ea7bc7db + languageName: node + linkType: hard + "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -7811,6 +8699,36 @@ __metadata: languageName: node linkType: hard +"is-string@npm:^1.1.1": + version: 1.1.1 + resolution: "is-string@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/2f518b4e47886bb81567faba6ffd0d8a8333cf84336e2e78bf160693972e32ad00fe84b0926491cc598dee576fdc55642c92e62d0cbe96bf36f643b6f956f94d + languageName: node + linkType: hard + +"is-symbol@npm:^1.1.1": + version: 1.1.1 + resolution: "is-symbol@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.2" + has-symbols: "npm:^1.1.0" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/f08f3e255c12442e833f75a9e2b84b2d4882fdfd920513cf2a4a2324f0a5b076c8fd913778e3ea5d258d5183e9d92c0cd20e04b03ab3df05316b049b2670af1e + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": + version: 1.1.15 + resolution: "is-typed-array@npm:1.1.15" + dependencies: + which-typed-array: "npm:^1.1.16" + checksum: 10c0/415511da3669e36e002820584e264997ffe277ff136643a3126cc949197e6ca3334d0f12d084e83b1994af2e9c8141275c741cf2b7da5a2ff62dd0cac26f76c4 + languageName: node + linkType: hard + "is-unicode-supported@npm:^2.0.0, is-unicode-supported@npm:^2.1.0": version: 2.1.0 resolution: "is-unicode-supported@npm:2.1.0" @@ -7825,6 +8743,32 @@ __metadata: languageName: node linkType: hard +"is-weakmap@npm:^2.0.2": + version: 2.0.2 + resolution: "is-weakmap@npm:2.0.2" + checksum: 10c0/443c35bb86d5e6cc5929cd9c75a4024bb0fff9586ed50b092f94e700b89c43a33b186b76dbc6d54f3d3d09ece689ab38dcdc1af6a482cbe79c0f2da0a17f1299 + languageName: node + linkType: hard + +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": + version: 1.1.1 + resolution: "is-weakref@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10c0/8e0a9c07b0c780949a100e2cab2b5560a48ecd4c61726923c1a9b77b6ab0aa0046c9e7fb2206042296817045376dee2c8ab1dabe08c7c3dfbf195b01275a085b + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.3": + version: 2.0.4 + resolution: "is-weakset@npm:2.0.4" + dependencies: + call-bound: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.6" + checksum: 10c0/6491eba08acb8dc9532da23cb226b7d0192ede0b88f16199e592e4769db0a077119c1f5d2283d1e0d16d739115f70046e887e477eb0e66cd90e1bb29f28ba647 + languageName: node + linkType: hard + "is-what@npm:^4.1.8": version: 4.1.16 resolution: "is-what@npm:4.1.16" @@ -7841,6 +8785,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: 10c0/4199f14a7a13da2177c66c31080008b7124331956f47bca57dd0b6ea9f11687aa25e565a2c7a2b519bc86988d10398e3049a1f5df13c9f6b7664154690ae79fd + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -7875,6 +8826,20 @@ __metadata: languageName: node linkType: hard +"iterator.prototype@npm:^1.1.5": + version: 1.1.5 + resolution: "iterator.prototype@npm:1.1.5" + dependencies: + define-data-property: "npm:^1.1.4" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.6" + get-proto: "npm:^1.0.0" + has-symbols: "npm:^1.1.0" + set-function-name: "npm:^2.0.2" + checksum: 10c0/f7a262808e1b41049ab55f1e9c29af7ec1025a000d243b83edf34ce2416eedd56079b117fa59376bb4a724110690f13aa8427f2ee29a09eec63a7e72367626d0 + languageName: node + linkType: hard + "jackspeak@npm:^3.1.2": version: 3.4.3 resolution: "jackspeak@npm:3.4.3" @@ -8037,6 +9002,18 @@ __metadata: languageName: node linkType: hard +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0": + version: 3.3.5 + resolution: "jsx-ast-utils@npm:3.3.5" + dependencies: + array-includes: "npm:^3.1.6" + array.prototype.flat: "npm:^1.3.1" + object.assign: "npm:^4.1.4" + object.values: "npm:^1.1.6" + checksum: 10c0/a32679e9cb55469cb6d8bbc863f7d631b2c98b7fc7bf172629261751a6e7bc8da6ae374ddb74d5fbd8b06cf0eb4572287b259813d92b36e384024ed35e4c13e1 + languageName: node + linkType: hard + "jwa@npm:^2.0.1": version: 2.0.1 resolution: "jwa@npm:2.0.1" @@ -8446,7 +9423,7 @@ __metadata: languageName: node linkType: hard -"loose-envify@npm:^1.1.0": +"loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" dependencies: @@ -8706,7 +9683,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:3.1.5, minimatch@npm:^3.1.1": +"minimatch@npm:3.1.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.5 resolution: "minimatch@npm:3.1.5" dependencies: @@ -8999,6 +9976,18 @@ __metadata: languageName: node linkType: hard +"node-exports-info@npm:^1.6.0": + version: 1.6.2 + resolution: "node-exports-info@npm:1.6.2" + dependencies: + array.prototype.flatmap: "npm:^1.3.3" + es-errors: "npm:^1.3.0" + object.entries: "npm:^1.1.9" + semver: "npm:^6.3.1" + checksum: 10c0/5278fab18e8c97f45275c51819c3078ca9488361e875bc01b680776a339d2fee1ca9c6fcfb972df14945a1b184cc9924a1d9ba87e90f6cb3422c7f5b6900f4bc + languageName: node + linkType: hard + "node-fetch@npm:^2.6.9": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" @@ -9197,7 +10186,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4": +"object-assign@npm:^4, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 @@ -9218,6 +10207,63 @@ __metadata: languageName: node linkType: hard +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: 10c0/b11f7ccdbc6d406d1f186cdadb9d54738e347b2692a14439ca5ac70c225fa6db46db809711b78589866d47b25fc3e8dee0b4c722ac751e11180f9380e3d8601d + languageName: node + linkType: hard + +"object.assign@npm:^4.1.4, object.assign@npm:^4.1.7": + version: 4.1.7 + resolution: "object.assign@npm:4.1.7" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + has-symbols: "npm:^1.1.0" + object-keys: "npm:^1.1.1" + checksum: 10c0/3b2732bd860567ea2579d1567525168de925a8d852638612846bd8082b3a1602b7b89b67b09913cbb5b9bd6e95923b2ae73580baa9d99cb4e990564e8cbf5ddc + languageName: node + linkType: hard + +"object.entries@npm:^1.1.9": + version: 1.1.9 + resolution: "object.entries@npm:1.1.9" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.1.1" + checksum: 10c0/d4b8c1e586650407da03370845f029aa14076caca4e4d4afadbc69cfb5b78035fd3ee7be417141abdb0258fa142e59b11923b4c44d8b1255b28f5ffcc50da7db + languageName: node + linkType: hard + +"object.fromentries@npm:^2.0.8": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/cd4327e6c3369cfa805deb4cbbe919bfb7d3aeebf0bcaba291bb568ea7169f8f8cdbcabe2f00b40db0c20cd20f08e11b5f3a5a36fb7dd3fe04850c50db3bf83b + languageName: node + linkType: hard + +"object.values@npm:^1.1.6, object.values@npm:^1.2.1": + version: 1.2.1 + resolution: "object.values@npm:1.2.1" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/3c47814fdc64842ae3d5a74bc9d06bdd8d21563c04d9939bf6716a9c00596a4ebc342552f8934013d1ec991c74e3671b26710a0c51815f0b603795605ab6b2c9 + languageName: node + linkType: hard + "obug@npm:^2.1.1": version: 2.1.3 resolution: "obug@npm:2.1.3" @@ -9317,6 +10363,18 @@ __metadata: languageName: node linkType: hard +"own-keys@npm:^1.0.1": + version: 1.0.2 + resolution: "own-keys@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.4" + get-intrinsic: "npm:^1.3.0" + object-keys: "npm:^1.1.1" + safe-push-apply: "npm:^1.0.0" + checksum: 10c0/84b0d9959475231166c3d4b9abd1b8af8042911e2e5625761eed980d1a1e4381cf52b34d907cae21ee8766c79de943f3cd85eba636149dee5e64cceff3ccdb78 + languageName: node + linkType: hard + "p-limit@npm:^3.0.1, p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" @@ -9598,6 +10656,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0, possible-typed-array-names@npm:^1.1.0": + version: 1.1.0 + resolution: "possible-typed-array-names@npm:1.1.0" + checksum: 10c0/c810983414142071da1d644662ce4caebce890203eb2bc7bf119f37f3fe5796226e117e6cca146b521921fa6531072674174a3325066ac66fce089a53e1e5196 + languageName: node + linkType: hard + "postcss-media-query-parser@npm:^0.2.3": version: 0.2.3 resolution: "postcss-media-query-parser@npm:0.2.3" @@ -9683,6 +10748,17 @@ __metadata: languageName: node linkType: hard +"prop-types@npm:^15.8.1": + version: 15.8.1 + resolution: "prop-types@npm:15.8.1" + dependencies: + loose-envify: "npm:^1.4.0" + object-assign: "npm:^4.1.1" + react-is: "npm:^16.13.1" + checksum: 10c0/59ece7ca2fb9838031d73a48d4becb9a7cc1ed10e610517c7d8f19a1e02fa47f7c27d557d8a5702bec3cfeccddc853579832b43f449e54635803f277b1c78077 + languageName: node + linkType: hard + "proper-lockfile@npm:^4.1.2": version: 4.1.2 resolution: "proper-lockfile@npm:4.1.2" @@ -9807,6 +10883,24 @@ __metadata: languageName: node linkType: hard +"react-dom@npm:^19.2.7": + version: 19.2.8 + resolution: "react-dom@npm:19.2.8" + dependencies: + scheduler: "npm:^0.27.0" + peerDependencies: + react: ^19.2.8 + checksum: 10c0/41ba2247b76f687fcfe5bbc99f514d6b851d8c8041c2f5ded36ed05bd7fdc5208cacbac9de51e3e6633e77f96f44cec9f0d4a5a55184dba4e00738f224439134 + languageName: node + linkType: hard + +"react-is@npm:^16.13.1": + version: 16.13.1 + resolution: "react-is@npm:16.13.1" + checksum: 10c0/33977da7a5f1a287936a0c85639fec6ca74f4f15ef1e59a6bc20338fc73dc69555381e211f7a3529b8150a1f71e4225525b41b60b52965bda53ce7d47377ada1 + languageName: node + linkType: hard + "react-remove-scroll-bar@npm:^2.3.7": version: 2.3.8 resolution: "react-remove-scroll-bar@npm:2.3.8" @@ -9877,6 +10971,13 @@ __metadata: languageName: node linkType: hard +"react@npm:^19.2.7": + version: 19.2.8 + resolution: "react@npm:19.2.8" + checksum: 10c0/5f86bdb56426652fd6d989d30a6f2e603c057272c47c9ca3a3fbe190a3a39ee9ccce937d63cfc039717abed1b8891d6a499134bc35311acc07eafdacd86537cd + languageName: node + linkType: hard + "readable-stream@npm:^3.1.1": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" @@ -9927,6 +11028,36 @@ __metadata: languageName: node linkType: hard +"reflect.getprototypeof@npm:^1.0.10, reflect.getprototypeof@npm:^1.0.9": + version: 1.0.10 + resolution: "reflect.getprototypeof@npm:1.0.10" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.9" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.7" + get-proto: "npm:^1.0.1" + which-builtin-type: "npm:^1.2.1" + checksum: 10c0/7facec28c8008876f8ab98e80b7b9cb4b1e9224353fd4756dda5f2a4ab0d30fa0a5074777c6df24e1e0af463a2697513b0a11e548d99cf52f21f7bc6ba48d3ac + languageName: node + linkType: hard + +"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": + version: 1.5.4 + resolution: "regexp.prototype.flags@npm:1.5.4" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-errors: "npm:^1.3.0" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + set-function-name: "npm:^2.0.2" + checksum: 10c0/83b88e6115b4af1c537f8dabf5c3744032cb875d63bc05c288b1b8c0ef37cbe55353f95d8ca817e8843806e3e150b118bc624e4279b24b4776b4198232735a77 + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -9955,6 +11086,22 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^2.0.0-next.5": + version: 2.0.0-next.7 + resolution: "resolve@npm:2.0.0-next.7" + dependencies: + es-errors: "npm:^1.3.0" + is-core-module: "npm:^2.16.2" + node-exports-info: "npm:^1.6.0" + object-keys: "npm:^1.1.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/8c6fa17ccdb826a3a52387ed8c42bf705dbc19d5494da52a86661b124b5b88fad5d8edbbb4434a1b563ecf7768368b7da9fb9489e20f36e02f7551a4ea87d707 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.1.6#optional!builtin": version: 1.22.12 resolution: "resolve@patch:resolve@npm%3A1.22.12#optional!builtin::version=1.22.12&hash=c3c19d" @@ -9969,6 +11116,22 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^2.0.0-next.5#optional!builtin": + version: 2.0.0-next.7 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.7#optional!builtin::version=2.0.0-next.7&hash=c3c19d" + dependencies: + es-errors: "npm:^1.3.0" + is-core-module: "npm:^2.16.2" + node-exports-info: "npm:^1.6.0" + object-keys: "npm:^1.1.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/6bb6f1d8a1789f7a5b4e35d950e76bc0ba632ff7d51fe86b6f34fb5f41e1ce0f7b884ec166828cfc0728ddffeaee49527711d752d12398297f90c51acd22195e + languageName: node + linkType: hard + "restore-cursor@npm:^5.0.0": version: 5.1.0 resolution: "restore-cursor@npm:5.1.0" @@ -10296,6 +11459,19 @@ __metadata: languageName: node linkType: hard +"safe-array-concat@npm:^1.1.3": + version: 1.1.4 + resolution: "safe-array-concat@npm:1.1.4" + dependencies: + call-bind: "npm:^1.0.9" + call-bound: "npm:^1.0.4" + get-intrinsic: "npm:^1.3.0" + has-symbols: "npm:^1.1.0" + isarray: "npm:^2.0.5" + checksum: 10c0/95fb4904ab1d9360a666fe5ba6d88f1c4a3a39682739e4512cff809fc6b5722a94bd95189211015bfb45859a7ffbc3340ea303ae22721c91c59e8946d310975a + languageName: node + linkType: hard + "safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -10303,6 +11479,27 @@ __metadata: languageName: node linkType: hard +"safe-push-apply@npm:^1.0.0": + version: 1.0.0 + resolution: "safe-push-apply@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + isarray: "npm:^2.0.5" + checksum: 10c0/831f1c9aae7436429e7862c7e46f847dfe490afac20d0ee61bae06108dbf5c745a0de3568ada30ccdd3eeb0864ca8331b2eef703abd69bfea0745b21fd320750 + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.1.0": + version: 1.1.0 + resolution: "safe-regex-test@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-regex: "npm:^1.2.1" + checksum: 10c0/f2c25281bbe5d39cddbbce7f86fca5ea9b3ce3354ea6cd7c81c31b006a5a9fff4286acc5450a3b9122c56c33eba69c56b9131ad751457b2b4a585825e6a10665 + languageName: node + linkType: hard + "safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -10369,6 +11566,13 @@ __metadata: languageName: node linkType: hard +"scheduler@npm:^0.27.0": + version: 0.27.0 + resolution: "scheduler@npm:0.27.0" + checksum: 10c0/4f03048cb05a3c8fddc45813052251eca00688f413a3cee236d984a161da28db28ba71bd11e7a3dd02f7af84ab28d39fb311431d3b3772fed557945beb00c452 + languageName: node + linkType: hard + "semver@npm:7.7.4": version: 7.7.4 resolution: "semver@npm:7.7.4" @@ -10405,6 +11609,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.3": + version: 7.8.5 + resolution: "semver@npm:7.8.5" + bin: + semver: bin/semver.js + checksum: 10c0/b1f3127a5be8125a94f37188b361c212466c292c6910adce3ec106cff5dc211ccaedc4739c11bb70fda59d6fc1f040a9bca289f4e093451521a2372e5231fe0c + languageName: node + linkType: hard + "send@npm:^1.1.0, send@npm:^1.2.0": version: 1.2.1 resolution: "send@npm:1.2.1" @@ -10451,6 +11664,43 @@ __metadata: languageName: node linkType: hard +"set-function-length@npm:^1.2.2": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.4" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.2" + checksum: 10c0/82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + functions-have-names: "npm:^1.2.3" + has-property-descriptors: "npm:^1.0.2" + checksum: 10c0/fce59f90696c450a8523e754abb305e2b8c73586452619c2bad5f7bf38c7b6b4651895c9db895679c5bef9554339cf3ef1c329b66ece3eda7255785fbe299316 + languageName: node + linkType: hard + +"set-proto@npm:^1.0.0": + version: 1.0.0 + resolution: "set-proto@npm:1.0.0" + dependencies: + dunder-proto: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/ca5c3ccbba479d07c30460e367e66337cec825560b11e8ba9c5ebe13a2a0d6021ae34eddf94ff3dfe17a3104dc1f191519cb6c48378b503e5c3f36393938776a + languageName: node + linkType: hard + "setprototypeof@npm:~1.2.0": version: 1.2.0 resolution: "setprototypeof@npm:1.2.0" @@ -10762,6 +12012,16 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.1.0": + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + internal-slot: "npm:^1.1.0" + checksum: 10c0/de4e45706bb4c0354a4b1122a2b8cc45a639e86206807ce0baf390ee9218d3ef181923fa4d2b67443367c491aa255c5fbaa64bb74648e3c5b48299928af86c09 + languageName: node + linkType: hard + "stream-events@npm:^1.0.5": version: 1.0.5 resolution: "stream-events@npm:1.0.5" @@ -10821,6 +12081,76 @@ __metadata: languageName: node linkType: hard +"string.prototype.matchall@npm:^4.0.12": + version: 4.0.12 + resolution: "string.prototype.matchall@npm:4.0.12" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.6" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.6" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + internal-slot: "npm:^1.1.0" + regexp.prototype.flags: "npm:^1.5.3" + set-function-name: "npm:^2.0.2" + side-channel: "npm:^1.1.0" + checksum: 10c0/1a53328ada73f4a77f1fdf1c79414700cf718d0a8ef6672af5603e709d26a24f2181208144aed7e858b1bcc1a0d08567a570abfb45567db4ae47637ed2c2f85c + languageName: node + linkType: hard + +"string.prototype.repeat@npm:^1.0.0": + version: 1.0.0 + resolution: "string.prototype.repeat@npm:1.0.0" + dependencies: + define-properties: "npm:^1.1.3" + es-abstract: "npm:^1.17.5" + checksum: 10c0/94c7978566cffa1327d470fd924366438af9b04b497c43a9805e476e2e908aa37a1fd34cc0911156c17556dab62159d12c7b92b3cc304c3e1281fe4c8e668f40 + languageName: node + linkType: hard + +"string.prototype.trim@npm:^1.2.10": + version: 1.2.11 + resolution: "string.prototype.trim@npm:1.2.11" + dependencies: + call-bind: "npm:^1.0.9" + call-bound: "npm:^1.0.4" + define-data-property: "npm:^1.1.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.24.2" + es-object-atoms: "npm:^1.1.2" + has-property-descriptors: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/b153cf8ed06db82ff40e27829e88e5c13f45eff9799f1d5707626e25989b488b059d6f5d57011e07f77745e28451e16735f295bc59c8ae146a4fd73a442366b0 + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.9": + version: 1.0.10 + resolution: "string.prototype.trimend@npm:1.0.10" + dependencies: + call-bind: "npm:^1.0.9" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.1.2" + checksum: 10c0/cc09233181769047a5330becfd5740fec5f0c8137886e7b553626788b00f75df9f34db1159bc52dbb7fc389b8ebb6e1dab44c8c9e31eb600039729a542013286 + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/d53af1899959e53c83b64a5fd120be93e067da740e7e75acb433849aa640782fb6c7d4cd5b84c954c84413745a3764df135a8afeb22908b86a835290788d8366 + languageName: node + linkType: hard + "string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" @@ -11057,6 +12387,15 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^2.5.0": + version: 2.5.0 + resolution: "ts-api-utils@npm:2.5.0" + peerDependencies: + typescript: ">=4.8.4" + checksum: 10c0/767849383c114e7f1971fa976b20e73ac28fd0c70d8d65c0004790bf4d8f89888c7e4cf6d5949f9c1beae9bc3c64835bef77bbe27fddf45a3c7b60cebcf85c8c + languageName: node + linkType: hard + "ts-node@npm:^10.9.2": version: 10.9.2 resolution: "ts-node@npm:10.9.2" @@ -11148,6 +12487,74 @@ __metadata: languageName: node linkType: hard +"typed-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-buffer@npm:1.0.3" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-typed-array: "npm:^1.1.14" + checksum: 10c0/1105071756eb248774bc71646bfe45b682efcad93b55532c6ffa4518969fb6241354e4aa62af679ae83899ec296d69ef88f1f3763657cdb3a4d29321f7b83079 + languageName: node + linkType: hard + +"typed-array-byte-length@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-byte-length@npm:1.0.3" + dependencies: + call-bind: "npm:^1.0.8" + for-each: "npm:^0.3.3" + gopd: "npm:^1.2.0" + has-proto: "npm:^1.2.0" + is-typed-array: "npm:^1.1.14" + checksum: 10c0/6ae083c6f0354f1fce18b90b243343b9982affd8d839c57bbd2c174a5d5dc71be9eb7019ffd12628a96a4815e7afa85d718d6f1e758615151d5f35df841ffb3e + languageName: node + linkType: hard + +"typed-array-byte-offset@npm:^1.0.4": + version: 1.0.4 + resolution: "typed-array-byte-offset@npm:1.0.4" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + for-each: "npm:^0.3.3" + gopd: "npm:^1.2.0" + has-proto: "npm:^1.2.0" + is-typed-array: "npm:^1.1.15" + reflect.getprototypeof: "npm:^1.0.9" + checksum: 10c0/3d805b050c0c33b51719ee52de17c1cd8e6a571abdf0fffb110e45e8dd87a657e8b56eee94b776b13006d3d347a0c18a730b903cf05293ab6d92e99ff8f77e53 + languageName: node + linkType: hard + +"typed-array-length@npm:^1.0.7": + version: 1.0.8 + resolution: "typed-array-length@npm:1.0.8" + dependencies: + call-bind: "npm:^1.0.9" + for-each: "npm:^0.3.5" + gopd: "npm:^1.2.0" + is-typed-array: "npm:^1.1.15" + possible-typed-array-names: "npm:^1.1.0" + reflect.getprototypeof: "npm:^1.0.10" + checksum: 10c0/5319f740fc426a3217182c2f7c87656acb0903e046de5a938e30167337d26abf1bb3ad4b32833a72521a4cc58223aec80627b38b357d0a3d5fd64881427e77ab + languageName: node + linkType: hard + +"typescript-eslint@npm:^8.61.0": + version: 8.67.0 + resolution: "typescript-eslint@npm:8.67.0" + dependencies: + "@typescript-eslint/eslint-plugin": "npm:8.67.0" + "@typescript-eslint/parser": "npm:8.67.0" + "@typescript-eslint/typescript-estree": "npm:8.67.0" + "@typescript-eslint/utils": "npm:8.67.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/6ec860f6763be8a5fabf143ff8b6d4e43b98be0c781afc4725eda578ba0e0cecfcc1f06bd1b56fcccc41fa3fc15e4661ec32120d28f2e7abe4953e91ee346de1 + languageName: node + linkType: hard + "typescript@npm:5.9.3": version: 5.9.3 resolution: "typescript@npm:5.9.3" @@ -11175,6 +12582,18 @@ __metadata: languageName: node linkType: hard +"unbox-primitive@npm:^1.1.0": + version: 1.1.0 + resolution: "unbox-primitive@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + has-bigints: "npm:^1.0.2" + has-symbols: "npm:^1.1.0" + which-boxed-primitive: "npm:^1.1.1" + checksum: 10c0/7dbd35ab02b0e05fe07136c72cb9355091242455473ec15057c11430129bab38b7b3624019b8778d02a881c13de44d63cd02d122ee782fb519e1de7775b5b982 + languageName: node + linkType: hard + "undici-types@npm:>=7.24.0 <7.24.7": version: 7.24.6 resolution: "undici-types@npm:7.24.6" @@ -11545,6 +12964,67 @@ __metadata: languageName: node linkType: hard +"which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1": + version: 1.1.1 + resolution: "which-boxed-primitive@npm:1.1.1" + dependencies: + is-bigint: "npm:^1.1.0" + is-boolean-object: "npm:^1.2.1" + is-number-object: "npm:^1.1.1" + is-string: "npm:^1.1.1" + is-symbol: "npm:^1.1.1" + checksum: 10c0/aceea8ede3b08dede7dce168f3883323f7c62272b49801716e8332ff750e7ae59a511ae088840bc6874f16c1b7fd296c05c949b0e5b357bfe3c431b98c417abe + languageName: node + linkType: hard + +"which-builtin-type@npm:^1.2.1": + version: 1.2.1 + resolution: "which-builtin-type@npm:1.2.1" + dependencies: + call-bound: "npm:^1.0.2" + function.prototype.name: "npm:^1.1.6" + has-tostringtag: "npm:^1.0.2" + is-async-function: "npm:^2.0.0" + is-date-object: "npm:^1.1.0" + is-finalizationregistry: "npm:^1.1.0" + is-generator-function: "npm:^1.0.10" + is-regex: "npm:^1.2.1" + is-weakref: "npm:^1.0.2" + isarray: "npm:^2.0.5" + which-boxed-primitive: "npm:^1.1.0" + which-collection: "npm:^1.0.2" + which-typed-array: "npm:^1.1.16" + checksum: 10c0/8dcf323c45e5c27887800df42fbe0431d0b66b1163849bb7d46b5a730ad6a96ee8bfe827d078303f825537844ebf20c02459de41239a0a9805e2fcb3cae0d471 + languageName: node + linkType: hard + +"which-collection@npm:^1.0.2": + version: 1.0.2 + resolution: "which-collection@npm:1.0.2" + dependencies: + is-map: "npm:^2.0.3" + is-set: "npm:^2.0.3" + is-weakmap: "npm:^2.0.2" + is-weakset: "npm:^2.0.3" + checksum: 10c0/3345fde20964525a04cdf7c4a96821f85f0cc198f1b2ecb4576e08096746d129eb133571998fe121c77782ac8f21cbd67745a3d35ce100d26d4e684c142ea1f2 + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19": + version: 1.1.22 + resolution: "which-typed-array@npm:1.1.22" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.9" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/e59db184a4e78b461fac3b05fafc1e7badbbedafbf04a967ee1de73717f1f9723a79699e7b5de71d449541cb5da8353efc01a4f8a72a152479850e54fa196c40 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -11814,7 +13294,7 @@ __metadata: languageName: node linkType: hard -"zod-to-json-schema@npm:^3.25.1": +"zod-to-json-schema@npm:^3.25.1, zod-to-json-schema@npm:^3.25.2": version: 3.25.2 resolution: "zod-to-json-schema@npm:3.25.2" peerDependencies: @@ -11823,6 +13303,15 @@ __metadata: languageName: node linkType: hard +"zod-validation-error@npm:^3.5.0 || ^4.0.0": + version: 4.0.2 + resolution: "zod-validation-error@npm:4.0.2" + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + checksum: 10c0/0ccfec48c46de1be440b719cd02044d4abb89ed0e14c13e637cd55bf29102f67ccdba373f25def0fc7130e5f15025be4d557a7edcc95d5a3811599aade689e1b + languageName: node + linkType: hard + "zod@npm:^3.25.76": version: 3.25.76 resolution: "zod@npm:3.25.76" diff --git a/specification/proposals/templates/README.md b/specification/proposals/templates/README.md new file mode 100644 index 0000000000..fd2ec6b2a1 --- /dev/null +++ b/specification/proposals/templates/README.md @@ -0,0 +1,737 @@ +# A2UI Template Specification + +## Abstract + +This document defines the authoritative specification for **A2UI Templates**. + +Templates provide a declarative, human-readable mechanism for authoring reusable UI subtrees in nested YAML or via native programmatic render functions. At generation time, an agent or Large Language Model (LLM) outputs compact, high-level template invocations (such as `UserProfile("u1", "Alice")` or `PayrollSummary("Eng", true)`). The backend SDK expands these invocations into standard, flat A2UI Basic Catalog components in a single synchronous pass before emitting standard A2UI protocol messages (`updateComponents`) to the client. + +This architecture achieves three fundamental objectives: + +1. **Human Readability**: Layouts are authored as clean, natural tree hierarchies in YAML or native language code, eliminating artificial IDs and flat array boilerplate. +2. **Token Efficiency & Context Optimization**: LLMs emit concise function-like signatures rather than verbose, deeply nested UI component trees, saving prompt context and generation tokens. +3. **Zero Client Overhead**: Client renderers (@a2ui/react, @a2ui/lit, @a2ui/angular, @a2ui/flutter) implement only standard Basic Catalog primitives (`Card`, `Column`, `Row`, `Text`, `Divider`, `Icon`, `Button`). No custom client widgets, dynamic code deployment, or renderer plugins are required. + +--- + +## 1. Architectural Overview & Execution Pipeline + +The template engine operates entirely server-side within the A2UI Agent SDK: + +```mermaid +flowchart TD + subgraph Stage1["1. Authoring & Registration"] + YAML["Static YAML Files
(multi-doc '---' & cross-references)"] + Dynamic["Dynamic Resolvers
(data-binding & programmatic AST)"] + end + + subgraph Stage2["2. Synthetic Catalog Generation"] + Proc["TemplateProcessor indexes templates
& synthesizes virtual Component Catalog"] + end + + subgraph Stage3["3. Model Prompt Generation & Inference"] + Prompt["PromptGenerator injects template signatures into prompt"] + LLM["LLM emits compact Express DSL / JSON
(e.g. root = TeamRoster(...))"] + end + + subgraph Stage4["4. Synchronous Template Expansion"] + Expand["TemplateProcessor unrolls loops,
substitutes params, assigns synthetic IDs"] + end + + subgraph Stage5["5. Standard A2UI Protocol Emission"] + Msg["Emits createSurface & updateComponents
(100% standard Basic Catalog primitives)"] + end + + subgraph Stage6["6. Client Renderer Execution"] + Client["Client renderers paint standard components
& bind reactive paths to client DataModel"] + end + + Stage1 --> Stage2 + Stage2 --> Stage3 + Stage3 --> Stage4 + Stage4 --> Stage5 + Stage5 --> Stage6 +``` + +--- + +## 2. Template Taxonomy + +A2UI supports three template authoring styles: + +### A. Declarative Static Templates (YAML) + +Declarative static templates define immutable layout trees authored in YAML files. All parameter placeholders are populated directly from arguments provided by the model or caller. + +```yaml +version: '0.1' +name: UserProfile +catalogs: + - 'https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json' +description: Standard identity card for team members. +parameters: + userId: + type: string + description: Unique user identifier. + userName: + type: string + description: Full name of the user. + role: + type: string + description: Position or title within the team. + default: Team Member + +layout: + component: Card + child: + component: Column + children: + - component: Icon + name: person + - component: Text + text: '{{ userName }}' + variant: h3 + - component: Text + text: '{{ role }}' + variant: caption +``` + +### B. Dynamic Templates: Data-Binding Mode (`resolver + layout`) + +Data-binding dynamic templates decouple public model parameters from private or live backend data. + +- **Public Surface**: The model only sees and outputs high-level lookup parameters (e.g. `employeeId: "emp_101"`). +- **Server Resolver**: At expansion time, a backend callback executes (e.g., querying an internal HR database or API) and produces a data dictionary. +- **Layout Inflation**: The resolved dictionary is merged with the caller's arguments and applied to an underlying static YAML layout. + +```python +# Server Registration +dynamic_salary = DynamicTemplate( + name="EmployeeSalaryCard", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + resolver=fetch_private_compensation, + layout=salary_yaml_layout, + description="Verified compensation card. Pass only employeeId.", +) +``` + +**Security Rationale**: Confidential numbers (e.g., executive salaries, PII) never enter the model's prompt context window or inference transcript. + +### C. Dynamic Templates: Programmatic Render Mode (`render_fn`) + +Programmatic dynamic templates bypass static YAML layouts entirely. Instead, a developer writes a native function in the host language (Python, Dart, etc.) that accepts parameters and directly returns a UI component tree. + +```python +def render_payroll_summary(department: str = "Engineering", includeBonus: bool = True) -> dict: + total_base = sum(e.salary for e in db.get_dept(department)) + total_bonus = sum(e.bonus for e in db.get_dept(department)) + + rows = [] + for emp in db.get_dept(department): + cols = [ + {"component": "Text", "text": emp.name, "variant": "body"}, + {"component": "Text", "text": f"${emp.salary:,}", "variant": "body"} + ] + if includeBonus: + cols.append({"component": "Text", "text": f"${emp.bonus:,}", "variant": "body"}) + rows.append({"component": "Row", "justify": "spaceBetween", "children": cols}) + + return { + "component": "Card", + "child": { + "component": "Column", + "children": [ + {"component": "Text", "text": f"Payroll Summary: {department}", "variant": "h2"}, + {"component": "Divider", "axis": "horizontal"}, + *rows, + {"component": "Divider", "axis": "horizontal"}, + {"component": "Text", "text": f"Total Budget: ${total_base + (total_bonus if includeBonus else 0):,}", "variant": "h3"} + ] + } + } + +payroll_tmpl = DynamicTemplate( + name="PayrollSummary", + catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"], + render=render_payroll_summary, + description="Dynamic payroll calculation matrix.", +) +``` + +**Advantages**: + +- Full host language power: arbitrary `for` loops, mathematical calculations, currency formatting, conditionals, and recursion. +- Polymorphic return values: accepts raw dictionaries/maps, dataclasses, or typesafe fluent builder objects (`Card()`, `Column()`). + +--- + +## 3. Loop Processing: Server Unrolling vs. Client Data Model + +A critical question in template design is: **When does the template engine unroll loops vs. when are collections handled by the client runtime?** + +### Comparison Matrix + +| Dimension | Server-Side Template Unrolling | Client-Side DataModel Loop | +| :--------------------- | :-------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | +| **Execution Point** | Backend SDK (`TemplateProcessor`) during template expansion. | Client Renderer runtime during paint/state updates. | +| **Data Source** | Static YAML literals, LLM invocation arguments, or server resolver output. | Client `DataModel` tree (e.g. `/session/cart/items`). | +| **Component Output** | Emits $N$ concrete Basic Catalog component nodes with synthesized unique IDs. | Emits a single repeater/collection component with a `DataBinding` path. | +| **Client Requirement** | Zero. Standard Basic Catalog renderers render it like any other static UI. | Requires client-side repeater support or SDK session re-renders. | +| **Dynamic Mutation** | Immutable once generated unless the agent emits a new `updateComponents` message. | Reactively re-renders when the client data model updates (e.g. via button events). | + +### Example 1: Server-Side Template Loop Unrolling + +A template author specifies a loop over a parameter array: + +#### Template Definition: + +```yaml +version: '0.1' +name: TeamGoalList +catalogs: + - 'https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json' +parameters: + teamName: {type: string} + goals: {type: array} +layout: + component: Card + child: + component: Column + children: + - component: Text + text: 'Objectives: {{ teamName }}' + variant: h2 + - component: Column + children: + loop: + param: goals + as: goal + item: + component: Row + justify: spaceBetween + children: + - component: Text + text: '{{ goal.title }}' + - component: Text + text: '{{ goal.priority }}' + variant: caption +``` + +#### Model Invocation: + +```text +root = TeamGoalList("Core Team", [ + {title: "Ship Protocol", priority: "High"}, + {title: "Write Tests", priority: "Medium"} +]) +``` + +#### Expanded Output Sent to Client: + +The engine unrolls the loop into concrete, synthetic child components: + +```json +[ + {"id": "root", "component": "Card", "child": "root_child_column"}, + { + "id": "root_child_column", + "component": "Column", + "children": ["root_child_column_children_0_text", "root_child_column_children_1_column"] + }, + { + "id": "root_child_column_children_0_text", + "component": "Text", + "text": "Objectives: Core Team", + "variant": "h2" + }, + { + "id": "root_child_column_children_1_column", + "component": "Column", + "children": [ + "root_child_column_children_1_column_goals_0_row", + "root_child_column_children_1_column_goals_1_row" + ] + }, + { + "id": "root_child_column_children_1_column_goals_0_row", + "component": "Row", + "justify": "spaceBetween", + "children": [ + "root_child_column_children_1_column_goals_0_row_children_0_text", + "root_child_column_children_1_column_goals_0_row_children_1_text" + ] + }, + { + "id": "root_child_column_children_1_column_goals_0_row_children_0_text", + "component": "Text", + "text": "Ship Protocol" + }, + { + "id": "root_child_column_children_1_column_goals_0_row_children_1_text", + "component": "Text", + "text": "High", + "variant": "caption" + }, + { + "id": "root_child_column_children_1_column_goals_1_row", + "component": "Row", + "justify": "spaceBetween", + "children": [ + "root_child_column_children_1_column_goals_1_row_children_0_text", + "root_child_column_children_1_column_goals_1_row_children_1_text" + ] + }, + { + "id": "root_child_column_children_1_column_goals_1_row_children_0_text", + "component": "Text", + "text": "Write Tests" + }, + { + "id": "root_child_column_children_1_column_goals_1_row_children_1_text", + "component": "Text", + "text": "Medium", + "variant": "caption" + } +] +``` + +--- + +## 4. Relationship to the A2UI Data Model + +Templates and the A2UI Data Model operate in complementary scopes: + +- **Templates** expand during **server-side inference / response formulation**. +- **Data Model** operates during **client-side runtime interaction & reactivity**. + +Templates interact with the client Data Model in three distinct patterns: + +### Pattern 1: Dynamic Path Plumbing (Path Interpolation) + +Templates can accept path prefixes or IDs as parameters, constructing reactive client-side binding paths: + +```yaml +version: '0.1' +name: BoundLiveMetric +catalogs: + - 'https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json' +parameters: + metricKey: {type: string} + label: {type: string} +layout: + component: Card + child: + component: Column + children: + - component: Text + text: '{{ label }}' + - component: Text + text: + path: '/system/metrics/{{ metricKey }}/currentValue' +``` + +**Expanded Output:** + +```json +{ + "id": "root_val", + "component": "Text", + "text": { + "path": "/system/metrics/cpuLoad/currentValue" + } +} +``` + +_Client Behavior_: The client renderer attaches a live subscriber to `/system/metrics/cpuLoad/currentValue`. When telemetry updates arrive via `updateDataModel`, the component automatically re-renders without server roundtrips. + +### Pattern 2: Direct `DataBinding` Passthrough + +When a template parameter has `type: object`, an agent or caller can pass an explicit A2UI binding object: + +#### Model Invocation: + +```text +root = MetricCard("Memory Used", {path: "/device/mem_percent"}) +``` + +#### Template Layout: + +```yaml +version: '0.1' +templateId: MetricCard +parameters: + title: {type: string} + val: {type: object} +layout: + component: Column + children: + - component: Text + text: '{{ title }}' + - component: Text + text: '{{ val }}' +``` + +**Expanded Output:** + +Because `{{ val }}` is an exact-match substitution, the dictionary type is strictly preserved: + +```json +{ + "component": "Text", + "text": {"path": "/device/mem_percent"} +} +``` + +### Pattern 3: Hardcoded Session State References + +Templates can embed constant client bindings for global session preferences: + +```yaml +layout: + component: Text + text: + path: '/session/currentUser/displayName' +``` + +--- + +## 5. Catalog Declaration, Validation & Multi-Catalog Disambiguation + +Templates must declare which catalog(s) they are authored against via the top-level `catalogs` property. + +### A. Mandatory Explicit Catalogs (No Basic Catalog Defaults) + +The template engine enforces strict decoupling from any specific catalog: + +- **No Hardcoded Defaults**: `TemplateProcessor` does not default to the Basic Catalog or any other specific catalog. +- **Explicit Catalog Requirement**: All catalogs required by registered templates must be explicitly provided to the processor upon initialization (e.g. via `catalogs={...}`). +- **Static Integrity Validation**: At registration time, the engine validates that every template's declared `catalogs` can be resolved against the provided catalog registry, and every primitive component referenced in `layout` exists within those catalogs with valid properties. + +### B. Prefix-Free Automatic Component Resolution + +In layout trees, authors write clean, standard component names (`Card`, `Text`, `HeartRateGraph`) without prefixes or namespace boilerplate: + +- **Unique Match (Standard Case)**: If component `Foo` exists in exactly one declared catalog, it automatically resolves to that catalog. +- **Name Collision**: If two declared catalogs define `Foo`, the author can specify `catalogId` on that specific component in the layout to disambiguate. If omitted, the engine raises an `AmbiguousComponentError`. +- **Unknown Component**: If `Foo` is found in zero declared catalogs, the engine raises an `UnknownComponentError`. + +### C. Protocol Version Rules: v0.9 vs. v1.0 + +The template engine tailors its expansion and output depending on the target protocol version: + +| Dimension | A2UI v0.9 / v0.9.1 Behavior | A2UI v1.0 Behavior | +| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------- | +| **Surface Catalog Model** | Single catalog per surface (`createSurface.catalogId` required). | Mixable catalogs (`createSurface.catalogId` optional default). | +| **Multi-Catalog Templates** | **Rejected**: If a template declares multiple catalogs, unrolling onto a v0.9 surface raises `CatalogCompatibilityError`. | **Supported**: Expanded seamlessly across mixed catalogs. | +| **Surface Validation** | Template's resolved catalog MUST match `createSurface.catalogId`. | All catalogs referenced by the template must be present in surface `supportedCatalogIds`. | +| **Expanded Component Output** | `catalogId` is **never** emitted on expanded component dicts (illegal property in v0.9). | `catalogId` is automatically injected on any component whose catalog differs from surface default. | + +--- + +## 6. Sub-Template Imports & Global Identity + +Templates decouple their local invocation name from their optional global identity: + +- **`name`** (Required): Component tag name used in layout trees and LLM prompts (`^[A-Za-z][A-Za-z0-9_]*$`). `templateId` is accepted as a backwards-compatible alias. +- **`id`** (Optional): Globally unique URI or URN string (e.g. `https://company.org/templates/card/v1.json`) for package distribution and version pinning. +- **`imports`** (Optional): List of global template IDs, or dictionary mapping local aliases to global template IDs (`imports: { VendorCard: "https://vendor.com/card.json" }`). + +### Usage Tiers + +1. **Tier 1 (Simple / Local)**: Templates omit `id` and `imports`. Sibling templates in the same file or registry resolve each other directly by `name`. +2. **Tier 2 (Modular / Distributed)**: Templates declare `id` and import external sub-templates by `id` or alias via `imports`. + +--- + +## 7. The Synthetic Catalog System + +To make templates discoverable and invoke-able by LLMs, the backend converts registered templates into a **Synthetic Component Catalog**. + +### The Catalog Synthesis Algorithm + +When `TemplateProcessor(templates, catalogs)` is initialized: + +1. It indexes all provided catalogs. +2. For each registered `StaticTemplate` and `DynamicTemplate`: + - It registers a new component definition under `components[template.name]`. + - It maps semantic parameter definitions to JSON schema properties: + - `string` $\rightarrow$ `{"type": "string"}` + - `number` / `integer` $\rightarrow$ `{"type": "number"}` / `{"type": "integer"}` + - `boolean` $\rightarrow$ `{"type": "boolean"}` + - `enum` $\rightarrow$ `{"type": "string", "enum": param.values}` + - `object` $\rightarrow$ `{"type": "object", "properties": ...}` + - `array` $\rightarrow$ `{"type": "array", "items": ...}` + - `child` $\rightarrow$ `{"$ref": "#/$defs/ComponentReference"}` + - `children` $\rightarrow$ `{"$ref": "#/$defs/ComponentReferenceList"}` + - It copies the `description` to provide context for the model. +3. The synthetic catalog is passed to `PromptGenerator` (Express, Elemental, Atom, Direct JSON), which automatically writes the syntax rules and documentation into the system prompt. + +### Surface Isolation Boundary + +```mermaid +flowchart LR + Agent["LLM Agent"] <--> SyntheticCatalog["Synthetic Catalog
(Templates + Primitives)"] + SyntheticCatalog <--> Processor["TemplateProcessor"] + Processor -->|"Synchronously expands
to flat primitives"| Client["Client Renderer
(Basic Catalog)"] +``` + +The synthetic catalog is an ephemeral compile-time construct. The client renderer is completely unaware that templates exist. + +--- + +## 8. Parameter Expressions & Substitution Engine + +The template substitution engine replaces expressions according to strict typing and evaluation rules using standard double-curly Mustache syntax (`{{ param }}`). + +### Rule 1: Exact Match Substitution (Type Preserving) + +If a string field value exactly matches the parameter token regex `^\{\{\s*([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*)\s*\}\}$`: + +- The entire field is replaced by the native runtime value of the parameter. +- **Integers remain integers**: `level: "{{ userLevel }}"` $\rightarrow$ `level: 4` (not `"4"`). +- **Booleans remain booleans**: `checked: "{{ isActive }}"` $\rightarrow$ `checked: true` (not `"true"`). +- **Objects and Arrays remain native structures**: `items: "{{ memberList }}"` $\rightarrow$ `items: [{...}, {...}]`. + +### Rule 2: Embedded String Interpolation + +If a parameter token appears alongside other characters (e.g. `"Hello, {{ userName }}!"` or `"{{ dept }} - {{ code }}"`): + +- All tokens matching `\{\{\s*([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*)\s*\}\}` are replaced by their string representations. +- Evaluates to a native string. + +### Rule 3: Client DataModel Disambiguation (`formatString`) + +Because template substitutions use double curlies `{{ ... }}`, client-side reactive expressions and data-model bindings in `formatString` (e.g. `${/user/name}`) pass through completely untouched without requiring escaping: + +```yaml +component: Text +text: + call: formatString + args: + value: 'Hello, ${/user/name}! Your team is {{ teamName }}.' +``` + +During server-side template expansion: + +- `{{ teamName }}` is resolved server-side and replaced with `"Engineering"`. +- `${/user/name}` is preserved verbatim and emitted directly to the client renderer for reactive data-binding. + +### Rule 4: Deep Dot-Notation for Structured Objects + +Templates natively support deep dot-notation paths on object parameters: + +#### Invocation: + +```text +root = AccountCard({ + account: { + id: "acc_99", + profile: {name: "Alpha Corp", tier: "Enterprise"} + } +}) +``` + +#### Template Layout: + +```yaml +version: '0.1' +templateId: AccountCard +parameters: + account: {type: object} +layout: + component: Card + child: + component: Text + text: '{{ account.profile.name }} ({{ account.profile.tier }})' +``` + +**Expanded Output:** + +```json +{ + "component": "Text", + "text": "Alpha Corp (Enterprise)" +} +``` + +### Rule 5: String Format AST Expressions + +For complex string formatting across multiple languages: + +```yaml +format: 'Level {lvl} ({pts} points)' +args: + lvl: '{{ level }}' + pts: '{{ experiencePoints }}' +``` + +### Rule 6: Token Escaping + +To emit a literal `{{ foo }}` string without triggering parameter substitution, escape the opening curly braces with a backslash: + +- `\{{ keep_literal }}` $\rightarrow$ evaluates to literal `"{{ keep_literal }}"`. + +### Rule 7: Missing Values & Defaults + +- If an argument is omitted but has a declared `default` in its parameter schema, the `default` is used. +- If an argument is omitted, has no `default`, and is not required: the property is omitted from the synthesized component (it is not emitted as `null`). +- If an argument is required and missing: expansion raises a `TemplateParameterError`. + +--- + +## 9. Deterministic Synthetic ID Generation Algorithm + +To guarantee collision-free component IDs across multiple template instances and deep nesting, implementations in all languages (Python, Dart, TypeScript) must implement the following deterministic naming rules: + +### ID Synthesis Specification + +``` +Let instance_id be the ID passed to expand_template(instance_id, template_id, params) + +1. Root Node: + id = instance_id + +2. Single Child Slot (e.g. card.child): + id = "{parent_id}_{slot_name}_{normalized_type}" + (where normalized_type is the component or template type converted to lowercase) + Example: "root_child_column" + +3. Multi-Child List Slot (e.g. column.children[i]): + id = "{parent_id}_{slot_name}_{i}_{normalized_type}" + (where normalized_type is the component or template type converted to lowercase) + Example: "root_children_0_text", "root_children_1_button" + +4. Loop Iteration Item (e.g. loop over param "members", iteration index i): + id = "{parent_id}_{param_name}_{i}_{normalized_type}" + (where normalized_type is the component or template type converted to lowercase) + Example: "team_col_members_0_userprofile" + +5. Authored Explicit IDs: + If a component in the template specifies an explicit id (e.g. id: "hero_img"): + id = "{instance_id}_{authored_id}" + Example: "my_card_hero_img" +``` + +This guarantees that two instances of the same template (`card_1` and `card_2`) on the same surface will never produce colliding component IDs. + +--- + +## 10. Higher-Order Container Templates (`child` and `children` Slots) + +Templates can define structural containers that receive caller-provided components. + +### Example: `SectionCard` Container + +```yaml +version: '0.1' +name: SectionCard +catalogs: + - 'https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json' +parameters: + title: {type: string} + headerAction: {type: child} + children: {type: children} + +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: '{{ title }}' + variant: h2 + - component: Column + children: '{{ headerAction }}' + - component: Divider + axis: horizontal + - component: Column + children: '{{ children }}' +``` + +#### Model Invocation: + +```text +root = SectionCard( + "Project Status", + Button("Refresh", {action: "reload"}), + [ + Text("Phase 1: Complete"), + Text("Phase 2: In Progress") + ] +) +``` + +The template engine replaces `{{ headerAction }}` with the synthesized single child node, and concatenates the `{{ children }}` component list into the body column. + +--- + +## 11. Error Handling, Cycle Guards & Safety + +### Recursion & Circular Reference Detection + +Templates can invoke other templates. However, circular references in template definitions (`A` invokes `B`, which invokes `A`) must be caught immediately to prevent stack overflow. + +- **Definition Cycles vs. Instance Nesting**: + - **Definition Cycles (Prohibited)**: The cycle guard specifically tracks the chain of template _definitions_ being expanded (`TemplateA -> TemplateB -> TemplateA`). If a template definition unconditionally references itself or another template in a cycle, expansion terminates with `TemplateCycleError`. + - **Instance Nesting (Fully Supported)**: When a caller passes an instance of a template as an argument into another template's `child` or `children` slot (for example, a `Card` template containing a `Carousel` template whose items are other `Card` template instances), this is standard, safe hierarchical composition. Each instance receives a unique synthetic ID and is bounded by caller input. +- **Call Stack Tracking**: The `TemplateProcessor` maintains an active `_call_stack: Set[str]` of template definition names currently being evaluated. +- **Cycle Guard**: Before expanding any template definition, if `template_name in _call_stack`, expansion terminates immediately with `TemplateCycleError: Circular template reference detected: A -> B -> A`. +- **Maximum Depth Guard**: An absolute limit (`MAX_EXPANSION_DEPTH = 50`) enforces termination even in deeply nested or runaway recursion. + +### Standard Error Hierarchy + +1. `TemplateNotFoundError`: Attempted to expand a template `name` or `id` not present in the registry. +2. `TemplateParameterError`: Missing required parameter or invalid parameter type. +3. `TemplateCycleError`: Circular reference detected during expansion. +4. `TemplateDepthExceededError`: Expansion exceeded maximum recursion depth. +5. `TemplateResolverError`: Exception raised by a dynamic template resolver function. +6. `CatalogCompatibilityError`: Declared catalogs incompatible with target surface (e.g. multi-catalog template on v0.9 surface). +7. `AmbiguousComponentError`: Component exists in multiple declared catalogs without disambiguation. +8. `UnknownComponentError`: Component not found in any declared catalog. + +--- + +## 12. Multi-Document YAML Streams (`---`) + +To streamline template maintenance, multiple templates can be defined in a single `.yaml` file separated by `---`: + +- **Order Independent**: Templates can reference templates declared later in the file (forward references). +- **Batch Registration**: Loading a multi-doc file registers all defined templates atomically into the `TemplateProcessor`. + +--- + +## 13. Template Versioning & Schema Evolution + +To ensure robust backward compatibility as template syntax and AST features evolve across future protocol releases, every template definition must declare a top-level `version` field. + +### Versioning Rules: + +1. **Mandatory Version Field**: Every YAML document (and each document within multi-doc streams separated by `---`) must include `version: "0.1"`. +2. **Strict Schema Validation**: The canonical JSON schema enforces `"version": {"type": "string", "const": "0.1"}`. Attempting to inflate a template with an unsupported version raises an explicit `TemplateVersionError` / `ValueError`. +3. **Future Extensibility**: As new template language capabilities are standardized (e.g. conditional slot rendering, client-expanded template directives), new version identifiers (such as `"0.2"` or `"1.0"`) allow engines to select the appropriate parser/evaluator without breaking legacy templates. + +--- + +## 14. Conformance Checklist for SDK Implementations + +An implementation of the A2UI Template Engine in any language (Python, Dart, TypeScript, Go, etc.) is conformant if and only if it satisfies the following test requirements: + +- [ ] **Template Versioning**: Validates that all ingested templates declare `version: "0.1"` and rejects unsupported version strings. +- [ ] **Catalog Decoupling**: Does not default to the Basic Catalog; requires catalogs to be passed explicitly and validates all components against them. +- [ ] **Catalog Resolution & Disambiguation**: Resolves components across declared catalogs without prefixes; handles collision disambiguation via component-level `catalogId`. +- [ ] **Protocol Version Output Rules**: Enforces v0.9 single-catalog surface constraints (stripping component `catalogId`); supports v1.0 mixable catalogs with automatic `catalogId` stamping. +- [ ] **Sub-Template Imports**: Supports Tier 1 (local by `name`) and Tier 2 (modular by `id` with `imports` list and alias dictionary). +- [ ] **Multi-Document Ingestion**: Parses single-doc and multi-doc (`---`) YAML streams. +- [ ] **Forward Reference Resolution**: Expands templates regardless of registration order. +- [ ] **Strict Native Type Preservation**: Exact `{{ param }}` substitutions preserve `int`, `float`, `bool`, `dict`, and `list` types. +- [ ] **Dot-Notation Path Traversal**: Resolves arbitrary depth paths (e.g. `{{ user.details.address.zip }}`). +- [ ] **Inline and Named Loop Expansion**: Accurately unrolls arrays into synthesized component subtrees with indexed child IDs. +- [ ] **Deterministic Synthetic IDs**: Emits canonical hierarchical IDs matching the `{parent}_{slot}_{index}_{type}` specification. +- [ ] **Two-Way DataModel Passthrough**: Preserves `{path: "..."}` dictionary bindings without string conversion. +- [ ] **Cycle and Recursion Safeguards**: Catches circular references and depth violations with explicit exceptions. +- [ ] **Synthetic Catalog Generation**: Generates valid A2UI JSON schema catalogs matching input parameter definitions. +- [ ] **Polymorphic Dynamic Templates**: Supports both resolver-based static bindings and programmatic render functions. diff --git a/specification/proposals/templates/examples/basic_cards.yaml b/specification/proposals/templates/examples/basic_cards.yaml new file mode 100644 index 0000000000..9b03872d3a --- /dev/null +++ b/specification/proposals/templates/examples/basic_cards.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: BasicUserProfile +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Standard identity card for team members. +parameters: + userId: + type: string + description: Unique user identifier. + userName: + type: string + description: Full name of the user. + role: + type: string + description: Position or title within the team. + default: Team Member + +layout: + component: Card + child: + component: Column + align: center + children: + - component: Icon + name: person + - component: Text + text: "{{ userName }}" + variant: h3 + - component: Text + text: "{{ role }}" + variant: caption + +sampleData: + userId: usr_101 + userName: Alice Smith + role: Lead Architect + +--- +version: "0.1" +name: BasicMetricCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Metric display card supporting both literal values and dynamic data model bindings. +parameters: + title: + type: string + description: Metric title. + metricValue: + type: object + description: "Literal value or reactive DataBinding object (e.g. {path: '/telemetry/cpu'})." + status: + type: enum + values: ["normal", "warning", "critical"] + default: "normal" + +layout: + component: Card + child: + component: Column + children: + - component: Text + text: "{{ title }}" + variant: caption + - component: Text + text: "{{ metricValue }}" + variant: h1 + +sampleData: + title: CPU Load + metricValue: + path: /system/metrics/cpuLoad + status: normal diff --git a/specification/proposals/templates/examples/feedback_item.yaml b/specification/proposals/templates/examples/feedback_item.yaml new file mode 100644 index 0000000000..74796a58eb --- /dev/null +++ b/specification/proposals/templates/examples/feedback_item.yaml @@ -0,0 +1,62 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: FeedbackItem +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Card showing feedback note, author, and rating. + +parameters: + author: + type: string + title: Author Name + description: The name of the colleague or customer providing feedback. + note: + type: string + title: Feedback Note + description: The written feedback or retrospective comment. + rating: + type: number + title: Feedback Rating + description: Score from 1 to 5. + minimum: 1 + maximum: 5 + default: 5 + +layout: + component: Card + child: + component: Column + children: + - component: Text + text: "{{ note }}" + variant: body + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ author }}" + variant: caption + - component: Text + text: "Rating: {{ rating }}/5" + variant: caption + +sampleData: + author: Dr. Elena Vance + note: A2UI templates are fast and easy to compose. + rating: 5 diff --git a/specification/proposals/templates/examples/goal_item.yaml b/specification/proposals/templates/examples/goal_item.yaml new file mode 100644 index 0000000000..f1be35d83f --- /dev/null +++ b/specification/proposals/templates/examples/goal_item.yaml @@ -0,0 +1,75 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: GoalItem +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Card showing an individual objective with priority, title, target date, and action button. + +parameters: + title: + type: string + title: Goal Title + description: Summary title of the objective. + priority: + type: enum + title: Priority Level + description: Urgency rating for the objective. + values: + - High + - Medium + - Low + default: Medium + targetDate: + type: string + title: Target Date + description: Target completion date in YYYY-MM-DD format. + default: "2026-12-31" + +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "Priority: {{ priority }}" + variant: caption + - component: Icon + name: star + - component: Text + text: "{{ title }}" + variant: h4 + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "Due: {{ targetDate }}" + variant: caption + - component: Button + child: + component: Text + text: View Details + +sampleData: + title: Launch A2UI SDK v1.0 + priority: High + targetDate: "2026-09-30" diff --git a/specification/proposals/templates/examples/nested_lists.yaml b/specification/proposals/templates/examples/nested_lists.yaml new file mode 100644 index 0000000000..8736a150b8 --- /dev/null +++ b/specification/proposals/templates/examples/nested_lists.yaml @@ -0,0 +1,103 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: NestedTeamRoster +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Team directory roster with styled header banner and nested team lists. +parameters: + directoryTitle: + type: string + description: Title text for the team directory. + teams: + type: array + description: List of team objects or TeamCard children. + default: [] + +layout: + component: Column + children: + - component: Text + text: "{{ directoryTitle }}" + variant: h1 + - component: Divider + axis: horizontal + - component: Column + children: + loop: + param: teams + template: NestedTeamCard + +sampleData: + directoryTitle: Global Engineering Directory + teams: + - teamName: Core Architecture + members: + - userId: u1 + userName: Dr. Elena Vance + role: Principal Architect + - userId: u2 + userName: Marcus Vance + role: Streaming Lead + +--- +version: "0.1" +name: NestedTeamCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Team container card displaying member cards. +parameters: + teamName: + type: string + description: Name of the engineering team. + members: + type: array + description: List of team members. + default: [] + +layout: + component: Card + child: + component: Column + children: + - component: Text + text: "{{ teamName }}" + variant: h2 + - component: Divider + axis: horizontal + - component: Column + children: + loop: + param: members + as: member + item: + component: Row + justify: spaceBetween + children: + - component: Text + text: "{{ member.userName }}" + - component: Text + text: "{{ member.role }}" + variant: caption + +sampleData: + teamName: Core Architecture + members: + - userId: u1 + userName: Dr. Elena Vance + role: Principal Architect + - userId: u2 + userName: Marcus Vance + role: Streaming Lead diff --git a/specification/proposals/templates/examples/salary_card.yaml b/specification/proposals/templates/examples/salary_card.yaml new file mode 100644 index 0000000000..167dc967b4 --- /dev/null +++ b/specification/proposals/templates/examples/salary_card.yaml @@ -0,0 +1,132 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: SalaryCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Layout card for employee compensation package with security verification badge. + +parameters: + employeeName: + type: string + title: Employee Full Name + description: Full name of the verified employee. + role: + type: string + title: Job Title + description: Official company role. + baseSalary: + type: string + title: Base Salary + description: Annual base compensation. + annualBonus: + type: string + title: Annual Bonus + description: Target annual incentive bonus. + equity: + type: string + title: Equity Grants + description: Stock units or RSU package. + clearanceLevel: + type: string + title: Security Clearance + description: Confidentiality level. + default: "Level 4 - Confidential" + verifiedAt: + type: string + title: Verification Date + description: Timestamp of record retrieval. + default: "2026-08-13" + +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Row + align: center + children: + - component: Icon + name: lock + - component: Text + text: "Verified Compensation" + variant: caption + - component: Text + text: "{{ clearanceLevel }}" + variant: caption + - component: Column + children: + - component: Text + text: "{{ employeeName }}" + variant: h3 + id: name_txt + - component: Text + text: "{{ role }}" + variant: body + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + children: + - component: Column + children: + - component: Text + text: "Base Salary" + variant: caption + - component: Text + text: "{{ baseSalary }}" + variant: h4 + id: sal_val + - component: Column + children: + - component: Text + text: "Annual Bonus" + variant: caption + - component: Text + text: "{{ annualBonus }}" + variant: h4 + - component: Column + children: + - component: Text + text: "Equity Grants" + variant: caption + - component: Text + text: "{{ equity }}" + variant: h4 + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "🔒 Fetched live from secure HR database" + variant: caption + - component: Text + text: "Verified: {{ verifiedAt }}" + variant: caption + +sampleData: + employeeName: Dr. Elena Vance + role: Principal Systems Architect + baseSalary: "$215,000" + annualBonus: "$45,000" + equity: "3,500 RSUs" + clearanceLevel: "Level 5 - Confidential" + verifiedAt: "2026-08-13" diff --git a/specification/proposals/templates/examples/section_card.yaml b/specification/proposals/templates/examples/section_card.yaml new file mode 100644 index 0000000000..b64d9aad4f --- /dev/null +++ b/specification/proposals/templates/examples/section_card.yaml @@ -0,0 +1,68 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: SectionCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Standard container card with title, description, optional action, and child components. + +parameters: + title: + type: string + title: Section Title + description: Heading text displayed at the top of the section card. + description: + type: string + title: Section Description + description: Subordinate descriptive text beneath the title. + default: "" + headerAction: + type: child + title: Header Action Component + description: Single child component placed in the right side of the header. + children: + type: children + title: Section Children + description: Child component IDs rendered in the section body. + default: [] + +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ title }}" + variant: h3 + - component: Column + id: action_slot + children: "{{ headerAction }}" + - component: Text + text: "{{ description }}" + variant: caption + - component: Divider + axis: horizontal + - component: Column + id: body_container + children: "{{ children }}" + +sampleData: + title: Protocol Overview + description: High-level summary of the streaming architecture. + children: [] diff --git a/specification/proposals/templates/examples/slot_composition.yaml b/specification/proposals/templates/examples/slot_composition.yaml new file mode 100644 index 0000000000..51cba60a03 --- /dev/null +++ b/specification/proposals/templates/examples/slot_composition.yaml @@ -0,0 +1,97 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: CompositeSectionCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Collapsible or styled content section card with title, custom header action slot, and children slot. +parameters: + title: + type: string + description: Section header title. + headerAction: + type: child + description: Single child component placed in the right side of the header. + children: + type: children + description: Content components contained within the section body. + default: [] + +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ title }}" + variant: h2 + - component: Column + children: "{{ headerAction }}" + - component: Divider + axis: horizontal + - component: Column + children: "{{ children }}" + +sampleData: + title: Project Milestones + headerAction: + component: Button + text: Refresh + children: [] + +--- +version: "0.1" +name: TwoColumnLayoutWithHeader +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Responsive two-column dashboard grid with a hero header, left column, and right column. +parameters: + headerChild: + type: child + description: Component rendered in the full-width header slot. + leftChildren: + type: children + description: Components rendered in the left column. + rightChildren: + type: children + description: Components rendered in the right column. + +layout: + component: Column + children: + - component: Column + children: "{{ headerChild }}" + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + align: start + children: + - component: Column + children: "{{ leftChildren }}" + - component: Column + children: "{{ rightChildren }}" + +sampleData: + headerChild: + component: Text + text: Executive Operations Dashboard + variant: h1 + leftChildren: [] + rightChildren: [] diff --git a/specification/proposals/templates/examples/team_card.yaml b/specification/proposals/templates/examples/team_card.yaml new file mode 100644 index 0000000000..d1ec4d163b --- /dev/null +++ b/specification/proposals/templates/examples/team_card.yaml @@ -0,0 +1,84 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: TeamCard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Card showing team header and unrolled member cards. + +parameters: + teamName: + type: string + title: Team Name + description: The display name of the team. + members: + type: array + title: Team Members List + description: Array of team member objects. + items: + type: object + title: Team Member + properties: + userId: + type: string + title: User ID + description: Unique identifier of the user. + userName: + type: string + title: User Name + description: Full name of the user. + role: + type: string + title: Role Name + description: Role or title of the user. + default: Member + required: + - userId + - userName + +layout: + component: Card + child: + component: Column + children: + - component: Row + justify: spaceBetween + align: center + children: + - component: Text + text: "{{ teamName }}" + variant: h3 + - component: Icon + name: person + - component: Divider + axis: horizontal + - component: Column + children: + loop: + param: members + template: UserProfile + +sampleData: + teamName: Antigravity Devs + members: + - userId: usr_101 + userName: Alice Smith + role: Lead Architect + - userId: usr_102 + userName: Bob Jones + role: Senior Engineer + - userId: usr_103 + userName: Charlie Brown + role: Product Manager diff --git a/specification/proposals/templates/examples/team_feedback_board.yaml b/specification/proposals/templates/examples/team_feedback_board.yaml new file mode 100644 index 0000000000..544f0dfcaa --- /dev/null +++ b/specification/proposals/templates/examples/team_feedback_board.yaml @@ -0,0 +1,80 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: TeamFeedbackBoard +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Feedback board showing team header and feedback items. + +parameters: + teamName: + type: string + title: Team Name + description: The display name of the team whose feedback board is being rendered. + feedbacks: + type: array + title: Feedbacks List + description: Array of feedback objects with author, note, and rating. + items: + type: object + title: Feedback Review + properties: + author: + type: string + title: Author Name + description: Full name of the person giving feedback. + note: + type: string + title: Feedback Note + description: Textual comment or recommendation. + rating: + type: number + title: Rating Score + minimum: 1 + maximum: 5 + default: 5 + required: + - author + - note + +layout: + component: Column + children: + - component: Card + child: + component: Row + align: center + children: + - component: Icon + name: mail + - component: Text + text: "Feedback & Retrospective: {{ teamName }}" + variant: h2 + - component: Column + id: feedbacks_container + children: + loop: + param: feedbacks + template: FeedbackItem + +sampleData: + teamName: Streaming & Protocols Guild + feedbacks: + - author: Dr. Elena Vance + note: Splitting createSurface and updateComponents cleanly unblocked sequential stream processing. + rating: 5 + - author: Marcus Vance + note: Unrolling nested lists statically in Python enables instant frontend mounting with zero runtime recursion. + rating: 5 diff --git a/specification/proposals/templates/examples/team_goal_list.yaml b/specification/proposals/templates/examples/team_goal_list.yaml new file mode 100644 index 0000000000..db6241144a --- /dev/null +++ b/specification/proposals/templates/examples/team_goal_list.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: TeamGoalList +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: List of team goals with header banner. + +parameters: + teamName: + type: string + title: Team Name + description: The display name of the team whose goals are being listed. + goals: + type: array + title: Goals List + description: Array of goal objects with title, priority, and targetDate. + items: + type: object + title: Goal Definition + properties: + title: + type: string + title: Goal Title + description: Summary title of the objective + priority: + type: enum + title: Priority Level + values: + - High + - Medium + - Low + default: Medium + targetDate: + type: string + title: Target Date + description: Target completion date (YYYY-MM-DD) + required: + - title + +layout: + component: Column + children: + - component: Card + child: + component: Row + align: center + children: + - component: Icon + name: star + - component: Text + text: "Strategic Objectives: {{ teamName }}" + variant: h2 + - component: Column + id: goals_container + children: + loop: + param: goals + template: GoalItem + +sampleData: + teamName: A2UI Core Team + goals: + - title: Implement bidirectional child/children container resolution + priority: High + targetDate: "2026-07-15" + - title: Upgrade all templates to standard Basic Catalog components + priority: High + targetDate: "2026-07-10" diff --git a/specification/proposals/templates/examples/team_member_knowledge_panel.yaml b/specification/proposals/templates/examples/team_member_knowledge_panel.yaml new file mode 100644 index 0000000000..fad8d61bdf --- /dev/null +++ b/specification/proposals/templates/examples/team_member_knowledge_panel.yaml @@ -0,0 +1,94 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: TeamMemberKnowledgePanel +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Card showing competency panel with user experience years and completed task count. + +parameters: + userName: + type: string + title: User Display Name + description: The full name of the team member. + role: + type: string + title: Role Name + description: The operational role of the team member. + experienceYears: + type: integer + title: Years of Experience + description: The number of years of professional experience. + minimum: 0 + completedTasks: + type: integer + title: Completed Tasks Count + description: The count of completed tasks or tickets. + minimum: 0 + +layout: + component: Card + child: + component: Column + children: + - component: Row + align: center + children: + - component: Icon + name: check + - component: Text + text: "Competency: {{ userName }}" + variant: h4 + - component: Divider + axis: horizontal + - component: Row + justify: spaceBetween + children: + - component: Column + align: center + children: + - component: Text + text: Role + variant: caption + - component: Text + text: "{{ role }}" + variant: body + - component: Column + align: center + children: + - component: Text + text: Experience + variant: caption + - component: Text + text: "{{ experienceYears }} Yrs" + variant: body + - component: Column + align: center + children: + - component: Text + text: Tasks + variant: caption + - component: Text + text: "{{ completedTasks }} Done" + variant: body + - component: Text + text: Verified Core Contributor + variant: caption + +sampleData: + userName: Alice Smith + role: Systems Architect + experienceYears: 9 + completedTasks: 142 diff --git a/specification/proposals/templates/examples/team_roster.yaml b/specification/proposals/templates/examples/team_roster.yaml new file mode 100644 index 0000000000..b0261c85f4 --- /dev/null +++ b/specification/proposals/templates/examples/team_roster.yaml @@ -0,0 +1,45 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: TeamRoster +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Team directory roster with styled header banner and nested team lists. + +parameters: + directoryTitle: + type: string + title: Directory Title + description: Title text for the team directory. + children: + type: children + title: Team Cards List + description: List of child TeamCard components. + default: [] + +layout: + component: Column + children: + - component: Text + text: "{{ directoryTitle }}" + variant: h1 + - component: Divider + axis: horizontal + - component: Column + children: "{{ children }}" + +sampleData: + directoryTitle: Global Engineering Directory + children: [] diff --git a/specification/proposals/templates/examples/two_column_layout.yaml b/specification/proposals/templates/examples/two_column_layout.yaml new file mode 100644 index 0000000000..41c4ee2585 --- /dev/null +++ b/specification/proposals/templates/examples/two_column_layout.yaml @@ -0,0 +1,56 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: TwoColumnLayout +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: Responsive two-column dashboard layout with banner header and split content regions. + +parameters: + headerChild: + type: child + title: Header Component Slot + description: Single child component ID mounted at the top banner. + leftChildren: + type: children + title: Left Column Children + description: Child components placed in the left primary region. + default: [] + rightChildren: + type: children + title: Right Column Children + description: Child components placed in the right secondary region. + default: [] + +layout: + component: Column + children: + - component: Column + children: "{{ headerChild }}" + - component: Divider + axis: horizontal + - component: Row + children: + - component: Column + children: "{{ leftChildren }}" + - component: Column + children: "{{ rightChildren }}" + +sampleData: + headerChild: + component: Text + text: Header Title + leftChildren: [] + rightChildren: [] diff --git a/specification/proposals/templates/examples/user_profile.yaml b/specification/proposals/templates/examples/user_profile.yaml new file mode 100644 index 0000000000..f73bb276dd --- /dev/null +++ b/specification/proposals/templates/examples/user_profile.yaml @@ -0,0 +1,54 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "0.1" +name: UserProfile +catalogs: + - "https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json" +description: User profile card displaying avatar, full name, and role. + +parameters: + userId: + type: string + title: User ID + description: Unique user account ID. + userName: + type: string + title: User Name + description: Full name of the user. + role: + type: string + title: Role + description: Job title or role. + default: Member + +layout: + component: Card + child: + component: Column + align: center + children: + - component: Icon + name: person + - component: Text + text: "{{ userName }}" + variant: h3 + - component: Text + text: "{{ role }}" + variant: caption + +sampleData: + userId: usr_101 + userName: Alice Smith + role: Lead Architect diff --git a/specification/proposals/templates/schema/template_definition.json b/specification/proposals/templates/schema/template_definition.json new file mode 100644 index 0000000000..0feb3f5886 --- /dev/null +++ b/specification/proposals/templates/schema/template_definition.json @@ -0,0 +1,312 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "A2UI Template Definition", + "description": "Schema defining a parameterized A2UI declarative template authored in YAML with a nested layout tree and synthetic ID generation.", + "type": "object", + "required": ["version", "parameters", "catalogs"], + "properties": { + "version": { + "type": "string", + "const": "0.1", + "description": "Specification version of the template definition format. Forced to '0.1'." + }, + "id": { + "type": "string", + "description": "Optional globally unique identifier or URI for the template." + }, + "name": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_]*$", + "description": "Component tag name of the template used in layout trees and LLM prompts." + }, + "templateId": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_]*$", + "description": "Deprecated alias for 'name'." + }, + "catalogs": { + "description": "Catalog identifier (URI) or list of catalog identifiers against which components are resolved.", + "anyOf": [ + { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + {"type": "string"} + ] + }, + "imports": { + "description": "Optional list or mapping of dependent templates imported by global ID.", + "anyOf": [ + { + "type": "array", + "items": {"type": "string"} + }, + { + "type": "object", + "additionalProperties": {"type": "string"} + } + ] + }, + "description": { + "type": "string", + "description": "Human-readable description of what this template represents." + }, + "parameters": { + "type": "object", + "description": "Mapping of parameter names to their explicit A2UI type definitions.", + "additionalProperties": { + "$ref": "#/$defs/ParameterDefinition" + } + }, + "requiredParameters": { + "type": "array", + "items": {"type": "string"}, + "description": "Optional list of parameter names that are required when invoking the template." + }, + "layout": { + "$ref": "#/$defs/NestedTemplateNode", + "description": "Root component of the nested layout tree." + }, + "components": { + "type": "array", + "description": "Optional flattened component list for internal graph representation.", + "items": { + "$ref": "#/$defs/TemplateComponent" + } + }, + "sampleData": { + "type": "object", + "description": "Sample parameter values used for previewing and testing template inflation." + } + }, + "allOf": [ + { + "anyOf": [{"required": ["name"]}, {"required": ["templateId"]}] + }, + { + "anyOf": [{"required": ["layout"]}, {"required": ["components"]}] + } + ], + "additionalProperties": false, + "$defs": { + "ParameterDefinition": { + "type": "object", + "required": ["type"], + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "integer", + "boolean", + "enum", + "object", + "array", + "child", + "children", + "action" + ], + "description": "A2UI semantic parameter type." + }, + "title": { + "type": "string", + "description": "Short human-readable title of the parameter." + }, + "description": { + "type": "string", + "description": "Detailed explanation of the parameter's purpose and usage." + }, + "default": { + "description": "Default fallback value if not specified." + }, + "values": { + "type": "array", + "items": {"type": "string"}, + "description": "Allowed string values when type is 'enum'." + }, + "items": { + "description": "Item type definition when type is 'array'. Can be an A2UI type name or nested ParameterDefinition." + }, + "properties": { + "type": "object", + "description": "Property definitions when type is 'object'.", + "additionalProperties": { + "$ref": "#/$defs/ParameterDefinition" + } + }, + "required": { + "anyOf": [ + { + "type": "boolean", + "description": "Whether this parameter is required when instantiating the template." + }, + { + "type": "array", + "items": {"type": "string"}, + "description": "List of required property names for object types." + } + ] + }, + "minimum": { + "type": "number", + "description": "Minimum value constraint for numeric parameters." + }, + "maximum": { + "type": "number", + "description": "Maximum value constraint for numeric parameters." + } + }, + "additionalProperties": false + }, + "ParamReference": { + "type": "object", + "required": ["param"], + "properties": { + "param": { + "type": "string", + "description": "Name or dot-separated path of the template parameter to substitute." + }, + "template": { + "type": "string", + "description": "Child template identifier when mapping an array parameter to child component instances." + }, + "default": { + "description": "Fallback value if the parameter path resolves to None." + } + }, + "additionalProperties": false + }, + "ConcatExpression": { + "type": "object", + "required": ["concat"], + "properties": { + "concat": { + "type": "array", + "description": "List of literal values and parameter references to concatenate into a string.", + "items": { + "anyOf": [{"type": "string"}, {"type": "number"}, {"$ref": "#/$defs/ParamReference"}] + } + } + }, + "additionalProperties": false + }, + "FormatExpression": { + "type": "object", + "required": ["format"], + "properties": { + "format": { + "type": "string", + "description": "Format string containing {key} placeholders." + }, + "args": { + "type": "object", + "description": "Mapping of placeholder keys to values or parameter references.", + "additionalProperties": { + "anyOf": [{"type": "string"}, {"type": "number"}, {"$ref": "#/$defs/ParamReference"}] + } + } + }, + "additionalProperties": false + }, + "LoopDefinition": { + "type": "object", + "required": ["param"], + "anyOf": [{"required": ["template"]}, {"required": ["item"]}], + "properties": { + "param": { + "type": "string", + "description": "Parameter name holding the list/array data to iterate over." + }, + "template": { + "type": "string", + "description": "Identifier of a named template to instantiate for each item." + }, + "item": { + "$ref": "#/$defs/NestedTemplateNode", + "description": "Self-contained inline component layout to instantiate for each item." + }, + "as": { + "type": "string", + "description": "Optional variable scope alias for accessing item fields in expressions." + } + }, + "additionalProperties": false + }, + "TemplateValue": { + "description": "A literal value, parameter substitution, or expression in a template component property.", + "anyOf": [ + {"type": "string"}, + {"type": "number"}, + {"type": "boolean"}, + {"type": "null"}, + {"$ref": "#/$defs/ParamReference"}, + {"$ref": "#/$defs/ConcatExpression"}, + {"$ref": "#/$defs/FormatExpression"}, + {"type": "array"}, + {"type": "object"} + ] + }, + "NestedTemplateNode": { + "type": "object", + "required": ["component"], + "properties": { + "id": { + "type": "string", + "description": "Optional explicit component ID within the template." + }, + "component": { + "type": "string", + "description": "Catalog component tag name." + }, + "catalogId": { + "type": "string", + "description": "Optional catalog ID to disambiguate if the component name exists in multiple declared catalogs." + }, + "child": { + "anyOf": [{"$ref": "#/$defs/NestedTemplateNode"}, {"$ref": "#/$defs/TemplateValue"}] + }, + "children": { + "anyOf": [ + { + "type": "object", + "required": ["loop"], + "properties": { + "loop": {"$ref": "#/$defs/LoopDefinition"} + }, + "additionalProperties": false + }, + {"type": "array"}, + {"$ref": "#/$defs/ParamReference"}, + {"type": "string"} + ] + } + }, + "additionalProperties": { + "$ref": "#/$defs/TemplateValue" + } + }, + "TemplateComponent": { + "type": "object", + "required": ["id", "component"], + "properties": { + "id": { + "type": "string", + "description": "Unique component ID within the template." + }, + "component": { + "type": "string", + "description": "Catalog component tag name." + }, + "catalogId": { + "type": "string", + "description": "Optional catalog ID to disambiguate if the component name exists in multiple declared catalogs." + } + }, + "additionalProperties": { + "$ref": "#/$defs/TemplateValue" + } + } + } +} diff --git a/uv.lock b/uv.lock index eda28872f6..2e95d522fd 100644 --- a/uv.lock +++ b/uv.lock @@ -68,6 +68,8 @@ dependencies = [ { name = "google-genai" }, { name = "httpx" }, { name = "jsonschema" }, + { name = "nest-asyncio" }, + { name = "pyyaml" }, ] [package.dev-dependencies] @@ -75,6 +77,7 @@ dev = [ { name = "antlr4-tools" }, { name = "hatchling" }, { name = "types-jsonschema" }, + { name = "types-pyyaml" }, ] [package.metadata] @@ -86,6 +89,8 @@ requires-dist = [ { name = "google-genai", specifier = ">=1.27.0" }, { name = "httpx", specifier = ">=0.27.0" }, { name = "jsonschema", specifier = ">=4.0.0" }, + { name = "nest-asyncio", specifier = ">=1.6.0" }, + { name = "pyyaml", specifier = ">=6.0" }, ] [package.metadata.requires-dev] @@ -93,6 +98,7 @@ dev = [ { name = "antlr4-tools", specifier = ">=0.2.1" }, { name = "hatchling", specifier = ">=1.30.1" }, { name = "types-jsonschema" }, + { name = "types-pyyaml" }, ] [[package]] @@ -3048,6 +3054,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + [[package]] name = "nest-asyncio2" version = "1.7.2"