@goodandready/dsh-model-sync 0.5.1 → 0.5.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/index.js +40 -69
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -6,31 +6,31 @@ import { registerHttpApi } from './http.js'
|
|
|
6
6
|
import { registerPluginUpdater } from './updater.js'
|
|
7
7
|
|
|
8
8
|
export const name = '@goodandready/dsh-model-sync'
|
|
9
|
-
export const inject = ['llm', '
|
|
9
|
+
export const inject = ['llm', 'webServer', 'credentials']
|
|
10
10
|
|
|
11
11
|
const NS = 'dsh-model-sync'
|
|
12
12
|
|
|
13
13
|
export const Config = Schema.object({
|
|
14
|
-
enabled: Schema.boolean().default(true),
|
|
15
|
-
intervalMinutes: Schema.number().default(60),
|
|
16
|
-
scheduleEnabled: Schema.boolean().default(false),
|
|
17
|
-
jitterMinutes: Schema.number().default(0),
|
|
18
|
-
ttlMinutes: Schema.number().default(0),
|
|
19
|
-
autoApply: Schema.boolean().default(false),
|
|
20
|
-
requestTimeoutMs: Schema.number().default(15000),
|
|
21
|
-
retryAttempts: Schema.number().default(3),
|
|
22
|
-
retryBaseDelayMs: Schema.number().default(250),
|
|
23
|
-
retryMaxDelayMs: Schema.number().default(4000),
|
|
24
|
-
concurrency: Schema.number().default(4),
|
|
25
|
-
circuitBreakerFailures: Schema.number().default(3),
|
|
26
|
-
circuitBreakerCooldownMinutes: Schema.number().default(5),
|
|
27
|
-
historyLimit: Schema.number().default(50),
|
|
28
|
-
notificationLimit: Schema.number().default(50),
|
|
29
|
-
diffWebhookUrl: Schema.string().default(),
|
|
30
|
-
diffWebhookSecret: Schema.string().default(),
|
|
31
|
-
notifyOnModelAdded: Schema.boolean().default(true),
|
|
32
|
-
notifyOnModelDeprecated: Schema.boolean().default(true),
|
|
33
|
-
notifyOnPriceChanged: Schema.boolean().default(true),
|
|
14
|
+
enabled: Schema.boolean().default(true).volatile(),
|
|
15
|
+
intervalMinutes: Schema.number().default(60).volatile(),
|
|
16
|
+
scheduleEnabled: Schema.boolean().default(false).volatile(),
|
|
17
|
+
jitterMinutes: Schema.number().default(0).volatile(),
|
|
18
|
+
ttlMinutes: Schema.number().default(0).volatile(),
|
|
19
|
+
autoApply: Schema.boolean().default(false).volatile(),
|
|
20
|
+
requestTimeoutMs: Schema.number().default(15000).volatile(),
|
|
21
|
+
retryAttempts: Schema.number().default(3).volatile(),
|
|
22
|
+
retryBaseDelayMs: Schema.number().default(250).volatile(),
|
|
23
|
+
retryMaxDelayMs: Schema.number().default(4000).volatile(),
|
|
24
|
+
concurrency: Schema.number().default(4).volatile(),
|
|
25
|
+
circuitBreakerFailures: Schema.number().default(3).volatile(),
|
|
26
|
+
circuitBreakerCooldownMinutes: Schema.number().default(5).volatile(),
|
|
27
|
+
historyLimit: Schema.number().default(50).volatile(),
|
|
28
|
+
notificationLimit: Schema.number().default(50).volatile(),
|
|
29
|
+
diffWebhookUrl: Schema.string().default().volatile(),
|
|
30
|
+
diffWebhookSecret: Schema.string().default().volatile(),
|
|
31
|
+
notifyOnModelAdded: Schema.boolean().default(true).volatile(),
|
|
32
|
+
notifyOnModelDeprecated: Schema.boolean().default(true).volatile(),
|
|
33
|
+
notifyOnPriceChanged: Schema.boolean().default(true).volatile(),
|
|
34
34
|
notifications: Schema.array(Schema.object({
|
|
35
35
|
id: Schema.string().required(),
|
|
36
36
|
fingerprint: Schema.string().required(),
|
|
@@ -44,9 +44,9 @@ export const Config = Schema.object({
|
|
|
44
44
|
message: Schema.string().required(),
|
|
45
45
|
providers: Schema.array(Schema.object({}).loose()).default([]),
|
|
46
46
|
}).loose()).default([]),
|
|
47
|
-
staleGraceRuns: Schema.number().default(2),
|
|
48
|
-
lifecycleRetentionRuns: Schema.number().default(20),
|
|
49
|
-
lifecycleRevision: Schema.number().default(0),
|
|
47
|
+
staleGraceRuns: Schema.number().default(2).volatile(),
|
|
48
|
+
lifecycleRetentionRuns: Schema.number().default(20).volatile(),
|
|
49
|
+
lifecycleRevision: Schema.number().default(0).volatile(),
|
|
50
50
|
modelLifecycle: Schema.dict(Schema.dict(Schema.object({
|
|
51
51
|
status: Schema.string().required(),
|
|
52
52
|
consecutiveMissing: Schema.number().default(0),
|
|
@@ -79,7 +79,7 @@ export const Config = Schema.object({
|
|
|
79
79
|
strategy: Schema.string(),
|
|
80
80
|
updatedAt: Schema.number().default(0),
|
|
81
81
|
}).loose()).default({}),
|
|
82
|
-
modelSelections: Schema.dict(Schema.array(Schema.string())).default({}),
|
|
82
|
+
modelSelections: Schema.dict(Schema.array(Schema.string())).default({}).volatile(),
|
|
83
83
|
adapterRegistry: Schema.dict(Schema.object({
|
|
84
84
|
enabled: Schema.boolean().default(true),
|
|
85
85
|
endpoint: Schema.string().default(''),
|
|
@@ -110,6 +110,17 @@ export const Config = Schema.object({
|
|
|
110
110
|
}).loose())).default({}),
|
|
111
111
|
})
|
|
112
112
|
|
|
113
|
+
// DSH serves a namespace's settings form from the volatile fields of its profile
|
|
114
|
+
// entry schema, and a volatile field holds a Volatile box rather than its value.
|
|
115
|
+
// Unwrap before any caller reads one, and read lazily: the Loader mutates the
|
|
116
|
+
// boxes in place and re-announces them with loader/volatile-update.
|
|
117
|
+
export function plainConfig(value) {
|
|
118
|
+
if (value === null || typeof value !== 'object') return value
|
|
119
|
+
if (Array.isArray(value)) return value.map(plainConfig)
|
|
120
|
+
if (typeof value.get === 'function') return plainConfig(value.get())
|
|
121
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, plainConfig(v)]))
|
|
122
|
+
}
|
|
123
|
+
|
|
113
124
|
export function apply(ctx, config) {
|
|
114
125
|
const baseConfig = structuredClone(config || {})
|
|
115
126
|
const resolveConfig = (value) => Config(structuredClone(value || {}))
|
|
@@ -125,50 +136,10 @@ export function apply(ctx, config) {
|
|
|
125
136
|
return saveConfigImpl(patch)
|
|
126
137
|
}
|
|
127
138
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
settingsScope = scope
|
|
133
|
-
liveConfig = resolveConfig(scope.get() || baseConfig)
|
|
134
|
-
const stop = scope.watch((next) => {
|
|
135
|
-
liveConfig = resolveConfig(next || baseConfig)
|
|
136
|
-
reconfigure()
|
|
137
|
-
})
|
|
138
|
-
let saveQueue = Promise.resolve()
|
|
139
|
-
saveConfigImpl = (patch) => {
|
|
140
|
-
const nextTask = saveQueue.then(async () => {
|
|
141
|
-
const result = await scope.update(patch)
|
|
142
|
-
liveConfig = resolveConfig(scope.get() || baseConfig)
|
|
143
|
-
return result
|
|
144
|
-
})
|
|
145
|
-
saveQueue = nextTask.catch(() => {})
|
|
146
|
-
return nextTask
|
|
147
|
-
}
|
|
148
|
-
ownerCtx.effect(() => () => {
|
|
149
|
-
settingsScope = undefined
|
|
150
|
-
saveConfigImpl = undefined
|
|
151
|
-
stop()
|
|
152
|
-
}, 'dsh-model-sync: settings')
|
|
153
|
-
return true
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
let settings
|
|
157
|
-
try { settings = ctx.get('settings') } catch (e) {
|
|
158
|
-
if (typeof ctx.logger?.debug === 'function') ctx.logger.debug('[dsh-model-sync] settings service not immediately available:', e)
|
|
159
|
-
}
|
|
160
|
-
if (!bindSettings(settings, ctx)) {
|
|
161
|
-
ctx.inject(['settings'], (sctx) => {
|
|
162
|
-
bindSettings((typeof sctx.get === 'function' ? sctx.get('settings') : null) ?? sctx.settings, sctx)
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const service = createProviderService(ctx)
|
|
168
|
-
const synchronizer = createModelSynchronizer(ctx, { getConfig: () => liveConfig, saveConfig })
|
|
169
|
-
const scheduler = createSyncScheduler(synchronizer, { getConfig: () => liveConfig })
|
|
170
|
-
reconfigure = () => scheduler.reconfigure()
|
|
171
|
-
scheduler.start()
|
|
139
|
+
// settings.register was removed before 0.1.7-rc.2. The host hands the profile entry
|
|
140
|
+
// config to apply() directly, and liveConfig above is derived from it; the
|
|
141
|
+
// Loader mutates the boxes in place and re-announces them with
|
|
142
|
+
// loader/volatile-update.
|
|
172
143
|
ctx.effect(() => () => scheduler.stop(), 'dsh-model-sync: scheduler cleanup')
|
|
173
144
|
ctx.effect(() => {
|
|
174
145
|
const registrations = registerHttpApi(ctx, synchronizer, { getSchedulerStatus: () => scheduler.status() })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-model-sync",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Automatic model catalog synchronization for API-key DeepSeek Harness providers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"license": "MIT",
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
56
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
57
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.
|
|
56
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
57
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1"
|
|
58
58
|
}
|
|
59
59
|
}
|