dsh-mobile-plugin 0.5.1 → 0.5.3
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/mobile/agent-presets.js +67 -1
- package/lib/mobile/debug-trace.js +180 -0
- package/lib/mobile/deepseek-account.js +3 -0
- package/lib/mobile/entry-window.js +6 -1
- package/lib/mobile/history-derive.js +148 -9
- package/lib/mobile/local-images.js +200 -47
- package/lib/mobile/session-local-image.js +45 -0
- package/lib/mobile/session-mirror.js +2 -1
- package/lib/mobile/session-send.js +13 -1
- package/lib/mobile/session-snapshot.js +37 -54
- package/lib/mobile/session-stats.js +51 -0
- package/lib/mobile/sessions.js +3 -2
- package/lib/mobile/tool-result-cache.js +75 -0
- package/lib/panel/index.html +6 -6
- package/lib/relay/firewall-probe.js +11 -5
- package/lib/routes/mobile-api.js +11 -0
- package/lib/sidecar-lifecycle.cjs +18 -1
- package/lib/update-install.cjs +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 「这一页里只看到工具调用、看不到它的结果」时的补救:把结果记在进程里,供更早的页用。
|
|
5
|
+
*
|
|
6
|
+
* 为什么需要:历史是倒着分页取的(`beforeSeq`),一页的事件是 `[oldest, beforeSeq)`。而
|
|
7
|
+
* `tool/result` 事件的 seq 比「发起这次调用的 assistant 消息」**大** —— 边界正好切在两者
|
|
8
|
+
* 之间时,那一页只看得到调用,看不到结果,于是那条消息的工具图缺一块;等下一页(更新的一页,
|
|
9
|
+
* 本机早就拿到过)把结果带回来再补,手机侧那一行已经从「没图」的高度长到「有图」的高度,
|
|
10
|
+
* 而它在用户头顶上 —— 一变就把正看的内容推走(真机录制:同一条消息 589 ↔ 817 来回)。
|
|
11
|
+
*
|
|
12
|
+
* 做法:每次投影都把这一页看到的结果记下来;下一次投影更早的页时,把这些记下的结果一并喂给
|
|
13
|
+
* `deriveMessages`,图就跟着消息一起下发,行在挂载那一帧就是终高。
|
|
14
|
+
*
|
|
15
|
+
* 边界:只活在插件进程里、只按会话分桶、每桶按插入序淘汰 —— 进程重启就没了,那时手机重新
|
|
16
|
+
* 进对话本来也要重拉。
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** 每条会话记住多少个调用:一次翻页窗口最多几百个,2000 足够覆盖一次通读。 */
|
|
20
|
+
const MAX_CALLS_PER_SESSION = 2000;
|
|
21
|
+
/** 同时记几条会话:手机一般只在一两条会话里翻历史。 */
|
|
22
|
+
const MAX_SESSIONS = 8;
|
|
23
|
+
|
|
24
|
+
/** sessionId → Map(callId → 结果)。Map 的插入序就是淘汰序。 */
|
|
25
|
+
const stores = new Map();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 记住这一页看到的结果(已存在的不覆盖:同一次调用的结果不会变,先记下的就是它)。
|
|
29
|
+
*/
|
|
30
|
+
function rememberToolResults(sessionId, results) {
|
|
31
|
+
if (!sessionId || !results || results.size === 0) return;
|
|
32
|
+
let bucket = stores.get(sessionId);
|
|
33
|
+
if (!bucket) {
|
|
34
|
+
bucket = new Map();
|
|
35
|
+
stores.set(sessionId, bucket);
|
|
36
|
+
// 新会话进来,把最旧的那条挤掉。
|
|
37
|
+
while (stores.size > MAX_SESSIONS) {
|
|
38
|
+
const oldest = stores.keys().next();
|
|
39
|
+
if (oldest.done) break;
|
|
40
|
+
stores.delete(oldest.value);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// 读到就挪到末尾(按使用序淘汰,而不是按写入序)。
|
|
44
|
+
stores.delete(sessionId);
|
|
45
|
+
stores.set(sessionId, bucket);
|
|
46
|
+
}
|
|
47
|
+
for (const [callId, result] of results) {
|
|
48
|
+
if (bucket.has(callId)) continue;
|
|
49
|
+
bucket.set(callId, result);
|
|
50
|
+
if (bucket.size > MAX_CALLS_PER_SESSION) {
|
|
51
|
+
const oldest = bucket.keys().next();
|
|
52
|
+
if (oldest.done) break;
|
|
53
|
+
bucket.delete(oldest.value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** 这条会话已经记下的结果(没有就是 empty Map)。调用方不要改它。 */
|
|
59
|
+
function toolResultsFor(sessionId) {
|
|
60
|
+
return (sessionId && stores.get(sessionId)) || null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 测试用:清掉一条(或全部)会话的记录。 */
|
|
64
|
+
function clearToolResults(sessionId) {
|
|
65
|
+
if (sessionId) stores.delete(sessionId);
|
|
66
|
+
else stores.clear();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
rememberToolResults,
|
|
71
|
+
toolResultsFor,
|
|
72
|
+
clearToolResults,
|
|
73
|
+
MAX_CALLS_PER_SESSION,
|
|
74
|
+
MAX_SESSIONS,
|
|
75
|
+
};
|