@goodandready/dsh-clinebot 0.3.17 → 0.3.19
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 +17 -0
- package/README.md +2 -2
- package/README.ru.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +12 -10
- package/lib/cline-client.js +11 -10
- package/lib/config.js +1 -0
- package/lib/models.js +22 -11
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ 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.19
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Settings no longer wait on the removed settingsScope service. The client uses configForms (#62).
|
|
12
|
+
|
|
13
|
+
## [0.3.18] - 2026-09-22
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **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).
|
|
17
|
+
- **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.
|
|
18
|
+
- **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`.
|
|
19
|
+
- **Reasoning Tooltip Localization**: Added localized explanatory tooltips (`models.reasoning_tooltip`) across English, Russian, and Chinese in the Settings UI.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **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.
|
|
23
|
+
- **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.
|
|
24
|
+
|
|
8
25
|
## [0.3.17] - 2026-09-21
|
|
9
26
|
|
|
10
27
|
### 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
|
|
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
|
|
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
|
|
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
|
)
|
|
@@ -837,10 +839,10 @@ function SettingsPage(props) {
|
|
|
837
839
|
const t = props?.t || makeT(en, en)
|
|
838
840
|
|
|
839
841
|
const scope = React.useMemo(() => {
|
|
840
|
-
const s = (ctx?.get && ctx.get('lanSettings')) || ctx?.
|
|
841
|
-
if (!s?.
|
|
842
|
+
const s = (ctx?.get && ctx.get('lanSettings')) || ctx?.configForms
|
|
843
|
+
if (!s?.get) return undefined
|
|
842
844
|
try {
|
|
843
|
-
return s.
|
|
845
|
+
return s.get(NS)
|
|
844
846
|
} catch (_) {
|
|
845
847
|
return undefined
|
|
846
848
|
}
|
|
@@ -1369,7 +1371,7 @@ function PluginCard(props) {
|
|
|
1369
1371
|
function refreshMirrorUntilVisible(ctx) {
|
|
1370
1372
|
const visible = () => {
|
|
1371
1373
|
try {
|
|
1372
|
-
const s = (ctx?.get && ctx.get('lanSettings')) || ctx?.
|
|
1374
|
+
const s = (ctx?.get && ctx.get('lanSettings')) || ctx?.configForms
|
|
1373
1375
|
const view = s?.describe?.()?.getSnapshot?.()?.view
|
|
1374
1376
|
return !!view && Array.isArray(view.namespaces) && view.namespaces.some((row) => row.ns === NS)
|
|
1375
1377
|
} catch (_) {
|
|
@@ -1382,7 +1384,7 @@ function refreshMirrorUntilVisible(ctx) {
|
|
|
1382
1384
|
if (visible() || tries >= 15) { clearInterval(timer); return }
|
|
1383
1385
|
tries += 1
|
|
1384
1386
|
try {
|
|
1385
|
-
const s = (ctx?.get && ctx.get('lanSettings')) || ctx?.
|
|
1387
|
+
const s = (ctx?.get && ctx.get('lanSettings')) || ctx?.configForms
|
|
1386
1388
|
s?.describe?.()?.load?.()
|
|
1387
1389
|
} catch (e) {
|
|
1388
1390
|
console.debug?.('[dsh-clinebot] Polling settings mirror:', e)
|
|
@@ -1492,7 +1494,7 @@ function apply(ctx) {
|
|
|
1492
1494
|
)
|
|
1493
1495
|
}
|
|
1494
1496
|
|
|
1495
|
-
module.exports = { apply, inject: ['slots', 'locale', '
|
|
1497
|
+
module.exports = { apply, inject: ['slots', 'locale', 'configForms'] }
|
|
1496
1498
|
|
|
1497
1499
|
return module.exports
|
|
1498
1500
|
},
|
package/lib/cline-client.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
6
|
-
*
|
|
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.
|
|
3
|
+
"version": "0.3.19",
|
|
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",
|
|
@@ -49,7 +49,11 @@
|
|
|
49
49
|
},
|
|
50
50
|
"client": {
|
|
51
51
|
"platform": "web",
|
|
52
|
-
"inject": [
|
|
52
|
+
"inject": [
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-slots",
|
|
54
|
+
"@deepseek-ai/dsh-client-locale",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
56
|
+
]
|
|
53
57
|
}
|
|
54
58
|
},
|
|
55
59
|
"peerDependencies": {
|