dsh-log-contract 0.3.9 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1 -1
- package/lib/log-reader.js +49 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 日志契约守护(DSH session log contract guard)。
|
|
5
5
|
* 公开 API:离线体检 + 写前校验 + 修复 + 契约目录。
|
|
6
6
|
*/
|
|
7
|
-
export { loadSessionLog, tailSeq } from './log-reader.js';
|
|
7
|
+
export { loadSessionLog, tailSeq, readSessionHeader } from './log-reader.js';
|
|
8
8
|
export { validateSessionLog, resumeVerdict } from './validate.js';
|
|
9
9
|
export { createPreWriter, preWriterFromLog } from './prewrite.js';
|
|
10
10
|
export { repairSession, strictScanText, removeMarkersText, neutralizeMarkersText, clipCrossStepSourcesText, dropFailedTurnsText, trimLastMessagesText, trimLastMessagesByBudget, estimateTokensText, compactLastMessagesText, rebuildZstdText, tailRenumberText, neutralizeOrphanText, extractTurnText, keepRangesText } from './repair.js';
|
package/lib/log-reader.js
CHANGED
|
@@ -220,3 +220,52 @@ export function loadSessionLog(path) {
|
|
|
220
220
|
|
|
221
221
|
return { header, headerLine, rows, events, frameInfo };
|
|
222
222
|
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* 轻量读取会话文件 header(只解第一帧,不读全文件帧)。
|
|
226
|
+
*
|
|
227
|
+
* 帧布局:帧 1 = header 行(单行 JSON,~几百字节),帧 2+ = 事件流。
|
|
228
|
+
* 短码推导(工作区 createdAt 序号)需要扫全部会话但只需要 header——
|
|
229
|
+
* 读文件前缀 64KiB 足够覆盖完整帧 1,避免全量读大文件(opena 工作区
|
|
230
|
+
* ~108MiB 压缩)。失败返回 null(调用方降级)。
|
|
231
|
+
*
|
|
232
|
+
* @param {string} path 会话日志文件路径(.jsonl.zstd 或明文 .jsonl)。
|
|
233
|
+
* @returns {object|null} header 对象;无法解析返回 null。
|
|
234
|
+
*/
|
|
235
|
+
export function readSessionHeader(path) {
|
|
236
|
+
let head;
|
|
237
|
+
try {
|
|
238
|
+
const fd = fs.openSync(path, 'r');
|
|
239
|
+
const buf = Buffer.alloc(64 * 1024);
|
|
240
|
+
const n = fs.readSync(fd, buf, 0, buf.length, 0);
|
|
241
|
+
fs.closeSync(fd);
|
|
242
|
+
head = buf.subarray(0, n);
|
|
243
|
+
} catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
if (head.length < 4 || head.readUInt32LE(0) !== ZSTD_MAGIC) {
|
|
247
|
+
// 明文(无 zstd magic):直接取首行
|
|
248
|
+
try {
|
|
249
|
+
const line = head.toString('utf8').split('\n').find((l) => l.trim().length > 0);
|
|
250
|
+
return line ? JSON.parse(line) : null;
|
|
251
|
+
} catch {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const { frames } = scanZstdFrames(head);
|
|
256
|
+
if (frames.length === 0) return null;
|
|
257
|
+
const [s, e] = frames[0];
|
|
258
|
+
let plain;
|
|
259
|
+
try {
|
|
260
|
+
plain = zstdDecompressSync(head.subarray(s, e));
|
|
261
|
+
} catch {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const line = plain.toString('utf8').split('\n').find((l) => l.trim().length > 0);
|
|
265
|
+
if (!line) return null;
|
|
266
|
+
try {
|
|
267
|
+
return JSON.parse(line);
|
|
268
|
+
} catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-log-contract",
|
|
3
3
|
"description": "日志契约守护 — DSH session log contract guard: offline health check (CLI) + pre-write validation for DeepSeek Harness session logs",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.10",
|
|
5
5
|
"packageManager": "pnpm@11.7.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|