11/**
2- * Human-readable tool arguments for the transcript. A call shows what it *is*
3- * — a path, a command, the shape of a view — and keeps the structured form
4- * behind the expand key.
2+ * Human-readable tool arguments for the transcript: what a call shows — a
3+ * path, a command, the shape of a view — with the structured form kept behind
4+ * the expand key.
55 *
6- * Wording comes from `tui/tool-formatter` and the view tree from `tui/view`;
7- * this module only maps them onto the palette and row model.
6+ * Wording comes from `tui/tool-formatter`; the view tree from `tui/view`.
7+ * This module only maps them onto the palette and row model.
88 */
99
1010import { isMcpToolName } from "../mcp/tool-name.js" ;
@@ -18,18 +18,17 @@ import { UI } from "./theme.js";
1818
1919/**
2020 * A summarised call: the collapsed line, and the body the expand key reveals.
21- * An empty summary means the verb already names the call; an absent detail
22- * means there is nothing behind the summary worth an arrow.
21+ * Empty summary: the verb already names the call. Absent detail: nothing
22+ * behind the summary worth an arrow.
2323 */
2424export interface ToolArgsView {
2525 readonly summary : string ;
2626 readonly detail ?: readonly StyledBodyLine [ ] ;
2727}
2828
2929/**
30- * View roles in the Corbits palette. Warning and danger both land on action
31- * orange — there is no red in the brand system, and no decision marker
32- * competes on these rows.
30+ * View roles in the Corbits palette. Warning and danger share action orange
31+ * — the brand has no red, and no decision marker competes on these rows.
3332 */
3433const ROLE_FG : Partial < Record < SemanticRole , string > > = {
3534 accent : UI . inFlightBright ,
@@ -65,8 +64,8 @@ function parseObject(raw: string): Record<string, unknown> | null {
6564 return parsed as Record < string , unknown > ;
6665}
6766
68- /** The view tree a call carries, whole-args or under a `view` key. Validated
69- * rather than duck-typed: renderers trust the shape. */
67+ /** The view tree a call carries, whole-args or under a `view` key.
68+ * Validated, not duck-typed: renderers trust the shape. */
7069function viewArgument ( args : Record < string , unknown > ) : ViewNode | null {
7170 const candidate = "view" in args ? args . view : args ;
7271 const result = validateView ( candidate ) ;
@@ -118,9 +117,9 @@ function isScalar(value: unknown): boolean {
118117}
119118
120119/**
121- * Scalar (or scalar-array) args as `key value` pairs with newlines intact —
122- * a shell command or spawn prompt is written to be read as text, and
123- * pretty-printed JSON would escape its line breaks.
120+ * Scalar (or scalar-array) args as `key value` pairs with newlines intact:
121+ * a shell command reads as text, and pretty-printed JSON would escape its
122+ * line breaks.
124123 *
125124 * Nested objects recurse one level so a task brief expands as fields; deeper
126125 * nesting collapses to a compact token.
@@ -170,7 +169,7 @@ function fieldDetail(
170169 continue ;
171170 }
172171 if ( typeof value === "object" && value !== null && ! Array . isArray ( value ) ) {
173- // One level of nesting is enough for a spawn brief; deeper stays compact .
172+ // One nesting level is enough for a spawn brief.
174173 if ( indent === 0 ) {
175174 lines . push ( [ { text : `${ pad } ${ key } :` , fg : UI . textDim } ] ) ;
176175 lines . push (
@@ -184,7 +183,7 @@ function fieldDetail(
184183 }
185184 continue ;
186185 }
187- // Arrays of objects, etc. — compact rather than a wall of JSON.
186+ // Arrays of objects: compact, not a wall of JSON.
188187 lines . push ( [
189188 { text : `${ pad } ${ key } : ` , fg : UI . textDim } ,
190189 {
@@ -207,10 +206,10 @@ function jsonDetail(value: unknown): readonly StyledBodyLine[] {
207206const INLINE_MAX = 60 ;
208207
209208/**
210- * Argument a call is *about*, most-meaningful first. A row's subject is one
211- * value — the query, the command, the URL — because a transcript is scanned,
212- * and a serialised list would spend the row on a second argument cut off
213- * mid-word ("numR…"). Everything else is behind the arrow.
209+ * Argument a call is *about*, most-meaningful first. A transcript is
210+ * scanned, so the subject is one value — the query, the command, the URL —
211+ * not a serialised list that would cut the next argument mid-word. The rest
212+ * stays behind the arrow.
214213 */
215214const SUBJECT_KEYS = [
216215 "command" ,
@@ -233,8 +232,7 @@ function flatten(value: string): string {
233232}
234233
235234/** The one argument worth painting, or null when nothing scalar stands out.
236- * Falls back to the first scalar so an unknown tool still reads as a
237- * subject. */
235+ * Falls back to the first scalar so an unknown tool still has a subject. */
238236function primarySubject ( args : Record < string , unknown > ) : string | null {
239237 for ( const key of SUBJECT_KEYS ) {
240238 const value = args [ key ] ;
@@ -250,8 +248,8 @@ function primarySubject(args: Record<string, unknown>): string | null {
250248 : flatten ( first [ 1 ] as string ) . slice ( 0 , SUBJECT_MAX ) ;
251249}
252250
253- /** Whether the formatter fell back to serialising the whole argument object.
254- * Its per-tool cases never lead with `key: ` and are better subjects. */
251+ /** Whether the formatter serialised the whole argument object: its per-tool
252+ * cases never lead with `key: ` and make better subjects. */
255253function isArgumentList (
256254 args : Record < string , unknown > ,
257255 summary : string ,
@@ -267,13 +265,13 @@ function subjectFor(
267265) : string {
268266 const { summary } = summarizeToolArgs ( name , raw ) ;
269267 // An empty formatter summary is not a subject — fall through so a task
270- // without description still paints its prompt rather than raw JSON.
268+ // without a description paints its prompt, not raw JSON.
271269 if ( summary . length > 0 && ! isArgumentList ( args , summary ) ) return summary ;
272270 return primarySubject ( args ) ?? summary ;
273271}
274272
275- /** The summary/detail pair for a call's arguments, or null when short literal
276- * args read better as themselves than with an expand hint . */
273+ /** The summary/detail pair for a call's arguments, or null when short
274+ * literal args read better as themselves. */
277275export function toolArgsView (
278276 name : string ,
279277 rawArgs : string ,
@@ -289,8 +287,8 @@ export function toolArgsView(
289287 }
290288 }
291289
292- // An MCP call's verb is already the whole sentence; its args are a query,
293- // not a subject — they belong behind the expand key or nowhere.
290+ // An MCP call's verb is the whole sentence; its args are a query, not a
291+ // subject — they belong behind the expand key or nowhere.
294292 if ( args !== null && isMcpToolName ( name ) ) {
295293 return withDetail ( "" , fieldDetail ( args ) ) ;
296294 }
@@ -304,7 +302,7 @@ export function toolArgsView(
304302 }
305303 const subject = subjectFor ( name , raw , args ) ;
306304 // Object args always get a summarised view — even with an empty subject the
307- // verb names the call. A null return is what used to dump raw JSON.
305+ // verb names the call.
308306 return withDetail ( subject , fieldDetail ( args ) ) ;
309307}
310308
@@ -323,7 +321,7 @@ function withDetail(
323321 )
324322 . join ( "\n" )
325323 . trim ( ) ;
326- // A one-argument call whose subject *is* that argument reveals nothing but
324+ // A one-argument call whose subject is that argument reveals nothing but
327325 // the key it was named by; no arrow.
328326 const bare = plain . includes ( "\n" )
329327 ? plain
0 commit comments