chore(chat): remove dead transcript code (#1309) (#1341)

This commit is contained in:
m57 authored and GitHub committed 2026-09-28 00:49:41 +03:00
1 parent 6a00696e68
commit 4bfc015cff
11 files changed
+19 -190

No files matched your search

@@ -272,15 +272,3 @@ class ChatMediaDelegate(
uiState.update { it.copy(openError = null) }
}
}
internal fun sameMessages(
left: List<ChatMessage>,
right: List<ChatMessage>,
): Boolean =
left.size == right.size &&
left.zip(right).all { (a, b) ->
a.id == b.id &&
a.role == b.role &&
a.content == b.content &&
a.reasoningText == b.reasoningText
}
@@ -375,7 +375,6 @@ fun ChatScreen(
viewModel.consumeComposerTextRestore()
}
}
var lastAnimatedMessageId by rememberSaveable { mutableStateOf<String?>(null) }
var showReloginDialog by rememberSaveable { mutableStateOf(false) }
var showSubagentInspectionSheet by rememberSaveable { mutableStateOf(false) }
LaunchedEffect(showSubagentInspectionSheet) {
@@ -783,8 +782,6 @@ fun ChatScreen(
},
listState = listState,
scrollController = scrollController,
lastAnimatedMessageId = lastAnimatedMessageId,
onLastAnimatedMessageIdChange = { lastAnimatedMessageId = it },
viewModel = viewModel,
clarifyRequest = state.clarifyRequest.takeUnless { timelineState.isHistorical },
onRespondClarify = viewModel::respondToClarify,
@@ -74,7 +74,6 @@ import com.m57.hermescontrol.ui.chat.markdown.splitInlineMath
import com.m57.hermescontrol.util.BidiUtils
private val URL_PATTERN = Regex("""https?://[^\s)>\[\]"'‘’]+""")
private val TABLE_COL_WIDTH = 160.dp
private fun bidiTextDirection(isRtl: Boolean): TextDirection = if (isRtl) TextDirection.Rtl else TextDirection.Ltr
@@ -359,13 +358,13 @@ fun MarkdownText(
.fillMaxWidth()
.padding(vertical = 4.dp),
) {
com.m57.hermescontrol.ui.chat.components.InlineVideoPlayer(
videoUri = resolvedUri,
com.m57.hermescontrol.ui.chat.components.InlineMediaPlayer(
uri = resolvedUri,
onFullScreenClick = { showVideoDialog = true },
)
if (showVideoDialog) {
com.m57.hermescontrol.ui.chat.components.VideoViewerDialog(
videoUri = resolvedUri,
com.m57.hermescontrol.ui.chat.components.MediaViewerDialog(
mediaUri = resolvedUri,
onDismissRequest = { showVideoDialog = false },
)
}
@@ -40,10 +40,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
*/
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). Emoji-free. */
val summaryPrefix: String = "",
/** Material icon for this tool type. */
val icon: ImageVector = Icons.Filled.Build,
)
@@ -55,285 +51,238 @@ object ToolSchemaRegistry {
"terminal" to
ToolDisplayConfig(
name = "terminal",
summaryArgKey = "command",
summaryPrefix = "$ ",
icon = Icons.Filled.Terminal,
),
"read_file" to
ToolDisplayConfig(
name = "read_file",
summaryArgKey = "path",
icon = Icons.Filled.Description,
),
"write_file" to
ToolDisplayConfig(
name = "write_file",
summaryArgKey = "path",
icon = Icons.Filled.Edit,
),
"patch" to
ToolDisplayConfig(
name = "patch",
summaryArgKey = "path",
icon = Icons.Filled.Build,
),
"search_files" to
ToolDisplayConfig(
name = "search_files",
summaryArgKey = "pattern",
icon = Icons.Filled.Search,
),
"web_search" to
ToolDisplayConfig(
name = "web_search",
summaryArgKey = "query",
icon = Icons.Filled.Public,
),
"browser_navigate" to
ToolDisplayConfig(
name = "browser_navigate",
summaryArgKey = "url",
icon = Icons.Filled.Language,
),
"browser_click" to
ToolDisplayConfig(
name = "browser_click",
summaryArgKey = "ref",
icon = Icons.Filled.TouchApp,
),
"browser_snapshot" to
ToolDisplayConfig(
name = "browser_snapshot",
summaryArgKey = null,
icon = Icons.Filled.Photo,
),
"clarify" to
ToolDisplayConfig(
name = "clarify",
summaryArgKey = "question",
icon = Icons.Filled.ChatBubble,
),
"delegate_task" to
ToolDisplayConfig(
name = "delegate_task",
summaryArgKey = "goal",
icon = Icons.Filled.AccountTree,
),
"execute_code" to
ToolDisplayConfig(
name = "execute_code",
summaryArgKey = "code",
icon = Icons.Filled.PlayArrow,
),
"todo" to
ToolDisplayConfig(
name = "todo",
summaryArgKey = null,
icon = Icons.Filled.Checklist,
),
"todo_list" to
ToolDisplayConfig(
name = "todo_list",
summaryArgKey = null,
icon = Icons.Filled.Checklist,
),
"fact_store" to
ToolDisplayConfig(
name = "fact_store",
summaryArgKey = null,
icon = Icons.Filled.Psychology,
),
"session_search" to
ToolDisplayConfig(
name = "session_search",
summaryArgKey = null,
icon = Icons.Filled.Search,
),
// ── Action-based tools ──
"cronjob" to
ToolDisplayConfig(
name = "cronjob",
summaryArgKey = "action",
icon = Icons.Filled.Schedule,
),
"cronjob_manage" to
ToolDisplayConfig(
name = "cronjob_manage",
summaryArgKey = "action",
icon = Icons.Filled.Schedule,
),
"memory" to
ToolDisplayConfig(
name = "memory",
summaryArgKey = "action",
icon = Icons.Filled.Memory,
),
"fact_feedback" to
ToolDisplayConfig(
name = "fact_feedback",
summaryArgKey = "action",
icon = Icons.Filled.ThumbUp,
),
"process" to
ToolDisplayConfig(
name = "process",
summaryArgKey = "action",
icon = Icons.Filled.Settings,
),
"process_manage" to
ToolDisplayConfig(
name = "process_manage",
summaryArgKey = "action",
icon = Icons.Filled.Settings,
),
"skill_manage" to
ToolDisplayConfig(
name = "skill_manage",
summaryArgKey = "action",
icon = Icons.Filled.Build,
),
// ── Web / Browser tools ──
"web_extract" to
ToolDisplayConfig(
name = "web_extract",
summaryArgKey = "urls",
icon = Icons.Filled.Language,
),
"browser_type" to
ToolDisplayConfig(
name = "browser_type",
summaryArgKey = null,
icon = Icons.Filled.Keyboard,
),
"browser_scroll" to
ToolDisplayConfig(
name = "browser_scroll",
summaryArgKey = "direction",
icon = Icons.Filled.TouchApp,
),
"browser_back" to
ToolDisplayConfig(
name = "browser_back",
summaryArgKey = null,
icon = Icons.Filled.Language,
),
"browser_press" to
ToolDisplayConfig(
name = "browser_press",
summaryArgKey = "key",
icon = Icons.Filled.Keyboard,
),
"browser_get_images" to
ToolDisplayConfig(
name = "browser_get_images",
summaryArgKey = null,
icon = Icons.Filled.Image,
),
"browser_vision" to
ToolDisplayConfig(
name = "browser_vision",
summaryArgKey = "question",
icon = Icons.Filled.Visibility,
),
"browser_console" to
ToolDisplayConfig(
name = "browser_console",
summaryArgKey = null,
icon = Icons.Filled.Terminal,
),
"browser_cdp" to
ToolDisplayConfig(
name = "browser_cdp",
summaryArgKey = "action",
icon = Icons.Filled.Build,
),
"browser_dialog" to
ToolDisplayConfig(
name = "browser_dialog",
summaryArgKey = "action",
icon = Icons.Filled.ChatBubble,
),
// ── Media / Vision tools ──
"vision_analyze" to
ToolDisplayConfig(
name = "vision_analyze",
summaryArgKey = "image_url",
icon = Icons.Filled.Visibility,
),
"text_to_speech" to
ToolDisplayConfig(
name = "text_to_speech",
summaryArgKey = null,
icon = Icons.AutoMirrored.Filled.VolumeUp,
),
"video_generate" to
ToolDisplayConfig(
name = "video_generate",
summaryArgKey = null,
icon = Icons.Filled.Movie,
),
"image_generate" to
ToolDisplayConfig(
name = "image_generate",
summaryArgKey = null,
icon = Icons.Filled.Image,
),
// ── Social / Messaging tools ──
"x_search" to
ToolDisplayConfig(
name = "x_search",
summaryArgKey = "query",
icon = Icons.Filled.Forum,
),
"send_message" to
ToolDisplayConfig(
name = "send_message",
summaryArgKey = null,
icon = Icons.AutoMirrored.Filled.Send,
),
// ── Skills tools ──
"skills_list" to
ToolDisplayConfig(
name = "skills_list",
summaryArgKey = null,
icon = Icons.AutoMirrored.Filled.MenuBook,
),
"skill_view" to
ToolDisplayConfig(
name = "skill_view",
summaryArgKey = "name",
icon = Icons.Filled.AutoStories,
),
// ── On-demand tools ──
"tool_search" to
ToolDisplayConfig(
name = "tool_search",
summaryArgKey = "query",
icon = Icons.Filled.Search,
),
"tool_describe" to
ToolDisplayConfig(
name = "tool_describe",
summaryArgKey = "name",
icon = Icons.Filled.AutoStories,
),
"tool_call" to
ToolDisplayConfig(
name = "tool_call",
summaryArgKey = "name",
icon = Icons.Filled.Build,
),
// ── Misc ──
"read_terminal" to
ToolDisplayConfig(
name = "read_terminal",
summaryArgKey = "session_id",
icon = Icons.Filled.Computer,
),
"computer_use" to
ToolDisplayConfig(
name = "computer_use",
summaryArgKey = "action",
icon = Icons.Filled.Computer,
),
)
@@ -209,3 +209,18 @@ private fun InlineVideoPreview(
}
}
}
/** Formats milliseconds into `M:SS` or `H:MM:SS` */
fun formatMediaDuration(durationMs: Long): String {
if (durationMs <= 0) return "0:00"
val totalSeconds = durationMs / 1000
val seconds = totalSeconds % 60
val minutes = (totalSeconds / 60) % 60
val hours = totalSeconds / 3600
return if (hours > 0) {
"%d:%02d:%02d".format(hours, minutes, seconds)
} else {
"%d:%02d".format(minutes, seconds)
}
}
@@ -1,35 +0,0 @@
package com.m57.hermescontrol.ui.chat.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
/**
* Backwards-compatible wrapper delegating to [InlineMediaPlayer].
*/
@Composable
fun InlineVideoPlayer(
videoUri: String,
modifier: Modifier = Modifier,
onFullScreenClick: () -> Unit = {},
) {
InlineMediaPlayer(
uri = videoUri,
modifier = modifier,
onFullScreenClick = onFullScreenClick,
)
}
/** Formats milliseconds into `M:SS` or `H:MM:SS` */
fun formatMediaDuration(durationMs: Long): String {
if (durationMs <= 0) return "0:00"
val totalSeconds = durationMs / 1000
val seconds = totalSeconds % 60
val minutes = (totalSeconds / 60) % 60
val hours = totalSeconds / 3600
return if (hours > 0) {
"%d:%02d:%02d".format(hours, minutes, seconds)
} else {
"%d:%02d".format(minutes, seconds)
}
}
@@ -90,7 +90,6 @@ import com.m57.hermescontrol.theme.CodeTerminalMuted
import com.m57.hermescontrol.theme.CodeTerminalText
import com.m57.hermescontrol.ui.chat.ClarifyUi
import com.m57.hermescontrol.ui.chat.MarkdownText
import com.m57.hermescontrol.ui.chat.SubagentIndicator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
@@ -400,14 +399,6 @@ private data class TokenPattern(
val color: Color,
)
private fun copyToClipboard(
context: Context,
text: String,
) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return
clipboard.setPrimaryClip(ClipData.newPlainText(null, text))
}
// ── ClarifyBubble ─────────────────────────────────────────────────────────
/**
@@ -670,58 +661,6 @@ fun ClarifyBubble(
)
}
// ── SubagentCard ──────────────────────────────────────────────────────────
/**
* Inline card showing subagent task progress.
*
* - While running: [CircularProgressIndicator] + goal text on [tertiaryContainer].
* - On completion: ✅ checkmark + summary text.
*/
@Composable
fun SubagentCard(
indicator: SubagentIndicator,
modifier: Modifier = Modifier,
) {
val isComplete = indicator.type == "subagent.complete"
Surface(
modifier = modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 2.dp).testTag("subagent_card"),
shape = RoundedCornerShape(12.dp),
color = MaterialTheme.colorScheme.tertiaryContainer,
) {
Row(
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
if (isComplete) {
Text(text = "✅", fontSize = 14.sp)
} else {
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
strokeWidth = 2.dp,
color = MaterialTheme.colorScheme.onTertiaryContainer,
)
}
Spacer(Modifier.width(8.dp))
val displayText =
if (isComplete && !indicator.summary.isNullOrBlank()) {
indicator.summary
} else if (!indicator.goal.isNullOrBlank()) {
indicator.goal
} else {
"Subagent task"
}
Text(
text = displayText,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onTertiaryContainer,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
}
}
}
// ── TypingIndicator ───────────────────────────────────────────────────────
/**
@@ -1,17 +0,0 @@
package com.m57.hermescontrol.ui.chat.components
import androidx.compose.runtime.Composable
/**
* Backwards-compatible wrapper delegating to [MediaViewerDialog].
*/
@Composable
fun VideoViewerDialog(
videoUri: String,
onDismissRequest: () -> Unit,
) {
MediaViewerDialog(
mediaUri = videoUri,
onDismissRequest = onDismissRequest,
)
}
@@ -93,8 +93,6 @@ fun FullBleedChatList(
isLoadingOlder: Boolean,
listState: androidx.compose.foundation.lazy.LazyListState,
scrollController: ChatScrollController,
lastAnimatedMessageId: String?,
onLastAnimatedMessageIdChange: (String?) -> Unit,
viewModel: ChatViewModel,
clarifyRequest: ClarifyUi? = null,
onRespondClarify: ((String) -> Unit)? = null,