refactor: unify skills+cli runtime and streamline ag-ui flow

This commit is contained in:
qzl
2026-04-22 17:09:37 +08:00
parent eeed737949
commit 4d55df45ab
111 changed files with 4858 additions and 3264 deletions
@@ -0,0 +1,190 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
import 'package:social_app/l10n/app_localizations.dart';
import 'package:social_app/shared/widgets/ui_schema/ui_schema_renderer.dart';
Map<String, dynamic> _toolResultSchema({
required String status,
required List<Map<String, dynamic>> children,
}) {
return {
'version': '2.0',
'status': status,
'locale': 'zh-CN',
'root': {
'type': 'stack',
'direction': 'vertical',
'gap': 12,
'appearance': 'card',
'children': children,
},
};
}
Widget _buildRendererHost(Map<String, dynamic> schema, Locale locale) {
return MaterialApp(
locale: locale,
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: Scaffold(
body: Builder(
builder: (context) {
final colorScheme = Theme.of(context).colorScheme;
return UiSchemaRenderer(context, colorScheme).renderSchema(schema);
},
),
),
);
}
void main() {
testWidgets('renders tool result with success status', (tester) async {
final schema = _toolResultSchema(
status: 'success',
children: [
{'type': 'text', 'content': '日程创建成功', 'role': 'title'},
{
'type': 'kv',
'items': [
{'key': 'title', 'label': '主题', 'value': '项目周会'},
{'key': 'time', 'label': '时间', 'value': '2026-04-22 15:00'},
],
},
],
);
await tester.pumpWidget(_buildRendererHost(schema, const Locale('zh')));
expect(find.text('日程创建成功'), findsOneWidget);
expect(find.text('主题'), findsOneWidget);
expect(find.text('项目周会'), findsOneWidget);
});
testWidgets('renders tool result with partial status badge', (tester) async {
final schema = _toolResultSchema(
status: 'partial',
children: [
{
'type': 'stack',
'direction': 'horizontal',
'gap': 8,
'children': [
{'type': 'text', 'content': '批量操作结果', 'role': 'title'},
{'type': 'badge', 'label': 'ui.status.warning', 'status': 'warning'},
],
},
{'type': 'text', 'content': '成功 2 项,失败 1 项', 'role': 'body'},
],
);
await tester.pumpWidget(_buildRendererHost(schema, const Locale('zh')));
expect(find.text('批量操作结果'), findsOneWidget);
expect(find.text('提醒'), findsOneWidget);
});
testWidgets('renders tool result with action buttons', (tester) async {
final schema = _toolResultSchema(
status: 'success',
children: [
{'type': 'text', 'content': '日程已创建', 'role': 'title'},
{
'type': 'stack',
'direction': 'horizontal',
'gap': 8,
'children': [
{
'type': 'button',
'label': '查看详情',
'style': 'primary',
'action': {'type': 'navigation', 'path': '/calendar/evt_123'},
},
{
'type': 'button',
'label': '分享',
'style': 'secondary',
'action': {'type': 'tool', 'toolId': 'calendar.share', 'params': {}},
},
],
},
],
);
await tester.pumpWidget(_buildRendererHost(schema, const Locale('zh')));
expect(find.text('日程已创建'), findsOneWidget);
expect(find.text('查看详情'), findsOneWidget);
expect(find.text('分享'), findsOneWidget);
});
testWidgets('renders error status tool result', (tester) async {
final schema = _toolResultSchema(
status: 'error',
children: [
{'type': 'text', 'content': '操作失败', 'role': 'title', 'status': 'error'},
{'type': 'text', 'content': '您没有权限执行此操作', 'role': 'body', 'status': 'error'},
{
'type': 'button',
'label': '重试',
'style': 'primary',
'action': {'type': 'tool', 'toolId': 'calendar.read', 'params': {}},
},
],
);
await tester.pumpWidget(_buildRendererHost(schema, const Locale('zh')));
expect(find.text('操作失败'), findsOneWidget);
expect(find.text('您没有权限执行此操作'), findsOneWidget);
expect(find.text('重试'), findsOneWidget);
});
testWidgets('renders calendar event list from tool result', (tester) async {
final schema = _toolResultSchema(
status: 'success',
children: [
{'type': 'text', 'content': '今日日程 (3)', 'role': 'title'},
{
'type': 'stack',
'direction': 'vertical',
'gap': 12,
'children': [
{
'type': 'stack',
'direction': 'vertical',
'gap': 4,
'appearance': 'card',
'children': [
{'type': 'text', 'content': '项目周会', 'role': 'subtitle'},
{'type': 'text', 'content': '15:00 - 16:00', 'role': 'caption'},
],
},
{
'type': 'stack',
'direction': 'vertical',
'gap': 4,
'appearance': 'card',
'children': [
{'type': 'text', 'content': '客户演示', 'role': 'subtitle'},
{'type': 'text', 'content': '17:00 - 18:00', 'role': 'caption'},
],
},
],
},
],
);
await tester.pumpWidget(_buildRendererHost(schema, const Locale('zh')));
expect(find.text('今日日程 (3)'), findsOneWidget);
expect(find.text('项目周会'), findsOneWidget);
expect(find.text('客户演示'), findsOneWidget);
});
testWidgets('handles null schema gracefully', (tester) async {
await tester.pumpWidget(_buildRendererHost({}, const Locale('zh')));
expect(find.byType(SizedBox), findsWidgets);
});
}