| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- #!/usr/bin/env node
- /**
- * 验收:容器是否**默认**自动上云(提示词不含任何上传暗示)
- *
- * 判定三条:
- * ① 回复里自动带出 https://s3.fmode.cn 链接
- * ② 成果表自动多一条记录
- * ③ 过程缓存没有被误传(成果数不应暴涨)
- */
- import { readFileSync } from 'node:fs';
- import { homedir } from 'node:os';
- import { join } from 'node:path';
- const F = 'https://server.fmode.cn/api/functions';
- const TARGET = 'agent-node-lj-test';
- const WAIT_MS = 420_000;
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const t = JSON.parse(readFileSync(join(homedir(), '.fmode/config/user.json'), 'utf8'))?.sessionToken;
- async function callFn(id, params) {
- const r = await fetch(F, { method: 'POST', headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ id, token: t, params }) });
- return r.json();
- }
- async function provision(id) {
- const j = await callFn('RP5Ht55NeX', { agentId: id });
- return j.result ?? j;
- }
- async function countDeliverables() {
- const d = await callFn('lfYlgU7SkK', { action: 'list', agentId: TARGET, limit: 200 });
- const list = d.deliverables ?? d.result?.deliverables ?? [];
- return list.length;
- }
- /* 🔴 全程不出现:上传 / 云盘 / S3 / 链接 / URL / 成果 / 分享 */
- const PROMPT = `帮我写一份这周的工作周报,用 Markdown,分成「本周完成」「下周计划」「风险」三块。`;
- async function main() {
- const before = await countDeliverables();
- console.log('测试前成果数:', before);
- const prov = await provision(TARGET);
- const agent = await provision(TARGET);
- const mx = await import('matrix-js-sdk');
- const c = mx.createClient({ baseUrl: prov.homeserver, accessToken: prov.accessToken, userId: prov.userMxId });
- const room = (await c.createRoom({ invite: [agent.agentMxId], name: `accept-${Date.now()}`, preset: mx.Preset.TrustedPrivateChat })).room_id;
- const hs = prov.homeserver.replace(/\/$/, '');
- const auth = { Authorization: `Bearer ${prov.accessToken}` };
- for (let i = 0; i < 30; i++) {
- await sleep(3000);
- const r = await fetch(`${hs}/_matrix/client/v3/rooms/${encodeURIComponent(room)}/joined_members`, { headers: auth }).catch(() => null);
- const j = r ? await r.json().catch(() => ({})) : {};
- if ((j.joined ?? {})[agent.agentMxId]) break;
- }
- console.log('\n=== 提示词(无任何上传暗示)===');
- console.log(PROMPT);
- const sent = await c.sendEvent(room, 'm.room.message', { msgtype: 'm.text', body: PROMPT, 'm.mentions': { user_ids: [agent.agentMxId] } });
- const seen = new Set([sent.event_id]);
- const deadline = Date.now() + WAIT_MS;
- const texts = [];
- let finished = false;
- while (Date.now() < deadline) {
- await sleep(8000);
- try {
- const r = await fetch(`${hs}/_matrix/client/v3/rooms/${encodeURIComponent(room)}/messages?dir=b&limit=50`, { headers: auth });
- const j = await r.json();
- let hasUrl = false;
- for (const ev of (j.chunk ?? []).reverse()) {
- if (ev.type !== 'm.room.message' || seen.has(ev.event_id) || ev.sender === prov.userMxId) continue;
- seen.add(ev.event_id);
- const b = String(ev.content?.body ?? '');
- texts.push(b);
- if (/https:\/\/s3\.fmode\.cn/.test(b)) hasUrl = true;
- }
- if (hasUrl) { finished = true; break; }
- } catch { /* 轮询抖动 */ }
- }
- const all = texts.join('\n');
- console.log('\n=== 最后一条正文 ===');
- const prose = texts.filter((b) => !/^[*·•]?\s*(🐍|💻|🔎|📖|✍️)/.test(b.trim()));
- console.log((prose[prose.length - 1] ?? '(无)').slice(0, 1500));
- await sleep(8000); // 等成果表写入
- const after = await countDeliverables();
- console.log('\n=== 验收判定 ===');
- const r1 = /https:\/\/s3\.fmode\.cn/.test(all);
- console.log(`① 回复自动带 https 链接 : ${r1 ? '✅ 是' : '❌ 否'}`);
- console.log(`② 成果表新增 : ${after - before} 条(${before} → ${after})${after > before ? '✅' : '❌'}`);
- console.log(`③ 未误传过程缓存 : ${after - before <= 2 ? '✅ 未暴涨' : `⚠️ 新增 ${after - before} 条,可能误传`}`);
- console.log(`④ 正文是否残留本地路径 : ${/\/opt\/data\//.test(prose.join('\n')) ? '⚠️ 是' : '✅ 否'}`);
- console.log(`\n总判定: ${r1 && after > before ? '✅ 通过 —— 默认上云已生效' : '❌ 未通过'}`);
- c.stopClient();
- }
- main().catch((e) => { console.error('失败:', e.message); process.exit(1); });
|