@@ -2,27 +2,25 @@ import { createLogger } from '@sim/logger'
22import { isRecordLike } from '@sim/utils/object'
33import {
44 CrawlWebsite ,
5- CreateFolder ,
6- DeleteFolder ,
75 DeleteWorkflow ,
86 DeployApi ,
97 DeployChat ,
108 DeployMcp ,
119 FunctionExecute ,
12- GetPageContents ,
1310 Glob ,
1411 Grep ,
1512 ManageCredential ,
1613 ManageCredentialOperation ,
1714 ManageCustomTool ,
1815 ManageCustomToolOperation ,
16+ ManageFolder ,
17+ ManageFolderOperation ,
1918 ManageMcpTool ,
2019 ManageMcpToolOperation ,
2120 ManageScheduledTask ,
2221 ManageScheduledTaskOperation ,
2322 ManageSkill ,
2423 ManageSkillOperation ,
25- MoveFolder ,
2624 MoveWorkflow ,
2725 QueryLogs ,
2826 Redeploy ,
@@ -36,6 +34,7 @@ import {
3634 WorkspaceFileOperation ,
3735} from '@/lib/copilot/generated/tool-catalog-v1'
3836import { VFS_DIR_TO_RESOURCE } from '@/lib/copilot/resources/types'
37+ import { getToolDisplayTitle } from '@/lib/copilot/tools/tool-display'
3938import type { ContentBlock , MothershipResource } from '@/app/workspace/[workspaceId]/home/types'
4039import { ToolCallStatus } from '@/app/workspace/[workspaceId]/home/types'
4140import { getWorkflowById } from '@/hooks/queries/utils/workflow-cache'
@@ -53,11 +52,7 @@ export const DEPLOY_TOOL_NAMES: Set<string> = new Set([
5352 Redeploy . id ,
5453] )
5554
56- export const FOLDER_TOOL_NAMES : Set < string > = new Set ( [
57- CreateFolder . id ,
58- DeleteFolder . id ,
59- MoveFolder . id ,
60- ] )
55+ export const FOLDER_TOOL_NAMES : Set < string > = new Set ( [ ManageFolder . id ] )
6156
6257export const WORKFLOW_MUTATION_TOOL_NAMES : Set < string > = new Set ( [
6358 MoveWorkflow . id ,
@@ -160,11 +155,6 @@ function stringParam(value: unknown): string | undefined {
160155 return typeof value === 'string' && value . trim ( ) ? value . trim ( ) : undefined
161156}
162157
163- function stringArrayParam ( value : unknown ) : string [ ] {
164- if ( ! Array . isArray ( value ) ) return [ ]
165- return value . filter ( ( item ) : item is string => typeof item === 'string' && item . trim ( ) . length > 0 )
166- }
167-
168158function resolveWorkflowNameForDisplay ( workflowId : unknown ) : string | undefined {
169159 const id = stringParam ( workflowId )
170160 if ( ! id ) return undefined
@@ -218,134 +208,27 @@ function functionExecuteTitle(title: string | undefined): string {
218208 return title ?? 'Running code'
219209}
220210
221- export function resolveToolDisplayTitle (
222- name : string ,
223- args ?: Record < string , unknown >
224- ) : string | undefined {
225- if ( ! args ) return undefined
226-
227- if ( name === FunctionExecute . id ) {
228- return functionExecuteTitle ( stringParam ( args . title ) )
229- }
230-
231- if ( name === WorkspaceFile . id ) {
232- const target = asPayloadRecord ( args . target )
233- return resolveWorkspaceFileDisplayTitle ( args . operation , args . title , target ?. fileName )
234- }
235-
236- if ( name === SearchOnline . id ) {
237- const toolTitle = stringParam ( args . toolTitle )
238- return toolTitle ? `Searching online for ${ toolTitle } ` : 'Searching online'
239- }
240-
241- if ( name === Grep . id ) {
242- const toolTitle = stringParam ( args . toolTitle )
243- return toolTitle ? `Searching for ${ toolTitle } ` : 'Searching'
244- }
245-
246- if ( name === Glob . id ) {
247- const toolTitle = stringParam ( args . toolTitle )
248- return toolTitle ? `Finding ${ toolTitle } ` : 'Finding files'
249- }
250-
251- if ( name === ScrapePage . id ) {
252- const url = stringParam ( args . url )
253- return url ? `Scraping ${ url } ` : 'Scraping page'
254- }
255-
256- if ( name === CrawlWebsite . id ) {
257- const url = stringParam ( args . url )
258- return url ? `Crawling ${ url } ` : 'Crawling website'
259- }
260-
261- if ( name === GetPageContents . id ) {
262- const urls = stringArrayParam ( args . urls )
263- if ( urls . length === 1 ) return `Getting ${ urls [ 0 ] } `
264- if ( urls . length > 1 ) return `Getting ${ urls . length } pages`
265- return 'Getting page contents'
266- }
267-
268- if ( name === ManageCustomTool . id ) {
269- return resolveOperationDisplayTitle (
270- args . operation ,
271- {
272- [ ManageCustomToolOperation . add ] : 'Creating custom tool' ,
273- [ ManageCustomToolOperation . edit ] : 'Updating custom tool' ,
274- [ ManageCustomToolOperation . delete ] : 'Deleting custom tool' ,
275- [ ManageCustomToolOperation . list ] : 'Listing custom tools' ,
276- } ,
277- 'Custom tool action'
278- )
279- }
280-
281- if ( name === ManageMcpTool . id ) {
282- return resolveOperationDisplayTitle (
283- args . operation ,
284- {
285- [ ManageMcpToolOperation . add ] : 'Creating MCP server' ,
286- [ ManageMcpToolOperation . edit ] : 'Updating MCP server' ,
287- [ ManageMcpToolOperation . delete ] : 'Deleting MCP server' ,
288- [ ManageMcpToolOperation . list ] : 'Listing MCP servers' ,
289- } ,
290- 'MCP server action'
291- )
292- }
293-
294- if ( name === ManageSkill . id ) {
295- return resolveOperationDisplayTitle (
296- args . operation ,
297- {
298- [ ManageSkillOperation . add ] : 'Creating skill' ,
299- [ ManageSkillOperation . edit ] : 'Updating skill' ,
300- [ ManageSkillOperation . delete ] : 'Deleting skill' ,
301- [ ManageSkillOperation . list ] : 'Listing skills' ,
302- } ,
303- 'Skill action'
304- )
305- }
306-
307- if ( name === ManageScheduledTask . id ) {
308- return resolveOperationDisplayTitle (
309- args . operation ,
310- {
311- [ ManageScheduledTaskOperation . create ] : 'Creating scheduled task' ,
312- [ ManageScheduledTaskOperation . get ] : 'Getting scheduled task' ,
313- [ ManageScheduledTaskOperation . update ] : 'Updating scheduled task' ,
314- [ ManageScheduledTaskOperation . delete ] : 'Deleting scheduled task' ,
315- [ ManageScheduledTaskOperation . list ] : 'Listing scheduled tasks' ,
316- } ,
317- 'Scheduled task action'
318- )
319- }
320-
321- if ( name === ManageCredential . id ) {
322- return resolveOperationDisplayTitle (
323- args . operation ,
324- {
325- [ ManageCredentialOperation . rename ] : 'Renaming credential' ,
326- [ ManageCredentialOperation . delete ] : 'Deleting credential' ,
327- } ,
328- 'Credential action'
329- )
330- }
331-
211+ export function resolveToolDisplayTitle ( name : string , args ?: Record < string , unknown > ) : string {
212+ // Cases that enrich the title with live workspace/block names from the client
213+ // stores. Everything else is resolved by the shared name+args resolver, which
214+ // is the single source of truth for tool-call titles.
332215 if ( name === RunWorkflow . id ) {
333- const workflowName = resolveWorkflowNameForDisplay ( args . workflowId )
216+ const workflowName = resolveWorkflowNameForDisplay ( args ? .workflowId )
334217 return workflowName ? `Running ${ workflowName } ` : 'Running workflow'
335218 }
336219
337220 if ( name === RunFromBlock . id ) {
338- const workflowName = resolveWorkflowNameForDisplay ( args . workflowId )
339- const blockName = resolveBlockNameForDisplay ( args . startBlockId )
221+ const workflowName = resolveWorkflowNameForDisplay ( args ? .workflowId )
222+ const blockName = resolveBlockNameForDisplay ( args ? .startBlockId )
340223 if ( workflowName && blockName ) return `Running ${ workflowName } from ${ blockName } `
341224 if ( workflowName ) return `Running ${ workflowName } `
342225 if ( blockName ) return `Running from ${ blockName } `
343226 return 'Running workflow'
344227 }
345228
346229 if ( name === RunWorkflowUntilBlock . id ) {
347- const workflowName = resolveWorkflowNameForDisplay ( args . workflowId )
348- const blockName = resolveBlockNameForDisplay ( args . stopAfterBlockId )
230+ const workflowName = resolveWorkflowNameForDisplay ( args ? .workflowId )
231+ const blockName = resolveBlockNameForDisplay ( args ? .stopAfterBlockId )
349232 if ( workflowName && blockName ) return `Running ${ workflowName } until ${ blockName } `
350233 if ( workflowName ) return `Running ${ workflowName } `
351234 if ( blockName ) return `Running until ${ blockName } `
@@ -354,11 +237,11 @@ export function resolveToolDisplayTitle(
354237
355238 if ( name === QueryLogs . id ) {
356239 const workflowName =
357- resolveWorkflowNameForDisplay ( args . workflowId ) ?? stringParam ( args . workflowName )
358- return workflowName ? `Querying logs for ${ workflowName } ` : undefined
240+ resolveWorkflowNameForDisplay ( args ? .workflowId ) ?? stringParam ( args ? .workflowName )
241+ if ( workflowName ) return `Querying logs for ${ workflowName } `
359242 }
360243
361- return undefined
244+ return getToolDisplayTitle ( name , args )
362245}
363246
364247function decodeStreamingString ( value : string ) : string {
@@ -480,5 +363,18 @@ export function resolveStreamingToolDisplayTitle(
480363 )
481364 }
482365
366+ if ( name === ManageFolder . id ) {
367+ return resolveOperationDisplayTitle (
368+ matchStreamingStringArg ( streamingArgs , 'operation' ) ,
369+ {
370+ [ ManageFolderOperation . create ] : 'Creating folder' ,
371+ [ ManageFolderOperation . rename ] : 'Renaming folder' ,
372+ [ ManageFolderOperation . move ] : 'Moving folder' ,
373+ [ ManageFolderOperation . delete ] : 'Deleting folder' ,
374+ } ,
375+ 'Folder action'
376+ )
377+ }
378+
483379 return undefined
484380}
0 commit comments