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 */}
+
+ setCurrentView('chat')}
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ gap: '6px',
+ padding: '6px 14px',
+ borderRadius: '8px',
+ border: 'none',
+ backgroundColor: currentView === 'chat' ? '#ffffff' : 'transparent',
+ color: currentView === 'chat' ? '#2563eb' : '#64748b',
+ fontWeight: 600,
+ fontSize: '13px',
+ cursor: 'pointer',
+ boxShadow: currentView === 'chat' ? '0 1px 3px rgba(0, 0, 0, 0.08)' : 'none',
+ transition: 'all 0.15s ease',
+ }}
+ >
+
+ chat
+
+ Interactive Chat
+
+ setCurrentView('library')}
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ gap: '6px',
+ padding: '6px 14px',
+ borderRadius: '8px',
+ border: 'none',
+ backgroundColor: currentView === 'library' ? '#ffffff' : 'transparent',
+ color: currentView === 'library' ? '#2563eb' : '#64748b',
+ fontWeight: 600,
+ fontSize: '13px',
+ cursor: 'pointer',
+ boxShadow: currentView === 'library' ? '0 1px 3px rgba(0, 0, 0, 0.08)' : 'none',
+ transition: 'all 0.15s ease',
+ }}
+ >
+
+ menu_book
+
+ Template Library
+
+
+
+
+ {/* 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 => (
+ sendPrompt(btn.prompt)}
+ disabled={loading}
+ style={{
+ textAlign: 'left',
+ padding: '12px 14px',
+ borderRadius: '12px',
+ border: '1px solid #e2e8f0',
+ backgroundColor: '#f8fafc',
+ color: '#1e293b',
+ fontSize: '13px',
+ fontWeight: 600,
+ cursor: loading ? 'not-allowed' : 'pointer',
+ transition: 'all 0.15s ease',
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '2px',
+ }}
+ >
+ {btn.label}
+
+ {btn.desc}
+
+
+ ))}
+
+
+
+
+ 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 => (
+ sendPrompt(chip.text)}
+ disabled={loading}
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ gap: '10px',
+ padding: '10px 14px',
+ backgroundColor: '#f8fafc',
+ border: '1px solid #e2e8f0',
+ borderRadius: '12px',
+ color: '#1e293b',
+ fontSize: '12px',
+ fontWeight: 500,
+ cursor: 'pointer',
+ textAlign: 'left',
+ transition: 'all 0.15s ease',
+ }}
+ onMouseEnter={e => {
+ e.currentTarget.style.backgroundColor = '#eff6ff';
+ e.currentTarget.style.borderColor = '#93c5fd';
+ e.currentTarget.style.color = '#1d4ed8';
+ }}
+ onMouseLeave={e => {
+ e.currentTarget.style.backgroundColor = '#f8fafc';
+ e.currentTarget.style.borderColor = '#e2e8f0';
+ e.currentTarget.style.color = '#1e293b';
+ }}
+ >
+
+ {chip.icon}
+
+ {chip.text}
+
+ ))}
+
+
+
+ )}
+
+ {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 && (
+
+ setActiveInspector(curr => (curr === item.id ? null : item.id))
+ }
+ title="Inspect raw LLM Express DSL and expanded A2UI JSON"
+ style={{
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: '6px',
+ padding: '6px 12px',
+ borderRadius: '20px',
+ border: '1px solid #e2e8f0',
+ backgroundColor: isInspectorOpen ? '#eff6ff' : '#ffffff',
+ borderColor: isInspectorOpen ? '#93c5fd' : '#e2e8f0',
+ color: isInspectorOpen ? '#1d4ed8' : '#64748b',
+ fontSize: '12px',
+ fontWeight: 600,
+ cursor: 'pointer',
+ transition: 'all 0.15s ease',
+ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.03)',
+ }}
+ >
+
+ data_object
+
+ {isInspectorOpen ? 'Hide Payload' : 'Inspect Format'}
+
+ )}
+
+
+
+ {/* Inspector Drawer */}
+ {isInspectorOpen && (
+
+
+
+ setInspectorTab('express')}
+ style={{
+ padding: '6px 12px',
+ borderRadius: '8px',
+ border: 'none',
+ backgroundColor:
+ inspectorTab === 'express' ? '#334155' : 'transparent',
+ color: inspectorTab === 'express' ? '#38bdf8' : '#94a3b8',
+ fontSize: '12px',
+ fontWeight: 600,
+ cursor: 'pointer',
+ }}
+ >
+ ⚡ Raw Express DSL
+
+ setInspectorTab('json')}
+ style={{
+ padding: '6px 12px',
+ borderRadius: '8px',
+ border: 'none',
+ backgroundColor:
+ inspectorTab === 'json' ? '#334155' : 'transparent',
+ color: inspectorTab === 'json' ? '#38bdf8' : '#94a3b8',
+ fontSize: '12px',
+ fontWeight: 600,
+ cursor: 'pointer',
+ }}
+ >
+ 📦 Expanded A2UI JSON
+
+
+
+
{
+ const textToCopy =
+ inspectorTab === 'express'
+ ? item.raw || ''
+ : JSON.stringify(item.messages || [], null, 2);
+ copyToClipboard(textToCopy);
+ }}
+ style={{
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: '4px',
+ padding: '4px 8px',
+ borderRadius: '6px',
+ border: '1px solid #475569',
+ backgroundColor: '#334155',
+ color: '#cbd5e1',
+ fontSize: '11px',
+ cursor: 'pointer',
+ }}
+ >
+
+ {copiedTurn ? 'check' : 'content_copy'}
+
+ {copiedTurn ? 'Copied!' : 'Copy'}
+
+
+
+
+ {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')}
+ />
+ sendPrompt(input)}
+ disabled={loading || !input.trim()}
+ style={{
+ padding: '0 24px',
+ backgroundColor: '#2563eb',
+ color: '#ffffff',
+ border: 'none',
+ borderRadius: '12px',
+ fontSize: '14px',
+ fontWeight: 600,
+ cursor: loading || !input.trim() ? 'not-allowed' : 'pointer',
+ opacity: loading || !input.trim() ? 0.6 : 1,
+ boxShadow: '0 2px 4px rgba(37, 99, 235, 0.2)',
+ transition: 'all 0.15s ease',
+ }}
+ >
+ Send
+
+
+
+
+ ) : (
+ /* 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 (
+
setSelectedTemplateId(tmpl.templateId)}
+ style={{
+ textAlign: 'left',
+ padding: '12px 14px',
+ borderRadius: '12px',
+ border: isSelected ? '1px solid #93c5fd' : '1px solid #e2e8f0',
+ backgroundColor: isSelected ? '#eff6ff' : '#ffffff',
+ cursor: 'pointer',
+ transition: 'all 0.15s ease',
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '4px',
+ }}
+ >
+
+
+ {tmpl.templateId}
+
+ {tmpl.isDynamic ? (
+
+ ⚡ Dynamic
+
+ ) : (
+
+ {paramCount} params
+
+ )}
+
+
+ {tmpl.isDynamic
+ ? 'Server database resolver callback'
+ : `${compCount} primitive components`}
+
+
+ );
+ })}
+
+
+ {/* 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 => (
+ setDynamicTab(tab.id as any)}
+ style={{
+ padding: '6px 14px',
+ borderRadius: '8px',
+ border: 'none',
+ backgroundColor: dynamicTab === tab.id ? '#ffffff' : 'transparent',
+ color: dynamicTab === tab.id ? '#2563eb' : '#64748b',
+ fontWeight: 600,
+ fontSize: '12px',
+ cursor: 'pointer',
+ boxShadow:
+ dynamicTab === tab.id ? '0 1px 3px rgba(0, 0, 0, 0.08)' : 'none',
+ }}
+ >
+ {tab.label}
+
+ ))}
+
+
+
+ {/* 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' ? (
+
+
+
+ Department Name (`department`):
+
+ {
+ 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',
+ }}
+ />
+
+
+
+ {
+ setPayrollIncludeBonus(e.target.checked);
+ handleResolveDynamicTemplate({includeBonus: e.target.checked});
+ }}
+ />
+ Include Annual Bonus Column (`includeBonus`)
+
+
+
+
+ Generated Express DSL by LLM:
+
+
+ {`\nroot = PayrollSummary("${payrollDept}", ${payrollIncludeBonus})\n `}
+
+
+
+ ) : (
+
+
+ Select Employee (Input Parameter `employeeId`):
+
+
handleResolveDynamicTemplate(e.target.value)}
+ style={{
+ padding: '10px 14px',
+ borderRadius: '8px',
+ border: '1px solid #cbd5e1',
+ fontSize: '14px',
+ fontWeight: 600,
+ color: '#0f172a',
+ backgroundColor: '#ffffff',
+ outline: 'none',
+ cursor: 'pointer',
+ }}
+ >
+ {(
+ selectedTemplate.availablePresets || [
+ {label: 'Dr. Elena Vance (emp_101)', value: 'emp_101'},
+ {label: 'Marcus Vance (emp_102)', value: 'emp_102'},
+ {label: 'Aria Chen (emp_103)', value: 'emp_103'},
+ {label: 'Liam Kjell (emp_104)', value: 'emp_104'},
+ ]
+ ).map(opt => (
+
+ {opt.label}
+
+ ))}
+
+
+
+
+ Generated Express DSL by LLM:
+
+
+ {`\nroot = EmployeeSalaryCard("${selectedDynamicEmpId}")\n `}
+
+
+
+ )}
+
+
+ handleResolveDynamicTemplate()}
+ disabled={dynamicResolving}
+ style={{
+ padding: '10px 20px',
+ borderRadius: '8px',
+ backgroundColor: '#2563eb',
+ color: '#ffffff',
+ border: 'none',
+ fontWeight: 600,
+ fontSize: '13px',
+ cursor: dynamicResolving ? 'not-allowed' : 'pointer',
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: '6px',
+ }}
+ >
+
+ sync
+
+
+ {dynamicResolving
+ ? 'Computing...'
+ : selectedTemplate.isProgrammatic
+ ? 'Run Python Render Function'
+ : 'Execute Server Resolver'}
+
+
+
+ {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
+
+
+
+
{
+ copyToClipboard(selectedTemplate.yamlContent || '', true);
+ }}
+ style={{
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: '6px',
+ padding: '6px 12px',
+ borderRadius: '8px',
+ border: '1px solid #cbd5e1',
+ backgroundColor: '#ffffff',
+ color: '#0f172a',
+ fontSize: '12px',
+ fontWeight: 600,
+ cursor: 'pointer',
+ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.04)',
+ }}
+ >
+
+ {copiedTemplate ? 'check' : 'content_copy'}
+
+ {copiedTemplate ? 'Copied YAML!' : 'Copy Template YAML'}
+
+
+
+
+
+ {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/client_expanded_templates.md b/specification/proposals/templates/client_expanded_templates.md
new file mode 100644
index 0000000000..7f1c8c9ef7
--- /dev/null
+++ b/specification/proposals/templates/client_expanded_templates.md
@@ -0,0 +1,464 @@
+# Proposal: Client-Expanded Templates & Dynamic MCP Template Federation
+
+## Abstract
+
+This proposal extends the A2UI Templates architecture to support **client-side template expansion** and **dynamic template federation over the Model Context Protocol (MCP)**.
+
+While server-expanded templates expand into canonical Basic Catalog primitives prior to leaving the Agent SDK, **client-expanded templates** are transported as compact JSON definitions over the wire. Templates can be bundled directly in `createSurface` or dynamically streamed via a new `updateTemplates` protocol message. Furthermore, components inside `updateComponents` can explicitly reference remote templates via a `templateSource` property (analogous to component-level `catalogId` in A2UI v1.0). When an unknown template source is encountered, the client framework dynamically fetches the template from the designated MCP server or endpoint, caches it locally, and synchronously inflates the layout tree on the client.
+
+This architecture enables:
+
+1. **Extreme Wire Efficiency**: Transmitting compact parameter payloads over low-bandwidth channels instead of extensive repetitive component graphs.
+2. **Decoupled Multi-Agent & Tool UI Federation**: Independent MCP servers (e.g., GitHub, Jira, Salesforce) can publish and maintain their own specialized UI templates without requiring the core conversational agent to know their visual layout details.
+3. **Reactive Edge Expansion**: Instant client-side re-inflation when local data models mutate, without server roundtrips.
+
+---
+
+## 1. Motivation & Problem Statement
+
+### The Multi-Agent & MCP UI Dilemma
+
+In modern AI agent ecosystems, a central orchestrating agent often communicates with multiple specialized tools and subagents via the Model Context Protocol (MCP).
+
+Under the existing model:
+
+- **Approach A (Server-expanded templates)**: The orchestrator's backend must hold all template layouts in memory. If a GitHub MCP server wants to display a Pull Request Card, the orchestrator needs to know the exact YAML layout of that card. This breaks tool encapsulation.
+- **Approach B (Raw Basic Catalog components from tools)**: The MCP tool returns hundreds of raw UI primitives in its tool output. This significantly inflates token usage and wire payload size.
+
+### The Solution: Client-Expanded Federated Templates
+
+Client-expanded templates solve this dilemma:
+
+- The MCP server serves as the **Template Authority**, emitting specialized template definitions via `updateTemplates`.
+- The central orchestrator outputs only a compact invocation:
+ ```json
+ {
+ "id": "pr_102",
+ "template": "PullRequestCard",
+ "templateSource": "mcp://github-tool/templates",
+ "parameters": {
+ "prNumber": 102,
+ "repo": "jacobsimionato/a2ui"
+ }
+ }
+ ```
+- The client-side A2UI framework resolves `templateSource`, loads the template definition (if not already cached), and expands the layout directly on the client.
+
+---
+
+## 2. Protocol Message Extensions
+
+To support client-side templates, the A2UI message protocol is extended in two areas: `createSurface` and the new `updateTemplates` message.
+
+### 2.1 Bundling in `createSurface`
+
+Initial templates known at surface creation time can be transported directly inside `createSurface`.
+
+```json
+{
+ "version": "v1.0",
+ "createSurface": {
+ "surfaceId": "main",
+ "catalogId": "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json",
+ "templates": [
+ {
+ "name": "MetricCard",
+ "catalogs": ["https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json"],
+ "description": "KPI metric card",
+ "parameters": {
+ "label": {"type": "string"},
+ "value": {"type": "string"}
+ },
+ "layout": {
+ "component": "Card",
+ "child": {
+ "component": "Column",
+ "children": [
+ {"component": "Text", "text": "{{ label }}", "variant": "caption"},
+ {"component": "Text", "text": "{{ value }}", "variant": "h2"}
+ ]
+ }
+ }
+ }
+ ]
+ }
+}
+```
+
+### 2.2 The `updateTemplates` Message
+
+For templates delivered after surface creation, or emitted dynamically by connected MCP servers, the protocol introduces the top-level `updateTemplates` message.
+
+#### Schema Specification:
+
+```json
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "title": "A2UI UpdateTemplates Message",
+ "type": "object",
+ "required": ["templates"],
+ "properties": {
+ "surfaceId": {
+ "type": "string",
+ "description": "Optional surface to which these templates are scoped. If omitted, templates are scoped globally to the client session."
+ },
+ "templateSource": {
+ "type": "string",
+ "description": "The authority URI or MCP server identifier publishing these templates (e.g. 'mcp://github-server/templates')."
+ },
+ "replace": {
+ "type": "boolean",
+ "default": false,
+ "description": "If true, clears previously registered templates under this templateSource before adding the new set."
+ },
+ "templates": {
+ "type": "array",
+ "items": {
+ "$ref": "template_definition.json"
+ },
+ "description": "Array of JSON-serialized template definitions."
+ }
+ }
+}
+```
+
+#### Example Message:
+
+```json
+{
+ "version": "v1.0",
+ "updateTemplates": {
+ "templateSource": "mcp://github-service/templates",
+ "templates": [
+ {
+ "name": "PullRequestCard",
+ "catalogs": ["https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json"],
+ "description": "GitHub PR status card with merge status and CI indicator.",
+ "parameters": {
+ "prNumber": {"type": "integer"},
+ "title": {"type": "string"},
+ "author": {"type": "string"},
+ "status": {"type": "enum", "values": ["open", "merged", "closed"]}
+ },
+ "layout": {
+ "component": "Card",
+ "child": {
+ "component": "Column",
+ "children": [
+ {
+ "component": "Row",
+ "justify": "spaceBetween",
+ "children": [
+ {"component": "Text", "text": "#{{ prNumber }} {{ title }}", "variant": "h3"},
+ {"component": "Text", "text": "{{ status }}", "variant": "caption"}
+ ]
+ },
+ {"component": "Divider", "axis": "horizontal"},
+ {"component": "Text", "text": "Opened by @{{ author }}", "variant": "body"}
+ ]
+ }
+ }
+ }
+ ]
+ }
+}
+```
+
+---
+
+## 3. Template Referencing in A2UI Content
+
+### 3.1 Component-Level Referencing & Contrast with v1.0 `catalogId`
+
+In the A2UI v1.0 specification, `ComponentCommon` introduced `catalogId` on individual components to override the surface-level default catalog:
+
+```json
+// A2UI v1.0 Component with custom catalogId
+{
+ "id": "chart_1",
+ "catalogId": "https://company.org/catalogs/analytics/catalog.json",
+ "component": "LineChart",
+ "series": "/metrics/cpu"
+}
+```
+
+Analogously, client-expanded templates introduce `template` and `templateSource` to the component model:
+
+```json
+// Client-Expanded Template Component Reference
+{
+ "id": "pr_widget_1",
+ "template": "PullRequestCard",
+ "templateSource": "mcp://github-service/templates",
+ "parameters": {
+ "prNumber": 342,
+ "title": "Add client-side template expansion",
+ "author": "octocat",
+ "status": "open"
+ }
+}
+```
+
+#### Property Definitions:
+
+- **`template`** (string, required): The ID of the template to instantiate (e.g. `"PullRequestCard"`).
+- **`templateSource`** (string, optional): The URI or namespace of the template provider.
+ - Can be an MCP URI: `mcp:///`
+ - Can be an HTTPS endpoint: `https://templates.a2ui.org/library/v1`
+ - Can be a local identifier: `local` or `shared`
+ - If omitted, the template is resolved from the surface's default template registry.
+- **`parameters`** (object, required): A key-value mapping matching the template's declared parameter schema.
+
+---
+
+## 4. MCP Server Integration & Dynamic Federation
+
+When a client encounters a template invocation with a `templateSource` that has not yet been loaded, it uses the Model Context Protocol (MCP) to fetch the template on demand.
+
+### 4.1 Sequence Diagram: On-Demand Dynamic Resolution
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Agent as Conversational Agent
+ participant MCP as MCP Tool Server (e.g. GitHub)
+ participant Client as A2UI Client Framework
+ participant UI as User Interface
+
+ Note over Agent, Client: User asks: "Show me PR #342"
+ Agent->>MCP: Call tool: get_pull_request(342)
+ MCP-->>Agent: Returns PR data {prNumber: 342, title: "Add client templates", ...}
+
+ Agent->>Client: updateComponents(components: [{id: "card_1", template: "PullRequestCard", templateSource: "mcp://github-server/templates", parameters: {...}}])
+
+ Note over Client: Client checks local template cache for "PullRequestCard" from "mcp://github-server/templates"... (MISS)
+
+ Client->>UI: Render Skeleton / Placeholder for "card_1"
+
+ Client->>MCP: Request MCP Resource or Tool: get_template("PullRequestCard")
+ MCP-->>Client: updateTemplates(templateSource: "mcp://github-server/templates", templates: [PullRequestCard])
+
+ Note over Client: Client caches PullRequestCard Expands template locally with parameters Injects synthetic child components
+
+ Client->>UI: Smoothly replaces Skeleton with rendered PullRequestCard!
+```
+
+### 4.2 Proactive vs. Reactive MCP Template Delivery
+
+The architecture supports both delivery patterns:
+
+1. **Proactive Delivery (Tool Response Multiplexing)**:
+ When an MCP server returns a tool response to an agent, it can include an `updateTemplates` message in its response payload or stream it directly over the client channel. When the client receives the agent's `updateComponents` message, the template is already warm in memory.
+
+2. **Reactive Delivery (Client On-Demand Fetching)**:
+ If an agent references a template that the client has not yet received:
+ - The client invokes the standard MCP resource:
+ `mcp:///templates/`
+ - The MCP server returns the template JSON in an `updateTemplates` payload.
+
+---
+
+## 5. Client Expansion Engine & Lifecycle
+
+### 5.1 Deterministic Client Synthetic ID Generation
+
+When the client-side A2UI framework expands a template, it preserves the existing adjacency list component architecture. It generates synthetic IDs for all internal components of the template layout:
+
+$$\text{syntheticId} = \{\text{hostId}\} \mathbin{\_} \{\text{slotName}\} \mathbin{\_} \{\text{index}\} \mathbin{\_} \{\text{componentType}\}$$
+
+#### Example Expansion:
+
+Given host component:
+
+```json
+{
+ "id": "team_lead_widget",
+ "template": "UserProfile",
+ "parameters": {"userName": "Elena Vance", "role": "Principal"}
+}
+```
+
+The client engine replaces `team_lead_widget` in its active render tree with:
+
+```json
+[
+ {
+ "id": "team_lead_widget",
+ "component": "Card",
+ "child": "team_lead_widget_child_column"
+ },
+ {
+ "id": "team_lead_widget_child_column",
+ "component": "Column",
+ "children": [
+ "team_lead_widget_child_column_children_0_text",
+ "team_lead_widget_child_column_children_1_text"
+ ]
+ },
+ {
+ "id": "team_lead_widget_child_column_children_0_text",
+ "component": "Text",
+ "text": "Elena Vance",
+ "variant": "h3"
+ },
+ {
+ "id": "team_lead_widget_child_column_children_1_text",
+ "component": "Text",
+ "text": "Principal",
+ "variant": "caption"
+ }
+]
+```
+
+### 5.2 Progressive Rendering & Skeleton Loading
+
+Because remote template retrieval involves an asynchronous network hop, the client framework must provide a seamless user experience:
+
+1. **Placeholder State**: When an un-cached template is encountered, the client mounts a canonical placeholder (e.g. an animated skeleton card with the specified dimensions or basic text).
+2. **Progressive Mounting**: Once `updateTemplates` is processed, the placeholder is smoothly replaced with the expanded component tree without unmounting neighboring components.
+3. **Timeout Fallback**: If the template source fails to resolve within a configurable timeout (default: 3000ms), a clean error card is displayed:
+ `"Unable to load template 'PullRequestCard' from mcp://github-server/templates"`.
+
+### 5.3 Two-Way Client Data Binding Interoperability
+
+Client-expanded templates have direct, low-latency access to the client's `DataModel`:
+
+- **Local Interpolation**: If a template parameter contains a data binding path (e.g. `path: "/currentUser/name"`), the client resolves it reactively against the local surface data store.
+- **Dynamic Updates**: When the agent sends `updateDataModel`, any client-expanded template bound to that path automatically updates without needing re-expansion.
+
+---
+
+## 6. End-to-End Concrete Example
+
+### Step 1: MCP Server Emits `updateTemplates`
+
+```json
+{
+ "version": "v1.0",
+ "updateTemplates": {
+ "templateSource": "mcp://cloud-ops/templates",
+ "templates": [
+ {
+ "name": "ServerHealthCard",
+ "catalogs": ["https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json"],
+ "parameters": {
+ "hostname": {"type": "string"},
+ "cpuUsage": {"type": "number"},
+ "status": {"type": "enum", "values": ["healthy", "warning", "down"]}
+ },
+ "layout": {
+ "component": "Card",
+ "child": {
+ "component": "Column",
+ "children": [
+ {
+ "component": "Row",
+ "justify": "spaceBetween",
+ "children": [
+ {"component": "Text", "text": "{{ hostname }}", "variant": "h3"},
+ {"component": "Icon", "name": "dns"}
+ ]
+ },
+ {"component": "Divider", "axis": "horizontal"},
+ {"component": "Text", "text": "CPU Load: {{ cpuUsage }}%", "variant": "body"}
+ ]
+ }
+ }
+ }
+ ]
+ }
+}
+```
+
+### Step 2: Agent Sends Compact `updateComponents`
+
+```json
+{
+ "version": "v1.0",
+ "updateComponents": {
+ "surfaceId": "ops_dashboard",
+ "components": [
+ {
+ "id": "root",
+ "component": "Column",
+ "children": ["server_1", "server_2"]
+ },
+ {
+ "id": "server_1",
+ "template": "ServerHealthCard",
+ "templateSource": "mcp://cloud-ops/templates",
+ "parameters": {
+ "hostname": "prod-api-01",
+ "cpuUsage": 42.5,
+ "status": "healthy"
+ }
+ },
+ {
+ "id": "server_2",
+ "template": "ServerHealthCard",
+ "templateSource": "mcp://cloud-ops/templates",
+ "parameters": {
+ "hostname": "prod-db-01",
+ "cpuUsage": 89.1,
+ "status": "warning"
+ }
+ }
+ ]
+ }
+}
+```
+
+### Step 3: Client Inflates Component Subtrees Locally
+
+The client expands `server_1` and `server_2` into native `Card`, `Column`, `Row`, and `Text` nodes, rendering the complete dashboard with zero server expansion overhead.
+
+---
+
+## 7. Edge Cases & Boundary Conditions
+
+### 1. Template Namespace Collisions
+
+**Problem**: Two distinct MCP servers (e.g. `mcp://github` and `mcp://gitlab`) both define a template named `IssueCard`.
+**Solution**: Templates are keyed internally in the client cache by the composite tuple `(templateSource, templateId)`. If `templateSource` is omitted in the invocation, the resolution order is:
+
+1. Active surface local templates.
+2. Global session templates.
+3. Fallback error if multiple matching templates exist in different sources.
+
+### 2. Security & Declarative Sandboxing
+
+**Risk**: Can an untrusted MCP server deliver malicious executable scripts inside a template?
+**Mitigation**:
+
+- A2UI templates are strictly **declarative JSON data structures** validating against `template_definition.json`.
+- Templates contain _no executable code_, JavaScript, or eval functions.
+- The client engine validates all component types within a template against the surface's allowed `catalogId`. A template cannot invoke unverified or unauthorized custom components.
+
+### 3. Client Recursion Limits
+
+To prevent cyclic template references (e.g. Template `A` invokes Template `B` which invokes Template `A`), the client expansion engine maintains a call-stack set and enforces a strict depth limit:
+
+```typescript
+const MAX_CLIENT_TEMPLATE_DEPTH = 16;
+```
+
+If this depth is exceeded, the client halts expansion and marks the node as `TemplateRecursionError`.
+
+### 4. Cache Persistence & Invalidation
+
+- **Session Cache**: Cached in memory for the duration of the client connection.
+- **Persistent Cache (Optional)**: If the client enables local storage caching (e.g. IndexedDB), templates with versioned sources (e.g. `mcp://github/templates/v1.2.0`) can be cached across browser refreshes, making subsequent loads instant.
+- **Invalidation**: Sending an `updateTemplates` message with `replace: true` flushes the cache for that `templateSource`.
+
+---
+
+## 8. Summary Comparison: Server vs. Client Expansion
+
+| Feature | Server-Expanded Templates | Client-Expanded Templates |
+| :------------------------------- | :------------------------------------------------------- | :-------------------------------------------------------------------------- |
+| **Expansion Location** | Agent SDK (Server-Side) | A2UI Framework / Renderer (Client-Side) |
+| **Wire Protocol Payload** | Standard Basic Catalog primitives (`Card`, `Text`, etc.) | Compact JSON template references & `updateTemplates` |
+| **Client Requirement** | Zero. Any standard Basic Catalog renderer works. | Client must include template inflation logic (`@a2ui/templates`). |
+| **Dynamic Tool Federation** | Central orchestrator must hold all tool templates. | Autonomous MCP servers publish templates dynamically via `updateTemplates`. |
+| **Confidential Data Resolution** | Excellent (secure server callbacks query private DBs). | Moderate (private data must be transmitted to the client). |
+| **Wire Bandwidth** | Higher (expanded component graphs sent over wire). | Minimal (only parameters and IDs sent over wire). |
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/python_fluent_template_builders.md b/specification/proposals/templates/python_fluent_template_builders.md
new file mode 100644
index 0000000000..f966867d88
--- /dev/null
+++ b/specification/proposals/templates/python_fluent_template_builders.md
@@ -0,0 +1,366 @@
+# Proposal: Python Fluent Template Builders
+
+## Abstract
+
+This document proposes a catalog-driven code generator and type-safe fluent builder library for authoring A2UI templates and dynamic server render functions in Python.
+
+By analyzing an A2UI Component Catalog JSON Schema (`catalog.json`), a builder generator script automatically synthesizes strongly typed, IDE-friendly Python component classes (`Card`, `Column`, `Row`, `Text`, `Button`, `Divider`, `Icon`, `Image`, etc.). These builder classes enforce compile-time and runtime type safety, provide instant editor autocompletion, and seamlessly interoperate with the A2UI Python Agent SDK's polymorphic template engine.
+
+---
+
+## 1. Motivation
+
+The A2UI Python SDK supports programmatic dynamic templates via server render functions:
+
+```python
+def render_team_dashboard(team_id: str) -> dict:
+ ...
+```
+
+While authoring UI trees using raw Python dictionaries is flexible, it exposes developers to common mistakes:
+
+- **Typo errors**: Accidentally typing `"algn": "center"` instead of `"align": "center"`.
+- **Type mismatches**: Passing an integer `42` where a child component or string is expected.
+- **Invalid enum variants**: Passing `variant="heading1"` instead of standard `variant="h1"`.
+- **Lack of discoverability**: Developers must consult documentation or JSON schemas to know what properties a component accepts.
+
+A catalog-driven fluent builder library solves these issues by turning JSON schemas into native Python classes with type annotations, docstrings, and constructor validation.
+
+---
+
+## 2. Architecture & Code Generation Workflow
+
+The builder system is catalog-driven and catalog-agnostic:
+
+```
++-------------------------------------------------------------------------------+
+| A2UI Catalog JSON Schema (e.g. basic/catalog.json or custom_catalog.json) |
++---------------------------------------+---------------------------------------+
+ |
+ v
++-------------------------------------------------------------------------------+
+| Generator CLI Tool: a2ui-build-builders |
+| 1. Ingests catalog schema (local file path or remote HTTPS URL) |
+| 2. Parses component definitions, slots, properties, and enum constraints |
+| 3. Emits type-annotated builder dataclasses with docstrings |
+| 4. Formats output code with pyink / black |
++---------------------------------------+---------------------------------------+
+ |
+ v
++-------------------------------------------------------------------------------+
+| Output Python Package: a2ui.inference_formats.experimental.template.builder |
+| - __init__.py |
+| - components.py (Card, Column, Row, Text, Button, Icon, Divider, Image...) |
+| - types.py (TextVariant, FlexAlign, FlexJustify, etc.) |
++---------------------------------------+---------------------------------------+
+ |
+ v
++-------------------------------------------------------------------------------+
+| Programmatic DynamicTemplate (render=render_fn) |
+| Python functions return fluent builder trees with IDE autocompletion |
++-------------------------------------------------------------------------------+
+```
+
+---
+
+## 3. Package Architecture: Generated vs. Handcrafted Files
+
+To maintain clean separation between runtime engine logic and generated code, the builder architecture splits into handcrafted runtime infrastructure and auto-generated catalog modules:
+
+```
+agent_sdks/python/
+├── a2ui_agent/
+│ ├── src/a2ui/inference_formats/experimental/template/
+│ │ ├── builder/ <-- Pre-bundled builders for Basic Catalog
+│ │ │ ├── __init__.py (Generated / Re-exported)
+│ │ │ ├── base.py (Handcrafted Runtime Infrastructure)
+│ │ │ ├── components.py (Auto-Generated from basic/catalog.json)
+│ │ │ └── types.py (Auto-Generated from basic/catalog.json)
+│ │ ├── models.py (Handcrafted: normalize_node, DynamicTemplate)
+│ │ └── processor.py (Handcrafted: TemplateProcessor)
+│ └── tools/
+│ └── codegen/
+│ ├── __init__.py
+│ └── builder_generator.py (Handcrafted: The Codegen CLI Tool)
+```
+
+### A. Handcrafted Runtime Infrastructure (Static SDK Code, Never Regenerated)
+
+These files provide the foundation and serialization contracts:
+
+1. **`base.py` (`ComponentBuilder`, `DataBinding`)**:
+ - `ComponentBuilder`: The abstract base class providing the `.to_dict()` protocol and equality checking.
+ - `DataBinding`: Strongly typed wrapper for client-side reactive bindings (`path: str`).
+ - `ActionRef`: Helper for dispatching user interaction events.
+2. **`models.py` (`normalize_node`, `flatten_nested_layout`)**:
+ - Handles duck-typing normalization. If a node implements `.to_dict()` (like `ComponentBuilder`), it automatically serializes it before flattening synthetic IDs.
+3. **`processor.py` (`TemplateProcessor`)**:
+ - The synchronous expansion engine that resolves dynamic functions and flattens layouts into standard Basic Catalog primitives.
+
+### B. Auto-Generated Files (Synthesized from `catalog.json`)
+
+These files are generated on demand from any A2UI catalog schema:
+
+1. **`components.py`**:
+ - Python `@dataclass` classes for every component in the catalog (`Text`, `Card`, `Column`, `Row`, `Button`, `Divider`, `Icon`, `Image`, etc.).
+ - Explicit constructor parameters (no untyped `**kwargs`).
+ - Python docstrings extracted directly from the `description` fields in the catalog schema.
+ - Implementation of `.to_dict()` that recursively normalizes child slots and data bindings.
+2. **`types.py`**:
+ - Strict `Literal[...]` unions for all string enums defined in the catalog (e.g. `TextVariant`, `FlexAlign`, `FlexJustify`, `ButtonVariant`).
+3. **`__init__.py`**:
+ - Re-exports all generated component classes alongside `DataBinding` and `ComponentBuilder` for clean imports (`from a2ui.inference_formats.experimental.template.builder import Card, Column, Text, DataBinding`).
+
+---
+
+## 4. Code Generation CLI & Distribution
+
+### 4.1 CLI Entry Point Registration
+
+The code generator is distributed as part of `a2ui-agent-sdk` (and standalone via `a2ui-core`). It is registered as a console script in `pyproject.toml`:
+
+```toml
+[project.scripts]
+a2ui-build-builders = "a2ui.tools.codegen.builder_generator:main"
+```
+
+### 4.2 Pre-bundled Builders (Zero-Setup for Standard Users)
+
+For standard A2UI development using the official **Basic Catalog**, developers do not need to run any code generation steps. The `a2ui-agent-sdk` package ships with pre-generated, tested builders directly under `a2ui.inference_formats.experimental.template.builder`.
+
+Developers simply write:
+
+```python
+from a2ui.inference_formats.experimental.template.builder import Card, Column, Text, Icon, Divider, DataBinding
+```
+
+### 4.3 Generating Builders for Custom / Enterprise Catalogs
+
+When an enterprise team defines a custom component catalog (e.g. `finance_catalog.json` with `StockTicker`, `OrderBook`, `CandlestickChart`), they can run the CLI generator to produce their own custom builder package:
+
+```bash
+# Run via uv in any project
+uv run a2ui-build-builders \
+ --catalog ./catalogs/finance/catalog.json \
+ --output ./src/my_app/ui_builders \
+ --package-name my_app.ui_builders
+```
+
+#### CLI Options & Flags:
+
+| Flag | Type | Description |
+| :---------------- | :----------------------- | :------------------------------------------------------------ |
+| `--catalog`, `-c` | `str` (Required) | Path to local `catalog.json` or remote HTTPS schema URL. |
+| `--output`, `-o` | `str` (Required) | Target directory where Python builder files will be written. |
+| `--package-name` | `str` (Optional) | Custom Python package namespace for generated imports. |
+| `--format` | `bool` (Default: `True`) | Automatically format generated code using `pyink` or `black`. |
+| `--strict-types` | `bool` (Default: `True`) | Emit `Literal` enum types and strict primitive unions. |
+
+### 4.4 Hatchling / Build Hook Integration
+
+In the A2UI repository, the builder generation is wired into the build lifecycle (`pack_specs_hook.py` or `wireit`). When specifications under `specification/v0_9_1/catalogs/` update, the build hook regenerates `a2ui.template.builder` automatically before wheels are built.
+
+---
+
+## 5. Type Mapping Rules
+
+The generator maps JSON schema types to Python type annotations:
+
+| A2UI Catalog JSON Type | Generated Python Type Annotation | Description |
+| :----------------------- | :-------------------------------------------------------------------------- | :----------------------------------------------------- |
+| `DynamicString` | `Union[str, DataBinding]` | Literal string or client data model binding. |
+| `DynamicNumber` | `Union[int, float, DataBinding]` | Numeric literal or client data model binding. |
+| `DynamicBoolean` | `Union[bool, DataBinding]` | Boolean flag or client data model binding. |
+| `ComponentId` / `child` | `Union[ComponentBuilder, Dict[str, Any], str]` | Single child component, raw dict AST, or ID reference. |
+| `ChildList` / `children` | `Union[List[Union[ComponentBuilder, Dict[str, Any], str]], Dict[str, Any]]` | Multi-child list or inline loop definition. |
+| `Action` | `Union[ActionRef, Dict[str, Any], str]` | Action event definition or action ID. |
+| `enum` (e.g. `variant`) | `Literal["h1", "h2", "h3", "h4", "h5", "caption", "body"]` | Strict string literals for IDE auto-complete. |
+
+---
+
+## 6. Generated Class Structure Example
+
+Here is the exact code emitted by `a2ui-build-builders` for standard components:
+
+```python
+# a2ui/inference_formats/experimental/template/builder/components.py
+# AUTO-GENERATED BY a2ui-build-builders. DO NOT EDIT DIRECTLY.
+
+from __future__ import annotations
+from dataclasses import dataclass
+from typing import Any, Dict, List, Literal, Optional, Union
+from a2ui.inference_formats.experimental.template.models import normalize_node
+from .base import ComponentBuilder, DataBinding, ActionRef
+from .types import TextVariant, FlexAlign, FlexJustify, DividerAxis
+
+@dataclass
+class Text(ComponentBuilder):
+ """Text component for structured typographic display.
+
+ Parameters:
+ text: The text content to display, or a DataBinding path.
+ variant: Typographic hierarchy level ('h1' through 'h5', 'caption', 'body').
+ id: Optional explicit component identifier.
+ """
+ text: Union[str, DataBinding]
+ variant: Optional[TextVariant] = "body"
+ id: Optional[str] = None
+
+ def to_dict(self) -> Dict[str, Any]:
+ res: Dict[str, Any] = {
+ "component": "Text",
+ "text": self.text.to_dict() if isinstance(self.text, DataBinding) else self.text,
+ }
+ if self.variant:
+ res["variant"] = self.variant
+ if self.id:
+ res["id"] = self.id
+ return res
+
+
+@dataclass
+class Column(ComponentBuilder):
+ """Vertical layout container.
+
+ Parameters:
+ children: List of child component builders or raw AST dicts.
+ align: Cross-axis alignment ('start', 'center', 'end', 'stretch').
+ justify: Main-axis distribution ('start', 'center', 'end', 'spaceBetween', 'spaceAround').
+ id: Optional explicit component identifier.
+ """
+ children: Union[List[Union[ComponentBuilder, Dict[str, Any], str]], Dict[str, Any]]
+ align: Optional[FlexAlign] = None
+ justify: Optional[FlexJustify] = None
+ id: Optional[str] = None
+
+ def to_dict(self) -> Dict[str, Any]:
+ res: Dict[str, Any] = {"component": "Column"}
+ if isinstance(self.children, list):
+ res["children"] = [normalize_node(c) for c in self.children]
+ else:
+ res["children"] = normalize_node(self.children)
+ if self.align:
+ res["align"] = self.align
+ if self.justify:
+ res["justify"] = self.justify
+ if self.id:
+ res["id"] = self.id
+ return res
+
+
+@dataclass
+class Card(ComponentBuilder):
+ """Visual surface container card.
+
+ Parameters:
+ child: Single child component contained within the card surface.
+ id: Optional explicit component identifier.
+ """
+ child: Union[ComponentBuilder, Dict[str, Any], str]
+ id: Optional[str] = None
+
+ def to_dict(self) -> Dict[str, Any]:
+ res: Dict[str, Any] = {
+ "component": "Card",
+ "child": normalize_node(self.child),
+ }
+ if self.id:
+ res["id"] = self.id
+ return res
+```
+
+---
+
+## 7. Developer Experience: Programmatic Dynamic Templates
+
+With fluent builders, developers author server render functions with complete IDE autocompletion, type safety, and inline docstrings:
+
+```python
+from a2ui.inference_formats.experimental.template.builder import Card, Column, Row, Text, Icon, Divider, DataBinding
+from a2ui.inference_formats.experimental.template import dynamic_template
+
+@dynamic_template(
+ name="ProjectStatusCard",
+ catalogs=["https://a2ui.org/specification/v0_9_1/catalogs/basic/catalog.json"],
+ description="Live project tracking card with milestones.",
+)
+def project_status_card(project_id: str):
+ project = project_db.get(project_id)
+
+ # 1. Native Python conditionals
+ status_icon = "check_circle" if project.status == "ON_TRACK" else "warning"
+
+ # 2. Native Python list comprehensions
+ milestone_rows = [
+ Row(
+ justify="spaceBetween",
+ children=[
+ Text(m.name, variant="body"),
+ Text(f"Due: {m.due_date}", variant="caption"),
+ ]
+ )
+ for m in project.milestones
+ ]
+
+ # 3. Reactive two-way client DataBinding
+ approval_binding = DataBinding(path=f"/projects/{project_id}/budgetApproved")
+
+ # 4. Construct type-safe component tree
+ return Card(
+ child=Column(
+ children=[
+ Row(
+ justify="spaceBetween",
+ align="center",
+ children=[
+ Text(project.name, variant="h2"),
+ Icon(name=status_icon),
+ ]
+ ),
+ Divider(),
+ Text(f"Lead Architect: {project.lead_name}", variant="caption"),
+ Text(f"Sprint Velocity: {project.velocity} pts", variant="body"),
+ Divider(),
+ Text("Milestones", variant="h3"),
+ Column(children=milestone_rows),
+ ]
+ )
+ )
+```
+
+---
+
+## 8. Static Type Checking & IDE Feedback
+
+When developers write code using fluent builders, IDEs (VS Code / Pylance, PyCharm, Cursor) and static type checkers (`mypy`, `pyright`) catch errors before runtime:
+
+### 1. Typo Prevention
+
+```python
+# Mypy Error: Unexpected keyword argument "algn" for "Column"
+Column(children=[], algn="center")
+```
+
+### 2. Slot Type Validation
+
+```python
+# Mypy Error: Argument "child" to "Card" has incompatible type "int"; expected "ComponentBuilder | dict | str"
+Card(child=123)
+```
+
+### 3. Enum Variant Checking
+
+```python
+# Mypy Error: Argument "variant" to "Text" has incompatible type 'Literal["heading1"]'; expected 'Literal["h1", "h2", ...]'
+Text("Title", variant="heading1")
+```
+
+---
+
+## 9. Polymorphic Engine Interoperability
+
+Because the engine's [`flatten_nested_layout()`](file:///Users/jsimionato/development/a2ui_repos/templates/a2ui/agent_sdks/python/a2ui_agent/src/a2ui/template/models.py#L358) includes duck-type normalization (`hasattr(node, "to_dict")`), fluent builder trees:
+
+- Are flattened automatically into canonical Basic Catalog primitives with synthetic IDs (`root`, `{parent}_{slot}_{index}_{type}`).
+- Can be freely mixed with raw dictionaries, dataclasses, or Pydantic models anywhere in the hierarchy.
+- Require zero modifications to `TemplateProcessor` or `TemplateInferenceFormat`.
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"