genui_a2ui 0.7.0 copy "genui_a2ui: ^0.7.0" to clipboard
genui_a2ui: ^0.7.0 copied to clipboard

Integration package for genui and A2UI Streaming UI Protocol.

genui_a2ui #

An integration package for genui and the A2UI Streaming UI Protocol. This package allows Flutter applications to connect to an A2A (Agent-to-Agent) server and render dynamic user interfaces generated by an AI agent using the genui framework.

Features #

  • A2A Server Connection: Establishes and manages a WebSocket connection to any server implementing the A2A protocol.
  • A2UI Message Processing: Receives and parses A2UI messages (like SurfaceUpdate, DataModelUpdate, BeginRendering) from the A2A stream.
  • Dynamic UI Rendering: Integrates seamlessly with genui's GenUiSurface to render UIs based on the received A2UI messages.
  • Content Generator Implementation: Provides A2uiContentGenerator, a specialized ContentGenerator for genui's GenUiConversation to handle the A2A communication flow.
  • Event Handling: Captures UI events from genui and sends them back to the A2A server as A2A messages.
  • Stateful Conversation: Maintains the conversation context (taskId, contextId) with the A2A server.

Getting Started #

Prerequisites #

  • A Flutter project.
  • An A2A server endpoint that implements the A2UI Streaming UI Protocol.

Installation #

Use flutter pub add to add the latest versions of genui and genui_a2ui as dependencies in your pubspec.yaml file:

flutter pub add genui genui_a2ui 

Basic Usage #

  1. Initialize A2uiMessageProcessor: Set up A2uiMessageProcessor with your widget Catalog.
  2. Create A2uiContentGenerator: Instantiate A2uiContentGenerator, providing the A2A server Uri.
  3. Create GenUiConversation: Pass the A2uiContentGenerator to the GenUiConversation.
  4. Render with GenUiSurface: Use GenUiSurface widgets in your UI to display the agent-generated content.
  5. Send Messages: Use GenUiConversation.sendRequest to send user input to the agent.
import 'package:flutter/material.dart'; import 'package:genui/genui.dart'; import 'package:genui_a2ui/genui_a2ui.dart'; import 'package:logging/logging.dart'; void main() { // Setup logging Logger.root.level = Level.ALL; Logger.root.onRecord.listen((record) { print('${record.level.name}: ${record.time}: ${record.message}'); if (record.error != null) { print(record.error); } if (record.stackTrace != null) { print(record.stackTrace); } }); runApp(const GenUIExampleApp()); } class GenUIExampleApp extends StatelessWidget { const GenUIExampleApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'A2UI Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: const ChatScreen(), ); } } class ChatScreen extends StatefulWidget { const ChatScreen({super.key}); @override State<ChatScreen> createState() => _ChatScreenState(); } class _ChatScreenState extends State<ChatScreen> { final TextEditingController _textController = TextEditingController(); final A2uiMessageProcessor _a2uiMessageProcessor = A2uiMessageProcessor(catalog: CoreCatalogItems.asCatalog()); late final A2uiContentGenerator _contentGenerator; late final GenUiConversation _uiAgent; final List<ChatMessage> _messages = []; @override void initState() { super.initState(); _contentGenerator = A2uiContentGenerator( serverUrl: Uri.parse('http://localhost:8080'), // Replace with your A2A server URL ); _uiAgent = GenUiConversation( contentGenerator: _contentGenerator, a2uiMessageProcessor: _a2uiMessageProcessor, ); // Listen for text responses from the agent _contentGenerator.textResponseStream.listen((String text) { setState(() { _messages.insert(0, AgentMessage.text(text)); }); }); // Listen for errors _contentGenerator.errorStream.listen((ContentGeneratorError error) { print('Error from ContentGenerator: ${error.error}'); // Optionally show error to the user }); } @override void dispose() { _textController.dispose(); _uiAgent.dispose(); _a2uiMessageProcessor.dispose(); _contentGenerator.dispose(); super.dispose(); } void _handleSubmitted(String text) { if (text.isEmpty) return; _textController.clear(); final message = UserMessage.text(text); setState(() { _messages.insert(0, message); }); _uiAgent.sendRequest(message); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('A2UI Example'), ), body: Column( children: <Widget>[ Expanded( child: ListView.builder( padding: const EdgeInsets.all(8.0), reverse: true, itemBuilder: (_, int index) => _buildMessage(_messages[index]), itemCount: _messages.length, ), ), const Divider(height: 1.0), Container( decoration: BoxDecoration(color: Theme.of(context).cardColor), child: _buildTextComposer(), ), // Surface for the main AI-generated UI SizedBox( height: 300, child: GenUiSurface( host: _a2uiMessageProcessor, surfaceId: 'main_surface', )), ], ), ); } Widget _buildMessage(ChatMessage message) { return Container( margin: const EdgeInsets.symmetric(vertical: 10.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Container( margin: const EdgeInsets.only(right: 16.0), child: CircleAvatar(child: Text(message is UserMessage ? 'U' : 'A')), ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text(message is UserMessage ? 'User' : 'Agent', style: const TextStyle(fontWeight: FontWeight.bold)), Container( margin: const EdgeInsets.only(top: 5.0), child: Text(message.parts.whereType<TextPart>().map((e) => e.text).join('\n')), ), ], ), ), ], ), ); } Widget _buildTextComposer() { return IconTheme( data: IconThemeData(color: Theme.of(context).colorScheme.secondary), child: Container( margin: const EdgeInsets.symmetric(horizontal: 8.0), child: Row( children: <Widget>[ Flexible( child: TextField( controller: _textController, onSubmitted: _handleSubmitted, decoration: const InputDecoration.collapsed(hintText: 'Send a message'), ), ), Container( margin: const EdgeInsets.symmetric(horizontal: 4.0), child: IconButton( icon: const Icon(Icons.send), onPressed: () => _handleSubmitted(_textController.text)), ), ], ), ), ); } } 

Key Components #

  • A2uiContentGenerator: Implements ContentGenerator. Manages the connection to the A2A server and processes incoming A2UI messages, updating the A2uiMessageProcessor.
  • A2uiAgentConnector: Handles the low-level WebSocket communication with the A2A server, including sending messages and parsing stream events.
  • AgentCard: A data class holding metadata about the connected AI agent.

Example App #

See the example/ directory for a more complete application demonstrating the usage of this package.

Further Information #

7
likes
150
points
1.4k
downloads

Documentation

API reference

Publisher

verified publisherlabs.flutter.dev

Weekly Downloads

Integration package for genui and A2UI Streaming UI Protocol.

License

BSD-3-Clause (license)

Dependencies

flutter, freezed_annotation, genui, http, json_annotation, json_schema_builder, logging, sse_channel, uuid

More

Packages that depend on genui_a2ui