@oh-my-pi/pi-catalog 16.2.8 → 16.2.11
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/CHANGELOG.md +33 -0
- package/dist/types/discovery/openai-compatible.d.ts +3 -1
- package/dist/types/identity/classify.d.ts +7 -0
- package/dist/types/identity/family.d.ts +8 -7
- package/dist/types/provider-models/descriptors.d.ts +4 -0
- package/dist/types/provider-models/openai-compat.d.ts +3 -2
- package/package.json +3 -3
- package/src/compat/openai.ts +20 -11
- package/src/discovery/openai-compatible.ts +51 -18
- package/src/identity/classify.ts +14 -0
- package/src/identity/family.ts +12 -14
- package/src/model-thinking.ts +10 -15
- package/src/models.json +564 -737
- package/src/provider-models/descriptors.ts +2 -0
- package/src/provider-models/openai-compat.ts +80 -35
- package/src/variant-collapse.ts +2 -2
|
@@ -80,7 +80,9 @@ export const CATALOG_PROVIDERS = [
|
|
|
80
80
|
{
|
|
81
81
|
id: "anthropic",
|
|
82
82
|
defaultModel: "claude-opus-4-8",
|
|
83
|
+
envVars: ["ANTHROPIC_API_KEY"],
|
|
83
84
|
createModelManagerOptions: (config: ModelManagerConfig) => anthropicModelManagerOptions(config),
|
|
85
|
+
catalogDiscovery: { label: "Anthropic" },
|
|
84
86
|
},
|
|
85
87
|
{
|
|
86
88
|
id: "azure",
|
|
@@ -20,6 +20,25 @@ import {
|
|
|
20
20
|
import { createBundledReferenceMap, createReferenceResolver, toModelSpec } from "./bundled-references";
|
|
21
21
|
|
|
22
22
|
const MODELS_DEV_URL = "https://models.dev/api.json";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Uses a cancellable timer rather than the native abort-timeout helper so
|
|
26
|
+
* successful fast discovery requests do not leave armed timeout signals for
|
|
27
|
+
* concurrent GC to trip over later.
|
|
28
|
+
*/
|
|
29
|
+
async function withCatalogDiscoveryTimeout<T>(timeoutMs: number, run: (signal: AbortSignal) => Promise<T>): Promise<T> {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timer = setTimeout(
|
|
32
|
+
() => controller.abort(new DOMException("The operation timed out.", "TimeoutError")),
|
|
33
|
+
timeoutMs,
|
|
34
|
+
);
|
|
35
|
+
try {
|
|
36
|
+
return await run(controller.signal);
|
|
37
|
+
} finally {
|
|
38
|
+
clearTimeout(timer);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
23
42
|
const ANTHROPIC_BASE_URL = "https://api.anthropic.com/v1";
|
|
24
43
|
const ANTHROPIC_OAUTH_BETA =
|
|
25
44
|
"claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,redact-thinking-2026-02-12,context-management-2025-06-27,prompt-caching-scope-2026-01-05,mid-conversation-system-2026-04-07,advanced-tool-use-2025-11-20,effort-2025-11-24,extended-cache-ttl-2025-04-11";
|
|
@@ -156,11 +175,23 @@ function buildAnthropicReferenceMap(
|
|
|
156
175
|
* first-party `/v1/models` endpoint but that models.dev has not catalogued yet.
|
|
157
176
|
* Seeded into model generation so the bundled catalog is never gated on
|
|
158
177
|
* models.dev's update cadence; deduped behind upstream catalog / models.dev
|
|
159
|
-
* entries once those appear. Token limits and pricing are pinned
|
|
160
|
-
*
|
|
178
|
+
* entries once those appear. Token limits and pricing are pinned either directly or
|
|
179
|
+
* in `applyAnthropicCatalogPolicy`, and `thinking` is re-baked
|
|
161
180
|
* by the generator's policy pass (scripts/generated-policies.ts).
|
|
162
181
|
*/
|
|
163
182
|
export const ANTHROPIC_CURATED_FALLBACK_MODELS: readonly ModelSpec<"anthropic-messages">[] = [
|
|
183
|
+
{
|
|
184
|
+
id: "claude-sonnet-5",
|
|
185
|
+
name: "Claude Sonnet 5",
|
|
186
|
+
api: "anthropic-messages",
|
|
187
|
+
provider: "anthropic",
|
|
188
|
+
baseUrl: "https://api.anthropic.com",
|
|
189
|
+
reasoning: true,
|
|
190
|
+
input: ["text", "image"],
|
|
191
|
+
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
192
|
+
contextWindow: 1_000_000,
|
|
193
|
+
maxTokens: 128_000,
|
|
194
|
+
},
|
|
164
195
|
{
|
|
165
196
|
id: "claude-fable-5",
|
|
166
197
|
name: "Claude Fable 5",
|
|
@@ -2339,34 +2370,40 @@ export async function fetchLmStudioNativeModelMetadata(
|
|
|
2339
2370
|
options?: LmStudioNativeModelMetadataOptions,
|
|
2340
2371
|
): Promise<Map<string, LmStudioNativeModelMetadata> | null> {
|
|
2341
2372
|
const nativeBaseUrl = toLmStudioNativeBaseUrl(baseUrl);
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
if (!response.ok) {
|
|
2349
|
-
return null;
|
|
2350
|
-
}
|
|
2351
|
-
const payload = await response.json();
|
|
2352
|
-
if (!isRecord(payload) || !Array.isArray(payload.data)) {
|
|
2353
|
-
return null;
|
|
2354
|
-
}
|
|
2355
|
-
const metadata = new Map<string, LmStudioNativeModelMetadata>();
|
|
2356
|
-
for (const entry of payload.data) {
|
|
2357
|
-
if (!isRecord(entry) || typeof entry.id !== "string" || entry.id.length === 0) {
|
|
2358
|
-
continue;
|
|
2359
|
-
}
|
|
2360
|
-
const contextWindow = getLmStudioNativeContextWindow(entry);
|
|
2361
|
-
metadata.set(entry.id, {
|
|
2362
|
-
input: getLmStudioNativeInput(entry),
|
|
2363
|
-
...(contextWindow === undefined ? {} : { contextWindow }),
|
|
2373
|
+
const fetchMetadata = async (signal?: AbortSignal): Promise<Map<string, LmStudioNativeModelMetadata> | null> => {
|
|
2374
|
+
try {
|
|
2375
|
+
const response = await fetchImpl(`${nativeBaseUrl}/api/v0/models`, {
|
|
2376
|
+
method: "GET",
|
|
2377
|
+
headers: { Accept: "application/json", ...(options?.headers ?? {}) },
|
|
2378
|
+
signal,
|
|
2364
2379
|
});
|
|
2380
|
+
if (!response.ok) {
|
|
2381
|
+
return null;
|
|
2382
|
+
}
|
|
2383
|
+
const payload = await response.json();
|
|
2384
|
+
if (!isRecord(payload) || !Array.isArray(payload.data)) {
|
|
2385
|
+
return null;
|
|
2386
|
+
}
|
|
2387
|
+
const metadata = new Map<string, LmStudioNativeModelMetadata>();
|
|
2388
|
+
for (const entry of payload.data) {
|
|
2389
|
+
if (!isRecord(entry) || typeof entry.id !== "string" || entry.id.length === 0) {
|
|
2390
|
+
continue;
|
|
2391
|
+
}
|
|
2392
|
+
const contextWindow = getLmStudioNativeContextWindow(entry);
|
|
2393
|
+
metadata.set(entry.id, {
|
|
2394
|
+
input: getLmStudioNativeInput(entry),
|
|
2395
|
+
...(contextWindow === undefined ? {} : { contextWindow }),
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
return metadata;
|
|
2399
|
+
} catch {
|
|
2400
|
+
return null;
|
|
2365
2401
|
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
return
|
|
2402
|
+
};
|
|
2403
|
+
if (options?.signal !== undefined) {
|
|
2404
|
+
return fetchMetadata(options.signal);
|
|
2369
2405
|
}
|
|
2406
|
+
return withCatalogDiscoveryTimeout(LM_STUDIO_NATIVE_METADATA_TIMEOUT_MS, fetchMetadata);
|
|
2370
2407
|
}
|
|
2371
2408
|
|
|
2372
2409
|
export interface LmStudioModelManagerConfig {
|
|
@@ -2857,6 +2894,7 @@ export interface FetchLiteLLMRichModelsOptions<TApi extends Api> {
|
|
|
2857
2894
|
headers?: Record<string, string>;
|
|
2858
2895
|
fetch?: FetchImpl;
|
|
2859
2896
|
signal?: AbortSignal;
|
|
2897
|
+
timeoutMs?: number;
|
|
2860
2898
|
referenceResolver?: (modelId: string) => ModelSpec<TApi> | undefined;
|
|
2861
2899
|
}
|
|
2862
2900
|
|
|
@@ -3012,6 +3050,7 @@ async function fetchLiteLLMRichEndpoint<TApi extends Api>(
|
|
|
3012
3050
|
options: FetchLiteLLMRichModelsOptions<TApi>,
|
|
3013
3051
|
managementBaseUrl: string,
|
|
3014
3052
|
runtimeBaseUrl: string,
|
|
3053
|
+
signal?: AbortSignal,
|
|
3015
3054
|
): Promise<ModelSpec<TApi>[] | null> {
|
|
3016
3055
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3017
3056
|
const requestHeaders: Record<string, string> = {
|
|
@@ -3026,7 +3065,7 @@ async function fetchLiteLLMRichEndpoint<TApi extends Api>(
|
|
|
3026
3065
|
response = await fetchImpl(`${managementBaseUrl}${endpoint}`, {
|
|
3027
3066
|
method: "GET",
|
|
3028
3067
|
headers: requestHeaders,
|
|
3029
|
-
signal
|
|
3068
|
+
signal,
|
|
3030
3069
|
});
|
|
3031
3070
|
} catch {
|
|
3032
3071
|
return null;
|
|
@@ -3065,13 +3104,19 @@ export async function fetchLiteLLMRichModels<TApi extends Api>(
|
|
|
3065
3104
|
if (!managementBaseUrl || !runtimeBaseUrl) {
|
|
3066
3105
|
return null;
|
|
3067
3106
|
}
|
|
3068
|
-
|
|
3069
|
-
const
|
|
3070
|
-
|
|
3071
|
-
|
|
3107
|
+
const fetchModels = async (signal?: AbortSignal): Promise<ModelSpec<TApi>[] | null> => {
|
|
3108
|
+
for (const endpoint of LITELLM_RICH_ENDPOINTS) {
|
|
3109
|
+
const models = await fetchLiteLLMRichEndpoint(endpoint, options, managementBaseUrl, runtimeBaseUrl, signal);
|
|
3110
|
+
if (models) {
|
|
3111
|
+
return models;
|
|
3112
|
+
}
|
|
3072
3113
|
}
|
|
3114
|
+
return null;
|
|
3115
|
+
};
|
|
3116
|
+
if (options.signal !== undefined) {
|
|
3117
|
+
return fetchModels(options.signal);
|
|
3073
3118
|
}
|
|
3074
|
-
return
|
|
3119
|
+
return options.timeoutMs !== undefined ? withCatalogDiscoveryTimeout(options.timeoutMs, fetchModels) : fetchModels();
|
|
3075
3120
|
}
|
|
3076
3121
|
|
|
3077
3122
|
export function litellmModelManagerOptions(
|
|
@@ -3096,7 +3141,7 @@ export function litellmModelManagerOptions(
|
|
|
3096
3141
|
apiKey,
|
|
3097
3142
|
fetch: config?.fetch,
|
|
3098
3143
|
referenceResolver: resolveReference,
|
|
3099
|
-
|
|
3144
|
+
timeoutMs: 10_000,
|
|
3100
3145
|
});
|
|
3101
3146
|
if (richModels && richModels.length > 0) {
|
|
3102
3147
|
return richModels;
|
|
@@ -3146,7 +3191,7 @@ export function vllmModelManagerOptions(config?: VllmModelManagerConfig): ModelM
|
|
|
3146
3191
|
};
|
|
3147
3192
|
},
|
|
3148
3193
|
fetch: config?.fetch,
|
|
3149
|
-
|
|
3194
|
+
timeoutMs: VLLM_DISCOVERY_TIMEOUT_MS,
|
|
3150
3195
|
}),
|
|
3151
3196
|
};
|
|
3152
3197
|
}
|
package/src/variant-collapse.ts
CHANGED
|
@@ -953,8 +953,8 @@ export function collapseBuiltModelVariants<TApi extends Api>(models: readonly Mo
|
|
|
953
953
|
const collapsed = collapseEffortVariantsAcrossProviders(models);
|
|
954
954
|
const inputRefs = new Set<Model<TApi>>(models);
|
|
955
955
|
return collapsed.map(model =>
|
|
956
|
-
//
|
|
957
|
-
inputRefs.has(model) ? model : buildModel(model as unknown as ModelSpec<TApi>),
|
|
956
|
+
// Rebuild from a projected spec (sparse compatConfig) instead of resolved compat.
|
|
957
|
+
inputRefs.has(model) ? model : buildModel({ ...model, compat: model.compatConfig } as unknown as ModelSpec<TApi>),
|
|
958
958
|
);
|
|
959
959
|
}
|
|
960
960
|
|