Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/chrome/src/agent/adapters.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 — Shopee (Southeast Asia, Taiwan, LATAM) ───────────────
{
name: 'shopee',
category: 'general',
matches: (url) => /^https?:\/\/(?:www\.)?(?:shopee\.(?:com|sg|vn|tw|co\.th|com\.mx|com\.my|com\.br|com\.la|com\.ar|co\.id|ph)|shopeekh\.com)\//.test(url),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8c16517. Both Chrome and Firefox now recognize shopeekh.com as a shopping host, with a regression test that uses a non-generic product path and asserts the compare-price recommendation.

notes: `
- As of 2026-08, shopee.com is a "Choose a country or region" handoff to separate regional storefronts. Choose the user's actual market before searching: accounts, catalog, currency, stock, delivery addresses, vouchers, and payment methods are region-specific, so availability in one storefront is not proof that another can fulfill it.
- A storefront may first show a language chooser or redirect to /verify/traffic/error with an almost empty page. Select the user's language when offered; for /verify/traffic, stop retries and ask the user to complete the traffic check manually in the current tab, then re-read it. Do not treat the empty tree as no results or try to bypass the check.
- On a product page select the preferred variation and quantity before comparing or adding it. Key labels include Indonesian "Masukkan Keranjang" / "Beli Sekarang", Vietnamese "Thêm Vào Giỏ Hàng" / "Mua Ngay", Thai "เพิ่มไปยังรถเข็น" / "ซื้อเลย", Chinese "加入購物車" / "直接購買", and Portuguese "Adicionar ao Carrinho" / "Comprar Agora"; use only the labels visible in the active market.
- Shopee is a multi-seller marketplace. A Shopee Mall badge identifies a participating official store, but still read the selected seller, shop profile, ratings, item reviews, return terms, stock, origin, shipping option, and arrival estimate; product reviews and a Mall badge do not prove every seller offer is equivalent.
- Discounts are conditional. A seller voucher, free shipping voucher, and platform voucher can have separate minimum spend, product, payment, user, quota, and expiry rules. Shipping also varies by seller; apply only eligible vouchers and quote the final checkout total separately from coins, cashback, and advertised savings.
- "Add to Cart" preserves a multi-item review step; "Buy Now" jumps directly to checkout. Re-read every selected variation, quantity, seller, shipping option, address, voucher, payment method, and total before "Place Order", and require the user's explicit confirmation before placing or paying for an order.
- Login can require password, SMS OTP, QR confirmation in the Shopee app, CAPTCHA, or trusted-device approval. Ask the user to complete any OTP, QR, or account verification manually; never request, read, repeat, or expose a verification code, and continue from the returned page instead of restarting the task.
- "Order Received" can release held purchase funds to the seller and affect guarantee or return timing. Never select it from tracking status alone; require the user's explicit confirmation that the exact goods arrived and were inspected. Report a placed order only from the confirmation or My Purchases page with an order ID; a cart, checkout, payment prompt, or submitted request is incomplete.`,
},

