* Extract operation options from the subBlock with id: 'operation' (if present). * Returns { label, id } pairs — label is the display name, id is the option's id field * (used to construct the tool ID as `{blockType}_{id}`). * Parses the subBlocks array using brace/bracket counting to safely trav
(blockContent: string)
| 424 | * the nested structure without eval or a full AST parser. |
| 425 | */ |
| 426 | function extractOperationsFromContent(blockContent: string): { label: string; id: string }[] { |
| 427 | const subBlocksMatch = /subBlocks\s*:\s*\[/.exec(blockContent) |
| 428 | if (!subBlocksMatch) return [] |
| 429 | |
| 430 | // Locate the opening '[' of the subBlocks array |
| 431 | const arrayStart = subBlocksMatch.index + subBlocksMatch[0].length - 1 |
| 432 | const arrayEnd = findMatchingClose(blockContent, arrayStart, '[', ']') |
| 433 | if (arrayEnd === -1) return [] |
| 434 | const subBlocksContent = blockContent.substring(arrayStart + 1, arrayEnd - 1) |
| 435 | |
| 436 | // Iterate over top-level objects in the subBlocks array, looking for id: 'operation' |
| 437 | let i = 0 |
| 438 | while (i < subBlocksContent.length) { |
| 439 | if (subBlocksContent[i] === '{') { |
| 440 | const j = findMatchingClose(subBlocksContent, i) |
| 441 | if (j === -1) break |
| 442 | const objContent = subBlocksContent.substring(i, j) |
| 443 | |
| 444 | if (/\bid\s*:\s*['"]operation['"]/.test(objContent)) { |
| 445 | const optionsMatch = /options\s*:\s*\[/.exec(objContent) |
| 446 | if (!optionsMatch) return [] |
| 447 | |
| 448 | const optArrayStart = optionsMatch.index + optionsMatch[0].length - 1 |
| 449 | const optArrayEnd = findMatchingClose(objContent, optArrayStart, '[', ']') |
| 450 | if (optArrayEnd === -1) return [] |
| 451 | const optionsContent = objContent.substring(optArrayStart + 1, optArrayEnd - 1) |
| 452 | |
| 453 | // Extract { label, id } pairs from each option object |
| 454 | const pairs: { label: string; id: string }[] = [] |
| 455 | const optionObjectRegex = /\{[^{}]*\}/g |
| 456 | let m |
| 457 | while ((m = optionObjectRegex.exec(optionsContent)) !== null) { |
| 458 | const optObj = m[0] |
| 459 | const labelMatch = /label\s*:\s*['"]([^'"]+)['"]/.exec(optObj) |
| 460 | const idMatch = /\bid\s*:\s*['"]([^'"]+)['"]/.exec(optObj) |
| 461 | if (labelMatch) { |
| 462 | pairs.push({ label: labelMatch[1], id: idMatch ? idMatch[1] : '' }) |
| 463 | } |
| 464 | } |
| 465 | return pairs |
| 466 | } |
| 467 | i = j |
| 468 | } else { |
| 469 | i++ |
| 470 | } |
| 471 | } |
| 472 | return [] |
| 473 | } |
| 474 | |
| 475 | /** |
| 476 | * Extract a mapping from operation id → tool id by scanning switch/case/return |
no test coverage detected