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 分钟超时,用户零感知)
35 lines
2.6 KiB
JavaScript
35 lines
2.6 KiB
JavaScript
const list = await fetch('http://localhost:9223/json').then((r) => r.json());
|
|
const page = list.find((t) => t.type === 'page' && t.url.includes('#/rewrites'));
|
|
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, 200) }; return r.result.value; };
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
await send('Page.enable'); await send('Runtime.enable');
|
|
// 弹窗可能还在(上轮遗留),先清理再开
|
|
await ev(`document.querySelectorAll('.modal-mask').forEach((m) => m.remove()); document.querySelector('[data-detail]') && document.querySelector('[data-detail]').click()`);
|
|
await sleep(1500);
|
|
const rect = await ev(`(() => {
|
|
const ai = [...document.querySelectorAll('.rw-stack > .rw-sec')].find((s) => s.querySelector('.rw-sec-head')?.textContent === 'AI脚本');
|
|
if (!ai) return null;
|
|
const r = ai.querySelector('.rw-sec-body').getBoundingClientRect();
|
|
return { x: Math.round(r.left + r.width / 2), y: Math.round(r.top + 300) };
|
|
})()`);
|
|
console.log('rect:', JSON.stringify(rect));
|
|
for (let i = 0; i < 5; i++) {
|
|
await send('Input.dispatchMouseEvent', { type: 'mouseWheel', x: rect.x, y: rect.y, deltaX: 0, deltaY: 400 });
|
|
await sleep(80);
|
|
}
|
|
await sleep(400);
|
|
const st = await ev(`(() => {
|
|
const secs = [...document.querySelectorAll('.rw-stack > .rw-sec')];
|
|
const aiBody = secs.find((s) => s.querySelector('.rw-sec-head')?.textContent === 'AI脚本').querySelector('.rw-sec-body');
|
|
const sbBody = secs.find((s) => s.querySelector('.rw-sec-head')?.textContent === 'AI分镜提示词').querySelector('.rw-sec-body');
|
|
const vis = [...sbBody.querySelectorAll('.sb-block')].find((b) => b.getBoundingClientRect().top >= sbBody.getBoundingClientRect().top - 2);
|
|
return { aiScrollTop: Math.round(aiBody.scrollTop), sbScrollTop: Math.round(sbBody.scrollTop), sbVis: vis ? (vis.querySelector('.sb-head')?.textContent.trim() || '').slice(0, 28) : null };
|
|
})()`);
|
|
console.log('滚轮后:', JSON.stringify(st));
|
|
process.exit(0);
|