feat(tui): add agent interaction workflows

This commit is contained in:
Xubin Ren
2026-08-17 20:56:10 +08:00
parent e77eed76c9
commit 4391bbf4da
28 changed files with 1275 additions and 87 deletions
+65
View File
@@ -0,0 +1,65 @@
import type { ToolProgressEvent } from "./protocol"
export function mergeToolEvent(
previous: ToolProgressEvent | undefined,
next: ToolProgressEvent,
): ToolProgressEvent {
if (!previous) return next
return {
...previous,
...next,
arguments: next.arguments ?? previous.arguments,
result: next.result ?? previous.result,
error: next.error ?? previous.error,
}
}
export function renderToolEvent(event: ToolProgressEvent): string {
const phase = event.phase || "start"
const marker = phase === "error" ? "×" : phase === "end" ? "✓" : ""
const name = (event.name || "tool").trim()
const args = record(event.arguments)
const result = record(event.result)
const detail = phase === "error" ? compact(event.error) : toolDetail(name, args, result)
return ` ${marker} ${toolLabel(name)}${detail ? ` ${detail}` : ""}`
}
function toolLabel(name: string): string {
if (/^(?:exec|exec_command|shell|run_command)$/u.test(name)) return "Command"
if (/^(?:read_file|read)$/u.test(name)) return "Read"
if (/^(?:write_file|write)$/u.test(name)) return "Write"
if (/^(?:edit_file|apply_patch|edit)$/u.test(name)) return "Edit"
if (name === "web_search") return "Search web"
if (name === "web_fetch") return "Fetch"
return name
}
function toolDetail(
name: string,
args: Record<string, unknown>,
result: Record<string, unknown>,
): string {
if (/^(?:exec|exec_command|shell|run_command)$/u.test(name)) {
return compact(args.command ?? args.cmd ?? result.output)
}
if (/^(?:read_file|write_file|edit_file|apply_patch|read|write|edit)$/u.test(name)) {
return compact(args.path ?? args.file_path ?? result.path)
}
if (name === "web_search") return compact(args.query ?? args.q)
if (name === "web_fetch") return compact(args.url)
if (/session/u.test(name)) return compact(args.session_key ?? args.chat_id ?? args.query)
if (Object.keys(args).length) return compact(args)
return Object.keys(result).length ? compact(result) : ""
}
function record(value: unknown): Record<string, unknown> {
return value && typeof value === "object" && !Array.isArray(value)
? value as Record<string, unknown>
: {}
}
function compact(value: unknown): string {
if (value == null || value === "") return ""
const text = typeof value === "string" ? value : JSON.stringify(value)
return text.length > 88 ? `${text.slice(0, 85)}` : text
}