From c736d0e1297a34cbfea48966c0780d0942e0dedf Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Tue, 12 May 2026 14:11:42 +0000 Subject: [PATCH] renderer: tool-call begin/end frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 commit #4 per docs/PHASE2.md §12. Adds M.tool_call_begin(name, args) and M.tool_call_end(content, is_error) for visual parity with the existing exec_begin/exec_end frame. Visual cadence: ─── tool: ─── ─── ok ─── (dim, success) ─── error ─── (red status word inside dim rule, on is_error=true) Same rule glyph (━) and ANSI palette as the exec frame so the user reads tool dispatch and shell dispatch the same way. Smoke-tested all five shapes: success with args / empty args / error / long args truncated / empty content. Co-Authored-By: Claude Opus 4.7 (1M context) --- renderer.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/renderer.lua b/renderer.lua index 1ee776c..cd21d7d 100644 --- a/renderer.lua +++ b/renderer.lua @@ -76,4 +76,35 @@ function M.assistant_flush() stream_buf = nil end +-- Phase 2: MCP tool-call frame. Visual parity with the exec_begin/exec_end +-- frame so the user reads tool dispatch and shell dispatch the same way. +-- tool_call_begin renders the top rule + (optionally) the args as a dim +-- preview; tool_call_end renders the result content followed by a status +-- rule. Status is "ok" (dim) by default; "error" (red) if is_error is true. +-- See docs/PHASE2.md §3 renderer.lua row + §4 Tool invocation. + +function M.tool_call_begin(name, args) + emit(A.dim, "─── tool: ", A.reset, + A.cyan, name, A.reset, + A.dim, " ───", A.reset, "\n") + if args and args ~= "" and args ~= "{}" then + local shown = (#args <= 200) and args or (args:sub(1, 197) .. "...") + emit(A.dim, shown, A.reset, "\n") + end +end + +function M.tool_call_end(content, is_error) + if content and content ~= "" then + emit(content) + if not content:match("\n$") then emit("\n") end + end + if is_error then + emit(A.dim, "─── ", A.reset, + A.red, "error", A.reset, + A.dim, " ───", A.reset, "\n") + else + emit(A.dim, "─── ok ───", A.reset, "\n") + end +end + return M