一键导入
genui-workshop-step-6
Execute Step 6 of the GenUI Workshop, creating the weather input widget and updating the system prompt.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Execute Step 6 of the GenUI Workshop, creating the weather input widget and updating the system prompt.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Creates a shell script to build and run the Flutter web app on Cloud Shell using a local HTTP server.
Execute Step 3 of the GenUI Workshop, creating the empty Flutter project and adding dependencies.
Execute Step 4 of the GenUI Workshop, setting up the GenUI scaffolding and initial chat interface.
Execute Step 5 of the GenUI Workshop, integrating the GenUI package into the Flutter app.
Execute Step 7 of the GenUI Workshop, creating the weather card widget and fake forecast data.
Orchestrates the discovery, mapping, design, and implementation of a premium Flutter-based frontend for an Agent Development Kit (ADK) agent written with Python.
| name | genui_workshop_step_6 |
| description | Execute Step 6 of the GenUI Workshop, creating the weather input widget and updating the system prompt. |
Goal: Execute Step 6 of the GenUI workshop.
Instructions: Use your code editing tools to create the weather input catalog widget and update the app's configuration.
lib/catalog/weather_input.dart:import 'package:flutter/material.dart';
import 'package:genui/genui.dart';
import 'package:json_schema_builder/json_schema_builder.dart';
final simpleWeatherSchema = S.object(
properties: {
'location': S.string(description: 'The location to check the weather.'),
'date': S.string(description: 'The date to check the weather.'),
},
);
final weatherInput = CatalogItem(
name: 'WeatherInput',
dataSchema: simpleWeatherSchema,
widgetBuilder: (itemContext) {
final json = itemContext.data as Map<String, Object?>;
final data = SimpleWeatherData.fromJson(json);
return WeatherInput(
data: data,
onFetchRequest: (loc, date) async {
final JsonMap resolvedContext = await resolveContext(
itemContext.dataContext,
{'location': loc, 'date': date.toString()},
);
itemContext.dispatchEvent(
UserActionEvent(
name: 'submit_weather_request',
sourceComponentId: 'submitButton',
timestamp: DateTime.now(),
context: resolvedContext
),
);
},
);
},
);
class SimpleWeatherData {
String location;
DateTime date;
SimpleWeatherData({required this.location, required this.date});
factory SimpleWeatherData.defaultValues() {
return SimpleWeatherData(location: 'Baltimore', date: DateTime.now());
}
factory SimpleWeatherData.fromJson(Map<String, Object?> json) {
if (json.isNotEmpty) {
return SimpleWeatherData(
location: json['location'] as String,
date: DateTime.parse(json['date'] as String),
);
} else {
return SimpleWeatherData(location: 'Baltimore', date: DateTime.now());
}
}
}
class WeatherInput extends StatefulWidget {
final SimpleWeatherData data;
final void Function(String, DateTime) onFetchRequest;
const WeatherInput({
super.key,
required this.data,
required this.onFetchRequest,
});
@override
State<WeatherInput> createState() => _WeatherInputState();
}
class _WeatherInputState extends State<WeatherInput> {
late TextEditingController _controller;
DateTime? selectedDate = DateTime.now();
Future<void> _selectDate() async {
final DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now().copyWith(month: 1, day: 1),
lastDate: DateTime.now().copyWith(month: 12, day: 31),
);
setState(() {
selectedDate = pickedDate;
});
}
@override
void initState() {
super.initState();
_controller = TextEditingController();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: 320,
padding: const EdgeInsets.all(16),
child: Card(
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Location", style: TextStyle(fontWeight: FontWeight.bold) ),
const SizedBox(height: 8),
TextField(decoration: InputDecoration(border: OutlineInputBorder()), controller: _controller,),
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
height: 50,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
),
onPressed: () {
widget.onFetchRequest(_controller.text, selectedDate!);
},
child: const Text("Get Forecast", style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold)),
),
),
],
),
),
),
);
}
}
lib/genui_utils.dart to append the UI instruction to systemInstruction:const systemInstruction = '''
## PERSONA
You are a meteorologist.
## GOAL
Work with me to produce of weather forecasts.
## RULES
Do not offer opinions unless I ask for them.
## PROCESS
### Planning
* Ask me for a location to check the weather.
* Follow up and ask for a date if not provided.
* Synthesize a list of weather forecasts from the provided information.
* Where available, you will use tool calls to retreive the info (not implemented yet)
* Advise if you are pulling the data from a real source or making it up.
* Ask clarifying questions if you need to.
* Respond to my suggestions for changes to date or location, if I have any.
## USER INTERFACE
* To request the location to retreive weather, create an instance of the WeatherInput
catalog item.
''';
(Hint: Make sure the rest of genui_utils.dart remains intact.)
lib/main.dart to import the new catalog item and add it to BasicCatalogItems.asCatalog().copyWith(...):
Add this import at the top:import 'package:genui_workshop/catalog/weather_input.dart';
And in initState, modify catalog = BasicCatalogItems.asCatalog().copyWith(); to:
catalog = BasicCatalogItems.asCatalog().copyWith(
newItems: [weatherInput],
);