Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ final catalog = CoreCatalogItems.asCatalog().copyWith([

/// Initializing the library.
final genUiManager = GenUiManager(catalog: catalog);
final aiClient = FirebaseAiClient(
final contentGenerator = FirebaseAiContentGenerator(
catalog: catalog,
systemInstruction: '''
You are a bicycle maintenance assistant who is an expert in diagnosing issues and
giving step-by-step instructions.
''',
tools: genUiManager.getTools(),
);
late final _genUiConversation = GenUiConversation(
genUiManager: genUiManager,
aiClient: aiClient,
contentGenerator: contentGenerator,
onSurfaceAdded: _onSurfaceAdded,
onSurfaceDeleted: (_) {},
onTextResponse: (_) {},
Expand All @@ -81,7 +81,7 @@ void _onSurfaceAdded(SurfaceAdded surface) {
Widget build(BuildContext context) {
if (type == MessageType.genUi) {
return GenUiSurface(
host: _genUiConversation.host,
host: _genUiConversation.genUiManager.host,
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The property host does not exist on GenUiManager. The GenUiManager instance itself is the GenUiHost that should be passed to the GenUiSurface. You can either use _genUiConversation.host which is a getter for genUiManager, or access _genUiConversation.genUiManager directly.

Suggested change
host: _genUiConversation.genUiManager.host,
host: _genUiConversation.genUiManager,

surfaceId: _surfaceId,
onEvent: _handleEvent,
);
Expand Down
5 changes: 2 additions & 3 deletions packages/flutter_genui/.guides/examples/riddles.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,14 @@ class _MyHomePageState extends State<MyHomePage> {
final genUiManager = GenUiManager(
catalog: CoreCatalogItems.asCatalog().copyWith([riddleCard]),
);
final contentGenerator = FirebaseContentGenerator(
apiKey: const String.fromEnvironment('GEMINI_API_KEY'),
final contentGenerator = FirebaseAiContentGenerator(
catalog: genUiManager.catalog,
systemInstruction: '''
You are an expert in creating funny riddles. Every time I give you a
word, you should generate a RiddleCard that displays one new riddle
related to that word. Each riddle should have both a question and an
answer.
''',
tools: genUiManager.getTools(),
);
conversation = GenUiConversation(
contentGenerator: contentGenerator,
Expand Down
22 changes: 11 additions & 11 deletions packages/flutter_genui/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ This guidance explains how to quickly get started with the
conversation with the LLM, handles UI state, and orchestrates the interaction
between the app, its UI, and the AI.

- **`AiClient`**: A client that manages communication with your LLM. The package
includes an (optional) `FirebaseAiClient` to communicate with Google's Gemini
- **`ContentGenerator`**: A client that manages communication with your LLM. The package
includes an (optional) `FirebaseAiContentGenerator` to communicate with Google's Gemini
models (using Firebase AI Logic), and you can create your own subclasses for
other models or LLM libraries.

Expand Down Expand Up @@ -40,7 +40,7 @@ below for your preferred provider.

#### Configure Firebase AI Logic

To use the built-in `FirebaseAiClient` to connect to Gemini via Firebase AI
To use the built-in `FirebaseAiContentGenerator` to connect to Gemini via Firebase AI
Logic, follow these instructions:

1. [Create a new Firebase project](https://support.google.com/appsheet/answer/10104995)
Expand Down Expand Up @@ -83,7 +83,7 @@ Logic, follow these instructions:

To use `flutter_genui` with another agent provider, you need to follow that
provider's instructions to configure your app, and then create your own subclass
of `AiClient` to connect to that provider. Use `FirebaseAiClient` as an example
of `ContentGenerator` to connect to that provider. Use `FirebaseAiContentGenerator` as an example
of how to do so.

### 2. Create the connection to an agent
Expand All @@ -105,10 +105,10 @@ provider.

1. Create a `GenUiManager`, and provide it with the catalog of widgets you want
to make available to the agent.
2. Create an `AiClient`, and provide it with a system instruction and a set of
2. Create an `ContentGenerator`, and provide it with a system instruction and a set of
tools (functions you want the agent to be able to invoke). You should always
include those provided by `GenUiManager`, but feel free to include others.
3. Create a `GenUiConversation` using the instances of `AiClient` and `GenUiManager`. Your
3. Create a `GenUiConversation` using the instances of `ContentGenerator` and `GenUiManager`. Your
app will primarily interact with this object to get things done.

For example:
Expand All @@ -126,9 +126,9 @@ provider.
// The CoreCatalogItems contain basic widgets for text, markdown, and images.
_genUiManager = GenUiManager(catalog: CoreCatalogItems.asCatalog());

// Create an AiClient to communicate with the LLM.
// Create a ContentGenerator to communicate with the LLM.
// Provide system instructions and the tools from the GenUiManager.
final aiClient = FirebaseAiClient(
final contentGenerator = FirebaseAiContentGenerator(
systemInstruction: '''
You are an expert in creating funny riddles. Every time I give you a word,
you should generate UI that displays one new riddle related to that word.
Expand All @@ -140,7 +140,7 @@ provider.
// Create the GenUiConversation to orchestrate everything.
_genUiConversation = GenUiConversation(
genUiManager: _genUiManager,
aiClient: aiClient,
contentGenerator: contentGenerator,
onSurfaceAdded: _onSurfaceAdded, // Added in the next step.
onSurfaceDeleted: _onSurfaceDeleted, // Added in the next step.
);
Expand Down Expand Up @@ -349,7 +349,7 @@ instruction to explicitly tell it how and when to do so. Provide the name from
the CatalogItem when you do.

```dart
final aiClient = FirebaseAiClient(
final contentGenerator = FirebaseAiContentGenerator(
systemInstruction: '''
You are an expert in creating funny riddles. Every time I give you a word,
you should generate a RiddleCard that displays one new riddle related to that word.
Expand Down Expand Up @@ -411,7 +411,7 @@ If something is unclear or missing, please

The `flutter_genui` package gives the LLM a set of tools it can use to generate
UI. To get the LLM to use these tools, the `systemInstruction` provided to
`AiClient` must explicitly tell it to do so. This is why the previous example
`ContentGenerator` must explicitly tell it to do so. This is why the previous example
includes a system instruction for the agent with the line "Every time I give
you a word, you should generate UI that displays one new riddle...".

Expand Down
32 changes: 16 additions & 16 deletions packages/flutter_genui_a2ui/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ The problem is to integrate the A2A communication and A2UI message parsing from

The `flutter_genui_a2ui` package will consist of the following key components:

### 1. `A2uiAiClient` (implements `AiClient` from `flutter_genui`)
### 1. `A2uiContentGenerator` (implements `ContentGenerator` from `flutter_genui`)

This will be the central class for connecting the A2A server to the `flutter_genui`'s `UiAgent`. It will implement the `AiClient` interface, but instead of performing AI inference, it will manage the A2A connection and process incoming A2UI messages.
This will be the central class for connecting the A2A server to the `flutter_genui`'s `UiAgent`. It will implement the `ContentGenerator` interface, but instead of performing AI inference, it will manage the A2A connection and process incoming A2UI messages.

- **Dependencies:** `flutter_genui`, `a2a` (for A2A communication).
- **Constructor:**
- `A2uiAiClient({required Uri serverUrl, required GenUiManager genUiManager})`
- `A2uiContentGenerator({required Uri serverUrl, required GenUiManager genUiManager})`
- **Internal State:**
- `A2AClient _a2aClient`: An instance of the A2A client for communication.
- `GenUiManager _genUiManager`: The `GenUiManager` instance provided by the `UiAgent`.
- `StreamController<A2uiMessage> _a2uiMessageController`: A stream controller to process incoming A2UI messages from the A2A server.
- `String? _taskId`, `String? _contextId`: To manage the A2A conversation context.
- `ValueNotifier<int> _activeRequests`: To implement the `activeRequests` getter from `AiClient`.
- `ValueNotifier<int> _activeRequests`: To implement the `activeRequests` getter from `ContentGenerator`.
- **Key Methods:**
- `Future<AgentCard> getAgentCard()`: Fetches the agent card from the A2A server, similar to `A2uiAgentConnector.getAgentCard` in the spike.
- `Future<void> sendUserMessage(String messageText, {void Function(String)? onResponse})`: Sends a user message to the A2A server. This will be called by the `UiAgent`.
Expand All @@ -53,7 +53,7 @@ A comprehensive example application will be created within the `example/` direct
- A chat conversation view to display user input and text responses from the A2A server.
- A fixed UI surface (using `GenUiSurface`) that renders the A2UI-generated interface.
- Input field for sending messages to the A2A agent.
- Clear demonstration of how to initialize `A2uiAiClient` and `UiAgent`.
- Clear demonstration of how to initialize `A2uiContentGenerator` and `UiAgent`.
- Basic error handling and loading indicators.

### 3. `A2uiAgentConnector` (Adapted from spike)
Expand All @@ -65,7 +65,7 @@ The core logic for connecting to the A2A server and handling the raw A2A stream
- Receiving A2A stream events.
- Parsing A2A stream events to extract A2UI protocol messages.

This adapted class will be internal to `flutter_genui_a2ui` and will be used by `A2uiAiClient`.
This adapted class will be internal to `flutter_genui_a2ui` and will be used by `A2uiContentGenerator`.

### 4. `AgentCard` (Adapted from spike)

Expand All @@ -76,19 +76,19 @@ The `AgentCard` class, representing metadata about the A2A agent, will also be *
```mermaid
graph TD
subgraph Flutter App
UiAgent -- "sends UserMessage" --> A2uiAiClient
A2uiAiClient -- "sends A2AMessage" --> A2A_Server["A2A Server"]
A2A_Server -- "sends A2AStreamEvent" --> A2uiAiClient
A2uiAiClient -- "processes A2uiMessage" --> GenUiManager
UiAgent -- "sends UserMessage" --> A2uiContentGenerator
A2uiContentGenerator -- "sends A2AMessage" --> A2A_Server["A2A Server"]
A2A_Server -- "sends A2AStreamEvent" --> A2uiContentGenerator
A2uiContentGenerator -- "processes A2uiMessage" --> GenUiManager
GenUiManager -- "emits GenUiUpdate" --> GenUiSurface
GenUiSurface -- "renders UI" --> User
User -- "interacts with UI" --> GenUiSurface
GenUiSurface -- "dispatches UiEvent" --> GenUiManager
GenUiManager -- "emits UserMessage (from UiEvent)" --> A2uiAiClient
GenUiManager -- "emits UserMessage (from UiEvent)" --> A2uiContentGenerator
end

subgraph `flutter_genui_a2ui` Package
A2uiAiClient
A2uiContentGenerator
A2uiAgentConnector
AgentCard
end
Expand All @@ -105,17 +105,17 @@ graph TD
A2AClient
end

A2uiAiClient -- uses --> A2uiAgentConnector
A2uiContentGenerator -- uses --> A2uiAgentConnector
A2uiAgentConnector -- uses --> A2AClient
A2uiAiClient -- uses --> GenUiManager
UiAgent -- uses --> A2uiAiClient
A2uiContentGenerator -- uses --> GenUiManager
UiAgent -- uses --> A2uiContentGenerator
UiAgent -- uses --> GenUiManager
GenUiSurface -- uses --> GenUiManager
```

## Summary of the Design

The `flutter_genui_a2ui` package will act as a specialized `AiClient` for `flutter_genui`, enabling seamless integration with A2A servers. It will encapsulate the A2A communication logic, translate incoming A2UI messages into `flutter_genui`'s internal UI update mechanisms, and forward user interactions back to the A2A server. This design promotes modularity, reusability, and adherence to the existing `flutter_genui` architecture.
The `flutter_genui_a2ui` package will act as a specialized `ContentGenerator` for `flutter_genui`, enabling seamless integration with A2A servers. It will encapsulate the A2A communication logic, translate incoming A2UI messages into `flutter_genui`'s internal UI update mechanisms, and forward user interactions back to the A2A server. This design promotes modularity, reusability, and adherence to the existing `flutter_genui` architecture.

## References to Research URLs

Expand Down
12 changes: 6 additions & 6 deletions packages/flutter_genui_a2ui/GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ The primary purpose of this package is to facilitate the creation of generative

## Implementation Details

### `A2uiAiClient`
### `A2uiContentGenerator`

This class implements the `AiClient` interface from `flutter_genui`. It acts as the main bridge between the `UiAgent` and the A2UI server. It uses an internal `A2uiAgentConnector` to handle the low-level A2A communication.
This class implements the `ContentGenerator` interface from `flutter_genui`. It acts as the main bridge between the `UiAgent` and the A2UI server. It uses an internal `A2uiAgentConnector` to handle the low-level A2A communication.

- **Constructor:** Takes `serverUrl` (the A2A server endpoint) and `genUiManager` (the `GenUiManager` instance from `flutter_genui`). An optional `A2AClient` can be provided for testing.
- **`generateContent` and `generateText`:** These methods are overridden to send user messages to the A2A server via the `A2uiAgentConnector`. UI updates are driven by the incoming A2UI stream, not direct return values from these methods.
Expand All @@ -24,7 +24,7 @@ This class is responsible for establishing and maintaining the WebSocket connect

- **Constructor:** Takes the `url` of the A2A server. An optional `A2AClient` can be provided for testing.
- **`getAgentCard`:** Fetches metadata about the AI agent from the server.
- **`connectAndSend`:** Establishes a connection (if not already established), sends a user message to the A2A server, and processes the incoming A2A stream, extracting A2UI messages and forwarding them to the `A2uiAiClient`.
- **`connectAndSend`:** Establishes a connection (if not already established), sends a user message to the A2A server, and processes the incoming A2A stream, extracting A2UI messages and forwarding them to the `A2uiContentGenerator`.
- **`sendEvent`:** Sends user interaction events (e.g., button clicks) back to the A2A server.
- **`_processA2uiMessages`:** An internal method to parse raw A2A data parts and convert them into `flutter_genui`'s `A2uiMessage` objects.

Expand All @@ -34,8 +34,8 @@ A simple data class to hold metadata about the A2A agent, including its name, de

## File Layout

- `lib/flutter_genui_a2ui.dart`: Exports the public API of the package (`A2uiAiClient`, `A2uiAgentConnector`, `AgentCard`).
- `lib/src/a2ui_ai_client.dart`: Contains the `A2uiAiClient` implementation.
- `lib/flutter_genui_a2ui.dart`: Exports the public API of the package (`A2uiContentGenerator`, `A2uiAgentConnector`, `AgentCard`).
- `lib/src/a2ui_ai_client.dart`: Contains the `A2uiContentGenerator` implementation.
- `lib/src/a2ui_agent_connector.dart`: Contains the `A2uiAgentConnector` and `AgentCard` implementations.
- `test/a2ui_client_test.dart`: Unit tests for `A2uiAiClient` and `A2uiAgentConnector`.
- `test/a2ui_client_test.dart`: Unit tests for `A2uiContentGenerator` and `A2uiAgentConnector`.
- `example/`: Contains a sample Flutter application demonstrating the usage of the `flutter_genui_a2ui` package.
Loading
Loading