@max-null/dsh-memory 0.9.2 → 0.11.0
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/README.md +25 -2
- package/dist/engine.d.ts +112 -0
- package/dist/engine.js +334 -96
- package/dist/index.js +48 -1
- package/dist/injection.d.ts +30 -0
- package/dist/injection.js +56 -1
- package/dist/self.js +4 -1
- package/package.json +5 -2
- package/scripts/ancestor-probe.mjs +415 -0
- package/scripts/scan-orphans.mjs +110 -0
- package/scripts/unzstd-frames.mjs +90 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 多帧 zstd 解压——读 DSH 会话日志的必经一步。
|
|
4
|
+
*
|
|
5
|
+
* **为什么需要它**:DSH 的会话日志(`session.v3.jsonl.zstd`)不是单个 zstd 流,而是
|
|
6
|
+
* **多个独立帧拼接**的结果(一段事件写一帧)。`zlib.zstdDecompressSync()` 只解**第一帧**
|
|
7
|
+
* 就返回——于是 1.9 MB 的日志读出来只有头一行,看起来像「日志是空的」,极易误判。
|
|
8
|
+
* Node 的 zstd 绑定没有暴露「解全部帧」的选项,所以只能自己切帧。
|
|
9
|
+
*
|
|
10
|
+
* **能回答什么**:把 `*.jsonl.zstd` 还原成完整 jsonl 文本,交给后续分析——事件普查、
|
|
11
|
+
* 找某次工具调用、统计 token 压力、解剖一个会话到底做了什么。
|
|
12
|
+
*
|
|
13
|
+
* **判据怎么算**:zstd 帧的 magic number 是 `28 B5 2F FD`(小端);扫描它在文件中的
|
|
14
|
+
* 全部出现位置即为候选帧边界,再逐帧解压。输出行的三个数就是判据:
|
|
15
|
+
* `frames`(切出几帧)、`ok`(解出几帧)、`failed`(几帧失败)。**failed > 0 说明切帧
|
|
16
|
+
* 切错了**——多半是压缩数据内部恰好出现了那 4 个字节(magic 扫描法的已知局限)。
|
|
17
|
+
*
|
|
18
|
+
* **哪些情况答不了**:
|
|
19
|
+
* - 逐字节扫描 magic 会有**假阳性**。feral > 0 时真帧通常仍能解出,但**不保证完整**;
|
|
20
|
+
* 要 100% 可靠需解析 zstd 帧头(`Frame_Header_Descriptor` 的长度字段),本脚本没做到。
|
|
21
|
+
* - 只做**解压**,不解析 jsonl 语义——事件类型、token 统计属于调用方。
|
|
22
|
+
* - **明文 jsonl 不需要它**:DSH 从 GUI 导出的会话就是明文(`session.v3.jsonl`),
|
|
23
|
+
* 直接 `readFileSync` 即可,别绕这一道。
|
|
24
|
+
*
|
|
25
|
+
* 用法:
|
|
26
|
+
* node scripts/unzstd-frames.mjs <源 .zstd> <目标 .jsonl>
|
|
27
|
+
* node scripts/unzstd-frames.mjs --help
|
|
28
|
+
*
|
|
29
|
+
* 退出码:0 = 全部帧解出;1 = 有帧失败(结果可能不完整);2 = 用法错误。
|
|
30
|
+
*/
|
|
31
|
+
import fs from 'node:fs'
|
|
32
|
+
import zlib from 'node:zlib'
|
|
33
|
+
|
|
34
|
+
const USAGE = `多帧 zstd 解压——读 DSH 会话日志的必经一步。
|
|
35
|
+
|
|
36
|
+
用法:
|
|
37
|
+
node scripts/unzstd-frames.mjs <源 .zstd> <目标 .jsonl>
|
|
38
|
+
node scripts/unzstd-frames.mjs --help
|
|
39
|
+
|
|
40
|
+
退出码:0 = 全部帧解出;1 = 有帧失败(结果可能不完整);2 = 用法错误。`
|
|
41
|
+
|
|
42
|
+
const args = process.argv.slice(2)
|
|
43
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
44
|
+
console.log(USAGE)
|
|
45
|
+
process.exit(0)
|
|
46
|
+
}
|
|
47
|
+
if (args.length < 2) {
|
|
48
|
+
console.error(USAGE)
|
|
49
|
+
process.exit(2)
|
|
50
|
+
}
|
|
51
|
+
const [src, dst] = args
|
|
52
|
+
if (!fs.existsSync(src)) {
|
|
53
|
+
console.error(`源文件不存在:${src}`)
|
|
54
|
+
process.exit(2)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const buf = fs.readFileSync(src)
|
|
58
|
+
const MAGIC = [0x28, 0xb5, 0x2f, 0xfd] // zstd frame magic(小端)
|
|
59
|
+
const positions = []
|
|
60
|
+
for (let i = 0; i + 3 < buf.length; i++) {
|
|
61
|
+
if (buf[i] === MAGIC[0] && buf[i + 1] === MAGIC[1] && buf[i + 2] === MAGIC[2] && buf[i + 3] === MAGIC[3]) {
|
|
62
|
+
positions.push(i)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
positions.push(buf.length) // 末帧以文件长度收尾
|
|
66
|
+
|
|
67
|
+
const parts = []
|
|
68
|
+
let ok = 0
|
|
69
|
+
let failed = 0
|
|
70
|
+
for (let i = 0; i + 1 < positions.length; i++) {
|
|
71
|
+
const slice = buf.subarray(positions[i], positions[i + 1])
|
|
72
|
+
try {
|
|
73
|
+
parts.push(zlib.zstdDecompressSync(slice))
|
|
74
|
+
ok += 1
|
|
75
|
+
} catch (error) {
|
|
76
|
+
// 不在这里尝试 stream 容错:`createZstdDecompress()` 是异步的,在同步块里 end() 之后
|
|
77
|
+
// 立刻取 chunks 必然拿不到数据。宁可如实报告失败,也不给一个看似成功的空结果。
|
|
78
|
+
failed += 1
|
|
79
|
+
console.error(` 帧 ${i}(偏移 ${positions[i]})解压失败:${error instanceof Error ? error.message : String(error)}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const out = Buffer.concat(parts)
|
|
84
|
+
fs.writeFileSync(dst, out)
|
|
85
|
+
console.log(`frames=${positions.length - 1} ok=${ok} failed=${failed}`)
|
|
86
|
+
console.log(`输出 ${out.length} 字节 → ${dst}`)
|
|
87
|
+
if (failed > 0) {
|
|
88
|
+
console.error('⚠️ 有帧未解出,结果可能不完整(magic 扫描法的已知局限,见脚本头部注释)')
|
|
89
|
+
process.exit(1)
|
|
90
|
+
}
|