@sriinnu/kosha-discovery 0.5.0
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/LICENSE +21 -0
- package/README.md +286 -0
- package/dist/aliases.d.ts +51 -0
- package/dist/aliases.d.ts.map +1 -0
- package/dist/aliases.js +115 -0
- package/dist/aliases.js.map +1 -0
- package/dist/cache.d.ts +57 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +123 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli-commands.d.ts +142 -0
- package/dist/cli-commands.d.ts.map +1 -0
- package/dist/cli-commands.js +746 -0
- package/dist/cli-commands.js.map +1 -0
- package/dist/cli-format.d.ts +119 -0
- package/dist/cli-format.d.ts.map +1 -0
- package/dist/cli-format.js +171 -0
- package/dist/cli-format.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +143 -0
- package/dist/cli.js.map +1 -0
- package/dist/credentials/index.d.ts +2 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +2 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/credentials/resolver.d.ts +170 -0
- package/dist/credentials/resolver.d.ts.map +1 -0
- package/dist/credentials/resolver.js +597 -0
- package/dist/credentials/resolver.js.map +1 -0
- package/dist/discovery/anthropic.d.ts +49 -0
- package/dist/discovery/anthropic.d.ts.map +1 -0
- package/dist/discovery/anthropic.js +101 -0
- package/dist/discovery/anthropic.js.map +1 -0
- package/dist/discovery/base.d.ts +59 -0
- package/dist/discovery/base.d.ts.map +1 -0
- package/dist/discovery/base.js +123 -0
- package/dist/discovery/base.js.map +1 -0
- package/dist/discovery/bedrock.d.ts +122 -0
- package/dist/discovery/bedrock.d.ts.map +1 -0
- package/dist/discovery/bedrock.js +356 -0
- package/dist/discovery/bedrock.js.map +1 -0
- package/dist/discovery/cerebras.d.ts +43 -0
- package/dist/discovery/cerebras.d.ts.map +1 -0
- package/dist/discovery/cerebras.js +65 -0
- package/dist/discovery/cerebras.js.map +1 -0
- package/dist/discovery/cohere.d.ts +57 -0
- package/dist/discovery/cohere.d.ts.map +1 -0
- package/dist/discovery/cohere.js +82 -0
- package/dist/discovery/cohere.js.map +1 -0
- package/dist/discovery/deepinfra.d.ts +41 -0
- package/dist/discovery/deepinfra.d.ts.map +1 -0
- package/dist/discovery/deepinfra.js +86 -0
- package/dist/discovery/deepinfra.js.map +1 -0
- package/dist/discovery/deepseek.d.ts +17 -0
- package/dist/discovery/deepseek.d.ts.map +1 -0
- package/dist/discovery/deepseek.js +45 -0
- package/dist/discovery/deepseek.js.map +1 -0
- package/dist/discovery/fireworks.d.ts +48 -0
- package/dist/discovery/fireworks.d.ts.map +1 -0
- package/dist/discovery/fireworks.js +101 -0
- package/dist/discovery/fireworks.js.map +1 -0
- package/dist/discovery/glm.d.ts +17 -0
- package/dist/discovery/glm.d.ts.map +1 -0
- package/dist/discovery/glm.js +52 -0
- package/dist/discovery/glm.js.map +1 -0
- package/dist/discovery/google.d.ts +53 -0
- package/dist/discovery/google.d.ts.map +1 -0
- package/dist/discovery/google.js +122 -0
- package/dist/discovery/google.js.map +1 -0
- package/dist/discovery/groq.d.ts +44 -0
- package/dist/discovery/groq.d.ts.map +1 -0
- package/dist/discovery/groq.js +89 -0
- package/dist/discovery/groq.js.map +1 -0
- package/dist/discovery/index.d.ts +48 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +116 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/llama-cpp.d.ts +45 -0
- package/dist/discovery/llama-cpp.d.ts.map +1 -0
- package/dist/discovery/llama-cpp.js +137 -0
- package/dist/discovery/llama-cpp.js.map +1 -0
- package/dist/discovery/minimax.d.ts +16 -0
- package/dist/discovery/minimax.d.ts.map +1 -0
- package/dist/discovery/minimax.js +56 -0
- package/dist/discovery/minimax.js.map +1 -0
- package/dist/discovery/mistral.d.ts +45 -0
- package/dist/discovery/mistral.d.ts.map +1 -0
- package/dist/discovery/mistral.js +82 -0
- package/dist/discovery/mistral.js.map +1 -0
- package/dist/discovery/moonshot.d.ts +16 -0
- package/dist/discovery/moonshot.d.ts.map +1 -0
- package/dist/discovery/moonshot.js +46 -0
- package/dist/discovery/moonshot.js.map +1 -0
- package/dist/discovery/nvidia.d.ts +60 -0
- package/dist/discovery/nvidia.d.ts.map +1 -0
- package/dist/discovery/nvidia.js +145 -0
- package/dist/discovery/nvidia.js.map +1 -0
- package/dist/discovery/ollama.d.ts +57 -0
- package/dist/discovery/ollama.d.ts.map +1 -0
- package/dist/discovery/ollama.js +151 -0
- package/dist/discovery/ollama.js.map +1 -0
- package/dist/discovery/openai-compatible.d.ts +126 -0
- package/dist/discovery/openai-compatible.d.ts.map +1 -0
- package/dist/discovery/openai-compatible.js +161 -0
- package/dist/discovery/openai-compatible.js.map +1 -0
- package/dist/discovery/openai.d.ts +62 -0
- package/dist/discovery/openai.d.ts.map +1 -0
- package/dist/discovery/openai.js +157 -0
- package/dist/discovery/openai.js.map +1 -0
- package/dist/discovery/openrouter.d.ts +78 -0
- package/dist/discovery/openrouter.d.ts.map +1 -0
- package/dist/discovery/openrouter.js +184 -0
- package/dist/discovery/openrouter.js.map +1 -0
- package/dist/discovery/perplexity.d.ts +66 -0
- package/dist/discovery/perplexity.d.ts.map +1 -0
- package/dist/discovery/perplexity.js +86 -0
- package/dist/discovery/perplexity.js.map +1 -0
- package/dist/discovery/together.d.ts +41 -0
- package/dist/discovery/together.d.ts.map +1 -0
- package/dist/discovery/together.js +88 -0
- package/dist/discovery/together.js.map +1 -0
- package/dist/discovery/vertex.d.ts +146 -0
- package/dist/discovery/vertex.d.ts.map +1 -0
- package/dist/discovery/vertex.js +371 -0
- package/dist/discovery/vertex.js.map +1 -0
- package/dist/discovery/zai.d.ts +17 -0
- package/dist/discovery/zai.d.ts.map +1 -0
- package/dist/discovery/zai.js +51 -0
- package/dist/discovery/zai.js.map +1 -0
- package/dist/discovery-contract.d.ts +186 -0
- package/dist/discovery-contract.d.ts.map +1 -0
- package/dist/discovery-contract.js +115 -0
- package/dist/discovery-contract.js.map +1 -0
- package/dist/discovery-routes.d.ts +14 -0
- package/dist/discovery-routes.d.ts.map +1 -0
- package/dist/discovery-routes.js +98 -0
- package/dist/discovery-routes.js.map +1 -0
- package/dist/enrichment/index.d.ts +2 -0
- package/dist/enrichment/index.d.ts.map +1 -0
- package/dist/enrichment/index.js +2 -0
- package/dist/enrichment/index.js.map +1 -0
- package/dist/enrichment/litellm.d.ts +52 -0
- package/dist/enrichment/litellm.d.ts.map +1 -0
- package/dist/enrichment/litellm.js +205 -0
- package/dist/enrichment/litellm.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize.d.ts +64 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +166 -0
- package/dist/normalize.js.map +1 -0
- package/dist/provider-catalog.d.ts +62 -0
- package/dist/provider-catalog.d.ts.map +1 -0
- package/dist/provider-catalog.js +331 -0
- package/dist/provider-catalog.js.map +1 -0
- package/dist/registry-delta.d.ts +17 -0
- package/dist/registry-delta.d.ts.map +1 -0
- package/dist/registry-delta.js +74 -0
- package/dist/registry-delta.js.map +1 -0
- package/dist/registry-discovery.d.ts +66 -0
- package/dist/registry-discovery.d.ts.map +1 -0
- package/dist/registry-discovery.js +339 -0
- package/dist/registry-discovery.js.map +1 -0
- package/dist/registry-query.d.ts +74 -0
- package/dist/registry-query.d.ts.map +1 -0
- package/dist/registry-query.js +310 -0
- package/dist/registry-query.js.map +1 -0
- package/dist/registry-runtime.d.ts +48 -0
- package/dist/registry-runtime.d.ts.map +1 -0
- package/dist/registry-runtime.js +255 -0
- package/dist/registry-runtime.js.map +1 -0
- package/dist/registry-selection.d.ts +31 -0
- package/dist/registry-selection.d.ts.map +1 -0
- package/dist/registry-selection.js +167 -0
- package/dist/registry-selection.js.map +1 -0
- package/dist/registry-state.d.ts +92 -0
- package/dist/registry-state.d.ts.map +1 -0
- package/dist/registry-state.js +35 -0
- package/dist/registry-state.js.map +1 -0
- package/dist/registry.d.ts +127 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +248 -0
- package/dist/registry.js.map +1 -0
- package/dist/resilience.d.ts +212 -0
- package/dist/resilience.d.ts.map +1 -0
- package/dist/resilience.js +292 -0
- package/dist/resilience.js.map +1 -0
- package/dist/security.d.ts +44 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +184 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +41 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +320 -0
- package/dist/server.js.map +1 -0
- package/dist/shell-safe.d.ts +15 -0
- package/dist/shell-safe.d.ts.map +1 -0
- package/dist/shell-safe.js +20 -0
- package/dist/shell-safe.js.map +1 -0
- package/dist/types.d.ts +365 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/logo.svg +81 -0
- package/package.json +85 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kosha-discovery — Core query helpers for ModelRegistry.
|
|
3
|
+
*
|
|
4
|
+
* I keep model lookup, role filtering, capability aggregation, and cheapest
|
|
5
|
+
* route selection here so the registry façade can stay under the file-size
|
|
6
|
+
* policy while preserving the public API.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { extractModelVersion, extractOriginProvider, normalizeModelId } from "./normalize.js";
|
|
10
|
+
import { getProviderDescriptor, isLocalProvider, normalizeProviderId } from "./provider-catalog.js";
|
|
11
|
+
const ROLE_ALIASES = {
|
|
12
|
+
embeddings: "embedding",
|
|
13
|
+
vector: "embedding",
|
|
14
|
+
vectors: "embedding",
|
|
15
|
+
images: "image_generation",
|
|
16
|
+
imagegen: "image_generation",
|
|
17
|
+
image_generation: "image_generation",
|
|
18
|
+
image_generation_model: "image_generation",
|
|
19
|
+
stt: "speech_to_text",
|
|
20
|
+
transcription: "speech_to_text",
|
|
21
|
+
tts: "text_to_speech",
|
|
22
|
+
speech: "audio",
|
|
23
|
+
tool_use: "function_calling",
|
|
24
|
+
tools: "function_calling",
|
|
25
|
+
functions: "function_calling",
|
|
26
|
+
functioncalling: "function_calling",
|
|
27
|
+
prompt_cache: "prompt_caching",
|
|
28
|
+
};
|
|
29
|
+
const MODE_ALIASES = {
|
|
30
|
+
chat: "chat",
|
|
31
|
+
completion: "chat",
|
|
32
|
+
completions: "chat",
|
|
33
|
+
embedding: "embedding",
|
|
34
|
+
image: "image",
|
|
35
|
+
image_generation: "image",
|
|
36
|
+
audio: "audio",
|
|
37
|
+
speech_to_text: "audio",
|
|
38
|
+
text_to_speech: "audio",
|
|
39
|
+
moderation: "moderation",
|
|
40
|
+
safety: "moderation",
|
|
41
|
+
rerank: "rerank",
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Return a stable provider descriptor, even for synthetic test providers.
|
|
45
|
+
*/
|
|
46
|
+
export function registryProviderDescriptor(state, providerId, providerInfo) {
|
|
47
|
+
return getProviderDescriptor(providerId) ?? {
|
|
48
|
+
providerId,
|
|
49
|
+
canonicalProviderId: providerId,
|
|
50
|
+
aliases: [],
|
|
51
|
+
name: providerInfo?.name ?? providerId,
|
|
52
|
+
origin: isLocalProvider(providerId) ? "local" : "direct",
|
|
53
|
+
isLocal: isLocalProvider(providerId),
|
|
54
|
+
transport: "native-http",
|
|
55
|
+
defaultBaseUrl: providerInfo?.baseUrl ?? "",
|
|
56
|
+
credentialRequired: false,
|
|
57
|
+
credentialEnvVars: [],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Normalize a role or capability token for routing and filtering.
|
|
62
|
+
*/
|
|
63
|
+
export function normalizeRoleToken(value) {
|
|
64
|
+
const token = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
65
|
+
return ROLE_ALIASES[token] ?? token;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Return the deduplicated role list for a single model.
|
|
69
|
+
*/
|
|
70
|
+
export function modelRoles(model) {
|
|
71
|
+
return Array.from(new Set([model.mode, ...model.capabilities.map((capability) => normalizeRoleToken(capability))]));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check whether a model satisfies a role or capability query.
|
|
75
|
+
*/
|
|
76
|
+
export function modelSupportsRole(model, roleOrCapability) {
|
|
77
|
+
const token = normalizeRoleToken(roleOrCapability);
|
|
78
|
+
if (modelRoles(model).includes(token))
|
|
79
|
+
return true;
|
|
80
|
+
const mode = MODE_ALIASES[token];
|
|
81
|
+
if (mode && model.mode === mode)
|
|
82
|
+
return true;
|
|
83
|
+
return token === "image_generation" && model.mode === "image";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* List models with provider-aware deduplication and optional filters.
|
|
87
|
+
*/
|
|
88
|
+
export function registryModels(state, filter) {
|
|
89
|
+
const normalizedProvider = normalizeProviderId(filter?.provider);
|
|
90
|
+
const normalizedOriginProvider = normalizeProviderId(filter?.originProvider);
|
|
91
|
+
const seen = new Set();
|
|
92
|
+
const result = [];
|
|
93
|
+
for (const providerInfo of state.providerMap.values()) {
|
|
94
|
+
if (normalizedProvider && providerInfo.id !== normalizedProvider)
|
|
95
|
+
continue;
|
|
96
|
+
for (const model of providerInfo.models) {
|
|
97
|
+
// I dedupe by provider+model so the same upstream model can still appear through different routes.
|
|
98
|
+
const dedupKey = `${model.provider}:${model.id}`;
|
|
99
|
+
if (seen.has(dedupKey))
|
|
100
|
+
continue;
|
|
101
|
+
if (normalizedOriginProvider && normalizeProviderId(model.originProvider) !== normalizedOriginProvider)
|
|
102
|
+
continue;
|
|
103
|
+
if (filter?.mode && model.mode !== filter.mode)
|
|
104
|
+
continue;
|
|
105
|
+
if (filter?.capability && !model.capabilities.includes(filter.capability))
|
|
106
|
+
continue;
|
|
107
|
+
seen.add(dedupKey);
|
|
108
|
+
result.push(model);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build the provider -> model -> roles matrix used by the legacy API.
|
|
115
|
+
*/
|
|
116
|
+
export function registryProviderRoles(state, filter) {
|
|
117
|
+
const normalizedProvider = normalizeProviderId(filter?.provider);
|
|
118
|
+
const normalizedOriginProvider = normalizeProviderId(filter?.originProvider);
|
|
119
|
+
const normalizedCapability = filter?.capability ? normalizeRoleToken(filter.capability) : undefined;
|
|
120
|
+
const providers = [];
|
|
121
|
+
for (const providerInfo of state.providerMap.values()) {
|
|
122
|
+
if (normalizedProvider && providerInfo.id !== normalizedProvider)
|
|
123
|
+
continue;
|
|
124
|
+
const models = providerInfo.models.filter((model) => {
|
|
125
|
+
if (normalizedOriginProvider && normalizeProviderId(model.originProvider) !== normalizedOriginProvider)
|
|
126
|
+
return false;
|
|
127
|
+
if (filter?.mode && model.mode !== filter.mode)
|
|
128
|
+
return false;
|
|
129
|
+
if (normalizedCapability && !modelSupportsRole(model, normalizedCapability))
|
|
130
|
+
return false;
|
|
131
|
+
if (filter?.role && !modelSupportsRole(model, filter.role))
|
|
132
|
+
return false;
|
|
133
|
+
return true;
|
|
134
|
+
}).map((model) => ({
|
|
135
|
+
id: model.id,
|
|
136
|
+
name: model.name,
|
|
137
|
+
provider: model.provider,
|
|
138
|
+
originProvider: model.originProvider,
|
|
139
|
+
mode: model.mode,
|
|
140
|
+
roles: modelRoles(model),
|
|
141
|
+
pricing: model.pricing,
|
|
142
|
+
}));
|
|
143
|
+
if (models.length === 0)
|
|
144
|
+
continue;
|
|
145
|
+
providers.push({
|
|
146
|
+
id: providerInfo.id,
|
|
147
|
+
name: providerInfo.name,
|
|
148
|
+
authenticated: providerInfo.authenticated,
|
|
149
|
+
credentialSource: providerInfo.credentialSource,
|
|
150
|
+
models: models.sort((a, b) => a.id.localeCompare(b.id)),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return providers.sort((a, b) => a.id.localeCompare(b.id));
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Return prompts for currently discovered providers missing required credentials.
|
|
157
|
+
*/
|
|
158
|
+
export function registryMissingCredentialPrompts(state, providerIds) {
|
|
159
|
+
const normalizedIds = providerIds?.map((providerId) => normalizeProviderId(providerId) ?? providerId);
|
|
160
|
+
const providers = providerIds && providerIds.length > 0
|
|
161
|
+
? normalizedIds?.flatMap((providerId) => {
|
|
162
|
+
const provider = state.providerMap.get(providerId ?? "");
|
|
163
|
+
return provider ? [provider] : [];
|
|
164
|
+
}) ?? []
|
|
165
|
+
: Array.from(state.providerMap.values());
|
|
166
|
+
const prompts = [];
|
|
167
|
+
for (const provider of providers) {
|
|
168
|
+
const descriptor = registryProviderDescriptor(state, provider.id, provider);
|
|
169
|
+
if (!descriptor.credentialRequired || provider.authenticated)
|
|
170
|
+
continue;
|
|
171
|
+
const envHint = descriptor.credentialEnvVars.length > 0 ? `Set ${descriptor.credentialEnvVars.join(" or ")}` : "Configure credentials";
|
|
172
|
+
prompts.push({
|
|
173
|
+
providerId: descriptor.providerId,
|
|
174
|
+
providerName: descriptor.name,
|
|
175
|
+
required: true,
|
|
176
|
+
envVars: descriptor.credentialEnvVars,
|
|
177
|
+
message: `${envHint} to enable ${descriptor.name} model discovery.`,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return prompts.sort((a, b) => a.providerId.localeCompare(b.providerId));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Rank the cheapest models for a normalized role/mode query.
|
|
184
|
+
*/
|
|
185
|
+
export function registryCheapestModels(state, options) {
|
|
186
|
+
const capability = options?.capability ? normalizeRoleToken(options.capability) : undefined;
|
|
187
|
+
const candidates = registryModels(state, {
|
|
188
|
+
provider: options?.provider,
|
|
189
|
+
originProvider: options?.originProvider,
|
|
190
|
+
mode: options?.mode,
|
|
191
|
+
}).filter((model) => (!capability || modelSupportsRole(model, capability)) && (!options?.role || modelSupportsRole(model, options.role)));
|
|
192
|
+
const priceMetric = options?.priceMetric ?? defaultPricingMetric(options);
|
|
193
|
+
const ranked = [];
|
|
194
|
+
const unpriced = [];
|
|
195
|
+
for (const model of candidates) {
|
|
196
|
+
const score = computeModelScore(model, priceMetric, options?.inputWeight ?? 1, options?.outputWeight ?? 1);
|
|
197
|
+
if (score === undefined) {
|
|
198
|
+
if (options?.includeUnpriced)
|
|
199
|
+
unpriced.push({ model, score: undefined, priceMetric });
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
ranked.push({ model, score, priceMetric });
|
|
203
|
+
}
|
|
204
|
+
ranked.sort((a, b) => (a.score ?? Number.POSITIVE_INFINITY) - (b.score ?? Number.POSITIVE_INFINITY) || a.model.provider.localeCompare(b.model.provider) || a.model.id.localeCompare(b.model.id));
|
|
205
|
+
unpriced.sort((a, b) => a.model.provider.localeCompare(b.model.provider) || a.model.id.localeCompare(b.model.id));
|
|
206
|
+
const scopedProviderIds = options?.provider ? [options.provider] : Array.from(state.providerMap.values()).map((provider) => provider.id);
|
|
207
|
+
return {
|
|
208
|
+
matches: [...ranked, ...unpriced].slice(0, normalizeLimit(options?.limit)),
|
|
209
|
+
candidates: candidates.length,
|
|
210
|
+
pricedCandidates: ranked.length,
|
|
211
|
+
skippedNoPricing: candidates.length - ranked.length,
|
|
212
|
+
priceMetric,
|
|
213
|
+
missingCredentials: registryMissingCredentialPrompts(state, scopedProviderIds),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Find every provider route for a normalized model identifier.
|
|
218
|
+
*/
|
|
219
|
+
export function registryModelRoutes(state, modelId) {
|
|
220
|
+
const targetNorm = normalizeModelId(modelId).toLowerCase();
|
|
221
|
+
const routes = registryModels(state).filter((model) => normalizeModelId(model.id).toLowerCase() === targetNorm);
|
|
222
|
+
return routes.sort((a, b) => a.provider.localeCompare(b.provider));
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Enrich raw routes with preferred/direct metadata for legacy consumers.
|
|
226
|
+
*/
|
|
227
|
+
export function registryModelRouteInfo(state, modelId) {
|
|
228
|
+
const info = registryModelRoutes(state, modelId).map((model) => {
|
|
229
|
+
const resolvedOrigin = model.originProvider ?? extractOriginProvider(model.id) ?? model.provider;
|
|
230
|
+
return {
|
|
231
|
+
model,
|
|
232
|
+
provider: model.provider,
|
|
233
|
+
originProvider: resolvedOrigin,
|
|
234
|
+
baseUrl: state.providerMap.get(model.provider)?.baseUrl,
|
|
235
|
+
version: extractModelVersion(model.id),
|
|
236
|
+
isDirect: model.provider === resolvedOrigin,
|
|
237
|
+
isPreferred: false,
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
if (info.length === 0)
|
|
241
|
+
return info;
|
|
242
|
+
const directRoutes = info.filter((route) => route.isDirect);
|
|
243
|
+
if (directRoutes.length > 0) {
|
|
244
|
+
// I prefer direct-origin routes first because they are usually the clearest default for operators.
|
|
245
|
+
for (const route of directRoutes)
|
|
246
|
+
route.isPreferred = true;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
const priced = info.filter((route) => route.model.pricing && Number.isFinite(route.model.pricing.inputPerMillion) && Number.isFinite(route.model.pricing.outputPerMillion));
|
|
250
|
+
(priced.length > 0 ? priced.sort((a, b) => ((a.model.pricing?.inputPerMillion ?? 0) + (a.model.pricing?.outputPerMillion ?? 0)) - ((b.model.pricing?.inputPerMillion ?? 0) + (b.model.pricing?.outputPerMillion ?? 0)) || a.provider.localeCompare(b.provider)) : info)[0].isPreferred = true;
|
|
251
|
+
}
|
|
252
|
+
return info.sort((a, b) => Number(b.isPreferred) - Number(a.isPreferred) || Number(b.isDirect) - Number(a.isDirect) || a.provider.localeCompare(b.provider));
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Aggregate capability statistics across all discovered models.
|
|
256
|
+
*/
|
|
257
|
+
export function registryCapabilities(state, filter) {
|
|
258
|
+
const capabilityMap = new Map();
|
|
259
|
+
for (const model of registryModels(state, { provider: filter?.provider })) {
|
|
260
|
+
for (const role of modelRoles(model)) {
|
|
261
|
+
const entry = capabilityMap.get(role) ?? { models: new Set(), providers: new Set(), modes: new Set(), exampleModelId: model.id };
|
|
262
|
+
entry.models.add(`${model.provider}:${model.id}`);
|
|
263
|
+
entry.providers.add(model.provider);
|
|
264
|
+
entry.modes.add(model.mode);
|
|
265
|
+
capabilityMap.set(role, entry);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return Array.from(capabilityMap.entries()).map(([capability, entry]) => ({
|
|
269
|
+
capability,
|
|
270
|
+
modelCount: entry.models.size,
|
|
271
|
+
providerCount: entry.providers.size,
|
|
272
|
+
providers: Array.from(entry.providers).sort(),
|
|
273
|
+
modes: Array.from(entry.modes).sort(),
|
|
274
|
+
exampleModelId: entry.exampleModelId,
|
|
275
|
+
})).sort((a, b) => b.modelCount - a.modelCount || a.capability.localeCompare(b.capability));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Pick the default pricing metric for a cheapest-model query.
|
|
279
|
+
*/
|
|
280
|
+
export function defaultPricingMetric(options) {
|
|
281
|
+
const effective = (options?.role ? normalizeRoleToken(options.role) : undefined) ?? (options?.capability ? normalizeRoleToken(options.capability) : undefined);
|
|
282
|
+
if (options?.mode === "embedding" || effective === "embedding")
|
|
283
|
+
return "input";
|
|
284
|
+
if (options?.mode === "audio" && (effective === "speech_to_text" || effective === "text_to_speech"))
|
|
285
|
+
return "input";
|
|
286
|
+
return "blended";
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Compute a comparable score for a model/pricing metric combination.
|
|
290
|
+
*/
|
|
291
|
+
export function computeModelScore(model, metric, inputWeight, outputWeight) {
|
|
292
|
+
if (!model.pricing)
|
|
293
|
+
return undefined;
|
|
294
|
+
if (metric === "input")
|
|
295
|
+
return Number.isFinite(model.pricing.inputPerMillion) ? model.pricing.inputPerMillion : undefined;
|
|
296
|
+
if (metric === "output")
|
|
297
|
+
return Number.isFinite(model.pricing.outputPerMillion) ? model.pricing.outputPerMillion : undefined;
|
|
298
|
+
return Number.isFinite(model.pricing.inputPerMillion) && Number.isFinite(model.pricing.outputPerMillion)
|
|
299
|
+
? model.pricing.inputPerMillion * inputWeight + model.pricing.outputPerMillion * outputWeight
|
|
300
|
+
: undefined;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Normalize a user-supplied result limit into a safe positive integer.
|
|
304
|
+
*/
|
|
305
|
+
export function normalizeLimit(limit) {
|
|
306
|
+
if (limit === undefined || !Number.isFinite(limit))
|
|
307
|
+
return 5;
|
|
308
|
+
return Math.max(1, Math.floor(limit));
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=registry-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-query.js","sourceRoot":"","sources":["../src/registry-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kosha-discovery — Discovery, enrichment, and cache helpers.
|
|
3
|
+
*
|
|
4
|
+
* I keep provider discovery and runtime plumbing here so the registry façade
|
|
5
|
+
* can stay small without losing the existing behavior.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import type { RegistryState, DiscoveryDependencies } from "./registry-state.js";
|
|
9
|
+
import type { CredentialResult, DiscoveryOptions, ProviderDiscoverer, ProviderInfo } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Run provider discovery, enrichment, caching, and delta emission.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registryDiscover(state: RegistryState, dependencies: DiscoveryDependencies, options?: DiscoveryOptions): Promise<ProviderInfo[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Force a fresh discovery pass for one provider or the full registry.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registryRefresh(state: RegistryState, discover: (options?: DiscoveryOptions) => Promise<ProviderInfo[]>, providerId?: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Dynamically load discoverers while respecting config and local filters.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadRegistryDiscoverers(state: RegistryState, providerIds?: string[], includeLocal?: boolean): Promise<ProviderDiscoverer[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Dynamically load the credential resolver when available.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getRegistryCredentialResolver(): Promise<{
|
|
26
|
+
resolve: (providerId: string, explicitKey?: string) => Promise<CredentialResult>;
|
|
27
|
+
} | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a credential from config or environment without the credential module.
|
|
30
|
+
*/
|
|
31
|
+
export declare function fallbackRegistryCredential(providerId: string, explicitKey?: string): CredentialResult;
|
|
32
|
+
/**
|
|
33
|
+
* Enrich the in-memory model set with pricing metadata when available.
|
|
34
|
+
*/
|
|
35
|
+
export declare function enrichRegistryModels(state: RegistryState): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Populate reverse aliases onto discovered models for legacy consumers.
|
|
38
|
+
*/
|
|
39
|
+
export declare function populateRegistryModelAliases(state: RegistryState): void;
|
|
40
|
+
/**
|
|
41
|
+
* Load provider data from disk cache when it is still fresh.
|
|
42
|
+
*/
|
|
43
|
+
export declare function loadRegistryFromCache(state: RegistryState, providerIds?: string[]): Promise<boolean>;
|
|
44
|
+
/**
|
|
45
|
+
* Persist the current provider map to the shared file cache.
|
|
46
|
+
*/
|
|
47
|
+
export declare function saveRegistryToCache(state: RegistryState): Promise<void>;
|
|
48
|
+
//# sourceMappingURL=registry-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-runtime.d.ts","sourceRoot":"","sources":["../src/registry-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,kBAAkB,EAClB,YAAY,EACZ,MAAM,YAAY,CAAC;AA2BpB;;GAEG;AACH,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,aAAa,EACpB,YAAY,EAAE,qBAAqB,EACnC,OAAO,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,YAAY,EAAE,CAAC,CA+CzB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACpC,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,EACjE,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC5C,KAAK,EAAE,aAAa,EACpB,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,YAAY,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA2B/B;AAED;;GAEG;AACH,wBAAsB,6BAA6B,IACnD,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;CAAE,GAAG,IAAI,CAAC,CAOnG;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACzC,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GAClB,gBAAgB,CASlB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB9E;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CASvE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAC1C,KAAK,EAAE,aAAa,EACpB,WAAW,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,OAAO,CAAC,CA0BlB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7E"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kosha-discovery — Discovery, enrichment, and cache helpers.
|
|
3
|
+
*
|
|
4
|
+
* I keep provider discovery and runtime plumbing here so the registry façade
|
|
5
|
+
* can stay small without losing the existing behavior.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { StaleCachePolicy } from "./resilience.js";
|
|
9
|
+
import { getProviderConfig, isLocalProvider, normalizeProviderId } from "./provider-catalog.js";
|
|
10
|
+
const DEFAULT_CACHE_TTL_MS = 86_400_000;
|
|
11
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
12
|
+
const CACHE_KEY_PREFIX = "provider_";
|
|
13
|
+
const FALLBACK_ENV_MAP = {
|
|
14
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
15
|
+
openai: "OPENAI_API_KEY",
|
|
16
|
+
google: "GOOGLE_API_KEY",
|
|
17
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
18
|
+
nvidia: "NVIDIA_API_KEY",
|
|
19
|
+
together: "TOGETHER_API_KEY",
|
|
20
|
+
fireworks: "FIREWORKS_API_KEY",
|
|
21
|
+
groq: "GROQ_API_KEY",
|
|
22
|
+
mistral: "MISTRAL_API_KEY",
|
|
23
|
+
deepinfra: "DEEPINFRA_API_KEY",
|
|
24
|
+
cohere: "CO_API_KEY",
|
|
25
|
+
cerebras: "CEREBRAS_API_KEY",
|
|
26
|
+
perplexity: "PERPLEXITY_API_KEY",
|
|
27
|
+
deepseek: "DEEPSEEK_API_KEY",
|
|
28
|
+
moonshot: "MOONSHOT_API_KEY",
|
|
29
|
+
glm: "GLM_API_KEY",
|
|
30
|
+
zai: "ZAI_API_KEY",
|
|
31
|
+
minimax: "MINIMAX_API_KEY",
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Run provider discovery, enrichment, caching, and delta emission.
|
|
35
|
+
*/
|
|
36
|
+
export async function registryDiscover(state, dependencies, options) {
|
|
37
|
+
const beforeSnapshot = dependencies.snapshotForDelta();
|
|
38
|
+
const providers = options?.providers?.map((providerId) => normalizeProviderId(providerId) ?? providerId);
|
|
39
|
+
const force = options?.force ?? false;
|
|
40
|
+
if (!force) {
|
|
41
|
+
const loaded = await dependencies.loadFromCache(providers);
|
|
42
|
+
if (loaded) {
|
|
43
|
+
dependencies.recordDiscoveryMutation(beforeSnapshot);
|
|
44
|
+
return Array.from(state.providerMap.values());
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const discoverers = await dependencies.loadDiscoverers(providers, options?.includeLocal);
|
|
48
|
+
const timeout = options?.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
49
|
+
const results = await Promise.allSettled(discoverers.map((discoverer) => discoverProvider(state, dependencies, discoverer, timeout)));
|
|
50
|
+
state.lastDiscoveryErrors = [];
|
|
51
|
+
for (let index = 0; index < results.length; index += 1) {
|
|
52
|
+
const result = results[index];
|
|
53
|
+
if (result.status === "fulfilled") {
|
|
54
|
+
if (result.value) {
|
|
55
|
+
state.providerMap.set(result.value.id, result.value);
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const discoverer = discoverers[index];
|
|
60
|
+
state.lastDiscoveryErrors.push({
|
|
61
|
+
providerId: discoverer.providerId,
|
|
62
|
+
providerName: discoverer.providerName,
|
|
63
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (options?.enrichWithPricing ?? true) {
|
|
68
|
+
await dependencies.enrichModels();
|
|
69
|
+
}
|
|
70
|
+
dependencies.populateModelAliases();
|
|
71
|
+
state.discoveredAt = Date.now();
|
|
72
|
+
await dependencies.saveToCache();
|
|
73
|
+
dependencies.recordDiscoveryMutation(beforeSnapshot);
|
|
74
|
+
return Array.from(state.providerMap.values());
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Force a fresh discovery pass for one provider or the full registry.
|
|
78
|
+
*/
|
|
79
|
+
export async function registryRefresh(state, discover, providerId) {
|
|
80
|
+
if (providerId) {
|
|
81
|
+
const normalizedProviderId = normalizeProviderId(providerId) ?? providerId;
|
|
82
|
+
await state.cache.invalidate(`${CACHE_KEY_PREFIX}${normalizedProviderId}`);
|
|
83
|
+
await discover({ providers: [normalizedProviderId], force: true });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await state.cache.clear();
|
|
87
|
+
await discover({ force: true });
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Dynamically load discoverers while respecting config and local filters.
|
|
91
|
+
*/
|
|
92
|
+
export async function loadRegistryDiscoverers(state, providerIds, includeLocal) {
|
|
93
|
+
try {
|
|
94
|
+
const discoveryModule = await import("./discovery/index.js");
|
|
95
|
+
let discoverers = discoveryModule.getAllDiscoverers({
|
|
96
|
+
ollamaBaseUrl: getProviderConfig(state.config, "ollama")?.baseUrl,
|
|
97
|
+
llamaCppBaseUrl: getProviderConfig(state.config, "llama.cpp")?.baseUrl,
|
|
98
|
+
});
|
|
99
|
+
if (providerIds && providerIds.length > 0) {
|
|
100
|
+
const normalizedProviderIds = providerIds.map((providerId) => normalizeProviderId(providerId) ?? providerId);
|
|
101
|
+
discoverers = discoverers.filter((discoverer) => normalizedProviderIds.includes(discoverer.providerId));
|
|
102
|
+
}
|
|
103
|
+
if (includeLocal === false) {
|
|
104
|
+
discoverers = discoverers.filter((discoverer) => !isLocalProvider(discoverer.providerId));
|
|
105
|
+
}
|
|
106
|
+
if (state.config.providers) {
|
|
107
|
+
discoverers = discoverers.filter((discoverer) => getProviderConfig(state.config, discoverer.providerId)?.enabled !== false);
|
|
108
|
+
}
|
|
109
|
+
return discoverers;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Dynamically load the credential resolver when available.
|
|
117
|
+
*/
|
|
118
|
+
export async function getRegistryCredentialResolver() {
|
|
119
|
+
try {
|
|
120
|
+
const { CredentialResolver } = await import("./credentials/index.js");
|
|
121
|
+
return new CredentialResolver();
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Resolve a credential from config or environment without the credential module.
|
|
129
|
+
*/
|
|
130
|
+
export function fallbackRegistryCredential(providerId, explicitKey) {
|
|
131
|
+
const normalizedProviderId = normalizeProviderId(providerId) ?? providerId;
|
|
132
|
+
if (explicitKey) {
|
|
133
|
+
return { apiKey: explicitKey, source: "config" };
|
|
134
|
+
}
|
|
135
|
+
const envVar = FALLBACK_ENV_MAP[normalizedProviderId];
|
|
136
|
+
const value = envVar ? process.env[envVar] : undefined;
|
|
137
|
+
return value ? { apiKey: value, source: "env" } : { source: "none" };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Enrich the in-memory model set with pricing metadata when available.
|
|
141
|
+
*/
|
|
142
|
+
export async function enrichRegistryModels(state) {
|
|
143
|
+
try {
|
|
144
|
+
const { LiteLLMEnricher } = await import("./enrichment/index.js");
|
|
145
|
+
const enricher = new LiteLLMEnricher();
|
|
146
|
+
for (const [providerId, providerInfo] of state.providerMap) {
|
|
147
|
+
try {
|
|
148
|
+
const enriched = await enricher.enrich(providerInfo.models);
|
|
149
|
+
state.providerMap.set(providerId, { ...providerInfo, models: enriched });
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// I keep enrichment failures non-fatal so base discovery remains useful.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// I silently skip enrichment when the optional module is not present.
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Populate reverse aliases onto discovered models for legacy consumers.
|
|
162
|
+
*/
|
|
163
|
+
export function populateRegistryModelAliases(state) {
|
|
164
|
+
for (const providerInfo of state.providerMap.values()) {
|
|
165
|
+
for (const model of providerInfo.models) {
|
|
166
|
+
const reverseAliases = state.aliasResolver.reverseAliases(model.id);
|
|
167
|
+
if (reverseAliases.length > 0) {
|
|
168
|
+
model.aliases = reverseAliases;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Load provider data from disk cache when it is still fresh.
|
|
175
|
+
*/
|
|
176
|
+
export async function loadRegistryFromCache(state, providerIds) {
|
|
177
|
+
const ttl = state.config.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
178
|
+
if (!providerIds || providerIds.length === 0) {
|
|
179
|
+
const allEntry = await state.cache.get("providers_all");
|
|
180
|
+
if (!allEntry || state.cache.isExpired(allEntry.timestamp, ttl)) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
for (const provider of allEntry.data) {
|
|
184
|
+
state.providerMap.set(provider.id, provider);
|
|
185
|
+
}
|
|
186
|
+
state.discoveredAt = allEntry.timestamp;
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
for (const providerId of providerIds) {
|
|
190
|
+
const entry = await state.cache.get(`${CACHE_KEY_PREFIX}${providerId}`);
|
|
191
|
+
if (!entry || state.cache.isExpired(entry.timestamp, ttl)) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
state.providerMap.set(providerId, entry.data);
|
|
195
|
+
}
|
|
196
|
+
state.discoveredAt = Date.now();
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Persist the current provider map to the shared file cache.
|
|
201
|
+
*/
|
|
202
|
+
export async function saveRegistryToCache(state) {
|
|
203
|
+
try {
|
|
204
|
+
const providers = Array.from(state.providerMap.values());
|
|
205
|
+
const saves = providers.map((provider) => state.cache.set(`${CACHE_KEY_PREFIX}${provider.id}`, provider));
|
|
206
|
+
saves.push(state.cache.set("providers_all", providers));
|
|
207
|
+
await Promise.all(saves);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// I intentionally ignore cache write failures so discovery still succeeds.
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async function discoverProvider(state, dependencies, discoverer, timeout) {
|
|
214
|
+
const breaker = state.healthTracker.breaker(discoverer.providerId);
|
|
215
|
+
const startedAt = Date.now();
|
|
216
|
+
if (!breaker.canExecute()) {
|
|
217
|
+
const stale = await StaleCachePolicy.getWithStale(state.cache, `${CACHE_KEY_PREFIX}${discoverer.providerId}`);
|
|
218
|
+
return stale?.data ?? null;
|
|
219
|
+
}
|
|
220
|
+
const explicitKey = getProviderConfig(state.config, discoverer.providerId)?.apiKey;
|
|
221
|
+
const credential = dependencies.resolveCredential
|
|
222
|
+
? await dependencies.resolveCredential(discoverer.providerId, explicitKey)
|
|
223
|
+
: dependencies.fallbackCredential(discoverer.providerId, explicitKey);
|
|
224
|
+
try {
|
|
225
|
+
const models = await discoverer.discover(credential, { timeout });
|
|
226
|
+
breaker.onSuccess();
|
|
227
|
+
dependencies.recordObservation(discoverer.providerId, {
|
|
228
|
+
latencyMs: Date.now() - startedAt,
|
|
229
|
+
errorType: null,
|
|
230
|
+
});
|
|
231
|
+
return {
|
|
232
|
+
id: discoverer.providerId,
|
|
233
|
+
name: discoverer.providerName,
|
|
234
|
+
baseUrl: discoverer.baseUrl,
|
|
235
|
+
authenticated: credential.source !== "none",
|
|
236
|
+
credentialSource: credential.source,
|
|
237
|
+
models,
|
|
238
|
+
lastRefreshed: Date.now(),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
243
|
+
breaker.onFailure(errorMessage);
|
|
244
|
+
dependencies.recordObservation(discoverer.providerId, {
|
|
245
|
+
latencyMs: Date.now() - startedAt,
|
|
246
|
+
errorType: dependencies.classifyError(errorMessage),
|
|
247
|
+
});
|
|
248
|
+
const stale = await StaleCachePolicy.getWithStale(state.cache, `${CACHE_KEY_PREFIX}${discoverer.providerId}`);
|
|
249
|
+
if (stale) {
|
|
250
|
+
return stale.data;
|
|
251
|
+
}
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=registry-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-runtime.js","sourceRoot":"","sources":["../src/registry-runtime.ts"],"names":[],"mappings":"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"}
|