virlen-remote 0.5.0 → 0.6.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +362 -169
  2. package/README.md +389 -201
  3. package/dist/index.d.ts +10 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +10 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/protocol/agents.d.ts +14 -0
  8. package/dist/protocol/agents.d.ts.map +1 -0
  9. package/dist/protocol/agents.js +14 -0
  10. package/dist/protocol/agents.js.map +1 -0
  11. package/dist/protocol/api.d.ts +356 -1
  12. package/dist/protocol/api.d.ts.map +1 -1
  13. package/dist/protocol/api.js.map +1 -1
  14. package/dist/protocol/compress.d.ts +55 -0
  15. package/dist/protocol/compress.d.ts.map +1 -0
  16. package/dist/protocol/compress.js +60 -0
  17. package/dist/protocol/compress.js.map +1 -0
  18. package/dist/protocol/files.d.ts +261 -0
  19. package/dist/protocol/files.d.ts.map +1 -0
  20. package/dist/protocol/files.js +506 -0
  21. package/dist/protocol/files.js.map +1 -0
  22. package/dist/protocol/host.d.ts +24 -1
  23. package/dist/protocol/host.d.ts.map +1 -1
  24. package/dist/protocol/host.js +9 -1
  25. package/dist/protocol/host.js.map +1 -1
  26. package/dist/protocol/message-files.d.ts +79 -0
  27. package/dist/protocol/message-files.d.ts.map +1 -0
  28. package/dist/protocol/message-files.js +118 -0
  29. package/dist/protocol/message-files.js.map +1 -0
  30. package/dist/protocol/tool-args.d.ts +95 -0
  31. package/dist/protocol/tool-args.d.ts.map +1 -0
  32. package/dist/protocol/tool-args.js +439 -0
  33. package/dist/protocol/tool-args.js.map +1 -0
  34. package/dist/testing/mock-host.d.ts +44 -1
  35. package/dist/testing/mock-host.d.ts.map +1 -1
  36. package/dist/testing/mock-host.js +439 -10
  37. package/dist/testing/mock-host.js.map +1 -1
  38. package/dist/transport/rtc.d.ts +17 -0
  39. package/dist/transport/rtc.d.ts.map +1 -1
  40. package/dist/transport/rtc.js +49 -12
  41. package/dist/transport/rtc.js.map +1 -1
  42. package/dist/transport/signaling.d.ts +12 -1
  43. package/dist/transport/signaling.d.ts.map +1 -1
  44. package/dist/transport/signaling.js +17 -3
  45. package/dist/transport/signaling.js.map +1 -1
  46. package/package.json +69 -69
  47. package/src/index.ts +270 -184
  48. package/src/protocol/agents.ts +13 -0
  49. package/src/protocol/api.ts +960 -615
  50. package/src/protocol/compress.ts +65 -0
  51. package/src/protocol/files.ts +544 -0
  52. package/src/protocol/host.ts +205 -165
  53. package/src/protocol/message-actions.ts +60 -60
  54. package/src/protocol/message-files.ts +161 -0
  55. package/src/protocol/pairing.ts +254 -254
  56. package/src/protocol/tool-args.ts +478 -0
  57. package/src/testing/mock-host.ts +1285 -740
  58. package/src/transport/link-kind.ts +222 -222
  59. package/src/transport/rtc.ts +381 -344
  60. package/src/transport/signaling.ts +331 -317
  61. package/src/transport/transfer-tier.ts +64 -64
