lark-remote 0.5.7 → 0.5.9

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 (57) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/bridge/index.d.ts +47 -7
  3. package/dist/bridge/index.js +300 -129
  4. package/dist/bridge/queue-manager.d.ts +6 -0
  5. package/dist/bridge/queue-manager.js +61 -63
  6. package/dist/card/approval-render.js +2 -1
  7. package/dist/card/bash-card-session.d.ts +0 -1
  8. package/dist/card/bash-card-session.js +0 -8
  9. package/dist/card/bash-renderer.js +2 -1
  10. package/dist/card/card-budget.js +15 -19
  11. package/dist/card/card-session.d.ts +3 -13
  12. package/dist/card/card-session.js +4 -18
  13. package/dist/card/card-shared.d.ts +11 -0
  14. package/dist/card/card-shared.js +23 -13
  15. package/dist/card/run-card-session.d.ts +0 -1
  16. package/dist/card/run-card-session.js +0 -6
  17. package/dist/card/run-renderer.d.ts +11 -10
  18. package/dist/card/run-renderer.js +198 -35
  19. package/dist/card/run-state.d.ts +29 -2
  20. package/dist/card/run-state.js +23 -4
  21. package/dist/card/text-truncate.d.ts +3 -5
  22. package/dist/card/text-truncate.js +3 -5
  23. package/dist/card/tool-render.js +7 -21
  24. package/dist/common/tool-summary.d.ts +8 -0
  25. package/dist/common/tool-summary.js +38 -20
  26. package/dist/common/turn-failure.d.ts +13 -0
  27. package/dist/common/turn-failure.js +18 -0
  28. package/dist/index.js +13 -14
  29. package/dist/order/index.d.ts +2 -0
  30. package/dist/order/index.js +2 -0
  31. package/dist/router/card-helpers.js +23 -42
  32. package/dist/router/config/codex.js +2 -3
  33. package/dist/router/config/common/model-patch.d.ts +8 -0
  34. package/dist/router/config/common/model-patch.js +13 -0
  35. package/dist/router/config/common/render.js +30 -77
  36. package/dist/router/config/dsh.js +2 -1
  37. package/dist/router/config/kimi.js +3 -3
  38. package/dist/router/index.d.ts +0 -11
  39. package/dist/router/index.js +119 -360
  40. package/dist/router/order-exec-dispatch.js +2 -1
  41. package/dist/router/usage-format.d.ts +5 -0
  42. package/dist/router/usage-format.js +1 -1
  43. package/dist/runner/common/defaults.d.ts +2 -0
  44. package/dist/runner/common/defaults.js +3 -0
  45. package/dist/runner/common/jsonrpc/connection-manager.js +1 -1
  46. package/dist/runner/dsh/client.d.ts +15 -0
  47. package/dist/runner/dsh/client.js +28 -2
  48. package/dist/runner/dsh/goal-view.d.ts +36 -0
  49. package/dist/runner/dsh/goal-view.js +106 -0
  50. package/dist/runner/dsh/runner.js +51 -2
  51. package/dist/runner/index.d.ts +1 -1
  52. package/dist/runner/types.d.ts +59 -1
  53. package/dist/runner/types.js +9 -0
  54. package/dist/session/claude/session-index.d.ts +0 -4
  55. package/dist/session/claude/session-index.js +0 -8
  56. package/dist/session/dsh/sessions.js +58 -2
  57. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { parseCliArgs, resolveConfigDir, setConfigDir, printHelp, printVersion,
5
5
  import { FeishuConnector } from './connector/index.js';
6
6
  import { ClaudeRunner, CodexAppServerRunner, OpencodeAcpRunner, PiRpcRunner, KimiAcpRunner, DshRunner, } from './runner/index.js';
7
7
  import { AgentRegistry } from './runner/registry.js';
8
+ import { AGENT_DISPLAY_NAMES, AGENT_KINDS } from './runner/types.js';
8
9
  import { probeAllAgents } from './runner/probe.js';
9
10
  import { warmCodexCatalogCache } from './config/codex-config.js';
10
11
  import { SessionReaderRegistry, SessionStore } from './session/index.js';
@@ -316,13 +317,10 @@ function initializeRunner(config, configDir, cliArgs) {
316
317
  getLogger().warn(`[dsh] startup probe failed: ${error.message}`);
317
318
  });
318
319
  }
