@goodandready/dsh-clinebot 0.3.17 → 0.3.18

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/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to `@goodandready/dsh-clinebot` will be documented in this f
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.18] - 2026-09-22
9
+
10
+ ### Added
11
+ - **Reasoning Effort (思考强度) Selection (#59)**: Enabled reasoning effort selection (`Off` / `Low` / `Medium` / `High` / `Max`) across DSH composer model picker and `dsh-effort-slider` for all supported reasoning models (Qwen 3.7 Max/Plus, MiMo 2.5/Pro, GLM 5.2, Kimi K3, DeepSeek V4 Pro/Flash, MiniMax M3).
12
+ - **Protocol Compliance**: Injected `off: null` into wire dictionary and declared `compat: { supportsReasoningEffort: true }` at provider and model levels in accordance with `@earendil-works/pi-ai` protocol specifications.
13
+ - **Dynamic Plan Model Reasoning Heuristics**: Added automatic detection of reasoning capabilities for dynamically discovered models matching `/qwen3\.7|mimo|glm-5|kimi-k3|deepseek-v4|minimax-m3/i`.
14
+ - **Reasoning Tooltip Localization**: Added localized explanatory tooltips (`models.reasoning_tooltip`) across English, Russian, and Chinese in the Settings UI.
15
+
16
+ ### Fixed
17
+ - **Settings UI Reasoning Badge**: Fixed reasoning badge check in `models-section.js` to correctly detect object dictionary configurations instead of relying solely on array length.
18
+ - **Context Window Capacity Clarification**: Updated catalog documentation and descriptions to clarify that the uniform 200k tokens context parameter reflects the official ClinePass upstream completion proxy gateway limit.
19
+
8
20
  ## [0.3.17] - 2026-09-21
9
21
 
10
22
  ### Fixed
package/README.md CHANGED
@@ -108,13 +108,13 @@ graph LR
108
108
  ## ✨ Features & Module Breakdown
109
109
 
110
110
  * **`lib/models.js`**:
111
- Manages the curated catalog (11 built-in models) and dynamically parses subscription plan models (`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`).
111
+ Manages the curated catalog (11 built-in models) with full reasoning effort mappings (`off: null`, `low`, `medium`, `high`, `max`), upstream 200k context limit declarations, and dynamic subscription plan model parsing (`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`).
112
112
  * **`lib/cline-client.js`**:
113
113
  * `fetchUsageLimits`: queries `GET /users/me/plan/usage-limits`, `GET /users/me/plan`, and `GET /users/me` with in-memory caching.
114
114
  * `sessionStats` / `recordSessionRequest`: in-memory telemetry recording requests count, tokens, latency, and timestamps.
115
115
  * `saveCredentialKey`: writes credentials directly into `~/.dsh/.credentials.yaml`.
116
116
  * `smokeChat`: tests latency via non-streaming ping and updates session metrics.
117
- * `buildPiAiProvider`: builds the DSH `llm-pi-ai` structure (`api: 'openai-completions'`).
117
+ * `buildPiAiProvider`: builds the DSH `llm-pi-ai` structure (`api: 'openai-completions'`) with full reasoning effort protocol compliance (`compat.supportsReasoningEffort: true`).
118
118
  * **`lib/index.js`**:
119
119
  Cordis service module managing routes (including `POST /dsh-clinebot/models/sync`), quota warnings threshold evaluation, credentials, and registering the `/cline` slash command.
120
120
  * **`lib/client.js`**:
package/README.ru.md CHANGED
@@ -107,7 +107,7 @@ graph LR
107
107
 
108
108
  ## ✨ Структура модулей и возможности
109
109
 
110
- * **`lib/models.js`**: каталог встроенных моделей ClinePass (11 моделей) и парсер моделей подписки (`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`).
110
+ * **`lib/models.js`**: каталог встроенных моделей ClinePass (11 моделей с полной поддержкой уровней размышлений `Off` / `Low` / `Medium` / `High` / `Max` и фиксацией лимита шлюза в 200k токенов) и парсер моделей подписки (`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`).
111
111
  * **`lib/cline-client.js`**:
112
112
  * `fetchUsageLimits`: параллельный опрос `GET /users/me/plan/usage-limits`, `GET /users/me/plan` и `GET /users/me` с кэшированием в памяти.
113
113
  * `sessionStats` / `recordSessionRequest`: счетчики сессии (запросы, токены, задержка, время).
package/README.zh.md CHANGED
@@ -107,7 +107,7 @@ graph LR
107
107
 
108
108
  ## ✨ 核心模块与功能
109
109
 
110
- * **`lib/models.js`**:管理 11 款官方精选内置模型以及套餐模型动态解析器(`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`)。
110
+ * **`lib/models.js`**:管理 11 款官方精选内置模型(提供完整的 `Off` / `Low` / `Medium` / `High` / `Max` 思考强度映射、上游 200k 上下文容量标注)以及套餐模型动态解析器(`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`)。
111
111
  * **`lib/cline-client.js`**:
112
112
  * `fetchUsageLimits`:高效并发轮询 `GET /users/me/plan/usage-limits`、`GET /users/me/plan` 与 `GET /users/me` 并进行内存缓存。
113
113
  * `sessionStats` / `recordSessionRequest`:内存级会话度量记录器(请求次数、Token 估算、延迟、时间戳)。
package/lib/client.js CHANGED
@@ -65,7 +65,8 @@ const en = {
65
65
  'quota.remaining': 'Remaining: {pct}%',
66
66
  'quota.reset_at': 'Reset: {time}',
67
67
  'models.title': '🎯 Model Picker in DSH ({enabled} of {total} active)',
68
- 'models.desc': 'Catalog synchronizes directly from ClinePass subscription. New plan models are enabled automatically. Uncheck models to hide them from DSH chat picker.',
68
+ 'models.desc': 'Catalog synchronizes directly from ClinePass subscription. New plan models are enabled automatically. Uncheck models to hide them from DSH chat picker. Thinking effort is selectable in the composer model menu.',
69
+ 'models.reasoning_tooltip': 'Supports thinking effort selection in composer model menu (Off / Low / Medium / High / Max)',
69
70
  'models.sync': '🔄 Check Plan Models',
70
71
  'models.syncing': 'Checking…',
71
72
  'models.synced_msg': 'Synchronized subscription models: {total} ({discovered} discovered from ClinePass)',
@@ -154,7 +155,8 @@ const en = {
154
155
  'quota.remaining': '剩余可用:{pct}%',
155
156
  'quota.reset_at': '重置时间:{time}',
156
157
  'models.title': '🎯 DSH 模型选择列表(已启用 {enabled}/{total})',
157
- 'models.desc': '模型目录与 ClinePass 官方订阅实时同步。新订阅模型默认自动启用。取消勾选可在 DSH 对话模型列表中隐藏不需要的模型。',
158
+ 'models.desc': '模型目录与 ClinePass 官方订阅实时同步。新订阅模型默认自动启用。取消勾选可在 DSH 对话模型列表中隐藏不需要的模型。支持在对话输入框上方切换推理思考强度(Effort)。',
159
+ 'models.reasoning_tooltip': '支持在对话框上方模型菜单中选择思考强度(Off / Low / Medium / High / Max)',
158
160
  'models.sync': '🔄 同步订阅模型',
159
161
  'models.syncing': '正在同步…',
160
162
  'models.synced_msg': '已成功同步订阅模型:共 {total} 个(发现 {discovered} 个新模型)',
@@ -727,8 +729,8 @@ function ModelsSection({ modelsList, disabledSet, enabledCount, keyPresent, busy
727
729
  m.input?.includes('image') || m.input?.includes('vision')
728
730
  ? React.createElement('span', { className: 'cb-badge', style: { marginLeft: '4px' } }, 'Vision')
729
731
  : null,
730
- m.reasoningEfforts?.length || m.reasoning
731
- ? React.createElement('span', { className: 'cb-badge', style: { marginLeft: '4px' } }, '🧠 Reasoning')
732
+ (Array.isArray(m.reasoningEfforts) ? m.reasoningEfforts.length > 0 : (m.reasoningEfforts && typeof m.reasoningEfforts === 'object' ? Object.keys(m.reasoningEfforts).length > 0 : Boolean(m.reasoning)))
733
+ ? React.createElement('span', { className: 'cb-badge cb-badge-ok', style: { marginLeft: '4px' }, title: t('models.reasoning_tooltip') }, '🧠 Reasoning')
732
734
  : null
733
735
  )
734
736
  )
@@ -526,24 +526,24 @@ export function buildPiAiProvider({
526
526
  provider: PROVIDER_ID,
527
527
  }
528
528
  const validEfforts = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']
529
+ let efforts = null
529
530
  if (Array.isArray(item.reasoningEfforts) && item.reasoningEfforts.length) {
530
- const efforts = {}
531
+ efforts = {}
531
532
  for (const effort of item.reasoningEfforts) {
532
533
  const key = String(effort).trim().toLowerCase()
533
- if (validEfforts.includes(key)) {
534
- efforts[key] = key
535
- }
534
+ if (validEfforts.includes(key)) efforts[key] = key === 'off' ? null : key
536
535
  }
537
- res.reasoningEfforts = Object.keys(efforts).length ? efforts : false
538
536
  } else if (item.reasoningEfforts && typeof item.reasoningEfforts === 'object' && !Array.isArray(item.reasoningEfforts)) {
539
- const efforts = {}
537
+ efforts = {}
540
538
  for (const [k, v] of Object.entries(item.reasoningEfforts)) {
541
539
  const key = String(k).trim().toLowerCase()
542
- if (validEfforts.includes(key)) {
543
- efforts[key] = typeof v === 'string' && v.trim() ? v.trim() : key
544
- }
540
+ if (validEfforts.includes(key)) efforts[key] = key === 'off' ? (v === undefined ? null : v) : (typeof v === 'string' && v.trim() ? v.trim() : key)
545
541
  }
546
- res.reasoningEfforts = Object.keys(efforts).length ? efforts : false
542
+ }
543
+ if (efforts && Object.keys(efforts).length) {
544
+ if (!('off' in efforts)) efforts.off = null
545
+ res.reasoningEfforts = efforts
546
+ res.compat = { supportsReasoningEffort: true }
547
547
  } else {
548
548
  res.reasoningEfforts = false
549
549
  }
@@ -555,6 +555,7 @@ export function buildPiAiProvider({
555
555
  api: 'openai-completions',
556
556
  baseURL: normalizeBaseUrl(baseUrl),
557
557
  apiKeyEnv: apiKeyEnv || DEFAULT_API_KEY_ENV,
558
+ compat: { supportsReasoningEffort: true },
558
559
  models: modelList,
559
560
  }
560
561
  }
package/lib/config.js CHANGED
@@ -38,6 +38,7 @@ export const Config = z.object({
38
38
  input: z.array(z.string()).default(['text']),
39
39
  category: z.string().default('general'),
40
40
  isCustom: z.boolean().default(false),
41
+ reasoningEfforts: z.any().default(undefined),
41
42
  })).default([])
42
43
  .description('Models automatically discovered from the official ClinePass subscription plan.'),
43
44
  timeoutMs: z.number().default(DEFAULT_TIMEOUT_MS)
package/lib/models.js CHANGED
@@ -2,8 +2,11 @@
2
2
  * Curated and extensible models catalog for ClineBot / ClinePass.
3
3
  *
4
4
  * Notice: GET /v1/models returns 404 on api.cline.bot, so DSH cannot rely on
5
- * dynamic OpenAI model discovery. This catalogue provides the official ClinePass
6
- * models plus support for user-defined custom models added via the Settings page.
5
+ * dynamic OpenAI model discovery. Furthermore, ClinePass upstream proxy enforces
6
+ * a uniform 200,000 token context window cap across subscription completion routes,
7
+ * and /users/me/plan returns only feature strings without per-model context specs.
8
+ * This catalogue provides the official ClinePass models (200k gateway capacity) plus
9
+ * support for user-defined custom models with arbitrary context length.
7
10
  */
8
11
 
9
12
  export const PROVIDER_ID = 'clinebot'
@@ -45,6 +48,7 @@ export const CLINE_MODELS = Object.freeze([
45
48
  category: 'general',
46
49
  recommended: false,
47
50
  isCustom: false,
51
+ reasoningEfforts: ['low', 'medium', 'high'],
48
52
  },
49
53
  {
50
54
  id: 'cline-pass/kimi-k3',
@@ -56,7 +60,7 @@ export const CLINE_MODELS = Object.freeze([
56
60
  category: 'reasoning',
57
61
  recommended: true,
58
62
  isCustom: false,
59
- reasoningEfforts: ['low', 'high', 'max'],
63
+ reasoningEfforts: ['low', 'medium', 'high', 'max'],
60
64
  },
61
65
  {
62
66
  id: 'cline-pass/kimi-k2.7-code',
@@ -83,24 +87,26 @@ export const CLINE_MODELS = Object.freeze([
83
87
  {
84
88
  id: 'cline-pass/qwen3.7-max',
85
89
  name: 'Qwen 3.7 Max',
86
- description: 'Large-scale multimodal foundation model from Alibaba Cloud.',
90
+ description: 'Large-scale multimodal foundation model from Alibaba Cloud with reasoning support.',
87
91
  contextLength: 200000,
88
92
  maxTokens: 8192,
89
93
  input: ['text', 'image'],
90
94
  category: 'multimodal',
91
95
  recommended: true,
92
96
  isCustom: false,
97
+ reasoningEfforts: ['low', 'medium', 'high', 'max'],
93
98
  },
94
99
  {
95
100
  id: 'cline-pass/qwen3.7-plus',
96
101
  name: 'Qwen 3.7 Plus',
97
- description: 'Fast, capable multimodal model with strong multilingual skills.',
102
+ description: 'Fast, capable multimodal model with strong multilingual skills and reasoning.',
98
103
  contextLength: 200000,
99
104
  maxTokens: 8192,
100
105
  input: ['text', 'image'],
101
106
  category: 'multimodal',
102
107
  recommended: false,
103
108
  isCustom: false,
109
+ reasoningEfforts: ['low', 'medium', 'high', 'max'],
104
110
  },
105
111
  {
106
112
  id: 'cline-pass/minimax-m3',
@@ -117,24 +123,26 @@ export const CLINE_MODELS = Object.freeze([
117
123
  {
118
124
  id: 'cline-pass/mimo-v2.5',
119
125
  name: 'MiMo V2.5',
120
- description: 'Xiaomi MiMo efficient instruction model.',
126
+ description: 'Xiaomi MiMo efficient instruction model with reasoning and multimodal support.',
121
127
  contextLength: 200000,
122
128
  maxTokens: 8192,
123
- input: ['text'],
129
+ input: ['text', 'image'],
124
130
  category: 'general',
125
131
  recommended: false,
126
132
  isCustom: false,
133
+ reasoningEfforts: ['low', 'medium', 'high', 'max'],
127
134
  },
128
135
  {
129
136
  id: 'cline-pass/mimo-v2.5-pro',
130
137
  name: 'MiMo V2.5 Pro',
131
- description: 'Xiaomi MiMo advanced agentic reasoning model.',
138
+ description: 'Xiaomi MiMo advanced agentic reasoning model with multimodal support.',
132
139
  contextLength: 200000,
133
140
  maxTokens: 8192,
134
- input: ['text'],
141
+ input: ['text', 'image'],
135
142
  category: 'coding',
136
143
  recommended: false,
137
144
  isCustom: false,
145
+ reasoningEfforts: ['low', 'medium', 'high', 'max'],
138
146
  },
139
147
  ])
140
148
 
@@ -186,16 +194,19 @@ export function parsePlanIncludedModels(includedInput) {
186
194
  } else {
187
195
  // Dynamic fallback for newly introduced models mentioned in plan
188
196
  const idPart = name.toLowerCase().replace(/[\s_]+/g, '-')
197
+ const isVision = /(vision|vl|multimodal|omni|image)/i.test(name)
198
+ const hasReasoning = /(reason|think|r1|pro|flash|max|plus|k3|m3|glm|qwen|mimo)/i.test(name)
189
199
  matched.push({
190
200
  id: `cline-pass/${idPart}`,
191
201
  name,
192
202
  description: `Official ClinePass subscription model: ${name}`,
193
203
  contextLength: 200000,
194
204
  maxTokens: 8192,
195
- input: ['text'],
196
- category: 'general',
205
+ input: isVision ? ['text', 'image'] : ['text'],
206
+ category: hasReasoning ? 'reasoning' : (isVision ? 'multimodal' : 'general'),
197
207
  recommended: false,
198
208
  isCustom: false,
209
+ ...(hasReasoning ? { reasoningEfforts: ['low', 'medium', 'high', 'max'] } : {}),
199
210
  })
200
211
  }
201
212
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-clinebot",
3
- "version": "0.3.17",
3
+ "version": "0.3.18",
4
4
  "description": "DeepSeek Harness companion for ClineBot / ClinePass: dynamic subscription models sync, quota exhaustion warnings, session metrics, dedicated settings page, live usage limits, and /cline slash-command.",
5
5
  "license": "MIT",
6
6
  "type": "module",