From 8cae8948ed98027595eb5d2615278f2a430545fd Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Tue, 14 Apr 2026 12:47:00 -0700 Subject: [PATCH] Fix nested folder display names --- .../[workspaceId]/home/hooks/use-chat.ts | 21 +++++++++++++++++-- .../copilot/tools/client/store-utils.test.ts | 6 ++++++ .../lib/copilot/tools/client/store-utils.ts | 16 ++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts index 2318b00249..dea4eaacc1 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts @@ -673,7 +673,10 @@ function extractResourceFromReadResult( ): MothershipResource | null { if (!path) return null - const segments = path.split('/') + const segments = path + .split('/') + .map((segment) => segment.trim()) + .filter(Boolean) const resourceType = VFS_DIR_TO_RESOURCE[segments[0]] if (!resourceType || !segments[1]) return null @@ -693,8 +696,22 @@ function extractResourceFromReadResult( } } + const fallbackTitle = + resourceType === 'workflow' + ? resolveLeafWorkflowPathSegment(segments) + : segments[1] || segments[segments.length - 1] + if (!id) return null - return { type: resourceType, id, title: name || segments[1] } + return { type: resourceType, id, title: name || fallbackTitle || id } +} + +function resolveLeafWorkflowPathSegment(segments: string[]): string | undefined { + const lastSegment = segments[segments.length - 1] + if (!lastSegment) return undefined + if (/\.[^/.]+$/.test(lastSegment) && segments.length > 1) { + return segments[segments.length - 2] + } + return lastSegment } export interface UseChatOptions { diff --git a/apps/sim/lib/copilot/tools/client/store-utils.test.ts b/apps/sim/lib/copilot/tools/client/store-utils.test.ts index c15bce9015..3c3bba5151 100644 --- a/apps/sim/lib/copilot/tools/client/store-utils.test.ts +++ b/apps/sim/lib/copilot/tools/client/store-utils.test.ts @@ -29,6 +29,12 @@ describe('resolveToolDisplay', () => { path: 'workflows/My Workflow/meta.json', })?.text ).toBe('Read My Workflow') + + expect( + resolveToolDisplay(ReadTool.id, ClientToolCallState.success, { + path: 'workflows/Folder 1/RET XYZ/state.json', + })?.text + ).toBe('Read RET XYZ') }) it('falls back to a humanized tool label for generic tools', () => { diff --git a/apps/sim/lib/copilot/tools/client/store-utils.ts b/apps/sim/lib/copilot/tools/client/store-utils.ts index 69de9f28bf..e1c04abb17 100644 --- a/apps/sim/lib/copilot/tools/client/store-utils.ts +++ b/apps/sim/lib/copilot/tools/client/store-utils.ts @@ -98,10 +98,26 @@ function describeReadTarget(path: string | undefined): string | undefined { return segments.slice(1).join('/') || segments[segments.length - 1] } + if (resourceType === 'workflow') { + return stripExtension(getLeafResourceSegment(segments)) + } + const resourceName = segments[1] || segments[segments.length - 1] return stripExtension(resourceName) } +function getLeafResourceSegment(segments: string[]): string { + const lastSegment = segments[segments.length - 1] || '' + if (hasFileExtension(lastSegment) && segments.length > 1) { + return segments[segments.length - 2] || lastSegment + } + return lastSegment +} + +function hasFileExtension(value: string): boolean { + return /\.[^/.]+$/.test(value) +} + function stripExtension(value: string): string { return value.replace(/\.[^/.]+$/, '') }