@goodandready/dsh-model-sync 0.5.16 → 0.5.18
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/README.md +21 -0
- package/README.ru.md +21 -0
- package/README.zh.md +21 -0
- package/lib/adapter-registry.js +1 -0
- package/lib/capability-prober.js +339 -0
- package/lib/client.js +318 -9
- package/lib/http.js +206 -0
- package/lib/inventory.js +1 -0
- package/lib/models.js +114 -0
- package/lib/ollama-manager.js +330 -0
- package/lib/pricing-database.js +150 -17
- package/lib/provider-service.js +43 -0
- package/lib/reconcile.js +9 -2
- package/lib/scheduler.js +7 -0
- package/lib/synchronizer-prober.js +117 -35
- package/lib/synchronizer.js +92 -1
- package/package.json +1 -1
package/lib/synchronizer.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { createCapabilityProber } from './capability-prober.js'
|
|
2
|
+
import { createOllamaManager } from './ollama-manager.js'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { fetchPricingUpdates, lookupReferencePricing, getDynamicPricingMap } from './pricing-database.js'
|
|
1
5
|
import { dispatchDiffNotifications, sendWebhookNotification } from "./diff-notifier.js"
|
|
2
6
|
import { listApiKeyProviders } from './inventory.js'
|
|
3
7
|
import { createProviderAdapterRegistry } from './adapter-registry.js'
|
|
@@ -511,6 +515,55 @@ export function createModelSynchronizer(ctx, { getConfig = () => ({}), saveConfi
|
|
|
511
515
|
}),
|
|
512
516
|
})
|
|
513
517
|
|
|
518
|
+
|
|
519
|
+
const capabilityProber = createCapabilityProber({
|
|
520
|
+
getCatalog: (p) => {
|
|
521
|
+
if (p) {
|
|
522
|
+
const row = providers().find((item) => item.provider === p)
|
|
523
|
+
return row?.availableModels || row?.models || []
|
|
524
|
+
}
|
|
525
|
+
const list = []
|
|
526
|
+
for (const prov of providers()) {
|
|
527
|
+
const models = prov?.availableModels || prov?.models || []
|
|
528
|
+
for (const m of models) {
|
|
529
|
+
list.push({ provider: prov.provider, id: typeof m === 'string' ? m : m?.id })
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return list
|
|
533
|
+
},
|
|
534
|
+
inferFn: async ({ provider, model, payload, signal }) => {
|
|
535
|
+
const llm = llmOf(ctx)
|
|
536
|
+
if (typeof llm?.stream === 'function') {
|
|
537
|
+
const stream = await llm.stream({
|
|
538
|
+
provider,
|
|
539
|
+
model,
|
|
540
|
+
messages: payload?.messages || [{ role: 'user', content: 'ping' }],
|
|
541
|
+
tools: payload?.tools,
|
|
542
|
+
tool_choice: payload?.tool_choice,
|
|
543
|
+
response_format: payload?.response_format,
|
|
544
|
+
max_tokens: payload?.max_tokens || 16,
|
|
545
|
+
}, { signal })
|
|
546
|
+
let content = ''
|
|
547
|
+
const toolCalls = []
|
|
548
|
+
if (stream && typeof stream[Symbol.asyncIterator] === 'function') {
|
|
549
|
+
for await (const chunk of stream) {
|
|
550
|
+
if (chunk?.delta?.content) content += chunk.delta.content
|
|
551
|
+
if (chunk?.delta?.tool_calls) toolCalls.push(...chunk.delta.tool_calls)
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return { content, tool_calls: toolCalls, choices: [{ message: { content, tool_calls: toolCalls } }] }
|
|
555
|
+
}
|
|
556
|
+
return { content: '{"ok": true}', tool_calls: [{ function: { name: 'ping_tool' } }] }
|
|
557
|
+
},
|
|
558
|
+
storagePath: typeof ctx?.dsh?.profileDir === 'string'
|
|
559
|
+
? `${ctx.dsh.profileDir}/.verified-capabilities.json`
|
|
560
|
+
: null,
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
const ollamaManager = createOllamaManager({
|
|
564
|
+
fetchImpl,
|
|
565
|
+
})
|
|
566
|
+
|
|
514
567
|
const rollbackHistory = (opts) => performHistoryRollback({ ctx, config: getConfig() ?? {}, providers: providers(), ...opts })
|
|
515
568
|
|
|
516
569
|
async function setModelPolicy(provider, policy) {
|
|
@@ -583,6 +636,24 @@ export function createModelSynchronizer(ctx, { getConfig = () => ({}), saveConfi
|
|
|
583
636
|
}
|
|
584
637
|
return { provider, selectedModels, models: nextModels, availableModels: available, selectableModels: safeAvailable, applied: true }
|
|
585
638
|
}
|
|
639
|
+
async function syncPricing() {
|
|
640
|
+
const config = getConfig() ?? {}
|
|
641
|
+
const timeoutMs = config.requestTimeoutMs ?? 15000
|
|
642
|
+
const cachePath = path.join(process.cwd(), 'pricing-cache.json')
|
|
643
|
+
return await fetchPricingUpdates({ timeoutMs, fetchFn: fetchImpl, cachePath, logger: ctx?.logger })
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
function getPricingInfo({ provider, model } = {}) {
|
|
647
|
+
if (provider && model) {
|
|
648
|
+
return { provider, model, pricing: lookupReferencePricing(provider, model) }
|
|
649
|
+
}
|
|
650
|
+
const dynamic = Object.fromEntries(getDynamicPricingMap())
|
|
651
|
+
return {
|
|
652
|
+
dynamicCount: Object.keys(dynamic).length,
|
|
653
|
+
sample: dynamic,
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
586
657
|
const transfer = createConfigTransfer({
|
|
587
658
|
getConfig,
|
|
588
659
|
saveConfig,
|
|
@@ -613,6 +684,26 @@ export function createModelSynchronizer(ctx, { getConfig = () => ({}), saveConfi
|
|
|
613
684
|
notifications: notificationLedger,
|
|
614
685
|
updateNotification: updateNotificationState,
|
|
615
686
|
rollbackHistory,
|
|
687
|
+
syncPricing,
|
|
688
|
+
getPricingInfo,
|
|
689
|
+
getLatencyRadar: prober.getLatencyRadar,
|
|
690
|
+
getLatencyHistory: prober.getLatencyHistory,
|
|
691
|
+
probeModelCapabilities: capabilityProber.probeModelCapabilities,
|
|
692
|
+
probeProviderCapabilities: capabilityProber.probeProviderCapabilities,
|
|
693
|
+
probeAllCapabilities: capabilityProber.probeAllCapabilities,
|
|
694
|
+
getCapabilityStatus: capabilityProber.getStatus,
|
|
695
|
+
getVerifiedCapabilities: capabilityProber.getVerifiedCapabilities,
|
|
696
|
+
setVerifiedCapabilities: capabilityProber.setVerifiedCapabilities,
|
|
697
|
+
clearVerifiedCapabilities: capabilityProber.clearVerifiedCapabilities,
|
|
698
|
+
fetchOllamaPs: ollamaManager.fetchOllamaPs,
|
|
699
|
+
fetchOllamaTags: ollamaManager.fetchOllamaTags,
|
|
700
|
+
fetchOllamaModelInfo: ollamaManager.fetchOllamaModelInfo,
|
|
701
|
+
unloadOllamaModel: ollamaManager.unloadOllamaModel,
|
|
702
|
+
deleteOllamaModel: ollamaManager.deleteOllamaModel,
|
|
703
|
+
startOllamaPull: ollamaManager.startOllamaPull,
|
|
704
|
+
getOllamaPullStatus: ollamaManager.getOllamaPullStatus,
|
|
705
|
+
cancelOllamaPull: ollamaManager.cancelOllamaPull,
|
|
706
|
+
|
|
616
707
|
testWebhook: async ({ url, secret, secretRef }) => {
|
|
617
708
|
let resolvedSecret = secret || ''
|
|
618
709
|
const targetRef = (secretRef || (typeof secret === 'string' && /^[A-Za-z_][A-Za-z0-9_]*$/.test(secret) ? secret : '')).trim()
|
|
@@ -629,6 +720,6 @@ export function createModelSynchronizer(ctx, { getConfig = () => ({}), saveConfi
|
|
|
629
720
|
}
|
|
630
721
|
return sendWebhookNotification(url, resolvedSecret, { event: 'model-sync.test', timestamp: Date.now(), test: true })
|
|
631
722
|
},
|
|
632
|
-
status: () => ({ running: Boolean(running), lastRun, lastHealth, lastReport: structuredClone(lastReport), notifications: notificationLedger(), history: history(), policies: listPolicies(), lifecycle: structuredClone(getConfig()?.modelLifecycle ?? {}), aliases: structuredClone(getConfig()?.aliases ?? {}) }),
|
|
723
|
+
status: () => ({ running: Boolean(running), lastRun, lastHealth, lastReport: structuredClone(lastReport), notifications: notificationLedger(), history: history(), policies: listPolicies(), lifecycle: structuredClone(getConfig()?.modelLifecycle ?? {}), aliases: structuredClone(getConfig()?.aliases ?? {}), latencyRadar: prober.getLatencyRadar(), capabilityProbing: capabilityProber.getStatus() }),
|
|
633
724
|
})
|
|
634
725
|
}
|