Skip to content

Migrate Rizzcharts client sample to use v0_9 angular renderer#1116

Open
suyangw-g wants to merge 1 commit intogoogle:mainfrom
suyangw-g:rizzcharts_v0.9
Open

Migrate Rizzcharts client sample to use v0_9 angular renderer#1116
suyangw-g wants to merge 1 commit intogoogle:mainfrom
suyangw-g:rizzcharts_v0.9

Conversation

@suyangw-g
Copy link
Copy Markdown
Collaborator

@suyangw-g suyangw-g commented Apr 9, 2026

This PR migrates the rizzcharts client sample and the shared a2a-chat-canvas library to use the new v0_9 Angular renderer and message protocol. This involves a shift from the path-based data resolution pattern to a more direct, property-bound approach using reactive inputs.

Key Changes

1. Protocol Update to v0.9

  • Updated extractA2uiDataParts in a2a-chat-canvas to process v0.9 message types: createSurface, updateComponents, updateDataModel, and deleteSurface (replacing beginRendering, surfaceUpdate, etc.).
  • Migrated imports to use @a2ui/web_core/v0_9.

2. Catalog Refactoring

  • Replaced the old object-based Catalog definition in rizzcharts with the new AngularCatalog class.
  • Custom components (Canvas, Chart, GoogleMap, YouTube) are now registered with a unique URI and mapped using the new catalog structure alongside BASIC_COMPONENTS.

3. Component Refactoring (Removal of DynamicComponent)

  • Components in rizzcharts no longer extend DynamicComponent.
  • Instead of pulling data via resolvePrimitive and complex path strings (e.g., ${pathPrefix.path}[${index}]), components now receive data via a single props input: input<Record<string, BoundProperty>>({}).
  • This significantly simplifies component logic, as seen in Chart and GoogleMap, where arrays and objects are iterated over directly as resolved JavaScript objects rather than being fetched by path in a loop.

4. Build & Configuration

  • Updated tsconfig files in both projects to handle path mappings and dependencies correctly for the new version.
  • Updated the README.md to reflect that dependencies now build from renderers/web_core and renderers/markdown instead of renderers/lit.

Files Modified (Summary)

  • Core/Catalog: catalog.ts, chart.ts, google-map.ts, youtube.ts in rizzcharts.
  • Shared Library: a2a-chat-canvas configuration, services, and utilities (a2ui.ts).
  • Documentation: samples/client/angular/README.md.

Copy link
Copy Markdown
Contributor

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

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 Angular client samples to the A2UI v0.9 architecture, updating message handling from 'beginRendering' to 'createSurface' and refactoring custom components like Canvas, Chart, and GoogleMap to use the new 'props' input system. Feedback focuses on addressing a regression in error handling within the ChatService, enhancing type safety by replacing 'any' types with specific interfaces in component inputs, and removing an obsolete 'title' property in the YouTube component.

Comment on lines +77 to 86
this.a2uiRenderer.surfaceGroup.onAction.subscribe(async (action: A2uiClientAction) => {
try {
// TODO: Replace this with a more robust event handling mechanism.
// Send A2UI actions silently if requested from the action context
const isSilent = Boolean(event.message.userAction?.context?.['silent']);
await this.sendMessage(JSON.stringify(event.message), isSilent);
event.completion.next([]);
event.completion.complete();
const isSilent = Boolean(action.context?.['silent']);
await this.sendMessage(JSON.stringify({ version: 'v0.9', action }), isSilent);
} catch (err) {
event.completion.error(err);
console.error('Failed to send action:', err);
}
});
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 error handling for A2UI actions has been simplified to just console.error. This is a regression from the previous implementation which propagated errors via event.completion.error(err). This change could lead to user actions failing silently without any feedback. Consider implementing a more robust error handling mechanism, such as displaying a notification to the user, to improve the user experience.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In the older implementation (e.g., using MessageProcessor.events), we had access to event.completion.error. With the migration to the v0_9 renderer and surfaceGroup.onAction, that specific completion handle isn't available on the event.

* @param child The component node, either as a string ID or an object.
* @returns The string ID of the component.
*/
protected getComponentId(child: string | any): string {
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

Using any for the child parameter type is not type-safe and reduces code maintainability. It's better to use a more specific type. Based on the usage, it seems child could be typed as string | { id: string } which would be more appropriate and safer.

Suggested change
protected getComponentId(child: string | any): string {
protected getComponentId(child: string | { id: string }): string {


private resolvePieChartData(
pathPrefix: Primitives.StringValue,
dataArray: any[],
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

Using any[] for dataArray is not type-safe. It's better to define a specific interface for the chart data items to improve maintainability and prevent potential errors.

For example:

interface ChartDataItem {
  label: string;
  value: number;
  drillDown?: ChartDataItem[];
}

Then you can use ChartDataItem[] as the type.

Suggested change
dataArray: any[],
dataArray: { label: string; value: number; drillDown?: any[] }[],


private resolveLocations(value: CustomProperties | undefined): Pin[] {
protected readonly resolvedPins = computed(() => {
const pinsArray = this.props()['pins']?.value() as any[];
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

Casting pinsArray to any[] is not type-safe. For better code clarity and to prevent potential runtime errors, you should define a specific interface for the pin data and use it for the type assertion.

For example:

interface PinData {
  lat: number;
  lng: number;
  name: string;
  description?: string;
  background?: string;
  borderColor?: string;
  glyphColor?: string;
}
Suggested change
const pinsArray = this.props()['pins']?.value() as any[];
const pinsArray = this.props()['pins']?.value() as { lat: number; lng: number; name: string; [key: string]: any }[];

this.props()['videoId']?.value() as string | null
);

readonly title = input<Primitives.StringValue | null>();
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

This title input property appears to be a remnant from before the refactoring. Since the component now receives its data via the props input, this property is unused and should be removed to avoid confusion and clean up the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants