| 12345678 |
- {
- "name": "get_product_compatibility",
- "description": "IMPORTANT: Always reply to the customer in their own language — the exact language they write in. Never switch to Polish unless the customer writes in Polish.\n\nWywołaj gdy użytkownik pyta o produkty do auta lub kompatybilność. To narzędzie AUTOMATYCZNIE prowadzi przez kilka kroków:\n1. Jeśli marka nieznana → pyta o markę\n2. Jeśli wiele modeli → pyta o model\n3. Jeśli wiele silników → pyta o silnik\n4. Gdy wszystko jasne → zwraca listę kompatybilnych produktów (lub sprawdza konkretny)\n\nNIE potrzebujesz wywoływać get_car_data wcześniej — to narzędzie obsługuje cały flow samodzielnie. Wywołuj kolejno, aż dostaniesz listę produktów. Zawsze podawaj language wykryty z wiadomości klienta.\n\nBez product_name/product_id → lista WSZYSTKICH kompatybilnych produktów. Z product_id (preferowane) lub product_name → sprawdzenie konkretnego produktu. Jeśli masz product_id z wcześniejszego wyszukiwania — zawsze go używaj.",
- "color": "linear-gradient(rgb(180,120,200), rgb(140,60,180))",
- "iconSrc": "",
- "schema": "[{\"id\": 0, \"property\": \"car_brand\", \"description\": \"Marka pojazdu (np. Toyota, BMW)\", \"type\": \"string\", \"required\": true}, {\"id\": 1, \"property\": \"car_model\", \"description\": \"Model pojazdu (np. Corolla, E46). Podaj gdy znany — narzędzie zapyta jeśli brak.\", \"type\": \"string\", \"required\": true}, {\"id\": 2, \"property\": \"car_year\", \"description\": \"Rok produkcji pojazdu (np. 2012). Pomaga filtrować modele i silniki.\", \"type\": \"string\", \"required\": true}, {\"id\": 3, \"property\": \"car_engine\", \"description\": \"DEPRECATED — użyj car_engine_index zamiast tego. Podaj tylko jeśli nie masz car_engine_index z listy opcji.\", \"type\": \"string\", \"required\": false}, {\"id\": 4, \"property\": \"product_name\", \"description\": \"Fragment nazwy produktu do wyszukania. Backend obsługuje tłumaczenia automatycznie. Jeśli masz product_id — użyj go zamiast.\", \"type\": \"string\", \"required\": false}, {\"id\": 5, \"property\": \"product_id\", \"description\": \"ID produktu z wcześniejszego wyszukiwania lub listy wyników. Preferowane nad product_name.\", \"type\": \"number\", \"required\": false}, {\"id\": 6, \"property\": \"language\", \"description\": \"Kod języka WPML (np. pl, de, en, fr, cs, tr). Wymagany do poprawnego dopasowania i tłumaczenia nazw.\", \"type\": \"string\", \"required\": false}, {\"id\": 7, \"property\": \"car_engine_index\", \"description\": \"Indeks silnika z listy opcji (Number->Index map). Użyj ZAMIAST car_engine — jednoznaczny, bez błędów string-matching. Gdy tool zwróci opcje silników, podaj ten indeks zamiast tekstu.\", \"type\": \"number\", \"required\": false}]",
- "func": "const fetch = require('node-fetch')\n\nconst base = String(($vars && ($vars.relay_base || $vars.webhook_base)) || 'http://localhost:8080').replace(/\\/$/,'')\nconst secret = String(($vars && $vars.relay_shared_secret) || '')\n\nconst car_brand = typeof $car_brand !== 'undefined' && $car_brand ? String($car_brand) : ''\nconst car_model = typeof $car_model !== 'undefined' && $car_model ? String($car_model) : ''\nconst car_year = typeof $car_year !== 'undefined' && $car_year ? String($car_year) : ''\nconst car_engine = typeof $car_engine !== 'undefined' && $car_engine ? String($car_engine) : ''\nconst car_engine_index = typeof $car_engine_index !== 'undefined' && $car_engine_index !== null && $car_engine_index !== '' ? Number($car_engine_index) : -1\nconst product_name = typeof $product_name !== 'undefined' && $product_name ? String($product_name) : ''\nconst language = typeof $language !== 'undefined' && $language ? String($language) : ''\nconst product_id = typeof $product_id !== 'undefined' && $product_id ? Number($product_id) : 0\n\nif (!car_brand || !car_model || !car_year) return 'Error: provide car_brand, car_model and car_year'\nif (!secret) return 'Error: missing $vars.relay_shared_secret'\n\ntry {\n const body = { car_brand, car_model, car_year }\n // Prefer index-based engine selection (unambiguous) over name-based (fragile string match)\n if (car_engine_index >= 0) body.car_engine_index = car_engine_index\n else 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\n\n const res = await fetch(`${base}/tools/get_product_compatibility`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${secret}`\n },\n body: JSON.stringify(body)\n })\n const data = await res.json()\n if (data.ok) {\n const result = data.data\n\n // Opcje do wyboru (model, silnik, marka)\n if (result && result.error === 'options') {\n const fieldName = result.field || 'pole'\n const rawOptions = result.options || []\n\n // Product options with IDs — titles are already translated by the relay backend\n if (fieldName === 'product_name' && rawOptions.length > 0 && typeof rawOptions[0] === 'object' && rawOptions[0].id) {\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=<that id> and the same car parameters. NEVER search by name again.\\nNumber->ID: ${idMap}]`\n }\n\n // Engine options — index-based selection avoids string-matching errors (LLM confuses \"3\" with \"3.0\", strips type prefixes like \"B \", \"D \")\n if (fieldName === 'car_engine' && rawOptions.length > 0 && typeof rawOptions[0] === 'object') {\n const indexMap = rawOptions.map((o, i) => `${i + 1}=${o.index}`).join(', ')\n const list = rawOptions.map((o, i) => `${i + 1}. ${o.name}`).join('\\n')\n const extras = product_id > 0 ? `, product_id=${product_id}` : product_name ? `, product_name=\"${product_name}\"` : ''\n const langParam = language ? `, language=\"${language}\"` : ''\n return `[STEP: car_engine]\\nEngines for ${car_brand} ${car_model} ${car_year}:\\n${list}\\n\\n[INSTRUCTION: Present these numbered options to the user IN THEIR OWN LANGUAGE asking them to choose. After the user picks number N, look up N in the Number->Index map to get the numeric index, then call this tool again with car_engine_index=<that index> plus car_brand=\"${car_brand}\", car_model=\"${car_model}\", car_year=\"${car_year}\"${extras}${langParam}. NEVER send car_engine as a text string — always use car_engine_index. Do NOT ask the user to re-state what they already told you.\\nNumber->Index: ${indexMap}]`\n }\n\n // Car disambiguation options (brand / model)\n const options = rawOptions.map(o => typeof o === 'object' ? (o.name || o.title || '') : String(o).trim()).filter(Boolean)\n const nextCallHint = `After the user picks, call this tool again with ${fieldName}=<chosen value> plus all other known parameters (brand, model, year, language). The tool may ask for the engine next, then will return products.`\n return `[STEP: ${fieldName}]\\nOptions for ${car_brand}${car_model ? ' ' + car_model : ''} ${car_year}:\\n${options.map((o, i) => `${i + 1}. ${o}`).join('\\n')}\\n\\n[INSTRUCTION: Present these numbered options to the user IN THEIR OWN LANGUAGE asking them to choose. ${nextCallHint} Do NOT ask the user to re-state what they already told you — just ask them to pick from this list.]`\n }\n\n // Lista wszystkich kompatybilnych produktów\n if (result && Array.isArray(result.compatible_products)) {\n const products = result.compatible_products\n const eng = result.selected_engine || {}\n const gasType = (eng.ac_gas_type || '').toUpperCase() || 'unknown'\n const engName = eng.name || car_engine || ''\n const carLabel = `${car_brand} ${car_model} ${car_year}${engName ? ' ' + engName : ''}`\n const currencyCode = data.currency || 'PLN'\n const currencyNote = data.currency_fallback && data.currency_note ? '\\n[NOTE: ' + data.currency_note + ']' : ''\n\n if (products.length === 0) {\n return `No compatible products found for ${carLabel} in our store.`\n }\n\n const idMap = products.map((p, i) => `${i + 1}=${p.id}`).join(', ')\n const lines = products.map((p, i) => `${i + 1}. ${p.title} — ${p.price ? p.price + ' ' + currencyCode : ''} — ${p.permalink}`)\n return `Car ${carLabel} requires refrigerant: ${gasType}.\\nCompatible products:\\n${lines.join('\\n')}${currencyNote}\\n\\n[INSTRUCTION: Reply to the customer IN THEIR OWN LANGUAGE. Show the relevant products from the list (based on what they asked). Always state the required refrigerant type (${gasType}). If the user wants details about a product, use product_id from the Number->ID map with get_product_data tool — NEVER search by name.\\nNumber->ID: ${idMap}]`\n }\n\n // Sprawdzenie konkretnego produktu — tytuł przetłumaczony przez relay backend\n if (result && typeof result.fit !== 'undefined') {\n const eng = result.selected_engine || {}\n const prod = result.selected_product || {}\n const engName = eng.name || car_engine || ''\n const carLabel = `${car_brand} ${car_model} ${car_year}${engName ? ' ' + engName : ''}`\n const gasType = (eng.ac_gas_type || '').toUpperCase()\n\n if (result.fit) {\n return `Product \"${prod.title || product_name}\" IS COMPATIBLE with ${carLabel}.`\n } else {\n const reasons = []\n if (!result.gas_fit) reasons.push(`refrigerant mismatch (car requires: ${gasType}, product has: ${(prod.attributes && prod.attributes.pa_rg || []).join('/') || 'none'})`)\n if (!result.adapter_fit) reasons.push(`adapter mismatch (car: ${eng.adapters || 'none'}, product: ${(prod.attributes && prod.attributes.pa_ra || []).join('/') || 'none'})`)\n return `Product \"${prod.title || product_name}\" is NOT COMPATIBLE with ${carLabel}. Reason: ${reasons.join(', ')}.`\n }\n }\n\n return JSON.stringify(result, null, 2)\n }\n return `Info: ${data.message || JSON.stringify(data)}`\n} catch (error) {\n return `Connection error: ${error?.message || String(error)}`\n}\n"
- }
|