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
15 changes: 15 additions & 0 deletions src/chrome/src/agent/adapters.js
Original file line number Diff line number Diff line change
Expand Up @@ -15942,6 +15942,21 @@ const ADAPTERS = [
- Login pages (\`wp-login.php\`) have a stable shape: \`#user_login\` (username/email), \`#user_pass\` (password), \`#wp-submit\` (submit). The password field is type=password — when the user provides credentials, do not echo them in any summary.`,
},

{
name: 'wechat-official-account',
category: 'general',
matches: (url) => /^https?:\/\/mp\.weixin\.qq\.com\/(?:$|[?#]|cgi-bin(?:[/?#]|$))/.test(url),
notes: `
- Confirm the current official account name in the top bar before editing or publishing; an old tab or session-token URL may belong to a different account.
- The article editor has separate title and body editable regions. The body uses ProseMirror/contenteditable; focus each region separately and verify its text after writing so the title is not inserted into the body or vice versa.
- "保存为草稿" (Save as draft) and "发表" (Publish) are different outcomes. A saved draft is not publicly visible and must never be reported as published.
- Under "封面" (Cover), "从正文选择" (Select from article) can reuse an inline image. Confirm the intended image and crop instead of accepting the first thumbnail automatically.
- Before clicking "发表", re-check the account, title, author/byline, summary, and cover because publishing is externally visible.
- Publishing can open stacked confirmation dialogs followed by "微信验证" with a QR code. Pause for the user to complete verification; do not dismiss, bypass, or repeatedly retry the dialog.
- Treat publishing as successful only when "发表记录" shows the new article (or a final public article URL is available), not when the editor closes or a confirmation button was clicked.
- Dashboard links contain short-lived session tokens. If a deep link expires or redirects, navigate from the current dashboard instead of inventing or reusing a tokenized URL.`,
},

// ─── Commerce ─────────────────────────────────────────────────────────
{
name: 'amazon',
Expand Down
15 changes: 15 additions & 0 deletions src/firefox/src/agent/adapters.js
Original file line number Diff line number Diff line change
Expand Up @@ -15940,6 +15940,21 @@ const ADAPTERS = [
- Login pages (\`wp-login.php\`) have a stable shape: \`#user_login\` (username/email), \`#user_pass\` (password), \`#wp-submit\` (submit). The password field is type=password — when the user provides credentials, do not echo them in any summary.`,
},

{
name: 'wechat-official-account',
category: 'general',
matches: (url) => /^https?:\/\/mp\.weixin\.qq\.com\/(?:$|[?#]|cgi-bin(?:[/?#]|$))/.test(url),
notes: `
- Confirm the current official account name in the top bar before editing or publishing; an old tab or session-token URL may belong to a different account.
- The article editor has separate title and body editable regions. The body uses ProseMirror/contenteditable; focus each region separately and verify its text after writing so the title is not inserted into the body or vice versa.
- "保存为草稿" (Save as draft) and "发表" (Publish) are different outcomes. A saved draft is not publicly visible and must never be reported as published.
- Under "封面" (Cover), "从正文选择" (Select from article) can reuse an inline image. Confirm the intended image and crop instead of accepting the first thumbnail automatically.
- Before clicking "发表", re-check the account, title, author/byline, summary, and cover because publishing is externally visible.
- Publishing can open stacked confirmation dialogs followed by "微信验证" with a QR code. Pause for the user to complete verification; do not dismiss, bypass, or repeatedly retry the dialog.
- Treat publishing as successful only when "发表记录" shows the new article (or a final public article URL is available), not when the editor closes or a confirmation button was clicked.
- Dashboard links contain short-lived session tokens. If a deep link expires or redirects, navigate from the current dashboard instead of inventing or reusing a tokenized URL.`,
},

// ─── Commerce ─────────────────────────────────────────────────────────
{
name: 'amazon',
Expand Down
30 changes: 30 additions & 0 deletions test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -2330,6 +2330,36 @@ test('matches Xiaohongshu surfaces with mirrored regional guidance', () => {
assert.match(chromeAdapter?.notes || '', /Creator Center.*final public note URL/s);
});

test('matches WeChat Official Account admin surfaces with safe publishing guidance', () => {
const urls = [
'https://mp.weixin.qq.com/',
'https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=123',
'https://mp.weixin.qq.com/cgi-bin/appmsg?t=media/appmsg_edit_v2&action=edit&type=77&token=123&lang=zh_CN',
];
for (const url of urls) {
assert.equal(getActiveAdapter(url)?.name, 'wechat-official-account', `chrome did not match ${url}`);
assert.equal(getActiveAdapterFx(url)?.name, 'wechat-official-account', `firefox did not match ${url}`);
}
assert.notEqual(
getActiveAdapter('https://mp.weixin.qq.com.evil.example/cgi-bin/home')?.name,
'wechat-official-account',
);
assert.notEqual(
getActiveAdapter('https://example.com/?next=https://mp.weixin.qq.com/')?.name,
'wechat-official-account',
);

const chromeAdapter = getActiveAdapter(urls[1]);
const firefoxAdapter = getActiveAdapterFx(urls[1]);
assert.equal(firefoxAdapter?.notes, chromeAdapter?.notes);
assert.match(chromeAdapter?.notes || '', /separate title and body.*ProseMirror\/contenteditable/s);
assert.match(chromeAdapter?.notes || '', /保存为草稿.*发表.*not publicly visible/s);
assert.match(chromeAdapter?.notes || '', /从正文选择.*intended image and crop/s);
assert.match(chromeAdapter?.notes || '', /微信验证.*QR code.*Pause for the user/s);
assert.match(chromeAdapter?.notes || '', /发表记录.*public article URL/s);
assert.match(chromeAdapter?.notes || '', /short-lived session tokens.*current dashboard/s);
});

test('regional social action shims expose Bilibili and Xiaohongshu custom controls', () => {
const axChrome = fs.readFileSync(path.join(ROOT, 'src/chrome/src/content/accessibility-tree.js'), 'utf8');
const axFirefox = fs.readFileSync(path.join(ROOT, 'src/firefox/src/content/accessibility-tree.js'), 'utf8');
Expand Down