@yfwu2020/dsh-selection-explain 0.10.4 → 0.10.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.
Files changed (120) hide show
  1. package/README.md +13 -11
  2. package/cordis.patch.yml +1 -1
  3. package/lib/client.js +10698 -12424
  4. package/lib/client.js.map +7 -0
  5. package/lib/config-values.js +55 -0
  6. package/lib/config-values.js.map +1 -0
  7. package/lib/host/analyze.js +795 -0
  8. package/lib/host/analyze.js.map +1 -0
  9. package/lib/host/config.js +81 -0
  10. package/lib/host/config.js.map +1 -0
  11. package/lib/host/constants.js +25 -0
  12. package/lib/host/constants.js.map +1 -0
  13. package/lib/host/context.js +237 -0
  14. package/lib/host/context.js.map +1 -0
  15. package/lib/host/design-skill.js +42 -0
  16. package/lib/host/design-skill.js.map +1 -0
  17. package/lib/host/effort.js +239 -0
  18. package/lib/host/effort.js.map +1 -0
  19. package/lib/host/filters.js +132 -0
  20. package/lib/host/filters.js.map +1 -0
  21. package/lib/host/history-store.js +404 -0
  22. package/lib/host/history-store.js.map +1 -0
  23. package/lib/host/http.js +46 -0
  24. package/lib/host/http.js.map +1 -0
  25. package/lib/host/messages.js +14 -0
  26. package/lib/host/messages.js.map +1 -0
  27. package/lib/host/mic.js +246 -0
  28. package/lib/host/mic.js.map +1 -0
  29. package/lib/host/models.js +246 -0
  30. package/lib/host/models.js.map +1 -0
  31. package/lib/host/plugin.js +41 -0
  32. package/lib/host/plugin.js.map +1 -0
  33. package/lib/host/promote.js +219 -0
  34. package/lib/host/promote.js.map +1 -0
  35. package/lib/host/routes.js +237 -0
  36. package/lib/host/routes.js.map +1 -0
  37. package/lib/host/sessions.js +181 -0
  38. package/lib/host/sessions.js.map +1 -0
  39. package/lib/host/settings-store.js +140 -0
  40. package/lib/host/settings-store.js.map +1 -0
  41. package/lib/host/speech.js +320 -0
  42. package/lib/host/speech.js.map +1 -0
  43. package/lib/host/tools.js +179 -0
  44. package/lib/host/tools.js.map +1 -0
  45. package/lib/host/types.js +2 -0
  46. package/lib/host/types.js.map +1 -0
  47. package/lib/index.js +10 -3765
  48. package/lib/index.js.map +1 -1
  49. package/lib/prompts.js +1 -1
  50. package/lib/settings.js +17 -27
  51. package/lib/settings.js.map +1 -1
  52. package/lib/types/config-values.d.ts +175 -0
  53. package/lib/types/host/analyze.d.ts +10 -0
  54. package/lib/types/host/config.d.ts +147 -0
  55. package/lib/types/host/constants.d.ts +24 -0
  56. package/lib/types/host/context.d.ts +41 -0
  57. package/lib/types/host/design-skill.d.ts +1 -0
  58. package/lib/types/host/effort.d.ts +61 -0
  59. package/lib/types/host/filters.d.ts +20 -0
  60. package/lib/types/host/history-store.d.ts +13 -0
  61. package/lib/types/host/http.d.ts +8 -0
  62. package/lib/types/host/messages.d.ts +13 -0
  63. package/lib/types/host/mic.d.ts +17 -0
  64. package/lib/types/host/models.d.ts +57 -0
  65. package/lib/types/host/plugin.d.ts +3 -0
  66. package/lib/types/host/promote.d.ts +9 -0
  67. package/lib/types/host/routes.d.ts +14 -0
  68. package/lib/types/host/sessions.d.ts +14 -0
  69. package/lib/types/host/settings-store.d.ts +8 -0
  70. package/lib/types/host/speech.d.ts +23 -0
  71. package/lib/types/host/tools.d.ts +39 -0
  72. package/lib/types/host/types.d.ts +89 -0
  73. package/lib/types/index.d.ts +12 -441
  74. package/lib/types/prompts.d.ts +1 -1
  75. package/lib/types/settings.d.ts +1 -1
  76. package/package.json +31 -21
  77. package/assets/code.png +0 -0
  78. package/assets/detail.png +0 -0
  79. package/assets/quotes.png +0 -0
  80. package/assets/stage1.png +0 -0
  81. package/assets/stage2.png +0 -0
  82. package/assets/translation.png +0 -0
  83. package/assets/voice-card-light.png +0 -0
  84. package/assets/voice-inserted.png +0 -0
  85. package/assets/voice-settings.png +0 -0
  86. package/assets/voice.png +0 -0
  87. package/assets/web.png +0 -0
  88. package/scripts/build-demo-pages.mjs +0 -350
  89. package/scripts/build-vcard-lab.mjs +0 -834
  90. package/scripts/build.sh +0 -147
  91. package/scripts/crop-png.mjs +0 -142
  92. package/scripts/dump-prompt.mjs +0 -143
  93. package/scripts/fixtures/fake-mic-probe.sh +0 -9
  94. package/scripts/gen-star-path.mjs +0 -71
  95. package/scripts/measure-cost.mjs +0 -251
  96. package/scripts/smoke-bridge.mjs +0 -365
  97. package/scripts/smoke-panel.mjs +0 -1903
  98. package/scripts/smoke-voice.mjs +0 -774
  99. package/scripts/test-bridge.mjs +0 -412
  100. package/scripts/test-client.mjs +0 -6175
  101. package/scripts/test-effort-map.mjs +0 -129
  102. package/scripts/test-effort-retry.mjs +0 -109
  103. package/scripts/test-escape-focus.mjs +0 -101
  104. package/scripts/test-filters.mjs +0 -146
  105. package/scripts/test-format.mjs +0 -93
  106. package/scripts/test-guard.mjs +0 -48
  107. package/scripts/test-mic-build.mjs +0 -146
  108. package/scripts/test-mic-idle.mjs +0 -158
  109. package/scripts/test-model-follow.mjs +0 -193
  110. package/scripts/test-prompt.mjs +0 -193
  111. package/scripts/test-route-cache.mjs +0 -138
  112. package/scripts/test-settings-behavior.mjs +0 -188
  113. package/scripts/test-settings-host.mjs +0 -48
  114. package/scripts/test-settings.mjs +0 -329
  115. package/scripts/test-speech.mjs +0 -220
  116. package/scripts/test-transcript.mjs +0 -151
  117. package/src/client/index.js +0 -12580
  118. package/src/index.ts +0 -4254
  119. package/src/prompts.ts +0 -144
  120. package/src/settings.ts +0 -313
