关于 integrate-genui-firebase
这项技能指导开发者在现有 Flutter 应用中加入 genui,并连接 Firebase AI Logic 对话 Agent。它涵盖依赖配置、控制器与事件接线及界面渲染,并要求先确认状态组件和输入控件选择。
主要功能
- 01检查 Firebase 初始化与依赖
- 02添加 genui 并配置日志
- 03连接对话与界面控制器
- 04通过 Firebase AI Logic 传递消息
- 05处理对话事件并渲染界面
- 06先确认状态组件和输入界面
适用场景
- 01在 Flutter 聊天界面集成 GenUI
- 02将聊天会话连接到 Firebase AI Logic
- 03在应用中呈现 Agent 提供的界面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ flutter/ genui --skill integrate-genui-firebase安装后在 Claude Code 中输入/integrate-genui-firebase确认已加载。
详细介绍
将 GenUI 与 Firebase AI Logic 集成
目标
将 genui 包成功集成到 Flutter 应用中,并使用 Firebase AI Logic 设置基本的对话 Agent。本指南假设项目中已设置并正常运行 Firebase AI Logic。
说明
接到集成 genui 并开始简单对话的任务时,请按以下步骤操作:
-
验证 Firebase 设置: 确保
pubspec.yaml中包含firebase_core和firebase_ai。 确认在main()函数中调用了Firebase.initializeApp:WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); -
添加 GenUI 包: 将
genui添加到pubspec.yaml的依赖项中。 -
导入所需库: 导入
genui并隐藏TextPart,以免与其他包冲突,然后再次导入并为其指定别名:import 'package:genui/genui.dart' hide TextPart; import 'package:genui/genui.dart' as genui; -
配置基本日志记录: 在
main()函数开头配置 GenUI 日志记录:configureLogging( logCallback: (level, msg) => debugPrint('GenUI $level: $msg'), ); -
创建模型和聊天会话: 初始化生成式模型并启动聊天会话。
final model = FirebaseAI.googleAI().generativeModel( model: 'gemini-3-flash-preview', ); final _chatSession = model.startChat(); -
确定目标 StatefulWidget: 如果不确定,请暂停并询问用户: 此集成需要一个
StatefulWidget来保存 GenUI 控制器(SurfaceController、A2uiTransportAdapter和Conversation)的引用。确定应用中要使用哪个StatefulWidget。如果不确定哪个 Widget 应保存此状态,请在继续之前询问用户。 -
在 State 中连接 GenUI 控制器: 在已确定的
State类中,实例化SurfaceController、A2uiTransportAdapter和Conversation:final catalog = BasicCatalogItems.asCatalog(); // Optionally inject custom CatalogItems final _controller = SurfaceController(catalogs: [catalog]); final _transport = A2uiTransportAdapter(onSend: _sendAndReceive); final _conversation = Conversation( controller: _controller, transport: _transport, ); -
实现
_sendAndReceive方法: 创建一个方法,从传输适配器获取消息,将其发送到 Firebase,并将 AI 的响应传回传输适配器。Future<void> _sendAndReceive(ChatMessage msg) async { final buffer = StringBuffer(); for (final part in msg.parts) { if (part.isUiInteractionPart) { buffer.write(part.asUiInteractionPart!.interaction); } else if (part is genui.TextPart) { buffer.write(part.text); } } if (buffer.isEmpty) return; final text = buffer.toString(); final response = await _chatSession.sendMessage(Content.text(text)); if (response.text?.isNotEmpty ?? false) { _transport.addChunk(response.text!); } } -
监听 Conversation 事件: 在 State 类中为每种事件类型创建空方法,并添加 DartDoc 注释说明这些方法需要执行的行为。根据界面设计,Agent 发来的新界面和文本会采用不同的处理方式。例如,对话界面可以将所有内容添加到列表中,并显示在
ListView中;而在标题、页脚等特定位置展示 UI 组件的界面,可能会依赖系统指令中提供给 Agent 的特定表面 ID,以确定在哪些位置显示哪些表面。/// Updates state to include the new [surfaceId] so a new `Surface` widget can be built. void _onSurfaceAdded(String surfaceId) { // TODO: Implement state update to add surfaceId } /// Updates state to remove the [surfaceId] so its `Surface` widget is no longer built. void _onSurfaceRemoved(String surfaceId) { // TODO: Implement state update to remove surfaceId } /// Handles displaying raw text content received from the AI to the user. void _onContentReceived(String text) { // TODO: Implement displaying the received text } /// Handles errors that occur during the conversation appropriately. void _onError(Object error) { // TODO: Implement error handling }订阅
_conversation.events,以跟踪 UI 表面或聊天消息的到达情况,并将其分派到相应的空方法:_conversation.events.listen((event) { switch (event) { case ConversationSurfaceAdded added: _onSurfaceAdded(added.surfaceId); case ConversationSurfaceRemoved removed: _onSurfaceRemoved(removed.surfaceId); case ConversationContentReceived content: _onContentReceived(content.text); case ConversationError error: _onError(error.error); default: } }); -
初始化系统提示词: 使用
PromptBuilder为 AI 提供基本指令,然后将其作为系统消息发送。final promptBuilder = PromptBuilder.chat( catalog: catalog, instructions: 'You are a helpful assistant. Respond to messages in a chatty way.', ); _conversation.sendRequest(ChatMessage.system(promptBuilder.systemPrompt)); -
显示表面: 在 Flutter 的
build()方法中,使用在第 9 步收集的surfaceIds,在需要渲染 GenUI Widget 的位置放置SurfaceWidget。Surface(surfaceContext: _controller.contextFor(surfaceId)); -
询问用户的输入偏好: 暂停并询问用户: 请用户说明希望使用哪些 UI 元素来接收输入。说明
TextField和ElevatedButton是不错的默认选项,但除非用户明确选择,否则不要假定他们就想使用这些 Widget。
约束
- 不要擅自假设用户输入 UI 元素;请参阅第 12 步。
- 确保在 Widget 的
dispose()方法中正确清理 GenUI 控制器(_transport.dispose()、_controller.dispose())。