dsh-mobile-plugin 0.5.5 → 0.5.6
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.
|
@@ -37,6 +37,7 @@ function collectTurnImages(entries, lookbackEntries) {
|
|
|
37
37
|
return byTurn;
|
|
38
38
|
}
|
|
39
39
|
const {
|
|
40
|
+
reasoningText,
|
|
40
41
|
reasoningStepSummary,
|
|
41
42
|
toolStepSummary,
|
|
42
43
|
toolStepState,
|
|
@@ -516,7 +517,8 @@ function deriveMessages(events, sessionId, lookbackEvents) {
|
|
|
516
517
|
content.forEach((raw, index) => {
|
|
517
518
|
if (!raw || typeof raw !== 'object') return;
|
|
518
519
|
if (raw.type === 'reasoning') {
|
|
519
|
-
|
|
520
|
+
// 签名块先剥掉再判空:只剩签名的那一段等于没有推理,不算一步(桌面那边是整行不显示)。
|
|
521
|
+
const text = reasoningText(raw.text);
|
|
520
522
|
// 空推理块(只有零宽字符那种)不算一步:App 点开一条什么都没有的行没有意义。
|
|
521
523
|
if (text.trim() === '') return;
|
|
522
524
|
list.push({
|
package/lib/mobile/live-steps.js
CHANGED
|
@@ -23,7 +23,7 @@ const MAX_SESSIONS = 4;
|
|
|
23
23
|
const TEXT_MAX = 200_000;
|
|
24
24
|
|
|
25
25
|
const { liveStepTurnOf } = require('./session-cache.js');
|
|
26
|
-
const { reasoningStepSummary, toolStepSummary } = require('./step-index.js');
|
|
26
|
+
const { reasoningText, reasoningStepSummary, toolStepSummary } = require('./step-index.js');
|
|
27
27
|
|
|
28
28
|
function bucketOf(ctx) {
|
|
29
29
|
return liveStepTurnOf(ctx);
|
|
@@ -328,8 +328,9 @@ function liveStepOf(ctx, sessionId, query) {
|
|
|
328
328
|
if (query && query.kind === 'think') {
|
|
329
329
|
const index = Number.isSafeInteger(query.index) ? query.index : null;
|
|
330
330
|
if (index === null) return null;
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
// 签名块在展示前剥掉(与桌面同口径);剥完没有正文,这一段思考就当还没有内容。
|
|
332
|
+
const text = reasoningText(turn.thoughts.get(index));
|
|
333
|
+
if (text === '') return null;
|
|
333
334
|
return { kind: 'think', text, live: true, state: turn.ended ? 'ok' : 'running' };
|
|
334
335
|
}
|
|
335
336
|
const callId = query && typeof query.callId === 'string' ? query.callId : '';
|
|
@@ -20,7 +20,7 @@ const { sendJson } = require('../shared/http-util');
|
|
|
20
20
|
const { unwrap } = require('./envelope.js');
|
|
21
21
|
const { callSessions } = require('./rpc.js');
|
|
22
22
|
const { liveStepOf } = require('./live-steps.js');
|
|
23
|
-
const { textOfParts } = require('./step-index.js');
|
|
23
|
+
const { reasoningText, textOfParts } = require('./step-index.js');
|
|
24
24
|
|
|
25
25
|
/** 详情单段文本的上限(参数 / 输出 / 思考全文各自适用)。 */
|
|
26
26
|
const DETAIL_MAX_CHARS = 200_000;
|
|
@@ -106,7 +106,9 @@ async function historyStep(ctx, { sessionId, kind, callId, seq, index, resultSeq
|
|
|
106
106
|
const message = target && target.data && target.data.message;
|
|
107
107
|
const content = message && Array.isArray(message.content) ? message.content : [];
|
|
108
108
|
const block = content[index];
|
|
109
|
-
|
|
109
|
+
// 签名块(`<signature>…</signature>`)先剥掉再判断有没有正文:宿主数据里那段还在,
|
|
110
|
+
// 桌面的剥法是渲染层的,这里不跟着剥就会把一整段签名原文摊给用户看。
|
|
111
|
+
const text = block && block.type === 'reasoning' ? reasoningText(block.text) : '';
|
|
110
112
|
if (!text) return null;
|
|
111
113
|
const capped = capText(text);
|
|
112
114
|
return { kind: 'think', state: 'ok', text: capped.text, ...(capped.truncated ? { truncated: true } : {}) };
|
package/lib/mobile/step-index.js
CHANGED
|
@@ -24,9 +24,34 @@ function clampSummary(text, max = STEP_SUMMARY_MAX) {
|
|
|
24
24
|
return `${value.slice(0, max - 1)}…`;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 推理正文里模型带的签名块(`<signature>…</signature>`)在展示前剥掉。
|
|
29
|
+
*
|
|
30
|
+
* 桌面从 0.2.1-rc.5 起在渲染层做同一件事,但宿主存的会话数据里那段还在 —— 手机不从数据里
|
|
31
|
+
* 剥一遍,清单摘要那第一行就是一串 base64、展开详情整段噪声。流式期间只写到半截签名
|
|
32
|
+
* (`<sig`)时返回空串,不让它先闪一下再消失;剥完什么都不剩的块等于没有推理,调用方按空处理。
|
|
33
|
+
*/
|
|
34
|
+
function reasoningText(text) {
|
|
35
|
+
const value = typeof text === 'string' ? text : '';
|
|
36
|
+
if (value[0] !== '<') return value;
|
|
37
|
+
const opening = '<signature>';
|
|
38
|
+
if (opening.startsWith(value)) return '';
|
|
39
|
+
if (!value.startsWith(opening)) return value;
|
|
40
|
+
const closing = '</signature>';
|
|
41
|
+
const end = value.indexOf(closing, opening.length);
|
|
42
|
+
if (end === -1) return '';
|
|
43
|
+
let start = end + closing.length;
|
|
44
|
+
while (start < value.length) {
|
|
45
|
+
if (value[start] === '\n') start += 1;
|
|
46
|
+
else if (value[start] === '\r' && value[start + 1] === '\n') start += 2;
|
|
47
|
+
else break;
|
|
48
|
+
}
|
|
49
|
+
return value.slice(start);
|
|
50
|
+
}
|
|
51
|
+
|
|
27
52
|
/** 推理正文的一行摘要。 */
|
|
28
53
|
function reasoningStepSummary(text) {
|
|
29
|
-
return clampSummary(firstLine(text));
|
|
54
|
+
return clampSummary(firstLine(reasoningText(text)));
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
/** 参数 JSON → 对象;解析不了就返回空对象(畸形参数不该让清单少一条)。 */
|
|
@@ -100,6 +125,7 @@ module.exports = {
|
|
|
100
125
|
STEP_SUMMARY_MAX,
|
|
101
126
|
firstLine,
|
|
102
127
|
clampSummary,
|
|
128
|
+
reasoningText,
|
|
103
129
|
reasoningStepSummary,
|
|
104
130
|
parseArgs,
|
|
105
131
|
toolStepSummary,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mobile-plugin",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "Mobile API (/api/mobile/v1) and relay client for the DSH mobile app — desktop profile build (dsh 0.2.x, peers resolved by the host)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"icon": "./icon.png",
|