Skip to content

feat(formats): implement Express and Elemental InferenceFormats #1982

Merged
gspencergoog merged 38 commits into
mainfrom
unified-inference-formats-strategies
Jul 17, 2026
Merged

feat(formats): implement Express and Elemental InferenceFormats #1982
gspencergoog merged 38 commits into
mainfrom
unified-inference-formats-strategies

Conversation

@gspencergoog

@gspencergoog gspencergoog commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR unifies the structured inference SDK API and evaluation harness in Python to support multiple inference formats (standard JSON transport, experimental Express DSL, and experimental Elemental HTML). It encapsulates format-specific details using polymorphic implementations of the InferenceFormat interface.

Changes

  • Polymorphic format abstractions: Defined the InferenceFormat base class contract and created polymorphic implementations TransportFormat, ExpressFormat, and ElementalFormat.
  • Decoupled strategy implementations: Relocated format-specific prompt generators, parsers, and decompilers under the unified formats hierarchy.
  • Elemental compiler enhancements:
    • Restricted ElementalCompiler root validation to <body>.
    • Wrapped HTML layout parsing in a virtual <root> tag dynamically during compilation to support top-level sibling tags (like <link> outside <body>).
    • Added property type coercion (boolean, float, integer) and fallback expression parsing for string array/object attributes (such as options).
  • Inference sentinel constants: Extracted <a2ui> and </a2ui> tags into A2UI_INFERENCE_OPEN_TAG and A2UI_INFERENCE_CLOSE_TAG constants.
  • Evaluation solver & scorer improvements:
    • Consolidated separate format solvers into a single polymorphic format.py solver.
    • Made experiments settings conditional on version == "1.0" in both solver and scorer to avoid enabling experimental version 1.0 features for older version tests.
  • Documentation: Added docstrings describing properties of the ClientUiCapabilities TypedDict.

Impact & Risks

This refactor changes internal SDK package layouts and imports, but preserves existing public API boundaries. It is non-breaking for external integrations.

Testing

Verify the changes by running all python unit tests and the evaluation suite runs:

uv run pytest
uv run main.py --strategies express,elemental

gemini-code-assist[bot]

This comment was marked as resolved.

@gspencergoog
gspencergoog force-pushed the unified-inference-formats-strategies branch 3 times, most recently from 6238957 to 82bd501 Compare July 10, 2026 16:56
@gspencergoog
gspencergoog force-pushed the unified-inference-formats-foundation branch from 89a547a to 1134c08 Compare July 10, 2026 16:59
@gspencergoog
gspencergoog force-pushed the unified-inference-formats-strategies branch 10 times, most recently from 5266cef to 77a52dd Compare July 13, 2026 21:12
@gspencergoog
gspencergoog force-pushed the unified-inference-formats-foundation branch from dd30576 to 914f571 Compare July 13, 2026 21:44
@gspencergoog
gspencergoog force-pushed the unified-inference-formats-strategies branch 2 times, most recently from c0e7429 to 33fc7c2 Compare July 13, 2026 21:49
gemini-code-assist[bot]

This comment was marked as resolved.

- Make experiments parameter conditional on version == "1.0" in eval format strategy resolver.
- Support resolving surface ID from both a2ui and body tags in completion solver regex.
- Auto-close unclosed a2ui tags during streaming compilation in ElementalParser.
- Ensure prompt generator delegates example decompilation using its pruned catalog decompiler if available.
- Call _ensure_catalog before instantiating prompt generator in ExpressFormat property.
- Fix prefix check for action properties in ElementalDecompiler to look for "on-".
…l & clean up tests

- Wrap Elemental HTML input in a virtual `<root>` tag to parse top-level sibling elements (like `<link>` outside `<body>`) without requiring LLM format changes.
- Add attribute type coercion (boolean, number, integer) and fallback JSON-like array/object parsing to handle LLM format variations.
- Make the `experiments` configuration in evals conditional on `version == "1.0"` in both solver and scorer to avoid loading v1.0 schemas for older formats.
- Merge the redundant `test_refactoring.py` assertions into `test_formats.py` and unify catalog provider test structures.
- Delete the empty `eval/tests/conftest.py` file.
gemini-code-assist[bot]

This comment was marked as resolved.

Comment thread agent_sdks/python/a2ui_agent/src/a2ui/inference_format.py Outdated
Comment thread agent_sdks/python/a2ui_agent/src/a2ui/decompiler.py Outdated
self._catalog = catalog
from urllib.parse import urljoin
from jsonschema import Draft202012Validator
from jsonschema import Draft202012Validator, FormatChecker

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but A2uiValidatorWrapperV10 uses jsonschema validation, while v0.9 uses pydantic model validation. I'll update the a2ui-core to consolidate the validation across multiple versions separately.

Comment thread agent_sdks/python/a2ui_agent/src/a2ui/schema/capabilities.py Outdated
Comment thread agent_sdks/python/a2ui_agent/src/a2ui/parser/lexer.py
…own cleaning

- Refactor unwrap_response in TransportParser to use BlockLexer for robust boundary detection.
- Unify markdown code block wrapper cleaning in BlockLexer into a single _clean_markdown method that handles both conversational text and inner blocks.
- Remove duplicate _sanitize_json_string and unused imports.
- Add unit tests for inner markdown block cleaning and nested close tags in JSON string literals.
# Conflicts:
#	eval/a2ui_eval/strategies/express.py
#	eval/a2ui_eval/strategies/subagent_tool.py
#	eval/tests/test_strategies.py
#	pyproject.toml
…tegies' into unified-inference-formats-strategies
@gspencergoog
gspencergoog force-pushed the unified-inference-formats-strategies branch from 9c08077 to 4868407 Compare July 17, 2026 19:19
…trip codecs

- Consolidated compilation and decompilation under the Parser class, turning them into symmetric codecs.
- Modified InferenceFormat to remove the separate decompiler property.
- Retained format decompiler classes as private internal helpers (_TransportDecompiler, _ExpressDecompiler, _ElementalDecompiler) to preserve SRP.
- Updated all unit, integration, and roundtrip tests, as well as helper scripts, to use the parser decompile APIs.
…entUiCapabilities

- Replaced custom ClientUiCapabilities TypedDict in a2ui_agent with the standardized V09Capabilities model from a2ui_core.
- Updated base prompt interfaces, template manager, and format-specific prompt generators to support Union[dict, V09Capabilities].
- Implemented dict-to-model validation coercion in TransportFormat._select_catalog with fallback for missing optional fields in conformance tests.
- Deleted src/a2ui/schema/capabilities.py.
@gspencergoog
gspencergoog merged commit 2472202 into main Jul 17, 2026
26 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in A2UI Jul 17, 2026
@gspencergoog
gspencergoog deleted the unified-inference-formats-strategies branch July 17, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants