@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.
Files changed (208) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +286 -0
  3. package/dist/aliases.d.ts +51 -0
  4. package/dist/aliases.d.ts.map +1 -0
  5. package/dist/aliases.js +115 -0
  6. package/dist/aliases.js.map +1 -0
  7. package/dist/cache.d.ts +57 -0
  8. package/dist/cache.d.ts.map +1 -0
  9. package/dist/cache.js +123 -0
  10. package/dist/cache.js.map +1 -0
  11. package/dist/cli-commands.d.ts +142 -0
  12. package/dist/cli-commands.d.ts.map +1 -0
  13. package/dist/cli-commands.js +746 -0
  14. package/dist/cli-commands.js.map +1 -0
  15. package/dist/cli-format.d.ts +119 -0
  16. package/dist/cli-format.d.ts.map +1 -0
  17. package/dist/cli-format.js +171 -0
  18. package/dist/cli-format.js.map +1 -0
  19. package/dist/cli.d.ts +15 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +143 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/credentials/index.d.ts +2 -0
  24. package/dist/credentials/index.d.ts.map +1 -0
  25. package/dist/credentials/index.js +2 -0
  26. package/dist/credentials/index.js.map +1 -0
  27. package/dist/credentials/resolver.d.ts +170 -0
  28. package/dist/credentials/resolver.d.ts.map +1 -0
  29. package/dist/credentials/resolver.js +597 -0
  30. package/dist/credentials/resolver.js.map +1 -0
  31. package/dist/discovery/anthropic.d.ts +49 -0
  32. package/dist/discovery/anthropic.d.ts.map +1 -0
  33. package/dist/discovery/anthropic.js +101 -0
  34. package/dist/discovery/anthropic.js.map +1 -0
  35. package/dist/discovery/base.d.ts +59 -0
  36. package/dist/discovery/base.d.ts.map +1 -0
  37. package/dist/discovery/base.js +123 -0
  38. package/dist/discovery/base.js.map +1 -0
  39. package/dist/discovery/bedrock.d.ts +122 -0
  40. package/dist/discovery/bedrock.d.ts.map +1 -0
  41. package/dist/discovery/bedrock.js +356 -0
  42. package/dist/discovery/bedrock.js.map +1 -0
  43. package/dist/discovery/cerebras.d.ts +43 -0
  44. package/dist/discovery/cerebras.d.ts.map +1 -0
  45. package/dist/discovery/cerebras.js +65 -0
  46. package/dist/discovery/cerebras.js.map +1 -0
  47. package/dist/discovery/cohere.d.ts +57 -0
  48. package/dist/discovery/cohere.d.ts.map +1 -0
  49. package/dist/discovery/cohere.js +82 -0
  50. package/dist/discovery/cohere.js.map +1 -0
  51. package/dist/discovery/deepinfra.d.ts +41 -0
  52. package/dist/discovery/deepinfra.d.ts.map +1 -0
  53. package/dist/discovery/deepinfra.js +86 -0
  54. package/dist/discovery/deepinfra.js.map +1 -0
  55. package/dist/discovery/deepseek.d.ts +17 -0
  56. package/dist/discovery/deepseek.d.ts.map +1 -0
  57. package/dist/discovery/deepseek.js +45 -0
  58. package/dist/discovery/deepseek.js.map +1 -0
  59. package/dist/discovery/fireworks.d.ts +48 -0
  60. package/dist/discovery/fireworks.d.ts.map +1 -0
  61. package/dist/discovery/fireworks.js +101 -0
  62. package/dist/discovery/fireworks.js.map +1 -0
  63. package/dist/discovery/glm.d.ts +17 -0
  64. package/dist/discovery/glm.d.ts.map +1 -0
  65. package/dist/discovery/glm.js +52 -0
  66. package/dist/discovery/glm.js.map +1 -0
  67. package/dist/discovery/google.d.ts +53 -0
  68. package/dist/discovery/google.d.ts.map +1 -0
  69. package/dist/discovery/google.js +122 -0
  70. package/dist/discovery/google.js.map +1 -0
  71. package/dist/discovery/groq.d.ts +44 -0
  72. package/dist/discovery/groq.d.ts.map +1 -0
  73. package/dist/discovery/groq.js +89 -0
  74. package/dist/discovery/groq.js.map +1 -0
  75. package/dist/discovery/index.d.ts +48 -0
  76. package/dist/discovery/index.d.ts.map +1 -0
  77. package/dist/discovery/index.js +116 -0
  78. package/dist/discovery/index.js.map +1 -0
  79. package/dist/discovery/llama-cpp.d.ts +45 -0
  80. package/dist/discovery/llama-cpp.d.ts.map +1 -0
  81. package/dist/discovery/llama-cpp.js +137 -0
  82. package/dist/discovery/llama-cpp.js.map +1 -0
  83. package/dist/discovery/minimax.d.ts +16 -0
  84. package/dist/discovery/minimax.d.ts.map +1 -0
  85. package/dist/discovery/minimax.js +56 -0
  86. package/dist/discovery/minimax.js.map +1 -0
  87. package/dist/discovery/mistral.d.ts +45 -0
  88. package/dist/discovery/mistral.d.ts.map +1 -0
  89. package/dist/discovery/mistral.js +82 -0
  90. package/dist/discovery/mistral.js.map +1 -0
  91. package/dist/discovery/moonshot.d.ts +16 -0
  92. package/dist/discovery/moonshot.d.ts.map +1 -0
  93. package/dist/discovery/moonshot.js +46 -0
  94. package/dist/discovery/moonshot.js.map +1 -0
  95. package/dist/discovery/nvidia.d.ts +60 -0
  96. package/dist/discovery/nvidia.d.ts.map +1 -0
  97. package/dist/discovery/nvidia.js +145 -0
  98. package/dist/discovery/nvidia.js.map +1 -0
  99. package/dist/discovery/ollama.d.ts +57 -0
  100. package/dist/discovery/ollama.d.ts.map +1 -0
  101. package/dist/discovery/ollama.js +151 -0
  102. package/dist/discovery/ollama.js.map +1 -0
  103. package/dist/discovery/openai-compatible.d.ts +126 -0
  104. package/dist/discovery/openai-compatible.d.ts.map +1 -0
  105. package/dist/discovery/openai-compatible.js +161 -0
  106. package/dist/discovery/openai-compatible.js.map +1 -0
  107. package/dist/discovery/openai.d.ts +62 -0
  108. package/dist/discovery/openai.d.ts.map +1 -0
  109. package/dist/discovery/openai.js +157 -0
  110. package/dist/discovery/openai.js.map +1 -0
  111. package/dist/discovery/openrouter.d.ts +78 -0
  112. package/dist/discovery/openrouter.d.ts.map +1 -0
  113. package/dist/discovery/openrouter.js +184 -0
  114. package/dist/discovery/openrouter.js.map +1 -0
  115. package/dist/discovery/perplexity.d.ts +66 -0
  116. package/dist/discovery/perplexity.d.ts.map +1 -0
  117. package/dist/discovery/perplexity.js +86 -0
  118. package/dist/discovery/perplexity.js.map +1 -0
  119. package/dist/discovery/together.d.ts +41 -0
  120. package/dist/discovery/together.d.ts.map +1 -0
  121. package/dist/discovery/together.js +88 -0
  122. package/dist/discovery/together.js.map +1 -0
  123. package/dist/discovery/vertex.d.ts +146 -0
  124. package/dist/discovery/vertex.d.ts.map +1 -0
  125. package/dist/discovery/vertex.js +371 -0
  126. package/dist/discovery/vertex.js.map +1 -0
  127. package/dist/discovery/zai.d.ts +17 -0
  128. package/dist/discovery/zai.d.ts.map +1 -0
  129. package/dist/discovery/zai.js +51 -0
  130. package/dist/discovery/zai.js.map +1 -0
  131. package/dist/discovery-contract.d.ts +186 -0
  132. package/dist/discovery-contract.d.ts.map +1 -0
  133. package/dist/discovery-contract.js +115 -0
  134. package/dist/discovery-contract.js.map +1 -0
  135. package/dist/discovery-routes.d.ts +14 -0
  136. package/dist/discovery-routes.d.ts.map +1 -0
  137. package/dist/discovery-routes.js +98 -0
  138. package/dist/discovery-routes.js.map +1 -0
  139. package/dist/enrichment/index.d.ts +2 -0
  140. package/dist/enrichment/index.d.ts.map +1 -0
  141. package/dist/enrichment/index.js +2 -0
  142. package/dist/enrichment/index.js.map +1 -0
  143. package/dist/enrichment/litellm.d.ts +52 -0
  144. package/dist/enrichment/litellm.d.ts.map +1 -0
  145. package/dist/enrichment/litellm.js +205 -0
  146. package/dist/enrichment/litellm.js.map +1 -0
  147. package/dist/index.d.ts +30 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +33 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/normalize.d.ts +64 -0
  152. package/dist/normalize.d.ts.map +1 -0
  153. package/dist/normalize.js +166 -0
  154. package/dist/normalize.js.map +1 -0
  155. package/dist/provider-catalog.d.ts +62 -0
  156. package/dist/provider-catalog.d.ts.map +1 -0
  157. package/dist/provider-catalog.js +331 -0
  158. package/dist/provider-catalog.js.map +1 -0
  159. package/dist/registry-delta.d.ts +17 -0
  160. package/dist/registry-delta.d.ts.map +1 -0
  161. package/dist/registry-delta.js +74 -0
  162. package/dist/registry-delta.js.map +1 -0
  163. package/dist/registry-discovery.d.ts +66 -0
  164. package/dist/registry-discovery.d.ts.map +1 -0
  165. package/dist/registry-discovery.js +339 -0
  166. package/dist/registry-discovery.js.map +1 -0
  167. package/dist/registry-query.d.ts +74 -0
  168. package/dist/registry-query.d.ts.map +1 -0
  169. package/dist/registry-query.js +310 -0
  170. package/dist/registry-query.js.map +1 -0
  171. package/dist/registry-runtime.d.ts +48 -0
  172. package/dist/registry-runtime.d.ts.map +1 -0
  173. package/dist/registry-runtime.js +255 -0
  174. package/dist/registry-runtime.js.map +1 -0
  175. package/dist/registry-selection.d.ts +31 -0
  176. package/dist/registry-selection.d.ts.map +1 -0
  177. package/dist/registry-selection.js +167 -0
  178. package/dist/registry-selection.js.map +1 -0
  179. package/dist/registry-state.d.ts +92 -0
  180. package/dist/registry-state.d.ts.map +1 -0
  181. package/dist/registry-state.js +35 -0
  182. package/dist/registry-state.js.map +1 -0
  183. package/dist/registry.d.ts +127 -0
  184. package/dist/registry.d.ts.map +1 -0
  185. package/dist/registry.js +248 -0
  186. package/dist/registry.js.map +1 -0
  187. package/dist/resilience.d.ts +212 -0
  188. package/dist/resilience.d.ts.map +1 -0
  189. package/dist/resilience.js +292 -0
  190. package/dist/resilience.js.map +1 -0
  191. package/dist/security.d.ts +44 -0
  192. package/dist/security.d.ts.map +1 -0
  193. package/dist/security.js +184 -0
  194. package/dist/security.js.map +1 -0
  195. package/dist/server.d.ts +41 -0
  196. package/dist/server.d.ts.map +1 -0
  197. package/dist/server.js +320 -0
  198. package/dist/server.js.map +1 -0
  199. package/dist/shell-safe.d.ts +15 -0
  200. package/dist/shell-safe.d.ts.map +1 -0
  201. package/dist/shell-safe.js +20 -0
  202. package/dist/shell-safe.js.map +1 -0
  203. package/dist/types.d.ts +365 -0
  204. package/dist/types.d.ts.map +1 -0
  205. package/dist/types.js +10 -0
  206. package/dist/types.js.map +1 -0
  207. package/logo.svg +81 -0
  208. package/package.json +85 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * kosha-discovery — OpenAI-compatible provider base class.
