toPromptString method
Format all elements as a human-readable prompt section for the LLM.
The output is structured to help the LLM understand the screen:
- Scroll indicators at the top if the screen has more content
- Elements grouped under header sections for visual clarity
- Noise filtered out (scrollable containers, empty-label elements)
Implementation
String toPromptString() {
if (elements.isEmpty) return '(No UI elements detected on screen)';
final buffer = StringBuffer();
// Scroll awareness: tell the LLM there's more content.
if (canScrollDown && canScrollUp) {
buffer.writeln(
'** This screen has MORE CONTENT above AND below — scroll to see all content. **',
);
} else if (canScrollDown) {
buffer.writeln(
'** This screen has MORE CONTENT below — scroll down to see it. **',
);
} else if (canScrollUp) {
buffer.writeln(
'** This screen has MORE CONTENT above — scroll up to see it. **',
);
}
// Filter out noise:
// - Scrollable containers (structural, not content)
// - Elements with empty labels AND no value (invisible/structural)
final meaningful = elements.where((e) {
if (e.type == UiElementType.scrollable) return false;
if (e.label.isEmpty && (e.value == null || e.value!.isEmpty)) {
return false;
}
return true;
}).toList();
if (meaningful.isEmpty) {
buffer.writeln('(No visible UI elements detected)');
return buffer.toString().trimRight();
}
// Group elements under headers for better structure.
int idx = 1;
for (final element in meaningful) {
if (element.type == UiElementType.header) {
// Headers are visual separators — show them distinctly.
buffer.writeln();
buffer.writeln('--- ${element.label} ---');
continue;
}
buffer.writeln(' $idx. ${element.toPromptString()}');
idx++;
}
return buffer.toString().trimRight();
}