lightclawbot 1.0.7 → 1.0.8
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 +47 -213
- package/dist/src/config.d.ts +5 -5
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +5 -5
- package/dist/src/config.js.map +1 -1
- package/dist/src/download-tool.d.ts +1 -1
- package/dist/src/download-tool.js +9 -9
- package/dist/src/download-tool.js.map +1 -1
- package/dist/src/file-storage.d.ts +9 -9
- package/dist/src/file-storage.d.ts.map +1 -1
- package/dist/src/file-storage.js +10 -10
- package/dist/src/file-storage.js.map +1 -1
- package/dist/src/format-urls.d.ts +5 -5
- package/dist/src/format-urls.js +8 -8
- package/dist/src/format-urls.js.map +1 -1
- package/dist/src/gateway.js +3 -3
- package/dist/src/gateway.js.map +1 -1
- package/dist/src/inbound.d.ts.map +1 -1
- package/dist/src/inbound.js +17 -18
- package/dist/src/inbound.js.map +1 -1
- package/dist/src/socket/handlers.d.ts +26 -0
- package/dist/src/socket/handlers.d.ts.map +1 -0
- package/dist/src/socket/handlers.js +130 -0
- package/dist/src/socket/handlers.js.map +1 -0
- package/dist/src/socket/index.d.ts +11 -0
- package/dist/src/socket/index.d.ts.map +1 -0
- package/dist/src/socket/index.js +9 -0
- package/dist/src/socket/index.js.map +1 -0
- package/dist/src/socket/registry.d.ts +59 -0
- package/dist/src/socket/registry.d.ts.map +1 -0
- package/dist/src/socket/registry.js +125 -0
- package/dist/src/socket/registry.js.map +1 -0
- package/dist/src/socket/reliable-emitter.d.ts +79 -0
- package/dist/src/socket/reliable-emitter.d.ts.map +1 -0
- package/dist/src/socket/reliable-emitter.js +213 -0
- package/dist/src/socket/reliable-emitter.js.map +1 -0
- package/dist/src/types.d.ts +2 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/upload-tool.d.ts +1 -1
- package/dist/src/upload-tool.js +3 -3
- package/dist/src/upload-tool.js.map +1 -1
- package/package.json +1 -1
- package/skills/lightclaw-media/SKILL.md +22 -102
- package/dist/public/data/scripts/manifest.json +0 -11
- package/dist/public/data/scripts/upgrade.211d7e4c.sh +0 -266
- package/dist/public/data/scripts/upgrade.sh +0 -266
- package/dist/src/session-history.d.ts +0 -88
- package/dist/src/session-history.d.ts.map +0 -1
- package/dist/src/session-history.js +0 -598
- package/dist/src/session-history.js.map +0 -1
- package/dist/src/streaming/delta-tracker.d.ts +0 -34
- package/dist/src/streaming/delta-tracker.d.ts.map +0 -1
- package/dist/src/streaming/delta-tracker.js +0 -145
- package/dist/src/streaming/delta-tracker.js.map +0 -1
- package/dist/src/streaming/index.d.ts +0 -12
- package/dist/src/streaming/index.d.ts.map +0 -1
- package/dist/src/streaming/index.js +0 -13
- package/dist/src/streaming/index.js.map +0 -1
- package/dist/src/streaming/stream-reply-sink.d.ts +0 -59
- package/dist/src/streaming/stream-reply-sink.d.ts.map +0 -1
- package/dist/src/streaming/stream-reply-sink.js +0 -293
- package/dist/src/streaming/stream-reply-sink.js.map +0 -1
- package/dist/src/streaming/types.d.ts +0 -45
- package/dist/src/streaming/types.d.ts.map +0 -1
- package/dist/src/streaming/types.js +0 -7
- package/dist/src/streaming/types.js.map +0 -1
|
@@ -1,598 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LightClaw — Session History Reader
|
|
3
|
-
*
|
|
4
|
-
* 直接读取 OpenClaw Gateway 的 JSONL session 文件,获取持久化的对话历史。
|
|
5
|
-
* 文件路径: ~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl
|
|
6
|
-
*
|
|
7
|
-
* JSONL 每行格式:
|
|
8
|
-
* { "type": "session", ... } ← session header (第一行)
|
|
9
|
-
* { "type": "message", "message": { ... }} ← 对话消息
|
|
10
|
-
* { "type": "compaction", ... } ← 上下文压缩标记
|
|
11
|
-
* { "type": "model_change", ... } ← 模型切换(跳过)
|
|
12
|
-
* { "type": "thinking_level_change", ... } ← 思考级别变更(跳过)
|
|
13
|
-
* { "type": "custom", ... } ← 自定义元数据(跳过)
|
|
14
|
-
*/
|
|
15
|
-
import fs from "node:fs";
|
|
16
|
-
import os from "node:os";
|
|
17
|
-
import path from "node:path";
|
|
18
|
-
// ============================================================
|
|
19
|
-
// 路径解析
|
|
20
|
-
// ============================================================
|
|
21
|
-
function resolveOpenClawHome() {
|
|
22
|
-
return process.env.OPENCLAW_HOME || path.join(os.homedir(), ".openclaw");
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* 解析 agentId 对应的 sessions 目录
|
|
26
|
-
* 默认 agentId 为 "main"(与 OpenClaw DEFAULT_AGENT_ID 一致)
|
|
27
|
-
*/
|
|
28
|
-
function resolveSessionsDir(agentId) {
|
|
29
|
-
const home = resolveOpenClawHome();
|
|
30
|
-
const id = agentId?.trim() || "main";
|
|
31
|
-
return path.join(home, "agents", id, "sessions");
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* 加载 sessions.json 索引,获取 sessionKey → sessionEntry 映射
|
|
35
|
-
*/
|
|
36
|
-
function loadSessionStore(agentId) {
|
|
37
|
-
const storePath = path.join(resolveSessionsDir(agentId), "sessions.json");
|
|
38
|
-
try {
|
|
39
|
-
const raw = fs.readFileSync(storePath, "utf-8");
|
|
40
|
-
if (!raw.trim())
|
|
41
|
-
return {};
|
|
42
|
-
const parsed = JSON.parse(raw);
|
|
43
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
44
|
-
return parsed;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
// 文件不存在或解析失败
|
|
49
|
-
}
|
|
50
|
-
return {};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* 根据 sessionKey 找到对应的 .jsonl transcript 文件路径
|
|
54
|
-
*/
|
|
55
|
-
export function resolveTranscriptPath(sessionKey, agentId) {
|
|
56
|
-
const store = loadSessionStore(agentId);
|
|
57
|
-
const normalizedKey = sessionKey.trim().toLowerCase();
|
|
58
|
-
// 尝试精确匹配和 case-insensitive 匹配
|
|
59
|
-
const entry = store[normalizedKey]
|
|
60
|
-
?? store[sessionKey]
|
|
61
|
-
?? Object.entries(store).find(([k]) => k.toLowerCase() === normalizedKey)?.[1];
|
|
62
|
-
if (!entry?.sessionId)
|
|
63
|
-
return null;
|
|
64
|
-
const sessionsDir = resolveSessionsDir(agentId);
|
|
65
|
-
// 优先使用 entry.sessionFile(如果指定了自定义路径)
|
|
66
|
-
if (entry.sessionFile) {
|
|
67
|
-
const sessionFilePath = path.isAbsolute(entry.sessionFile)
|
|
68
|
-
? entry.sessionFile
|
|
69
|
-
: path.join(sessionsDir, entry.sessionFile);
|
|
70
|
-
if (fs.existsSync(sessionFilePath))
|
|
71
|
-
return sessionFilePath;
|
|
72
|
-
}
|
|
73
|
-
// 默认路径: <sessionsDir>/<sessionId>.jsonl
|
|
74
|
-
const defaultPath = path.join(sessionsDir, `${entry.sessionId}.jsonl`);
|
|
75
|
-
if (fs.existsSync(defaultPath))
|
|
76
|
-
return defaultPath;
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
// ============================================================
|
|
80
|
-
// 传输元数据剥离
|
|
81
|
-
// ============================================================
|
|
82
|
-
/**
|
|
83
|
-
* 剥离 OpenClaw 传输层注入到用户消息中的元数据前缀,提取用户真正的输入。
|
|
84
|
-
*
|
|
85
|
-
* 采用 **双层策略** 以通用应对不断变化的注入格式:
|
|
86
|
-
*
|
|
87
|
-
* **第一层 — 锚点截断(优先):**
|
|
88
|
-
* OpenClaw 注入的元数据遵循固定尾部结构:最后一个 `Xxx (untrusted metadata):` 块
|
|
89
|
-
* 之后即为用户真正输入。找到该锚点并截断,天然兼容前方任意 operator 前缀。
|
|
90
|
-
*
|
|
91
|
-
* **第二层 — 逐条正则剥离(后备):**
|
|
92
|
-
* 当消息中不含 `(untrusted metadata)` 锚点时(如纯系统消息),回退到模式匹配:
|
|
93
|
-
* - [media attached: ... ] 行
|
|
94
|
-
* - To send an image back, ... 提示行
|
|
95
|
-
* - Xxx (untrusted metadata): ```json ... ``` 块(通配所有类型)
|
|
96
|
-
* - Xxx (operator configured): 编号列表块(通配所有类型)
|
|
97
|
-
* - HEARTBEAT_OK 行
|
|
98
|
-
* - System: [...] 异步任务完成回调通知行
|
|
99
|
-
* - 用户发送了文件: ... 描述文本(含内联 <file>...</file> 标签)
|
|
100
|
-
*/
|
|
101
|
-
function stripTransportMetadata(text) {
|
|
102
|
-
if (!text)
|
|
103
|
-
return text;
|
|
104
|
-
// ── 第一层:锚点截断 ──
|
|
105
|
-
// OpenClaw 传输层注入的元数据遵循固定结构:
|
|
106
|
-
// [各种 operator/system 前缀块...]
|
|
107
|
-
// Sender (untrusted metadata):
|
|
108
|
-
// ```json
|
|
109
|
-
// { ... }
|
|
110
|
-
// ```
|
|
111
|
-
// <用户真正的输入>
|
|
112
|
-
//
|
|
113
|
-
// "Sender (untrusted metadata)" 是 OpenClaw 注入的最后一个标准元数据块。
|
|
114
|
-
// 策略:找到最后一个 ```json ... ``` 代码块的结尾位置(后面跟着的就是用户输入),
|
|
115
|
-
// 但仅在前文中确实存在 "(untrusted metadata)" 标记时才执行截断,避免误伤。
|
|
116
|
-
const hasUntrustedMeta = text.includes("(untrusted metadata)");
|
|
117
|
-
if (hasUntrustedMeta) {
|
|
118
|
-
// 匹配所有 Xxx (untrusted metadata): ```json {...} ``` 块,
|
|
119
|
-
// 取最后一个匹配的结束位置作为截断点
|
|
120
|
-
const metaBlockRe = /\w[\w ]*\(untrusted metadata\):\s*```json\s*\{[^}]*\}\s*```/gs;
|
|
121
|
-
let lastEnd = -1;
|
|
122
|
-
let m;
|
|
123
|
-
while ((m = metaBlockRe.exec(text)) !== null) {
|
|
124
|
-
lastEnd = m.index + m[0].length;
|
|
125
|
-
}
|
|
126
|
-
if (lastEnd > 0 && lastEnd < text.length) {
|
|
127
|
-
// 截断:只保留最后一个 metadata 块之后的内容
|
|
128
|
-
const userPart = text.slice(lastEnd).replace(/^\s+/, "");
|
|
129
|
-
if (userPart) {
|
|
130
|
-
// 截断成功,对剩余部分做第二层清理后返回
|
|
131
|
-
return stripResidualMetadata(userPart);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// ── 第二层(后备):逐条正则剥离 ──
|
|
136
|
-
// 当锚点截断不适用(如消息中不含 untrusted metadata 块)时,
|
|
137
|
-
// 回退到逐条剥离已知模式。
|
|
138
|
-
return stripResidualMetadata(text);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* 剥离残留的传输层元数据片段。
|
|
142
|
-
*
|
|
143
|
-
* 用于:
|
|
144
|
-
* 1. 锚点截断后的残余清理
|
|
145
|
-
* 2. 不含 untrusted metadata 的消息的后备剥离
|
|
146
|
-
*/
|
|
147
|
-
function stripResidualMetadata(text) {
|
|
148
|
-
if (!text)
|
|
149
|
-
return text;
|
|
150
|
-
let result = text;
|
|
151
|
-
// 移除 [media attached: ...] 行
|
|
152
|
-
result = result.replace(/^\[media attached:.*?\]\s*$/gm, "");
|
|
153
|
-
// 移除 "To send an image back, ..." 指令块(可能跨多行直到空行)
|
|
154
|
-
result = result.replace(/^To send an image back,.*?(?:Keep caption in the text body\.)\s*/gms, "");
|
|
155
|
-
// 移除 Xxx (untrusted metadata): ```json ... ``` 块(通用模式,匹配所有 untrusted metadata 块)
|
|
156
|
-
result = result.replace(/^\w[\w ]*\(untrusted metadata\):\s*```json\s*\{[^}]*\}\s*```\s*/gms, "");
|
|
157
|
-
// 移除 Xxx (operator configured): 后跟编号列表的块(如 Skills store policy)
|
|
158
|
-
result = result.replace(/^\w[\w ]*\(operator configured\):[\s\S]*?(?=\n\n(?![ \t]*\d+\.)|\n*$)/gm, "");
|
|
159
|
-
// 移除 HEARTBEAT_OK 行
|
|
160
|
-
result = result.replace(/^HEARTBEAT_OK\s*$/gm, "");
|
|
161
|
-
// 移除 System: [...] 异步任务完成回调通知行
|
|
162
|
-
result = result.replace(/^System:\s*\[.*?\].*$/gm, "");
|
|
163
|
-
// 移除内联 <file ...>...</file> 标签及其内容
|
|
164
|
-
result = result.replace(/<file\b[^>]*>.*?<\/file>/gs, "");
|
|
165
|
-
// 移除 "用户发送了文件: filename (size)" 描述文本
|
|
166
|
-
result = result.replace(/用户发送了文件:\s*.+?\s*\([^)]+\)\s*/g, "");
|
|
167
|
-
return result.trim();
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* 从用户消息文本中提取文件附件信息。
|
|
171
|
-
*
|
|
172
|
-
* 匹配 "用户发送了文件: xxx.png (3.0KB)" 格式。
|
|
173
|
-
* 以及 [media attached: .../name---uuid.ext (mime/type) | file://...] 格式。
|
|
174
|
-
*/
|
|
175
|
-
function extractFileAttachments(text) {
|
|
176
|
-
const files = [];
|
|
177
|
-
// 从 "用户发送了文件: filename (size)" 提取
|
|
178
|
-
const userFileRe = /用户发送了文件:\s*(.+?)\s*\(([^)]+)\)/g;
|
|
179
|
-
let match;
|
|
180
|
-
while ((match = userFileRe.exec(text)) !== null) {
|
|
181
|
-
files.push({ name: match[1], size: match[2] });
|
|
182
|
-
}
|
|
183
|
-
// 从 [media attached: ...] 提取 MIME 和 URI
|
|
184
|
-
const mediaRe = /\[media attached:\s*\S+\s*\(([^)]+)\)\s*\|\s*(\S+)\s*\]/g;
|
|
185
|
-
let mediaIdx = 0;
|
|
186
|
-
while ((match = mediaRe.exec(text)) !== null) {
|
|
187
|
-
const mimeType = match[1];
|
|
188
|
-
const uri = match[2];
|
|
189
|
-
if (mediaIdx < files.length) {
|
|
190
|
-
files[mediaIdx].mimeType = mimeType;
|
|
191
|
-
files[mediaIdx].uri = uri;
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
// 没有匹配的中文描述,用 URI 提取文件名
|
|
195
|
-
const uriFileName = uri.split("/").pop()?.replace(/---[0-9a-f-]+\./, ".") || "file";
|
|
196
|
-
files.push({ name: uriFileName, mimeType, uri });
|
|
197
|
-
}
|
|
198
|
-
mediaIdx++;
|
|
199
|
-
}
|
|
200
|
-
return files;
|
|
201
|
-
}
|
|
202
|
-
// ============================================================
|
|
203
|
-
// 系统注入消息检测
|
|
204
|
-
// ============================================================
|
|
205
|
-
/**
|
|
206
|
-
* 检测 role=user 的消息是否实际上是传输层/系统注入的消息,而非用户真实输入。
|
|
207
|
-
*
|
|
208
|
-
* 匹配模式:以 "System: [<timestamp>]" 开头的消息,如定时提醒回调:
|
|
209
|
-
* System: [2026-03-05 16:23:00 GMT+8] ⏰ 提醒:该看日志啦!
|
|
210
|
-
*/
|
|
211
|
-
const SYSTEM_INJECTED_RE = /^System:\s*\[\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}/;
|
|
212
|
-
function isSystemInjectedUserMessage(msg) {
|
|
213
|
-
if (msg.role?.toLowerCase() !== "user")
|
|
214
|
-
return false;
|
|
215
|
-
const content = msg.content;
|
|
216
|
-
// content 为字符串
|
|
217
|
-
if (typeof content === "string") {
|
|
218
|
-
return SYSTEM_INJECTED_RE.test(content.trim());
|
|
219
|
-
}
|
|
220
|
-
// content 为数组时,检查第一个 text 块
|
|
221
|
-
if (Array.isArray(content)) {
|
|
222
|
-
for (const entry of content) {
|
|
223
|
-
if (!entry || typeof entry !== "object")
|
|
224
|
-
continue;
|
|
225
|
-
if ((entry.type === "text" || entry.type === "input_text")
|
|
226
|
-
&& typeof entry.text === "string") {
|
|
227
|
-
return SYSTEM_INJECTED_RE.test(entry.text.trim());
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
// ============================================================
|
|
234
|
-
// JSONL 解析
|
|
235
|
-
// ============================================================
|
|
236
|
-
/**
|
|
237
|
-
* 从 content 字段提取纯文本(剥离传输元数据)
|
|
238
|
-
*/
|
|
239
|
-
function extractText(content, role) {
|
|
240
|
-
if (typeof content === "string") {
|
|
241
|
-
return role === "user" ? stripTransportMetadata(content) : content;
|
|
242
|
-
}
|
|
243
|
-
if (!Array.isArray(content))
|
|
244
|
-
return "";
|
|
245
|
-
const parts = [];
|
|
246
|
-
for (const entry of content) {
|
|
247
|
-
if (!entry || typeof entry !== "object")
|
|
248
|
-
continue;
|
|
249
|
-
if ((entry.type === "text" || entry.type === "output_text" || entry.type === "input_text")
|
|
250
|
-
&& typeof entry.text === "string") {
|
|
251
|
-
parts.push(entry.text);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
const joined = parts.join("\n");
|
|
255
|
-
return role === "user" ? stripTransportMetadata(joined) : joined;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* 从 content 字段提取 thinking 内容
|
|
259
|
-
*/
|
|
260
|
-
function extractThinking(content) {
|
|
261
|
-
if (!Array.isArray(content))
|
|
262
|
-
return undefined;
|
|
263
|
-
const parts = [];
|
|
264
|
-
for (const entry of content) {
|
|
265
|
-
if (!entry || typeof entry !== "object")
|
|
266
|
-
continue;
|
|
267
|
-
if (entry.type === "thinking") {
|
|
268
|
-
const text = typeof entry.thinking === "string"
|
|
269
|
-
? entry.thinking
|
|
270
|
-
: typeof entry.text === "string" ? entry.text : undefined;
|
|
271
|
-
if (text)
|
|
272
|
-
parts.push(text);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* 从 content 字段提取工具调用信息
|
|
279
|
-
*
|
|
280
|
-
* 兼容 type: "tool_use" / "tool_call" / "toolCall"
|
|
281
|
-
* 兼容参数字段: input / arguments / args
|
|
282
|
-
*/
|
|
283
|
-
function extractToolCalls(content) {
|
|
284
|
-
if (!Array.isArray(content))
|
|
285
|
-
return undefined;
|
|
286
|
-
const calls = [];
|
|
287
|
-
for (const entry of content) {
|
|
288
|
-
if (!entry || typeof entry !== "object")
|
|
289
|
-
continue;
|
|
290
|
-
if (entry.type === "tool_use" || entry.type === "tool_call" || entry.type === "toolCall") {
|
|
291
|
-
const name = typeof entry.name === "string"
|
|
292
|
-
? entry.name
|
|
293
|
-
: typeof entry.toolName === "string"
|
|
294
|
-
? entry.toolName
|
|
295
|
-
: typeof entry.tool_name === "string"
|
|
296
|
-
? entry.tool_name
|
|
297
|
-
: "unknown";
|
|
298
|
-
const rawArgs = entry.input ?? entry.arguments ?? entry.args;
|
|
299
|
-
const args = rawArgs
|
|
300
|
-
? (typeof rawArgs === "string" ? rawArgs : JSON.stringify(rawArgs))
|
|
301
|
-
: undefined;
|
|
302
|
-
calls.push({ name, args });
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
return calls.length > 0 ? calls : undefined;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* 从 content 字段提取文件/图片信息
|
|
309
|
-
*/
|
|
310
|
-
function extractContentFiles(content) {
|
|
311
|
-
if (!Array.isArray(content))
|
|
312
|
-
return undefined;
|
|
313
|
-
const files = [];
|
|
314
|
-
for (const entry of content) {
|
|
315
|
-
if (!entry || typeof entry !== "object")
|
|
316
|
-
continue;
|
|
317
|
-
if (entry.type === "image" || entry.type === "file") {
|
|
318
|
-
// 跳过只有 data 字段的内嵌 base64 图片(传输层给模型的编码,不是用户附件)
|
|
319
|
-
if (entry.type === "image" && entry.data && !entry.uri && !entry.fileName && !entry.file_name && !entry.filename) {
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
const name = asString(entry.fileName) ?? asString(entry.file_name) ?? asString(entry.filename) ?? asString(entry.name) ?? (entry.type === "image" ? "image" : "file");
|
|
323
|
-
const mimeType = asString(entry.mimeType) ?? asString(entry.mime_type);
|
|
324
|
-
const uri = asString(entry.uri);
|
|
325
|
-
files.push({ name, mimeType, uri });
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return files.length > 0 ? files : undefined;
|
|
329
|
-
}
|
|
330
|
-
/** 安全提取非空字符串 */
|
|
331
|
-
function asString(v) {
|
|
332
|
-
return typeof v === "string" && v.trim() ? v : undefined;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* 将原始 JSONL message 对象标准化为 HistoryMessage
|
|
336
|
-
*/
|
|
337
|
-
function normalizeMessage(msg) {
|
|
338
|
-
const role = msg.role;
|
|
339
|
-
if (!role)
|
|
340
|
-
return null;
|
|
341
|
-
const normalizedRole = (() => {
|
|
342
|
-
switch (role.toLowerCase()) {
|
|
343
|
-
case "user": return "user";
|
|
344
|
-
case "assistant": return "assistant";
|
|
345
|
-
case "system": return "system";
|
|
346
|
-
case "tool":
|
|
347
|
-
case "toolresult":
|
|
348
|
-
case "tool_result":
|
|
349
|
-
return "tool";
|
|
350
|
-
default: return "assistant";
|
|
351
|
-
}
|
|
352
|
-
})();
|
|
353
|
-
const text = extractText(msg.content, normalizedRole);
|
|
354
|
-
const toolCalls = normalizedRole === "assistant" ? extractToolCalls(msg.content) : undefined;
|
|
355
|
-
const thinking = normalizedRole === "assistant" ? extractThinking(msg.content) : undefined;
|
|
356
|
-
const timestamp = typeof msg.timestamp === "number" ? msg.timestamp : undefined;
|
|
357
|
-
// 从用户消息文本中提取文件附件(原始文本,非剥离后的)
|
|
358
|
-
let files;
|
|
359
|
-
if (normalizedRole === "user") {
|
|
360
|
-
const rawText = extractRawText(msg.content);
|
|
361
|
-
const textFiles = extractFileAttachments(rawText);
|
|
362
|
-
const contentFiles = extractContentFiles(msg.content);
|
|
363
|
-
const allFiles = [...(textFiles.length > 0 ? textFiles : []), ...(contentFiles ?? [])];
|
|
364
|
-
if (allFiles.length > 0)
|
|
365
|
-
files = deduplicateFiles(allFiles);
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
files = extractContentFiles(msg.content) || undefined;
|
|
369
|
-
}
|
|
370
|
-
// tool / toolResult 角色的处理
|
|
371
|
-
let toolResult;
|
|
372
|
-
if (normalizedRole === "tool") {
|
|
373
|
-
const toolCallId = asString(msg.toolCallId)
|
|
374
|
-
?? asString(msg.tool_call_id)
|
|
375
|
-
?? asString(msg.callId);
|
|
376
|
-
const name = asString(msg.name)
|
|
377
|
-
?? asString(msg.toolName)
|
|
378
|
-
?? asString(msg.tool_name);
|
|
379
|
-
const output = text
|
|
380
|
-
|| (msg.result ? (typeof msg.result === "string" ? msg.result : JSON.stringify(msg.result)) : undefined)
|
|
381
|
-
|| undefined;
|
|
382
|
-
toolResult = { toolCallId, name, output };
|
|
383
|
-
}
|
|
384
|
-
// assistant 消息中嵌入的 toolResult 子块 → 合并到 toolCalls 信息中(不单独展开)
|
|
385
|
-
// 这些信息主要用于上下文完整性,前端一般只展示 text + toolCalls
|
|
386
|
-
// 跳过完全空的消息(除了 tool 结果和有工具调用的 assistant 消息)
|
|
387
|
-
if (!text && !toolCalls && !toolResult && !thinking && !files?.length)
|
|
388
|
-
return null;
|
|
389
|
-
return {
|
|
390
|
-
role: normalizedRole,
|
|
391
|
-
content: text,
|
|
392
|
-
timestamp,
|
|
393
|
-
...(toolCalls && { toolCalls }),
|
|
394
|
-
...(toolResult && { toolResult }),
|
|
395
|
-
...(thinking && { thinking }),
|
|
396
|
-
...(files && files.length > 0 && { files }),
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* 从 content 字段提取原始文本(不做剥离,用于文件信息提取)
|
|
401
|
-
*/
|
|
402
|
-
function extractRawText(content) {
|
|
403
|
-
if (typeof content === "string")
|
|
404
|
-
return content;
|
|
405
|
-
if (!Array.isArray(content))
|
|
406
|
-
return "";
|
|
407
|
-
const parts = [];
|
|
408
|
-
for (const entry of content) {
|
|
409
|
-
if (!entry || typeof entry !== "object")
|
|
410
|
-
continue;
|
|
411
|
-
if ((entry.type === "text" || entry.type === "output_text" || entry.type === "input_text")
|
|
412
|
-
&& typeof entry.text === "string") {
|
|
413
|
-
parts.push(entry.text);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return parts.join("\n");
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* 文件去重(按文件名)
|
|
420
|
-
*/
|
|
421
|
-
function deduplicateFiles(files) {
|
|
422
|
-
const seen = new Map();
|
|
423
|
-
for (const f of files) {
|
|
424
|
-
const existing = seen.get(f.name);
|
|
425
|
-
if (existing) {
|
|
426
|
-
// 合并信息:优先保留有更多字段的版本
|
|
427
|
-
if (!existing.mimeType && f.mimeType)
|
|
428
|
-
existing.mimeType = f.mimeType;
|
|
429
|
-
if (!existing.size && f.size)
|
|
430
|
-
existing.size = f.size;
|
|
431
|
-
if (!existing.uri && f.uri)
|
|
432
|
-
existing.uri = f.uri;
|
|
433
|
-
}
|
|
434
|
-
else {
|
|
435
|
-
seen.set(f.name, { ...f });
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
return [...seen.values()];
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* 读取指定 sessionKey 的历史对话消息
|
|
442
|
-
*
|
|
443
|
-
* @param sessionKey - 会话标识(与 gateway.ts 中 route.sessionKey 一致)
|
|
444
|
-
* @param opts - 选项
|
|
445
|
-
* @returns 历史消息数组(按时间正序),如果找不到 session 返回空数组
|
|
446
|
-
*/
|
|
447
|
-
export function readSessionHistory(sessionKey, opts) {
|
|
448
|
-
const limit = opts?.limit ?? 200;
|
|
449
|
-
const chatOnly = opts?.chatOnly ?? false;
|
|
450
|
-
const filePath = resolveTranscriptPath(sessionKey, opts?.agentId);
|
|
451
|
-
if (!filePath)
|
|
452
|
-
return [];
|
|
453
|
-
try {
|
|
454
|
-
const raw = fs.readFileSync(filePath, "utf-8");
|
|
455
|
-
const lines = raw.split(/\r?\n/).filter((l) => l.trim());
|
|
456
|
-
const messages = [];
|
|
457
|
-
for (const line of lines) {
|
|
458
|
-
try {
|
|
459
|
-
const parsed = JSON.parse(line);
|
|
460
|
-
const lineType = parsed?.type;
|
|
461
|
-
// 非消息行:显式跳过已知的元数据行类型
|
|
462
|
-
if (lineType === "session" || lineType === "model_change"
|
|
463
|
-
|| lineType === "thinking_level_change" || lineType === "custom") {
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
// compaction 标记
|
|
467
|
-
if (lineType === "compaction") {
|
|
468
|
-
if (!chatOnly) {
|
|
469
|
-
const ts = typeof parsed.timestamp === "string" ? Date.parse(parsed.timestamp) : undefined;
|
|
470
|
-
messages.push({
|
|
471
|
-
role: "system",
|
|
472
|
-
content: "── Context compacted ──",
|
|
473
|
-
timestamp: ts && Number.isFinite(ts) ? ts : Date.now(),
|
|
474
|
-
isCompaction: true,
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
// 标准消息行(type === "message" 或含 message 字段)
|
|
480
|
-
const msg = parsed?.message;
|
|
481
|
-
if (!msg || typeof msg !== "object")
|
|
482
|
-
continue;
|
|
483
|
-
// 过滤传输层伪装为 user 的系统注入消息(如定时提醒回调)
|
|
484
|
-
if (isSystemInjectedUserMessage(msg))
|
|
485
|
-
continue;
|
|
486
|
-
const normalized = normalizeMessage(msg);
|
|
487
|
-
if (!normalized)
|
|
488
|
-
continue;
|
|
489
|
-
if (chatOnly && normalized.role !== "user" && normalized.role !== "assistant")
|
|
490
|
-
continue;
|
|
491
|
-
messages.push(normalized);
|
|
492
|
-
}
|
|
493
|
-
catch {
|
|
494
|
-
// 跳过格式错误的行
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
// 只返回最后 limit 条
|
|
498
|
-
return messages.length > limit ? messages.slice(-limit) : messages;
|
|
499
|
-
}
|
|
500
|
-
catch {
|
|
501
|
-
return [];
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* 读取指定 sessionKey 的历史消息(从文件末尾读取,大文件性能更好)
|
|
506
|
-
*
|
|
507
|
-
* 对于大文件(>1MB),不读取整个文件,而是从末尾读取指定字节数。
|
|
508
|
-
*/
|
|
509
|
-
export function readSessionHistoryTail(sessionKey, opts) {
|
|
510
|
-
const limit = opts?.limit ?? 200;
|
|
511
|
-
const chatOnly = opts?.chatOnly ?? false;
|
|
512
|
-
const maxBytes = opts?.maxBytes ?? 1_048_576; // 默认 1MB
|
|
513
|
-
const filePath = resolveTranscriptPath(sessionKey, opts?.agentId);
|
|
514
|
-
if (!filePath)
|
|
515
|
-
return [];
|
|
516
|
-
let fd = null;
|
|
517
|
-
try {
|
|
518
|
-
fd = fs.openSync(filePath, "r");
|
|
519
|
-
const stat = fs.fstatSync(fd);
|
|
520
|
-
const size = stat.size;
|
|
521
|
-
if (size === 0)
|
|
522
|
-
return [];
|
|
523
|
-
// 小文件直接全量读取
|
|
524
|
-
if (size <= maxBytes) {
|
|
525
|
-
fs.closeSync(fd);
|
|
526
|
-
fd = null;
|
|
527
|
-
return readSessionHistory(sessionKey, opts);
|
|
528
|
-
}
|
|
529
|
-
// 大文件从末尾读取
|
|
530
|
-
const readStart = Math.max(0, size - maxBytes);
|
|
531
|
-
const readLen = Math.min(size, maxBytes);
|
|
532
|
-
const buf = Buffer.alloc(readLen);
|
|
533
|
-
fs.readSync(fd, buf, 0, readLen, readStart);
|
|
534
|
-
const chunk = buf.toString("utf-8");
|
|
535
|
-
const lines = chunk.split(/\r?\n/).filter((l) => l.trim());
|
|
536
|
-
// 跳过第一行(可能是不完整的行,因为从中间开始读取)
|
|
537
|
-
if (readStart > 0 && lines.length > 0) {
|
|
538
|
-
lines.shift();
|
|
539
|
-
}
|
|
540
|
-
const messages = [];
|
|
541
|
-
for (const line of lines) {
|
|
542
|
-
try {
|
|
543
|
-
const parsed = JSON.parse(line);
|
|
544
|
-
const lineType = parsed?.type;
|
|
545
|
-
if (lineType === "session" || lineType === "compaction"
|
|
546
|
-
|| lineType === "model_change" || lineType === "thinking_level_change"
|
|
547
|
-
|| lineType === "custom") {
|
|
548
|
-
continue;
|
|
549
|
-
}
|
|
550
|
-
const msg = parsed?.message;
|
|
551
|
-
if (!msg || typeof msg !== "object")
|
|
552
|
-
continue;
|
|
553
|
-
// 过滤传输层伪装为 user 的系统注入消息(如定时提醒回调)
|
|
554
|
-
if (isSystemInjectedUserMessage(msg))
|
|
555
|
-
continue;
|
|
556
|
-
const normalized = normalizeMessage(msg);
|
|
557
|
-
if (!normalized)
|
|
558
|
-
continue;
|
|
559
|
-
if (chatOnly && normalized.role !== "user" && normalized.role !== "assistant")
|
|
560
|
-
continue;
|
|
561
|
-
messages.push(normalized);
|
|
562
|
-
}
|
|
563
|
-
catch {
|
|
564
|
-
// skip
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
return messages.length > limit ? messages.slice(-limit) : messages;
|
|
568
|
-
}
|
|
569
|
-
catch {
|
|
570
|
-
return [];
|
|
571
|
-
}
|
|
572
|
-
finally {
|
|
573
|
-
if (fd !== null) {
|
|
574
|
-
try {
|
|
575
|
-
fs.closeSync(fd);
|
|
576
|
-
}
|
|
577
|
-
catch { /* ignore */ }
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* 列出所有已知的 session(从 sessions.json 索引读取)
|
|
583
|
-
*/
|
|
584
|
-
export function listSessions(agentId) {
|
|
585
|
-
const store = loadSessionStore(agentId);
|
|
586
|
-
return Object.entries(store)
|
|
587
|
-
.filter(([, entry]) => entry && entry.sessionId)
|
|
588
|
-
.map(([key, entry]) => ({
|
|
589
|
-
sessionKey: key,
|
|
590
|
-
sessionId: entry.sessionId,
|
|
591
|
-
updatedAt: entry.updatedAt,
|
|
592
|
-
label: entry.label,
|
|
593
|
-
displayName: entry.displayName,
|
|
594
|
-
channel: entry.channel,
|
|
595
|
-
}))
|
|
596
|
-
.sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
|
|
597
|
-
}
|
|
598
|
-
//# sourceMappingURL=session-history.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-history.js","sourceRoot":"","sources":["../../src/session-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LightClaw — 文本增量计算器 (DeltaTracker)
|
|
3
|
-
*
|
|
4
|
-
* 参考 kimi-claw `utils/text.js` 中的 `toStreamDeltaText` 算法。
|
|
5
|
-
*
|
|
6
|
-
* 核心作用:
|
|
7
|
-
* AI 引擎的 `onPartialReply` 回调输出的文本格式不确定 —— 有的模型输出全量快照(snapshot),
|
|
8
|
-
* 有的输出纯增量(delta),甚至可能在同一次对话中混合使用。
|
|
9
|
-
* DeltaTracker 会自动检测模式,始终输出 **纯增量文本**,方便直接追加到流式推送中。
|
|
10
|
-
*
|
|
11
|
-
* 算法概述:
|
|
12
|
-
* 1. 维护 `{ latest, mode, lastEmitted, localSnapshot }` 状态
|
|
13
|
-
* 2. 新文本到达时,判断其与 `latest` 的关系:
|
|
14
|
-
* - 如果新文本以 latest 为前缀 → snapshot 模式,截取增量
|
|
15
|
-
* - 如果新文本与 latest 有较长公共前缀 → snapshot 模式(可能是局部重传)
|
|
16
|
-
* - 如果上述均不满足 → delta 模式,直接追加
|
|
17
|
-
* 3. 各种边界处理:重复文本、前缀回退、模式切换等
|
|
18
|
-
*/
|
|
19
|
-
import type { DeltaTrackerState } from "./types.js";
|
|
20
|
-
/**
|
|
21
|
-
* 创建一个新的增量追踪器状态。
|
|
22
|
-
*/
|
|
23
|
-
export declare function createDeltaTrackerState(): DeltaTrackerState;
|
|
24
|
-
/**
|
|
25
|
-
* 将传入的文本(可能是快照或增量)转换为纯增量文本。
|
|
26
|
-
*
|
|
27
|
-
* @param state - 增量追踪器状态(会被就地修改)
|
|
28
|
-
* @param text - AI 引擎传入的文本
|
|
29
|
-
* @returns 需要追加发送的增量文本;如果无新增量则返回 `undefined`
|
|
30
|
-
*
|
|
31
|
-
* 直接移植自 kimi-claw 的 `toStreamDeltaText`,逻辑完全对齐。
|
|
32
|
-
*/
|
|
33
|
-
export declare function toStreamDeltaText(state: DeltaTrackerState, text: unknown): string | undefined;
|
|
34
|
-
//# sourceMappingURL=delta-tracker.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delta-tracker.d.ts","sourceRoot":"","sources":["../../../src/streaming/delta-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoBpD;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAO3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAwG7F"}
|