@@ -0,0 +1,439 @@
1
+ /**
2
+ * 工具入参摘要 —— 「这一步工具到底在干什么」的**唯一格式化口径**。
3
+ *
4
+ * 为什么单列一个模块:手机屏上一行只放得下一步工具调用,而**哪几个键才是关键入参**是随
5
+ * 工具而变的(`read_file` 看路径、`execute_command` 看命令、`search_text_in_files` 看
6
+ * 「在哪儿搜什么」)。这份知识原先只存在于桌面端的 28 个 `getShortText()` 组件里 ——
7
+ * 手机端拿不到,于是真机反馈是「工具气泡只有工具名,看不到编辑的是哪个文件、执行的是什么命令」。
8
+ *
9
+ * 三条纪律(与桌面 `tool-call/primary-path.ts` 同源):
10
+ *
11
+ * 1. **按工具名取键**:键名以 `tool_defs/definitions.json` 为准(那是权威契约,本文件
12
+ * 只挑「主参数」)——不用「给每个工具加一个方法」那种写法,那是把同一件事抄 28 遍;
13
+ * 2. **拿不到就不猜**:没有可用的关键入参 → `undefined`,手机端只显示工具名(宁可不显示,
14
+ * 也不要显示一句听起来像那么回事的假话);
15
+ * 3. **只给摘要,不给原文**:`write_file.content` / `edit_file.edits[].old_string` 可能是
16
+ * 整篇文章,原样下行就是流量事故(§7-⑦ 同一条纪律)。长度有硬上限,超长一律截断。
17
+ *
18
+ * 产出是**纯文本、纯函数**:同一份实现同时供真实电脑侧(`bridge/dto.ts`)与演示宿主
19
+ * (`testing/mock-host.ts`)使用,两端不会漂移。
20
+ *
21
+ * 本模块承担工具调用的**两种呈现**(两级粒度,别混用):
22
+ * - {@link summarizeToolArgs} —— **折叠态**的一行摘要(硬上限 {@link TOOL_ARGS_MAX} = 160);
23
+ * - {@link formatToolArgs} —— **展开态**的完整入参(上限 {@link TOOL_DETAIL_MAX} = 5000,
24
+ * 超出走中间省略 {@link elideMiddle})。
25
+ * 两级共用同一个 `shortenPath` 回调:同一份路径不能在折叠态与展开态显示成两个样子。
26
+ */
27
+ /** 摘要长度硬上限:手机一行放不下更多,也避免长命令 / 长路径把帧撑大。 */
28
+ export const TOOL_ARGS_MAX = 160;
29
+ /**
30
+ * 各工具的「主参数」键名(按优先级),键名取自 `tool_defs/definitions.json`。
31
+ *
32
+ * 只列**需要与兜底顺序不同**的工具:其余工具(`file_info` / `vision_analyze` / `mkdir` …)
33
+ * 的主参数就是 `path`,交给下面的通用规则即可。
34
+ */
35
+ const PRIMARY_KEYS = {
36
+ read_file: ['path', 'paths'],
37
+ delete_file: ['path', 'paths'],
38
+ mkdir: ['path', 'paths'],
39
+ execute_script: ['file_path'],
40
+ search_knowledge_base: ['query'],
41
+ list_knowledge_base_documents: ['knowledge_base_id'],
42
+ get_knowledge_base_document: ['document_id', 'knowledge_base_id'],
43
+ write_to_knowledge_base: ['document_name'],
44
+ delete_knowledge_base_document: ['document_id', 'knowledge_base_id'],
45
+ web_search: ['query'],
46
+ web_fetch: ['url'],
47
+ read_skill_source: ['name'],
48
+ read_messages: ['message_id'],
49
+ list_messages: ['keyword'],
50
+ user_choice: ['question'],
51
+ };
52
+ /**
53
+ * 兜底顺序 —— 未知工具(协议比工具集新 / 旧)也给出一个像样的摘要。
54
+ *
55
+ * `path` 在 `query` 之前:与桌面 `DefaultMessage` 的取舍一致(它也是优先取 `path`),
56
+ * 这种「同一种入参键在两端必须是同一个含义」的规则不该各写一份。
57
+ */
58
+ const FALLBACK_KEYS = [
59
+ 'command',
60
+ 'path',
61
+ 'paths',
62
+ 'file_path',
63
+ 'url',
64
+ 'query',
65
+ 'keyword',
66
+ 'name',
67
+ 'document_name',
68
+ 'document_id',
69
+ 'knowledge_base_id',
70
+ 'message_id',
71
+ 'question',
72
+ ];
73
+ /**
74
+ * 生成一行入参摘要;没有可显示的内容时返回 `undefined`。
75
+ *
76
+ * 未知工具走兜底键序;一个都不命中时用「键=值」拼(最多两个键)——那是桌面
77
+ * `DefaultMessage` 的行为,手机端不需要比它更聪明,但需要至少能看出「调了什么」。
78
+ */
79
+ export function summarizeToolArgs(name, input, options = {}) {
80
+ const max = options.maxLength ?? TOOL_ARGS_MAX;
81
+ // 入参可能是 JSON 字符串(引擎透传 / 老数据),先解开再当对象用
82
+ const record = asRecord(input);
83
+ if (!record) {
84
+ /*
85
+ * 看起来像 JSON 却解不开(老数据可能被截断)→ **不给摘要**:半截 JSON 不是信息,
86
+ * 是噪音 —— 手机屏上一行「{ "path": "src/a」除了占地方什么也说明不了。
87
+ */
88
+ if (typeof input === 'string' && looksLikeJson(input))
89
+ return undefined;
90
+ const text = scalarText(input);
91
+ return text ? clip(collapse(text), max) : undefined;
92
+ }
93
+ const short = options.shortenPath ?? ((path) => path);
94
+ const text = summarize(name, record, short);
95
+ return text ? clip(collapse(text), max) : undefined;
96
+ }
97
+ function summarize(name, rec, short) {
98
+ switch (name) {
99
+ // 命令就是这件事本身(tips 是模型的解释,放不进行内摘要,留给桌面卡片)
100
+ case 'execute_command':
101
+ return scalarText(rec.command);
102
+ case 'copy_move_file': {
103
+ const source = pathText(rec.source, short);
104
+ const dest = pathText(rec.destination, short);
105
+ if (!source && !dest)
106
+ return undefined;
107
+ if (source && dest)
108
+ return `${source} → ${dest}`;
109
+ return source || dest;
110
+ }
111
+ /*
112
+ * 搜索类:桌面文案是「在 X 中搜索 Y」(`SearchTextInFileMessage` /
113
+ * `SearchFileByNameMessage`),手机沿用同一句式 —— 用户在两个屏幕上看到同一句话,
114
+ * 才不需要重新理解一次。
115
+ */
116
+ case 'search_text_in_files':
117
+ case 'search_files_by_name': {
118
+ const root = pathText(rec.path, short);
119
+ const query = scalarText(rec.query);
120
+ if (root && query)
121
+ return `在 ${root} 中搜索 ${query}`;
122
+ return query ?? root;
123
+ }
124
+ case 'read_file': {
125
+ const paths = pathList(rec, short);
126
+ if (!paths)
127
+ return undefined;
128
+ const range = readRange(rec);
129
+ return range ? `${paths} ${range}` : paths;
130
+ }
131
+ case 'write_file': {
132
+ const path = pathText(rec.path, short);
133
+ if (!path)
134
+ return undefined;
135
+ const lines = typeof rec.content === 'string' ? countLines(rec.content) : 0;
136
+ return lines > 0 ? `${path} · 写入 ${lines} 行` : path;
137
+ }
138
+ case 'edit_file': {
139
+ const path = pathText(rec.path, short);
140
+ const stat = editStat(rec);
141
+ if (!path)
142
+ return stat;
143
+ return stat ? `${path} · ${stat}` : path;
144
+ }
145
+ // 清单只在桌面的标题栏浮层里看;消息流这一行只需说明「改了流程」(桌面同一句文案)
146
+ case 'todo_write': {
147
+ const todos = rec.todos;
148
+ if (Array.isArray(todos))
149
+ return `更新了 ${todos.length} 项任务`;
150
+ return undefined;
151
+ }
152
+ default:
153
+ break;
154
+ }
155
+ const keys = PRIMARY_KEYS[name] ?? FALLBACK_KEYS;
156
+ for (const key of keys) {
157
+ const value = rec[key];
158
+ if (Array.isArray(value)) {
159
+ const list = listText(value, short);
160
+ if (list)
161
+ return list;
162
+ continue;
163
+ }
164
+ const text = pathOrScalar(key, value, short);
165
+ if (text)
166
+ return text;
167
+ }
168
+ return objectFallback(rec, short);
169
+ }
170
+ /** 一个键都不命中时的兜底:最多两个「键=值」,仍然比一整串 JSON 好读。 */
171
+ function objectFallback(rec, short) {
172
+ const parts = [];
173
+ for (const key of Object.keys(rec)) {
174
+ if (parts.length >= 2)
175
+ break;
176
+ const value = rec[key];
177
+ if (Array.isArray(value))
178
+ continue;
179
+ const text = pathOrScalar(key, value, short);
180
+ if (text)
181
+ parts.push(`${key}=${text}`);
182
+ }
183
+ return parts.length ? parts.join(' ') : undefined;
184
+ }
185
+ /** 路径类键名(这些键的值要过 `shortenPath`,其余原样)。 */
186
+ const PATH_KEYS = new Set(['path', 'paths', 'file_path', 'source', 'destination']);
187
+ function pathOrScalar(key, value, short) {
188
+ if (PATH_KEYS.has(key))
189
+ return pathText(value, short);
190
+ return scalarText(value);
191
+ }
192
+ function pathText(value, short) {
193
+ if (typeof value !== 'string')
194
+ return undefined;
195
+ const trimmed = value.trim();
196
+ return trimmed ? short(trimmed) : undefined;
197
+ }
198
+ /** 路径列表:首项 + `+N`(桌面也是一样只报首项与总数,不铺开一串)。 */
199
+ function listText(values, short) {
200
+ const items = [];
201
+ for (const value of values) {
202
+ const text = pathText(value, short);
203
+ if (text)
204
+ items.push(text);
205
+ }
206
+ if (items.length === 0)
207
+ return undefined;
208
+ if (items.length === 1)
209
+ return items[0];
210
+ return `${items[0]} +${items.length - 1}`;
211
+ }
212
+ /** `path` / `paths` 两种形状统一成一行(批量形态优先:它是这次调用真正的覆盖面)。 */
213
+ function pathList(rec, short) {
214
+ if (Array.isArray(rec.paths)) {
215
+ const text = listText(rec.paths, short);
216
+ if (text)
217
+ return text;
218
+ }
219
+ return pathText(rec.path, short);
220
+ }
221
+ /** `read_file` 的读取范围:`start_line` / `max_lines` 都已知时给出行区间。 */
222
+ function readRange(rec) {
223
+ const start = numberText(rec.start_line);
224
+ if (!start)
225
+ return undefined;
226
+ const max = numberText(rec.max_lines);
227
+ return max ? `${start}-${start + max - 1}` : `${start}`;
228
+ }
229
+ /**
230
+ * `edit_file` 的改动规模。
231
+ *
232
+ * 与桌面 `EditFileMessage` 的**降级分支**同一条算法(没有工具结果 uiData 时按入参行数估):
233
+ * 电脑侧手上只有入参,拿不到那次编辑的精确 diff —— 于是如实给一个「按行数估」的说法,
234
+ * 文案与桌面逐字一致(`减少 X行,新增 Y行`)。
235
+ */
236
+ function editStat(rec) {
237
+ let del = 0;
238
+ let ins = 0;
239
+ const edits = Array.isArray(rec.edits)
240
+ ? rec.edits
241
+ : [{ old_string: rec.old_string, new_string: rec.new_string }];
242
+ for (const edit of edits) {
243
+ const item = asRecord(edit);
244
+ if (!item)
245
+ continue;
246
+ if (typeof item.old_string === 'string')
247
+ del += countLines(item.old_string);
248
+ if (typeof item.new_string === 'string')
249
+ ins += countLines(item.new_string);
250
+ }
251
+ const parts = [];
252
+ if (del > 0)
253
+ parts.push(`减少 ${del}行`);
254
+ if (ins > 0)
255
+ parts.push(`新增 ${ins}行`);
256
+ return parts.length ? parts.join(',') : undefined;
257
+ }
258
+ /** 行数(末尾空行不算,与手机端 `countLines` 同一口径)。 */
259
+ function countLines(text) {
260
+ const body = text.replace(/\n+$/, '');
261
+ return body.trim() ? body.split('\n').length : 0;
262
+ }
263
+ /** 标量 → 文本:字符串 / 数字 / 布尔;其余(对象、数组、null)返回 `undefined`。 */
264
+ function scalarText(value) {
265
+ if (typeof value === 'string')
266
+ return value.trim() || undefined;
267
+ if (typeof value === 'number' && Number.isFinite(value))
268
+ return String(value);
269
+ if (typeof value === 'boolean')
270
+ return String(value);
271
+ return undefined;
272
+ }
273
+ /** 数字键(`start_line` 之类):只认正整数,`0` / 负数 / NaN 一律当没给。 */
274
+ function numberText(value) {
275
+ const n = typeof value === 'string' ? Number(value) : value;
276
+ return typeof n === 'number' && Number.isInteger(n) && n > 0 ? n : undefined;
277
+ }
278
+ /** 对象视图;JSON 字符串也认(宽松解析失败就返回 `undefined`,不抛)。 */
279
+ function asRecord(input) {
280
+ if (input && typeof input === 'object' && !Array.isArray(input)) {
281
+ return input;
282
+ }
283
+ if (typeof input === 'string') {
284
+ const trimmed = input.trim();
285
+ if (!trimmed.startsWith('{'))
286
+ return undefined;
287
+ try {
288
+ const parsed = JSON.parse(trimmed);
289
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
290
+ return parsed;
291
+ }
292
+ }
293
+ catch {
294
+ return undefined;
295
+ }
296
+ }
297
+ return undefined;
298
+ }
299
+ /** 看着像 JSON(对象 / 数组):用于区分「一段普通文本」与「解不开的结构化入参」。 */
300
+ function looksLikeJson(text) {
301
+ const trimmed = text.trim();
302
+ return trimmed.startsWith('{') || trimmed.startsWith('[');
303
+ }
304
+ /** 换行 / 连续空白压成单个空格:多行命令与 JSON 片段在行内摘要里必须是一行。 */
305
+ function collapse(text) {
306
+ return text.replace(/\s+/g, ' ').trim();
307
+ }
308
+ function clip(text, max) {
309
+ return text.length > max ? `${text.slice(0, max)}…` : text;
310
+ }
311
+ // ─────────────────── 展开态的「完整入参」与通用中间省略 ───────────────────
312
+ /**
313
+ * **展开区**文本的长度上限 —— 入参详情与工具输出**共用同一条线**。
314
+ *
315
+ * 与 {@link TOOL_ARGS_MAX} 不是一个量级,也不是一回事:那个是**折叠态一行**能放下多少字,
316
+ * 这个是**展开后**愿意渲染多少字(用户 2026-10 拍板:超了就中间省略)。
317
+ *
318
+ * 为什么是 5000:手机一屏约 30 行 × 40 字,5000 字符已是四屏以上;再长就不叫「看」,
319
+ * 叫「拖着滚」—— 而拖动过程中真正需要的信息(开头在做什么、结尾成没成)都在两头,
320
+ * 中间那段从来没人读完过。
321
+ */
322
+ export const TOOL_DETAIL_MAX = 5000;
323
+ /**
324
+ * 中间省略 —— 头尾都留,挖掉中间。
325
+ *
326
+ * 为什么不「从尾部截断」:工具输出与入参的**结论都在两头** —— 开头是命令 / 标题 / 第一个
327
+ * 文件,结尾是报错 / 汇总 / 最后一个 diff 块。只留头等于把结论切掉,用户还得回电脑前看。
328
+ *
329
+ * ⚠️ 被省略的字符数写进正文里(`…(中间省略 N 字符)…`)——这是「这里少了东西」的
330
+ * **唯一凭证**:只看长度看不出来,一段刚好的 5000 字符与被砍过的 5000 字符无法区分。
331
+ */
332
+ export function elideMiddle(text, max = TOOL_DETAIL_MAX) {
333
+ if (max <= 0)
334
+ return '';
335
+ if (text.length <= max)
336
+ return text;
337
+ // 标记本身也要占额度:先按最坏情况留出余量,末尾再兜一次硬截(结果绝不超上限)
338
+ const keep = Math.max(2, max - MARKER_RESERVE);
339
+ const headLength = Math.ceil(keep / 2);
340
+ const head = text.slice(0, headLength);
341
+ const tail = text.slice(text.length - (keep - headLength));
342
+ const omitted = text.length - head.length - tail.length;
343
+ const result = `${head}\n\n${omittedMark(omitted)}\n\n${tail}`;
344
+ return result.length <= max ? result : result.slice(0, max);
345
+ }
346
+ /** {@link elideMiddle} 的最坏长度预留(标记行 + 首尾换行),用于算「还能留多少原文字符」。 */
347
+ const MARKER_RESERVE = 32;
348
+ function omittedMark(omitted) {
349
+ return `…(中间省略 ${omitted} 字符)…`;
350
+ }
351
+ /**
352
+ * 工具入参的**完整文本**(展开区用):两空格缩进的 JSON,路径按工作目录缩短,超长中间省略。
353
+ *
354
+ * 为什么不把 {@link summarizeToolArgs} 的输出「加长」:摘要只挑**主参数**,而用户点开卡片
355
+ * 想看的恰恰是那行没显示完的部分 —— 还有哪些键、`write_file` 到底写了什么、`edit_file` 的
356
+ * old/new 是什么。唯一忠实的做法是把入参本身摆出来,于是这里与桌面导出
357
+ * (`ui/pages/chat/components/sidebar` 的 `JSON.stringify(tc.input, null, 2)`)用同一种形态。
358
+ *
359
+ * ⚠️ 与摘要「只给摘要、不给原文」的纪律**不同**:这里允许出现正文(`write_file.content`
360
+ * 会原样出现)—— 前提是用户**主动点开**才渲染,总量由 {@link TOOL_DETAIL_MAX} 兜住。
361
+ * 折叠态绝不带它,那才是流量事故的现场。
362
+ *
363
+ * 没有可显示的内容 → `undefined`(展开区不渲染这一块)。
364
+ */
365
+ export function formatToolArgs(input, options = {}) {
366
+ const max = options.maxLength ?? TOOL_DETAIL_MAX;
367
+ const short = options.shortenPath ?? ((path) => path);
368
+ const value = normalizeDetail(input);
369
+ if (value === undefined || isEmptyDetail(value))
370
+ return undefined;
371
+ const text = typeof value === 'object'
372
+ ? JSON.stringify(shortenPathValues(value, short), null, 2)
373
+ : String(value);
374
+ const trimmed = (text ?? '').trim();
375
+ return trimmed ? elideMiddle(trimmed, max) : undefined;
376
+ }
377
+ /**
378
+ * 归一化入参:JSON 字符串解开、普通文本原样、标量转文本,对象 / 数组原样。
379
+ *
380
+ * 解不开的 JSON 字符串**原样给出**(与摘要那边的取舍相反:摘要是「半截 JSON 不是信息」,
381
+ * 而展开区是用户点开来看的现场 —— 模型真发了一段坏 JSON,如实摆出来比藏起来有用)。
382
+ */
383
+ function normalizeDetail(input) {
384
+ if (input === undefined || input === null)
385
+ return undefined;
386
+ if (typeof input === 'string') {
387
+ const trimmed = input.trim();
388
+ if (!trimmed)
389
+ return undefined;
390
+ if (!looksLikeJson(trimmed))
391
+ return trimmed;
392
+ try {
393
+ return JSON.parse(trimmed);
394
+ }
395
+ catch {
396
+ return trimmed;
397
+ }
398
+ }
399
+ if (typeof input === 'object')
400
+ return input;
401
+ return scalarText(input);
402
+ }
403
+ /**
404
+ * 空入参(`{}` / `[]`)→ 没有可展示的内容。
405
+ *
406
+ * 为什么不是把它当「入参为空」显示出来:展开区那一块的唯一职责是回答「刚才调它的时候
407
+ * 到底传了什么」。无参数的工具(`get_current_time` 之类)传了个空对象 —— 摆一个 `{}`
408
+ * 只占地方,反而让用户以为漏显示了什么。
409
+ */
410
+ function isEmptyDetail(value) {
411
+ if (Array.isArray(value))
412
+ return value.length === 0;
413
+ if (value && typeof value === 'object')
414
+ return Object.keys(value).length === 0;
415
+ return false;
416
+ }
417
+ /**
418
+ * 递归把**路径键**的值缩短(键名与 {@link PATH_KEYS} 同一份:`path` / `paths` / `file_path` …)。
419
+ */
420
+ function shortenPathValues(value, short) {
421
+ if (Array.isArray(value))
422
+ return value.map((item) => shortenPathValues(item, short));
423
+ if (!value || typeof value !== 'object')
424
+ return value;
425
+ const out = {};
426
+ for (const [key, raw] of Object.entries(value)) {
427
+ out[key] = PATH_KEYS.has(key) ? shortenPathValue(raw, short) : shortenPathValues(raw, short);
428
+ }
429
+ return out;
430
+ }
431
+ /** 路径键的值:字符串 / 字符串数组缩短,其余按普通值递归。 */
432
+ function shortenPathValue(value, short) {
433
+ if (typeof value === 'string')
434
+ return short(value);
435
+ if (Array.isArray(value))
436
+ return value.map((item) => shortenPathValue(item, short));
437
+ return shortenPathValues(value, short);
438
+ }
439
+ //# sourceMappingURL=tool-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-args.js","sourceRoot":"","sources":["../../src/protocol/tool-args.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
+ import { type CompressMode } from '../protocol/compress.js';
1
2
  import type { HostDataSource, HostEmit } from '../protocol/host.js';
