/** 批量列出会话档位:id / 创建时间 / preset / sandbox mode / approval / turn 数 */ * 会话取证 · 批量对比各会话 preset/sandbox/approval(定位"老会话档位未跟随平台默认"的关键工具) import { readFileSync } from 'node:fs' import { zstdDecompressSync } from 'node:zlib' const MAGIC = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]) const t = (ms) => new Date(Number(ms)).toLocaleString('zh-CN', { hour12: false, timeZone: 'Asia/Shanghai' }) for (const file of process.argv.slice(2)) { const raw = readFileSync(file) const offs = [] for (let i = 0; i + 4 <= raw.length; i++) if (raw.compare(MAGIC, 0, 4, i, i + 4) === 0) offs.push(i) let text = '' for (let f = 0; f < (offs.length ? offs : [0]).length; f++) { const s = offs[f], e = f + 1 < offs.length ? offs[f + 1] : raw.length try { text += zstdDecompressSync(raw.subarray(s, e)).toString('utf8') } catch {} } const evs = [] for (const l of text.split('\n')) { if (!l.trim()) continue; try { evs.push(JSON.parse(l)) } catch {} } const meta = evs.find((e) => e.type === 'session') const uniq = (ty, f) => [...new Set(evs.filter((e) => e.type === ty).map(f))].join(',') const tl = text.match(/"text":"([^"]{0,60})"/g)?.slice(0, 1)?.join('') ?? '' console.log( '%s | 创建 %s | preset=%s | sandbox=%s | approval=%s | turns=%d | %d 事件', (meta?.id ?? '?').slice(-12), t(meta?.createdAt), uniq('permission/preset', (e) => e.data?.preset), uniq('sandbox/mode', (e) => e.data?.mode), uniq('approval/policy', (e) => e.data?.policy), evs.filter((e) => e.type === 'turn/start').length, evs.length, ) }