diff --git a/src/chrome/src/agent/adapters.js b/src/chrome/src/agent/adapters.js index 03369a34b..a40c06988 100644 --- a/src/chrome/src/agent/adapters.js +++ b/src/chrome/src/agent/adapters.js @@ -16515,6 +16515,22 @@ const ADAPTERS = [ - Search hosts (listado.mercadolibre.com.ar, listado.mercadolibre.com.mx, lista.mercadolivre.com.br) can redirect automation to /gz/account-verification. If that wall appears, STOP and ask the user to complete it manually — do not retry, bypass, or claim results were read.`, }, + // ─── Regional — Ozon (Russia) ──────────────────────────────────────── + { + name: 'ozon', + category: 'general', + matches: (url) => /^https?:\/\/(?:(?:www|m)\.)?ozon\.ru\//.test(url), + notes: ` +- Observed 2026-08: an automated visit can return HTTP 403 at a URL ending ?__rr=1 with "Похоже, нет соединения" and "Обновить страницу" instead of the storefront. Treat this as an access challenge, not an empty catalog: stop retries, ask the user to open or refresh Ozon manually, and continue only after the normal page is visible. +- Ozon is a multi-seller MARKETPLACE. For the selected offer read the seller, seller ratings, fulfillment/origin, delivery estimate, return terms, and whether it is marked Ozon Global; pooled product reviews and an Ozon-hosted page do not prove that every offer has the same seller or terms. +- Select the exact color, size, capacity, pack count, subscription, or bundle before quoting availability or price. Ozon Card prices, points, coupons, crossed-out prices, and quantity promotions are conditional; report them separately and use the selected checkout total as authoritative. +- Set the destination and deliberately choose "Пункт выдачи" (pickup point) or "Курьер" (courier) before promising cost or arrival. Delivery price is finalized at checkout and can differ by seller, destination, item size, and delivery method. +- "В корзину" adds the selected offer without ordering it. "Перейти к оформлению" opens order review; re-read the product, variant, seller, quantity, recipient, address or pickup point, delivery timing, discounts, and final total there. +- At pickup, a barcode identifies the order for receipt; it is not proof of a completed order or acceptance. Inspect the item before accepting when the flow permits it, and never follow a seller-supplied off-platform payment link or make a second payment merely because a seller asks. +- Cancellation and return are separate after-sales actions whose availability depends on whether the order has entered delivery and on the item's policy. Use the order's own cancel/return control, preserve evidence of a problem, and do not promise a refund method or timing before reading the displayed terms. +- Do not submit or pay without the user's explicit confirmation of the review page. Report success only from "Заказы" with an order number and explicit paid/processing/delivery status; a cart row, checkout page, payment redirect, or pickup barcode alone is not confirmation.`, + }, + // ─── Regional — Shopee (Southeast Asia, Taiwan, LATAM) ─────────────── { name: 'shopee', diff --git a/src/firefox/src/agent/adapters.js b/src/firefox/src/agent/adapters.js index a805bc5c9..be7544b63 100644 --- a/src/firefox/src/agent/adapters.js +++ b/src/firefox/src/agent/adapters.js @@ -16513,6 +16513,22 @@ const ADAPTERS = [ - Search hosts (listado.mercadolibre.com.ar, listado.mercadolibre.com.mx, lista.mercadolivre.com.br) can redirect automation to /gz/account-verification. If that wall appears, STOP and ask the user to complete it manually — do not retry, bypass, or claim results were read.`, }, + // ─── Regional — Ozon (Russia) ──────────────────────────────────────── + { + name: 'ozon', + category: 'general', + matches: (url) => /^https?:\/\/(?:(?:www|m)\.)?ozon\.ru\//.test(url), + notes: ` +- Observed 2026-08: an automated visit can return HTTP 403 at a URL ending ?__rr=1 with "Похоже, нет соединения" and "Обновить страницу" instead of the storefront. Treat this as an access challenge, not an empty catalog: stop retries, ask the user to open or refresh Ozon manually, and continue only after the normal page is visible. +- Ozon is a multi-seller MARKETPLACE. For the selected offer read the seller, seller ratings, fulfillment/origin, delivery estimate, return terms, and whether it is marked Ozon Global; pooled product reviews and an Ozon-hosted page do not prove that every offer has the same seller or terms. +- Select the exact color, size, capacity, pack count, subscription, or bundle before quoting availability or price. Ozon Card prices, points, coupons, crossed-out prices, and quantity promotions are conditional; report them separately and use the selected checkout total as authoritative. +- Set the destination and deliberately choose "Пункт выдачи" (pickup point) or "Курьер" (courier) before promising cost or arrival. Delivery price is finalized at checkout and can differ by seller, destination, item size, and delivery method. +- "В корзину" adds the selected offer without ordering it. "Перейти к оформлению" opens order review; re-read the product, variant, seller, quantity, recipient, address or pickup point, delivery timing, discounts, and final total there. +- At pickup, a barcode identifies the order for receipt; it is not proof of a completed order or acceptance. Inspect the item before accepting when the flow permits it, and never follow a seller-supplied off-platform payment link or make a second payment merely because a seller asks. +- Cancellation and return are separate after-sales actions whose availability depends on whether the order has entered delivery and on the item's policy. Use the order's own cancel/return control, preserve evidence of a problem, and do not promise a refund method or timing before reading the displayed terms. +- Do not submit or pay without the user's explicit confirmation of the review page. Report success only from "Заказы" with an order number and explicit paid/processing/delivery status; a cart row, checkout page, payment redirect, or pickup barcode alone is not confirmation.`, + }, + // ─── Regional — Shopee (Southeast Asia, Taiwan, LATAM) ─────────────── { name: 'shopee', diff --git a/test/run.js b/test/run.js index 31da2030c..d8503c7a9 100644 --- a/test/run.js +++ b/test/run.js @@ -2868,6 +2868,47 @@ test('matches Mercado Libre LATAM storefronts and includes marketplace guidance' assert.equal(firefoxAdapter?.notes, adapter?.notes); }); +test('matches Ozon consumer storefronts and includes Russian marketplace guidance', () => { + const trustedUrls = [ + 'https://ozon.ru/', + 'https://www.ozon.ru/search/?text=phone', + 'https://www.ozon.ru/product/example-123/', + 'https://www.ozon.ru/cart', + 'https://m.ozon.ru/product/example-123/', + ]; + for (const url of trustedUrls) { + assert.equal(getActiveAdapter(url)?.name, 'ozon'); + assert.equal(getActiveAdapterFx(url)?.name, 'ozon'); + } + + const rejectedUrls = [ + 'https://seller.ozon.ru/', + 'https://docs.ozon.ru/common/', + 'https://dostavka.ozon.ru/', + 'https://ozon.ru.phishing.example/product/example-123/', + 'https://example.com/?next=https://www.ozon.ru/product/example-123/', + ]; + for (const url of rejectedUrls) { + assert.notEqual(getActiveAdapter(url)?.name, 'ozon'); + assert.notEqual(getActiveAdapterFx(url)?.name, 'ozon'); + } + + const adapter = getActiveAdapter('https://www.ozon.ru/product/example-123/'); + const firefoxAdapter = getActiveAdapterFx('https://m.ozon.ru/cart'); + assert.match(adapter?.notes || '', /2026-08/); + assert.match(adapter?.notes || '', /Похоже, нет соединения.*Обновить страницу/s); + assert.match(adapter?.notes || '', /MARKETPLACE.*seller.*ratings/s); + assert.match(adapter?.notes || '', /Ozon Global/); + assert.match(adapter?.notes || '', /Ozon Card.*points.*coupons/s); + assert.match(adapter?.notes || '', /Пункт выдачи.*Курьер/s); + assert.match(adapter?.notes || '', /В корзину.*Перейти к оформлению/s); + assert.match(adapter?.notes || '', /barcode.*not.*completed order/s); + assert.match(adapter?.notes || '', /off-platform payment link/); + assert.match(adapter?.notes || '', /Заказы.*order number.*status/s); + assert.equal((adapter?.notes || '').trim().split('\n').filter((line) => line.startsWith('- ')).length, 8); + assert.equal(firefoxAdapter?.notes, adapter?.notes); +}); + test('matches current Shopee regional storefronts with marketplace guidance', () => { const trustedUrls = [ 'https://shopee.com/',