Skip to content

Commit 42b9d5f

Browse files
authored
improvement(workflows): stop writing placeholder workflow descriptions (#5729)
* improvement(workflows): stop writing placeholder workflow descriptions * fix(workflows): scrub placeholder descriptions at the import boundary * test(workflows): pin import-boundary description scrubbing behavior
1 parent f6bb8e6 commit 42b9d5f

5 files changed

Lines changed: 79 additions & 13 deletions

File tree

apps/sim/app/workspace/[workspaceId]/home/home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export function Home({ chatId, userName, userId }: HomeProps) {
144144
filename: `${seed.workflowName}.json`,
145145
workspaceId,
146146
nameOverride: seed.workflowName,
147-
descriptionOverride: seed.workflowDescription || 'Imported from landing template',
147+
descriptionOverride: seed.workflowDescription || undefined,
148148
createWorkflow: async ({ name, description, workspaceId }) => {
149149
return requestJson(createWorkflowContract, {
150150
body: {

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/general/components/api-info-modal.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '@sim/emcn'
1818
import { getErrorMessage } from '@sim/utils/errors'
1919
import { useParams } from 'next/navigation'
20+
import { getMeaningfulWorkflowDescription } from '@/lib/mcp/workflow-tool-schema'
2021
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
2122
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
2223
import type { InputFormatField } from '@/lib/workflows/types'
@@ -89,14 +90,9 @@ export function ApiInfoModal({ open, onOpenChange, workflowId }: ApiInfoModalPro
8990

9091
useEffect(() => {
9192
if (open) {
92-
const normalizedDesc = workflowMetadata?.description?.toLowerCase().trim()
93-
const isDefaultDescription =
94-
!workflowMetadata?.description ||
95-
workflowMetadata.description === workflowMetadata.name ||
96-
normalizedDesc === 'new workflow' ||
97-
normalizedDesc === 'your first workflow - start building here!'
98-
99-
const initialDescription = isDefaultDescription ? '' : workflowMetadata?.description || ''
93+
const initialDescription =
94+
getMeaningfulWorkflowDescription(workflowMetadata?.description, workflowMetadata?.name) ??
95+
''
10096
setDescription(initialDescription)
10197
initialDescriptionRef.current = initialDescription
10298

@@ -181,7 +177,7 @@ export function ApiInfoModal({ open, onOpenChange, workflowId }: ApiInfoModalPro
181177
await updateWorkflowMutation.mutateAsync({
182178
workspaceId,
183179
workflowId,
184-
metadata: { description: description.trim() || 'New workflow' },
180+
metadata: { description: description.trim() },
185181
})
186182
}
187183

apps/sim/hooks/queries/workflows.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export function useCreateWorkflow() {
175175
body: {
176176
id,
177177
name: name || generateCreativeWorkflowName(),
178-
description: description || 'New workflow',
178+
description,
179179
workspaceId,
180180
folderId: folderId || null,
181181
sortOrder,
@@ -226,7 +226,7 @@ export function useCreateWorkflow() {
226226
name: variables.name || generateCreativeWorkflowName(),
227227
lastModified: new Date(),
228228
createdAt: new Date(),
229-
description: variables.description || 'New workflow',
229+
description: variables.description ?? '',
230230
workspaceId: variables.workspaceId,
231231
folderId: variables.folderId || null,
232232
sortOrder,

apps/sim/lib/workflows/operations/import-export.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ import { describe, expect, it, vi } from 'vitest'
22

33
vi.unmock('@/blocks/registry')
44

5+
vi.mock('@/lib/api/client/request', () => ({
6+
requestJson: vi.fn().mockResolvedValue({}),
7+
}))
8+
59
import {
610
extractWorkflowName,
711
parseWorkflowJson,
12+
persistImportedWorkflow,
813
sanitizePathSegment,
914
} from '@/lib/workflows/operations/import-export'
1015

@@ -134,6 +139,67 @@ describe('workflow import/export parsing', () => {
134139
})
135140
})
136141

142+
describe('persistImportedWorkflow description handling', () => {
143+
function buildContent(description?: string) {
144+
const state = createLegacyState()
145+
return JSON.stringify({
146+
data: {
147+
version: '1.0',
148+
workflow: { name: 'Imported Workflow' },
149+
state: {
150+
...state,
151+
metadata: { name: 'Imported Workflow', description },
152+
},
153+
},
154+
})
155+
}
156+
157+
async function importWithContent(content: string, descriptionOverride?: string) {
158+
const createWorkflow = vi.fn().mockResolvedValue({ id: 'wf-1' })
159+
await persistImportedWorkflow({
160+
content,
161+
filename: 'imported-workflow.json',
162+
workspaceId: 'ws-1',
163+
descriptionOverride,
164+
createWorkflow,
165+
})
166+
return createWorkflow.mock.calls[0][0].description as string
167+
}
168+
169+
it('scrubs placeholder metadata descriptions to an empty string', async () => {
170+
expect(await importWithContent(buildContent('New workflow'))).toBe('')
171+
expect(
172+
await importWithContent(buildContent('Your first workflow - start building here!'))
173+
).toBe('')
174+
})
175+
176+
it('scrubs name-equal metadata descriptions to an empty string', async () => {
177+
expect(await importWithContent(buildContent('Imported Workflow'))).toBe('')
178+
})
179+
180+
it('preserves meaningful metadata descriptions', async () => {
181+
expect(await importWithContent(buildContent('Syncs leads from HubSpot to Slack'))).toBe(
182+
'Syncs leads from HubSpot to Slack'
183+
)
184+
})
185+
186+
it('uses an empty string when no description is present', async () => {
187+
expect(await importWithContent(buildContent(undefined))).toBe('')
188+
})
189+
190+
it('prefers a meaningful override over metadata', async () => {
191+
expect(
192+
await importWithContent(buildContent('Metadata description'), 'Override description')
193+
).toBe('Override description')
194+
})
195+
196+
it('falls back to meaningful metadata when the override is a placeholder', async () => {
197+
expect(await importWithContent(buildContent('Metadata description'), 'New workflow')).toBe(
198+
'Metadata description'
199+
)
200+
})
201+
})
202+
137203
describe('sanitizePathSegment', () => {
138204
it('should preserve ASCII alphanumeric characters', () => {
139205
expect(sanitizePathSegment('workflow-123_abc')).toBe('workflow-123_abc')

apps/sim/lib/workflows/operations/import-export.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
type WorkflowStateContractInput,
1212
workflowVariablesContract,
1313
} from '@/lib/api/contracts/workflows'
14+
import { getMeaningfulWorkflowDescription } from '@/lib/mcp/workflow-tool-schema'
1415
import { migrateSubblockIds } from '@/lib/workflows/migrations/subblock-migrations'
1516
import {
1617
type ExportWorkflowState,
@@ -677,7 +678,10 @@ export async function persistImportedWorkflow({
677678

678679
const createdWorkflow = await createWorkflow({
679680
name: workflowName,
680-
description: descriptionOverride || workflowData.metadata?.description || 'Imported from JSON',
681+
description:
682+
getMeaningfulWorkflowDescription(descriptionOverride, workflowName) ??
683+
getMeaningfulWorkflowDescription(workflowData.metadata?.description, workflowName) ??
684+
'',
681685
workspaceId,
682686
folderId,
683687
sortOrder,

0 commit comments

Comments
 (0)