319
- // 2026-07-17: 注册所有 agent 的显示名,实现单点真相
320
- agentRegistry.registerDisplayName('claude', 'Claude');
321
- agentRegistry.registerDisplayName('codex', 'Codex');
322
- agentRegistry.registerDisplayName('opencode', 'Opencode');
323
- agentRegistry.registerDisplayName('pi', 'Pi');
324
- agentRegistry.registerDisplayName('kimi', 'Kimi');
325
- agentRegistry.registerDisplayName('dsh', 'DSH');
320
+ // 显示名单源在 runner/types.ts 的 AGENT_DISPLAY_NAMES(启动注册与回退共用)
321
+ for (const kind of AGENT_KINDS) {
322
+ agentRegistry.registerDisplayName(kind, AGENT_DISPLAY_NAMES[kind]);
323
+ }
326
324
  // 设置全局 registry,供 agentDisplayName 等全局函数使用
327
325
  AgentRegistry.setGlobalInstance(agentRegistry);
328
326
  // Probe agent CLI availability (fire-and-forget, populates cache for /config card).
@@ -534,16 +532,17 @@ function setupMessageHandlers(connector, router, bridge, sessionStore, workspace
534
532
  const content = router.expandAliasMessage(msg.content);
535
533
  if (isStopCommand(content)) {
536
534
  void (async () => {
537
- const stopped = await bridge.interruptCurrentRun({
535
+ const interrupt = await bridge.interruptCurrentRunDetailed({
538
536
  userId: msg.userId,
539
537
  chatId: msg.chatId,
540
538
  });
541
- if (!stopped) {
542
- await bridge.sendResult({ text: '当前没有运行中的进程' }, {
543
- userId: msg.userId,
544
- chatId: msg.chatId,
545
- messageId: msg.messageId,
546
- });
539
+ const ctx = { userId: msg.userId, chatId: msg.chatId, messageId: msg.messageId };
540
+ if (!interrupt.stopped) {
541
+ await bridge.sendResult({ text: '当前没有运行中的进程' }, ctx);
542
+ }
543
+ else if ((interrupt.stoppedCount ?? 1) > 1) {
544
+ // 并行 workspace 时 /stop 停全部,必须让用户看到数量。
545
+ await bridge.sendResult({ text: `✅ 已停止 ${interrupt.stoppedCount} 个运行中的任务` }, ctx);
547
546
  }
548
547
  })().catch((err) => logger.error('[control] /stop failed:', err));
549
548
  return;
@@ -1,3 +1,5 @@
1
+ /** 指令已被删除/不存在时的统一用户提示。 */
2
+ export declare const ORDER_NOT_FOUND_TEXT = "\u6307\u4EE4\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664";
1
3
  export interface OrderEntry {
2
4
  id: string;
3
5
  text: string;
@@ -2,6 +2,8 @@ import path from 'node:path';
2
2
  import os from 'node:os';
3
3
  import { atomicWriteJson } from '../persistence/atomic-write.js';
4
4
  import { loadJsonFile } from '../persistence/load-json-file.js';
5
+ /** 指令已被删除/不存在时的统一用户提示。 */
6
+ export const ORDER_NOT_FOUND_TEXT = '指令不存在或已被删除';
5
7
  const MAX_TEXT_LENGTH = 200;
6
8
  const MAX_ORDERS = 50;
7
9
  /** 别名名称规则:`[A-Za-z_][A-Za-z0-9_]*`,≤20 字符,不能数字开头。 */
@@ -6,7 +6,7 @@
6
6
  * specific builders (e.g. `sessionEventPanel`) so `router/index.ts` can fold
7
7
  * long session histories into collapsible panels without duplicating logic.
8
8
  */
9
- import { agentDisplayName } from '../card/card-shared.js';
9
+ import { agentDisplayName, cardButton } from '../card/card-shared.js';
10
10
  import { collapsibleMarkdownPanel, markdownDiv } from '../card/collapsible.js';
11
11
  import { formatMonthDayClock } from '../card/time.js';
12
12
  import { displayWidth, truncateMiddleToDisplayWidth } from '../common/text-width.js';
@@ -142,18 +142,7 @@ export function paginationBar(opts) {
142
142
  width: 'auto',
143
143
  vertical_align: 'center',
144
144
  elements: [
145
- {
146
- tag: 'button',
147
- text: { tag: 'plain_text', content: prevText },
148
- type: 'default',
149
- size: 'small',
150
- behaviors: [
151
- {
152
- type: 'callback',
153
- value: { cmd: opts.cmd, offset: opts.offset - opts.pageSize, ...opts.extra },
154
- },
155
- ],
156
- },
145
+ cardButton(prevText, { cmd: opts.cmd, offset: opts.offset - opts.pageSize, ...opts.extra }, { type: 'default', size: 'small' }),
157
146
  ],
158
147
  });
159
148
  }
@@ -185,18 +174,7 @@ export function paginationBar(opts) {
185
174
  width: 'auto',
186
175
  vertical_align: 'center',
187
176
  elements: [
188
- {
189
- tag: 'button',
190
- text: { tag: 'plain_text', content: nextText },
191
- type: 'default',
192
- size: 'small',
193
- behaviors: [
194
- {
195
- type: 'callback',
196
- value: { cmd: opts.cmd, offset: opts.offset + opts.pageSize, ...opts.extra },
197
- },
198
- ],
199
- },
177
+ cardButton(nextText, { cmd: opts.cmd, offset: opts.offset + opts.pageSize, ...opts.extra }, { type: 'default', size: 'small' }),
200
178
  ],
201
179
  });
202
180
  }
@@ -264,18 +242,7 @@ export function searchBar(opts) {
264
242
  width: 'auto',
265
243
  vertical_align: 'center',
266
244
  elements: [
267
- {
268
- tag: 'button',
269
- text: { tag: 'plain_text', content: '清除筛选' },
270
- type: 'default',
271
- size: 'small',
272
- behaviors: [
273
- {
274
- type: 'callback',
275
- value: { cmd: opts.cmd, clearQuery: true, ...opts.extra },
276
- },
277
- ],
278
- },
245
+ cardButton('清除筛选', { cmd: opts.cmd, clearQuery: true, ...opts.extra }, { type: 'default', size: 'small' }),
279
246
  ],
280
247
  });
281
248
  }
