Clean up LLM digest provider errors
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:relationship_saver/app/data/relationship_repository.dart';
|
||||
import 'package:relationship_saver/app/state/local_data_state.dart';
|
||||
import 'package:relationship_saver/core/llm/llm_config.dart';
|
||||
import 'package:relationship_saver/core/llm/llm_service.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/application/ai_digest_notifier.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/application/ai_digest_response_parser.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/application/anonymized_llm_context_builder.dart';
|
||||
@@ -185,11 +186,12 @@ class LlmDigestOrchestrator {
|
||||
createdDraftCount: parsed.drafts.length,
|
||||
);
|
||||
} catch (error) {
|
||||
await _markFailure('$error');
|
||||
final String reason = _digestFailureReason(error);
|
||||
await _markFailure(reason);
|
||||
return LlmDigestRunResult(
|
||||
started: true,
|
||||
completed: false,
|
||||
reason: '$error',
|
||||
reason: reason,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -232,6 +234,13 @@ class LlmDigestOrchestrator {
|
||||
}
|
||||
}
|
||||
|
||||
String _digestFailureReason(Object error) {
|
||||
if (error is LlmProviderException) {
|
||||
return error.message;
|
||||
}
|
||||
return '$error';
|
||||
}
|
||||
|
||||
const String _systemPrompt = '''
|
||||
You create private relationship-maintenance digest suggestions.
|
||||
The input contains pseudonymous people only. Never ask for or invent names.
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'package:relationship_saver/app/data/relationship_repository.dart';
|
||||
import 'package:relationship_saver/app/data/storage/local_data_store_in_memory.dart';
|
||||
import 'package:relationship_saver/app/data/storage/local_data_store_provider.dart';
|
||||
import 'package:relationship_saver/app/state/local_data_state.dart';
|
||||
import 'package:relationship_saver/core/llm/llm_config.dart';
|
||||
import 'package:relationship_saver/core/llm/llm_service.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/application/ai_digest_notifier.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/application/llm_digest_environment.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/application/llm_digest_orchestrator.dart';
|
||||
@@ -117,10 +119,45 @@ void main() {
|
||||
expect(result.started, isFalse);
|
||||
expect(textClient.calls, 0);
|
||||
});
|
||||
|
||||
test('manual digest reports provider rate limits without Dio noise', () async {
|
||||
final ThrowingTextClient textClient = ThrowingTextClient(
|
||||
error: const LlmProviderException(
|
||||
provider: LlmProvider.openai,
|
||||
statusCode: 429,
|
||||
message:
|
||||
'OpenAI rejected the digest request with 429 rate limiting or quota pressure.',
|
||||
),
|
||||
);
|
||||
final ProviderContainer container = _createContainer(
|
||||
textClient: textClient,
|
||||
notifier: FakeNotifier(),
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container.read(localRepositoryProvider.future);
|
||||
await container
|
||||
.read(localRepositoryProvider.notifier)
|
||||
.addPerson(
|
||||
name: 'Taylor Quinn',
|
||||
relationship: 'Friend',
|
||||
notes: '',
|
||||
tags: const <String>['tea'],
|
||||
);
|
||||
|
||||
final LlmDigestRunResult result = await container
|
||||
.read(llmDigestOrchestratorProvider)
|
||||
.runManualDigest();
|
||||
|
||||
expect(result.started, isTrue);
|
||||
expect(result.completed, isFalse);
|
||||
expect(result.reason, contains('429 rate limiting'));
|
||||
expect(result.reason, isNot(contains('DioException')));
|
||||
});
|
||||
}
|
||||
|
||||
ProviderContainer _createContainer({
|
||||
required FakeTextClient textClient,
|
||||
required LlmDigestTextClient textClient,
|
||||
required FakeNotifier notifier,
|
||||
LlmDigestEnvironment environment = const FakeEnvironment(),
|
||||
}) {
|
||||
@@ -158,6 +195,20 @@ class FakeTextClient implements LlmDigestTextClient {
|
||||
}
|
||||
}
|
||||
|
||||
class ThrowingTextClient implements LlmDigestTextClient {
|
||||
const ThrowingTextClient({required this.error});
|
||||
|
||||
final Object error;
|
||||
|
||||
@override
|
||||
Future<String> complete({
|
||||
required String systemPrompt,
|
||||
required String userPrompt,
|
||||
}) async {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeNotifier implements AiDigestNotifier {
|
||||
int? lastCount;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user