feat(ai): add AI trace tracking and admin panel
- Add AiTrace model to Prisma schema with relations to User - Implement AiTraceService with CRUD operations for AI traces - Add new admin panel for AI traces with filtering and detail views - Integrate trace persistence in receipt import flow - Add API endpoints for listing and retrieving AI traces - Update Flutter admin UI with new AI tab and navigation - Add new domain models for AI traces and details - Add migration for AiTrace table creation BREAKING CHANGE: None
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import 'admin_ai_trace.dart';
|
||||
|
||||
class AdminAiTraceDetail {
|
||||
final String id;
|
||||
final AdminAiTraceSource source;
|
||||
final AdminAiTraceStatus status;
|
||||
final DateTime createdAt;
|
||||
final int userId;
|
||||
final String userLabel;
|
||||
final int? sessionId;
|
||||
final String? fileName;
|
||||
final String? model;
|
||||
final int? durationMs;
|
||||
final int? retryCount;
|
||||
final int? chunkCount;
|
||||
final List<String> warnings;
|
||||
final String? error;
|
||||
final String? prompt;
|
||||
final String? rawOutput;
|
||||
final Map<String, dynamic>? normalizedOutput;
|
||||
final Map<String, dynamic> summary;
|
||||
|
||||
const AdminAiTraceDetail({
|
||||
required this.id,
|
||||
required this.source,
|
||||
required this.status,
|
||||
required this.createdAt,
|
||||
required this.userId,
|
||||
required this.userLabel,
|
||||
required this.sessionId,
|
||||
required this.fileName,
|
||||
required this.model,
|
||||
required this.durationMs,
|
||||
required this.retryCount,
|
||||
required this.chunkCount,
|
||||
required this.warnings,
|
||||
required this.error,
|
||||
required this.prompt,
|
||||
required this.rawOutput,
|
||||
required this.normalizedOutput,
|
||||
required this.summary,
|
||||
});
|
||||
|
||||
factory AdminAiTraceDetail.fromJson(Map<String, dynamic> json) {
|
||||
final warningsRaw = (json['warnings'] as List<dynamic>?) ?? const [];
|
||||
final normalizedOutputMap = json['normalizedOutput'] is Map
|
||||
? Map<String, dynamic>.from(json['normalizedOutput'] as Map)
|
||||
: null;
|
||||
final summaryMap = json['summary'] is Map
|
||||
? Map<String, dynamic>.from(json['summary'] as Map)
|
||||
: const <String, dynamic>{};
|
||||
|
||||
return AdminAiTraceDetail(
|
||||
id: (json['id'] ?? '').toString(),
|
||||
source: AdminAiTraceSourceX.fromApi(json['source']?.toString()),
|
||||
status: AdminAiTraceStatusX.fromApi(json['status']?.toString()),
|
||||
createdAt: DateTime.tryParse((json['createdAt'] ?? '').toString()) ??
|
||||
DateTime.fromMillisecondsSinceEpoch(0),
|
||||
userId: (json['userId'] as num?)?.toInt() ?? 0,
|
||||
userLabel: (json['userLabel'] ?? '').toString(),
|
||||
sessionId: (json['sessionId'] as num?)?.toInt(),
|
||||
fileName: json['fileName']?.toString(),
|
||||
model: json['model']?.toString(),
|
||||
durationMs: (json['durationMs'] as num?)?.toInt(),
|
||||
retryCount: (json['retryCount'] as num?)?.toInt(),
|
||||
chunkCount: (json['chunkCount'] as num?)?.toInt(),
|
||||
warnings: warningsRaw.map((entry) => entry.toString()).toList(),
|
||||
error: json['error']?.toString(),
|
||||
prompt: json['prompt']?.toString(),
|
||||
rawOutput: json['rawOutput']?.toString(),
|
||||
normalizedOutput: normalizedOutputMap,
|
||||
summary: summaryMap,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user