// ─── Regional — Flipkart (India) ─────────────────────────────────────
{
name: 'flipkart',
Expand Down
2 changes: 1 addition & 1 deletion src/chrome/src/ui/recommended-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const SOCIAL_HOST_RE = /(^|\.)(instagram\.com|tiktok\.com|x\.com|twitter\.com|fa
const PUBLIC_MEDIA_HOST_RE = /(^|\.)(youtube\.com|youtu\.be|tiktok\.com|instagram\.com|x\.com|twitter\.com|reddit\.com|redd\.it|facebook\.com|fb\.com|fb\.watch|pinterest\.com|pin\.it|linkedin\.com|threads\.net)$/i;
const MEETING_HOST_RE = /(^|\.)(zoom\.us|meet\.google\.com|teams\.microsoft\.com|whereby\.com|webex\.com|gotomeeting\.com)$/i;
const DATING_HOST_RE = /(^|\.)(tinder\.com|bumble\.com|hinge\.co|okcupid\.com|match\.com|pof\.com|badoo\.com|happn\.com|coffeemeetsbagel\.com)$/i;
const SHOPPING_HOST_RE = /(^|\.)(amazon\.[a-z.]+|ebay\.[a-z.]+|etsy\.com|walmart\.com|target\.com|bestbuy\.com|shopify\.com|aliexpress\.com|mercadolibre\.[a-z.]+|mercadolivre\.com\.br|hepsiburada\.com|trendyol\.com|n11\.com|shopee\.[a-z.]+|lazada\.[a-z.]+)$/i;
const SHOPPING_HOST_RE = /(^|\.)(amazon\.[a-z.]+|ebay\.[a-z.]+|etsy\.com|walmart\.com|target\.com|bestbuy\.com|shopify\.com|aliexpress\.com|mercadolibre\.[a-z.]+|mercadolivre\.com\.br|hepsiburada\.com|trendyol\.com|n11\.com|shopee\.[a-z.]+|shopeekh\.com|lazada\.[a-z.]+)$/i;
const PRODUCT_PATH_RE = /\/(dp|gp\/product|itm|p|product|products|prod|item|listing|ilan|urun)\b/i;
const RELEASES_PATH_RE = /^\/[^/]+\/[^/]+\/releases(?:\/|$)/i;
const SEARCH_INPUT_RE = /^(search|q|query|keyword|keywords|s)$/i;
Expand Down
16 changes: 16 additions & 0 deletions src/firefox/src/agent/adapters.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 — Shopee (Southeast Asia, Taiwan, LATAM) ───────────────
{
name: 'shopee',
category: 'general',
matches: (url) => /^https?:\/\/(?:www\.)?(?:shopee\.(?:com|sg|vn|tw|co\.th|com\.mx|com\.my|com\.br|com\.la|com\.ar|co\.id|ph)|shopeekh\.com)\//.test(url),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8c16517. Both Chrome and Firefox now recognize shopeekh.com as a shopping host, with a regression test that uses a non-generic product path and asserts the compare-price recommendation.

notes: `
- As of 2026-08, shopee.com is a "Choose a country or region" handoff to separate regional storefronts. Choose the user's actual market before searching: accounts, catalog, currency, stock, delivery addresses, vouchers, and payment methods are region-specific, so availability in one storefront is not proof that another can fulfill it.
- A storefront may first show a language chooser or redirect to /verify/traffic/error with an almost empty page. Select the user's language when offered; for /verify/traffic, stop retries and ask the user to complete the traffic check manually in the current tab, then re-read it. Do not treat the empty tree as no results or try to bypass the check.
- On a product page select the preferred variation and quantity before comparing or adding it. Key labels include Indonesian "Masukkan Keranjang" / "Beli Sekarang", Vietnamese "Thêm Vào Giỏ Hàng" / "Mua Ngay", Thai "เพิ่มไปยังรถเข็น" / "ซื้อเลย", Chinese "加入購物車" / "直接購買", and Portuguese "Adicionar ao Carrinho" / "Comprar Agora"; use only the labels visible in the active market.
- Shopee is a multi-seller marketplace. A Shopee Mall badge identifies a participating official store, but still read the selected seller, shop profile, ratings, item reviews, return terms, stock, origin, shipping option, and arrival estimate; product reviews and a Mall badge do not prove every seller offer is equivalent.
- Discounts are conditional. A seller voucher, free shipping voucher, and platform voucher can have separate minimum spend, product, payment, user, quota, and expiry rules. Shipping also varies by seller; apply only eligible vouchers and quote the final checkout total separately from coins, cashback, and advertised savings.
- "Add to Cart" preserves a multi-item review step; "Buy Now" jumps directly to checkout. Re-read every selected variation, quantity, seller, shipping option, address, voucher, payment method, and total before "Place Order", and require the user's explicit confirmation before placing or paying for an order.
- Login can require password, SMS OTP, QR confirmation in the Shopee app, CAPTCHA, or trusted-device approval. Ask the user to complete any OTP, QR, or account verification manually; never request, read, repeat, or expose a verification code, and continue from the returned page instead of restarting the task.
- "Order Received" can release held purchase funds to the seller and affect guarantee or return timing. Never select it from tracking status alone; require the user's explicit confirmation that the exact goods arrived and were inspected. Report a placed order only from the confirmation or My Purchases page with an order ID; a cart, checkout, payment prompt, or submitted request is incomplete.`,
},

// ─── Regional — Flipkart (India) ─────────────────────────────────────
{
name: 'flipkart',
Expand Down
2 changes: 1 addition & 1 deletion src/firefox/src/ui/recommended-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { t } from './i18n.js';
const SOCIAL_HOST_RE = /(^|\.)(instagram\.com|tiktok\.com|x\.com|twitter\.com|facebook\.com|fb\.com|threads\.net|youtube\.com|youtu\.be|reddit\.com|pinterest\.com|snapchat\.com)$/i;
const PUBLIC_MEDIA_HOST_RE = /(^|\.)(youtube\.com|youtu\.be|tiktok\.com|instagram\.com|x\.com|twitter\.com|reddit\.com|redd\.it|facebook\.com|fb\.com|fb\.watch|pinterest\.com|pin\.it|linkedin\.com|threads\.net)$/i;
const DATING_HOST_RE = /(^|\.)(tinder\.com|bumble\.com|hinge\.co|okcupid\.com|match\.com|pof\.com|badoo\.com|happn\.com|coffeemeetsbagel\.com)$/i;
const SHOPPING_HOST_RE = /(^|\.)(amazon\.[a-z.]+|ebay\.[a-z.]+|etsy\.com|walmart\.com|target\.com|bestbuy\.com|shopify\.com|aliexpress\.com|mercadolibre\.[a-z.]+|mercadolivre\.com\.br|hepsiburada\.com|trendyol\.com|n11\.com|shopee\.[a-z.]+|lazada\.[a-z.]+)$/i;
const SHOPPING_HOST_RE = /(^|\.)(amazon\.[a-z.]+|ebay\.[a-z.]+|etsy\.com|walmart\.com|target\.com|bestbuy\.com|shopify\.com|aliexpress\.com|mercadolibre\.[a-z.]+|mercadolivre\.com\.br|hepsiburada\.com|trendyol\.com|n11\.com|shopee\.[a-z.]+|shopeekh\.com|lazada\.[a-z.]+)$/i;
const PRODUCT_PATH_RE = /\/(dp|gp\/product|itm|p|product|products|prod|item|listing|ilan|urun)\b/i;
const RELEASES_PATH_RE = /^\/[^/]+\/[^/]+\/releases(?:\/|$)/i;
const SEARCH_INPUT_RE = /^(search|q|query|keyword|keywords|s)$/i;
Expand Down
58 changes: 58 additions & 0 deletions test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -2868,6 +2868,53 @@ test('matches Mercado Libre LATAM storefronts and includes marketplace guidance'
assert.equal(firefoxAdapter?.notes, adapter?.notes);
});

test('matches current Shopee regional storefronts with marketplace guidance', () => {
const trustedUrls = [
'https://shopee.com/',
'https://shopee.sg/search?keyword=phone',
'https://www.shopee.vn/example-shop/example-item',
'https://shopee.tw/',
'https://shopee.co.th/',
'https://shopee.com.mx/',
'https://shopee.com.my/',
'https://shopee.com.br/',
'https://shopee.com.la/',
'https://shopee.com.ar/',
'https://shopee.co.id/',
'https://shopee.ph/',
'https://www.shopeekh.com/',
];
for (const url of trustedUrls) {
assert.equal(getActiveAdapter(url)?.name, 'shopee');
assert.equal(getActiveAdapterFx(url)?.name, 'shopee');
}

const rejectedUrls = [
'https://seller.shopee.sg/',
'https://help.shopee.sg/portal/4',
'https://account.seller.shopee.com/signin',
'https://shopee.com.phishing.example/search?keyword=phone',
'https://example.com/?next=https://shopee.sg/',
];
for (const url of rejectedUrls) {
assert.notEqual(getActiveAdapter(url)?.name, 'shopee');
assert.notEqual(getActiveAdapterFx(url)?.name, 'shopee');
}

const adapter = getActiveAdapter(trustedUrls[1]);
const firefoxAdapter = getActiveAdapterFx(trustedUrls.at(-1));
assert.match(adapter?.notes || '', /2026-08.*Choose a country or region/s);
assert.match(adapter?.notes || '', /verify\/traffic.*complete.*manually/s);
assert.match(adapter?.notes || '', /preferred variation.*Masukkan Keranjang.*Thêm Vào Giỏ Hàng.*加入購物車/s);
assert.match(adapter?.notes || '', /Shopee Mall.*seller.*ratings/s);
assert.match(adapter?.notes || '', /seller voucher.*free shipping voucher.*platform voucher.*minimum spend/s);
assert.match(adapter?.notes || '', /Add to Cart.*Buy Now.*Place Order/s);
assert.match(adapter?.notes || '', /OTP.*manually/s);
assert.match(adapter?.notes || '', /Order Received.*release.*funds.*order ID/s);
assert.equal((adapter?.notes || '').trim().split('\n').filter((line) => line.startsWith('- ')).length, 8);
assert.equal(firefoxAdapter?.notes, adapter?.notes);
});

test('matches Flipkart shopping surfaces with India marketplace guidance', () => {
const trustedUrls = [
'https://flipkart.com/',
Expand Down Expand Up @@ -9737,6 +9784,17 @@ test('recommended actions match issue scenarios', () => {
}
});

for (const [label, buildRecommendedActions] of [['chrome', buildRecommendedActionsCh], ['firefox', buildRecommendedActionsFx]]) {
test(`recommended actions recognize Shopee Cambodia's distinct hostname in ${label}`, () => {
const actions = buildRecommendedActions({
url: 'https://www.shopeekh.com/kh-en/detail/123',
title: 'Wireless headphones',
description: 'US$20.00',
});
assert.ok(actions.some((action) => action.id === 'compare-price'));
});
}

test('WebBrain promotion has explicit X and LinkedIn variants with ready-to-go plans', () => {
const exactPost = 'Introducing WebBrain — an open-source AI browser agent that lives in your browser. Chat with any page, automate multi-step workflows, and bring your own LLM. Extensible by design. Try it: https://webbrain.one';
const expectedTweetSteps = [
Expand Down
Loading