* Sanitize subblocks by removing null values and simplifying structure * Maps each subblock key directly to its value instead of the full object
( subBlocks: BlockState['subBlocks'] )
| 256 | * Maps each subblock key directly to its value instead of the full object |
| 257 | */ |
| 258 | function sanitizeSubBlocks( |
| 259 | subBlocks: BlockState['subBlocks'] |
| 260 | ): Record<string, string | number | string[][] | object> { |
| 261 | const sanitized: Record<string, string | number | string[][] | object> = {} |
| 262 | |
| 263 | Object.entries(subBlocks).forEach(([key, subBlock]) => { |
| 264 | // Skip null/undefined values |
| 265 | if (subBlock.value === null || subBlock.value === undefined) { |
| 266 | return |
| 267 | } |
| 268 | |
| 269 | // Normalize responseFormat for consistent key ordering (important for training data) |
| 270 | if (key === 'responseFormat') { |
| 271 | try { |
| 272 | let obj = subBlock.value |
| 273 | |
| 274 | // Parse JSON string if needed |
| 275 | if (typeof subBlock.value === 'string') { |
| 276 | const trimmed = subBlock.value.trim() |
| 277 | if (!trimmed) { |
| 278 | return |
| 279 | } |
| 280 | obj = JSON.parse(trimmed) |
| 281 | } |
| 282 | |
| 283 | // Sort keys for consistent comparison |
| 284 | if (obj && typeof obj === 'object') { |
| 285 | sanitized[key] = sortObjectKeysDeep(obj) as Record<string, unknown> |
| 286 | return |
| 287 | } |
| 288 | } catch { |
| 289 | // Invalid JSON - pass through as-is |
| 290 | sanitized[key] = subBlock.value |
| 291 | return |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | // Special handling for condition-input type - clean UI metadata |
| 296 | if (subBlock.type === 'condition-input') { |
| 297 | if (typeof subBlock.value === 'string') { |
| 298 | sanitized[key] = sanitizeConditions(subBlock.value) |
| 299 | } else if (Array.isArray(subBlock.value)) { |
| 300 | sanitized[key] = subBlock.value.map(toSanitizedCondition) |
| 301 | } else { |
| 302 | sanitized[key] = subBlock.value |
| 303 | } |
| 304 | return |
| 305 | } |
| 306 | |
| 307 | if (key === 'tools' && Array.isArray(subBlock.value)) { |
| 308 | const toolItems: unknown[] = subBlock.value |
| 309 | sanitized[key] = sanitizeTools(toolItems.filter(isToolInput)) |
| 310 | return |
| 311 | } |
| 312 | |
| 313 | // Skip knowledge base tag filters and document tags (workspace-specific data) |
| 314 | if (key === 'tagFilters' || key === 'documentTags') { |
| 315 | return |
no test coverage detected