(nodePath: string)
| 526 | // Helper to find content by matching path suffix |
| 527 | // Returns both content AND the canonical key (for consistent cache storage) |
| 528 | const findContentWithKey = (nodePath: string): { content: string; key: string } | undefined => { |
| 529 | // Try exact match first |
| 530 | if (contents[nodePath]) return { content: contents[nodePath], key: nodePath }; |
| 531 | |
| 532 | // Normalize both paths for comparison |
| 533 | const normalizedNode = nodePath.replace(/\\/g, '/').replace(/^\//, ''); |
| 534 | |
| 535 | for (const [contentKey, content] of Object.entries(contents)) { |
| 536 | const normalizedKey = contentKey.replace(/\\/g, '/').replace(/^\//, ''); |
| 537 | |
| 538 | // Exact match after normalization |
| 539 | if (normalizedNode === normalizedKey) return { content, key: contentKey }; |
| 540 | |
| 541 | // Either path could be full or relative, so check both directions |
| 542 | // Case 1: nodePath is full, contentKey is relative |
| 543 | if (normalizedNode.endsWith('/' + normalizedKey)) return { content, key: contentKey }; |
| 544 | if (normalizedNode.endsWith(normalizedKey)) return { content, key: contentKey }; |
| 545 | |
| 546 | // Case 2: contentKey is full, nodePath is relative (LLM returned short path) |
| 547 | if (normalizedKey.endsWith('/' + normalizedNode)) return { content, key: contentKey }; |
| 548 | if (normalizedKey.endsWith(normalizedNode)) return { content, key: contentKey }; |
| 549 | } |
| 550 | |
| 551 | return undefined; |
| 552 | }; |
| 553 | |
| 554 | // Build per-node workflow mapping from LLM-assigned workflows |
| 555 | // A single file can have nodes in multiple workflows (e.g., gemini.ts serves 5 workflows) |
nothing calls this directly
no outgoing calls
no test coverage detected