@jesonliu/lark-claudecode-bridge 1.4.3 → 2.0.1
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/assets/web/css/main.css +774 -574
- package/assets/web/index.html +37 -17
- package/assets/web/js/auth.js +218 -0
- package/assets/web/js/bootstrap.js +36 -34
- package/assets/web/js/core.js +4 -3
- package/assets/web/js/main.js +79 -20
- package/assets/web/js/markdown.js +64 -0
- package/assets/web/js/pages/apps.js +338 -251
- package/assets/web/js/pages/chats.js +481 -0
- package/assets/web/js/pages/claude.js +243 -180
- package/assets/web/js/pages/mcp.js +59 -43
- package/assets/web/js/pages/memory.js +43 -46
- package/assets/web/js/pages/overview.js +426 -88
- package/assets/web/js/pages/permissions.js +121 -34
- package/assets/web/js/pages/plugins.js +51 -37
- package/assets/web/js/pages/skills.js +68 -92
- package/assets/web/js/pages/slash.js +31 -23
- package/assets/web/js/pages/workspaces.js +114 -73
- package/assets/web/js/theme.js +21 -18
- package/assets/web/js/ui.js +75 -32
- package/dist/access/access-control.d.ts +18 -0
- package/dist/access/access-control.js +29 -0
- package/dist/access/access-control.js.map +1 -1
- package/dist/bin/lcb.js +15 -0
- package/dist/bin/lcb.js.map +1 -1
- package/dist/feishu/name-cache.d.ts +15 -0
- package/dist/feishu/name-cache.js +82 -0
- package/dist/feishu/name-cache.js.map +1 -0
- package/dist/feishu/sibling-names.d.ts +1 -0
- package/dist/feishu/sibling-names.js +63 -0
- package/dist/feishu/sibling-names.js.map +1 -0
- package/dist/gateway/feishu-gateway.d.ts +24 -0
- package/dist/gateway/feishu-gateway.js +132 -0
- package/dist/gateway/feishu-gateway.js.map +1 -1
- package/dist/gateway/gateway-registry.d.ts +18 -0
- package/dist/gateway/gateway-registry.js +14 -0
- package/dist/gateway/gateway-registry.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +52 -9
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/web/chats-api.d.ts +93 -0
- package/dist/web/chats-api.js +603 -0
- package/dist/web/chats-api.js.map +1 -0
- package/dist/web/lifecycle.d.ts +21 -0
- package/dist/web/lifecycle.js +80 -3
- package/dist/web/lifecycle.js.map +1 -1
- package/dist/web/logs-api.d.ts +37 -0
- package/dist/web/logs-api.js +141 -0
- package/dist/web/logs-api.js.map +1 -0
- package/dist/web/server.js +196 -13
- package/dist/web/server.js.map +1 -1
- package/dist/web/webauth.d.ts +44 -0
- package/dist/web/webauth.js +221 -0
- package/dist/web/webauth.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
// 「会话记录」页后端(三接口,全部只读):树(机器人 → 通道)/ 话题(CC 会话聚合)/ 时间线。
|
|
2
|
+
// 数据源全部是 LCB 自有落盘,与记忆增强是否开启完全无关:
|
|
3
|
+
// - transcripts/<appId>/<chatId>/<YYYY-MM-DD>.jsonl:对话全文流水(transcript-writer,按天分文件)
|
|
4
|
+
// - sessions.<appId>.json:每通道话题索引(sessionId + 首条消息摘要,/resume 列表同源)
|
|
5
|
+
// - access.json:userId → 飞书人名
|
|
6
|
+
// 群名/会话类型经运行中网关的飞书 REST 现拉(gateway-registry;成功缓存 24h、失败短缓存 10 分钟
|
|
7
|
+
// ——权限补开后十分钟内自动恢复真名,不必重启)。lcb ui 独立进程无网关来源 → 走降级显示名。
|
|
8
|
+
// 设计基调:查看器不能因数据缺失报错——目录/文件缺失按空处理、坏行跳过、ID 白名单防路径穿越。
|
|
9
|
+
import { readdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { CONFIG_DIR, loadConfig } from '../config.js';
|
|
12
|
+
import { getChatInfoSource } from '../gateway/gateway-registry.js';
|
|
13
|
+
import { getCachedChatMeta, getCachedUserName, getCachedUserUnion, putCachedChatMeta, putCachedUserName } from '../feishu/name-cache.js';
|
|
14
|
+
import { resolveNamesByUnionViaSiblings } from '../feishu/sibling-names.js';
|
|
15
|
+
const TRANSCRIPTS_DIR = join(CONFIG_DIR, 'transcripts');
|
|
16
|
+
/** 路径安全:appId/chatId 仅接受飞书 id 字符集(拼路径前把守,杜绝 ../ 穿越);日期由白名单正则把守 */
|
|
17
|
+
const ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
18
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
19
|
+
const JSONL_RE = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
20
|
+
/** 话题跨天索引的防呆上限(主人已拍板:无天数上限;此处仅防异常巨库一次性拖死进程) */
|
|
21
|
+
const MAX_SCAN_FILES = 300;
|
|
22
|
+
const MAX_SCAN_BYTES = 150 * 1024 * 1024;
|
|
23
|
+
/** 时间线单次返回的任务数上限(前端「仅显示最近 N 条」提示的口径) */
|
|
24
|
+
const DEFAULT_TASK_LIMIT = 400;
|
|
25
|
+
function listDirs(dir) {
|
|
26
|
+
try {
|
|
27
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
28
|
+
.filter((e) => e.isDirectory() && ID_RE.test(e.name))
|
|
29
|
+
.map((e) => e.name)
|
|
30
|
+
.sort();
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
} // transcripts 目录不存在(尚无任何对话)= 空树而非报错
|
|
35
|
+
}
|
|
36
|
+
function listDateFiles(dir) {
|
|
37
|
+
try {
|
|
38
|
+
return readdirSync(dir).filter((f) => JSONL_RE.test(f)).sort().reverse(); // 新→旧
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** access.json 人名表(userId → name;损坏/缺失按空表,查看器不因准入数据报错) */
|
|
45
|
+
function readAccessNames() {
|
|
46
|
+
const out = new Map();
|
|
47
|
+
try {
|
|
48
|
+
const raw = JSON.parse(readFileSync(join(CONFIG_DIR, 'access.json'), 'utf8'));
|
|
49
|
+
for (const [uid, u] of Object.entries(raw.users ?? {})) {
|
|
50
|
+
if (u?.name)
|
|
51
|
+
out.set(uid, u.name);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch { /* 无准入数据:人名全部走 chatId/尾号降级 */ }
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/** sessions.<appId>.json 原样读(channelKey → ChannelState);缺失/损坏按空表 */
|
|
58
|
+
function readSessionStore(appId) {
|
|
59
|
+
try {
|
|
60
|
+
const raw = JSON.parse(readFileSync(join(CONFIG_DIR, `sessions.${appId}.json`), 'utf8'));
|
|
61
|
+
return raw && typeof raw === 'object' ? raw : {};
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** 成功态走磁盘持久缓存(name-cache,重启不丢);本 Map 只留「拉取失败」短缓存(10 分钟自愈) */
|
|
68
|
+
const chatMetaCache = new Map(); // key `${appId}/${chatId}`
|
|
69
|
+
const META_FAIL_TTL_MS = 10 * 60 * 1000; // 拉取失败短缓存:im:chat 权限补开后十分钟内自动恢复真名
|
|
70
|
+
async function fetchChatMeta(appId, chatId) {
|
|
71
|
+
const key = `${appId}/${chatId}`;
|
|
72
|
+
const disk = getCachedChatMeta(appId, chatId);
|
|
73
|
+
if (disk?.name)
|
|
74
|
+
return { ...disk, at: 0 }; // 磁盘命中:零 API 调用(30 天/3 天 TTL 由缓存层管)
|
|
75
|
+
const hit = chatMetaCache.get(key);
|
|
76
|
+
if (hit && Date.now() - hit.at < META_FAIL_TTL_MS)
|
|
77
|
+
return hit; // 失败短缓存:别反复打飞书
|
|
78
|
+
const src = getChatInfoSource(appId);
|
|
79
|
+
if (!src)
|
|
80
|
+
return hit ?? (disk ? { ...disk, at: 0 } : undefined); // 桥未运行:失败态或磁盘旧值
|
|
81
|
+
try {
|
|
82
|
+
const res = await src.request({ method: 'GET', url: `/open-apis/im/v1/chats/${encodeURIComponent(chatId)}` });
|
|
83
|
+
const data = res.data;
|
|
84
|
+
if (res.code === 0 && typeof data?.name === 'string' && data.name) {
|
|
85
|
+
const meta = {
|
|
86
|
+
name: data.name,
|
|
87
|
+
// 飞书字段不统一:详情接口部分会话给 chat_type(取值 private/group)、部分只有
|
|
88
|
+
// chat_mode(p2p/group)——实测同一应用两种形态都出现,两个都读
|
|
89
|
+
chatType: typeof data.chat_type === 'string' && data.chat_type
|
|
90
|
+
? data.chat_type
|
|
91
|
+
: typeof data.chat_mode === 'string' ? data.chat_mode : '',
|
|
92
|
+
at: Date.now(),
|
|
93
|
+
};
|
|
94
|
+
putCachedChatMeta(appId, chatId, { name: meta.name, chatType: meta.chatType });
|
|
95
|
+
return meta;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch { /* 机器人不在群 / 权限缺失 / 网络失败:降级显示名 */ }
|
|
99
|
+
const failed = { at: Date.now() };
|
|
100
|
+
chatMetaCache.set(key, failed);
|
|
101
|
+
// 曾拉到过真名(磁盘旧值未过期)→ 继续用旧真名,好过降级串
|
|
102
|
+
return disk?.name ? { ...disk, at: 0 } : failed;
|
|
103
|
+
}
|
|
104
|
+
function chatIdTail(chatId) {
|
|
105
|
+
return chatId.length > 6 ? chatId.slice(-6) : chatId;
|
|
106
|
+
}
|
|
107
|
+
/** 成功态走磁盘持久缓存(name-cache,30 天、重启不丢);本 Map 只留「解析失败」短缓存(10 分钟自愈) */
|
|
108
|
+
const userNameCache = new Map(); // key `${appId}/${openId}`
|
|
109
|
+
const USER_FAIL_TTL_MS = 10 * 60 * 1000;
|
|
110
|
+
/** contact batch 接口单次 user_ids 上限(官方约定 ≤50) */
|
|
111
|
+
const USER_BATCH_SIZE = 50;
|
|
112
|
+
/** 批量解析 open_id → 姓名(配对授权 API 同源复用)。整批失败(权限/网络)落短缓存防每轮树接口重打;零结果视为失败态 */
|
|
113
|
+
export async function fetchUserNames(appId, ids) {
|
|
114
|
+
const out = new Map();
|
|
115
|
+
const need = [];
|
|
116
|
+
for (const id of ids) {
|
|
117
|
+
const diskName = getCachedUserName(appId, id);
|
|
118
|
+
if (diskName) {
|
|
119
|
+
out.set(id, diskName);
|
|
120
|
+
continue;
|
|
121
|
+
} // 磁盘命中:零 API 调用
|
|
122
|
+
const hit = userNameCache.get(`${appId}/${id}`);
|
|
123
|
+
if (hit && Date.now() - hit.at < USER_FAIL_TTL_MS)
|
|
124
|
+
continue; // 失败短缓存:10 分钟后自动重试
|
|
125
|
+
need.push(id);
|
|
126
|
+
}
|
|
127
|
+
if (!need.length)
|
|
128
|
+
return out;
|
|
129
|
+
const attempted = [...need]; // 本轮已尝试 contact 的 id 快照:兄弟桥候选(失败缓存是 contact 阶段才打的,不能堵同轮兄弟桥)
|
|
130
|
+
const src = getChatInfoSource(appId);
|
|
131
|
+
if (!src)
|
|
132
|
+
return out; // 桥未运行(lcb ui 独立进程):吃缓存,没有则本轮降级,不报错
|
|
133
|
+
/** 吸收一批结果。⚠️ 飞书 v3 user 对象的标识字段是 open_id(user_id_type=open_id 时实测响应
|
|
134
|
+
* 只有 open_id/union_id,无 user_id 字段)——10-15 起误取 it.user_id 恒为 undefined,
|
|
135
|
+
* 真名解析从未生效、会话页全员 ou_(2026-10-18 主人反馈 + 插桩实锤后修复) */
|
|
136
|
+
const absorb = (items, batch) => {
|
|
137
|
+
if (!Array.isArray(items))
|
|
138
|
+
return false;
|
|
139
|
+
const got = new Set();
|
|
140
|
+
for (const it of items) {
|
|
141
|
+
const uid = typeof it.open_id === 'string' && it.open_id ? it.open_id : it.user_id;
|
|
142
|
+
const name = it.name;
|
|
143
|
+
if (typeof uid === 'string' && typeof name === 'string' && name) {
|
|
144
|
+
putCachedUserName(appId, uid, name); // 成功态落磁盘持久缓存(跨重启/跨场景共用)
|
|
145
|
+
out.set(uid, name);
|
|
146
|
+
got.add(uid);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// 本批未被接口返回的 id:落失败短缓存(10 分钟后自动重试,可能后配对)
|
|
150
|
+
for (const id of batch) {
|
|
151
|
+
if (!got.has(id))
|
|
152
|
+
userNameCache.set(`${appId}/${id}`, { at: Date.now() });
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
};
|
|
156
|
+
const query = async (batch) => {
|
|
157
|
+
const qs = batch.map((id) => `user_ids=${encodeURIComponent(id)}`).join('&');
|
|
158
|
+
let ok = false;
|
|
159
|
+
try {
|
|
160
|
+
const res = await src.request({
|
|
161
|
+
method: 'GET',
|
|
162
|
+
url: `/open-apis/contact/v3/users/batch?user_id_type=open_id&${qs}`,
|
|
163
|
+
});
|
|
164
|
+
const items = res.code === 0
|
|
165
|
+
? res.data?.items
|
|
166
|
+
: undefined;
|
|
167
|
+
ok = absorb(items, batch);
|
|
168
|
+
}
|
|
169
|
+
catch { /* 权限缺失 / 网络失败 / open_id 跨应用(99992361) 整批被拒:走下方逐个回退 */ }
|
|
170
|
+
if (!ok && batch.length > 1) {
|
|
171
|
+
// 整批失败 → 逐个回退:跨应用的坏 id 单查时被隔离(该 id 落失败缓存),好 id 照样拿到真名
|
|
172
|
+
for (const id of batch)
|
|
173
|
+
await query([id]);
|
|
174
|
+
}
|
|
175
|
+
else if (!ok) {
|
|
176
|
+
for (const id of batch)
|
|
177
|
+
userNameCache.set(`${appId}/${id}`, { at: Date.now() });
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
for (let i = 0; i < need.length; i += USER_BATCH_SIZE) {
|
|
181
|
+
await query(need.slice(i, i + USER_BATCH_SIZE));
|
|
182
|
+
}
|
|
183
|
+
// 兄弟应用桥兜底(与网关 resolveUserNames 同款):通讯录权限范围外用户的缺口 id,
|
|
184
|
+
// 用磁盘 union 索引借兄弟应用凭证解析;命中写共享磁盘缓存并清失败短缓存;兄弟也查不到
|
|
185
|
+
// → 失败缓存已在 absorb 落好(跨轮节流,防配置页 30s 轮询重打);无 union 索引的不动
|
|
186
|
+
// 失败缓存(后续事件带来 union 时即清缓存立即可重试)
|
|
187
|
+
const missing = attempted.filter((id) => !out.has(id));
|
|
188
|
+
if (missing.length) {
|
|
189
|
+
const unions = new Map();
|
|
190
|
+
for (const id of missing) {
|
|
191
|
+
const u = getCachedUserUnion(appId, id);
|
|
192
|
+
if (u)
|
|
193
|
+
unions.set(id, u);
|
|
194
|
+
}
|
|
195
|
+
if (unions.size) {
|
|
196
|
+
try {
|
|
197
|
+
const got = await resolveNamesByUnionViaSiblings(appId, unions);
|
|
198
|
+
for (const [id, name] of got) {
|
|
199
|
+
putCachedUserName(appId, id, name);
|
|
200
|
+
out.set(id, name);
|
|
201
|
+
userNameCache.delete(`${appId}/${id}`);
|
|
202
|
+
}
|
|
203
|
+
for (const id of unions.keys())
|
|
204
|
+
if (!got.has(id))
|
|
205
|
+
userNameCache.set(`${appId}/${id}`, { at: Date.now() });
|
|
206
|
+
}
|
|
207
|
+
catch { /* 桥失败不影响已解析结果 */ }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 真名回写 access.json(自愈):配对时拿不到真名、name 落的是原始 open_id 的记录,
|
|
214
|
+
* 一旦通讯录解析成功就补正——配对展示/群内管理员名/会话页全线受益。只修「缺失或自指」项,
|
|
215
|
+
* 用户自填的真名永不被覆盖;确有修改才写盘(读-改-写,与运行中 AccessControl 实例的整盘
|
|
216
|
+
* 覆写存在竞态窗口,但本写入低频 + 下轮树接口自愈,可接受)
|
|
217
|
+
*/
|
|
218
|
+
function backfillAccessNames(names) {
|
|
219
|
+
if (!names.length)
|
|
220
|
+
return;
|
|
221
|
+
const path = join(CONFIG_DIR, 'access.json');
|
|
222
|
+
let raw;
|
|
223
|
+
try {
|
|
224
|
+
raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return;
|
|
228
|
+
} // 无准入数据/损坏:不造文件
|
|
229
|
+
let changed = false;
|
|
230
|
+
for (const [uid, name] of names) {
|
|
231
|
+
const u = raw.users?.[uid];
|
|
232
|
+
if (u && (!u.name || u.name === uid) && name !== uid) {
|
|
233
|
+
u.name = name;
|
|
234
|
+
changed = true;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!changed)
|
|
238
|
+
return;
|
|
239
|
+
try {
|
|
240
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
241
|
+
writeFileSync(tmp, JSON.stringify(raw, null, 2), 'utf8');
|
|
242
|
+
renameSync(tmp, path);
|
|
243
|
+
}
|
|
244
|
+
catch { /* 回写失败不影响展示(内存缓存已生效) */ }
|
|
245
|
+
}
|
|
246
|
+
/** 显示名三级降级:飞书真名 → access 人名(单用户=p2p)→ 「群聊(N人)/会话 ·尾号」。
|
|
247
|
+
* chatType 独立透出:群信息拉到但群名为空(如 p2p 无名)时类型不再被丢弃——
|
|
248
|
+
* 此前丢弃导致前端把群聊误标「私聊」(2026-10-17 主人反馈) */
|
|
249
|
+
function buildDisplayName(meta, users, access, chatId) {
|
|
250
|
+
const chatType = meta?.chatType || (users.length > 1 ? 'group' : '');
|
|
251
|
+
if (meta?.name)
|
|
252
|
+
return { displayName: meta.name, chatType, nameSource: 'feishu' };
|
|
253
|
+
if (users.length === 1) {
|
|
254
|
+
const n = access.get(users[0]);
|
|
255
|
+
if (n)
|
|
256
|
+
return { displayName: n, chatType: chatType || 'p2p', nameSource: 'access' };
|
|
257
|
+
}
|
|
258
|
+
const label = users.length > 1 ? `群聊(${users.length}人)` : '会话';
|
|
259
|
+
return { displayName: `${label} ·${chatIdTail(chatId)}`, chatType, nameSource: 'fallback' };
|
|
260
|
+
}
|
|
261
|
+
export async function chatsTree(configPath) {
|
|
262
|
+
let config;
|
|
263
|
+
try {
|
|
264
|
+
config = loadConfig(configPath);
|
|
265
|
+
}
|
|
266
|
+
catch { /* 配置损坏也照常扫目录:显示名退化为 appId */ }
|
|
267
|
+
const appNames = new Map((config?.apps ?? []).map((a) => [a.appId, a.name || a.appId]));
|
|
268
|
+
const access = readAccessNames();
|
|
269
|
+
const bots = [];
|
|
270
|
+
for (const appId of listDirs(TRANSCRIPTS_DIR)) {
|
|
271
|
+
const store = readSessionStore(appId);
|
|
272
|
+
// channelKey = `${chatId}:${userId}`(session/channel.ts 口径)→ 按 chatId 聚合用户、话题数与会话条目
|
|
273
|
+
const usersByChat = new Map();
|
|
274
|
+
const topicCountByChat = new Map();
|
|
275
|
+
/** (chatId, sessionId) 聚合:跨 userId 合并、updatedAt 取最新、标题同步取最新一条的摘要(与 chatTopics 同口径) */
|
|
276
|
+
const sessionsByChat = new Map();
|
|
277
|
+
for (const [key, st] of Object.entries(store)) {
|
|
278
|
+
const i = key.lastIndexOf(':');
|
|
279
|
+
if (i <= 0)
|
|
280
|
+
continue;
|
|
281
|
+
const chatId = key.slice(0, i);
|
|
282
|
+
const userId = key.slice(i + 1);
|
|
283
|
+
let arr = usersByChat.get(chatId);
|
|
284
|
+
if (!arr)
|
|
285
|
+
usersByChat.set(chatId, arr = []);
|
|
286
|
+
if (!arr.includes(userId))
|
|
287
|
+
arr.push(userId);
|
|
288
|
+
topicCountByChat.set(chatId, (topicCountByChat.get(chatId) ?? 0) + (st.sessions?.length ?? 0));
|
|
289
|
+
let bySid = sessionsByChat.get(chatId);
|
|
290
|
+
if (!bySid)
|
|
291
|
+
sessionsByChat.set(chatId, bySid = new Map());
|
|
292
|
+
for (const t of st.sessions ?? []) {
|
|
293
|
+
if (!t?.sessionId)
|
|
294
|
+
continue;
|
|
295
|
+
const cur = bySid.get(t.sessionId);
|
|
296
|
+
if (cur) {
|
|
297
|
+
cur.users.add(userId);
|
|
298
|
+
if ((t.updatedAt ?? '') > cur.updatedAt) {
|
|
299
|
+
cur.updatedAt = t.updatedAt ?? '';
|
|
300
|
+
cur.title = t.summary ?? '';
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
bySid.set(t.sessionId, { title: t.summary ?? '', updatedAt: t.updatedAt ?? '', users: new Set([userId]) });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const channels = [];
|
|
309
|
+
for (const chatId of listDirs(join(TRANSCRIPTS_DIR, appId))) {
|
|
310
|
+
const dates = [];
|
|
311
|
+
let lastActiveMs = 0;
|
|
312
|
+
let sizeBytes = 0;
|
|
313
|
+
for (const f of listDateFiles(join(TRANSCRIPTS_DIR, appId, chatId))) {
|
|
314
|
+
dates.push(f.slice(0, 10));
|
|
315
|
+
try {
|
|
316
|
+
const st = statSync(join(TRANSCRIPTS_DIR, appId, chatId, f));
|
|
317
|
+
lastActiveMs = Math.max(lastActiveMs, st.mtimeMs);
|
|
318
|
+
sizeBytes += st.size;
|
|
319
|
+
}
|
|
320
|
+
catch { /* 文件恰好被清理:跳过 */ }
|
|
321
|
+
}
|
|
322
|
+
const users = usersByChat.get(chatId) ?? [];
|
|
323
|
+
const meta = await fetchChatMeta(appId, chatId);
|
|
324
|
+
// 发信人真名:飞书通讯录解析为权威,access 仅兜底——合并顺序 feishu 在后(同 key 胜出),
|
|
325
|
+
// 且 access 里 name===userId 的自指记录(配对时拿不到真名落了原始 id)不参与兜底,
|
|
326
|
+
// 否则会把飞书真名顶回 ou_ 串(2026-10-17 主人反馈会话页 ou_ 满屏的根因之一)
|
|
327
|
+
const feishuNames = await fetchUserNames(appId, users);
|
|
328
|
+
const accessNames = new Map();
|
|
329
|
+
for (const [uid, n] of access) {
|
|
330
|
+
if (n && n !== uid)
|
|
331
|
+
accessNames.set(uid, n);
|
|
332
|
+
}
|
|
333
|
+
const nameMap = new Map([...accessNames, ...feishuNames]);
|
|
334
|
+
backfillAccessNames([...feishuNames]);
|
|
335
|
+
const name = buildDisplayName(meta, users, nameMap, chatId);
|
|
336
|
+
// 会话条目(列表页列表项):名字复用本通道已解析的 nameMap,无额外飞书调用
|
|
337
|
+
const sessions = [];
|
|
338
|
+
for (const [sessionId, v] of sessionsByChat.get(chatId) ?? []) {
|
|
339
|
+
sessions.push({
|
|
340
|
+
sessionId,
|
|
341
|
+
title: v.title || sessionId.slice(0, 8), // 无摘要的历史数据退化为短 id
|
|
342
|
+
updatedAt: v.updatedAt,
|
|
343
|
+
users: [...v.users].map((userId) => ({ userId, ...(nameMap.get(userId) ? { name: nameMap.get(userId) } : {}) })),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
sessions.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
347
|
+
channels.push({
|
|
348
|
+
chatId,
|
|
349
|
+
displayName: name.displayName,
|
|
350
|
+
chatType: name.chatType,
|
|
351
|
+
nameSource: name.nameSource,
|
|
352
|
+
users: users.map((userId) => ({ userId, ...(nameMap.get(userId) ? { name: nameMap.get(userId) } : {}) })),
|
|
353
|
+
dates,
|
|
354
|
+
lastActiveAt: lastActiveMs ? new Date(lastActiveMs).toISOString() : '',
|
|
355
|
+
topics: topicCountByChat.get(chatId) ?? 0,
|
|
356
|
+
sizeBytes,
|
|
357
|
+
sessions,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
channels.sort((a, b) => b.lastActiveAt.localeCompare(a.lastActiveAt));
|
|
361
|
+
bots.push({ appId, name: appNames.get(appId) ?? appId, channels });
|
|
362
|
+
}
|
|
363
|
+
return { bots };
|
|
364
|
+
}
|
|
365
|
+
/** 某通道的话题列表(session-store 聚合:跨 userId 合并、同 sessionId 去重取最新)。标题 = 首条消息摘要 */
|
|
366
|
+
export function chatTopics(appId, chatId) {
|
|
367
|
+
if (!ID_RE.test(appId) || !ID_RE.test(chatId))
|
|
368
|
+
return { topics: [] };
|
|
369
|
+
const store = readSessionStore(appId);
|
|
370
|
+
const prefix = `${chatId}:`;
|
|
371
|
+
const bySid = new Map();
|
|
372
|
+
for (const [key, st] of Object.entries(store)) {
|
|
373
|
+
if (!key.startsWith(prefix))
|
|
374
|
+
continue;
|
|
375
|
+
const userId = key.slice(prefix.length);
|
|
376
|
+
for (const t of st.sessions ?? []) {
|
|
377
|
+
if (!t?.sessionId)
|
|
378
|
+
continue;
|
|
379
|
+
const cur = bySid.get(t.sessionId);
|
|
380
|
+
if (cur) {
|
|
381
|
+
cur.users.add(userId);
|
|
382
|
+
if ((t.updatedAt ?? '') > cur.updatedAt) {
|
|
383
|
+
cur.updatedAt = t.updatedAt ?? '';
|
|
384
|
+
cur.title = t.summary ?? '';
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
bySid.set(t.sessionId, { title: t.summary ?? '', updatedAt: t.updatedAt ?? '', users: new Set([userId]) });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const topics = [...bySid.entries()]
|
|
393
|
+
.map(([sessionId, v]) => ({
|
|
394
|
+
sessionId,
|
|
395
|
+
title: v.title || sessionId.slice(0, 8), // 无摘要的历史数据退化为短 id
|
|
396
|
+
updatedAt: v.updatedAt,
|
|
397
|
+
users: [...v.users],
|
|
398
|
+
}))
|
|
399
|
+
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
400
|
+
return { topics };
|
|
401
|
+
}
|
|
402
|
+
/** 单日 JSONL → 任务序列(顺序行走;坏行跳过;孤儿 assistant/tool 不进时间线)。
|
|
403
|
+
* assistant 事件是流式分块(每块一行),顺序拼接即完整回复;reply 为空时回退 result 文本 */
|
|
404
|
+
function parseDayTasks(dir, date) {
|
|
405
|
+
let text;
|
|
406
|
+
try {
|
|
407
|
+
text = readFileSync(join(dir, `${date}.jsonl`), 'utf8');
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
return [];
|
|
411
|
+
} // 缺天 = 空
|
|
412
|
+
const tasks = [];
|
|
413
|
+
let cur = null;
|
|
414
|
+
for (const line of text.split('\n')) {
|
|
415
|
+
if (!line.trim())
|
|
416
|
+
continue;
|
|
417
|
+
let ev;
|
|
418
|
+
try {
|
|
419
|
+
ev = JSON.parse(line);
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (ev.kind === 'user') {
|
|
425
|
+
cur = {
|
|
426
|
+
date,
|
|
427
|
+
ts: ev.ts,
|
|
428
|
+
userId: ev.userId,
|
|
429
|
+
...(ev.workspace ? { workspace: ev.workspace } : {}),
|
|
430
|
+
...(ev.sessionId ? { sessionId: ev.sessionId } : {}),
|
|
431
|
+
prompt: ev.text,
|
|
432
|
+
reply: '',
|
|
433
|
+
tools: [],
|
|
434
|
+
};
|
|
435
|
+
tasks.push(cur);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (!cur)
|
|
439
|
+
continue;
|
|
440
|
+
if (ev.kind === 'assistant') {
|
|
441
|
+
cur.reply += ev.text;
|
|
442
|
+
}
|
|
443
|
+
else if (ev.kind === 'tool') {
|
|
444
|
+
if (ev.phase === 'start') {
|
|
445
|
+
cur.tools.push({ ts: ev.ts, tool: ev.tool });
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
// result 相位回填同工具的执行状态(倒序找最近一个未定状态的 start)
|
|
449
|
+
for (let i = cur.tools.length - 1; i >= 0; i--) {
|
|
450
|
+
if (cur.tools[i].tool === ev.tool && cur.tools[i].ok === undefined) {
|
|
451
|
+
cur.tools[i].ok = ev.ok;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
else if (ev.kind === 'result') {
|
|
458
|
+
cur.result = {
|
|
459
|
+
subtype: ev.subtype,
|
|
460
|
+
...(ev.producedFiles?.length ? { producedFiles: ev.producedFiles } : {}),
|
|
461
|
+
...(ev.turns !== undefined ? { turns: ev.turns } : {}),
|
|
462
|
+
};
|
|
463
|
+
if (ev.sessionId)
|
|
464
|
+
cur.sessionId = ev.sessionId; // 权威口径覆盖起点指针
|
|
465
|
+
if (!cur.reply && ev.text)
|
|
466
|
+
cur.reply = ev.text;
|
|
467
|
+
cur = null;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return tasks;
|
|
471
|
+
}
|
|
472
|
+
function extractJsonString(line, key) {
|
|
473
|
+
const marker = `"${key}":"`;
|
|
474
|
+
const i = line.indexOf(marker);
|
|
475
|
+
if (i < 0)
|
|
476
|
+
return '';
|
|
477
|
+
const start = i + marker.length;
|
|
478
|
+
const end = line.indexOf('"', start);
|
|
479
|
+
return end < 0 ? '' : line.slice(start, end);
|
|
480
|
+
}
|
|
481
|
+
const indexCache = new Map(); // key = 通道目录
|
|
482
|
+
function fingerprintOf(dir, files) {
|
|
483
|
+
const parts = [];
|
|
484
|
+
for (const f of files) {
|
|
485
|
+
try {
|
|
486
|
+
const st = statSync(join(dir, f));
|
|
487
|
+
parts.push(`${f}:${st.mtimeMs}:${st.size}`);
|
|
488
|
+
}
|
|
489
|
+
catch {
|
|
490
|
+
parts.push(f);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return parts.join('|');
|
|
494
|
+
}
|
|
495
|
+
/** 建「会话 → 出现日期」索引:行级子串抽取(user=起点指针 / result=权威 id),不做全量 JSON.parse。
|
|
496
|
+
* 无天数上限(新→旧扫全部历史);仅文件数/字节数防呆。首次建后进程内缓存,文件指纹变化才重建 */
|
|
497
|
+
function buildTopicIndex(dir, files) {
|
|
498
|
+
const datesBySession = new Map();
|
|
499
|
+
let bytes = 0;
|
|
500
|
+
let scanned = 0;
|
|
501
|
+
let partial = false;
|
|
502
|
+
for (const f of files) {
|
|
503
|
+
if (scanned >= MAX_SCAN_FILES || bytes > MAX_SCAN_BYTES) {
|
|
504
|
+
partial = true;
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
let size = 0;
|
|
508
|
+
try {
|
|
509
|
+
size = statSync(join(dir, f)).size;
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
bytes += size;
|
|
515
|
+
scanned++;
|
|
516
|
+
let text;
|
|
517
|
+
try {
|
|
518
|
+
text = readFileSync(join(dir, f), 'utf8');
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const date = f.slice(0, 10);
|
|
524
|
+
let pending = ''; // 最近一条 user 行的起点指针(新话题首轮为空,由 result 行权威 id 补齐)
|
|
525
|
+
const reg = (sid) => {
|
|
526
|
+
if (!sid)
|
|
527
|
+
return;
|
|
528
|
+
let arr = datesBySession.get(sid);
|
|
529
|
+
if (!arr)
|
|
530
|
+
datesBySession.set(sid, arr = []);
|
|
531
|
+
if (!arr.includes(date))
|
|
532
|
+
arr.push(date);
|
|
533
|
+
};
|
|
534
|
+
for (const line of text.split('\n')) {
|
|
535
|
+
if (line.includes('"kind":"user"')) {
|
|
536
|
+
pending = extractJsonString(line, 'sessionId');
|
|
537
|
+
reg(pending);
|
|
538
|
+
}
|
|
539
|
+
else if (line.includes('"kind":"result"')) {
|
|
540
|
+
reg(extractJsonString(line, 'sessionId'));
|
|
541
|
+
reg(pending);
|
|
542
|
+
pending = '';
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
reg(pending); // 无 result 收尾(进程被杀)的任务同样归进索引
|
|
546
|
+
}
|
|
547
|
+
return { fingerprint: fingerprintOf(dir, files), datesBySession, partial };
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* 时间线查询。三种口径:
|
|
551
|
+
* - date 指定:单日视图(不过索引,直读该日文件)
|
|
552
|
+
* - session 指定:话题视图(索引定位该会话出现的日期,再跨天聚合归属任务)——任何历史话题都能看全
|
|
553
|
+
* - 都不传:最新往旧全量(防呆上限内),供「全部记录」浏览
|
|
554
|
+
* 返回任务序列(时间升序);truncated=达到单次返回上限,partial=索引被防呆上限截断。
|
|
555
|
+
*/
|
|
556
|
+
export function chatTimeline(appId, chatId, query) {
|
|
557
|
+
const empty = { tasks: [], truncated: false, partial: false, scanDays: 0 };
|
|
558
|
+
if (!ID_RE.test(appId) || !ID_RE.test(chatId))
|
|
559
|
+
return empty;
|
|
560
|
+
const dir = join(TRANSCRIPTS_DIR, appId, chatId);
|
|
561
|
+
const files = listDateFiles(dir);
|
|
562
|
+
if (files.length === 0)
|
|
563
|
+
return empty;
|
|
564
|
+
const limit = Math.min(Math.max(query.limit ?? DEFAULT_TASK_LIMIT, 1), 1000);
|
|
565
|
+
let scanDates;
|
|
566
|
+
let partial = false;
|
|
567
|
+
if (query.date && DATE_RE.test(query.date)) {
|
|
568
|
+
scanDates = [query.date];
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
let index = indexCache.get(dir);
|
|
572
|
+
const fingerprint = fingerprintOf(dir, files);
|
|
573
|
+
if (!index || index.fingerprint !== fingerprint) {
|
|
574
|
+
index = buildTopicIndex(dir, files);
|
|
575
|
+
indexCache.set(dir, index);
|
|
576
|
+
}
|
|
577
|
+
partial = index.partial;
|
|
578
|
+
scanDates = query.session
|
|
579
|
+
? (index.datesBySession.get(query.session) ?? [])
|
|
580
|
+
: files.map((f) => f.slice(0, 10));
|
|
581
|
+
}
|
|
582
|
+
const tasks = [];
|
|
583
|
+
let truncated = false;
|
|
584
|
+
for (const date of scanDates) {
|
|
585
|
+
if (!DATE_RE.test(date))
|
|
586
|
+
continue;
|
|
587
|
+
for (const t of parseDayTasks(dir, date)) {
|
|
588
|
+
if (query.session && t.sessionId !== query.session)
|
|
589
|
+
continue;
|
|
590
|
+
if (query.user && t.userId !== query.user)
|
|
591
|
+
continue;
|
|
592
|
+
tasks.push(t);
|
|
593
|
+
if (tasks.length >= limit) {
|
|
594
|
+
truncated = true;
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (truncated)
|
|
599
|
+
break;
|
|
600
|
+
}
|
|
601
|
+
return { tasks, truncated, partial, scanDays: scanDates.length };
|
|
602
|
+
}
|
|
603
|
+
//# sourceMappingURL=chats-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chats-api.js","sourceRoot":"","sources":["../../src/web/chats-api.ts"],"names":[],"mappings":"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"}
|