Skip to content

Commit e87adf0

Browse files
committed
improvement(mship): clean up deprecated fields from contracts
1 parent 4280949 commit e87adf0

11 files changed

Lines changed: 265 additions & 326 deletions

File tree

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
'use client'
22

33
import { memo, useMemo } from 'react'
4-
import { stripVersionSuffix } from '@sim/utils/string'
54
import { Read as ReadTool, WorkspaceFile } from '@/lib/copilot/generated/tool-catalog-v1'
65
import { isToolHiddenInUi } from '@/lib/copilot/tools/client/hidden-tools'
76
import { resolveToolDisplay } from '@/lib/copilot/tools/client/store-utils'
87
import { ClientToolCallState } from '@/lib/copilot/tools/client/tool-call-state'
8+
import { getToolDisplayTitle, humanizeToolName } from '@/lib/copilot/tools/tool-display'
99
import { useChatSurface } from '@/app/workspace/[workspaceId]/home/components/chat-surface-context'
1010
import type { ContentBlock, OptionItem, ToolCallData } from '../../types'
11-
import { SUBAGENT_LABELS, TOOL_UI_METADATA } from '../../types'
11+
import { SUBAGENT_LABELS } from '../../types'
1212
import type { AgentGroupItem } from './components'
1313
import {
1414
AgentGroup,
@@ -81,16 +81,9 @@ function isHiddenToolCall(toolName: string | undefined): boolean {
8181
return isToolHiddenInUi(toolName)
8282
}
8383

84-
function formatToolName(name: string): string {
85-
return stripVersionSuffix(name)
86-
.split('_')
87-
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
88-
.join(' ')
89-
}
90-
9184
function resolveAgentLabel(key: string): string {
9285
if (key === 'mothership') return 'Sim'
93-
return SUBAGENT_LABELS[key] ?? formatToolName(key)
86+
return SUBAGENT_LABELS[key] ?? humanizeToolName(key)
9487
}
9588

9689
function isToolDone(status: ToolCallData['status']): boolean {
@@ -137,10 +130,7 @@ function getOverrideDisplayTitle(tc: NonNullable<ContentBlock['toolCall']>): str
137130
function toToolData(tc: NonNullable<ContentBlock['toolCall']>): ToolCallData {
138131
const overrideDisplayTitle = getOverrideDisplayTitle(tc)
139132
const displayTitle =
140-
overrideDisplayTitle ||
141-
tc.displayTitle ||
142-
TOOL_UI_METADATA[tc.name as keyof typeof TOOL_UI_METADATA]?.title ||
143-
formatToolName(tc.name)
133+
overrideDisplayTitle || tc.displayTitle || getToolDisplayTitle(tc.name, tc.params)
144134

145135
return {
146136
id: tc.id,

apps/sim/app/workspace/[workspaceId]/home/hooks/stream/handle-tool-event.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,8 @@ export function handleToolEvent(
214214
}
215215
const ui = getToolUI(payload.ui)
216216
if (ui?.hidden) return
217-
let displayTitle = ui?.title
218217
const args = payload.arguments as Record<string, unknown> | undefined
219-
220-
displayTitle = resolveToolDisplayTitle(name, args) ?? displayTitle
218+
const displayTitle = resolveToolDisplayTitle(name, args)
221219

222220
if (name === 'edit_content') {
223221
const parentToolCallId = deps.latestPreviewTargetToolCallIdRef.current

apps/sim/app/workspace/[workspaceId]/home/hooks/stream/stream-helpers.ts

Lines changed: 15 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
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'
3938
import { VFS_DIR_TO_RESOURCE } from '@/lib/copilot/resources/types'
39+
import { getToolDisplayTitle } from '@/lib/copilot/tools/tool-display'
4040
import type { ContentBlock, MothershipResource } from '@/app/workspace/[workspaceId]/home/types'
4141
import { ToolCallStatus } from '@/app/workspace/[workspaceId]/home/types'
4242
import { getWorkflowById } from '@/hooks/queries/utils/workflow-cache'
@@ -66,7 +66,6 @@ export type StreamPayload = Record<string, unknown>
6666

6767
export 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-
204191
function 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

413280
function decodeStreamingString(value: string): string {

apps/sim/app/workspace/[workspaceId]/home/types.ts

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,3 @@
1-
import {
2-
Agent,
3-
Auth,
4-
CreateWorkflow,
5-
Deploy,
6-
EditWorkflow,
7-
Ffmpeg,
8-
FunctionExecute,
9-
GenerateAudio,
10-
GenerateImage,
11-
GenerateVideo,
12-
GetPageContents,
13-
Glob,
14-
Grep,
15-
Knowledge,
16-
KnowledgeBase,
17-
ManageMcpTool,
18-
ManageSkill,
19-
Media,
20-
OpenResource,
21-
Read as ReadTool,
22-
Research,
23-
ScheduledTask,
24-
ScrapePage,
25-
SearchLibraryDocs,
26-
SearchOnline,
27-
Superagent,
28-
Table,
29-
UserMemory,
30-
UserTable,
31-
Workflow,
32-
WorkspaceFile,
33-
} from '@/lib/copilot/generated/tool-catalog-v1'
341
import type { ChatContext } from '@/stores/panel'
352

363
const EDIT_CONTENT_TOOL_ID = 'edit_content'
@@ -199,49 +166,3 @@ export const SUBAGENT_LABELS: Record<string, string> = {
199166
file: 'File Agent',
200167
media: 'Media Agent',
201168
} as const
202-
203-
interface ToolTitleMetadata {
204-
title: string
205-
}
206-
207-
/**
208-
* Fallback titles for tool calls when the stream did not provide one.
209-
*/
210-
export const TOOL_UI_METADATA: Record<string, ToolTitleMetadata> = {
211-
[Glob.id]: { title: 'Finding files' },
212-
[Grep.id]: { title: 'Searching' },
213-
[ReadTool.id]: { title: 'Reading file' },
214-
[SearchOnline.id]: { title: 'Searching online' },
215-
[ScrapePage.id]: { title: 'Scraping page' },
216-
[GetPageContents.id]: { title: 'Getting page contents' },
217-
[SearchLibraryDocs.id]: { title: 'Searching library docs' },
218-
[ManageMcpTool.id]: { title: 'MCP server action' },
219-
[ManageSkill.id]: { title: 'Skill action' },
220-
[UserMemory.id]: { title: 'Accessing memory' },
221-
[FunctionExecute.id]: { title: 'Running code' },
222-
[Superagent.id]: { title: 'Executing action' },
223-
[UserTable.id]: { title: 'Managing table' },
224-
[WorkspaceFile.id]: { title: 'Editing file' },
225-
[EDIT_CONTENT_TOOL_ID]: { title: 'Applying file content' },
226-
[CreateWorkflow.id]: { title: 'Creating workflow' },
227-
[EditWorkflow.id]: { title: 'Editing workflow' },
228-
[Workflow.id]: { title: 'Workflow Agent' },
229-
[RUN_SUBAGENT_ID]: { title: 'Run Agent' },
230-
[Deploy.id]: { title: 'Deploy Agent' },
231-
[Auth.id]: { title: 'Auth Agent' },
232-
[Knowledge.id]: { title: 'Knowledge Agent' },
233-
[KnowledgeBase.id]: { title: 'Managing knowledge base' },
234-
[Table.id]: { title: 'Table Agent' },
235-
[ScheduledTask.id]: { title: 'Scheduled Task Agent' },
236-
job: { title: 'Job Agent' },
237-
[Agent.id]: { title: 'Tools Agent' },
238-
custom_tool: { title: 'Creating tool' },
239-
[Research.id]: { title: 'Research Agent' },
240-
[OpenResource.id]: { title: 'Opening resource' },
241-
[Media.id]: { title: 'Media Agent' },
242-
[GenerateImage.id]: { title: 'Generating image' },
243-
[GenerateVideo.id]: { title: 'Generating video' },
244-
[GenerateAudio.id]: { title: 'Generating audio' },
245-
[Ffmpeg.id]: { title: 'Processing media' },
246-
context_compaction: { title: 'Compacted context' },
247-
}

0 commit comments

Comments
 (0)