Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ final result = await client.detectGrooming(
if (result.groomingRisk == GroomingRisk.high) {
print('Flags: ${result.flags}'); // [secrecy, isolation]
}

// Per-message breakdown (optional, returned on conversation-aware endpoints)
if (result.messageAnalysis != null) {
for (final m in result.messageAnalysis!) {
print('Message ${m.messageIndex}: risk=${m.riskScore}, flags=${m.flags}, summary=${m.summary}');
}
}
```

### Unsafe Content Detection
Expand Down
34 changes: 34 additions & 0 deletions lib/src/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ class GroomingResult {
required this.rationale,
required this.riskScore,
required this.recommendedAction,
this.messageAnalysis,
this.externalId,
this.metadata,
this.creditsUsed,
Expand All @@ -317,6 +318,9 @@ class GroomingResult {
rationale: json['rationale'] as String,
riskScore: (json['risk_score'] as num).toDouble(),
recommendedAction: json['recommended_action'] as String,
messageAnalysis: (json['message_analysis'] as List?)
?.map((e) => MessageAnalysis.fromJson(e as Map<String, dynamic>))
.toList(),
externalId: json['external_id'] as String?,
metadata: json['metadata'] as Map<String, dynamic>?,
creditsUsed: json['credits_used'] as int?,
Expand All @@ -331,6 +335,7 @@ class GroomingResult {
final String rationale;
final double riskScore;
final String recommendedAction;
final List<MessageAnalysis>? messageAnalysis;
final String? externalId;
final Map<String, dynamic>? metadata;
final int? creditsUsed;
Expand Down Expand Up @@ -1102,6 +1107,30 @@ class ImageAnalysisResult {
// Detection Results (Fraud & Safety Extended)
// =============================================================================

/// Per-message analysis from conversation-aware detection.
class MessageAnalysis {
const MessageAnalysis({
required this.messageIndex,
required this.riskScore,
required this.flags,
required this.summary,
});

factory MessageAnalysis.fromJson(Map<String, dynamic> json) {
return MessageAnalysis(
messageIndex: json['message_index'] as int,
riskScore: (json['risk_score'] as num).toDouble(),
flags: List<String>.from(json['flags'] as List),
summary: json['summary'] as String,
);
}

final int messageIndex;
final double riskScore;
final List<String> flags;
final String summary;
}

/// A detection category with confidence score.
class DetectionCategory {
const DetectionCategory({
Expand Down Expand Up @@ -1181,6 +1210,7 @@ class DetectionResult {
required this.languageStatus,
this.evidence,
this.ageCalibration,
this.messageAnalysis,
this.creditsUsed,
this.processingTimeMs,
this.externalId,
Expand Down Expand Up @@ -1209,6 +1239,9 @@ class DetectionResult {
ageCalibration: json['age_calibration'] != null
? AgeCalibration.fromJson(json['age_calibration'] as Map<String, dynamic>)
: null,
messageAnalysis: (json['message_analysis'] as List?)
?.map((e) => MessageAnalysis.fromJson(e as Map<String, dynamic>))
.toList(),
creditsUsed: json['credits_used'] as int?,
processingTimeMs: (json['processing_time_ms'] as num?)?.toDouble(),
externalId: json['external_id'] as String?,
Expand All @@ -1230,6 +1263,7 @@ class DetectionResult {
final String languageStatus;
final List<DetectionEvidence>? evidence;
final AgeCalibration? ageCalibration;
final List<MessageAnalysis>? messageAnalysis;
final int? creditsUsed;
final double? processingTimeMs;
final String? externalId;
Expand Down