10 files changed
+57
No files matched your search
@@ -495,6 +495,13 @@ private fun ExpandedToolContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view.outputCut?.let { omitted ->
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.chat_tool_output_omitted, omitted),
|
||||||
|
style = MaterialTheme.typography.labelSmall.copy(color = statusColors.warning),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// ── Duration footer ──
|
// ── Duration footer ──
|
||||||
view.durationLabel?.let {
|
view.durationLabel?.let {
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ internal interface ToolRenderer {
|
|||||||
*/
|
*/
|
||||||
internal data class ToolViewExtras(
|
internal data class ToolViewExtras(
|
||||||
val detailLabel: String? = null,
|
val detailLabel: String? = null,
|
||||||
|
/** Process output characters omitted by the backend. */
|
||||||
|
val outputCut: Long? = null,
|
||||||
val stdout: String? = null,
|
val stdout: String? = null,
|
||||||
val stderr: String? = null,
|
val stderr: String? = null,
|
||||||
val exitCode: Int? = null,
|
val exitCode: Int? = null,
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ data class ToolView(
|
|||||||
val detail: String = "",
|
val detail: String = "",
|
||||||
/** Optional section label above [detail] (e.g. "Search results"). */
|
/** Optional section label above [detail] (e.g. "Search results"). */
|
||||||
val detailLabel: String? = null,
|
val detailLabel: String? = null,
|
||||||
|
/** Process output characters omitted by the backend. */
|
||||||
|
val outputCut: Long? = null,
|
||||||
/** Compact count, e.g. "3 results". */
|
/** Compact count, e.g. "3 results". */
|
||||||
val countLabel: String? = null,
|
val countLabel: String? = null,
|
||||||
/** Human duration, e.g. "1.2s". */
|
/** Human duration, e.g. "1.2s". */
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ object ToolViewBuilder {
|
|||||||
subtitle = subtitle,
|
subtitle = subtitle,
|
||||||
detail = clampedDetail,
|
detail = clampedDetail,
|
||||||
detailLabel = extras.detailLabel,
|
detailLabel = extras.detailLabel,
|
||||||
|
outputCut = extras.outputCut,
|
||||||
countLabel = countLabel?.let { (count, noun) -> "$count ${ToolCounts.pluralizeNoun(noun, count)}" },
|
countLabel = countLabel?.let { (count, noun) -> "$count ${ToolCounts.pluralizeNoun(noun, count)}" },
|
||||||
durationLabel = ToolJson.durationLabel(call.result),
|
durationLabel = ToolJson.durationLabel(call.result),
|
||||||
stdout = clampedStdout,
|
stdout = clampedStdout,
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ package com.m57.hermescontrol.ui.chat.tool.render
|
|||||||
import com.m57.hermescontrol.ui.chat.tool.ToolCall
|
import com.m57.hermescontrol.ui.chat.tool.ToolCall
|
||||||
import com.m57.hermescontrol.ui.chat.tool.ToolJson
|
import com.m57.hermescontrol.ui.chat.tool.ToolJson
|
||||||
import com.m57.hermescontrol.ui.chat.tool.ToolRenderer
|
import com.m57.hermescontrol.ui.chat.tool.ToolRenderer
|
||||||
|
import com.m57.hermescontrol.ui.chat.tool.ToolViewExtras
|
||||||
|
import com.m57.hermescontrol.ui.chat.tool.ToolViewStatus
|
||||||
import kotlinx.serialization.json.JsonArray
|
import kotlinx.serialization.json.JsonArray
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
|
import kotlinx.serialization.json.longOrNull
|
||||||
|
|
||||||
/** `cronjob`: job listings with schedules, or the mutated job's key fields. */
|
/** `cronjob`: job listings with schedules, or the mutated job's key fields. */
|
||||||
internal object CronjobRenderer : ToolRenderer {
|
internal object CronjobRenderer : ToolRenderer {
|
||||||
@@ -214,6 +217,15 @@ internal object SessionSearchRenderer : ToolRenderer {
|
|||||||
|
|
||||||
/** `process`: background session listings and lifecycle acks. */
|
/** `process`: background session listings and lifecycle acks. */
|
||||||
internal object ProcessRenderer : ToolRenderer {
|
internal object ProcessRenderer : ToolRenderer {
|
||||||
|
override fun extras(
|
||||||
|
call: ToolCall,
|
||||||
|
status: ToolViewStatus,
|
||||||
|
): ToolViewExtras {
|
||||||
|
if (status == ToolViewStatus.RUNNING) return ToolViewExtras.NONE
|
||||||
|
val count = (call.result?.get("output_cut") as? JsonPrimitive)?.takeUnless { it.isString }?.longOrNull
|
||||||
|
return ToolViewExtras(outputCut = count?.takeIf { it > 0 })
|
||||||
|
}
|
||||||
|
|
||||||
override fun subtitle(call: ToolCall): String {
|
override fun subtitle(call: ToolCall): String {
|
||||||
val action = ToolJson.firstString(call.args, listOf("action"))
|
val action = ToolJson.firstString(call.args, listOf("action"))
|
||||||
val procId = ToolJson.firstString(call.args, listOf("session_id"))
|
val procId = ToolJson.firstString(call.args, listOf("session_id"))
|
||||||
|
|||||||
@@ -165,6 +165,7 @@
|
|||||||
<string name="chat_input_placeholder_type_message">اكتب رسالة\u2026</string>
|
<string name="chat_input_placeholder_type_message">اكتب رسالة\u2026</string>
|
||||||
<string name="chat_tool_execution_error">خطأ في التنفيذ: %1$s</string>
|
<string name="chat_tool_execution_error">خطأ في التنفيذ: %1$s</string>
|
||||||
<string name="chat_tool_exit_code">رمز الخروج: %1$d</string>
|
<string name="chat_tool_exit_code">رمز الخروج: %1$d</string>
|
||||||
|
<string name="chat_tool_output_omitted">تم حذف %1$d حرف من مخرجات العملية</string>
|
||||||
<string name="chat_tool_fallback">أداة</string>
|
<string name="chat_tool_fallback">أداة</string>
|
||||||
<string name="chat_tool_show_raw">عرض ملف JSON الأولي</string>
|
<string name="chat_tool_show_raw">عرض ملف JSON الأولي</string>
|
||||||
<string name="chat_tool_show_parsed">عرض المخرجات المعالجة</string>
|
<string name="chat_tool_show_parsed">عرض المخرجات المعالجة</string>
|
||||||
|
|||||||
@@ -162,6 +162,7 @@
|
|||||||
<string name="chat_input_placeholder_type_message">메시지 입력…</string>
|
<string name="chat_input_placeholder_type_message">메시지 입력…</string>
|
||||||
<string name="chat_tool_execution_error">실행 오류: %1$s</string>
|
<string name="chat_tool_execution_error">실행 오류: %1$s</string>
|
||||||
<string name="chat_tool_exit_code">종료 코드: %1$d</string>
|
<string name="chat_tool_exit_code">종료 코드: %1$d</string>
|
||||||
|
<string name="chat_tool_output_omitted">프로세스 출력에서 %1$d자 생략됨</string>
|
||||||
<string name="chat_tool_fallback">도구</string>
|
<string name="chat_tool_fallback">도구</string>
|
||||||
<string name="chat_tool_show_raw">Raw JSON 보기</string>
|
<string name="chat_tool_show_raw">Raw JSON 보기</string>
|
||||||
<string name="chat_tool_show_parsed">파싱된 결과 보기</string>
|
<string name="chat_tool_show_parsed">파싱된 결과 보기</string>
|
||||||
|
|||||||
@@ -165,6 +165,7 @@
|
|||||||
<string name="chat_input_placeholder_type_message">输入消息…</string>
|
<string name="chat_input_placeholder_type_message">输入消息…</string>
|
||||||
<string name="chat_tool_execution_error">执行错误:%1$s</string>
|
<string name="chat_tool_execution_error">执行错误:%1$s</string>
|
||||||
<string name="chat_tool_exit_code">退出码:%1$d</string>
|
<string name="chat_tool_exit_code">退出码:%1$d</string>
|
||||||
|
<string name="chat_tool_output_omitted">进程输出省略了 %1$d 个字符</string>
|
||||||
<string name="chat_tool_fallback">工具</string>
|
<string name="chat_tool_fallback">工具</string>
|
||||||
<string name="chat_tool_show_raw">显示原始 JSON</string>
|
<string name="chat_tool_show_raw">显示原始 JSON</string>
|
||||||
<string name="chat_tool_show_parsed">显示解析输出</string>
|
<string name="chat_tool_show_parsed">显示解析输出</string>
|
||||||
|
|||||||
@@ -196,6 +196,7 @@
|
|||||||
<string name="chat_input_placeholder_type_message">Type a message\u2026</string>
|
<string name="chat_input_placeholder_type_message">Type a message\u2026</string>
|
||||||
<string name="chat_tool_execution_error">Execution Error: %1$s</string>
|
<string name="chat_tool_execution_error">Execution Error: %1$s</string>
|
||||||
<string name="chat_tool_exit_code">Exit Code: %1$d</string>
|
<string name="chat_tool_exit_code">Exit Code: %1$d</string>
|
||||||
|
<string name="chat_tool_output_omitted">%1$d characters omitted from process output</string>
|
||||||
<string name="chat_tool_fallback">Tool</string>
|
<string name="chat_tool_fallback">Tool</string>
|
||||||
<string name="chat_tool_show_raw">Show Raw JSON</string>
|
<string name="chat_tool_show_raw">Show Raw JSON</string>
|
||||||
<string name="chat_tool_show_parsed">Show Parsed Output</string>
|
<string name="chat_tool_show_parsed">Show Parsed Output</string>
|
||||||
|
|||||||
@@ -308,6 +308,35 @@ class ToolViewBuilderTest {
|
|||||||
assertEquals("poll: proc-1", view.subtitle)
|
assertEquals("poll: proc-1", view.subtitle)
|
||||||
assertTrue(view.detail.contains("Status: running"))
|
assertTrue(view.detail.contains("Status: running"))
|
||||||
assertTrue(view.detail.contains("listening on port 8080"))
|
assertTrue(view.detail.contains("listening on port 8080"))
|
||||||
|
assertEquals(null, view.outputCut)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `process output reports backend omitted character count for each action`() {
|
||||||
|
listOf("poll", "wait", "log", "kill").forEach { action ->
|
||||||
|
val outputKey = if (action == "poll") "output_preview" else "output"
|
||||||
|
val view =
|
||||||
|
build(
|
||||||
|
"process_manage",
|
||||||
|
"""{"action":"$action","session_id":"proc-1"}""",
|
||||||
|
"""{"status":"exited","$outputKey":"partial output","output_cut":42}""",
|
||||||
|
)
|
||||||
|
|
||||||
|
assertTrue(view.detail.contains("partial output"))
|
||||||
|
assertEquals(42L, view.outputCut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `process output without positive numeric omission has no notice`() {
|
||||||
|
listOf("{}", """{"output_cut":0}""", """{"output_cut":"unknown"}""").forEach { metadata ->
|
||||||
|
val fields = metadata.removePrefix("{").removeSuffix("}")
|
||||||
|
val result = """{"output":"complete"${if (fields.isNotEmpty()) ",$fields" else ""}}"""
|
||||||
|
val view = build("process", """{"action":"wait"}""", result)
|
||||||
|
|
||||||
|
assertEquals("complete", view.detail)
|
||||||
|
assertEquals(null, view.outputCut)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in new issue
Block a user