2
- import type { ApprovalTier } from '../protocol/api.js';
3
+ import type { ApprovalTier, RunningToolDTO } from '../protocol/api.js';
3
4
  export interface MockHostOptions {
4
5
  /** 流式段数。 */
5
6
  streamSteps?: number;
@@ -17,6 +18,14 @@ export interface MockHostOptions {
17
18
  * 打开后手机端能看到「工具 · list_files」气泡(harness 人工验证用)。
18
19
  */
19
20
  demoToolMessage?: boolean;
21
+ /**
22
+ * 模拟链路通讯类型(§37):`'relay'` 时**所有 `host.file.*` 一律拒**,
23
+ * 与真实电脑侧的「非中继才给传文件」同一条口径(文案也同一句)。
24
+ *
25
+ * 为何要能模拟:手机端「中继时置灰入口」与「电脑端拒了之后怎么提示」是两条独立分支,
26
+ * 而不给一个会拒的宿主就测不到后者的错误路径。
27
+ */
28
+ fileLinkKind?: 'direct' | 'relay';
20
29
  }
21
30
  /** 构造演示用交互(供 harness / 单测触发手机端卡片)。 */
22
31
  export interface MockInteractionSpec {
@@ -61,6 +70,40 @@ export interface MockHostDataSource extends HostDataSource {
61
70
  name: string;
62
71
  chars: number;
63
72
  } | null): void;
73
+ /**
74
+ * 手动推一次「**正在执行中**的工具」(`RuntimeDTO.runningTools`),供手机端 UI 联调 / 单测。
75
+ *
76
+ * 与 `setToolProgress` 是一对(先后相接的两个阶段):参数累积期看 `toolProgress`,
77
+ * 工具开始执行到结果回来之间看 `runningTools`。传 `null` = **跑完了**(一并把 `working` 收掉,
78
+ * 真机上工具跑完要么接着下一轮、要么整个 run 结束);传空数组 = 这次执行中的工具都结束了,
79
+ * 但会话仍在跑(模型正在接着思考)。
80
+ *
81
+ * ⚠️ 真实电脑侧没有这个「手动口」:那些字段是 `store-bridge` 从会话消息(assistant 的
82
+ * `toolCalls[]` 减去已有结果)**推导**出来的(§27 的姊妹字段),mock 手推是为了让手机端
83
+ * 在**没有引擎**的情况下也能看到这一帧。
84
+ */
85
+ setRunningTools(sessionId: string, tools: RunningToolDTO[] | null): void;
86
+ /**
87
+ * 读一份**演示文件树**里的文件(测试 / harness 断言用)—— `null` = 不存在。
88
+ *
89
+ * 为什么需要:上传是否真的落到「正确的相对路径、正确的字节」只能从宿主侧看,
90
+ * 而手机端的 RPC 应答只说「成功了」。只测应答 = 测了个寂寞。
91
+ */
92
+ readMockFile(sessionId: string, relPath: string): Uint8Array | null;
93
+ /** 往演示文件树里放一个文件(建目录是隐式的)。 */
94
+ writeMockFile(sessionId: string, relPath: string, content: string | Uint8Array): void;
95
+ /** 当前文件树里的全部相对路径(排序后)。 */
96
+ listMockFiles(sessionId: string): string[];
97
+ /**
98
+ * 最后**真正执行**的那次压缩(`null` = 还没压过)—— 测试 / harness 观察口。
99
+ *
100
+ * 为什么需要:手机端的 RPC 应答只是一句 `{ok:true}`,它只说「电脑侧受理了」,**不说用了哪种方式**
101
+ * —— 而「选中了正文压缩却走了 AI 摘要(还花了钱)」正是这个参数最危险的失败形态。
102
+ */
103
+ lastCompress(): {
104
+ sessionId: string;
105
+ mode: CompressMode;
106
+ } | null;
64
107
  }