@@ -339,15 +306,29 @@ export function buildSessionHistoryCard(state, opts) {
339
306
  const { displayTitle, aiTitle, recap, events, usage } = state;
340
307
  let header = opts.headerText;
341
308
  const sections = [];
309
+ const preview = (text) => (text.length > 200 ? text.slice(0, 197) + '...' : text);
342
310
  // Reader 层不再截断 displayTitle/summary;统一在消费侧这里截到 200 字符。
311
+ //
312
+ // `aiTitle` 与 `displayTitle` 是两种东西:前者是 agent 自己起的会话标题
313
+ // (DSH 的 projections.title / claude 的 ai-title),后者是最近一条用户输入。
314
+ // claude 的 displayTitle 本身就取 aiTitle,两者相等 → 保持旧的「AI 标题」
315
+ // 单段文案;DSH 两者都有(标题 + 末轮 prompt)→ 各占一段,别把用户那句话
316
+ // 挂在「AI 标题」下面(2026-10-21)。
343
317
  if (displayTitle) {
344
- const label = aiTitle ? 'AI 标题' : '最近输入';
345
- const preview = displayTitle.length > 200 ? displayTitle.slice(0, 197) + '...' : displayTitle;
346
- sections.push(`🏷️ **${label}**\n${preview}`);
318
+ if (aiTitle && aiTitle !== displayTitle) {
319
+ sections.push(`🏷️ **标题**\n${preview(aiTitle)}`);
320
+ sections.push(`✏️ **最近输入**\n${preview(displayTitle)}`);
321
+ }
322
+ else {
323
+ const label = aiTitle ? 'AI 标题' : '最近输入';
324
+ sections.push(`🏷️ **${label}**\n${preview(displayTitle)}`);
325
+ }
326
+ }
327
+ else if (aiTitle) {
328
+ sections.push(`🏷️ **AI 标题**\n${preview(aiTitle)}`);
347
329
  }
348
330
  if (recap) {
349
- const recapPreview = recap.length > 200 ? recap.slice(0, 197) + '...' : recap;
350
- sections.push(`📝 **Recap**\n${recapPreview}`);
331
+ sections.push(`📝 **Recap**\n${preview(recap)}`);
351
332
  }
352
333
  if (sections.length > 0) {
353
334
  header += '\n\n' + sections.join('\n\n──\n\n');
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { loadCodexConfig, getReasoningEffortOptions, getDefaultReasoningEffort, } from '../../config/codex-config.js';
5
5
  import { DEFAULT_TURN_IDLE_TIMEOUT_MINUTES } from '../../config/index.js';
6
- import { resetModelPatch } from './common/model-patch.js';
6
+ import { pickMiddleValue, resetModelPatch } from './common/model-patch.js';
7
7
  export class CodexConfigBuilder {
8
8
  buildFields(displayConfig) {
9
9
  const fields = [];
@@ -116,8 +116,7 @@ export class CodexConfigBuilder {
116
116
  const isCurrentEffortValid = currentReasoningEffort && newModelSupportedEfforts.includes(currentReasoningEffort);
117
117
  if (isCurrentEffortValid)
118
118
  return null;
119
- const middle = newModelSupportedEfforts[Math.floor((newModelSupportedEfforts.length - 1) / 2)];
120
- const newEffort = middle ?? getDefaultReasoningEffort(newModel);
119
+ const newEffort = pickMiddleValue(newModelSupportedEfforts) ?? getDefaultReasoningEffort(newModel);
121
120
  return { key: 'agents.codex.reasoningEffort', value: newEffort };
122
121
  }
123
122
  }
@@ -19,3 +19,11 @@ export declare function resetModelPatch(modelKey: string, currentModel: string |
19
19
  key: string;
20
20
  value: unknown;
21
21
  } | null;
22
+ /**
23
+ * 取档位列表的中位值(切换模型后当前档位不受支持时的兜底)。
24
+ *
25
+ * 偶数长度的中位口径由调用方显式选择,避免各 builder 各写一套公式后漂移:
26
+ * - `lower`:`(len-1)/2`,kimi/codex 既有口径;
27
+ * - `upper`:`len/2`,DSH 需要偏高的一档(off/low → low)。
28
+ */
29
+ export declare function pickMiddleValue<T>(values: readonly T[], bias?: 'lower' | 'upper'): T | undefined;
@@ -22,4 +22,17 @@ export function resetModelPatch(modelKey, currentModel, newModelOptions) {
22
22
  }
23
23
  return null;
24
24
  }
25
+ /**
26
+ * 取档位列表的中位值(切换模型后当前档位不受支持时的兜底)。
27
+ *
28
+ * 偶数长度的中位口径由调用方显式选择,避免各 builder 各写一套公式后漂移:
29
+ * - `lower`:`(len-1)/2`,kimi/codex 既有口径;
30
+ * - `upper`:`len/2`,DSH 需要偏高的一档(off/low → low)。
31
+ */
32
+ export function pickMiddleValue(values, bias = 'lower') {
33
+ if (values.length === 0)
34
+ return undefined;
35
+ const index = bias === 'upper' ? Math.floor(values.length / 2) : Math.floor((values.length - 1) / 2);
36
+ return values[index];
37
+ }
25
38
  //# sourceMappingURL=model-patch.js.map
@@ -5,6 +5,7 @@
5
5
  * Used by all agent config builders and the shared tabs (idle, logging).
6
6
  */
7
7
  import { getConfigValue } from '../../../config/index.js';
8
+ import { cardButton } from '../../../card/card-shared.js';
8
9
  /** Build CardKit 2.0 elements for a list of config fields. */
9
10
  function buildFieldElements(fields, displayConfig) {
10
11
  const elements = [];
@@ -29,8 +30,8 @@ function buildFieldElements(fields, displayConfig) {
29
30
  }
30
31
  return elements;
31
32
  }
32
- function buildBooleanElement(field, isOn) {
33
- const displayVal = isOn ? '✅ 已开启' : '⚪ 已关闭';
33
+ /** 配置项统一行:左 label(2 份宽)+ 右控件(3 份宽)。 */
34
+ function fieldRow(label, control) {
34
35
  return {
35
36
  tag: 'column_set',
36
37
  flex_mode: 'none',
@@ -40,25 +41,24 @@ function buildBooleanElement(field, isOn) {
40
41
  width: 'weighted',
41
42
  weight: 2,
42
43
  vertical_align: 'center',
43
- elements: [{ tag: 'div', text: { tag: 'lark_md', content: field.label } }],
44
+ elements: [{ tag: 'div', text: { tag: 'lark_md', content: label } }],
44
45
  },
45
46
  {
46
47
  tag: 'column',
47
48
  width: 'weighted',
48
49
  weight: 3,
49
50
  vertical_align: 'center',
50
- elements: [
51
- {
52
- tag: 'button',
53
- text: { tag: 'plain_text', content: displayVal },
54
- type: isOn ? 'primary' : 'default',
55
- behaviors: [{ type: 'callback', value: { cmd: 'config.toggle', key: field.key } }],
56
- },
57
- ],
51
+ elements: [control],
58
52
  },
59
53
  ],
60
54
  };
61
55
  }
56
+ function buildBooleanElement(field, isOn) {
57
+ const displayVal = isOn ? '✅ 已开启' : '⚪ 已关闭';
58
+ return fieldRow(field.label, cardButton(displayVal, { cmd: 'config.toggle', key: field.key }, {
59
+ type: isOn ? 'primary' : 'default',
60
+ }));
61
+ }
62
62
  function buildSelectElement(field, currentValue) {
63
63
  // 优先使用 field.currentValue(卡片显示用覆盖值),否则使用 config 中的值
64
64
  const selectedValue = field.currentValue != null
@@ -66,38 +66,17 @@ function buildSelectElement(field, currentValue) {
66
66
  : currentValue == null
67
67
  ? undefined
68
68
  : String(currentValue);
69
- return {
70
- tag: 'column_set',
71
- flex_mode: 'none',
72
- columns: [
73
- {
74
- tag: 'column',
75
- width: 'weighted',
76
- weight: 2,
77
- vertical_align: 'center',
78
- elements: [{ tag: 'div', text: { tag: 'lark_md', content: field.label } }],
79
- },
80
- {
81
- tag: 'column',
82
- width: 'weighted',
83
- weight: 3,
84
- vertical_align: 'center',
85
- elements: [
86
- {
87
- tag: 'select_static',
88
- placeholder: { tag: 'plain_text', content: '请选择' },
89
- options: field.options.map((opt) => {
90
- const text = typeof opt === 'string' ? opt : opt.text;
91
- const value = typeof opt === 'string' ? opt : opt.value;
92
- return { text: { tag: 'plain_text', content: text }, value };
93
- }),
94
- initial_option: selectedValue,
95
- behaviors: [{ type: 'callback', value: { cmd: 'config.set', key: field.key } }],
96
- },
97
- ],
98
- },
99
- ],
100
- };
69
+ return fieldRow(field.label, {
70
+ tag: 'select_static',
71
+ placeholder: { tag: 'plain_text', content: '请选择' },
72
+ options: field.options.map((opt) => {
73
+ const text = typeof opt === 'string' ? opt : opt.text;
74
+ const value = typeof opt === 'string' ? opt : opt.value;
75
+ return { text: { tag: 'plain_text', content: text }, value };
76
+ }),
77
+ initial_option: selectedValue,
78
+ behaviors: [{ type: 'callback', value: { cmd: 'config.set', key: field.key } }],
79
+ });
101
80
  }
102
81
  function buildInputElement(field, currentValue) {
103
82
  // 优先使用 field.currentValue(允许覆盖 displayConfig 中的值)
@@ -106,34 +85,13 @@ function buildInputElement(field, currentValue) {
106
85
  : currentValue == null
107
86
  ? ''
108
87
  : String(currentValue);
109
- return {
110
- tag: 'column_set',
111
- flex_mode: 'none',
112
- columns: [
113
- {
114
- tag: 'column',
115
- width: 'weighted',
116
- weight: 2,
117
- vertical_align: 'center',
118
- elements: [{ tag: 'div', text: { tag: 'lark_md', content: field.label } }],
119
- },
120
- {
121
- tag: 'column',
122
- width: 'weighted',
123
- weight: 3,
124
- vertical_align: 'center',
125
- elements: [
126
- {
127
- tag: 'input',
128
- name: field.key,
129
- placeholder: { tag: 'plain_text', content: '请输入值' },
130
- default_value: currentStr,
131
- behaviors: [{ type: 'callback', value: { cmd: 'config.input', key: field.key } }],
132
- },
133
- ],
134
- },
135
- ],
136
- };
88
+ return fieldRow(field.label, {
89
+ tag: 'input',
90
+ name: field.key,
91
+ placeholder: { tag: 'plain_text', content: '请输入值' },
92
+ default_value: currentStr,
93
+ behaviors: [{ type: 'callback', value: { cmd: 'config.input', key: field.key } }],
94
+ });
137
95
  }
138
96
  /** Build the full CardKit 2.0 card from tabs. */
139
97
  export function buildConfigCardFromTabs(tabs, displayConfig) {
@@ -147,12 +105,7 @@ export function buildConfigCardFromTabs(tabs, displayConfig) {
147
105
  elements.push({ tag: 'hr' });
148
106
  }
149
107
  // 底部保存按钮
150
- elements.push({
151
- tag: 'button',
152
- text: { tag: 'plain_text', content: '💾 保存所有修改' },
153
- type: 'primary',
154
- behaviors: [{ type: 'callback', value: { cmd: 'config.save' } }],
155
- });
108
+ elements.push(cardButton('💾 保存所有修改', { cmd: 'config.save' }, { type: 'primary' }));
156
109
  return {
157
110
  schema: '2.0',
158
111
  config: { wide_screen_mode: true, update_multi: true },
@@ -16,6 +16,7 @@
16
16
  * 与 runner 的兼容规则一致。provider 清单不硬编码,来自服务端目录。
17
17
  */
18
18
  import { DEFAULT_DSH_HOST } from '../../config/index.js';
19
+ import { pickMiddleValue } from './common/model-patch.js';
19
20
  import { DshClient } from '../../runner/dsh/client.js';
20
21
  import { getLogger } from '../../logger/index.js';
21
22
  /** 旧配置没有 provider 时的生效值(与 DshRunner 的兼容规则一致)。 */
@@ -361,7 +362,7 @@ export class DshConfigBuilder {
361
362
  if (currentEffort && supported.includes(currentEffort))
362
363
  return null;
363
364
  // 新模型目录中位档位;偶数长度取偏高位(off/low → low,符合 DSH 默认 high 语义)
364
- const middle = supported[Math.floor(supported.length / 2)];
365
+ const middle = pickMiddleValue(supported, 'upper');
365
366
  return { key: 'agents.dsh.reasoningEffort', value: middle };
366
367
  }
367
368
  }
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { loadKimiConfig, KIMI_THINKING_EFFORTS, FALLBACK_EFFORTS, } from '../../config/kimi-config.js';
8
8
  import { DEFAULT_TURN_IDLE_TIMEOUT_MINUTES } from '../../config/index.js';
9
+ import { pickMiddleValue } from './common/model-patch.js';
9
10
  const PERMISSION_MODE_OPTIONS = [
10
11
  // kimi 0.40.0(2026-09-02)起官方语义:manual=始终询问 / yolo=必要时询问 / auto=完全自动
11
12
  { text: 'manual(始终询问)', value: 'manual' },
@@ -79,12 +80,11 @@ export class KimiConfigBuilder {
79
80
  const supported = kimiCfg.modelEfforts[newModel] ?? [...FALLBACK_EFFORTS];
80
81
  if (currentEffort && supported.includes(currentEffort))
81
82
  return null;
82
- const middle = supported[Math.floor((supported.length - 1) / 2)];
83
- let newEffort = middle;
83
+ let newEffort = pickMiddleValue(supported);
84
84
  if (!newEffort)
85
85
  newEffort = kimiCfg.modelDefaultEfforts?.[newModel];
86
86
  if (!newEffort)
87
- newEffort = FALLBACK_EFFORTS[Math.floor((FALLBACK_EFFORTS.length - 1) / 2)];
87
+ newEffort = pickMiddleValue(FALLBACK_EFFORTS);
88
88
  return { key: 'agents.kimi.thinkingEffort', value: newEffort };
89
89
  }
90
90
  }
@@ -641,17 +641,6 @@ export declare class CommandRouter {
641
641
  * 不敏感。省略/空 = 无筛选。
642
642
  */
643
643
  cmdWs(args: string[], ctx: CommandContext, offset?: number, q?: string): CommandResult;
644
- /**
645
- * degraded card when a session's export is non-empty but unparseable
646
- * (truncated by opencode's pipe cap on huge sessions, or otherwise corrupt).
647
- * The session exists, so reuse listSessions metadata (title) instead of the
648
- * misleading "未找到". Reuses the same card-builder helpers (markdownDiv) as
649
- * the normal resume card; enforceCardBudget still applies at send time.
650
- */
651
- /**
652
- * /resume 核心实现(public:handleResumePage / handle / resume.use 共用,
653
- * 也是测试的直接 seam,避免测试用 @ts-expect-error 摸私有方法)。
654
- */
655
644
  /**
656
645
  * DSH /resume preset 一致性校验:返回 mismatch 详情,或 undefined(一致/不可判定)。
657
646
  *