@@ -80,6 +80,39 @@ class ToolCall:
8080 elapsed : float | None = None # execution wall-time in seconds (TUI display)
8181
8282
83+ def arg_repr (value : Any , limit : int = 100 ) -> str :
84+ """repr() of a tool-call argument, truncated to LIMIT chars total.
85+
86+ Long values (a long Bash command, a big JSON payload) are cut with
87+ an ellipsis instead of being dropped from the label entirely.
88+ """
89+ r = repr (value )
90+ if len (r ) <= limit :
91+ return r
92+ return r [: limit - 1 ] + "…"
93+
94+
95+ def display_args (arguments : dict [str , Any ] | str , limit : int = 100 ) -> dict [str , str ]:
96+ """Tool-call arguments as short display strings, keyed by name.
97+
98+ ``arguments`` arrives either already decoded or as the raw JSON
99+ string the model emitted (unparseable when the model truncated it).
100+ ``content`` is skipped: a Write/Edit payload is far too large for a
101+ one-line label, and it is shown as a diff instead.
102+
103+ Values are truncated, so the result is a display artifact -- never
104+ the data a tool is executed with.
105+ """
106+ if isinstance (arguments , str ):
107+ try :
108+ arguments = json .loads (arguments )
109+ except (json .JSONDecodeError , ValueError ):
110+ return {}
111+ if not isinstance (arguments , dict ):
112+ return {}
113+ return {k : arg_repr (v , limit ) for k , v in arguments .items () if k != "content" }
114+
115+
83116@dataclass
84117class Message :
85118 """One conversation message in OpenAI-compatible format.
0 commit comments