diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000..cfcb44c9c --- /dev/null +++ b/examples/README.md @@ -0,0 +1,35 @@ +# Examples + +This directory contains example applications demonstrating the `genui` SDK +capabilities. + +## Overview + +| Example | Complexity | Backend | Description | +|---------|------------|---------|-------------| +| [catalog_gallery][catalog_gallery] | Simple | None | Visual reference for core catalog widgets | +| [custom_backend][custom_backend] | Intermediate | JSON `assets` | Demonstrates custom backend integration | +| [simple_chat][simple_chat] | Intermediate | Firebase/Google AI | A simple, conversational chat application. | +| [travel_app][travel_app] | Advanced | Firebase/Google AI | Full travel planning assistant with custom catalog | +| [verdure][verdure] | Advanced | Python A2A Server | Full-stack landscape design agent | + +[catalog_gallery]: https://github.com/flutter/genui/tree/main/examples/catalog_gallery +[custom_backend]: https://github.com/flutter/genui/tree/main/examples/custom_backend +[simple_chat]: https://github.com/flutter/genui/tree/main/examples/simple_chat +[travel_app]: https://github.com/flutter/genui/tree/main/examples/travel_app +[verdure]: https://github.com/flutter/genui/tree/main/examples/verdure + +Each example directory contains a more detailed `README.md` file with +its specific instructions. + +--- + +## Choosing an Example + +| Goal | Recommended Example | +|------|---------------------| +| Understand core widgets | `catalog_gallery` | +| Basic use of the SDK | `simple_chat` | +| Build custom backend integration | `custom_backend` | +| Build a production-like app with custom catalog | `travel_app` | +| Implement client-server architecture with A2A | `verdure` | diff --git a/examples/catalog_gallery/README.md b/examples/catalog_gallery/README.md index ec185dad1..4f8beebb6 100644 --- a/examples/catalog_gallery/README.md +++ b/examples/catalog_gallery/README.md @@ -1,16 +1,18 @@ # catalog_gallery -A new Flutter project. +A developer tool for visualizing and testing the core widget catalog. Displays all available `CoreCatalogItems` widgets and allows interaction testing. -## Getting Started - -This project is a starting point for a Flutter application. +**Key Features:** +- Browse all core catalog widgets +- Interactive widget testing with event logging +- Sample file loading support -A few resources to get you started if this is your first Flutter project: +## Getting Started -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) +This is a standard Flutter app, and can be run with `flutter run`. -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +**Run:** +```bash +cd examples/catalog_gallery +flutter run +``` diff --git a/examples/custom_backend/README.md b/examples/custom_backend/README.md index de9b08a5a..2b7ad5cd9 100644 --- a/examples/custom_backend/README.md +++ b/examples/custom_backend/README.md @@ -1,3 +1,31 @@ # custom_backend -An example that illustrates how custom backend can interact with genui. +This app demonstrates integrating genui with a custom backend without using +predefined provider packages (`genui_firebase_ai`, +`genui_google_generative_ai`). + +**Key Features:** +- Direct integration with `A2uiMessageProcessor` +- Manual tool call parsing and handling +- Saved response testing for development without API calls +- Shows how to build `UiSchemaDefinition` and `catalogToFunctionDeclaration` + +**Key Files:** +- `lib/backend.dart` - Custom backend implementation +- `lib/gemini_client.dart` - Direct Gemini API client +- `assets/data/saved-response-*.json` - Pre-recorded responses for testing + +## Getting Started + +This is a standard flutter app that directly calls the Gemini API. You need +a Gemini API Key. Get one in [Google AI Studio][ai-studio]. + +Then pass it as a `--dart-define` when calling `flutter run`: + +**Run:** +```bash +cd examples/custom_backend +flutter run --dart-define=GEMINI_API_KEY=YOUR_API_KEY +``` + +[ai-studio]: https://aistudio.google.com/api-keys diff --git a/packages/genui/CHANGELOG.md b/packages/genui/CHANGELOG.md index 30fe40926..05cfe5daf 100644 --- a/packages/genui/CHANGELOG.md +++ b/packages/genui/CHANGELOG.md @@ -5,6 +5,7 @@ - **Fix**: Improved error handling for catalog example loading to include context about the invalid item (#653). - **BREAKING**: Renamed `ChatMessageWidget` to `ChatMessageView` and `InternalMessageWidget` to `InternalMessageView` (#661). - **Fix**: Pass the correct `catalogId` in `DebugCatalogView` widget (#676). +- Added some dart documentation and an `example` directory to improve `package:genui` pub score. ## 0.6.1 diff --git a/packages/genui/example/README.md b/packages/genui/example/README.md new file mode 100644 index 000000000..935176061 --- /dev/null +++ b/packages/genui/example/README.md @@ -0,0 +1,9 @@ +Check the `examples` directory at the root of the `flutter/genui` monorepo for +several sample apps demonstrating the SDK: + +* https://github.com/flutter/genui/tree/main/examples + +Each example is backed by a different backend stack. Check the [README.md][1] +file there for more information about each example. + +[1]: https://github.com/flutter/genui/blob/main/examples/README.md diff --git a/packages/genui/lib/src/model/a2ui_schemas.dart b/packages/genui/lib/src/model/a2ui_schemas.dart index 6e35030d0..1c0f02c7b 100644 --- a/packages/genui/lib/src/model/a2ui_schemas.dart +++ b/packages/genui/lib/src/model/a2ui_schemas.dart @@ -9,7 +9,7 @@ import 'tools.dart'; /// Provides a set of pre-defined, reusable schema objects for common /// A2UI patterns, simplifying the creation of CatalogItem definitions. -class A2uiSchemas { +abstract final class A2uiSchemas { /// Schema for a value that can be either a literal string or a /// data-bound path to a string in the DataModel. If both path and /// literal are provided, the value at the path will be initialized diff --git a/packages/genui/lib/src/model/catalog_item.dart b/packages/genui/lib/src/model/catalog_item.dart index 4e1715a02..b1a18a9dc 100644 --- a/packages/genui/lib/src/model/catalog_item.dart +++ b/packages/genui/lib/src/model/catalog_item.dart @@ -25,7 +25,17 @@ typedef ExampleBuilderCallback = String Function(); /// A callback that builds a widget for a catalog item. typedef CatalogWidgetBuilder = Widget Function(CatalogItemContext itemContext); +/// Context provided to a [CatalogItem]'s widget builder. +/// +/// This class encapsulates all the information and callbacks needed to build +/// a catalog widget, including access to the widget's data, its position in +/// the component tree, and mechanisms for building children and dispatching +/// events. class CatalogItemContext { + /// Creates a [CatalogItemContext] with the required parameters. + /// + /// All parameters are required to ensure the widget builder has complete + /// context for rendering and interaction. CatalogItemContext({ required this.data, required this.id, @@ -37,13 +47,28 @@ class CatalogItemContext { required this.surfaceId, }); + /// The parsed data for this component from the AI-generated definition. final Object data; + + /// The unique identifier for this component instance. final String id; + + /// Callback to build a child widget by its component ID. final ChildBuilderCallback buildChild; + + /// Callback to dispatch UI events (e.g., button taps) back to the system. final DispatchEventCallback dispatchEvent; + + /// The Flutter [BuildContext] for this widget. final BuildContext buildContext; + + /// The [DataContext] for accessing and modifying the data model. final DataContext dataContext; + + /// Callback to retrieve a component definition by its ID. final GetComponentCallback getComponent; + + /// The ID of the surface this component belongs to. final String surfaceId; } diff --git a/packages/genui/lib/src/model/chat_message.dart b/packages/genui/lib/src/model/chat_message.dart index e18fa3120..5038bba58 100644 --- a/packages/genui/lib/src/model/chat_message.dart +++ b/packages/genui/lib/src/model/chat_message.dart @@ -242,5 +242,9 @@ final class AiUiMessage extends ChatMessage { final String surfaceId; + /// The parts of this message, containing a text description of the UI. + /// + /// This is automatically generated from the [definition] and provides + /// context for the AI about the current UI state. final List parts; } diff --git a/packages/genui/lib/test/fake_content_generator.dart b/packages/genui/lib/test/fake_content_generator.dart index bde6dc8f3..372c9ce79 100644 --- a/packages/genui/lib/test/fake_content_generator.dart +++ b/packages/genui/lib/test/fake_content_generator.dart @@ -9,7 +9,15 @@ import 'package:flutter/foundation.dart'; import '../genui.dart'; /// A fake [ContentGenerator] for use in tests. +/// +/// This implementation allows tests to control AI responses by: +/// - Tracking calls to [sendRequest] via [sendRequestCallCount] +/// - Capturing the last message and history via [lastMessage] and [lastHistory] +/// - Emitting fake A2UI messages via [addA2uiMessage] +/// - Emitting fake text responses via [addTextResponse] +/// - Pausing execution via [sendRequestCompleter] class FakeContentGenerator implements ContentGenerator { + /// Creates a new [FakeContentGenerator] instance. FakeContentGenerator(); final _a2uiMessageController = StreamController.broadcast();