@goodandready/dsh-subscriptions 0.7.45 → 0.7.46
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/client.js +8 -0
- package/lib/client.panels.js +69 -3
- package/lib/config-schema.js +2 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -300,6 +300,10 @@ window.__ModuleLoader__.load({
|
|
|
300
300
|
"discovered": "discovered",
|
|
301
301
|
"shown": "shown",
|
|
302
302
|
"searchModels": "Search models by name or id",
|
|
303
|
+
"compact": "Compact",
|
|
304
|
+
"heatmap": "Heatmap · last 24h",
|
|
305
|
+
"editModels": "Edit models",
|
|
306
|
+
"hidden": "hidden",
|
|
303
307
|
"tabRouting": "Routing",
|
|
304
308
|
"tabModels": "Models",
|
|
305
309
|
"tabVault": "Vault",
|
|
@@ -725,6 +729,10 @@ window.__ModuleLoader__.load({
|
|
|
725
729
|
"discovered": "已发现",
|
|
726
730
|
"shown": "已显示",
|
|
727
731
|
"searchModels": "按名称或 ID 搜索模型",
|
|
732
|
+
"compact": "紧凑模式",
|
|
733
|
+
"heatmap": "热力图 · 最近 24 小时",
|
|
734
|
+
"editModels": "编辑模型",
|
|
735
|
+
"hidden": "隐藏",
|
|
728
736
|
"tabRouting": "路由",
|
|
729
737
|
"tabModels": "模型",
|
|
730
738
|
"tabVault": "Vault",
|
package/lib/client.panels.js
CHANGED
|
@@ -191,16 +191,39 @@ window.__ModuleLoader__.load({
|
|
|
191
191
|
const [sort, setSort] = React.useState('risk')
|
|
192
192
|
const [usage, setUsage] = React.useState({})
|
|
193
193
|
const [speed, setSpeed] = React.useState('standard')
|
|
194
|
+
const [analytics, setAnalytics] = React.useState(null)
|
|
195
|
+
const [compact, setCompact] = React.useState(false)
|
|
196
|
+
const [editing, setEditing] = React.useState(false)
|
|
197
|
+
const [draft, setDraft] = React.useState({})
|
|
194
198
|
const usageRef = React.useRef({ inflight: {}, gen: {} })
|
|
195
199
|
const pull = () => fetch('/dsh-subscriptions/config', { cache: 'no-store' })
|
|
196
200
|
.then((res) => res.json())
|
|
197
201
|
.then((cfg) => {
|
|
198
202
|
setData(cfg)
|
|
199
203
|
setSpeed((cfg.config && cfg.config.codexSubagentSpeed) || 'standard')
|
|
204
|
+
setDraft(JSON.parse(JSON.stringify((cfg.config && cfg.config.modelOverrides) || {})))
|
|
200
205
|
if (!provider && cfg.accounts && cfg.accounts.length) setProvider(cfg.accounts[0].provider)
|
|
201
206
|
})
|
|
202
207
|
.catch(() => {})
|
|
203
|
-
React.useEffect(() => {
|
|
208
|
+
React.useEffect(() => {
|
|
209
|
+
pull()
|
|
210
|
+
fetch('/dsh-subscriptions/analytics', { cache: 'no-store' })
|
|
211
|
+
.then((res) => res.json())
|
|
212
|
+
.then((out) => setAnalytics((out && out.analytics) || null))
|
|
213
|
+
.catch(() => {})
|
|
214
|
+
}, [])
|
|
215
|
+
const saveOverrides = () => {
|
|
216
|
+
if (!data || !data.config) return
|
|
217
|
+
fetch('/dsh-subscriptions/config', {
|
|
218
|
+
method: 'PUT',
|
|
219
|
+
headers: { 'content-type': 'application/json' },
|
|
220
|
+
body: JSON.stringify({ config: Object.assign({}, data.config, { modelOverrides: draft }), revision: data.revision }),
|
|
221
|
+
}).then(() => { setEditing(false); pull() }).catch(() => {})
|
|
222
|
+
}
|
|
223
|
+
const cancelOverrides = () => {
|
|
224
|
+
setDraft(JSON.parse(JSON.stringify((data && data.config && data.config.modelOverrides) || {})))
|
|
225
|
+
setEditing(false)
|
|
226
|
+
}
|
|
204
227
|
const loadUsage = (row) => {
|
|
205
228
|
const key = row.provider + ':' + row.index
|
|
206
229
|
if (usageRef.current.inflight[key]) return
|
|
@@ -264,10 +287,53 @@ window.__ModuleLoader__.load({
|
|
|
264
287
|
u && u.value ? h('span', { className: 'dsub-dim' }, JSON.stringify(u.value).slice(0, 180)) : null),
|
|
265
288
|
)
|
|
266
289
|
}),
|
|
267
|
-
h('div', { className: 'dsub-
|
|
290
|
+
h('div', { className: 'dsub-row' },
|
|
291
|
+
h('label', { className: 'dsub-sub' }, h('input', { type: 'checkbox', checked: compact, onChange: (e) => setCompact(e.target.checked) }), ' ' + t('compact')),
|
|
292
|
+
),
|
|
293
|
+
h('div', { className: 'dsub-h' }, t('heatmap')),
|
|
294
|
+
h('div', { className: 'dsub-row', style: { gap: 2 } },
|
|
295
|
+
((analytics && analytics.hourly) || []).slice(-24).map((hour, i) => h('span', {
|
|
296
|
+
key: i,
|
|
297
|
+
title: (hour && hour.requests || 0) + ' req',
|
|
298
|
+
style: { display: 'inline-block', width: 8, height: 18, background: 'rgba(88,166,255,' + Math.min(1, ((hour && hour.requests) || 0) / 10 + 0.1) + ')' },
|
|
299
|
+
}))),
|
|
300
|
+
h('div', { className: 'dsub-row' },
|
|
301
|
+
h('span', { className: 'dsub-h' }, t('modelEditor') + ' · ' + t('discovered') + ' ' + models.length + ' · ' + t('shown') + ' ' + shown.length),
|
|
302
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: () => setEditing(!editing) }, t('editModels')),
|
|
303
|
+
editing ? h('button', { type: 'button', className: 'dsub-mini', onClick: saveOverrides }, t('save')) : null,
|
|
304
|
+
editing ? h('button', { type: 'button', className: 'dsub-mini', onClick: cancelOverrides }, t('cancel')) : null,
|
|
305
|
+
),
|
|
268
306
|
h('input', { className: 'dsub-grow', value: query, placeholder: t('searchModels'), onChange: (e) => setQuery(e.target.value) }),
|
|
269
307
|
shown.slice(0, 40).map((m) => h('div', { key: m.id, className: 'dsub-row' },
|
|
270
|
-
h('span', { className: 'dsub-h' }, m.independent ? '★ ' : ''),
|
|
308
|
+
h('span', { className: 'dsub-h' }, m.independent ? '★ ' : ''),
|
|
309
|
+
editing
|
|
310
|
+
? h('input', {
|
|
311
|
+
className: 'dsub-grow',
|
|
312
|
+
value: (draft[m.id] && draft[m.id].name) || '',
|
|
313
|
+
placeholder: m.name || m.id,
|
|
314
|
+
onChange: (e) => setDraft((d) => Object.assign({}, d, { [m.id]: Object.assign({}, d[m.id], { name: e.target.value }) })),
|
|
315
|
+
})
|
|
316
|
+
: h('span', { className: 'dsub-sub' }, (draft[m.id] && draft[m.id].name) || m.name || m.id),
|
|
317
|
+
editing ? h('input', {
|
|
318
|
+
type: 'number',
|
|
319
|
+
className: 'dsub-inp',
|
|
320
|
+
style: { width: '90px', minWidth: '90px' },
|
|
321
|
+
value: (draft[m.id] && draft[m.id].contextWindow) || '',
|
|
322
|
+
placeholder: 'ctx',
|
|
323
|
+
onChange: (e) => setDraft((d) => Object.assign({}, d, { [m.id]: Object.assign({}, d[m.id], { contextWindow: Number(e.target.value) || undefined }) })),
|
|
324
|
+
}) : null,
|
|
325
|
+
editing ? h('select', {
|
|
326
|
+
className: 'dsub-select',
|
|
327
|
+
value: (draft[m.id] && draft[m.id].reasoningEffort) || '',
|
|
328
|
+
onChange: (e) => setDraft((d) => Object.assign({}, d, { [m.id]: Object.assign({}, d[m.id], { reasoningEffort: e.target.value || undefined }) })),
|
|
329
|
+
}, ['', 'low', 'medium', 'high'].map((level) => h('option', { key: level || 'default', value: level }, level || 'effort'))) : null,
|
|
330
|
+
editing ? h('label', { className: 'dsub-dim' },
|
|
331
|
+
h('input', {
|
|
332
|
+
type: 'checkbox',
|
|
333
|
+
checked: !!(draft[m.id] && draft[m.id].hidden),
|
|
334
|
+
onChange: (e) => setDraft((d) => Object.assign({}, d, { [m.id]: Object.assign({}, d[m.id], { hidden: e.target.checked }) })),
|
|
335
|
+
}), ' ' + t('hidden')) : null,
|
|
336
|
+
h('span', { className: 'dsub-dim' }, m.id))),
|
|
271
337
|
)
|
|
272
338
|
}
|
|
273
339
|
|
package/lib/config-schema.js
CHANGED
|
@@ -171,6 +171,8 @@ export const Config = z.object({
|
|
|
171
171
|
.description('#788 Per-provider model glob rules. First match wins; account may be a ref, label or index.'),
|
|
172
172
|
tiers: z.array(z.any()).volatile().default([])
|
|
173
173
|
.description('#817 Named picker tiers: { id, name, members: [accountRef] }. No cross-tier fallback.'),
|
|
174
|
+
modelOverrides: z.any().volatile().default({})
|
|
175
|
+
.description('#807 Per-model editor overrides: display name, hidden, context window, default reasoning effort.'),
|
|
174
176
|
rotationStrategy: z.string().volatile().default('round-robin')
|
|
175
177
|
.description('Load balancing strategy among available accounts: round-robin (balanced), least-loaded (fair-share quota), quota-aware (urgent quota first), or priority (sequential).'),
|
|
176
178
|
poolEnabled: z.boolean().volatile().default(true)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-subscriptions",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.46",
|
|
4
4
|
"description": "Use ChatGPT Codex, Claude, Grok, Antigravity, Kimi, GLM, Cursor, Kiro, Copilot, Qwen, ERNIE, Spark, JetBrains, Perplexity, Replit, and Cody subscriptions as DeepSeek Harness LLM providers via OAuth.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|