Skip to content

Commit 9939eff

Browse files
committed
feat: implement schema packaging and runtime loading
- Add a base InferenceStrategy class - Add PackSpecsBuildHook to copy JSON schemas into the package during build time. - Update pyproject.toml to include assets and configure the build hook. - Implement A2uiSchemaManager for robust schema loading, pruning, and prompt generation.
1 parent cdfe6d0 commit 9939eff

18 files changed

Lines changed: 1822 additions & 58 deletions

.github/workflows/python_a2ui_agent_build_and_test.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,14 @@ jobs:
4646
working-directory: a2a_agents/python/a2ui_agent
4747
run: uv run pyink --check .
4848

49+
- name: Run unit tests
50+
working-directory: a2a_agents/python/a2ui_agent
51+
run: uv run --with pytest pytest tests/
52+
4953
- name: Build the python SDK
5054
working-directory: a2a_agents/python/a2ui_agent
5155
run: uv build .
5256

53-
- name: Run unit tests
57+
- name: Run validation scripts on assets packing
5458
working-directory: a2a_agents/python/a2ui_agent
55-
run: uv run --with pytest pytest tests/
59+
run: uv run python tests/integration/verify_load_real.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/a2ui/assets/**/*.json
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
import shutil
17+
import sys
18+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
19+
20+
21+
class PackSpecsBuildHook(BuildHookInterface):
22+
23+
def initialize(self, version, build_data):
24+
project_root = self.root
25+
26+
# Add src to sys.path to import the constant
27+
src_path = os.path.join(project_root, "src")
28+
if src_path not in sys.path:
29+
sys.path.insert(0, src_path)
30+
31+
from a2ui.inference.schema.constants import (
32+
SPEC_VERSION_MAP,
33+
A2UI_ASSET_PACKAGE,
34+
SPECIFICATION_DIR,
35+
find_repo_root,
36+
)
37+
38+
# project root is in a2a_agents/python/a2ui_agent
39+
# Dynamically find repo root by looking for SPECIFICATION_DIR
40+
repo_root = find_repo_root(project_root)
41+
if not repo_root:
42+
# Check for PKG-INFO which implies a packaged state (sdist).
43+
# If PKG-INFO is present, trust the bundled assets.
44+
if os.path.exists(os.path.join(project_root, "PKG-INFO")):
45+
print("Repository root not found, but PKG-INFO present (sdist). Skipping copy.")
46+
return
47+
48+
raise RuntimeError(
49+
f"Could not find repository root (looked for '{SPECIFICATION_DIR}'"
50+
" directory)."
51+
)
52+
53+
# Target directory: src/a2ui/assets
54+
target_base = os.path.join(
55+
project_root, "src", A2UI_ASSET_PACKAGE.replace(".", os.sep)
56+
)
57+
58+
for ver, schema_map in SPEC_VERSION_MAP.items():
59+
target_dir = os.path.join(target_base, ver)
60+
os.makedirs(target_dir, exist_ok=True)
61+
62+
for _schema_key, source_rel_path in schema_map.items():
63+
source_path = os.path.join(repo_root, source_rel_path)
64+
65+
if not os.path.exists(source_path):
66+
print(
67+
f"WARNING: Source schema file not found at {source_path}. Build might"
68+
" produce incomplete wheel if not running from monorepo root."
69+
)
70+
continue
71+
72+
filename = os.path.basename(source_path)
73+
dst_file = os.path.join(target_dir, filename)
74+
75+
print(f"Copying {source_path} -> {dst_file}")
76+
shutil.copy2(source_path, dst_file)

a2a_agents/python/a2ui_agent/pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ build-backend = "hatchling.build"
1717

1818
[tool.hatch.build.targets.wheel]
1919
packages = ["src/a2ui"]
20+
artifacts = ["src/a2ui/assets/**"]
21+
22+
[tool.hatch.build.targets.sdist]
23+
artifacts = ["src/a2ui/assets/**"]
24+
25+
[tool.hatch.build.hooks.custom]
26+
path = "pack_specs_hook.py"
2027

2128
[[tool.uv.index]]
2229
url = "https://pypi.org/simple"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from abc import ABC, abstractmethod
16+
from typing import List, Optional, Any
17+
18+
19+
class InferenceStrategy(ABC):
20+
21+
@abstractmethod
22+
def generate_system_prompt(
23+
self,
24+
role_description: str,
25+
workflow_description: str = "",
26+
ui_description: str = "",
27+
supported_catalog_ids: List[str] = [],
28+
allowed_components: List[str] = [],
29+
include_schema: bool = False,
30+
include_examples: bool = False,
31+
) -> str:
32+
"""
33+
Generates a system prompt for all LLM requests.
34+
35+
Args:
36+
role_description: Description of the agent's role.
37+
workflow_description: Description of the workflow.
38+
ui_description: Description of the UI.
39+
supported_catalog_ids: List of supported catalog IDs.
40+
allowed_components: List of allowed components.
41+
include_schema: Whether to include the schema.
42+
include_examples: Whether to include examples.
43+
44+
Returns:
45+
The system prompt.
46+
"""
47+
pass
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

0 commit comments

Comments
 (0)