65
108
  export declare function createMockHostDataSource(options?: MockHostOptions): MockHostDataSource;
66
109
  //# sourceMappingURL=mock-host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mock-host.d.ts","sourceRoot":"","sources":["../../src/testing/mock-host.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEhE,OAAO,KAAK,EAGV,YAAY,EAkBb,MAAM,iBAAiB,CAAA;AAGxB,MAAM,WAAW,eAAe;IAC9B,YAAY;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gBAAgB;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,sCAAsC;AACtC,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,eAAe,CAAA;IACjC,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;CACpC;AAED,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,iDAAiD;IACjD,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC1B,wCAAwC;IACxC,kBAAkB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAAA;IACtD,mBAAmB;IACnB,mBAAmB,IAAI,MAAM,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,gDAAgD;IAChD,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;;;OAKG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,IAAI,CAAA;CAC3F;AAqBD,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,eAAoB,GAAG,kBAAkB,CA0kB1F"}
1
+ {"version":3,"file":"mock-host.d.ts","sourceRoot":"","sources":["../../src/testing/mock-host.ts"],"names":[],"mappings":"AAyBA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAA;AA2B7B,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEhE,OAAO,KAAK,EAIV,YAAY,EA0BZ,cAAc,EAKf,MAAM,iBAAiB,CAAA;AAGxB,MAAM,WAAW,eAAe;IAC9B,YAAY;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gBAAgB;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAClC;AAED,sCAAsC;AACtC,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,eAAe,CAAA;IACjC,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;CACpC;AAED,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,iDAAiD;IACjD,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC1B,wCAAwC;IACxC,kBAAkB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAAA;IACtD,mBAAmB;IACnB,mBAAmB,IAAI,MAAM,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,gDAAgD;IAChD,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;;;OAKG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,IAAI,CAAA;IAC1F;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;IACxE;;;;;OAKG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAA;IACnE,6BAA6B;IAC7B,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAA;IACrF,0BAA0B;IAC1B,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC1C;;;;;OAKG;IACH,YAAY,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAE,GAAG,IAAI,CAAA;CACjE;AA8HD,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,eAAoB,GAAG,kBAAkB,CA86B1F"}