@@ -0,0 +1,239 @@
1
+ /**
2
+ * 设置页那四个格子(**规范档位**)。
3
+ *
4
+ * 它们不是发给模型的 id,而是一份"意图词汇":关(尽量不思考)/ 低 / 高 / 最高。
5
+ * 各 adapter 的档位词汇表并不统一 —— 本机 74 个模型上就数出七种:
6
+ * off>low>high>max / low>high>max / high>max / off>minimal>low>medium>high /
7
+ * off>low>medium>high>xhigh>max / low>medium>high>xhigh / minimal>low>medium>high>xhigh /
8
+ * max(只有一档)/ 一档都不声明(不支持推理)。
9
+ * 落到哪个真实档位由 `mapEffortToModel` 算(纯函数,有单测)。
10
+ */
11
+ const EFFORT_CANONICAL = ['off', 'low', 'high', 'max'];
12
+ /**
13
+ * 档位名 → "思考深度"刻度(认 id,也认显示名;比较前会去掉空格/下划线/连字符并转小写)。
14
+ *
15
+ * 刻度只用来**比较深浅**,绝对数值没有意义。锚点取最常见的五档:off 0 / low 2 /
16
+ * medium 4 / high 6 / max 8,其余名字插在它们之间(minimal 在 off 与 low 之间、
17
+ * xhigh 在 high 与 max 之间)。认不出的名字不在这张表里 —— 由 `rankEfforts` 按位置插值。
18
+ */
19
+ const EFFORT_RANK = {
20
+ off: 0, none: 0, disabled: 0, no: 0, nocontext: 0,
21
+ minimal: 1, minimum: 1, least: 1, tiny: 1,
22
+ low: 2, light: 2,
23
+ mid: 3, moderate: 3,
24
+ medium: 4,
25
+ high: 6,
26
+ xhigh: 7, veryhigh: 7,
27
+ max: 8, maximum: 8, highest: 8,
28
+ ultra: 9, extreme: 9,
29
+ };
30
+ /** 归一化档位名:'X-High' / 'very high' / 'x_high' 都算一个东西。 */
31
+ function normEffortName(value) {
32
+ return String(value ?? '')
33
+ .trim()
34
+ .toLowerCase()
35
+ .replace(/[\s_-]+/g, '');
36
+ }
37
+ /**
38
+ * 每个声明档位的刻度:认得的名字用表,不认识的按**位置**在已知邻居之间线性插值
39
+ * (两头都没有已知锚点时按序号平铺到 0..8)。最后钳成不递减 —— 各 adapter 的声明都是升序,
40
+ * 插值不该把这个顺序弄反。
41
+ */
42
+ function rankEfforts(declared) {
43
+ const known = declared.map((item) => {
44
+ const byId = EFFORT_RANK[normEffortName(item.id)];
45
+ if (byId !== undefined)
46
+ return byId;
47
+ const byName = EFFORT_RANK[normEffortName(item.name)];
48
+ return byName === undefined ? null : byName;
49
+ });
50
+ const n = declared.length;
51
+ const ranks = [];
52
+ for (let i = 0; i < n; i += 1) {
53
+ const hit = known[i];
54
+ if (hit !== null && hit !== undefined) {
55
+ ranks.push(hit);
56
+ continue;
57
+ }
58
+ let left = -1;
59
+ for (let l = i - 1; l >= 0; l -= 1) {
60
+ if (known[l] !== null && known[l] !== undefined) {
61
+ left = l;
62
+ break;
63
+ }
64
+ }
65
+ let right = -1;
66
+ for (let r = i + 1; r < n; r += 1) {
67
+ if (known[r] !== null && known[r] !== undefined) {
68
+ right = r;
69
+ break;
70
+ }
71
+ }
72
+ const leftRank = left >= 0 ? known[left] : null;
73
+ const rightRank = right >= 0 ? known[right] : null;
74
+ if (leftRank !== null && rightRank !== null) {
75
+ ranks.push(leftRank + ((rightRank - leftRank) * (i - left)) / (right - left));
76
+ }
77
+ else if (leftRank !== null) {
78
+ ranks.push(leftRank + (i - left));
79
+ }
80
+ else if (rightRank !== null) {
81
+ ranks.push(rightRank - (right - i));
82
+ }
83
+ else {
84
+ ranks.push(n > 1 ? (8 * i) / (n - 1) : 0);
85
+ }
86
+ }
87
+ for (let i = 1; i < n; i += 1) {
88
+ if (ranks[i] < ranks[i - 1])
89
+ ranks[i] = ranks[i - 1];
90
+ }
91
+ return ranks;
92
+ }
93
+ /**
94
+ * 规范四格 → 当前模型**真实声明**的档位(返回 '' 表示这个模型没有可发的档位)。
95
+ *
96
+ * 规则一条到底(对 `off>low>high>max` 这类 4 档模型恰好是恒等映射):
97
+ * · 关 → 声明里**最弱**的那档(模型没有 off 这类档时,就是它"能关到"的最小思考)
98
+ * · 最高 → 声明里**最强**的那档
99
+ * · 低/高 → 在整条刻度上取 1/3、2/3 处**最近的档**;候选**排除两端**(最弱那档留给「关」、
100
+ * 最强那档留给「最高」,四个格子于是各有落点),并保证 关 ≤ 低 ≤ 高 ≤ 最高 单调;
101
+ * 同样近时「低」取更浅的、「高」取更深的 —— 低要省、高要深。
102
+ *
103
+ * ⚠️ 这里**没有**任何按模型写死的表:输入只有"这个模型自己声明的档位列表"。
104
+ * 名字认得出来(off/low/high/max、minimal、xhigh…)就用名字的深度刻度;认不出来
105
+ * (别的 adapter 可能叫 a/b/c、tier1/tier2,或者干脆是数字)就按**它在声明里的位置**插值 ——
106
+ * 所以任何用户换任何模型都能落位,插件作者没见过那个模型也能映射。
107
+ * 为什么不让「低/高」也去抢最弱那档:那两个格子表达的是"开着思考、但别太深",
108
+ * 落到"关"那一档等于**把用户要的思考关掉**;只有「关」该动那一档。
109
+ * 只有一档可发时(如 kimi-k3 只有 max),四格都落到它 —— 模型没有别的选择。
110
+ *
111
+ * 返回 '' 表示"这个模型没有可发的档位"(声明为空),调用方据此**不带** reasoningEffort。
112
+ */
113
+ export function mapEffortToModel(declared, canonical) {
114
+ const list = (declared ?? []).filter((item) => item && typeof item.id === 'string' && item.id.length > 0);
115
+ if (list.length === 0)
116
+ return '';
117
+ if (list.length === 1)
118
+ return list[0].id;
119
+ const slot = EFFORT_CANONICAL.includes(canonical) ? canonical : 'off';
120
+ const ranks = rankEfforts(list);
121
+ // 两端:按刻度取最浅/最深;同样深时**以声明顺序为准**(声明在前的那档更弱、在后的更强)。
122
+ // 不能只按下标取首尾:adapter 万一声明得不严格升序,按下标就选错了;也不能只按刻度取最大,
123
+ // 那样 `…>max>ultra` 这种"更强但刻度相同"的档会被 max 抢走。
124
+ let weakest = 0;
125
+ let strongest = 0;
126
+ for (let i = 1; i < list.length; i += 1) {
127
+ if (ranks[i] < ranks[weakest])
128
+ weakest = i;
129
+ if (ranks[i] >= ranks[strongest])
130
+ strongest = i;
131
+ }
132
+ if (slot === 'max')
133
+ return list[strongest].id;
134
+ if (slot !== 'low' && slot !== 'high')
135
+ return list[weakest].id;
136
+ const pool = [];
137
+ for (let i = 0; i < list.length; i += 1) {
138
+ if (i !== weakest && i !== strongest)
139
+ pool.push(i);
140
+ }
141
+ // 中间两档没人可选时(只有"最弱 + 最强"两档):都落到最强 —— 最弱那档留给「关」
142
+ if (pool.length === 0)
143
+ return list[strongest].id;
144
+ const span = ranks[strongest] - ranks[weakest];
145
+ const target = ranks[weakest] + span * (slot === 'low' ? 1 / 3 : 2 / 3);
146
+ const preferDeeper = slot === 'high';
147
+ let best = pool[0];
148
+ let bestDistance = Math.abs(ranks[best] - target);
149
+ for (const index of pool) {
150
+ const distance = Math.abs(ranks[index] - target);
151
+ const closer = distance < bestDistance;
152
+ const tie = distance === bestDistance;
153
+ if (closer || (tie && (preferDeeper ? ranks[index] > ranks[best] : ranks[index] < ranks[best]))) {
154
+ best = index;
155
+ bestDistance = distance;
156
+ }
157
+ }
158
+ return list[best].id;
159
+ }
160
+ /**
161
+ * 一个模型的四格映射(设置页给用户看的就是它;请求时也走这份算)。
162
+ * 返回空串的格子表示"没有可发的档位"(模型不支持推理时四个格子都是空串)。
163
+ */
164
+ export function effortMapOf(declared) {
165
+ const out = {};
166
+ for (const slot of EFFORT_CANONICAL)
167
+ out[slot] = mapEffortToModel(declared, slot);
168
+ return out;
169
+ }
170
+ /**
171
+ * 清单里查不到这个模型时的兜底阶梯。
172
+ * 只列**最常见**的四档(与客户端 `FALLBACK_TIERS` 同一份):多出来的 `medium` 很多模型
173
+ * 并不声明,而 dsh-llm 对"声明里没有的档"是**直接抛错**(不 clamp)—— 兜底时不该去撞它。
174
+ */
175
+ const EFFORT_LADDER_FALLBACK = ['off', 'low', 'high', 'max'];
176
+ /** 档位的中文名(notice 文案用,与客户端 TIER_LABEL 一致)。 */
177
+ export const EFFORT_LABEL = { off: '关', low: '低', medium: '中', high: '高', max: '最大' };
178
+ /**
179
+ * 这条上游错误是不是"**我们发的这个档位**不被接受"。
180
+ *
181
+ * ⚠️ 判据必须窄。免费/预览端点的上游会**偶发**返回
182
+ * `Reasoning is mandatory for this endpoint and cannot be disabled.` ——
183
+ * 2026-10-09 实测(`opencode-go/step-5-preview-free`,交错发送排除时间漂移):
184
+ * · effort=low 成功 5/8;effort=high 成功 5/8 —— **同一档位时好时坏,档位不是变量**;
185
+ * · 对照模型 `longcat-2.5-preview-free` 6/6 成功(连 off 都收)。
186
+ * 所以只认"明确说这个档位无效"的措辞;"必须开推理"另有一条判据
187
+ * (见 looksLikeReasoningRequired,只在**我们发的是关档**时才算数)。
188
+ * 把偶发失败当成"档位不支持"会连锁出三个错:给用户一句错诊断、把失败永久记进
189
+ * noOffRoutes(以后再也不发这个档)、清掉用户选的档位。
190
+ */
191
+ export function looksLikeUnsupportedTier(message) {
192
+ const tier = '(?:reasoning|effort|thinking|推理|思考|档位?)';
193
+ const bad = '(?:unsupported|not\\s+support|invalid|unrecognized|不支持|无效|不认识)';
194
+ return (new RegExp(`${bad}[^。\\n]{0,24}${tier}`, 'i').test(message) ||
195
+ new RegExp(`${tier}[^。\\n]{0,24}${bad}`, 'i').test(message));
196
+ }
197
+ /** 上游要求"必须开推理"——只有在**我们这次把推理关掉**(发的 off)时,这句才是冲我们来的。 */
198
+ export function looksLikeReasoningRequired(message) {
199
+ return (/(?:reasoning|thinking|推理|思考)/i.test(message) &&
200
+ /(?:mandatory|required|must|cannot\s+be\s+disabled|必须|不能(?:被)?关闭|不可关闭)/i.test(message));
201
+ }
202
+ /**
203
+ * 换一个"没试过的"档位(重试用)。
204
+ *
205
+ * 为什么**绝不能省略档位**(老代码就是省略):省略 = 请求里不带 reasoning,
206
+ * 对"必须开推理"的端点等于把推理关掉 —— 实测 20 次这样的重试 **0 次成功**,
207
+ * 而同一档位首发成功率约 60%。省略比"发一个可能不被接受的档"更糟。
208
+ *
209
+ * 顺序:模型自己声明的 defaultEffort → 沿档位阶梯往上走一格(离"关"越远越安全)。
210
+ * 返回空串表示"没档位可换了",调用方就不重试。
211
+ */
212
+ export function pickNextEffort(declared, defaultEffort, rejected, tried) {
213
+ const usable = (id) => !!id && id !== rejected && !tried.has(id);
214
+ if (usable(defaultEffort))
215
+ return defaultEffort;
216
+ // 用**模型自己的声明顺序**(各 adapter 都是从最省到最深),"往上走一格"才落在它真实的下一档上。
217
+ // 老写法是"我方五档阶梯 ∩ 声明",看不见 minimal / xhigh / none 这类 id —— 而按刻度映射之后,
218
+ // 被拒的那个很可能正是这类 id(indexOf 得到 -1 → 退回最弱的那档,方向正好反了)。
219
+ const order = declared.length > 0 ? declared : EFFORT_LADDER_FALLBACK;
220
+ const start = order.indexOf(rejected);
221
+ // ① 先往上走:离「关」越远越安全(不吃 off 的模型通常都吃更高的档)
222
+ for (let i = (start < 0 ? 0 : start + 1); i < order.length; i += 1) {
223
+ const id = order[i];
224
+ if (usable(id))
225
+ return id;
226
+ }
227
+ // ② 再按"通常最稳"的顺序退(模型拒的是 max 时往上没得走,该退到 high,而不是退回 off ——
228
+ // off 恰恰是最容易被拒的那一档)
229
+ for (const id of ['high', 'medium', 'low', 'max', 'off']) {
230
+ if (order.includes(id) && usable(id))
231
+ return id;
232
+ }
233
+ // ③ 兜底:声明里剩下的
234
+ for (const id of order)
235
+ if (usable(id))
236
+ return id;
237
+ return '';
238
+ }
239
+ //# sourceMappingURL=effort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort.js","sourceRoot":"","sources":["../../src/host/effort.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ /** 返回一个 JSON 响应。 */
2
+ /**
3
+ * 把模型**内联在正文里**的思考块拆出来。
4
+ *
5
+ * 为什么要它:有的模型(实测 opencode-go 上的 minimax-m3 偶发)不走 reasoning 通道,
6
+ * 而是把整段思考当正文吐出来,形如 `<think>The user wants…</think>`——
7
+ * 不处理的话,用户看到的"答案"就是一大段思考(实测报过"输出错乱、把思考也输出了")。
8
+ *
9
+ * 流式难点是标签可能被切成两块("...<thi" + "nk>..."),所以没找到标签时**留一小截尾巴**再输出。
10
+ */
11
+ const THINK_TAGS = 'think|thinking|reasoning|analysis|scratchpad';
12
+ const THINK_OPEN = new RegExp(`<(${THINK_TAGS})\\s*>`, 'i');
13
+ const THINK_CLOSE = new RegExp(`</(${THINK_TAGS})\\s*>`, 'i');
14
+ const THINK_TAIL = 24;
15
+ export function createThinkFilter() {
16
+ let buffer = '';
17
+ let inside = false;
18
+ const drain = (final) => {
19
+ let text = '';
20
+ let think = '';
21
+ for (;;) {
22
+ if (inside) {
23
+ const close = THINK_CLOSE.exec(buffer);
24
+ if (!close) {
25
+ if (final) {
26
+ think += buffer;
27
+ buffer = '';
28
+ }
29
+ else if (buffer.length > THINK_TAIL) {
30
+ think += buffer.slice(0, buffer.length - THINK_TAIL);
31
+ buffer = buffer.slice(-THINK_TAIL);
32
+ }
33
+ break;
34
+ }
35
+ think += buffer.slice(0, close.index);
36
+ buffer = buffer.slice(close.index + close[0].length);
37
+ inside = false;
38
+ continue;
39
+ }
40
+ const open = THINK_OPEN.exec(buffer);
41
+ if (!open) {
42
+ if (final) {
43
+ text += buffer;
44
+ buffer = '';
45
+ }
46
+ else if (buffer.length > THINK_TAIL) {
47
+ text += buffer.slice(0, buffer.length - THINK_TAIL);
48
+ buffer = buffer.slice(-THINK_TAIL);
49
+ }
50
+ break;
51
+ }
52
+ text += buffer.slice(0, open.index);
53
+ buffer = buffer.slice(open.index + open[0].length);
54
+ inside = true;
55
+ }
56
+ return { text, think };
57
+ };
58
+ return {
59
+ push: (chunk) => {
60
+ buffer += chunk;
61
+ return drain(false);
62
+ },
63
+ flush: () => drain(true),
64
+ };
65
+ }
66
+ /**
67
+ * 检测"思考被写进正文"的泄漏段。
68
+ *
69
+ * 实测 omen-alpha 在 `off` 档(上游 none)时不走 reasoning 通道,把整段英文推理当正文吐出来:
70
+ * 「The user is asking which model I am. According to my instructions…我是 Omen Alpha。」
71
+ * —— 这种文本**不带任何标签**,靠 `<think>` 过滤器抓不到,只能按"开头是自我盘算"来认。
72
+ *
73
+ * 保守三条件,缺一不裁(宁可留着,也不误删正文):
74
+ * ① 逐句扫描,从开头起连续命中"元推理"句式;
75
+ * ② 命中段以英文为主(≥80% ASCII 字母);
76
+ * ③ 剩下的正文里有中文(说明真正的答案是中文,被裁的不是答案)。
77
+ */
78
+ const META_SENTENCE = /^\s*(?:The user|The question|The request|The person|According to (?:my|the)|Based on (?:my|the)|Per (?:my|the)|My (?:instructions|system prompt|guidelines)|I (?:should|must|need|will|am asked|always|usually|will just)|So I|Thus I|Therefore I|Instructed to|Now I (?:have|need|know|see)|Let me (?:verify|check|think|see|confirm)|I have (?:the|a|enough)|First,? I|OK,? (?:I|let)|用户(?:问|要求)的?是|根据(?:我的)?(?:指令|系统提示)|我应该|我需要|按照(?:我的)?(?:指令|系统提示))/i;
79
+ /**
80
+ * 宽松判据:开头是**英文盘算**、后面才是**中文答案**。
81
+ * 只用来"记住这个模型在关档会泄漏"(下次自动抬档),**不用来裁剪** ——
82
+ * 裁错了会误删正文,而记错了只是下次少一个档位可选,代价不对称。
83
+ */
84
+ export function looksLikeLeakedReasoning(text) {
85
+ const body = String(text || '');
86
+ if (body.length < 40)
87
+ return false;
88
+ const cut = body.search(/[\u4e00-\u9fff]/);
89
+ if (cut < 30)
90
+ return false;
91
+ const head = body.slice(0, cut);
92
+ const tail = body.slice(cut);
93
+ if (!/[\u4e00-\u9fff]/.test(tail))
94
+ return false;
95
+ const letters = head.replace(/[^A-Za-z]/g, '').length;
96
+ return letters / head.length >= 0.5;
97
+ }
98
+ export function splitLeakedReasoning(text) {
99
+ const body = String(text || '');
100
+ if (body.length < 40)
101
+ return { prefix: '', rest: body };
102
+ // 注意:不能用 split(/(?<=[.。!!??])\s*/) —— 它会把句末空白吃掉,
103
+ // 于是拼回来的 prefix 与真正流出去的正文差一个空格,客户端 indexOf 匹配不上(实测踩过)。
104
+ // 这里保留分隔符本身,保证 parts.join('') === body。
105
+ const parts = body.match(/[^.。!!??]*[.。!!??]\s*|[^.。!!??]+$/g) ?? [body];
106
+ // 从句首开始,连续吃"不含中文的句子"作为泄漏段。
107
+ // 为什么不是"必须命中元推理句式":实测泄漏段里会夹着 "Previously I said something incorrect … — that was wrong."
108
+ // 这种自述句,逐句匹配元句式会在这里断掉、只裁掉前半段。结构判据(英文盘算 + 中文答案)更稳。
109
+ // 但仍然要求:整段里**至少有一句**命中元推理句式,避免把"英文开头的正常回答"误裁。
110
+ let index = 0;
111
+ let ascii = 0;
112
+ let metaHit = false;
113
+ while (index < parts.length && !/[\u4e00-\u9fff]/.test(parts[index])) {
114
+ if (META_SENTENCE.test(parts[index]))
115
+ metaHit = true;
116
+ ascii += (parts[index].match(/[A-Za-z]/g) || []).length;
117
+ index += 1;
118
+ }
119
+ if (index === 0 || !metaHit)
120
+ return { prefix: '', rest: body };
121
+ const head = parts.slice(0, index).join('');
122
+ const tail = parts.slice(index).join('');
123
+ if (!tail.trim())
124
+ return { prefix: '', rest: body }; // 整篇都是盘算:不裁(可能是模型只说了这些)
125
+ const letters = head.replace(/[^A-Za-z]/g, '').length;
126
+ if (head.length > 0 && letters / head.length < 0.5)
127
+ return { prefix: '', rest: body };
128
+ if (!/[\u4e00-\u9fff]/.test(tail))
129
+ return { prefix: '', rest: body };
130
+ return { prefix: head, rest: tail };
131
+ }
132
+ //# sourceMappingURL=filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.js","sourceRoot":"","sources":["../../src/host/filters.ts"],"names":[],"mappings":"AAEA,oBAAoB;AACpB;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,8CAA8C,CAAA;AAEjE,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,KAAK,UAAU,QAAQ,EAAE,GAAG,CAAC,CAAA;AAE3D,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,MAAM,UAAU,QAAQ,EAAE,GAAG,CAAC,CAAA;AAE7D,MAAM,UAAU,GAAG,EAAE,CAAA;AAErB,MAAM,UAAU,iBAAiB;IAC/B,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,MAAM,KAAK,GAAG,CAAC,KAAc,EAAmC,EAAE;QAChE,IAAI,IAAI,GAAG,EAAE,CAAA;QACb,IAAI,KAAK,GAAG,EAAE,CAAA;QACd,SAAS,CAAC;YACR,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACtC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,IAAI,KAAK,EAAE,CAAC;wBACV,KAAK,IAAI,MAAM,CAAA;wBACf,MAAM,GAAG,EAAE,CAAA;oBACb,CAAC;yBAAM,IAAI,MAAM,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;wBACtC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,CAAA;wBACpD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAA;oBACpC,CAAC;oBACD,MAAK;gBACP,CAAC;gBACD,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;gBACrC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;gBACpD,MAAM,GAAG,KAAK,CAAA;gBACd,SAAQ;YACV,CAAC;YACD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACpC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,IAAI,MAAM,CAAA;oBACd,MAAM,GAAG,EAAE,CAAA;gBACb,CAAC;qBAAM,IAAI,MAAM,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;oBACtC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,CAAA;oBACnD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAA;gBACpC,CAAC;gBACD,MAAK;YACP,CAAC;YACD,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;YACnC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;YAClD,MAAM,GAAG,IAAI,CAAA;QACf,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IACxB,CAAC,CAAA;IACD,OAAO;QACL,IAAI,EAAE,CAAC,KAAa,EAAE,EAAE;YACtB,MAAM,IAAI,KAAK,CAAA;YACf,OAAO,KAAK,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;KACzB,CAAA;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,aAAa,GACjB,2bAA2b,CAAA;AAE7b;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IAC/B,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAA;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;IAC1C,IAAI,GAAG,GAAG,EAAE;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,MAAM,CAAA;IACrD,OAAO,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IAC/B,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACvD,iDAAiD;IACjD,uDAAuD;IACvD,wCAAwC;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxE,2BAA2B;IAC3B,yFAAyF;IACzF,kDAAkD;IAClD,8CAA8C;IAC9C,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACrE,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,GAAG,IAAI,CAAA;QACpD,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;QACvD,KAAK,IAAI,CAAC,CAAA;IACZ,CAAC;IACD,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACxC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA,CAAC,wBAAwB;IAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,MAAM,CAAA;IACrD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACrF,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACpE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AACrC,CAAC"}