Skip to content

refactor(protocol): rename client/server to renderer/agent consistently - #2075

Closed
gspencergoog wants to merge 2 commits into
a2ui-project:mainfrom
gspencergoog:naming-refactor
Closed

refactor(protocol): rename client/server to renderer/agent consistently#2075
gspencergoog wants to merge 2 commits into
a2ui-project:mainfrom
gspencergoog:naming-refactor

Conversation

@gspencergoog

Copy link
Copy Markdown
Collaborator

Consistently adopt "renderer" (for client) and "agent" (for server) terms across the v1.0 protocol specification, SDKs (Swift, Kotlin, Python), renderers (Web Core, Lit, React, Angular workspaces), samples, and documentation.

Implement fallback handling for legacy tool names (send_a2ui_json_to_client) and version-aware prompts/schemas to preserve backwards compatibility for frozen specifications (v0.8, v0.9).

Verify that all unit, integration, and conformance tests compile and pass successfully across all platforms.

Consistently adopt "renderer" (for client) and "agent" (for server) terms across the v1.0 protocol specification, SDKs (Swift, Kotlin, Python), renderers (Web Core, Lit, React, Angular workspaces), samples, and documentation.

Implement fallback handling for legacy tool names (`send_a2ui_json_to_client`) and version-aware prompts/schemas to preserve backwards compatibility for frozen specifications (v0.8, v0.9).

Verify that all unit, integration, and conformance tests compile and pass successfully across all platforms.
@github-project-automation github-project-automation Bot moved this from Todo to Done in A2UI Jul 22, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the A2UI protocol from version 0.9 to 1.0, involving extensive renaming of components and schemas from 'client' to 'renderer' and 'server-to-client' to 'agent-to-renderer'. Key changes include updates to the Python SDK's validation logic, schema generation scripts, and component definitions. The review feedback identifies several critical issues: a missing import for analyze_topology in the validator, a likely incorrect change in return types for formatting APIs from 'string' to 'boolean', missing backwards compatibility for legacy tool names in the Kotlin SDK, and dead code in the Python validator.

Comment on lines 300 to 302
from a2ui.core.validating.integrity_checker import (
validate_component_integrity,
validate_recursion_and_paths,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The function analyze_topology is called at line 362 but is not imported anywhere in this file. This will raise a NameError at runtime when validation is executed. Please add analyze_topology to the local import statement from a2ui.core.validating.integrity_checker.

Suggested change
from a2ui.core.validating.integrity_checker import (
validate_component_integrity,
validate_recursion_and_paths,
from a2ui.core.validating.integrity_checker import (
validate_component_integrity,
validate_recursion_and_paths,
analyze_topology,
)

name = "formatString"
schema = FormatStringArgs
return_type = "string"
return_type = "boolean"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The return type of FormatStringApi (and other formatting APIs like FormatNumberApi, FormatCurrencyApi, FormatDateApi, and PluralizeApi) has been changed from "string" to "boolean". Since these functions are designed to format values into strings for display, they should return "string". Returning "boolean" is likely a copy-paste error and will cause validation or runtime type mismatches.

Suggested change
return_type = "boolean"
return_type = "string"

Comment on lines 54 to +57
val functionResponse = part.functionResponse().orElse(null)
val isSendA2uiJsonToClientResponse =
val isSendA2uiJsonToRendererResponse =
functionResponse != null &&
functionResponse.name().orElse(null) == SendA2uiToClientToolset.TOOL_NAME
functionResponse.name().orElse(null) == SendA2uiToRendererToolset.TOOL_NAME

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The legacy tool name "send_a2ui_json_to_client" is not handled as a fallback in Converters.kt, unlike in A2aHandler.kt. If an older client/renderer sends a response using the legacy tool name, isSendA2uiJsonToRendererResponse will evaluate to false and the response will be ignored. Please add fallback handling for "send_a2ui_json_to_client" to preserve backwards compatibility as intended.

Suggested change
val functionResponse = part.functionResponse().orElse(null)
val isSendA2uiJsonToClientResponse =
val isSendA2uiJsonToRendererResponse =
functionResponse != null &&
functionResponse.name().orElse(null) == SendA2uiToClientToolset.TOOL_NAME
functionResponse.name().orElse(null) == SendA2uiToRendererToolset.TOOL_NAME
val functionResponse = part.functionResponse().orElse(null)
val fnName = functionResponse?.name()?.orElse(null)
val isSendA2uiJsonToRendererResponse =
functionResponse != null &&
(fnName == SendA2uiToRendererToolset.TOOL_NAME || fnName == "send_a2ui_json_to_client")

Comment on lines 72 to 77
val functionCall = part.functionCall().orElse(null)
if (
functionCall != null && functionCall.name().orElse(null) == SendA2uiToClientToolset.TOOL_NAME
functionCall != null && functionCall.name().orElse(null) == SendA2uiToRendererToolset.TOOL_NAME
) {
return emptyList()
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Similarly, the functionCall check should also handle the legacy tool name "send_a2ui_json_to_client" as a fallback to prevent processing it incorrectly.

Suggested change
val functionCall = part.functionCall().orElse(null)
if (
functionCall != null && functionCall.name().orElse(null) == SendA2uiToClientToolset.TOOL_NAME
functionCall != null && functionCall.name().orElse(null) == SendA2uiToRendererToolset.TOOL_NAME
) {
return emptyList()
}
val functionCall = part.functionCall().orElse(null)
val callFnName = functionCall?.name()?.orElse(null)
if (
functionCall != null &&
(callFnName == SendA2uiToRendererToolset.TOOL_NAME || callFnName == "send_a2ui_json_to_client")
) {
return emptyList()
}

Comment on lines +278 to +283
def collect_messages(error: Any) -> list[str]:
msgs = [error.message]
if error.context:
for sub in error.context:
msgs.extend(collect_messages(sub))
return msgs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The helper function collect_messages is defined inside the validate method but is never used anywhere in the function. It should be removed to clean up dead code and avoid redundantly recreating it on every invocation of validate.

References
  1. Avoid defining helper functions inside loops or nested functions where they are redundantly recreated on every iteration. Define them at the module level to improve performance and maintainability.
  2. When refactoring or fixing issues in code, prefer completely removing dead code or redundant checks rather than modifying them with more complex conditional logic.

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.

1 participant