Skip to content

Commit 6300d3e

Browse files
committed
Normalize copilot subblock ids
1 parent 84fb75b commit 6300d3e

File tree

1 file changed

+58
-16
lines changed

1 file changed

+58
-16
lines changed

apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -627,12 +627,9 @@ function createBlockFromParams(
627627

628628
let sanitizedValue = value
629629

630-
// Special handling for inputFormat - ensure it's an array
631-
if (key === 'inputFormat' && value !== null && value !== undefined) {
632-
if (!Array.isArray(value)) {
633-
// Invalid format, default to empty array
634-
sanitizedValue = []
635-
}
630+
// Normalize array subblocks with id fields (inputFormat, table rows, etc.)
631+
if (shouldNormalizeArrayIds(key)) {
632+
sanitizedValue = normalizeArrayWithIds(value)
636633
}
637634

638635
// Special handling for tools - normalize and filter disallowed
@@ -720,6 +717,55 @@ function normalizeTools(tools: any[]): any[] {
720717
})
721718
}
722719

720+
/** UUID v4 regex pattern for validation */
721+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
722+
723+
/**
724+
* Subblock types that store arrays of objects with `id` fields.
725+
* The LLM may generate arbitrary IDs which need to be converted to proper UUIDs.
726+
*/
727+
const ARRAY_WITH_ID_SUBBLOCK_TYPES = new Set([
728+
'inputFormat', // input-format: Fields with id, name, type, value, collapsed
729+
'headers', // table: Rows with id, cells (used for HTTP headers)
730+
'params', // table: Rows with id, cells (used for query params)
731+
'variables', // table or variables-input: Rows/assignments with id
732+
'tagFilters', // knowledge-tag-filters: Filters with id, tagName, etc.
733+
'documentTags', // document-tag-entry: Tags with id, tagName, etc.
734+
'metrics', // eval-input: Metrics with id, name, description, range
735+
])
736+
737+
/**
738+
* Normalizes array subblock values by ensuring each item has a valid UUID.
739+
* The LLM may generate arbitrary IDs like "input-desc-001" or "row-1" which need
740+
* to be converted to proper UUIDs for consistency with UI-created items.
741+
*/
742+
function normalizeArrayWithIds(value: unknown): any[] {
743+
if (!Array.isArray(value)) {
744+
return []
745+
}
746+
747+
return value.map((item: any) => {
748+
if (!item || typeof item !== 'object') {
749+
return item
750+
}
751+
752+
// Check if id is missing or not a valid UUID
753+
const hasValidUUID = typeof item.id === 'string' && UUID_REGEX.test(item.id)
754+
if (!hasValidUUID) {
755+
return { ...item, id: crypto.randomUUID() }
756+
}
757+
758+
return item
759+
})
760+
}
761+
762+
/**
763+
* Checks if a subblock key should have its array items normalized with UUIDs.
764+
*/
765+
function shouldNormalizeArrayIds(key: string): boolean {
766+
return ARRAY_WITH_ID_SUBBLOCK_TYPES.has(key)
767+
}
768+
723769
/**
724770
* Normalize responseFormat to ensure consistent storage
725771
* Handles both string (JSON) and object formats
@@ -1360,12 +1406,9 @@ function applyOperationsToWorkflowState(
13601406
}
13611407
let sanitizedValue = value
13621408

1363-
// Special handling for inputFormat - ensure it's an array
1364-
if (key === 'inputFormat' && value !== null && value !== undefined) {
1365-
if (!Array.isArray(value)) {
1366-
// Invalid format, default to empty array
1367-
sanitizedValue = []
1368-
}
1409+
// Normalize array subblocks with id fields (inputFormat, table rows, etc.)
1410+
if (shouldNormalizeArrayIds(key)) {
1411+
sanitizedValue = normalizeArrayWithIds(value)
13691412
}
13701413

13711414
// Special handling for tools - normalize and filter disallowed
@@ -2011,10 +2054,9 @@ function applyOperationsToWorkflowState(
20112054

20122055
let sanitizedValue = value
20132056

2014-
if (key === 'inputFormat' && value !== null && value !== undefined) {
2015-
if (!Array.isArray(value)) {
2016-
sanitizedValue = []
2017-
}
2057+
// Normalize array subblocks with id fields (inputFormat, table rows, etc.)
2058+
if (shouldNormalizeArrayIds(key)) {
2059+
sanitizedValue = normalizeArrayWithIds(value)
20182060
}
20192061

20202062
// Special handling for tools - normalize and filter disallowed

0 commit comments

Comments
 (0)