import json, re path = r'c:/Users/aiac_dev/eks_relay/flowise-tools/get_product_compatibility.json' with open(path, 'r', encoding='utf-8') as f: data = json.load(f) # ── 1. Schema: insert product_id before language ──────────────────── schema = json.loads(data['schema']) for s in schema: if s['property'] == 'language': s['id'] = 6 schema.insert(5, { 'id': 5, 'property': 'product_id', 'description': 'ID produktu — podaj zamiast product_name gdy uzytkownik wybral z listy (uzyj mapy Number->ID)', 'type': 'number', 'required': False, }) data['schema'] = json.dumps(schema, ensure_ascii=False) # ── 2. Func: work on the actual decoded JS string ─────────────────── func = data['func'] # 2a. Add product_id variable OLD_A = "const language = typeof $language !== 'undefined' && $language ? String($language) : ''\n\nif (!car_brand" NEW_A = "const language = typeof $language !== 'undefined' && $language ? String($language) : ''\nconst product_id = typeof $product_id !== 'undefined' && $product_id ? Number($product_id) : 0\n\nif (!car_brand" assert OLD_A in func, 'pattern 2a not found' func = func.replace(OLD_A, NEW_A) # 2b. Body construction: product_id takes priority over product_name OLD_B = ' if (car_engine) body.car_engine = car_engine\n if (product_name) body.product_name = product_name\n if (language) body.language = language' NEW_B = ' if (car_engine) body.car_engine = car_engine\n if (product_id > 0) body.product_id = product_id\n else if (product_name) body.product_name = product_name\n if (language) body.language = language' assert OLD_B in func, 'pattern 2b not found' func = func.replace(OLD_B, NEW_B) # 2c. Replace options handler block match = re.search(r' // Opcje do wyboru \(np\. silnik.*? \}', func, re.DOTALL) assert match, 'options handler not found' old_c = match.group(0) # In the actual JS string (after JSON.load), \n inside template literals # is the two-char sequence \n. Python represents this as \\n in string literals. new_c = ( " // Opcje do wyboru\n" " if (result && result.error === 'options') {\n" " const fieldName = result.field || 'pole'\n" " const rawOptions = result.options || []\n" "\n" " // Product options with IDs — use ID map like get_product_data\n" " if (fieldName === 'product_name' && rawOptions.length > 0 && typeof rawOptions[0] === 'object') {\n" " const idMap = rawOptions.map((o, i) => `${i + 1}=${o.id}`).join(', ')\n" " const list = rawOptions.map((o, i) => `${i + 1}. ${o.title}`).join('\\n')\n" " return `Found ${rawOptions.length} products:\\n${list}\\n\\n[INSTRUCTION: Show the numbered list to the user. When user picks a number N, use the Number->ID map to get the product_id, then call this tool again with product_id= and the same car parameters. NEVER search by name again.\\nNumber->ID: ${idMap}]`\n" " }\n" "\n" " // Generic options (brand, model, engine)\n" " const options = rawOptions.map(o => typeof o === 'object' ? o.title : String(o).trim()).filter(Boolean)\n" " return `Selection required for field\"${fieldName}\". Available options:\\n${options.map((o, i) => `${i + 1}. ${o}`).join('\\n')}\\nAsk the user to choose, then call the tool again with the selected value as parameter\"${fieldName}\".`\n" " }" ) func = func.replace(old_c, new_c) data['func'] = func with open(path, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) print('OK')