Retry agent skill loading after transient errors
This commit is contained in:
@@ -21,6 +21,8 @@ class _VersionTestApi extends ApiRepository {
|
||||
List<String> deletedFiles = const [];
|
||||
String? registeredProject;
|
||||
String? unregisteredProject;
|
||||
int skillFailuresRemaining = 0;
|
||||
int skillLoadCount = 0;
|
||||
|
||||
@override
|
||||
Future<String> getModelName() async => 'gemma4:e2b';
|
||||
@@ -40,23 +42,30 @@ class _VersionTestApi extends ApiRepository {
|
||||
];
|
||||
|
||||
@override
|
||||
Future<List<AgentSkillDescriptor>> getAgentSkills() async => const [
|
||||
AgentSkillDescriptor(
|
||||
id: 'code_explain',
|
||||
name: 'شرح الكود',
|
||||
description: 'شرح المصدر.',
|
||||
),
|
||||
AgentSkillDescriptor(
|
||||
id: 'code_review',
|
||||
name: 'مراجعة الكود',
|
||||
description: 'مراجعة المصدر.',
|
||||
),
|
||||
AgentSkillDescriptor(
|
||||
id: 'test_plan',
|
||||
name: 'خطة اختبارات',
|
||||
description: 'اقتراح الاختبارات.',
|
||||
),
|
||||
];
|
||||
Future<List<AgentSkillDescriptor>> getAgentSkills() async {
|
||||
skillLoadCount++;
|
||||
if (skillFailuresRemaining > 0) {
|
||||
skillFailuresRemaining--;
|
||||
throw StateError('temporary API failure');
|
||||
}
|
||||
return const [
|
||||
AgentSkillDescriptor(
|
||||
id: 'code_explain',
|
||||
name: 'شرح الكود',
|
||||
description: 'شرح المصدر.',
|
||||
),
|
||||
AgentSkillDescriptor(
|
||||
id: 'code_review',
|
||||
name: 'مراجعة الكود',
|
||||
description: 'مراجعة المصدر.',
|
||||
),
|
||||
AgentSkillDescriptor(
|
||||
id: 'test_plan',
|
||||
name: 'خطة اختبارات',
|
||||
description: 'اقتراح الاختبارات.',
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<SavedConversation>> listConversations() async => [];
|
||||
@@ -164,6 +173,36 @@ class _MemorySettingsStore extends LocalSettingsStore {
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('agent skills retry a transient API failure during startup', () async {
|
||||
final api = _VersionTestApi()..skillFailuresRemaining = 1;
|
||||
final cubit = ChatCubit(api, settingsStore: LocalSettingsStore.inMemory());
|
||||
|
||||
await Future<void>.delayed(const Duration(milliseconds: 450));
|
||||
|
||||
expect(api.skillLoadCount, 2);
|
||||
expect(cubit.state.availableSkills, hasLength(3));
|
||||
expect(cubit.state.error, isNull);
|
||||
await cubit.close();
|
||||
});
|
||||
|
||||
test(
|
||||
'agent skills preserve an error after all startup retries fail',
|
||||
() async {
|
||||
final api = _VersionTestApi()..skillFailuresRemaining = 3;
|
||||
final cubit = ChatCubit(
|
||||
api,
|
||||
settingsStore: LocalSettingsStore.inMemory(),
|
||||
);
|
||||
|
||||
await Future<void>.delayed(const Duration(milliseconds: 1200));
|
||||
|
||||
expect(api.skillLoadCount, 3);
|
||||
expect(cubit.state.availableSkills, isEmpty);
|
||||
expect(cubit.state.error, contains('تعذر تحميل مهارات الوكيل'));
|
||||
await cubit.close();
|
||||
},
|
||||
);
|
||||
|
||||
test('embedding-only models are not selectable for chat', () async {
|
||||
final api = _VersionTestApi();
|
||||
final cubit = ChatCubit(api, settingsStore: LocalSettingsStore.inMemory());
|
||||
@@ -197,14 +236,8 @@ void main() {
|
||||
]);
|
||||
expect(message, contains('فُهرست 2 ملفًا'));
|
||||
expect(message, contains('4 مقطعًا'));
|
||||
expect(
|
||||
progressUpdates,
|
||||
contains('يفهرس الملف 1/2: README.md…'),
|
||||
);
|
||||
expect(
|
||||
progressUpdates,
|
||||
contains('يفهرس الملف 2/2: main.dart…'),
|
||||
);
|
||||
expect(progressUpdates, contains('يفهرس الملف 1/2: README.md…'));
|
||||
expect(progressUpdates, contains('يفهرس الملف 2/2: main.dart…'));
|
||||
expect(cubit.state.agentProgress, isNull);
|
||||
await subscription.cancel();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user