feat: add full chat slash commands support (/help, /status, /sessions, /stats)
This commit is contained in:
1 parent
21a020c87e
commit
48bf0a1ffc
2 files changed
+127
No files matched your search
@@ -34,6 +34,8 @@ This document tracks the completed features and the pending backlog for the Herm
|
||||
* **System View (`SystemScreen`)**: Diagnostics doctor reports (`GET /api/ops/doctor`) and backups trigger (`POST /api/ops/backup`).
|
||||
* **Kanban View (`KanbanScreen`)**: Full task boards, task columns (To Do, In Progress, Done), new tasks dialog, and task movement with optimistic updates.
|
||||
* **Navigation Drawer**: Material3 navigation drawer using Navigation3 keys to switch between all screens.
|
||||
* **Chat Slash Commands**: Local interception and execution of custom commands (`/help`, `/status`, `/sessions`, `/stats` / `/system`, `/new`, `/stop` / `/interrupt`) displaying results inline.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -310,6 +310,12 @@ class ChatViewModel : ViewModel() {
|
||||
if (text.isBlank()) return
|
||||
val sessionId = _uiState.value.currentSessionId ?: return
|
||||
|
||||
val trimmed = text.trim()
|
||||
if (trimmed.startsWith("/", ignoreCase = true)) {
|
||||
handleSlashCommand(trimmed)
|
||||
return
|
||||
}
|
||||
|
||||
// Add user message to UI
|
||||
val userMessage =
|
||||
ChatMessage(
|
||||
@@ -329,6 +335,125 @@ class ChatViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSlashCommand(command: String) {
|
||||
val userMsg = ChatMessage(role = MessageRole.USER, content = command)
|
||||
_uiState.update { it.copy(messages = it.messages + userMsg) }
|
||||
|
||||
val parts = command.split(" ")
|
||||
val cmd = parts[0].lowercase()
|
||||
|
||||
when (cmd) {
|
||||
"/stop", "/interrupt" -> {
|
||||
interruptSession()
|
||||
}
|
||||
|
||||
"/new" -> {
|
||||
createNewSession()
|
||||
}
|
||||
|
||||
"/help" -> {
|
||||
val helpText =
|
||||
"""
|
||||
**Available Commands:**
|
||||
• `/help` - Show this help menu
|
||||
• `/status` - Check gateway and platform status
|
||||
• `/sessions` - List all chat sessions
|
||||
• `/stats` or `/system` - Check system resource usage
|
||||
• `/new` - Create a new chat session
|
||||
• `/stop` or `/interrupt` - Interrupt the active run
|
||||
""".trimIndent()
|
||||
addAssistantMessage(helpText)
|
||||
}
|
||||
|
||||
"/status" -> {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val response = withContext(Dispatchers.IO) { ApiClient.hermesApi.getStatus() }
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val body = response.body()!!
|
||||
val platformsStr =
|
||||
body.gateway_platforms?.entries?.joinToString("\n") { (k, v) ->
|
||||
" • **$k**: ${v.state ?: "Unknown"}${if (v.error_code != null) " (Error: ${v.error_code})" else ""}"
|
||||
} ?: "No active platforms"
|
||||
|
||||
val statusText =
|
||||
"""
|
||||
**Hermes Gateway Status:**
|
||||
• **Version:** ${body.version ?: "Unknown"}
|
||||
• **Gateway Running:** ${body.gateway_running ?: false}
|
||||
• **Active Sessions:** ${body.active_sessions ?: 0}
|
||||
• **Auth Required:** ${body.auth_required ?: false}
|
||||
|
||||
**Platforms:**
|
||||
$platformsStr
|
||||
""".trimIndent()
|
||||
addAssistantMessage(statusText)
|
||||
} else {
|
||||
addAssistantMessage("Failed to retrieve status: HTTP ${response.code()}")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
addAssistantMessage("Failed to retrieve status: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"/sessions" -> {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val response = withContext(Dispatchers.IO) { ApiClient.hermesApi.getSessions() }
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val body = response.body()!!
|
||||
val sessionsStr =
|
||||
body.sessions.joinToString("\n") { s ->
|
||||
"• **${s.title ?: "Untitled"}** (ID: `${s.id}`, Messages: ${s.message_count ?: 0})"
|
||||
}
|
||||
addAssistantMessage("**Sessions List:**\n$sessionsStr")
|
||||
} else {
|
||||
addAssistantMessage("Failed to list sessions: HTTP ${response.code()}")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
addAssistantMessage("Failed to list sessions: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"/stats", "/system" -> {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val response = withContext(Dispatchers.IO) { ApiClient.hermesApi.getSystemStats() }
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val body = response.body()!!
|
||||
val cpuPct = body.cpuPercent?.let { String.format("%.1f%%", it) } ?: "N/A"
|
||||
val memPct = body.memoryPercent?.let { String.format("%.1f%%", it) } ?: "N/A"
|
||||
val uptimeVal = body.uptime ?: "N/A"
|
||||
val statsText =
|
||||
"""
|
||||
**System Resource Stats:**
|
||||
• **CPU Usage:** $cpuPct
|
||||
• **Memory Usage:** $memPct
|
||||
• **Uptime:** $uptimeVal
|
||||
""".trimIndent()
|
||||
addAssistantMessage(statsText)
|
||||
} else {
|
||||
addAssistantMessage("Failed to retrieve system stats: HTTP ${response.code()}")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
addAssistantMessage("Failed to retrieve system stats: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
addAssistantMessage("Unknown command: `$cmd`. Type `/help` to view a list of available commands.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addAssistantMessage(text: String) {
|
||||
val msg = ChatMessage(role = MessageRole.ASSISTANT, content = text)
|
||||
_uiState.update { it.copy(messages = it.messages + msg) }
|
||||
}
|
||||
|
||||
fun interruptSession() {
|
||||
val sessionId = _uiState.value.currentSessionId ?: return
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
|
||||
Reference in new issue
Block a user