blob: ed1146905fabbae35cba0844ad1408bcd063dc3b [file]
import 'agent_tool_event.dart';
import 'agent_tool_id.dart';
import 'agent_tool_metadata.dart';
/// UI-friendly representation of an executed tool event.
class AgentToolEventPresentation {
const AgentToolEventPresentation({
required this.toolLabel,
required this.actionText,
required this.ariaLabel,
required this.uiKind,
this.errorText,
});
/// The user-facing label/name of the tool.
final String toolLabel;
/// Human-readable summary of the action performed by the tool.
final String actionText;
/// Screen-reader accessible label describing the tool's execution and outcome.
final String ariaLabel;
/// The UI category of the tool (e.g. read, edit, search) for icons and colors.
final AgentToolUiKind uiKind;
/// Error message details, if the tool execution failed.
final String? errorText;
}
/// Helper that transforms low-level [AgentToolEvent] objects into [AgentToolEventPresentation]
/// suitable for rendering in the UI.
class AgentToolEventPresenter {
const AgentToolEventPresenter._();
/// Converts a raw [AgentToolEvent] into a structured [AgentToolEventPresentation].
static AgentToolEventPresentation present(AgentToolEvent event) {
final toolLabel = event.toolName;
final actionText = _buildActionText(event);
final errorText = event.status == ToolStatus.error ? event.errorMessage : null;
final statusText = event.status == ToolStatus.running
? 'running'
: (event.status == ToolStatus.success ? 'succeeded' : 'failed');
final ariaLabel = errorText == null
? 'Tool $toolLabel $statusText. $actionText.'
: 'Tool $toolLabel $statusText. $actionText. Error: $errorText.';
return AgentToolEventPresentation(
toolLabel: toolLabel,
actionText: actionText,
ariaLabel: ariaLabel,
uiKind: event.uiKind,
errorText: errorText,
);
}
static String _buildActionText(AgentToolEvent event) {
final path = event.targetPath ?? 'unknown file';
return switch ((event.toolId, event.status)) {
(AgentToolId.writeFile, ToolStatus.running) => 'Editing $path',
(AgentToolId.writeFile, _) => 'Edited $path',
(AgentToolId.applyPatch, ToolStatus.running) => 'Editing $path',
(AgentToolId.applyPatch, _) => 'Edited $path',
(AgentToolId.readFile, ToolStatus.running) => 'Reading $path',
(AgentToolId.readFile, _) => 'Read $path',
(AgentToolId.readLines, ToolStatus.running) => 'Reading $path',
(AgentToolId.readLines, _) =>
event.startLine != null && event.endLine != null
? 'Read lines ${event.startLine}-${event.endLine} from $path'
: 'Read $path',
(AgentToolId.deleteFile, ToolStatus.running) => 'Deleting $path',
(AgentToolId.deleteFile, _) => 'Deleted $path',
(AgentToolId.grep, ToolStatus.running) => 'Searching workspace',
(AgentToolId.grep, _) => 'Searched workspace',
(AgentToolId.glob, ToolStatus.running) => 'Searching files',
(AgentToolId.glob, _) => 'Searched files',
(AgentToolId.fuzzyFileSearch, ToolStatus.running) => 'Searching files',
(AgentToolId.fuzzyFileSearch, _) => 'Searched files',
(AgentToolId.analyzeStart, ToolStatus.running) => 'Analyzing files',
(AgentToolId.analyzeStart, _) => 'Analyzed files',
(AgentToolId.askQuestion, ToolStatus.running) => 'Asking a question',
(AgentToolId.askQuestion, _) => 'Asked a question',
// planExit is never rendered as a tool row (uiKind == interaction).
(AgentToolId.planExit, _) => throw StateError('Unreachable: planExit is not displayed'),
(AgentToolId.controlApp, ToolStatus.running) => switch (event.subAction) {
'restart' => 'Restarting preview',
'reload' => 'Reloading preview',
_ => 'Starting preview',
},
(AgentToolId.controlApp, _) => switch (event.subAction) {
'restart' => 'Restarted preview',
'reload' => 'Reloaded preview',
_ => 'Started preview',
},
(AgentToolId.workspaceMaintenance, ToolStatus.running) => switch (event.subAction) {
'clean' => 'Cleaning workspace',
'pub_get' => 'Resolving packages',
'full_rebuild' => 'Cleaning and rebuilding workspace',
_ => 'Running maintenance',
},
(AgentToolId.workspaceMaintenance, _) => switch (event.subAction) {
'clean' => 'Cleaned workspace',
'pub_get' => 'Resolved packages',
'full_rebuild' => 'Cleaned and rebuilt workspace',
_ => 'Maintenance finished',
},
(AgentToolId.generateImage, ToolStatus.running) => 'Generating image',
(AgentToolId.generateImage, _) => 'Generated image',
(AgentToolId.getWidgetTree, _) => event.summary,
(AgentToolId.getWidgetDetails, _) => event.summary,
(AgentToolId.findWidget, _) => event.summary,
(AgentToolId.screenshotWidget, ToolStatus.running) => 'Capturing screenshot',
(AgentToolId.screenshotWidget, _) => 'Captured screenshot',
(AgentToolId.tapWidget, _) => event.summary,
(AgentToolId.enterText, _) => event.summary,
(AgentToolId.scrollWidget, _) => event.summary,
(AgentToolId.changeDeviceMode, ToolStatus.running) => 'Changing device mode',
(AgentToolId.changeDeviceMode, _) => event.summary,
};
}
}