import "dart:convert"; import "package:shadcn_flutter/shadcn_flutter.dart"; import "tools/advisor_bubble.dart"; import "tools/bash_bubble.dart"; import "tools/default_tool_bubble.dart"; import "tools/edit_bubble.dart"; import "tools/glob_bubble.dart"; import "tools/grep_bubble.dart"; import "tools/read_bubble.dart"; import "tools/web_fetch_bubble.dart"; import "tools/web_search_bubble.dart"; import "tools/write_bubble.dart"; class ToolBubble extends StatelessWidget { const ToolBubble({ super.key, required this.toolName, this.toolInput, this.result, this.isPendingPermission = false, }); final String toolName; final Map? toolInput; final String? result; final bool isPendingPermission; // parse a tool message content string into (toolName, toolInput) // format: "$toolName call\n{json}" or "$toolName result\n..." static (String, Map?) parseContent(String content) { final newlineIdx = content.indexOf("\n"); if (newlineIdx == -1) { // no body, just a label line final name = _extractName(content); return (name, null); } final firstLine = content.substring(0, newlineIdx).trim(); final rest = content.substring(newlineIdx + 1).trim(); final name = _extractName(firstLine); if (firstLine.endsWith(" call") && rest.isNotEmpty) { try { final decoded = jsonDecode(rest); if (decoded is Map) { return (name, decoded); } } catch (_) {} } return (name, null); } static String _extractName(String line) { // strip trailing " call" or " result" if (line.endsWith(" call")) return line.substring(0, line.length - 5).trim(); if (line.endsWith(" result")) return line.substring(0, line.length - 7).trim(); return line.trim(); } @override Widget build(BuildContext context) { final input = toolInput ?? {}; switch (toolName) { case "Bash": return BashBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "Edit": return EditBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "Read": return ReadBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "Write": return WriteBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "Glob": return GlobBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "Grep": return GrepBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "WebSearch": return WebSearchBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "WebFetch": return WebFetchBubble(input: input, result: result, isPendingPermission: isPendingPermission); case "Advisor": return AdvisorBubble(input: input, result: result, isPendingPermission: isPendingPermission); default: return DefaultToolBubble(toolName: toolName, input: toolInput, result: result, isPendingPermission: isPendingPermission); } } }