@goodandready/dsh-clinebot 0.3.1 → 0.3.3

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/lib/models.js CHANGED
@@ -21,6 +21,7 @@ export const CLINE_MODELS = Object.freeze([
21
21
  category: 'coding',
22
22
  recommended: true,
23
23
  isCustom: false,
24
+ reasoningEfforts: ['low', 'medium', 'high'],
24
25
  },
25
26
  {
26
27
  id: 'cline-pass/deepseek-v4-pro',
@@ -32,6 +33,7 @@ export const CLINE_MODELS = Object.freeze([
32
33
  category: 'coding',
33
34
  recommended: true,
34
35
  isCustom: false,
36
+ reasoningEfforts: ['low', 'medium', 'high', 'max'],
35
37
  },
36
38
  {
37
39
  id: 'cline-pass/glm-5.2',
@@ -54,6 +56,7 @@ export const CLINE_MODELS = Object.freeze([
54
56
  category: 'reasoning',
55
57
  recommended: true,
56
58
  isCustom: false,
59
+ reasoningEfforts: ['low', 'high', 'max'],
57
60
  },
58
61
  {
59
62
  id: 'cline-pass/kimi-k2.7-code',
@@ -109,6 +112,7 @@ export const CLINE_MODELS = Object.freeze([
109
112
  category: 'reasoning',
110
113
  recommended: false,
111
114
  isCustom: false,
115
+ reasoningEfforts: ['low', 'medium', 'high'],
112
116
  },
113
117
  {
114
118
  id: 'cline-pass/mimo-v2.5',
@@ -218,3 +222,82 @@ export function getDefaultModelIds(dynamicModels = []) {
218
222
  return getAllModels(dynamicModels).map((m) => m.id)
219
223
  }
220
224
 
225
+ /**
226
+ * Filter out models explicitly disabled by user.
227
+ * Any newly introduced model (not in disabledModelIds) is active by default.
228
+ */
229
+ export function getActiveModelIds(allModels = [], disabledModelIds = []) {
230
+ const disabledSet = new Set(Array.isArray(disabledModelIds) ? disabledModelIds : [])
231
+ return (Array.isArray(allModels) ? allModels : [])
232
+ .map((m) => (typeof m === 'string' ? m : m?.id))
233
+ .filter((id) => Boolean(id && !disabledSet.has(id)))
234
+ }
235
+
236
+ /**
237
+ * Format context length cleanly (e.g. 200000 -> '200K', 128000 -> '128K').
238
+ */
239
+ export function formatModelContext(contextLength) {
240
+ const num = Number(contextLength) || 200000
241
+ if (num >= 1000000) return `${Math.round(num / 1000000)}M`
242
+ if (num >= 1000) return `${Math.round(num / 1000)}K`
243
+ return String(num)
244
+ }
245
+
246
+ /**
247
+ * Format model description with compact tags for DSH model picker.
248
+ */
249
+ export function formatModelDescription(model) {
250
+ const parts = []
251
+ const ctx = formatModelContext(model.contextLength || model.contextWindow)
252
+ if (ctx) parts.push(ctx)
253
+ if (model.input?.includes('image') || model.input?.includes('vision')) {
254
+ parts.push('Vision')
255
+ }
256
+ if (model.category && model.category !== 'general') {
257
+ const cat = model.category.charAt(0).toUpperCase() + model.category.slice(1)
258
+ parts.push(cat)
259
+ }
260
+ const prefix = parts.length > 0 ? `[${parts.join(' · ')}] ` : ''
261
+ const baseDesc = model.description || model.name || model.id
262
+ return `${prefix}${baseDesc}`
263
+ }
264
+
265
+ /**
266
+ * Check if a model supports vision input.
267
+ */
268
+ export function isVisionModel(id, dynamicModels = []) {
269
+ const m = findModel(id, dynamicModels)
270
+ if (!m) return false
271
+ return Boolean(m.input?.includes('image') || m.input?.includes('vision'))
272
+ }
273
+
274
+ /**
275
+ * Disk caching for discovered models.
276
+ */
277
+ export async function saveModelsDiskCache(cachePath, models = []) {
278
+ if (!cachePath || !Array.isArray(models) || !models.length) return false
279
+ try {
280
+ const fs = await import('node:fs/promises')
281
+ const path = await import('node:path')
282
+ const dir = path.dirname(cachePath)
283
+ await fs.mkdir(dir, { recursive: true })
284
+ const payload = JSON.stringify({ savedAt: Date.now(), models }, null, 2)
285
+ await fs.writeFile(cachePath, payload, 'utf8')
286
+ return true
287
+ } catch {
288
+ return false
289
+ }
290
+ }
291
+
292
+ export async function loadModelsDiskCache(cachePath) {
293
+ if (!cachePath) return null
294
+ try {
295
+ const fs = await import('node:fs/promises')
296
+ const raw = await fs.readFile(cachePath, 'utf8')
297
+ const parsed = JSON.parse(raw)
298
+ return Array.isArray(parsed?.models) ? parsed.models : null
299
+ } catch {
300
+ return null
301
+ }
302
+ }
303
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-clinebot",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
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",