@goodandready/dsh-model-sync 0.5.12 → 0.5.14
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 +39 -30
- package/lib/http.js +8 -1
- package/lib/index.js +1 -1
- package/lib/provider-service.js +5 -5
- package/lib/synchronizer-helpers.js +8 -4
- package/package.json +5 -5
package/lib/client.js
CHANGED
|
@@ -528,6 +528,25 @@ window.__ModuleLoader__.load({
|
|
|
528
528
|
}
|
|
529
529
|
|
|
530
530
|
|
|
531
|
+
async function safeJson(r) {
|
|
532
|
+
const text = await r.text()
|
|
533
|
+
if (!text || !text.trim()) {
|
|
534
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}${r.statusText ? ': ' + r.statusText : ''}`)
|
|
535
|
+
return {}
|
|
536
|
+
}
|
|
537
|
+
let parsed
|
|
538
|
+
try {
|
|
539
|
+
parsed = JSON.parse(text)
|
|
540
|
+
} catch {
|
|
541
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}${text ? ': ' + text.slice(0, 120) : ''}`)
|
|
542
|
+
throw new Error(`Invalid JSON response (HTTP ${r.status})`)
|
|
543
|
+
}
|
|
544
|
+
if (!r.ok) {
|
|
545
|
+
throw new Error(parsed?.error?.message ?? parsed?.message ?? `HTTP ${r.status}`)
|
|
546
|
+
}
|
|
547
|
+
return parsed
|
|
548
|
+
}
|
|
549
|
+
|
|
531
550
|
function UpdaterSection({ t, api }) {
|
|
532
551
|
const [updaterStatus, setUpdaterStatus] = React.useState(null)
|
|
533
552
|
const [updaterChecking, setUpdaterChecking] = React.useState(false)
|
|
@@ -541,8 +560,7 @@ window.__ModuleLoader__.load({
|
|
|
541
560
|
setUpdaterNotice('')
|
|
542
561
|
fetch(`${api}/update?fresh=1`)
|
|
543
562
|
.then((res) => {
|
|
544
|
-
|
|
545
|
-
return res.json()
|
|
563
|
+
return safeJson(res)
|
|
546
564
|
})
|
|
547
565
|
.then((data) => {
|
|
548
566
|
setUpdaterStatus(data)
|
|
@@ -563,7 +581,7 @@ window.__ModuleLoader__.load({
|
|
|
563
581
|
method: 'POST',
|
|
564
582
|
headers: { 'x-dsh-plugin-update': '1', 'content-type': 'application/json' },
|
|
565
583
|
})
|
|
566
|
-
.then(
|
|
584
|
+
.then(safeJson)
|
|
567
585
|
.then((resData) => {
|
|
568
586
|
if (resData.error) throw new Error(resData.error.message || resData.error)
|
|
569
587
|
const cur = resData.updatedVersion || (updaterStatus && updaterStatus.latestVersion) || ''
|
|
@@ -759,7 +777,7 @@ window.__ModuleLoader__.load({
|
|
|
759
777
|
secretRef: webhookDraft.diffWebhookSecretRef || webhookDraft.diffWebhookSecret || '',
|
|
760
778
|
}),
|
|
761
779
|
})
|
|
762
|
-
const body = await res
|
|
780
|
+
const body = await safeJson(res)
|
|
763
781
|
if (res.ok && body.ok) {
|
|
764
782
|
setWebhookMsg(t.webhookSuccess)
|
|
765
783
|
} else {
|
|
@@ -893,7 +911,7 @@ window.__ModuleLoader__.load({
|
|
|
893
911
|
const key = `${targetProvider}:${targetModel}`
|
|
894
912
|
setTryState((current) => ({ ...current, [key]: { loading: true } }))
|
|
895
913
|
fetch(`${API}/try`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ provider: targetProvider, model: targetModel }) })
|
|
896
|
-
.then(async (r) => { const b = await r
|
|
914
|
+
.then(async (r) => { const b = await safeJson(r); return { ok: r.ok && b.ok !== false, latency: b.latencyMs, status: b.status, error: b.error } })
|
|
897
915
|
.then((res) => { setTryState((current) => ({ ...current, [key]: { loading: false, ok: res.ok, latency: res.latency, status: res.status, error: res.error } })) })
|
|
898
916
|
.catch((err) => { setTryState((current) => ({ ...current, [key]: { loading: false, ok: false, error: String(err?.message ?? err) } })) })
|
|
899
917
|
}
|
|
@@ -908,9 +926,7 @@ window.__ModuleLoader__.load({
|
|
|
908
926
|
body: JSON.stringify({ provider: selectionProvider, models: selectionDraft }),
|
|
909
927
|
})
|
|
910
928
|
.then(async (r) => {
|
|
911
|
-
|
|
912
|
-
if (!r.ok || data.error) throw new Error(data?.error?.message ?? `HTTP ${r.status}`)
|
|
913
|
-
return data
|
|
929
|
+
return safeJson(r)
|
|
914
930
|
})
|
|
915
931
|
.then((data) => {
|
|
916
932
|
const next = { ...tryState }
|
|
@@ -964,9 +980,7 @@ window.__ModuleLoader__.load({
|
|
|
964
980
|
body: JSON.stringify(parsed),
|
|
965
981
|
})
|
|
966
982
|
.then(async (r) => {
|
|
967
|
-
|
|
968
|
-
if (!r.ok) throw new Error(res.error?.message ?? `HTTP ${r.status}`)
|
|
969
|
-
return res
|
|
983
|
+
return safeJson(r)
|
|
970
984
|
})
|
|
971
985
|
.then(() => {
|
|
972
986
|
setImportMsg(t.importSuccess)
|
|
@@ -991,9 +1005,7 @@ window.__ModuleLoader__.load({
|
|
|
991
1005
|
body: JSON.stringify({ alias: aliasDraft.alias.trim(), provider: aliasDraft.provider, model: aliasDraft.model.trim() }),
|
|
992
1006
|
})
|
|
993
1007
|
.then(async (r) => {
|
|
994
|
-
|
|
995
|
-
if (!r.ok) throw new Error(res.error?.message ?? `HTTP ${r.status}`)
|
|
996
|
-
return res
|
|
1008
|
+
return safeJson(r)
|
|
997
1009
|
})
|
|
998
1010
|
.then(() => {
|
|
999
1011
|
setAliasDraft({ alias: '', provider: '', model: '' })
|
|
@@ -1012,9 +1024,7 @@ window.__ModuleLoader__.load({
|
|
|
1012
1024
|
body: JSON.stringify({ alias: aliasName, action: 'delete' }),
|
|
1013
1025
|
})
|
|
1014
1026
|
.then(async (r) => {
|
|
1015
|
-
|
|
1016
|
-
if (!r.ok) throw new Error(res.error?.message ?? `HTTP ${r.status}`)
|
|
1017
|
-
return res
|
|
1027
|
+
return safeJson(r)
|
|
1018
1028
|
})
|
|
1019
1029
|
.then(() => load())
|
|
1020
1030
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
@@ -1024,9 +1034,8 @@ window.__ModuleLoader__.load({
|
|
|
1024
1034
|
const resolveSmartAlias = (aliasName) => {
|
|
1025
1035
|
setResolvingKey(aliasName)
|
|
1026
1036
|
fetch(`${API}/aliases/resolve?alias=${encodeURIComponent(aliasName)}`)
|
|
1027
|
-
.then(
|
|
1028
|
-
|
|
1029
|
-
if (!r.ok) throw new Error(res.error?.message ?? `HTTP ${r.status}`)
|
|
1037
|
+
.then(safeJson)
|
|
1038
|
+
.then((res) => {
|
|
1030
1039
|
setResolvedAliases((prev) => ({ ...prev, [aliasName]: res }))
|
|
1031
1040
|
})
|
|
1032
1041
|
.catch((e) => {
|
|
@@ -1039,7 +1048,7 @@ window.__ModuleLoader__.load({
|
|
|
1039
1048
|
if (typeof document !== 'undefined' && document.hidden) return
|
|
1040
1049
|
setError('')
|
|
1041
1050
|
fetch(`${API}/status`)
|
|
1042
|
-
.then(
|
|
1051
|
+
.then(safeJson)
|
|
1043
1052
|
.then(setStatus)
|
|
1044
1053
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1045
1054
|
loadCredentials()
|
|
@@ -1047,7 +1056,7 @@ window.__ModuleLoader__.load({
|
|
|
1047
1056
|
|
|
1048
1057
|
const loadCredentials = () => {
|
|
1049
1058
|
fetch(`${API}/credentials`)
|
|
1050
|
-
.then(
|
|
1059
|
+
.then(safeJson)
|
|
1051
1060
|
.then(setCredentialStatus)
|
|
1052
1061
|
.catch(() => {})
|
|
1053
1062
|
}
|
|
@@ -1058,7 +1067,7 @@ window.__ModuleLoader__.load({
|
|
|
1058
1067
|
const effectiveDryRun = options.dryRun !== undefined ? options.dryRun : dryRun
|
|
1059
1068
|
setBusy(true); setError(''); setPreview(null)
|
|
1060
1069
|
fetch(`${API}/run`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ provider: targetProvider, dryRun: effectiveDryRun, removeMissing }) })
|
|
1061
|
-
.then(
|
|
1070
|
+
.then(safeJson)
|
|
1062
1071
|
.then((body) => {
|
|
1063
1072
|
setStatus(body)
|
|
1064
1073
|
if (effectiveDryRun && body.results) setPreview(body.results)
|
|
@@ -1074,7 +1083,7 @@ window.__ModuleLoader__.load({
|
|
|
1074
1083
|
const checkHealth = (targetProvider) => {
|
|
1075
1084
|
setBusy(true); setError('')
|
|
1076
1085
|
fetch(`${API}/health`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ provider: targetProvider }) })
|
|
1077
|
-
.then(
|
|
1086
|
+
.then(safeJson)
|
|
1078
1087
|
.then(setStatus)
|
|
1079
1088
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1080
1089
|
.finally(() => setBusy(false))
|
|
@@ -1083,7 +1092,7 @@ window.__ModuleLoader__.load({
|
|
|
1083
1092
|
const checkCredentials = (targetProvider) => {
|
|
1084
1093
|
setBusy(true); setError('')
|
|
1085
1094
|
fetch(`${API}/credentials/check`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ provider: targetProvider }) })
|
|
1086
|
-
.then(
|
|
1095
|
+
.then(safeJson)
|
|
1087
1096
|
.then((body) => { if (body.credentials) setCredentialStatus(body.credentials); load() })
|
|
1088
1097
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1089
1098
|
.finally(() => setBusy(false))
|
|
@@ -1092,7 +1101,7 @@ window.__ModuleLoader__.load({
|
|
|
1092
1101
|
const updateNotification = (id, action) => {
|
|
1093
1102
|
setBusy(true); setError('')
|
|
1094
1103
|
fetch(`${API}/notifications/${action}`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id }) })
|
|
1095
|
-
.then(
|
|
1104
|
+
.then(safeJson)
|
|
1096
1105
|
.then(() => load())
|
|
1097
1106
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1098
1107
|
.finally(() => setBusy(false))
|
|
@@ -1187,7 +1196,7 @@ window.__ModuleLoader__.load({
|
|
|
1187
1196
|
headers: { 'content-type': 'application/json' },
|
|
1188
1197
|
body: JSON.stringify(payload),
|
|
1189
1198
|
})
|
|
1190
|
-
.then(
|
|
1199
|
+
.then(safeJson)
|
|
1191
1200
|
.then(() => { closePolicy(); return load() })
|
|
1192
1201
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1193
1202
|
.finally(() => setBusy(false))
|
|
@@ -1204,7 +1213,7 @@ window.__ModuleLoader__.load({
|
|
|
1204
1213
|
headers: { 'content-type': 'application/json' },
|
|
1205
1214
|
body: JSON.stringify({ provider: selectionProvider, models }),
|
|
1206
1215
|
})
|
|
1207
|
-
.then(
|
|
1216
|
+
.then(safeJson)
|
|
1208
1217
|
.then((body) => { setStatus(body); closeSelection() })
|
|
1209
1218
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1210
1219
|
.finally(() => setBusy(false))
|
|
@@ -1218,7 +1227,7 @@ window.__ModuleLoader__.load({
|
|
|
1218
1227
|
headers: { 'content-type': 'application/json' },
|
|
1219
1228
|
body: JSON.stringify({ historyId: entry.id, provider: targetProvider }),
|
|
1220
1229
|
})
|
|
1221
|
-
.then(
|
|
1230
|
+
.then(safeJson)
|
|
1222
1231
|
.then(() => load())
|
|
1223
1232
|
.catch((e) => setError(String(e?.message ?? e)))
|
|
1224
1233
|
.finally(() => setBusy(false))
|
|
@@ -1807,7 +1816,7 @@ window.__ModuleLoader__.load({
|
|
|
1807
1816
|
ensureStyles()
|
|
1808
1817
|
const load = () => {
|
|
1809
1818
|
if (typeof document !== 'undefined' && document.hidden) return
|
|
1810
|
-
fetch(`${API}/status`).then(
|
|
1819
|
+
fetch(`${API}/status`).then(safeJson).then(setCardStatus).catch(() => {})
|
|
1811
1820
|
}
|
|
1812
1821
|
load()
|
|
1813
1822
|
if (open) return
|
package/lib/http.js
CHANGED
|
@@ -272,7 +272,8 @@ export function registerHttpApi(ctx, synchronizer, { getSchedulerStatus = () =>
|
|
|
272
272
|
return []
|
|
273
273
|
}
|
|
274
274
|
const makeHandler = (route) => async (req, res) => {
|
|
275
|
-
|
|
275
|
+
try {
|
|
276
|
+
// 1. Core connection check on all routes (#237)
|
|
276
277
|
const conn = ctx?.connection || ctx?.get?.('connection') || req?.connection
|
|
277
278
|
if (conn && typeof conn.requestRejection === 'function') {
|
|
278
279
|
const rejection = conn.requestRejection(req)
|
|
@@ -382,6 +383,12 @@ export function registerHttpApi(ctx, synchronizer, { getSchedulerStatus = () =>
|
|
|
382
383
|
const code = error?.code === 'SETTINGS_CONFLICT' ? 409 : error?.code === 'SETTINGS_UNAVAILABLE' || error?.code === 'CONFIG_UNAVAILABLE' ? 503 : error?.code === 'PROVIDER_NOT_CONFIGURED' || error?.code === 'UNKNOWN_MODEL' || error?.code === 'INVALID_POLICY' || error?.code === 'INVALID_HISTORY' || error?.code === 'HISTORY_NOT_FOUND' || error?.code === 'INVALID_NOTIFICATION' || error?.code === 'NOTIFICATION_NOT_FOUND' || error?.code === 'INVALID_ALIAS' || error?.code === 'INVALID_CONFIG' ? 400 : 500
|
|
383
384
|
return json(res, code, { error: { code: error?.code ?? 'run-failed', message: error instanceof Error ? error.message : String(error) } })
|
|
384
385
|
}
|
|
386
|
+
} catch (unhandledError) {
|
|
387
|
+
if (typeof ctx?.logger?.error === 'function') {
|
|
388
|
+
ctx.logger.error('[dsh-model-sync] unhandled HTTP error on route ' + route + ':', unhandledError)
|
|
389
|
+
}
|
|
390
|
+
return json(res, 500, { error: { code: 'internal_error', message: unhandledError instanceof Error ? unhandledError.message : String(unhandledError) } })
|
|
391
|
+
}
|
|
385
392
|
}
|
|
386
393
|
return [
|
|
387
394
|
ctx.webServer.register({ kind: 'exact', path: `${BASE}/status`, handler: makeHandler('status') }),
|
package/lib/index.js
CHANGED
|
@@ -6,7 +6,7 @@ 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', 'webServer', 'credentials']
|
|
9
|
+
export const inject = ['llm', 'webServer', 'credentials', 'settings']
|
|
10
10
|
|
|
11
11
|
const NS = 'dsh-model-sync'
|
|
12
12
|
|
package/lib/provider-service.js
CHANGED
|
@@ -3,18 +3,18 @@ import { listApiKeyProviders } from './inventory.js'
|
|
|
3
3
|
export function createProviderService(ctx) {
|
|
4
4
|
const readSettings = () => {
|
|
5
5
|
try {
|
|
6
|
-
return (typeof ctx
|
|
6
|
+
return ctx?.settings ?? ctx?.reflect?.get?.('settings') ?? (typeof ctx?.get === 'function' ? ctx.get('settings') : undefined)
|
|
7
7
|
} catch {
|
|
8
|
-
return
|
|
8
|
+
return undefined
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const readLlm = () => {
|
|
13
13
|
try {
|
|
14
|
-
const llm = typeof ctx
|
|
15
|
-
return (llm && typeof llm === 'object' && (llm.listConfigurableProviders || llm.listProviders)) ? llm :
|
|
14
|
+
const llm = ctx?.llm ?? ctx?.reflect?.get?.('llm') ?? (typeof ctx?.get === 'function' ? ctx.get('llm') : null)
|
|
15
|
+
return (llm && typeof llm === 'object' && (llm.listConfigurableProviders || llm.listProviders)) ? llm : undefined
|
|
16
16
|
} catch {
|
|
17
|
-
return
|
|
17
|
+
return undefined
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -39,15 +39,19 @@ export function reliabilityOptions(config, options) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function settingsOf(ctx) {
|
|
42
|
-
try {
|
|
42
|
+
try {
|
|
43
|
+
return ctx?.settings ?? ctx?.reflect?.get?.('settings') ?? (typeof ctx?.get === 'function' ? ctx.get('settings') : undefined)
|
|
44
|
+
} catch {
|
|
45
|
+
return undefined
|
|
46
|
+
}
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
export function llmOf(ctx) {
|
|
46
50
|
try {
|
|
47
|
-
const llm = typeof ctx
|
|
48
|
-
return (llm && typeof llm === 'object' && (llm.listConfigurableProviders || llm.listProviders)) ? llm :
|
|
51
|
+
const llm = ctx?.llm ?? ctx?.reflect?.get?.('llm') ?? (typeof ctx?.get === 'function' ? ctx.get('llm') : null)
|
|
52
|
+
return (llm && typeof llm === 'object' && (llm.listConfigurableProviders || llm.listProviders)) ? llm : undefined
|
|
49
53
|
} catch {
|
|
50
|
-
return
|
|
54
|
+
return undefined
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
|
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.14",
|
|
4
4
|
"description": "Automatic model catalog synchronization for API-key DeepSeek Harness providers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"license": "MIT",
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
56
|
-
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
57
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
58
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
59
|
-
"@deepseek-ai/dsh-settings": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.1 || >=0.2.1-alpha.1",
|
|
57
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1 || >=0.2.1-alpha.1",
|
|
58
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1 || >=0.2.1-alpha.1",
|
|
59
|
+
"@deepseek-ai/dsh-settings": "^0.1.7-rc.2 || ^0.2.0-rc.1 || >=0.2.1-alpha.1",
|
|
60
60
|
"@deepseek-ai/schemastery": "^3.18.4"
|
|
61
61
|
}
|
|
62
62
|
}
|