99 DeployChat ,
1010 DeployMcp ,
1111 FunctionExecute ,
12- GetPageContents ,
1312 Glob ,
1413 Grep ,
1514 ManageCredential ,
@@ -37,6 +36,7 @@ import {
3736 WorkspaceFileOperation ,
3837} from '@/lib/copilot/generated/tool-catalog-v1'
3938import { VFS_DIR_TO_RESOURCE } from '@/lib/copilot/resources/types'
39+ import { getToolDisplayTitle } from '@/lib/copilot/tools/tool-display'
4040import type { ContentBlock , MothershipResource } from '@/app/workspace/[workspaceId]/home/types'
4141import { ToolCallStatus } from '@/app/workspace/[workspaceId]/home/types'
4242import { getWorkflowById } from '@/hooks/queries/utils/workflow-cache'
@@ -66,7 +66,6 @@ export type StreamPayload = Record<string, unknown>
6666
6767export type StreamToolUI = {
6868 hidden ?: boolean
69- title ?: string
7069 clientExecutable ?: boolean
7170}
7271
@@ -85,17 +84,10 @@ export function getToolUI(ui?: MothershipStreamV1ToolUI): StreamToolUI | undefin
8584 if ( ! ui ) {
8685 return undefined
8786 }
88-
89- const title =
90- typeof ui . title === 'string'
91- ? ui . title
92- : typeof ui . phaseLabel === 'string'
93- ? ui . phaseLabel
94- : undefined
95-
87+ // The stream carries only behavioral flags now; display (title/icon) is
88+ // derived client-side from the tool name via getToolDisplayTitle/getToolIcon.
9689 return {
9790 ...( typeof ui . hidden === 'boolean' ? { hidden : ui . hidden } : { } ) ,
98- ...( title ? { title } : { } ) ,
9991 ...( typeof ui . clientExecutable === 'boolean' ? { clientExecutable : ui . clientExecutable } : { } ) ,
10092 }
10193}
@@ -196,11 +188,6 @@ function stringParam(value: unknown): string | undefined {
196188 return typeof value === 'string' && value . trim ( ) ? value . trim ( ) : undefined
197189}
198190
199- function stringArrayParam ( value : unknown ) : string [ ] {
200- if ( ! Array . isArray ( value ) ) return [ ]
201- return value . filter ( ( item ) : item is string => typeof item === 'string' && item . trim ( ) . length > 0 )
202- }
203-
204191function resolveWorkflowNameForDisplay ( workflowId : unknown ) : string | undefined {
205192 const id = stringParam ( workflowId )
206193 if ( ! id ) return undefined
@@ -254,147 +241,27 @@ function functionExecuteTitle(title: string | undefined): string {
254241 return title ?? 'Running code'
255242}
256243
257- export function resolveToolDisplayTitle (
258- name : string ,
259- args ?: Record < string , unknown >
260- ) : string | undefined {
261- if ( ! args ) return undefined
262-
263- if ( name === FunctionExecute . id ) {
264- return functionExecuteTitle ( stringParam ( args . title ) )
265- }
266-
267- if ( name === WorkspaceFile . id ) {
268- const target = asPayloadRecord ( args . target )
269- return resolveWorkspaceFileDisplayTitle ( args . operation , args . title , target ?. fileName )
270- }
271-
272- if ( name === SearchOnline . id ) {
273- const toolTitle = stringParam ( args . toolTitle )
274- return toolTitle ? `Searching online for ${ toolTitle } ` : 'Searching online'
275- }
276-
277- if ( name === Grep . id ) {
278- const toolTitle = stringParam ( args . toolTitle )
279- return toolTitle ? `Searching for ${ toolTitle } ` : 'Searching'
280- }
281-
282- if ( name === Glob . id ) {
283- const toolTitle = stringParam ( args . toolTitle )
284- return toolTitle ? `Finding ${ toolTitle } ` : 'Finding files'
285- }
286-
287- if ( name === ScrapePage . id ) {
288- const url = stringParam ( args . url )
289- return url ? `Scraping ${ url } ` : 'Scraping page'
290- }
291-
292- if ( name === CrawlWebsite . id ) {
293- const url = stringParam ( args . url )
294- return url ? `Crawling ${ url } ` : 'Crawling website'
295- }
296-
297- if ( name === GetPageContents . id ) {
298- const urls = stringArrayParam ( args . urls )
299- if ( urls . length === 1 ) return `Getting ${ urls [ 0 ] } `
300- if ( urls . length > 1 ) return `Getting ${ urls . length } pages`
301- return 'Getting page contents'
302- }
303-
304- if ( name === ManageCustomTool . id ) {
305- return resolveOperationDisplayTitle (
306- args . operation ,
307- {
308- [ ManageCustomToolOperation . add ] : 'Creating custom tool' ,
309- [ ManageCustomToolOperation . edit ] : 'Updating custom tool' ,
310- [ ManageCustomToolOperation . delete ] : 'Deleting custom tool' ,
311- [ ManageCustomToolOperation . list ] : 'Listing custom tools' ,
312- } ,
313- 'Custom tool action'
314- )
315- }
316-
317- if ( name === ManageMcpTool . id ) {
318- return resolveOperationDisplayTitle (
319- args . operation ,
320- {
321- [ ManageMcpToolOperation . add ] : 'Creating MCP server' ,
322- [ ManageMcpToolOperation . edit ] : 'Updating MCP server' ,
323- [ ManageMcpToolOperation . delete ] : 'Deleting MCP server' ,
324- [ ManageMcpToolOperation . list ] : 'Listing MCP servers' ,
325- } ,
326- 'MCP server action'
327- )
328- }
329-
330- if ( name === ManageSkill . id ) {
331- return resolveOperationDisplayTitle (
332- args . operation ,
333- {
334- [ ManageSkillOperation . add ] : 'Creating skill' ,
335- [ ManageSkillOperation . edit ] : 'Updating skill' ,
336- [ ManageSkillOperation . delete ] : 'Deleting skill' ,
337- [ ManageSkillOperation . list ] : 'Listing skills' ,
338- } ,
339- 'Skill action'
340- )
341- }
342-
343- if ( name === ManageScheduledTask . id ) {
344- return resolveOperationDisplayTitle (
345- args . operation ,
346- {
347- [ ManageScheduledTaskOperation . create ] : 'Creating scheduled task' ,
348- [ ManageScheduledTaskOperation . get ] : 'Getting scheduled task' ,
349- [ ManageScheduledTaskOperation . update ] : 'Updating scheduled task' ,
350- [ ManageScheduledTaskOperation . delete ] : 'Deleting scheduled task' ,
351- [ ManageScheduledTaskOperation . list ] : 'Listing scheduled tasks' ,
352- } ,
353- 'Scheduled task action'
354- )
355- }
356-
357- if ( name === ManageCredential . id ) {
358- return resolveOperationDisplayTitle (
359- args . operation ,
360- {
361- [ ManageCredentialOperation . rename ] : 'Renaming credential' ,
362- [ ManageCredentialOperation . delete ] : 'Deleting credential' ,
363- } ,
364- 'Credential action'
365- )
366- }
367-
368- if ( name === ManageFolder . id ) {
369- return resolveOperationDisplayTitle (
370- args . operation ,
371- {
372- [ ManageFolderOperation . create ] : 'Creating folder' ,
373- [ ManageFolderOperation . rename ] : 'Renaming folder' ,
374- [ ManageFolderOperation . move ] : 'Moving folder' ,
375- [ ManageFolderOperation . delete ] : 'Deleting folder' ,
376- } ,
377- 'Folder action'
378- )
379- }
380-
244+ export function resolveToolDisplayTitle ( name : string , args ?: Record < string , unknown > ) : string {
245+ // Cases that enrich the title with live workspace/block names from the client
246+ // stores. Everything else is resolved by the shared name+args resolver, which
247+ // is the single source of truth for tool-call titles.
381248 if ( name === RunWorkflow . id ) {
382- const workflowName = resolveWorkflowNameForDisplay ( args . workflowId )
249+ const workflowName = resolveWorkflowNameForDisplay ( args ? .workflowId )
383250 return workflowName ? `Running ${ workflowName } ` : 'Running workflow'
384251 }
385252
386253 if ( name === RunFromBlock . id ) {
387- const workflowName = resolveWorkflowNameForDisplay ( args . workflowId )
388- const blockName = resolveBlockNameForDisplay ( args . startBlockId )
254+ const workflowName = resolveWorkflowNameForDisplay ( args ? .workflowId )
255+ const blockName = resolveBlockNameForDisplay ( args ? .startBlockId )
389256 if ( workflowName && blockName ) return `Running ${ workflowName } from ${ blockName } `
390257 if ( workflowName ) return `Running ${ workflowName } `
391258 if ( blockName ) return `Running from ${ blockName } `
392259 return 'Running workflow'
393260 }
394261
395262 if ( name === RunWorkflowUntilBlock . id ) {
396- const workflowName = resolveWorkflowNameForDisplay ( args . workflowId )
397- const blockName = resolveBlockNameForDisplay ( args . stopAfterBlockId )
263+ const workflowName = resolveWorkflowNameForDisplay ( args ? .workflowId )
264+ const blockName = resolveBlockNameForDisplay ( args ? .stopAfterBlockId )
398265 if ( workflowName && blockName ) return `Running ${ workflowName } until ${ blockName } `
399266 if ( workflowName ) return `Running ${ workflowName } `
400267 if ( blockName ) return `Running until ${ blockName } `
@@ -403,11 +270,11 @@ export function resolveToolDisplayTitle(
403270
404271 if ( name === QueryLogs . id ) {
405272 const workflowName =
406- resolveWorkflowNameForDisplay ( args . workflowId ) ?? stringParam ( args . workflowName )
407- return workflowName ? `Querying logs for ${ workflowName } ` : undefined
273+ resolveWorkflowNameForDisplay ( args ? .workflowId ) ?? stringParam ( args ? .workflowName )
274+ if ( workflowName ) return `Querying logs for ${ workflowName } `
408275 }
409276
410- return undefined
277+ return getToolDisplayTitle ( name , args )
411278}
412279
413280function decodeStreamingString ( value : string ) : string {
0 commit comments