test(webui): 全流程演练的两处判据修正(同主题请求的定位、工作区目录)
第三次跑通 **37/37(0 失败 0 无法判定)**,含真 Agent 闭环:写信带附件 →
pi 请求 bash 授权 → **在界面点同意** → 决策落库 → pi 回信把附件原样带回
(sha256 一致)→ 回信出现在收件箱。
两处都是**判据/前置条件**的问题,不是产品缺陷,但都会伪装成产品故障:
1. 授权页上同一 Agent 的请求主题**一模一样**("是否允许执行 bash?")。原先按主题
`.first()` 选行,于是点到了**别的会话那条旧请求**上 —— 网关回 `expired` 警告,
界面看起来"点了但没生效"。现在按**本轮会话别名**定位分组容器
(`header.locator('xpath=..')`,DOM 探针确认头与请求行同容器),且**只在折叠时**
才点头按钮(已展开时再点会把它折起来,那正是第二次又落到别人行上的原因)。
2. **工作区寻址里的 path 必须是已存在的目录**,否则桥按设计回退到自己的兜底目录
(`~/.pi/mail-sessions/<会话>`),产物就落在别处而不是我指定的目录。脚本现在
先 mkdir —— zcode 那次也栽在同一条规则上。
顺带记录一个**产品层面值得决策**的现象:pi 的 worker 池上限是 3,而**"等人点头"的
worker 占着池子**。我上一轮的误点让 3 个 worker 全卡在等决策上 → 池满 → 新邮件排队
(设计如此:满载排队不丢信),于是我 300s 等不到回信。清掉卡住的请求后队列**立即
排空**、排队那封信被取出并起了一轮。也就是说:人在开会时,同一个 Agent 接不了新活。
是否把等待授权的 worker 挪出池子(或单独给额度),需要你定。
This commit is contained in:
@ -213,6 +213,10 @@ try {
|
||||
if (composeOpened && composeText.includes('新建邮件')) {
|
||||
pass('写信页打开', '看到「新建邮件」');
|
||||
const sessionPath = `/root/gotmp/webui-full-flow/${MARK}.new`;
|
||||
// ★ 先建目录:工作区寻址里的 path **必须是已存在的目录**,否则桥按设计回退到
|
||||
// 自己的兜底目录(`~/.pi/mail-sessions/<会话>`),产物就落在别处 ——
|
||||
// 实测撞过两次(zcode 一次、pi 一次),脚本这边必须先建。
|
||||
mkdirSync(`/root/gotmp/webui-full-flow/${MARK}`, { recursive: true });
|
||||
await page.locator('input[placeholder*="@"]').first().fill(`${AGENT}@${sessionPath}`);
|
||||
await page.locator('input[placeholder*="特性"], input[placeholder*="分支"]').first().fill(`全流程演练 ${MARK}`).catch(() => {});
|
||||
await page.locator('textarea').first().fill(`这是全流程演练 ${MARK}。请回信并**原样附回**我发的附件。`);
|
||||
@ -248,6 +252,13 @@ try {
|
||||
console.log('\n— E. Agent 闭环(权限请求 → 批准 → 回传附件,最多 300s)—');
|
||||
const mine = (sent.body?.mails || []).find(m => String(m.subject || '').includes(MARK));
|
||||
const sid = mine?.session_id;
|
||||
// 本轮会话别名:授权页上用它把"点哪条请求"限定到这一轮(同主题的旧请求太多)
|
||||
let sessionAlias = '';
|
||||
if (sid) {
|
||||
const sess = await api(`/api/v1/sessions/${sid}`, {}, adminKey).catch(() => ({ body: {} }));
|
||||
sessionAlias = String(sess.body?.session?.session_alias || sess.body?.session_alias || '').trim();
|
||||
if (sessionAlias) console.log(` · 本轮会话别名:${sessionAlias}`);
|
||||
}
|
||||
if (!sid) {
|
||||
undec('Agent 闭环', '发件箱里没找到刚发出的那封(拿不到会话 id)');
|
||||
} else {
|
||||
@ -280,11 +291,33 @@ try {
|
||||
await page.locator('text=授权').first().click().catch(() => {});
|
||||
});
|
||||
await page.waitForTimeout(2000);
|
||||
// ★ 必须**限定到本轮会话**再点。
|
||||
// 授权页上同一 Agent 的请求主题常常一模一样("是否允许执行 bash?"),
|
||||
// 点开本轮那条请求。
|
||||
// 授权页上同一 Agent 的请求主题一模一样("是否允许执行 bash?"),所以必须
|
||||
// **限定到本轮会话的容器里**再点:按主题 .first() 会点到别的会话那条(多半早已
|
||||
// 过期)——症状是"点了、但库里没有这条的决策结果"(网关回的是 expired 警告)。
|
||||
const reqText = String(perm.subject || '').replace(/^权限请求:\s*/, '').slice(0, 12);
|
||||
const rowById = page.locator(`text=${String(perm.subject || '').slice(0, 18)}`).first();
|
||||
const rowByText = page.locator(`text=${reqText}`).first();
|
||||
if ((await rowById.count()) > 0) await rowById.click().catch(() => {});
|
||||
else await rowByText.click().catch(() => {});
|
||||
const header = page.locator(`button:has-text("${sessionAlias}")`).first();
|
||||
let clickedRow = false;
|
||||
if (sessionAlias && (await header.count()) > 0) {
|
||||
// 分组容器 = 头按钮的父节点(DOM 里头与请求行同容器,探针确认过)
|
||||
const group = header.locator('xpath=..');
|
||||
const rows = group.locator('button').filter({ hasText: '权限请求' });
|
||||
const visible = (await rows.count()) > 0 && (await rows.first().isVisible().catch(() => false));
|
||||
if (!visible) {
|
||||
// 只有折叠状态才点开;已经展开时再点会把它折起来(我踩过:于是又落到别人的行上)
|
||||
await header.click().catch(() => {});
|
||||
await page.waitForTimeout(700);
|
||||
}
|
||||
if ((await rows.count()) > 0) {
|
||||
clickedRow = await rows.first().click().then(() => true).catch(() => false);
|
||||
}
|
||||
}
|
||||
if (!clickedRow) {
|
||||
const byText = page.locator(`text=${reqText}`).first();
|
||||
if ((await byText.count()) > 0) await byText.click().catch(() => {});
|
||||
}
|
||||
await page.waitForTimeout(2000);
|
||||
await shot('44-permission-detail');
|
||||
// ★ 决策按钮必须用**精确文本**匹配。
|
||||
|
||||
Reference in New Issue
Block a user