@@ -84,41 +84,47 @@ function stringOrNumberArg(args: ToolArgs, key: string): string {
8484 */
8585function splitTableTitle ( name : string , args : ToolArgs ) : string {
8686 const op = stringArg ( args , 'operation' )
87- const target = firstStringArg ( args , 'name' , ' columnName', 'viewName' , 'tableName ' , 'title' )
87+ const target = firstStringArg ( args , 'columnName' , 'viewName' , 'name ' , 'title' )
8888 const suffix = target ? ` ${ target } ` : ''
89+ // "in Runtimes" / "of Runtimes" — enrichment resolves the nested tableId.
90+ const table = stringArg ( args , 'tableName' )
91+ const inTable = table ? ` in ${ table } ` : ''
92+ const ofTable = table ? ` of ${ table } ` : ''
8993 switch ( name ) {
9094 case 'table_manage' :
91- if ( op === 'create' ) return `Creating table${ suffix } `
92- if ( op === 'delete' ) return `Deleting table${ suffix } `
93- if ( op === 'read' || op === 'get' || op === 'list' ) return 'Reading table'
94- return 'Updating table'
95+ if ( op === 'create' ) return `Creating table${ suffix || ( table ? ` ${ table } ` : '' ) } `
96+ if ( op === 'delete' ) return `Deleting table${ table ? ` ${ table } ` : suffix } `
97+ if ( op === 'read' || op === 'get' || op === 'list' )
98+ return `Reading${ table ? ` ${ table } ` : ' table' } `
99+ return `Updating${ table ? ` ${ table } ` : ' table' } `
95100 case 'table_rows' :
96- if ( op === 'insert' || op === 'add' || op === 'create' ) return 'Adding rows'
97- if ( op === 'update' ) return 'Updating rows'
98- if ( op === 'delete' ) return 'Deleting rows'
99- if ( op === 'read' || op === 'list' || op === 'query' ) return 'Reading rows'
100- return 'Editing rows'
101+ if ( op === 'insert' || op === 'add' || op === 'create' )
102+ return `Adding rows${ inTable ? ` to ${ table } ` : '' } `
103+ if ( op === 'update' ) return `Updating rows${ inTable } `
104+ if ( op === 'delete' ) return `Deleting rows${ inTable } `
105+ if ( op === 'read' || op === 'list' || op === 'query' ) return `Reading rows${ ofTable } `
106+ return `Editing rows${ ofTable } `
101107 case 'table_columns' :
102- if ( op === 'add' || op === 'create' ) return `Adding column${ suffix } `
103- if ( op === 'update' ) return `Updating column${ suffix } `
104- if ( op === 'delete' ) return `Deleting column${ suffix } `
105- if ( op === 'read' || op === 'list' ) return ' Reading columns'
106- return ' Editing columns'
108+ if ( op === 'add' || op === 'create' ) return `Adding column${ suffix } ${ inTable } `
109+ if ( op === 'update' ) return `Updating column${ suffix } ${ inTable } `
110+ if ( op === 'delete' ) return `Deleting column${ suffix } ${ inTable } `
111+ if ( op === 'read' || op === 'list' ) return ` Reading columns${ ofTable } `
112+ return ` Editing columns${ ofTable } `
107113 case 'table_automations' :
108- if ( op === 'read' || op === 'list' ) return ' Reading automations'
109- if ( op === 'delete' ) return ' Removing automation'
110- return ' Wiring automation'
114+ if ( op === 'read' || op === 'list' ) return ` Reading automations${ ofTable } `
115+ if ( op === 'delete' ) return ` Removing automation${ inTable } `
116+ return ` Wiring automation${ inTable } `
111117 case 'table_enrichments' :
112- if ( op === 'read' || op === 'list' ) return ' Reading enrichments'
113- if ( op === 'delete' ) return ' Removing enrichment'
114- return ' Configuring enrichment'
118+ if ( op === 'read' || op === 'list' ) return ` Reading enrichments${ ofTable } `
119+ if ( op === 'delete' ) return ` Removing enrichment${ inTable } `
120+ return ` Configuring enrichment${ suffix } ${ inTable } `
115121 case 'table_views' :
116- if ( op === 'create' ) return `Creating view${ suffix } `
117- if ( op === 'delete' ) return `Deleting view${ suffix } `
118- if ( op === 'read' || op === 'list' ) return ' Reading views'
119- return ' Editing views'
122+ if ( op === 'create' ) return `Creating view${ suffix } ${ inTable } `
123+ if ( op === 'delete' ) return `Deleting view${ suffix } ${ inTable } `
124+ if ( op === 'read' || op === 'list' ) return ` Reading views${ ofTable } `
125+ return ` Editing views${ ofTable } `
120126 default :
121- return ' Updating table'
127+ return ` Updating${ table ? ` ${ table } ` : ' table' } `
122128 }
123129}
124130
@@ -165,6 +171,29 @@ function displayUrl(raw: string): string {
165171 }
166172}
167173
174+ /**
175+ * Human name for a block type id: strip the version suffix and title-case the
176+ * snake_case stem (`slack_v2` -> `Slack`, `google_sheets_v2` -> `Google Sheets`).
177+ */
178+ export function blockDisplayName ( blockType : string ) : string {
179+ const stem = stripVersionSuffix ( blockType . trim ( ) )
180+ if ( ! stem ) return blockType
181+ return stem
182+ . split ( '_' )
183+ . filter ( Boolean )
184+ . map ( ( word ) => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) )
185+ . join ( ' ' )
186+ }
187+
188+ /** Ellipsizes the middle so both ends of a value stay recognizable. */
189+ function truncateMiddle ( value : string , maxChars : number ) : string {
190+ const text = value . replace ( / \s + / g, ' ' ) . trim ( )
191+ if ( text . length <= maxChars ) return text
192+ const head = Math . ceil ( ( maxChars - 1 ) / 2 )
193+ const tail = Math . floor ( ( maxChars - 1 ) / 2 )
194+ return `${ text . slice ( 0 , head ) } …${ text . slice ( text . length - tail ) } `
195+ }
196+
168197function isWorkflowArtifactPath ( path : string , filename : string ) : boolean {
169198 const trimmed = path . trim ( )
170199 return trimmed . startsWith ( 'workflows/' ) && trimmed . endsWith ( `/${ filename } ` )
@@ -305,12 +334,12 @@ function queryUserTableTitle(args: ToolArgs): string {
305334}
306335
307336function searchKnowledgeBaseTitle ( args : ToolArgs ) : string {
308- const titles : Record < string , string > = {
309- get : 'Reading knowledge base' ,
310- query : 'Searching knowledge base',
311- list_tags : 'Listing knowledge base tags' ,
312- }
313- return titles [ stringArg ( args , 'operation' ) ] ?? 'Searching knowledge base'
337+ const query = stringArg ( args , 'query' )
338+ const operation = stringArg ( args , 'operation' )
339+ if ( operation === 'get' ) return 'Reading knowledge base'
340+ if ( operation === ' list_tags' ) return 'Listing knowledge base tags'
341+ // A search row is far more useful with the question it asked.
342+ return query ? `Searching knowledge base for ${ query } ` : 'Searching knowledge base'
314343}
315344
316345function manageSandboxTitle ( args : ToolArgs ) : string {
@@ -524,9 +553,7 @@ const TOOL_TITLES: Record<string, string> = {
524553 manage_knowledge_base : 'Managing knowledge base' ,
525554 search_knowledge_base : 'Searching knowledge base' ,
526555 open_resource : 'Opening resource' ,
527- generate_image : 'Generating image' ,
528- generate_video : 'Generating video' ,
529- generate_audio : 'Generating audio' ,
556+
530557 ffmpeg : 'Processing media' ,
531558 get_deployment_status : 'Checking deployment status' ,
532559 create_empty_file : 'Creating file' ,
@@ -538,7 +565,7 @@ const TOOL_TITLES: Record<string, string> = {
538565 publish_custom_block : 'Publishing custom block' ,
539566 deploy_as_mcp : 'Deploying as MCP tool' ,
540567 diff_workflows : 'Comparing workflows' ,
541- download_file : 'Downloading file' ,
568+
542569 run_function : 'Running code' ,
543570 generate_api_key : 'Generating API key' ,
544571 // Retired in favor of the account/ and organization/ VFS namespaces. Kept so
@@ -589,8 +616,7 @@ const TOOL_TITLES: Record<string, string> = {
589616 browser_screenshot : 'Taking screenshot' ,
590617 browser_click : 'Clicking element' ,
591618 browser_click_at : 'Clicking point' ,
592- browser_type : 'Typing text' ,
593- browser_insert_text : 'Inserting text' ,
619+
594620 browser_drag : 'Dragging element' ,
595621 browser_select_option : 'Selecting option' ,
596622 browser_hover : 'Hovering element' ,
@@ -996,6 +1022,40 @@ export function getToolDisplayTitle(name: string, args?: Record<string, unknown>
9961022 const text = stringArg ( args , 'text' )
9971023 return text ? `Waiting for "${ text } "` : 'Waiting for page'
9981024 }
1025+ case 'generate_image' :
1026+ case 'generate_video' :
1027+ case 'generate_audio' : {
1028+ const kind =
1029+ name === 'generate_image' ? 'image' : name === 'generate_video' ? 'video' : 'audio'
1030+ const target =
1031+ firstStringArg ( args , 'toolTitle' , 'title' ) ||
1032+ ( stringArg ( args , 'path' ) ? pathLeaf ( stringArg ( args , 'path' ) ) : '' )
1033+ return target ? `Generating ${ target } ` : `Generating ${ kind } `
1034+ }
1035+ case 'download_file' : {
1036+ const target =
1037+ firstStringArg ( args , 'fileName' , 'toolTitle' , 'title' ) ||
1038+ ( stringArg ( args , 'path' ) ? pathLeaf ( stringArg ( args , 'path' ) ) : '' ) ||
1039+ ( stringArg ( args , 'url' ) ? displayUrl ( stringArg ( args , 'url' ) ) : '' )
1040+ return target ? `Downloading ${ target } ` : 'Downloading file'
1041+ }
1042+ case 'search_library_docs' : {
1043+ const library = firstStringArg ( args , 'library_name' , 'libraryName' , 'library' )
1044+ const query = stringArg ( args , 'query' )
1045+ if ( library && query ) return `Searching ${ library } docs for ${ query } `
1046+ if ( library ) return `Searching ${ library } docs`
1047+ return query ? `Searching library docs for ${ query } ` : 'Searching library docs'
1048+ }
1049+ case 'run_code' : {
1050+ const title = stringArg ( args , 'title' )
1051+ return title || 'Running code'
1052+ }
1053+ case 'browser_type' :
1054+ case 'browser_insert_text' : {
1055+ const verb = name === 'browser_type' ? 'Typing' : 'Inserting'
1056+ const text = stringArg ( args , 'text' )
1057+ return text ? `${ verb } "${ truncateMiddle ( text , 32 ) } "` : `${ verb } text`
1058+ }
9991059 case 'browser_press_key' : {
10001060 const key = stringArg ( args , 'key' )
10011061 return key ? `Pressing ${ key } ` : 'Pressing key'
@@ -1161,6 +1221,12 @@ export function getToolDisplayTitle(name: string, args?: Record<string, unknown>
11611221 }
11621222 // Workflow artifacts name BOTH the workflow and which part, so five
11631223 // reads in a row differentiate instead of all saying the same thing.
1224+ // A block schema read is the model looking up how a block works; name
1225+ // the block, not the file. The row's icon is chosen from the same id.
1226+ const blockSchema = path . match ( / ^ c o m p o n e n t s \/ b l o c k s \/ ( [ ^ / ] + ) \. j s o n $ / )
1227+ if ( blockSchema ) return `Loading ${ blockDisplayName ( decodePathSegment ( blockSchema [ 1 ] ) ) } `
1228+ const blockTips = path . match ( / ^ c o m p o n e n t s \/ b l o c k s \/ ( [ ^ / ] + ) \/ R E A D M E \. m d $ / )
1229+ if ( blockTips ) return `Loading ${ blockDisplayName ( decodePathSegment ( blockTips [ 1 ] ) ) } tips`
11641230 const workflowArtifact = path . match ( / ^ w o r k f l o w s \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) $ / )
11651231 if ( workflowArtifact ) {
11661232 const part =
0 commit comments