3
+ *
4
+ * Many providers (NVIDIA, Together AI, Fireworks AI, Groq, Mistral AI,
5
+ * DeepInfra, Cerebras, Perplexity, etc.) expose an OpenAI-compatible
6
+ * `/v1/models` endpoint with Bearer auth. This base class extracts the
7
+ * shared discover/filter/map pipeline so concrete providers only need to
8
+ * define identity fields and override the three hooks:
9
+ *
10
+ * - {@link isRelevantModel} — filter out irrelevant models
11
+ * - {@link classifyModel} — determine origin, mode, and capabilities
12
+ *
13
+ * @module
14
+ */
15
+ import type { CredentialResult, ModelCard, ModelMode } from "../types.js";
16
+ import { BaseDiscoverer } from "./base.js";
17
+ /** Shape of a single model from any OpenAI-compatible `/v1/models` response. */
18
+ export interface OpenAICompatibleModel {
19
+ id: string;
20
+ object: string;
21
+ created: number;
22
+ owned_by: string;
23
+ /** Some providers (Together AI) include a type field. */
24
+ type?: string;
25
+ /** Some providers (Groq) include a context_window field. */
26
+ context_window?: number;
27
+ /** Some providers expose explicit max output tokens. */
28
+ max_output_tokens?: number;
29
+ /** Some providers expose explicit max input tokens. */
30
+ max_input_tokens?: number;
31
+ /** Some embedding providers expose vector dimensionality. */
32
+ output_vector_size?: number;
33
+ }
34
+ /** Standard response shape from `GET /v1/models`. */
35
+ export interface OpenAICompatibleListResponse {
36
+ data: OpenAICompatibleModel[];
37
+ object: string;
38
+ }
39
+ /** Classification result returned by the per-provider hook. */
40
+ export interface ModelClassification {
41
+ originProvider: string;
42
+ mode: ModelMode;
43
+ capabilities: string[];
44
+ contextWindow?: number;
45
+ maxOutputTokens?: number;
46
+ maxInputTokens?: number;
47
+ dimensions?: number;
48
+ }
49
+ /**
50
+ * Base class for providers that expose an OpenAI-compatible `/v1/models` endpoint.
51
+ *
52
+ * Concrete subclasses set `providerId`, `providerName`, `baseUrl` and override:
53
+ *
54
+ * - {@link isRelevantModel} — Return false to filter a model out.
55
+ * - {@link classifyModel} — Return origin, mode, and capabilities.
56
+ *
57
+ * The `discover()` pipeline handles auth, fetch, filter, and card construction.
58
+ *
59
+ * @example
60
+ * export class MyProviderDiscoverer extends OpenAICompatibleDiscoverer {
61
+ * readonly providerId = "myprovider";
62
+ * readonly providerName = "My Provider";
63
+ * readonly baseUrl = "https://api.myprovider.com";
64
+ *
65
+ * protected isRelevantModel(model: OpenAICompatibleModel): boolean { ... }
66
+ * protected classifyModel(model: OpenAICompatibleModel): ModelClassification { ... }
67
+ * }
68
+ */
69
+ export declare abstract class OpenAICompatibleDiscoverer extends BaseDiscoverer {
70
+ /**
71
+ * Fetch the model list, filter, classify, and return normalized cards.
72
+ *
73
+ * @param credential - Must contain `apiKey` or `accessToken`.
74
+ * @param options - Optional timeout override (default 10 s).
75
+ */
76
+ discover(credential: CredentialResult, options?: {
77
+ timeout?: number;
78
+ }): Promise<ModelCard[]>;
79
+ /**
80
+ * Ordered model-list endpoints to try.
81
+ *
82
+ * Most providers use `/v1/models`. Some OpenAI-compatible APIs expose
83
+ * `/models` at versioned base URLs; subclasses can override this.
84
+ */
85
+ protected modelListEndpoints(): string[];
86
+ /**
87
+ * Return false to exclude a model from discovery results.
88
+ *
89
+ * Default implementation keeps all models. Override to filter
90
+ * reward models, fine-tune snapshots, deprecated entries, etc.
91
+ */
92
+ protected isRelevantModel(_model: OpenAICompatibleModel): boolean;
93
+ /**
94
+ * Classify a model: determine origin provider, mode, and capabilities.
95
+ *
96
+ * Must be implemented by each concrete subclass since classification
97
+ * rules are provider-specific.
98
+ */
99
+ protected abstract classifyModel(model: OpenAICompatibleModel): ModelClassification;
100
+ /**
101
+ * Extract origin provider from a `vendor/model-name` namespaced ID.
102
+ * Returns `fallback` if no `/` is present.
103
+ */
104
+ protected extractPrefixOrigin(id: string, fallback: string, aliases?: Record<string, string>): string;
105
+ /**
106
+ * Infer origin from flat model ID keywords (for providers like Groq
107
+ * that don't use namespaced IDs).
108
+ *
109
+ * Checks keywords in order — put more-specific matches first
110
+ * (e.g. "deepseek" before "llama" for `deepseek-r1-distill-llama-70b`).
111
+ */
112
+ protected inferOriginFromKeywords(lower: string, rules: [string, string][], fallback: string): string;
113
+ /** Check if a lowercase model ID looks like an embedding model. */
114
+ protected looksLikeEmbedding(lower: string): boolean;
115
+ /** Check if a lowercase model ID looks like a vision model. */
116
+ protected looksLikeVision(lower: string): boolean;
117
+ /** Check if a lowercase model ID looks like a code model. */
118
+ protected looksLikeCode(lower: string): boolean;
119
+ /** Check if a lowercase model ID looks like an audio/speech model. */
120
+ protected looksLikeAudio(lower: string): boolean;
121
+ /** Check if ID contains common "reward model" patterns to filter. */
122
+ protected looksLikeReward(lower: string): boolean;
123
+ /** Build a ModelCard from a raw API model + classification. */
124
+ private toCard;
125
+ }
126
+ //# sourceMappingURL=openai-compatible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.d.ts","sourceRoot":"","sources":["../../src/discovery/openai-compatible.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qDAAqD;AACrD,MAAM,WAAW,4BAA4B;IAC5C,IAAI,EAAE,qBAAqB,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;CACf;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,8BAAsB,0BAA2B,SAAQ,cAAc;IACtE;;;;;OAKG;IACG,QAAQ,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAkClG;;;;;OAKG;IACH,SAAS,CAAC,kBAAkB,IAAI,MAAM,EAAE;IAIxC;;;;;OAKG;IACH,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO;IAIjE;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,qBAAqB,GAAG,mBAAmB;IAMnF;;;OAGG;IACH,SAAS,CAAC,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM;IASrG;;;;;;OAMG;IACH,SAAS,CAAC,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAOrG,mEAAmE;IACnE,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIpD,+DAA+D;IAC/D,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAMjD,6DAA6D;IAC7D,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAK/C,sEAAsE;IACtE,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhD,qEAAqE;IACrE,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQjD,+DAA+D;IAC/D,OAAO,CAAC,MAAM;CAed"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * kosha-discovery — OpenAI-compatible provider base class.
3
+ *
4
+ * Many providers (NVIDIA, Together AI, Fireworks AI, Groq, Mistral AI,
5
+ * DeepInfra, Cerebras, Perplexity, etc.) expose an OpenAI-compatible
6
+ * `/v1/models` endpoint with Bearer auth. This base class extracts the
7
+ * shared discover/filter/map pipeline so concrete providers only need to
8
+ * define identity fields and override the three hooks:
9
+ *
10
+ * - {@link isRelevantModel} — filter out irrelevant models
11
+ * - {@link classifyModel} — determine origin, mode, and capabilities
12
+ *
13
+ * @module
14
+ */
15
+ import { BaseDiscoverer } from "./base.js";
16
+ /**
17
+ * Base class for providers that expose an OpenAI-compatible `/v1/models` endpoint.
18
+ *
19
+ * Concrete subclasses set `providerId`, `providerName`, `baseUrl` and override:
20
+ *
21
+ * - {@link isRelevantModel} — Return false to filter a model out.
22
+ * - {@link classifyModel} — Return origin, mode, and capabilities.
23
+ *
24
+ * The `discover()` pipeline handles auth, fetch, filter, and card construction.
25
+ *
26
+ * @example
27
+ * export class MyProviderDiscoverer extends OpenAICompatibleDiscoverer {
28
+ * readonly providerId = "myprovider";
29
+ * readonly providerName = "My Provider";
30
+ * readonly baseUrl = "https://api.myprovider.com";
31
+ *
32
+ * protected isRelevantModel(model: OpenAICompatibleModel): boolean { ... }
33
+ * protected classifyModel(model: OpenAICompatibleModel): ModelClassification { ... }
34
+ * }
35
+ */
36
+ export class OpenAICompatibleDiscoverer extends BaseDiscoverer {
37
+ /**
38
+ * Fetch the model list, filter, classify, and return normalized cards.
39
+ *
40
+ * @param credential - Must contain `apiKey` or `accessToken`.
41
+ * @param options - Optional timeout override (default 10 s).
42
+ */
43
+ async discover(credential, options) {
44
+ const apiKey = credential.apiKey ?? credential.accessToken;
45
+ if (!apiKey) {
46
+ return [];
47
+ }
48
+ const timeoutMs = this.validateTimeout(options?.timeout);
49
+ const headers = {
50
+ Authorization: `Bearer ${apiKey}`,
51
+ };
52
+ let response = null;
53
+ let lastError;
54
+ for (const endpoint of this.modelListEndpoints()) {
55
+ try {
56
+ response = await this.fetchJSON(endpoint, headers, timeoutMs);
57
+ break;
58
+ }
59
+ catch (error) {
60
+ lastError = error;
61
+ }
62
+ }
63
+ if (!response) {
64
+ throw lastError instanceof Error ? lastError : new Error(`${this.providerName} API request failed`);
65
+ }
66
+ return response.data
67
+ .filter((model) => this.isRelevantModel(model))
68
+ .map((model) => this.toCard(model));
69
+ }
70
+ /**
71
+ * Ordered model-list endpoints to try.
72
+ *
73
+ * Most providers use `/v1/models`. Some OpenAI-compatible APIs expose
74
+ * `/models` at versioned base URLs; subclasses can override this.
75
+ */
76
+ modelListEndpoints() {
77
+ return [`${this.baseUrl}/v1/models`];
78
+ }
79
+ /**
80
+ * Return false to exclude a model from discovery results.
81
+ *
82
+ * Default implementation keeps all models. Override to filter
83
+ * reward models, fine-tune snapshots, deprecated entries, etc.
84
+ */
85
+ isRelevantModel(_model) {
86
+ return true;
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // Shared classification helpers — subclasses can call these for common logic
90
+ // ---------------------------------------------------------------------------
91
+ /**
92
+ * Extract origin provider from a `vendor/model-name` namespaced ID.
93
+ * Returns `fallback` if no `/` is present.
94
+ */
95
+ extractPrefixOrigin(id, fallback, aliases) {
96
+ const slashIdx = id.indexOf("/");
97
+ if (slashIdx === -1)
98
+ return fallback;
99
+ const prefix = id.slice(0, slashIdx).toLowerCase();
100
+ if (aliases && prefix in aliases)
101
+ return aliases[prefix];
102
+ return prefix;
103
+ }
104
+ /**
105
+ * Infer origin from flat model ID keywords (for providers like Groq
106
+ * that don't use namespaced IDs).
107
+ *
108
+ * Checks keywords in order — put more-specific matches first
109
+ * (e.g. "deepseek" before "llama" for `deepseek-r1-distill-llama-70b`).
110
+ */
111
+ inferOriginFromKeywords(lower, rules, fallback) {
112
+ for (const [keyword, origin] of rules) {
113
+ if (lower.includes(keyword))
114
+ return origin;
115
+ }
116
+ return fallback;
117
+ }
118
+ /** Check if a lowercase model ID looks like an embedding model. */
119
+ looksLikeEmbedding(lower) {
120
+ return lower.includes("embed") || lower.includes("rerank");
121
+ }
122
+ /** Check if a lowercase model ID looks like a vision model. */
123
+ looksLikeVision(lower) {
124
+ return lower.includes("vision") || lower.includes("vlm") || lower.includes("llava") ||
125
+ lower.includes("pixtral") || lower.includes("neva") || lower.includes("fuyu") ||
126
+ lower.includes("cogvlm") || lower.includes("vila");
127
+ }
128
+ /** Check if a lowercase model ID looks like a code model. */
129
+ looksLikeCode(lower) {
130
+ return lower.includes("code") || lower.includes("codestral") ||
131
+ lower.includes("starcoder") || lower.includes("codellama") || lower.includes("coder");
132
+ }
133
+ /** Check if a lowercase model ID looks like an audio/speech model. */
134
+ looksLikeAudio(lower) {
135
+ return lower.includes("whisper") || lower.includes("tts");
136
+ }
137
+ /** Check if ID contains common "reward model" patterns to filter. */
138
+ looksLikeReward(lower) {
139
+ return lower.includes("reward");
140
+ }
141
+ // ---------------------------------------------------------------------------
142
+ // Private
143
+ // ---------------------------------------------------------------------------
144
+ /** Build a ModelCard from a raw API model + classification. */
145
+ toCard(model) {
146
+ const classification = this.classifyModel(model);
147
+ return this.makeCard({
148
+ id: model.id,
149
+ name: model.id,
150
+ provider: this.providerId,
151
+ originProvider: classification.originProvider,
152
+ mode: classification.mode,
153
+ capabilities: classification.capabilities,
154
+ contextWindow: classification.contextWindow ?? model.context_window ?? 0,
155
+ maxOutputTokens: classification.maxOutputTokens ?? model.max_output_tokens ?? 0,
156
+ maxInputTokens: classification.maxInputTokens ?? model.max_input_tokens,
157
+ dimensions: classification.dimensions ?? model.output_vector_size,
158
+ });
159
+ }
160
+ }
161
+ //# sourceMappingURL=openai-compatible.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../src/discovery/openai-compatible.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAqC3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAgB,0BAA2B,SAAQ,cAAc;IACtE;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,UAA4B,EAAE,OAA8B;QAC1E,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,WAAW,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;QACX,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,OAAO,GAA2B;YACvC,aAAa,EAAE,UAAU,MAAM,EAAE;SACjC,CAAC;QAEF,IAAI,QAAQ,GAAwC,IAAI,CAAC;QACzD,IAAI,SAAkB,CAAC;QACvB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAClD,IAAI,CAAC;gBACJ,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAC9B,QAAQ,EACR,OAAO,EACP,SAAS,CACT,CAAC;gBACF,MAAM;YACP,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,SAAS,GAAG,KAAK,CAAC;YACnB,CAAC;QACF,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,YAAY,qBAAqB,CAAC,CAAC;QACrG,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI;aAClB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;aAC9C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACO,kBAAkB;QAC3B,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,YAAY,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACO,eAAe,CAAC,MAA6B;QACtD,OAAO,IAAI,CAAC;IACb,CAAC;IAUD,8EAA8E;IAC9E,6EAA6E;IAC7E,8EAA8E;IAE9E;;;OAGG;IACO,mBAAmB,CAAC,EAAU,EAAE,QAAgB,EAAE,OAAgC;QAC3F,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,QAAQ,KAAK,CAAC,CAAC;YAAE,OAAO,QAAQ,CAAC;QAErC,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QACnD,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACO,uBAAuB,CAAC,KAAa,EAAE,KAAyB,EAAE,QAAgB;QAC3F,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,OAAO,MAAM,CAAC;QAC5C,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,mEAAmE;IACzD,kBAAkB,CAAC,KAAa;QACzC,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,+DAA+D;IACrD,eAAe,CAAC,KAAa;QACtC,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;YAClF,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC7E,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC;IAED,6DAA6D;IACnD,aAAa,CAAC,KAAa;QACpC,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC3D,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxF,CAAC;IAED,sEAAsE;IAC5D,cAAc,CAAC,KAAa;QACrC,OAAO,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,qEAAqE;IAC3D,eAAe,CAAC,KAAa;QACtC,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,8EAA8E;IAC9E,UAAU;IACV,8EAA8E;IAE9E,+DAA+D;IACvD,MAAM,CAAC,KAA4B;QAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,QAAQ,CAAC;YACpB,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,IAAI,EAAE,KAAK,CAAC,EAAE;YACd,QAAQ,EAAE,IAAI,CAAC,UAAU;YACzB,cAAc,EAAE,cAAc,CAAC,cAAc;YAC7C,IAAI,EAAE,cAAc,CAAC,IAAI;YACzB,YAAY,EAAE,cAAc,CAAC,YAAY;YACzC,aAAa,EAAE,cAAc,CAAC,aAAa,IAAI,KAAK,CAAC,cAAc,IAAI,CAAC;YACxE,eAAe,EAAE,cAAc,CAAC,eAAe,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC;YAC/E,cAAc,EAAE,cAAc,CAAC,cAAc,IAAI,KAAK,CAAC,gBAAgB;YACvE,UAAU,EAAE,cAAc,CAAC,UAAU,IAAI,KAAK,CAAC,kBAAkB;SACjE,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * kosha-discovery — OpenAI provider discoverer.
3
+ *
4
+ * Queries the OpenAI `/v1/models` endpoint, filters out irrelevant
5
+ * legacy/fine-tuned models, and maps the rest into {@link ModelCard} objects.
6
+ * @module
7
+ */
8
+ import type { CredentialResult, ModelCard } from "../types.js";
9
+ import { BaseDiscoverer } from "./base.js";
10
+ /**
11
+ * Discovers models available through the OpenAI API.
12
+ *
13
+ * The OpenAI list endpoint returns *every* model the key has access to,
14
+ * including deprecated completions models (babbage, davinci, curie, ada)
15
+ * and fine-tune snapshots. This discoverer filters those out and keeps
16
+ * only chat, embedding, image, and audio models.
17
+ */
18
+ export declare class OpenAIDiscoverer extends BaseDiscoverer {
19
+ readonly providerId = "openai";
20
+ readonly providerName = "OpenAI";
21
+ readonly baseUrl = "https://api.openai.com";
22
+ /**
23
+ * Fetch the full model list from OpenAI, filter, and normalize.
24
+ * @param credential - Must contain an `apiKey` or `accessToken`.
25
+ * @param options - Optional timeout override (default 10 s).
26
+ */
27
+ discover(credential: CredentialResult, options?: {
28
+ timeout?: number;
29
+ }): Promise<ModelCard[]>;
30
+ /**
31
+ * Determine whether a model ID represents a model we want to track.
32
+ *
33
+ * We exclude:
34
+ * - Fine-tune snapshots (contain "ft:" or ":ft-")
35
+ * - Legacy completions-only models (babbage, davinci, curie, ada) which
36
+ * lack chat support and clutter results
37
+ */
38
+ private isRelevantModel;
39
+ /** Check if the model ID belongs to the chat model family. */
40
+ private isChatModel;
41
+ /** Check if the model ID belongs to the embedding family. */
42
+ private isEmbeddingModel;
43
+ /** Check if the model ID belongs to the image generation family (DALL-E). */
44
+ private isImageModel;
45
+ /** Check if the model ID belongs to the audio family (Whisper / TTS). */
46
+ private isAudioModel;
47
+ /** Convert an OpenAI model object into a normalized {@link ModelCard}. */
48
+ private toModelCard;
49
+ /** Map a model ID to its primary {@link ModelMode}. */
50
+ private inferMode;
51
+ /**
52
+ * Infer capability flags from the model ID.
53
+ *
54
+ * Key design decisions:
55
+ * - o-series reasoning models (o1, o3, o4) do NOT get "function_calling"
56
+ * because their reasoning loop does not support tool use in the same way.
57
+ * - GPT-4o / GPT-4 Turbo get "vision" since they accept image inputs.
58
+ * - GPT-4o-mini lacks vision but retains function_calling.
59
+ */
60
+ private inferCapabilities;
61
+ }
62
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/discovery/openai.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAa,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAgB3C;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IACnD,QAAQ,CAAC,UAAU,YAAY;IAC/B,QAAQ,CAAC,YAAY,YAAY;IACjC,QAAQ,CAAC,OAAO,4BAA4B;IAE5C;;;;OAIG;IACG,QAAQ,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAkBlG;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAsBvB,8DAA8D;IAC9D,OAAO,CAAC,WAAW;IAUnB,6DAA6D;IAC7D,OAAO,CAAC,gBAAgB;IAIxB,6EAA6E;IAC7E,OAAO,CAAC,YAAY;IAIpB,yEAAyE;IACzE,OAAO,CAAC,YAAY;IAIpB,0EAA0E;IAC1E,OAAO,CAAC,WAAW;IAcnB,uDAAuD;IACvD,OAAO,CAAC,SAAS;IAOjB;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;CA8CzB"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * kosha-discovery — OpenAI provider discoverer.
3
+ *
4
+ * Queries the OpenAI `/v1/models` endpoint, filters out irrelevant
5
+ * legacy/fine-tuned models, and maps the rest into {@link ModelCard} objects.
6
+ * @module
7
+ */
8
+ import { BaseDiscoverer } from "./base.js";
9
+ /**
10
+ * Discovers models available through the OpenAI API.
11
+ *
12
+ * The OpenAI list endpoint returns *every* model the key has access to,
13
+ * including deprecated completions models (babbage, davinci, curie, ada)
14
+ * and fine-tune snapshots. This discoverer filters those out and keeps
15
+ * only chat, embedding, image, and audio models.
16
+ */
17
+ export class OpenAIDiscoverer extends BaseDiscoverer {
18
+ providerId = "openai";
19
+ providerName = "OpenAI";
20
+ baseUrl = "https://api.openai.com";
21
+ /**
22
+ * Fetch the full model list from OpenAI, filter, and normalize.
23
+ * @param credential - Must contain an `apiKey` or `accessToken`.
24
+ * @param options - Optional timeout override (default 10 s).
25
+ */
26
+ async discover(credential, options) {
27
+ const apiKey = credential.apiKey ?? credential.accessToken;
28
+ if (!apiKey) {
29
+ return [];
30
+ }
31
+ const timeoutMs = this.validateTimeout(options?.timeout);
32
+ const headers = {
33
+ Authorization: `Bearer ${apiKey}`,
34
+ };
35
+ const response = await this.fetchJSON(`${this.baseUrl}/v1/models`, headers, timeoutMs);
36
+ return response.data
37
+ .filter((model) => this.isRelevantModel(model.id))
38
+ .map((model) => this.toModelCard(model));
39
+ }
40
+ /**
41
+ * Determine whether a model ID represents a model we want to track.
42
+ *
43
+ * We exclude:
44
+ * - Fine-tune snapshots (contain "ft:" or ":ft-")
45
+ * - Legacy completions-only models (babbage, davinci, curie, ada) which
46
+ * lack chat support and clutter results
47
+ */
48
+ isRelevantModel(id) {
49
+ const lower = id.toLowerCase();
50
+ // Skip fine-tune snapshots — they are user-specific variants
51
+ if (lower.includes("ft:") || lower.includes(":ft-")) {
52
+ return false;
53
+ }
54
+ // Skip legacy completions-era models that predate the chat API
55
+ if (lower.startsWith("babbage") || lower.startsWith("davinci") || lower.startsWith("curie") || lower.startsWith("ada")) {
56
+ return false;
57
+ }
58
+ // Keep chat, embedding, image, and audio models
59
+ return (this.isChatModel(lower) ||
60
+ this.isEmbeddingModel(lower) ||
61
+ this.isImageModel(lower) ||
62
+ this.isAudioModel(lower));
63
+ }
64
+ /** Check if the model ID belongs to the chat model family. */
65
+ isChatModel(id) {
66
+ return (id.startsWith("gpt-") ||
67
+ id.startsWith("o1") ||
68
+ id.startsWith("o3") ||
69
+ id.startsWith("o4") ||
70
+ id.startsWith("chatgpt-"));
71
+ }
72
+ /** Check if the model ID belongs to the embedding family. */
73
+ isEmbeddingModel(id) {
74
+ return id.includes("embedding");
75
+ }
76
+ /** Check if the model ID belongs to the image generation family (DALL-E). */
77
+ isImageModel(id) {
78
+ return id.includes("dall-e");
79
+ }
80
+ /** Check if the model ID belongs to the audio family (Whisper / TTS). */
81
+ isAudioModel(id) {
82
+ return id.includes("whisper") || id.includes("tts");
83
+ }
84
+ /** Convert an OpenAI model object into a normalized {@link ModelCard}. */
85
+ toModelCard(model) {
86
+ const id = model.id.toLowerCase();
87
+ const mode = this.inferMode(id);
88
+ const capabilities = this.inferCapabilities(id);
89
+ return this.makeCard({
90
+ id: model.id,
91
+ name: model.id,
92
+ provider: this.providerId,
93
+ mode,
94
+ capabilities,
95
+ });
96
+ }
97
+ /** Map a model ID to its primary {@link ModelMode}. */
98
+ inferMode(id) {
99
+ if (this.isEmbeddingModel(id))
100
+ return "embedding";
101
+ if (this.isImageModel(id))
102
+ return "image";
103
+ if (this.isAudioModel(id))
104
+ return "audio";
105
+ return "chat";
106
+ }
107
+ /**
108
+ * Infer capability flags from the model ID.
109
+ *
110
+ * Key design decisions:
111
+ * - o-series reasoning models (o1, o3, o4) do NOT get "function_calling"
112
+ * because their reasoning loop does not support tool use in the same way.
113
+ * - GPT-4o / GPT-4 Turbo get "vision" since they accept image inputs.
114
+ * - GPT-4o-mini lacks vision but retains function_calling.
115
+ */
116
+ inferCapabilities(id) {
117
+ // Embedding models — single capability
118
+ if (this.isEmbeddingModel(id)) {
119
+ return ["embedding"];
120
+ }
121
+ // Image generation models (DALL-E)
122
+ if (this.isImageModel(id)) {
123
+ return ["image_generation"];
124
+ }
125
+ // Audio models — Whisper for STT, TTS for speech synthesis
126
+ if (this.isAudioModel(id)) {
127
+ if (id.includes("whisper"))
128
+ return ["speech_to_text"];
129
+ if (id.includes("tts"))
130
+ return ["text_to_speech"];
131
+ return ["audio"];
132
+ }
133
+ // Reasoning models (o1, o3, o4 series) — no function_calling
134
+ // because their chain-of-thought architecture handles tool use differently
135
+ if (id.startsWith("o1") || id.startsWith("o3") || id.startsWith("o4")) {
136
+ return ["chat", "code", "nlu"];
137
+ }
138
+ // GPT-4o-mini — capable but lacks vision (must be checked before gpt-4o)
139
+ if (id.includes("gpt-4o-mini")) {
140
+ return ["chat", "function_calling", "code", "nlu"];
141
+ }
142
+ // GPT-4o and GPT-4 Turbo — full capabilities including vision
143
+ if (id.includes("gpt-4o") || id.includes("gpt-4-turbo")) {
144
+ return ["chat", "vision", "function_calling", "code", "nlu"];
145
+ }
146
+ // GPT-4 (non-turbo, non-4o)
147
+ if (id.startsWith("gpt-4")) {
148
+ return ["chat", "function_calling", "code", "nlu"];
149
+ }
150
+ // GPT-3.5 and other chat models — basic chat with function calling
151
+ if (id.startsWith("gpt-") || id.startsWith("chatgpt-")) {
152
+ return ["chat", "function_calling", "code"];
153
+ }
154
+ return ["chat"];
155
+ }
156
+ }
157
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/discovery/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * kosha-discovery — OpenRouter aggregator discoverer.
3
+ *
4
+ * OpenRouter is a unified gateway that proxies requests to many upstream
5
+ * providers (OpenAI, Anthropic, Google, Meta, Mistral, etc.). Its model
6
+ * list endpoint returns rich metadata including pricing, context lengths,
7
+ * and architecture info — making it one of the most informative sources.
8
+ * @module
9
+ */
10
+ import type { CredentialResult, ModelCard } from "../types.js";
11
+ import { BaseDiscoverer } from "./base.js";
12
+ /**
13
+ * Discovers models available through the OpenRouter aggregator.
14
+ *
15
+ * OpenRouter acts as a single gateway to dozens of providers. Its model
16
+ * list is publicly accessible (no API key required), though an
17
+ * authenticated request gets higher rate limits.
18
+ */
19
+ export declare class OpenRouterDiscoverer extends BaseDiscoverer {
20
+ readonly providerId = "openrouter";
21
+ readonly providerName = "OpenRouter";
22
+ readonly baseUrl = "https://openrouter.ai";
23
+ /**
24
+ * Fetch the full model catalogue from OpenRouter.
25
+ *
26
+ * @param credential - API key is **optional** for this provider.
27
+ * The endpoint works without auth, just with stricter rate limits.
28
+ * @param options - Optional timeout override (default 15 s — larger because the
29
+ * response contains hundreds of models).
30
+ */
31
+ discover(credential: CredentialResult, options?: {
32
+ timeout?: number;
33
+ }): Promise<ModelCard[]>;
34
+ /**
35
+ * Filter out unavailable models. OpenRouter marks delisted models
36
+ * with `pricing.prompt === "-1"`.
37
+ */
38
+ private isAvailable;
39
+ /** Convert an OpenRouter model object into a normalized {@link ModelCard}. */
40
+ private toModelCard;
41
+ /**
42
+ * Extract the canonical origin-provider slug from an OpenRouter compound
43
+ * model ID of the form `{vendor}/{model-name}`.
44
+ *
45
+ * OpenRouter uses vendor-namespaced IDs (e.g. `anthropic/claude-opus-4-6`,
46
+ * `meta-llama/llama-3-70b`). We take the prefix before the first `/` and
47
+ * normalise it to our canonical slug so that downstream consumers can group
48
+ * models by original creator regardless of which gateway serves them.
49
+ *
50
+ * @param modelId - Raw OpenRouter model ID.
51
+ * @returns Canonical provider slug (e.g. `"anthropic"`, `"meta"`, `"openai"`).
52
+ */
53
+ private extractOriginProvider;
54
+ /** Infer the primary {@link ModelMode} from modality and naming patterns. */
55
+ private inferMode;
56
+ /**
57
+ * Infer capability flags from architecture modality and model ID.
58
+ */
59
+ private inferCapabilities;
60
+ /**
61
+ * Heuristic to identify "modern chat models" that support structured
62
+ * tool use (function calling), code generation, and NLU.
63
+ *
64
+ * We match on known provider/model family prefixes. This is intentionally
65
+ * broad — false positives are benign (extra capability flags), while false
66
+ * negatives would hide useful features.
67
+ */
68
+ private isModernChatModel;
69
+ /**
70
+ * Parse OpenRouter's per-token pricing into our per-million format.
71
+ *
72
+ * OpenRouter returns pricing as **cost per single token** (stringified
73
+ * floats). We multiply by 1,000,000 to convert to our standard
74
+ * per-million-token pricing representation.
75
+ */
76
+ private parsePricing;
77
+ }
78
+ //# sourceMappingURL=openrouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../src/discovery/openrouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAA2B,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAwC3C;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,cAAc;IACvD,QAAQ,CAAC,UAAU,gBAAgB;IACnC,QAAQ,CAAC,YAAY,gBAAgB;IACrC,QAAQ,CAAC,OAAO,2BAA2B;IAE3C;;;;;;;OAOG;IACG,QAAQ,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAsBlG;;;OAGG;IACH,OAAO,CAAC,WAAW;IAInB,8EAA8E;IAC9E,OAAO,CAAC,WAAW;IAmBnB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,qBAAqB;IAyB7B,6EAA6E;IAC7E,OAAO,CAAC,SAAS;IAkBjB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6BzB;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;CAgBpB"}