chore(ui): replace emoji with Material icons across chat UI (#944)
* chore(ui): replace emoji with Material icons across chat UI Removes emoji glyphs and swaps them for real Material icons / plain text: - ToolSchemaRegistry: iconEmoji String -> ImageVector icon for all ~35 tools; summaryPrefix emoji stripped (terminal keeps '$ '); consumer renders Icon(). - ToolBubble: collapsed summary now shows Icon(config.icon) instead of an emoji Text prefix; web-search url drops the link emoji; warning badge uses Icons.Filled.Warning instead of a '⚠' Text glyph. - ChatBubble SelfImprovementReviewCard: 🛠/🧠 String -> Build/Psychology Icon. - ChatViewModel / ChatWsEventReducer: drop ⚠️/✅ prefixes from user-facing status/error messages (severity already conveyed by color/styling). - SubagentInspectionSheet: ✅/🔄/❌/⭕ status markers -> CheckCircle/Autorenew/ Cancel/RadioButtonUnchecked (tinted); ElectricBolt section headers -> FormatListBulleted + Groups. - strings.xml (en/zh/ko): drop '✓' from the Copied label. ktlint clean; compileDebugKotlin SUCCESSFUL. Remaining chat files (ToolViewBuilder, ChatComposer, MessageCards, ChatReactions, ComposerToolbar, FullBleedAgentMessage) tracked in follow-up commits on this branch. * test: align unit tests with emoji-free summary + status messages composeToolSummaryLines dropped the emoji parameter and no longer prepends an emoji glyph to the collapsed summary line, so update ToolSummaryLinesTest call sites + expected strings accordingly. SlashCommandDispatchRpcTest asserted the old '⚠️ /cmd: ...' error messages; those prefixes were removed in the UI cleanup, so drop them from the expected strings. ChatWsEventReducerTest emoji usages are model-output fixtures, not assertions on changed code paths — left untouched.
This commit is contained in:
11 files changed
+148
-108
No files matched your search
@@ -143,7 +143,7 @@ sealed class WsEvent {
|
||||
/**
|
||||
* Self-improvement background review summary event.
|
||||
* Emitted when background review patches a skill or saves a memory.
|
||||
* Payload: `{ text: "💾 Self-improvement review: ..." }`
|
||||
* Payload: `{ text: "Self-improvement review: ..." }`
|
||||
*/
|
||||
data class ReviewSummary(
|
||||
val text: String,
|
||||
|
||||
@@ -25,10 +25,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.InsertDriveFile
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.ContentCopy
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Psychology
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
@@ -51,6 +53,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.ClipEntry
|
||||
import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
@@ -65,7 +68,6 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.m57.hermescontrol.R
|
||||
import com.m57.hermescontrol.data.model.Attachment
|
||||
import com.m57.hermescontrol.theme.DarkOnSurface
|
||||
@@ -257,7 +259,7 @@ private fun SelfImprovementReviewCard(
|
||||
val isSkill =
|
||||
cleanText.contains("skill", ignoreCase = true) ||
|
||||
cleanText.contains("SKILL.md", ignoreCase = true)
|
||||
val icon = if (isSkill) "🛠" else "🧠"
|
||||
val icon: ImageVector = if (isSkill) Icons.Filled.Build else Icons.Filled.Psychology
|
||||
val title =
|
||||
if (isSkill) {
|
||||
"Self-Improvement Review • Skill Patched"
|
||||
@@ -279,7 +281,12 @@ private fun SelfImprovementReviewCard(
|
||||
) {
|
||||
Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(text = icon, fontSize = 16.sp)
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text(
|
||||
text = title,
|
||||
|
||||
@@ -1112,7 +1112,7 @@ class ChatViewModel(
|
||||
val map = result as? Map<*, *>
|
||||
val resolved = (map?.get("resolved") as? Number)?.toInt() ?: 0
|
||||
if (resolved > 0) {
|
||||
addSystemMessage("✅ Approval submitted")
|
||||
addSystemMessage("Approval submitted")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1308,7 +1308,7 @@ class ChatViewModel(
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to upload attachment ${attachment.name}", e)
|
||||
_uiState.update {
|
||||
it.copy(errorMessage = "⚠️ Upload failed: ${attachment.name}")
|
||||
it.copy(errorMessage = "Upload failed: ${attachment.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1424,7 +1424,7 @@ class ChatViewModel(
|
||||
// (before any RPC fires) with a clear message instead of a doomed call.
|
||||
if (CommandBlocklist.contains(command)) {
|
||||
addAssistantMessage(
|
||||
"⚠️ ${command.split(" ", limit = 2)[0]} is not supported on mobile",
|
||||
"${command.split(" ", limit = 2)[0]} is not supported on mobile",
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -1608,11 +1608,11 @@ class ChatViewModel(
|
||||
val output = (result as? Map<*, *>)?.get("output") as? String
|
||||
if (!output.isNullOrBlank()) addAssistantMessage(output)
|
||||
} catch (e2: HermesWsClient.HermesRpcException) {
|
||||
addAssistantMessage("⚠️ /$name: ${e2.message}")
|
||||
addAssistantMessage("/$name: ${e2.message}")
|
||||
}
|
||||
} else {
|
||||
// Legit error from command.dispatch (busy, no history, etc.)
|
||||
addAssistantMessage("⚠️ /$name: ${e.message}")
|
||||
addAssistantMessage("/$name: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3315,7 +3315,7 @@ class ChatViewModel(
|
||||
|
||||
private fun handleApprovalRequest(event: WsEvent.ApprovalRequest) {
|
||||
val description = event.description ?: event.command ?: "Unknown command"
|
||||
val content = "⚠️ **Approval Required**\n$description"
|
||||
val content = "**Approval Required**\n$description"
|
||||
val msg =
|
||||
ChatMessage(
|
||||
role = MessageRole.SYSTEM,
|
||||
|
||||
@@ -682,7 +682,7 @@ object ChatWsEventReducer {
|
||||
state =
|
||||
state.copy(
|
||||
isLoading = false,
|
||||
errorMessage = "⚠️ Backend error: ${event.message ?: "Unknown gateway error"}",
|
||||
errorMessage = "Backend error: ${event.message ?: "Unknown gateway error"}",
|
||||
),
|
||||
streamingState = streamingState,
|
||||
)
|
||||
@@ -700,8 +700,8 @@ object ChatWsEventReducer {
|
||||
when (val label = event.data?.get("label")) {
|
||||
is String -> label
|
||||
else -> event.data?.get("name") as? String
|
||||
}?.let { "✅ Background job finished: $it" }
|
||||
?: "✅ Background job finished"
|
||||
}?.let { "Background job finished: $it" }
|
||||
?: "Background job finished"
|
||||
return ReducerResult(
|
||||
state = state.copy(backgroundCompleteMessage = message),
|
||||
streamingState = streamingState,
|
||||
|
||||
@@ -19,6 +19,7 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -26,6 +27,7 @@ import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.ContentCopy
|
||||
import androidx.compose.material.icons.filled.Error
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
@@ -79,7 +81,6 @@ import kotlinx.coroutines.launch
|
||||
internal fun composeToolSummaryLines(
|
||||
view: ToolView,
|
||||
toolName: String?,
|
||||
emoji: String,
|
||||
): Pair<String, String?>? {
|
||||
val titleIsGeneric = view.title.equals(ToolViewBuilder.genericTitleFor(toolName), ignoreCase = true)
|
||||
val subtitle = view.subtitle.takeIf { it.isNotBlank() && it != view.title }
|
||||
@@ -89,9 +90,8 @@ internal fun composeToolSummaryLines(
|
||||
if (titleIsGeneric) {
|
||||
firstLine =
|
||||
buildString {
|
||||
append(emoji)
|
||||
if (subtitle != null) {
|
||||
append(" $subtitle")
|
||||
append(subtitle)
|
||||
}
|
||||
view.countLabel?.let { append(" ($it)") }
|
||||
}
|
||||
@@ -99,13 +99,13 @@ internal fun composeToolSummaryLines(
|
||||
} else {
|
||||
firstLine =
|
||||
buildString {
|
||||
append("$emoji ${view.title}")
|
||||
append(view.title)
|
||||
view.countLabel?.let { append(" ($it)") }
|
||||
}
|
||||
secondLine = subtitle
|
||||
}
|
||||
|
||||
return firstLine.takeIf { it.trim() != emoji }?.let { it to secondLine }
|
||||
return firstLine.takeIf { it.isNotBlank() }?.let { it to secondLine }
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -180,21 +180,32 @@ internal fun ToolBubble(
|
||||
SecurityRiskChip(riskData, contentColor)
|
||||
}
|
||||
|
||||
// ── Collapsed summary: emoji + title, then subtitle ──
|
||||
// ── Collapsed summary: icon + title, then subtitle ──
|
||||
if (!expanded && view != null) {
|
||||
composeToolSummaryLines(view, message.toolName, config.iconEmoji)?.let { (firstLine, secondLine) ->
|
||||
Text(
|
||||
text = firstLine,
|
||||
style =
|
||||
MaterialTheme.typography.bodySmall.copy(
|
||||
color = contentColor.copy(alpha = 0.7f),
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = 11.sp,
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
composeToolSummaryLines(view, message.toolName)?.let { (firstLine, secondLine) ->
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(top = 4.dp, start = 22.dp),
|
||||
)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = config.icon,
|
||||
contentDescription = null,
|
||||
tint = contentColor.copy(alpha = 0.7f),
|
||||
modifier = Modifier.size(13.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = firstLine,
|
||||
style =
|
||||
MaterialTheme.typography.bodySmall.copy(
|
||||
color = contentColor.copy(alpha = 0.7f),
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = 11.sp,
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
if (secondLine != null) {
|
||||
Text(
|
||||
text = secondLine,
|
||||
@@ -450,7 +461,7 @@ private fun ExpandedToolContent(
|
||||
}
|
||||
if (hit.url.isNotEmpty()) {
|
||||
Text(
|
||||
text = "🔗 ${hit.url}",
|
||||
text = hit.url,
|
||||
style =
|
||||
MaterialTheme.typography.bodySmall.copy(
|
||||
color = contentColor.copy(alpha = 0.7f),
|
||||
@@ -567,10 +578,11 @@ internal fun SecurityRiskChip(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "⚠",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = chipColor,
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Warning,
|
||||
contentDescription = null,
|
||||
tint = chipColor,
|
||||
modifier = Modifier.size(14.dp),
|
||||
)
|
||||
Text(
|
||||
text = label,
|
||||
|
||||
@@ -1,5 +1,36 @@
|
||||
package com.m57.hermescontrol.ui.chat
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.MenuBook
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material.icons.filled.AccountTree
|
||||
import androidx.compose.material.icons.filled.AutoStories
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.ChatBubble
|
||||
import androidx.compose.material.icons.filled.Checklist
|
||||
import androidx.compose.material.icons.filled.Computer
|
||||
import androidx.compose.material.icons.filled.Description
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.Forum
|
||||
import androidx.compose.material.icons.filled.Image
|
||||
import androidx.compose.material.icons.filled.Keyboard
|
||||
import androidx.compose.material.icons.filled.Language
|
||||
import androidx.compose.material.icons.filled.Memory
|
||||
import androidx.compose.material.icons.filled.Movie
|
||||
import androidx.compose.material.icons.filled.Photo
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Psychology
|
||||
import androidx.compose.material.icons.filled.Public
|
||||
import androidx.compose.material.icons.filled.Schedule
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.Terminal
|
||||
import androidx.compose.material.icons.filled.ThumbUp
|
||||
import androidx.compose.material.icons.filled.TouchApp
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
/**
|
||||
* Display configuration for a Hermes tool — controls the summary line,
|
||||
* icon, and which arg field is shown when the bubble is collapsed.
|
||||
@@ -11,10 +42,10 @@ data class ToolDisplayConfig(
|
||||
val name: String,
|
||||
/** Key into the `args` dict for the one-line summary (e.g. "command" for terminal). */
|
||||
val summaryArgKey: String? = null,
|
||||
/** Prefix for the summary line (e.g. "$ " for terminal, "📄 " for read_file). */
|
||||
/** Prefix for the summary line (e.g. "$ " for terminal). Emoji-free. */
|
||||
val summaryPrefix: String = "",
|
||||
/** Emoji icon for this tool type. */
|
||||
val iconEmoji: String = "🔧",
|
||||
/** Material icon for this tool type. */
|
||||
val icon: ImageVector = Icons.Filled.Build,
|
||||
)
|
||||
|
||||
/** Maps tool names to their display config. Ordered by expected frequency of use. */
|
||||
@@ -26,240 +57,230 @@ object ToolSchemaRegistry {
|
||||
name = "terminal",
|
||||
summaryArgKey = "command",
|
||||
summaryPrefix = "$ ",
|
||||
iconEmoji = "💻",
|
||||
icon = Icons.Filled.Terminal,
|
||||
),
|
||||
"read_file" to
|
||||
ToolDisplayConfig(
|
||||
name = "read_file",
|
||||
summaryArgKey = "path",
|
||||
summaryPrefix = "📄 ",
|
||||
iconEmoji = "📄",
|
||||
icon = Icons.Filled.Description,
|
||||
),
|
||||
"write_file" to
|
||||
ToolDisplayConfig(
|
||||
name = "write_file",
|
||||
summaryArgKey = "path",
|
||||
summaryPrefix = "✏️ ",
|
||||
iconEmoji = "✏️",
|
||||
icon = Icons.Filled.Edit,
|
||||
),
|
||||
"patch" to
|
||||
ToolDisplayConfig(
|
||||
name = "patch",
|
||||
summaryArgKey = "path",
|
||||
summaryPrefix = "🔧 ",
|
||||
iconEmoji = "🔧",
|
||||
icon = Icons.Filled.Build,
|
||||
),
|
||||
"search_files" to
|
||||
ToolDisplayConfig(
|
||||
name = "search_files",
|
||||
summaryArgKey = "pattern",
|
||||
summaryPrefix = "🔍 ",
|
||||
iconEmoji = "🔍",
|
||||
icon = Icons.Filled.Search,
|
||||
),
|
||||
"web_search" to
|
||||
ToolDisplayConfig(
|
||||
name = "web_search",
|
||||
summaryArgKey = "query",
|
||||
summaryPrefix = "🌐 ",
|
||||
iconEmoji = "🌐",
|
||||
icon = Icons.Filled.Public,
|
||||
),
|
||||
"browser_navigate" to
|
||||
ToolDisplayConfig(
|
||||
name = "browser_navigate",
|
||||
summaryArgKey = "url",
|
||||
summaryPrefix = "🌍 ",
|
||||
iconEmoji = "🌍",
|
||||
icon = Icons.Filled.Language,
|
||||
),
|
||||
"browser_click" to
|
||||
ToolDisplayConfig(
|
||||
name = "browser_click",
|
||||
summaryArgKey = "ref",
|
||||
summaryPrefix = "🖱 ",
|
||||
iconEmoji = "🖱",
|
||||
icon = Icons.Filled.TouchApp,
|
||||
),
|
||||
"browser_snapshot" to
|
||||
ToolDisplayConfig(
|
||||
name = "browser_snapshot",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "📋",
|
||||
icon = Icons.Filled.Photo,
|
||||
),
|
||||
"clarify" to
|
||||
ToolDisplayConfig(
|
||||
name = "clarify",
|
||||
summaryArgKey = "question",
|
||||
summaryPrefix = "💬 ",
|
||||
iconEmoji = "💬",
|
||||
icon = Icons.Filled.ChatBubble,
|
||||
),
|
||||
"delegate_task" to
|
||||
ToolDisplayConfig(
|
||||
name = "delegate_task",
|
||||
summaryArgKey = "goal",
|
||||
summaryPrefix = "🔄 ",
|
||||
iconEmoji = "🔄",
|
||||
icon = Icons.Filled.AccountTree,
|
||||
),
|
||||
"execute_code" to
|
||||
ToolDisplayConfig(
|
||||
name = "execute_code",
|
||||
summaryArgKey = "code",
|
||||
summaryPrefix = "▶️ ",
|
||||
iconEmoji = "▶️",
|
||||
icon = Icons.Filled.PlayArrow,
|
||||
),
|
||||
"todo" to
|
||||
ToolDisplayConfig(
|
||||
name = "todo",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "📋",
|
||||
icon = Icons.Filled.Checklist,
|
||||
),
|
||||
"fact_store" to
|
||||
ToolDisplayConfig(
|
||||
name = "fact_store",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "🧠",
|
||||
icon = Icons.Filled.Psychology,
|
||||
),
|
||||
"session_search" to
|
||||
ToolDisplayConfig(
|
||||
name = "session_search",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "🔍",
|
||||
icon = Icons.Filled.Search,
|
||||
),
|
||||
// ── Action-based tools ──
|
||||
"cronjob" to
|
||||
ToolDisplayConfig(
|
||||
name = "cronjob",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "🔄",
|
||||
icon = Icons.Filled.Schedule,
|
||||
),
|
||||
"memory" to
|
||||
ToolDisplayConfig(
|
||||
name = "memory",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "💾",
|
||||
icon = Icons.Filled.Memory,
|
||||
),
|
||||
"fact_feedback" to
|
||||
ToolDisplayConfig(
|
||||
name = "fact_feedback",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "👍",
|
||||
icon = Icons.Filled.ThumbUp,
|
||||
),
|
||||
"process" to
|
||||
ToolDisplayConfig(
|
||||
name = "process",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "⚙️",
|
||||
icon = Icons.Filled.Settings,
|
||||
),
|
||||
"skill_manage" to
|
||||
ToolDisplayConfig(
|
||||
name = "skill_manage",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "🛠️",
|
||||
icon = Icons.Filled.Build,
|
||||
),
|
||||
// ── Web / Browser tools ──
|
||||
"web_extract" to
|
||||
ToolDisplayConfig(
|
||||
name = "web_extract",
|
||||
summaryArgKey = "urls",
|
||||
iconEmoji = "🕸️",
|
||||
icon = Icons.Filled.Language,
|
||||
),
|
||||
"browser_type" to
|
||||
ToolDisplayConfig(
|
||||
name = "browser_type",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "⌨️",
|
||||
icon = Icons.Filled.Keyboard,
|
||||
),
|
||||
"browser_cdp" to
|
||||
ToolDisplayConfig(
|
||||
name = "browser_cdp",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "🔧",
|
||||
icon = Icons.Filled.Build,
|
||||
),
|
||||
"browser_dialog" to
|
||||
ToolDisplayConfig(
|
||||
name = "browser_dialog",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "💬",
|
||||
icon = Icons.Filled.ChatBubble,
|
||||
),
|
||||
// ── Media / Vision tools ──
|
||||
"vision_analyze" to
|
||||
ToolDisplayConfig(
|
||||
name = "vision_analyze",
|
||||
summaryArgKey = "image_url",
|
||||
iconEmoji = "👁️",
|
||||
icon = Icons.Filled.Visibility,
|
||||
),
|
||||
"text_to_speech" to
|
||||
ToolDisplayConfig(
|
||||
name = "text_to_speech",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "🔊",
|
||||
icon = Icons.AutoMirrored.Filled.VolumeUp,
|
||||
),
|
||||
"video_generate" to
|
||||
ToolDisplayConfig(
|
||||
name = "video_generate",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "🎬",
|
||||
icon = Icons.Filled.Movie,
|
||||
),
|
||||
"image_generate" to
|
||||
ToolDisplayConfig(
|
||||
name = "image_generate",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "🎨",
|
||||
icon = Icons.Filled.Image,
|
||||
),
|
||||
// ── Social / Messaging tools ──
|
||||
"x_search" to
|
||||
ToolDisplayConfig(
|
||||
name = "x_search",
|
||||
summaryArgKey = "query",
|
||||
iconEmoji = "𝕏",
|
||||
icon = Icons.Filled.Forum,
|
||||
),
|
||||
"send_message" to
|
||||
ToolDisplayConfig(
|
||||
name = "send_message",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "📨",
|
||||
icon = Icons.AutoMirrored.Filled.Send,
|
||||
),
|
||||
// ── Skills tools ──
|
||||
"skills_list" to
|
||||
ToolDisplayConfig(
|
||||
name = "skills_list",
|
||||
summaryArgKey = null,
|
||||
iconEmoji = "📚",
|
||||
icon = Icons.AutoMirrored.Filled.MenuBook,
|
||||
),
|
||||
"skill_view" to
|
||||
ToolDisplayConfig(
|
||||
name = "skill_view",
|
||||
summaryArgKey = "name",
|
||||
iconEmoji = "📖",
|
||||
icon = Icons.Filled.AutoStories,
|
||||
),
|
||||
// ── On-demand tools ──
|
||||
"tool_search" to
|
||||
ToolDisplayConfig(
|
||||
name = "tool_search",
|
||||
summaryArgKey = "query",
|
||||
iconEmoji = "🔍",
|
||||
icon = Icons.Filled.Search,
|
||||
),
|
||||
"tool_describe" to
|
||||
ToolDisplayConfig(
|
||||
name = "tool_describe",
|
||||
summaryArgKey = "name",
|
||||
iconEmoji = "📖",
|
||||
icon = Icons.Filled.AutoStories,
|
||||
),
|
||||
"tool_call" to
|
||||
ToolDisplayConfig(
|
||||
name = "tool_call",
|
||||
summaryArgKey = "name",
|
||||
iconEmoji = "🔧",
|
||||
icon = Icons.Filled.Build,
|
||||
),
|
||||
// ── Misc ──
|
||||
"read_terminal" to
|
||||
ToolDisplayConfig(
|
||||
name = "read_terminal",
|
||||
summaryArgKey = "session_id",
|
||||
iconEmoji = "🖥️",
|
||||
icon = Icons.Filled.Computer,
|
||||
),
|
||||
"computer_use" to
|
||||
ToolDisplayConfig(
|
||||
name = "computer_use",
|
||||
summaryArgKey = "action",
|
||||
iconEmoji = "🖥️",
|
||||
icon = Icons.Filled.Computer,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
Reference in new issue
Block a user