class ContentBlock { final String type; final Map raw; ContentBlock({required this.type, required this.raw}); factory ContentBlock.fromJson(Map json) { final type = json['type'] as String? ?? 'unknown'; switch (type) { case 'text': return TextBlock.fromJson(json); case 'thinking': return ThinkingBlock.fromJson(json); case 'tool_use': return ToolUseBlock.fromJson(json); default: return ContentBlock(type: type, raw: json); } } } class TextBlock extends ContentBlock { final String text; TextBlock({required this.text, required super.raw}) : super(type: 'text'); factory TextBlock.fromJson(Map json) { return TextBlock( text: json['text'] as String? ?? '', raw: json, ); } } class ThinkingBlock extends ContentBlock { final String thinking; final String? signature; ThinkingBlock({ required this.thinking, this.signature, required super.raw, }) : super(type: 'thinking'); factory ThinkingBlock.fromJson(Map json) { return ThinkingBlock( thinking: json['thinking'] as String? ?? '', signature: json['signature'] as String?, raw: json, ); } } class ToolUseBlock extends ContentBlock { final String id; final String name; final Map input; ToolResultData? linkedResult; ToolUseBlock({ required this.id, required this.name, required this.input, this.linkedResult, required super.raw, }) : super(type: 'tool_use'); factory ToolUseBlock.fromJson(Map json) { return ToolUseBlock( id: json['id'] as String? ?? '', name: json['name'] as String? ?? '', input: (json['input'] as Map?) ?? {}, raw: json, ); } bool get isAgentCall => name == 'Agent'; String? get subagentType => isAgentCall ? input['subagent_type'] as String? : null; String? get agentDescription => isAgentCall ? input['description'] as String? : null; String? get agentPrompt => isAgentCall ? input['prompt'] as String? : null; } class ToolResultData { final String toolUseId; final dynamic content; final bool isError; final Map raw; ToolResultData({ required this.toolUseId, this.content, this.isError = false, required this.raw, }); String get textContent { if (content is String) return content; if (content is List) { return (content as List) .where((c) => c is Map && c['type'] == 'text') .map((c) => c['text'] as String? ?? '') .join('\n'); } return content?.toString() ?? ''; } factory ToolResultData.fromJson(Map json) { return ToolResultData( toolUseId: json['tool_use_id'] as String? ?? '', content: json['content'], isError: json['is_error'] as bool? ?? false, raw: json, ); } }