1. 目录 mcn-work-shop -> mcn-workshop(空间分组名取会话 cwd 的目录名,只改字符串无效,必须真改名) 2. 全仓替换 mcn-work-shop -> mcn-workshop:37 文件 121 处;历史日志按沿革句规矩保留当时目录名 3. 任务进度可见:/api/run/status 产出 已运行时长/工具调用/最近动作/停滞判定(读会话日志尾部),前端新增右下角常驻面板,四处任务入口接入 4. 会话归属目录配置化:新增 config.sessionCwd(留空=工作台自身目录),现指向 D://AI技能//mcn-workshop,使任务显示为命名分组而非「未分组任务」 5. 修前端轮询静默缺陷:连续 3 次查询失败即提示服务断开(原逻辑静默空转到 15 分钟超时,用户零感知)
77 lines
4.2 KiB
JavaScript
77 lines
4.2 KiB
JavaScript
// 验证:①展开源脚本按钮移到 AI脚本 标题右侧(间隔 10px)②弹窗最大宽度 1400→1600
|
|
const list = await fetch('http://localhost:9223/json').then((r) => r.json());
|
|
let page = list.find((t) => t.type === 'page' && t.url.includes('localhost:8899'));
|
|
if (!page) { console.log('ERR: no workbuddy page'); process.exit(1); }
|
|
const ws = new WebSocket(page.webSocketDebuggerUrl);
|
|
let id = 0; const pending = new Map();
|
|
const send = (method, params = {}) => new Promise((res, rej) => { const i = ++id; pending.set(i, { res, rej }); ws.send(JSON.stringify({ id: i, method, params })); });
|
|
ws.onmessage = (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { const p = pending.get(m.id); pending.delete(m.id); m.error ? p.rej(new Error(m.error.message)) : p.res(m.result); } };
|
|
await new Promise((r) => (ws.onopen = r));
|
|
const ev = async (expr) => { const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true }); if (r.exceptionDetails) return { __err: (r.exceptionDetails.exception?.description || r.exceptionDetails.text).slice(0, 300) }; return r.result.value; };
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
await send('Page.enable'); await send('Runtime.enable');
|
|
|
|
if (!page.url.includes('#/rewrites')) {
|
|
await send('Page.navigate', { url: 'http://localhost:8899/#/rewrites' });
|
|
await sleep(2000);
|
|
}
|
|
await send('Page.reload', { ignoreCache: true });
|
|
await sleep(3000);
|
|
|
|
// 打开第一条改写的查看弹窗
|
|
await ev(`(() => { const b = document.querySelector('[data-detail]'); if (!b) return 'no-detail-btn'; b.click(); return 'opened'; })()`);
|
|
await sleep(2500);
|
|
|
|
// ① 按钮位置:应在 AI脚本 .rw-sec-head 内,与「AI脚本」文字间隔 10px
|
|
const pos = await ev(`(() => {
|
|
const head = [...document.querySelectorAll('.rw-sec-head')].find((h) => h.textContent.trim().startsWith('AI脚本'));
|
|
if (!head) return { err: 'no AI脚本 head' };
|
|
const btn = head.querySelector('[data-src-toggle]');
|
|
if (!btn) return { err: 'no toggle in AI head' };
|
|
const textNode = [...head.childNodes].find((n) => n.nodeType === 3 && n.textContent.includes('AI脚本'));
|
|
const range = document.createRange();
|
|
range.selectNodeContents(textNode);
|
|
const textRect = range.getBoundingClientRect();
|
|
const btnRect = btn.getBoundingClientRect();
|
|
// 文字右缘 → 按钮左缘 的水平距离(同一行)
|
|
const gap = btnRect.left - textRect.right;
|
|
// 顶部标题行不应再有 toggle
|
|
const titleRowHasToggle = !!document.querySelector('.modal-title-row [data-src-toggle]');
|
|
return {
|
|
inAiHead: true,
|
|
gap: Math.round(gap * 100) / 100,
|
|
btnTitle: btn.title,
|
|
verticalAligned: Math.abs(btnRect.top - textRect.top) < 4,
|
|
titleRowHasToggle,
|
|
};
|
|
})()`);
|
|
console.log('① 按钮位置:', JSON.stringify(pos));
|
|
|
|
// ② 点击按钮 → 源脚本列展开
|
|
await ev(`(() => { const b = document.querySelector('[data-src-toggle]'); b.click(); return 'toggled'; })()`);
|
|
await sleep(600);
|
|
const expanded = await ev(`(() => {
|
|
const srcSec = document.querySelector('[data-src-sec]');
|
|
const toggle = document.querySelector('[data-src-toggle]');
|
|
return { srcVisible: srcSec && getComputedStyle(srcSec).display !== 'none', toggleTitle: toggle ? toggle.title : null };
|
|
})()`);
|
|
console.log('② 点击后展开源脚本:', JSON.stringify(expanded));
|
|
await ev(`(() => { const b = document.querySelector('[data-src-toggle]'); b.click(); return 'toggled-back'; })()`);
|
|
await sleep(500);
|
|
|
|
// ③ 弹窗宽度:多视口验证 1600 封顶
|
|
const widthAt = async (vw) => {
|
|
await send('Emulation.setDeviceMetricsOverride', { width: vw, height: 900, deviceScaleFactor: 1, mobile: false });
|
|
await sleep(500);
|
|
return ev(`(() => { const m = document.querySelector('.rw-modal'); if (!m) return null; const r = m.getBoundingClientRect(); return { vw: window.innerWidth, w: Math.round(r.width), left: Math.round(r.left), right: Math.round(window.innerWidth - r.right) }; })()`);
|
|
};
|
|
const w1200 = await widthAt(1200);
|
|
const w1500 = await widthAt(1500);
|
|
const w1700 = await widthAt(1700);
|
|
const w2000 = await widthAt(2000);
|
|
console.log('③ 弹窗宽度:', JSON.stringify({ w1200, w1500, w1700, w2000 }));
|
|
await send('Emulation.clearDeviceMetricsOverride');
|
|
|
|
ws.close();
|
|
console.log('DONE');
|