@goodandready/dsh-model-sync 0.5.4 → 0.5.5
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/adapter-registry.js +4 -6
- package/lib/client.js +14 -0
- package/lib/index.js +17 -5
- package/lib/inventory.js +3 -2
- package/lib/synchronizer-helpers.js +16 -5
- package/lib/synchronizer.js +2 -1
- package/package.json +1 -1
package/lib/adapter-registry.js
CHANGED
|
@@ -12,7 +12,7 @@ const PROVIDER_ADAPTERS = Object.freeze({
|
|
|
12
12
|
clinebot: {
|
|
13
13
|
endpoint: 'https://api.cline.bot/api/v1/users/me/plan',
|
|
14
14
|
auth: 'bearer',
|
|
15
|
-
|
|
15
|
+
parse: 'clinebot-plan',
|
|
16
16
|
defaultModels: [
|
|
17
17
|
'cline-pass/deepseek-v4-flash',
|
|
18
18
|
'cline-pass/deepseek-v4-pro',
|
|
@@ -99,12 +99,13 @@ function mappedRows(provider, rows, descriptor) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
function parseRows(provider, payload, descriptor) {
|
|
102
|
-
|
|
102
|
+
const parserKind = descriptor.parse || descriptor.parser
|
|
103
|
+
if (parserKind === 'clinebot-plan') {
|
|
103
104
|
const plan = payload?.data?.plan || payload?.data || payload?.plan || payload
|
|
104
105
|
const included = plan?.features?.included || plan?.includedModels || []
|
|
105
106
|
return parseClinePassModels(included)
|
|
106
107
|
}
|
|
107
|
-
if (
|
|
108
|
+
if (parserKind === 'google') {
|
|
108
109
|
const rows = Array.isArray(payload?.models) ? payload.models : []
|
|
109
110
|
return normalizeModels(provider, rows.map((row) => ({
|
|
110
111
|
...row,
|
|
@@ -224,9 +225,6 @@ async function fetchSpecific(profile, descriptor, options) {
|
|
|
224
225
|
return rows
|
|
225
226
|
}
|
|
226
227
|
} catch (error) {
|
|
227
|
-
if (descriptor.defaultModels && Array.isArray(descriptor.defaultModels) && descriptor.defaultModels.length > 0) {
|
|
228
|
-
return normalizeModels(profile.provider, descriptor.defaultModels.map((id) => ({ id })))
|
|
229
|
-
}
|
|
230
228
|
throw error
|
|
231
229
|
}
|
|
232
230
|
if (descriptor.defaultModels && Array.isArray(descriptor.defaultModels) && descriptor.defaultModels.length > 0) {
|
package/lib/client.js
CHANGED
|
@@ -785,6 +785,20 @@ window.__ModuleLoader__.load({
|
|
|
785
785
|
.finally(() => setBusy(false))
|
|
786
786
|
}
|
|
787
787
|
|
|
788
|
+
const resolveSmartAlias = (aliasName) => {
|
|
789
|
+
setResolvingKey(aliasName)
|
|
790
|
+
fetch(`${API}/aliases/resolve?alias=${encodeURIComponent(aliasName)}`)
|
|
791
|
+
.then(async (r) => {
|
|
792
|
+
const res = await r.json()
|
|
793
|
+
if (!r.ok) throw new Error(res.error?.message ?? `HTTP ${r.status}`)
|
|
794
|
+
setResolvedAliases((prev) => ({ ...prev, [aliasName]: res }))
|
|
795
|
+
})
|
|
796
|
+
.catch((e) => {
|
|
797
|
+
setResolvedAliases((prev) => ({ ...prev, [aliasName]: { error: String(e?.message ?? e) } }))
|
|
798
|
+
})
|
|
799
|
+
.finally(() => setResolvingKey(''))
|
|
800
|
+
}
|
|
801
|
+
|
|
788
802
|
const load = () => {
|
|
789
803
|
if (typeof document !== 'undefined' && document.hidden) return
|
|
790
804
|
setError('')
|
package/lib/index.js
CHANGED
|
@@ -123,7 +123,16 @@ export function plainConfig(value) {
|
|
|
123
123
|
|
|
124
124
|
export function apply(ctx, config) {
|
|
125
125
|
const baseConfig = structuredClone(plainConfig(config || {}))
|
|
126
|
-
const resolveConfig = (value) =>
|
|
126
|
+
const resolveConfig = (value) => {
|
|
127
|
+
try {
|
|
128
|
+
return plainConfig(Config(plainConfig(value) || {}))
|
|
129
|
+
} catch (err) {
|
|
130
|
+
if (typeof ctx?.logger?.warn === "function") {
|
|
131
|
+
ctx.logger.warn("[dsh-model-sync] invalid config payload, fallback to current config:", err?.message || err)
|
|
132
|
+
}
|
|
133
|
+
return liveConfig ?? baseConfig
|
|
134
|
+
}
|
|
135
|
+
}
|
|
127
136
|
let liveConfig = resolveConfig(baseConfig)
|
|
128
137
|
let reconfigure = () => {}
|
|
129
138
|
let saveConfigImpl = async (patch) => {
|
|
@@ -165,12 +174,16 @@ export function apply(ctx, config) {
|
|
|
165
174
|
reconfigure = () => scheduler.reconfigure()
|
|
166
175
|
scheduler.start()
|
|
167
176
|
|
|
168
|
-
|
|
169
|
-
ctx.on
|
|
177
|
+
ctx.effect(() => {
|
|
178
|
+
if (typeof ctx.on !== 'function') return () => {}
|
|
179
|
+
const dispose = ctx.on('loader/volatile-update', () => {
|
|
170
180
|
liveConfig = resolveConfig(config)
|
|
171
181
|
reconfigure()
|
|
172
182
|
})
|
|
173
|
-
|
|
183
|
+
return () => {
|
|
184
|
+
if (typeof dispose === 'function') dispose()
|
|
185
|
+
}
|
|
186
|
+
}, 'dsh-model-sync: volatile-update listener')
|
|
174
187
|
|
|
175
188
|
// settings.register was removed before 0.1.7-rc.2. The host hands the profile entry
|
|
176
189
|
// config to apply() directly, and liveConfig above is derived from it; the
|
|
@@ -189,7 +202,6 @@ export function apply(ctx, config) {
|
|
|
189
202
|
manifestUrl: new URL('../package.json', import.meta.url),
|
|
190
203
|
}), 'dsh-model-sync: plugin updater')
|
|
191
204
|
ctx.effect(() => {
|
|
192
|
-
if (!liveConfig.enabled) return () => {}
|
|
193
205
|
ctx.provide('modelSync', service)
|
|
194
206
|
ctx.provide('modelSyncRunner', synchronizer)
|
|
195
207
|
return () => {}
|
package/lib/inventory.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeModels } from './models.js'
|
|
2
|
+
import { sectionOf } from './synchronizer-helpers.js'
|
|
2
3
|
|
|
3
4
|
export const API_KEY_PROVIDER_IDS = Object.freeze([
|
|
4
5
|
'anthropic',
|
|
@@ -42,7 +43,7 @@ const API_KEY_PROVIDER_SET = new Set(API_KEY_PROVIDER_IDS)
|
|
|
42
43
|
|
|
43
44
|
function settingsProfiles(settings) {
|
|
44
45
|
try {
|
|
45
|
-
return settings
|
|
46
|
+
return sectionOf(settings, 'llm-pi-ai')?.providers ?? {}
|
|
46
47
|
} catch {
|
|
47
48
|
return {}
|
|
48
49
|
}
|
|
@@ -66,7 +67,7 @@ export function listApiKeyProviders(llm, settings) {
|
|
|
66
67
|
for (const entry of directory) {
|
|
67
68
|
let profile = profiles[entry.provider]
|
|
68
69
|
if (!profile && (entry.provider === 'commandcode' || entry.settingsNs === 'llm-commandcode')) {
|
|
69
|
-
const cc = settings
|
|
70
|
+
const cc = sectionOf(settings, 'llm-commandcode')
|
|
70
71
|
profile = {
|
|
71
72
|
apiKeyEnv: cc?.apiKeyEnv ?? 'COMMANDCODE_API_KEY',
|
|
72
73
|
credentialRef: cc?.apiKeyEnv ?? 'COMMANDCODE_API_KEY',
|
|
@@ -55,12 +55,23 @@ export function descriptorOf(settings, ns) {
|
|
|
55
55
|
catch { return undefined }
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
export function sectionOf(settings, ns) {
|
|
59
|
+
try {
|
|
60
|
+
const desc = descriptorOf(settings, ns)
|
|
61
|
+
if (desc && desc.value !== undefined) return desc.value
|
|
62
|
+
if (typeof settings?.get === 'function') return settings.get(ns)
|
|
63
|
+
return undefined
|
|
64
|
+
} catch {
|
|
65
|
+
return undefined
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
58
69
|
export function profileOf(settings, provider) {
|
|
59
70
|
try {
|
|
60
|
-
const piai = settings
|
|
71
|
+
const piai = sectionOf(settings, PIAI_NS)?.providers?.[provider]
|
|
61
72
|
if (piai) return piai
|
|
62
73
|
if (provider === 'commandcode') {
|
|
63
|
-
const cc = settings
|
|
74
|
+
const cc = sectionOf(settings, 'llm-commandcode')
|
|
64
75
|
return {
|
|
65
76
|
apiKeyEnv: cc?.apiKeyEnv ?? 'COMMANDCODE_API_KEY',
|
|
66
77
|
credentialRef: cc?.apiKeyEnv ?? 'COMMANDCODE_API_KEY',
|
|
@@ -97,7 +108,7 @@ export function adapterErrorType(error) {
|
|
|
97
108
|
export async function replaceWithRetry(settings, ns, patchFn, attempts = 3) {
|
|
98
109
|
let lastError
|
|
99
110
|
for (let i = 0; i < attempts; i++) {
|
|
100
|
-
const section = settings
|
|
111
|
+
const section = sectionOf(settings, ns)
|
|
101
112
|
const descriptor = descriptorOf(settings, ns)
|
|
102
113
|
if (!section || !descriptor || typeof settings.replace !== 'function') {
|
|
103
114
|
throw Object.assign(new Error(`${ns} settings are not writable`), { code: 'SETTINGS_UNAVAILABLE' })
|
|
@@ -120,7 +131,7 @@ export async function replaceWithRetry(settings, ns, patchFn, attempts = 3) {
|
|
|
120
131
|
|
|
121
132
|
export function rotationRefs(settings, provider) {
|
|
122
133
|
try {
|
|
123
|
-
const rows = settings
|
|
134
|
+
const rows = sectionOf(settings, 'dsh-key-rotation')?.providers
|
|
124
135
|
if (!Array.isArray(rows)) return []
|
|
125
136
|
return rows.filter((row) => row?.provider === provider).flatMap((row) => Array.isArray(row.keys) ? row.keys : [])
|
|
126
137
|
} catch {
|
|
@@ -149,7 +160,7 @@ export async function performHistoryRollback({ ctx, config, providers = [], hist
|
|
|
149
160
|
if (!snapshot || !Array.isArray(snapshot.before)) throw Object.assign(new Error(`history snapshot not found: ${provider}`), { code: 'HISTORY_NOT_FOUND' })
|
|
150
161
|
if (!providers.some((row) => row.provider === provider && row.configured)) throw Object.assign(new Error(`provider is not configured: ${provider}`), { code: 'PROVIDER_NOT_CONFIGURED' })
|
|
151
162
|
const settings = settingsOf(ctx)
|
|
152
|
-
const section = settings
|
|
163
|
+
const section = sectionOf(settings, PIAI_NS)
|
|
153
164
|
const descriptor = descriptorOf(settings, PIAI_NS)
|
|
154
165
|
if (!section || !descriptor || typeof settings.replace !== 'function') {
|
|
155
166
|
throw Object.assign(new Error('llm-pi-ai settings are not writable'), { code: 'SETTINGS_UNAVAILABLE' })
|
package/lib/synchronizer.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
settingsOf,
|
|
19
19
|
llmOf,
|
|
20
20
|
descriptorOf,
|
|
21
|
+
sectionOf,
|
|
21
22
|
profileOf,
|
|
22
23
|
errorMessage,
|
|
23
24
|
diagnosticMessage,
|
|
@@ -488,7 +489,7 @@ export function createModelSynchronizer(ctx, { getConfig = () => ({}), saveConfi
|
|
|
488
489
|
if (typeof saveConfig !== 'function') throw Object.assign(new Error('dsh-model-sync settings are not writable'), { code: 'CONFIG_UNAVAILABLE' })
|
|
489
490
|
|
|
490
491
|
const settings = settingsOf(ctx)
|
|
491
|
-
const section = settings
|
|
492
|
+
const section = sectionOf(settings, PIAI_NS)
|
|
492
493
|
const descriptor = descriptorOf(settings, PIAI_NS)
|
|
493
494
|
const current = normalizeModels(provider, profileOf(settings, provider).models ?? row.models)
|
|
494
495
|
const nextModels = selectedModels.length
|