/** * 验证:App 真实会话发消息时,容器能否读到 threadRoot * * 背景:容器说 HERMES_SESSION_THREAD_ID 是空。 * 根因待查:App 的 sendReal 明明传了 sid 作为 threadRootId。 * * 本脚本在 App 里真实发一条消息,然后问容器那一回合读到的值。 */ import { chromium } from 'playwright'; import { mkdirSync } from 'node:fs'; import { resolve } from 'node:path'; import { loadDevLogin } from './dev-login.mjs'; const OUT = resolve('test-results/thread-check-20261110'); mkdirSync(OUT, { recursive: true }); const login = loadDevLogin(); if (!login.enabled) throw new Error(`开发态登录不可用:${login.reason}`); const b = await chromium.launch({ headless: true, channel: 'chromium' }); const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } }); const page = await ctx.newPage(); await page.addInitScript((d) => { localStorage.setItem('fmode_session_token', d.token); localStorage.setItem('fmode_me', JSON.stringify(d.me)); }, login.payload); /* 🔴 抓取 App 真正发出去的 m.room.message content —— 这是判定依据 */ let sentContent = null; page.on('request', (req) => { const u = req.url(); if (!u.includes('/send/m.room.message/')) return; try { sentContent = JSON.parse(req.postData() ?? '{}'); } catch { /* 忽略 */ } }); await page.goto('http://localhost:4200/desktop/chat', { waitUntil: 'domcontentloaded' }); await page.waitForTimeout(6000); /* 点开列表里第一个真实会话(按文本更稳,类名可能变) */ const byText = page.getByText(/写一份团队周报/).first(); if ((await byText.count()) > 0) { await byText.click({ timeout: 8000 }).catch(() => undefined); } else { const first = page.locator('.session-item').first(); if ((await first.count()) > 0) await first.click().catch(() => undefined); } await page.waitForTimeout(6000); const url = page.url(); const sessionId = decodeURIComponent(url.split('/').pop() ?? ''); console.log(`会话: ${sessionId}`); const ta = page.locator('textarea').first(); await ta.waitFor({ timeout: 15000 }); await ta.fill('请只回一句话:收到。不要调用任何工具。'); await ta.press('Enter'); await page.waitForTimeout(4000); if (sentContent) { const rel = sentContent['m.relates_to']; console.log('\n=== App 发出的 m.room.message content ==='); console.log(JSON.stringify(sentContent, null, 2).slice(0, 800)); console.log(`\n是否带 m.relates_to: ${rel ? '✅ 有' : '❌ 没有'}`); if (rel) console.log(` rel_type = ${rel.rel_type}`); if (rel) console.log(` event_id = ${rel.event_id}`); console.log(` 与当前会话 id 一致: ${rel?.event_id === sessionId ? '✅' : `❌ (${rel?.event_id} vs ${sessionId})`}`); } else { console.log('❌ 没抓到发送请求'); } await page.screenshot({ path: `${OUT}/01-sent.png` }); await ctx.close(); await b.close();