@sriinnu/kosha-discovery 0.6.1 → 1.1.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/README.md +95 -263
- package/dist/cli-cmd-model.d.ts +48 -0
- package/dist/cli-cmd-model.d.ts.map +1 -0
- package/dist/cli-cmd-model.js +231 -0
- package/dist/cli-cmd-model.js.map +1 -0
- package/dist/cli-cmd-query.d.ts +40 -0
- package/dist/cli-cmd-query.d.ts.map +1 -0
- package/dist/cli-cmd-query.js +303 -0
- package/dist/cli-cmd-query.js.map +1 -0
- package/dist/cli-commands.d.ts +65 -75
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +93 -543
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli-format.d.ts +32 -0
- package/dist/cli-format.d.ts.map +1 -1
- package/dist/cli-format.js +51 -0
- package/dist/cli-format.js.map +1 -1
- package/dist/cli-help.d.ts +19 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +150 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/discovery/anthropic.d.ts +8 -1
- package/dist/discovery/anthropic.d.ts.map +1 -1
- package/dist/discovery/anthropic.js +26 -3
- package/dist/discovery/anthropic.js.map +1 -1
- package/dist/discovery/base.d.ts +26 -0
- package/dist/discovery/base.d.ts.map +1 -1
- package/dist/discovery/base.js +55 -2
- package/dist/discovery/base.js.map +1 -1
- package/dist/discovery/free-tier.d.ts +31 -0
- package/dist/discovery/free-tier.d.ts.map +1 -0
- package/dist/discovery/free-tier.js +47 -0
- package/dist/discovery/free-tier.js.map +1 -0
- package/dist/discovery/google.d.ts +8 -1
- package/dist/discovery/google.d.ts.map +1 -1
- package/dist/discovery/google.js +25 -3
- package/dist/discovery/google.js.map +1 -1
- package/dist/discovery/index.d.ts +3 -6
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/index.js +36 -55
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/litellm-seed.d.ts +32 -0
- package/dist/discovery/litellm-seed.d.ts.map +1 -0
- package/dist/discovery/litellm-seed.js +252 -0
- package/dist/discovery/litellm-seed.js.map +1 -0
- package/dist/discovery/modelsdev-catalog.d.ts +95 -0
- package/dist/discovery/modelsdev-catalog.d.ts.map +1 -0
- package/dist/discovery/modelsdev-catalog.js +131 -0
- package/dist/discovery/modelsdev-catalog.js.map +1 -0
- package/dist/discovery/modelsdev-seed.d.ts +19 -0
- package/dist/discovery/modelsdev-seed.d.ts.map +1 -0
- package/dist/discovery/modelsdev-seed.js +203 -0
- package/dist/discovery/modelsdev-seed.js.map +1 -0
- package/dist/discovery/openai-compatible.d.ts.map +1 -1
- package/dist/discovery/openai-compatible.js +12 -1
- package/dist/discovery/openai-compatible.js.map +1 -1
- package/dist/discovery/openai.d.ts +9 -1
- package/dist/discovery/openai.d.ts.map +1 -1
- package/dist/discovery/openai.js +31 -8
- package/dist/discovery/openai.js.map +1 -1
- package/dist/discovery/promo-overrides.d.ts +54 -0
- package/dist/discovery/promo-overrides.d.ts.map +1 -0
- package/dist/discovery/promo-overrides.js +74 -0
- package/dist/discovery/promo-overrides.js.map +1 -0
- package/dist/discovery/public-seed.d.ts +30 -0
- package/dist/discovery/public-seed.d.ts.map +1 -0
- package/dist/discovery/public-seed.js +51 -0
- package/dist/discovery/public-seed.js.map +1 -0
- package/dist/discovery-contract.d.ts +14 -2
- package/dist/discovery-contract.d.ts.map +1 -1
- package/dist/discovery-contract.js +28 -0
- package/dist/discovery-contract.js.map +1 -1
- package/dist/enrichment/litellm-catalog.d.ts +81 -0
- package/dist/enrichment/litellm-catalog.d.ts.map +1 -0
- package/dist/enrichment/litellm-catalog.js +129 -0
- package/dist/enrichment/litellm-catalog.js.map +1 -0
- package/dist/enrichment/litellm.d.ts +9 -2
- package/dist/enrichment/litellm.d.ts.map +1 -1
- package/dist/enrichment/litellm.js +168 -20
- package/dist/enrichment/litellm.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +18 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +293 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/model-features.d.ts +77 -0
- package/dist/model-features.d.ts.map +1 -0
- package/dist/model-features.js +245 -0
- package/dist/model-features.js.map +1 -0
- package/dist/provider-catalog.d.ts +9 -0
- package/dist/provider-catalog.d.ts.map +1 -1
- package/dist/provider-catalog.js +22 -0
- package/dist/provider-catalog.js.map +1 -1
- package/dist/proxy.d.ts +31 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +193 -0
- package/dist/proxy.js.map +1 -0
- package/dist/registry-discovery.d.ts.map +1 -1
- package/dist/registry-discovery.js +12 -2
- package/dist/registry-discovery.js.map +1 -1
- package/dist/registry-runtime.d.ts +40 -1
- package/dist/registry-runtime.d.ts.map +1 -1
- package/dist/registry-runtime.js +502 -30
- package/dist/registry-runtime.js.map +1 -1
- package/dist/registry-selection.js +2 -0
- package/dist/registry-selection.js.map +1 -1
- package/dist/registry.d.ts +9 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +11 -1
- package/dist/registry.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +6 -0
- package/dist/server.js.map +1 -1
- package/dist/tokenizer-family.d.ts +39 -0
- package/dist/tokenizer-family.d.ts.map +1 -0
- package/dist/tokenizer-family.js +92 -0
- package/dist/tokenizer-family.js.map +1 -0
- package/dist/types.d.ts +186 -0
- package/dist/types.d.ts.map +1 -1
- package/logo.png +0 -0
- package/package.json +15 -3
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* heuristics here so the registry can stay focused on orchestration.
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
|
-
import type { ModelCard, ModelPricing } from "./types.js";
|
|
8
|
+
import type { ModelCard, ModelPricing, StructuredOutputMode, ToolDialect } from "./types.js";
|
|
9
9
|
import type { ProviderDescriptor } from "./provider-catalog.js";
|
|
10
10
|
/** Stable schema version exposed to Chitragupta and other daemon consumers. */
|
|
11
11
|
export declare const DISCOVERY_SCHEMA_VERSION = 1;
|
|
12
12
|
/** Trusted capability taxonomy surfaced by the v1 discovery contract. */
|
|
13
|
-
export type TrustedCapability = "chat" | "function_calling" | "embeddings" | "vision" | "rerank" | "structured_output" | "streaming" | "long_context" | "local_exec" | "code_generation" | "reasoning" | "low_latency" | "cheap_inference";
|
|
13
|
+
export type TrustedCapability = "chat" | "function_calling" | "embeddings" | "vision" | "rerank" | "structured_output" | "streaming" | "long_context" | "local_exec" | "code_generation" | "reasoning" | "low_latency" | "cheap_inference" | "free_tier";
|
|
14
14
|
/** Normalized role hints exposed by the v1 schema. */
|
|
15
15
|
export interface DiscoveryRoleDefinition {
|
|
16
16
|
/** Stable role identifier. */
|
|
@@ -77,6 +77,18 @@ export interface DiscoveryModelV1 {
|
|
|
77
77
|
computeTarget: string | null;
|
|
78
78
|
supportsStructuredOutput: boolean | null;
|
|
79
79
|
supportsStreaming: boolean | null;
|
|
80
|
+
/** Tool-calling dialect family (e.g. `"anthropic-tools"`). */
|
|
81
|
+
toolDialect: ToolDialect | null;
|
|
82
|
+
/** Structured-output production modes surfaced for bindings. */
|
|
83
|
+
structuredOutputModes: StructuredOutputMode[];
|
|
84
|
+
/** Whether the model supports multiple tool calls per turn. */
|
|
85
|
+
supportsParallelToolCalls: boolean | null;
|
|
86
|
+
/** Lifecycle status used by routing and deprecation warnings. */
|
|
87
|
+
status: "active" | "preview" | "deprecated" | "retired" | null;
|
|
88
|
+
/** ISO-8601 deprecation/sunset date when announced by the provider. */
|
|
89
|
+
deprecationDate: string | null;
|
|
90
|
+
/** Canonical successor model ID when the provider has published one. */
|
|
91
|
+
replacedBy: string | null;
|
|
80
92
|
}
|
|
81
93
|
/** Normalized provider health exposed by the v1 discovery snapshot. */
|
|
82
94
|
export interface DiscoveryHealthRecord {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery-contract.d.ts","sourceRoot":"","sources":["../src/discovery-contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery-contract.d.ts","sourceRoot":"","sources":["../src/discovery-contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,yEAAyE;AACzE,MAAM,MAAM,iBAAiB,GAC1B,MAAM,GACN,kBAAkB,GAClB,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,mBAAmB,GACnB,WAAW,GACX,cAAc,GACd,YAAY,GACZ,iBAAiB,GACjB,WAAW,GACX,aAAa,GACb,iBAAiB,GACjB,WAAW,CAAC;AAEf,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACvC,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,oBAAoB,EAAE,iBAAiB,EAAE,CAAC;IAC1C,mEAAmE;IACnE,qBAAqB,EAAE,iBAAiB,EAAE,CAAC;IAC3C,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;CACxB;AAED,wDAAwD;AACxD,MAAM,WAAW,yBAAyB;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,kEAAkE;AAClE,MAAM,WAAW,mBAAmB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,wBAAwB,EAAE,OAAO,GAAG,IAAI,CAAC;IACzC,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,8DAA8D;IAC9D,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,gEAAgE;IAChE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;IAC9C,+DAA+D;IAC/D,yBAAyB,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1C,iEAAiE;IACjE,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/D,uEAAuE;IACvE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,IAAI,GAAG,WAAW,GAAG,SAAS,CAAC;IAC/C,YAAY,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;CAC9C;AAED,kCAAkC;AAClC,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,iBAAiB,EAAE,yBAAyB,EAAE,CAAC;CAC/C;AAED,sDAAsD;AACtD,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,mBAAmB,CAAC;AAE1F,mDAAmD;AACnD,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,yBAAyB,GAAG,IAAI,CAAC;CACzG;AAED,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,4EAA4E;AAC5E,MAAM,WAAW,4BAA4B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED,0DAA0D;AAC1D,MAAM,WAAW,yBAAyB;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,4BAA4B,EAAE,CAAC;CACxC;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,uEAAuE;AACvE,MAAM,WAAW,uBAAuB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IACxD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAED,0DAA0D;AAC1D,eAAO,MAAM,0BAA0B,EAAE,SAAS,uBAAuB,EAqC/D,CAAC;AAMX;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC,EAAE,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAE9G;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,GAAG,iBAAiB,EAAE,CA4BjH;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,uBAAuB,EAAE,CAE1D"}
|
|
@@ -99,6 +99,12 @@ export function trustedCapabilitiesForModel(model, descriptor) {
|
|
|
99
99
|
caps.add("low_latency");
|
|
100
100
|
if (descriptor.isLocal || isCheapPricing(model.pricing))
|
|
101
101
|
caps.add("cheap_inference");
|
|
102
|
+
// Free tier is a strict subset of cheap — set both so consumers filtering on
|
|
103
|
+
// either get a coherent answer. Distinct from "cheap" because $0 is a real
|
|
104
|
+
// signal (free dev tiers, promo windows) that downstream cost classifiers
|
|
105
|
+
// should be able to single out.
|
|
106
|
+
if (rawCaps.includes("free_tier") || isFreeTierPricing(model))
|
|
107
|
+
caps.add("free_tier");
|
|
102
108
|
return [...caps].sort();
|
|
103
109
|
}
|
|
104
110
|
/**
|
|
@@ -112,4 +118,26 @@ function isCheapPricing(pricing) {
|
|
|
112
118
|
return false;
|
|
113
119
|
return pricing.inputPerMillion <= 1 && pricing.outputPerMillion <= 4;
|
|
114
120
|
}
|
|
121
|
+
function isFreeTierPricing(model) {
|
|
122
|
+
const pricing = model.pricing;
|
|
123
|
+
if (!pricing)
|
|
124
|
+
return false;
|
|
125
|
+
// `free_tier` is a token-billed concept (NVIDIA dev tier, Gemma/open-weight free,
|
|
126
|
+
// OpenAI moderation). Multimodal-only models — TTS billed per second, image gen
|
|
127
|
+
// billed per image, character-billed Vertex models — legitimately publish 0/0
|
|
128
|
+
// base token pricing because they are not token-billed; flagging them as
|
|
129
|
+
// free_tier would be misleading.
|
|
130
|
+
if (model.mode !== "chat" && model.mode !== "embedding")
|
|
131
|
+
return false;
|
|
132
|
+
if (pricing.imageOutputPerImage !== undefined ||
|
|
133
|
+
pricing.imageInputPerImage !== undefined ||
|
|
134
|
+
pricing.audioInputPerSecond !== undefined ||
|
|
135
|
+
pricing.audioOutputPerSecond !== undefined ||
|
|
136
|
+
pricing.videoInputPerSecond !== undefined ||
|
|
137
|
+
pricing.inputPerMillionCharacters !== undefined ||
|
|
138
|
+
pricing.outputPerMillionCharacters !== undefined) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return pricing.inputPerMillion === 0 && pricing.outputPerMillion === 0;
|
|
142
|
+
}
|
|
115
143
|
//# sourceMappingURL=discovery-contract.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery-contract.js","sourceRoot":"","sources":["../src/discovery-contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery-contract.js","sourceRoot":"","sources":["../src/discovery-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kosha-discovery — Shared LiteLLM catalog loader.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the community-maintained LiteLLM model catalog
|
|
5
|
+
* used by both the discovery seed (origin providers without an API key) and
|
|
6
|
+
* the post-discovery pricing enricher.
|
|
7
|
+
*
|
|
8
|
+
* Hardening:
|
|
9
|
+
* - HTTPS-only, fixed source URL — no caller-supplied URLs.
|
|
10
|
+
* - Promise-deduplicated singleton load — concurrent callers share one fetch.
|
|
11
|
+
* - AbortController-bounded fetch with explicit timeout.
|
|
12
|
+
* - Response size cap before parsing to prevent memory bombs.
|
|
13
|
+
* - {@link assertCleanPayload} runs before any field is read.
|
|
14
|
+
* - Entry-count cap after parse to bound downstream work.
|
|
15
|
+
*
|
|
16
|
+
* The catalog source is the same one already trusted by the existing
|
|
17
|
+
* enricher; this module just centralises the load.
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
/** Pinned upstream catalog URL — HTTPS only, no user override. */
|
|
21
|
+
export declare const LITELLM_CATALOG_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
22
|
+
/**
|
|
23
|
+
* Shape of a single entry in the LiteLLM pricing JSON.
|
|
24
|
+
* Fields are all optional because the upstream schema evolves over time;
|
|
25
|
+
* consumers must defensively handle missing fields.
|
|
26
|
+
*/
|
|
27
|
+
export interface LiteLLMModelEntry {
|
|
28
|
+
max_tokens?: number;
|
|
29
|
+
max_input_tokens?: number;
|
|
30
|
+
max_output_tokens?: number;
|
|
31
|
+
input_cost_per_token?: number;
|
|
32
|
+
output_cost_per_token?: number;
|
|
33
|
+
input_cost_per_reasoning_token?: number;
|
|
34
|
+
output_cost_per_reasoning_token?: number;
|
|
35
|
+
reasoning_input_cost_per_token?: number;
|
|
36
|
+
reasoning_output_cost_per_token?: number;
|
|
37
|
+
cache_read_input_token_cost?: number;
|
|
38
|
+
cache_creation_input_token_cost?: number;
|
|
39
|
+
input_cost_per_token_batches?: number;
|
|
40
|
+
output_cost_per_token_batches?: number;
|
|
41
|
+
input_cost_per_image?: number;
|
|
42
|
+
output_cost_per_image?: number;
|
|
43
|
+
input_cost_per_audio_token?: number;
|
|
44
|
+
output_cost_per_audio_token?: number;
|
|
45
|
+
input_cost_per_audio_per_second?: number;
|
|
46
|
+
output_cost_per_audio_per_second?: number;
|
|
47
|
+
input_cost_per_video_per_second?: number;
|
|
48
|
+
input_cost_per_video_token?: number;
|
|
49
|
+
input_cost_per_character?: number;
|
|
50
|
+
output_cost_per_character?: number;
|
|
51
|
+
input_cost_per_token_above_128k_tokens?: number;
|
|
52
|
+
output_cost_per_token_above_128k_tokens?: number;
|
|
53
|
+
input_cost_per_token_above_200k_tokens?: number;
|
|
54
|
+
output_cost_per_token_above_200k_tokens?: number;
|
|
55
|
+
deprecation_date?: string;
|
|
56
|
+
litellm_provider?: string;
|
|
57
|
+
mode?: string;
|
|
58
|
+
supports_function_calling?: boolean;
|
|
59
|
+
supports_parallel_function_calling?: boolean;
|
|
60
|
+
supports_tool_choice?: boolean;
|
|
61
|
+
supports_response_schema?: boolean;
|
|
62
|
+
supports_system_messages?: boolean;
|
|
63
|
+
supports_vision?: boolean;
|
|
64
|
+
supports_audio_input?: boolean;
|
|
65
|
+
supports_audio_output?: boolean;
|
|
66
|
+
supports_video_input?: boolean;
|
|
67
|
+
supports_prompt_caching?: boolean;
|
|
68
|
+
supports_reasoning?: boolean;
|
|
69
|
+
output_vector_size?: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Fetch the LiteLLM catalog with full hardening, returning a defensively
|
|
73
|
+
* filtered map. Concurrent callers share the same in-flight promise.
|
|
74
|
+
*/
|
|
75
|
+
export declare function loadLiteLLMCatalog(): Promise<Record<string, LiteLLMModelEntry>>;
|
|
76
|
+
/**
|
|
77
|
+
* Reset the cached catalog. Test-only helper — callers in production code
|
|
78
|
+
* should rely on the process-lifetime cache.
|
|
79
|
+
*/
|
|
80
|
+
export declare function resetLiteLLMCatalogCache(): void;
|
|
81
|
+
//# sourceMappingURL=litellm-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"litellm-catalog.d.ts","sourceRoot":"","sources":["../../src/enrichment/litellm-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,kEAAkE;AAClE,eAAO,MAAM,mBAAmB,gGAC8D,CAAC;AAW/F;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IAEvC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAEnC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IAChD,uCAAuC,CAAC,EAAE,MAAM,CAAC;IACjD,sCAAsC,CAAC,EAAE,MAAM,CAAC;IAChD,uCAAuC,CAAC,EAAE,MAAM,CAAC;IAEjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kCAAkC,CAAC,EAAE,OAAO,CAAC;IAC7C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAKD;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAQ/E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kosha-discovery — Shared LiteLLM catalog loader.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the community-maintained LiteLLM model catalog
|
|
5
|
+
* used by both the discovery seed (origin providers without an API key) and
|
|
6
|
+
* the post-discovery pricing enricher.
|
|
7
|
+
*
|
|
8
|
+
* Hardening:
|
|
9
|
+
* - HTTPS-only, fixed source URL — no caller-supplied URLs.
|
|
10
|
+
* - Promise-deduplicated singleton load — concurrent callers share one fetch.
|
|
11
|
+
* - AbortController-bounded fetch with explicit timeout.
|
|
12
|
+
* - Response size cap before parsing to prevent memory bombs.
|
|
13
|
+
* - {@link assertCleanPayload} runs before any field is read.
|
|
14
|
+
* - Entry-count cap after parse to bound downstream work.
|
|
15
|
+
*
|
|
16
|
+
* The catalog source is the same one already trusted by the existing
|
|
17
|
+
* enricher; this module just centralises the load.
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
import { assertCleanPayload } from "../security.js";
|
|
21
|
+
/** Pinned upstream catalog URL — HTTPS only, no user override. */
|
|
22
|
+
export const LITELLM_CATALOG_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
23
|
+
/** Maximum response payload size in bytes (8 MB) — current catalog is ~3 MB. */
|
|
24
|
+
const MAX_PAYLOAD_BYTES = 8 * 1024 * 1024;
|
|
25
|
+
/** Maximum entry count in the parsed catalog before we refuse it. */
|
|
26
|
+
const MAX_ENTRIES = 25_000;
|
|
27
|
+
/** Network timeout for the catalog fetch. */
|
|
28
|
+
const FETCH_TIMEOUT_MS = 15_000;
|
|
29
|
+
/** Module-level promise-dedup cache so concurrent callers share one fetch. */
|
|
30
|
+
let inflight = null;
|
|
31
|
+
/**
|
|
32
|
+
* Fetch the LiteLLM catalog with full hardening, returning a defensively
|
|
33
|
+
* filtered map. Concurrent callers share the same in-flight promise.
|
|
34
|
+
*/
|
|
35
|
+
export function loadLiteLLMCatalog() {
|
|
36
|
+
if (inflight)
|
|
37
|
+
return inflight;
|
|
38
|
+
inflight = fetchAndValidate().catch((error) => {
|
|
39
|
+
// Reset on failure so a future call can retry instead of memoising the error.
|
|
40
|
+
inflight = null;
|
|
41
|
+
throw error;
|
|
42
|
+
});
|
|
43
|
+
return inflight;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reset the cached catalog. Test-only helper — callers in production code
|
|
47
|
+
* should rely on the process-lifetime cache.
|
|
48
|
+
*/
|
|
49
|
+
export function resetLiteLLMCatalogCache() {
|
|
50
|
+
inflight = null;
|
|
51
|
+
}
|
|
52
|
+
async function fetchAndValidate() {
|
|
53
|
+
const controller = new AbortController();
|
|
54
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
55
|
+
let response;
|
|
56
|
+
try {
|
|
57
|
+
response = await fetch(LITELLM_CATALOG_URL, { signal: controller.signal });
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
}
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
throw new Error(`Failed to fetch litellm data: ${response.status} ${response.statusText}`);
|
|
64
|
+
}
|
|
65
|
+
const text = await readBoundedText(response, MAX_PAYLOAD_BYTES);
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(text);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
throw new Error("Failed to parse litellm data: invalid JSON");
|
|
72
|
+
}
|
|
73
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
74
|
+
throw new Error("Failed to parse litellm data: expected an object");
|
|
75
|
+
}
|
|
76
|
+
assertCleanPayload(parsed, "litellm");
|
|
77
|
+
const entries = Object.entries(parsed);
|
|
78
|
+
if (entries.length > MAX_ENTRIES) {
|
|
79
|
+
throw new Error(`LiteLLM catalog exceeds entry cap (${entries.length} > ${MAX_ENTRIES}) — refusing to load`);
|
|
80
|
+
}
|
|
81
|
+
const out = Object.create(null);
|
|
82
|
+
for (const [key, value] of entries) {
|
|
83
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
84
|
+
out[key] = value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Read a Response body as text but reject if the body exceeds maxBytes.
|
|
91
|
+
* Streams the body chunk-by-chunk so we never buffer more than the cap.
|
|
92
|
+
*/
|
|
93
|
+
async function readBoundedText(response, maxBytes) {
|
|
94
|
+
const contentLength = Number(response.headers.get("content-length") ?? "0");
|
|
95
|
+
if (contentLength > maxBytes) {
|
|
96
|
+
throw new Error(`LiteLLM catalog too large (${contentLength} > ${maxBytes} bytes) — refusing to load`);
|
|
97
|
+
}
|
|
98
|
+
if (!response.body) {
|
|
99
|
+
// No streaming body available — fall back to text() but enforce cap on result.
|
|
100
|
+
const text = await response.text();
|
|
101
|
+
if (text.length > maxBytes) {
|
|
102
|
+
throw new Error(`LiteLLM catalog too large (${text.length} > ${maxBytes} chars) — refusing to load`);
|
|
103
|
+
}
|
|
104
|
+
return text;
|
|
105
|
+
}
|
|
106
|
+
const reader = response.body.getReader();
|
|
107
|
+
const decoder = new TextDecoder("utf-8");
|
|
108
|
+
let received = 0;
|
|
109
|
+
let text = "";
|
|
110
|
+
while (true) {
|
|
111
|
+
const { done, value } = await reader.read();
|
|
112
|
+
if (done)
|
|
113
|
+
break;
|
|
114
|
+
received += value.byteLength;
|
|
115
|
+
if (received > maxBytes) {
|
|
116
|
+
try {
|
|
117
|
+
await reader.cancel();
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
/* swallow cancel errors; we are already failing */
|
|
121
|
+
}
|
|
122
|
+
throw new Error(`LiteLLM catalog too large (>${maxBytes} bytes) — refusing to load`);
|
|
123
|
+
}
|
|
124
|
+
text += decoder.decode(value, { stream: true });
|
|
125
|
+
}
|
|
126
|
+
text += decoder.decode();
|
|
127
|
+
return text;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=litellm-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"litellm-catalog.js","sourceRoot":"","sources":["../../src/enrichment/litellm-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,8 +15,7 @@ import type { Enricher, ModelCard } from "../types.js";
|
|
|
15
15
|
*/
|
|
16
16
|
export declare class LiteLLMEnricher implements Enricher {
|
|
17
17
|
private data;
|
|
18
|
-
|
|
19
|
-
/** Fetch and cache the litellm pricing JSON. Safe to call multiple times. */
|
|
18
|
+
/** Fetch and cache the litellm pricing JSON via the shared catalog loader. */
|
|
20
19
|
load(): Promise<void>;
|
|
21
20
|
/**
|
|
22
21
|
* Enrich an array of ModelCards with litellm data.
|
|
@@ -27,6 +26,14 @@ export declare class LiteLLMEnricher implements Enricher {
|
|
|
27
26
|
*/
|
|
28
27
|
enrich(models: ModelCard[]): Promise<ModelCard[]>;
|
|
29
28
|
private enrichOne;
|
|
29
|
+
/**
|
|
30
|
+
* Best-effort lifecycle status from a deprecation-date string.
|
|
31
|
+
*
|
|
32
|
+
* Returns `"retired"` when the date has already passed,
|
|
33
|
+
* `"deprecated"` when one is set but still in the future,
|
|
34
|
+
* and `"active"` when no date is present.
|
|
35
|
+
*/
|
|
36
|
+
private inferStatus;
|
|
30
37
|
/**
|
|
31
38
|
* Look up a model in the litellm pricing catalogue using a tiered set of
|
|
32
39
|
* key strategies. Later strategies use `originProvider` to handle models
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"litellm.d.ts","sourceRoot":"","sources":["../../src/enrichment/litellm.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"litellm.d.ts","sourceRoot":"","sources":["../../src/enrichment/litellm.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAc7F;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC/C,OAAO,CAAC,IAAI,CAAkD;IAE9D,8EAA8E;IACxE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;;;;;OAMG;IACG,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IASvD,OAAO,CAAC,SAAS;IAwKjB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAOnB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,WAAW;IA6CnB,8DAA8D;IAC9D,OAAO,CAAC,cAAc;IAuHtB;;;OAGG;IACH,OAAO,CAAC,WAAW;IASnB,sDAAsD;IACtD,OAAO,CAAC,OAAO;CAkBf"}
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
* flags on already-discovered {@link ModelCard} objects.
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
+
import { applyFreeTierFlag } from "../discovery/free-tier.js";
|
|
9
10
|
import { normalizeModelId } from "../normalize.js";
|
|
10
|
-
import {
|
|
11
|
+
import { inferParallelToolCalls, inferStructuredOutputModes, inferToolDialect } from "../model-features.js";
|
|
12
|
+
import { inferTokenizerFamily } from "../tokenizer-family.js";
|
|
13
|
+
import { loadLiteLLMCatalog } from "./litellm-catalog.js";
|
|
11
14
|
/**
|
|
12
15
|
* Multiplier to convert litellm's per-token costs into our standard
|
|
13
16
|
* per-million-token pricing. litellm stores costs as cost-per-single-token,
|
|
@@ -22,18 +25,11 @@ const PER_MILLION = 1_000_000;
|
|
|
22
25
|
*/
|
|
23
26
|
export class LiteLLMEnricher {
|
|
24
27
|
data = null;
|
|
25
|
-
|
|
26
|
-
/** Fetch and cache the litellm pricing JSON. Safe to call multiple times. */
|
|
28
|
+
/** Fetch and cache the litellm pricing JSON via the shared catalog loader. */
|
|
27
29
|
async load() {
|
|
28
30
|
if (this.data)
|
|
29
31
|
return;
|
|
30
|
-
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw new Error(`Failed to fetch litellm data: ${response.status} ${response.statusText}`);
|
|
33
|
-
}
|
|
34
|
-
const raw = (await response.json());
|
|
35
|
-
assertCleanPayload(raw, "litellm");
|
|
36
|
-
this.data = raw;
|
|
32
|
+
this.data = await loadLiteLLMCatalog();
|
|
37
33
|
}
|
|
38
34
|
/**
|
|
39
35
|
* Enrich an array of ModelCards with litellm data.
|
|
@@ -44,7 +40,7 @@ export class LiteLLMEnricher {
|
|
|
44
40
|
*/
|
|
45
41
|
async enrich(models) {
|
|
46
42
|
await this.load();
|
|
47
|
-
return models.map((model) => this.enrichOne(model));
|
|
43
|
+
return models.map((model) => applyFreeTierFlag(this.enrichOne(model)));
|
|
48
44
|
}
|
|
49
45
|
// ---------------------------------------------------------------------------
|
|
50
46
|
// Private
|
|
@@ -78,6 +74,20 @@ export class LiteLLMEnricher {
|
|
|
78
74
|
cacheWritePerMillion: entryPricing.cacheWritePerMillion,
|
|
79
75
|
};
|
|
80
76
|
}
|
|
77
|
+
if (enriched.pricing.batchInputPerMillion === undefined &&
|
|
78
|
+
entryPricing.batchInputPerMillion !== undefined) {
|
|
79
|
+
enriched.pricing = {
|
|
80
|
+
...enriched.pricing,
|
|
81
|
+
batchInputPerMillion: entryPricing.batchInputPerMillion,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (enriched.pricing.batchOutputPerMillion === undefined &&
|
|
85
|
+
entryPricing.batchOutputPerMillion !== undefined) {
|
|
86
|
+
enriched.pricing = {
|
|
87
|
+
...enriched.pricing,
|
|
88
|
+
batchOutputPerMillion: entryPricing.batchOutputPerMillion,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
// Preserve proxy-route pricing while surfacing direct-origin reference pricing.
|
|
@@ -127,8 +137,80 @@ export class LiteLLMEnricher {
|
|
|
127
137
|
if (entry.supports_prompt_caching && !enriched.capabilities.includes("prompt_caching")) {
|
|
128
138
|
enriched.capabilities.push("prompt_caching");
|
|
129
139
|
}
|
|
140
|
+
if (entry.supports_audio_input && !enriched.capabilities.includes("audio_input")) {
|
|
141
|
+
enriched.capabilities.push("audio_input");
|
|
142
|
+
}
|
|
143
|
+
if (entry.supports_audio_output && !enriched.capabilities.includes("audio_output")) {
|
|
144
|
+
enriched.capabilities.push("audio_output");
|
|
145
|
+
}
|
|
146
|
+
if (entry.supports_video_input && !enriched.capabilities.includes("video_input")) {
|
|
147
|
+
enriched.capabilities.push("video_input");
|
|
148
|
+
}
|
|
149
|
+
if (entry.supports_reasoning && !enriched.capabilities.includes("reasoning")) {
|
|
150
|
+
enriched.capabilities.push("reasoning");
|
|
151
|
+
}
|
|
152
|
+
if (entry.supports_response_schema && !enriched.capabilities.includes("structured_output")) {
|
|
153
|
+
enriched.capabilities.push("structured_output");
|
|
154
|
+
}
|
|
155
|
+
// Tokenizer family — only fill when missing. Prefer a local-runtime value
|
|
156
|
+
// when the discoverer already supplied one; fall back to heuristic inference
|
|
157
|
+
// based on origin provider and model ID.
|
|
158
|
+
if (!enriched.tokenizerFamily) {
|
|
159
|
+
const localFamily = enriched.localRuntime?.tokenizerFamily;
|
|
160
|
+
enriched.tokenizerFamily =
|
|
161
|
+
localFamily ?? inferTokenizerFamily(enriched.originProvider, enriched.id);
|
|
162
|
+
}
|
|
163
|
+
// Tool dialect — only fill when missing. The discoverer might know the
|
|
164
|
+
// canonical dialect for managed proxy endpoints; we only infer when it
|
|
165
|
+
// didn't come through.
|
|
166
|
+
if (enriched.toolDialect === undefined) {
|
|
167
|
+
const dialect = inferToolDialect(enriched.originProvider, enriched.id);
|
|
168
|
+
if (dialect !== undefined)
|
|
169
|
+
enriched.toolDialect = dialect;
|
|
170
|
+
}
|
|
171
|
+
// Structured output modes — only fill when the discoverer hasn't set them.
|
|
172
|
+
if (enriched.structuredOutputModes === undefined) {
|
|
173
|
+
const modes = inferStructuredOutputModes(enriched.originProvider, enriched.id);
|
|
174
|
+
if (modes.length > 0)
|
|
175
|
+
enriched.structuredOutputModes = modes;
|
|
176
|
+
}
|
|
177
|
+
// Parallel tool calls — litellm's flag takes precedence when present,
|
|
178
|
+
// otherwise fall back to the heuristic from the dialect / model ID.
|
|
179
|
+
if (enriched.supportsParallelToolCalls === undefined) {
|
|
180
|
+
if (entry.supports_parallel_function_calling !== undefined) {
|
|
181
|
+
enriched.supportsParallelToolCalls = entry.supports_parallel_function_calling;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
const parallel = inferParallelToolCalls(enriched.originProvider, enriched.id);
|
|
185
|
+
if (parallel !== undefined)
|
|
186
|
+
enriched.supportsParallelToolCalls = parallel;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Deprecation metadata — only fill when missing; litellm publishes
|
|
190
|
+
// `deprecation_date` as an ISO string for models with announced sunset.
|
|
191
|
+
if (!enriched.deprecationDate && entry.deprecation_date) {
|
|
192
|
+
enriched.deprecationDate = entry.deprecation_date;
|
|
193
|
+
}
|
|
194
|
+
if (!enriched.status) {
|
|
195
|
+
enriched.status = this.inferStatus(enriched.deprecationDate);
|
|
196
|
+
}
|
|
130
197
|
return enriched;
|
|
131
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Best-effort lifecycle status from a deprecation-date string.
|
|
201
|
+
*
|
|
202
|
+
* Returns `"retired"` when the date has already passed,
|
|
203
|
+
* `"deprecated"` when one is set but still in the future,
|
|
204
|
+
* and `"active"` when no date is present.
|
|
205
|
+
*/
|
|
206
|
+
inferStatus(deprecationDate) {
|
|
207
|
+
if (!deprecationDate)
|
|
208
|
+
return "active";
|
|
209
|
+
const ts = Date.parse(deprecationDate);
|
|
210
|
+
if (Number.isNaN(ts))
|
|
211
|
+
return "active";
|
|
212
|
+
return ts <= Date.now() ? "retired" : "deprecated";
|
|
213
|
+
}
|
|
132
214
|
/**
|
|
133
215
|
* Look up a model in the litellm pricing catalogue using a tiered set of
|
|
134
216
|
* key strategies. Later strategies use `originProvider` to handle models
|
|
@@ -192,18 +274,31 @@ export class LiteLLMEnricher {
|
|
|
192
274
|
extractPricing(entry) {
|
|
193
275
|
const reasoningInputCost = this.firstFinite(entry.input_cost_per_reasoning_token, entry.reasoning_input_cost_per_token);
|
|
194
276
|
const reasoningOutputCost = this.firstFinite(entry.output_cost_per_reasoning_token, entry.reasoning_output_cost_per_token);
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
277
|
+
const baseInput = this.firstFinite(entry.input_cost_per_token);
|
|
278
|
+
const baseOutput = this.firstFinite(entry.output_cost_per_token);
|
|
279
|
+
const hasBaseTokenPricing = baseInput !== undefined && baseOutput !== undefined;
|
|
280
|
+
// Multimodal-only entries (TTS by-the-second, image generation, per-character
|
|
281
|
+
// Vertex models) legitimately publish no token-billed pricing — synthesizing
|
|
282
|
+
// 0/0 base on those is honest, and downstream free_tier detection skips
|
|
283
|
+
// non-chat modes. Cache-only / batch-only / reasoning-only entries, on the
|
|
284
|
+
// other hand, are incomplete catalog rows: synthesizing 0/0 base from them
|
|
285
|
+
// would falsely flag the model as free_tier, so we refuse.
|
|
286
|
+
const hasNonTokenPricing = entry.input_cost_per_image !== undefined ||
|
|
287
|
+
entry.output_cost_per_image !== undefined ||
|
|
288
|
+
entry.input_cost_per_audio_token !== undefined ||
|
|
289
|
+
entry.output_cost_per_audio_token !== undefined ||
|
|
290
|
+
entry.input_cost_per_audio_per_second !== undefined ||
|
|
291
|
+
entry.output_cost_per_audio_per_second !== undefined ||
|
|
292
|
+
entry.input_cost_per_video_per_second !== undefined ||
|
|
293
|
+
entry.input_cost_per_video_token !== undefined ||
|
|
294
|
+
entry.input_cost_per_character !== undefined ||
|
|
295
|
+
entry.output_cost_per_character !== undefined;
|
|
296
|
+
if (!hasBaseTokenPricing && !hasNonTokenPricing) {
|
|
202
297
|
return undefined;
|
|
203
298
|
}
|
|
204
299
|
const pricing = {
|
|
205
|
-
inputPerMillion: (
|
|
206
|
-
outputPerMillion: (
|
|
300
|
+
inputPerMillion: (baseInput ?? 0) * PER_MILLION,
|
|
301
|
+
outputPerMillion: (baseOutput ?? 0) * PER_MILLION,
|
|
207
302
|
};
|
|
208
303
|
if (reasoningInputCost !== undefined) {
|
|
209
304
|
pricing.reasoningInputPerMillion = reasoningInputCost * PER_MILLION;
|
|
@@ -217,6 +312,59 @@ export class LiteLLMEnricher {
|
|
|
217
312
|
if (entry.cache_creation_input_token_cost !== undefined) {
|
|
218
313
|
pricing.cacheWritePerMillion = entry.cache_creation_input_token_cost * PER_MILLION;
|
|
219
314
|
}
|
|
315
|
+
if (entry.input_cost_per_token_batches !== undefined) {
|
|
316
|
+
pricing.batchInputPerMillion = entry.input_cost_per_token_batches * PER_MILLION;
|
|
317
|
+
}
|
|
318
|
+
if (entry.output_cost_per_token_batches !== undefined) {
|
|
319
|
+
pricing.batchOutputPerMillion = entry.output_cost_per_token_batches * PER_MILLION;
|
|
320
|
+
}
|
|
321
|
+
// Multimodal — images are already per-unit; audio/video tokens go through PER_MILLION.
|
|
322
|
+
if (entry.input_cost_per_image !== undefined) {
|
|
323
|
+
pricing.imageInputPerImage = entry.input_cost_per_image;
|
|
324
|
+
}
|
|
325
|
+
if (entry.output_cost_per_image !== undefined) {
|
|
326
|
+
pricing.imageOutputPerImage = entry.output_cost_per_image;
|
|
327
|
+
}
|
|
328
|
+
if (entry.input_cost_per_audio_token !== undefined) {
|
|
329
|
+
pricing.audioInputPerMillion = entry.input_cost_per_audio_token * PER_MILLION;
|
|
330
|
+
}
|
|
331
|
+
if (entry.output_cost_per_audio_token !== undefined) {
|
|
332
|
+
pricing.audioOutputPerMillion = entry.output_cost_per_audio_token * PER_MILLION;
|
|
333
|
+
}
|
|
334
|
+
if (entry.input_cost_per_audio_per_second !== undefined) {
|
|
335
|
+
pricing.audioInputPerSecond = entry.input_cost_per_audio_per_second;
|
|
336
|
+
}
|
|
337
|
+
if (entry.output_cost_per_audio_per_second !== undefined) {
|
|
338
|
+
pricing.audioOutputPerSecond = entry.output_cost_per_audio_per_second;
|
|
339
|
+
}
|
|
340
|
+
if (entry.input_cost_per_video_per_second !== undefined) {
|
|
341
|
+
pricing.videoInputPerSecond = entry.input_cost_per_video_per_second;
|
|
342
|
+
}
|
|
343
|
+
if (entry.input_cost_per_video_token !== undefined) {
|
|
344
|
+
pricing.videoInputPerMillion = entry.input_cost_per_video_token * PER_MILLION;
|
|
345
|
+
}
|
|
346
|
+
// Character-billed providers (Vertex AI, Azure).
|
|
347
|
+
if (entry.input_cost_per_character !== undefined) {
|
|
348
|
+
pricing.inputPerMillionCharacters = entry.input_cost_per_character * PER_MILLION;
|
|
349
|
+
}
|
|
350
|
+
if (entry.output_cost_per_character !== undefined) {
|
|
351
|
+
pricing.outputPerMillionCharacters = entry.output_cost_per_character * PER_MILLION;
|
|
352
|
+
}
|
|
353
|
+
// Tiered long-context pricing — prefer 128k, fall back to 200k (Claude-style).
|
|
354
|
+
const tieredIn = this.firstFinite(entry.input_cost_per_token_above_128k_tokens, entry.input_cost_per_token_above_200k_tokens);
|
|
355
|
+
const tieredOut = this.firstFinite(entry.output_cost_per_token_above_128k_tokens, entry.output_cost_per_token_above_200k_tokens);
|
|
356
|
+
if (tieredIn !== undefined) {
|
|
357
|
+
pricing.longContextInputPerMillion = tieredIn * PER_MILLION;
|
|
358
|
+
}
|
|
359
|
+
if (tieredOut !== undefined) {
|
|
360
|
+
pricing.longContextOutputPerMillion = tieredOut * PER_MILLION;
|
|
361
|
+
}
|
|
362
|
+
if (entry.input_cost_per_token_above_128k_tokens !== undefined || entry.output_cost_per_token_above_128k_tokens !== undefined) {
|
|
363
|
+
pricing.longContextThresholdTokens = 128_000;
|
|
364
|
+
}
|
|
365
|
+
else if (entry.input_cost_per_token_above_200k_tokens !== undefined || entry.output_cost_per_token_above_200k_tokens !== undefined) {
|
|
366
|
+
pricing.longContextThresholdTokens = 200_000;
|
|
367
|
+
}
|
|
220
368
|
return pricing;
|
|
221
369
|
}
|
|
222
370
|
/**
|