noosphere 0.2.1 → 0.3.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/dist/index.d.ts CHANGED
@@ -70,6 +70,10 @@ interface NoosphereStream extends AsyncIterable<StreamEvent> {
70
70
  result(): Promise<NoosphereResult>;
71
71
  abort(): void;
72
72
  }
73
+ interface ProviderLogo$1 {
74
+ svg?: string;
75
+ png?: string;
76
+ }
73
77
  interface ModelInfo {
74
78
  id: string;
75
79
  provider: string;
@@ -80,6 +84,7 @@ interface ModelInfo {
80
84
  price: number;
81
85
  unit: string;
82
86
  };
87
+ logo?: ProviderLogo$1;
83
88
  capabilities?: {
84
89
  contextWindow?: number;
85
90
  maxTokens?: number;
@@ -104,6 +109,7 @@ interface ProviderInfo {
104
109
  local: boolean;
105
110
  status: 'online' | 'offline' | 'degraded';
106
111
  modelCount: number;
112
+ logo?: ProviderLogo$1;
107
113
  }
108
114
  interface UsageEvent {
109
115
  modality: Modality;
@@ -254,4 +260,19 @@ declare class NoosphereError extends Error {
254
260
  isRetryable(): boolean;
255
261
  }
256
262
 
257
- export { type BaseOptions, type ChatOptions, type ImageOptions, type LocalServiceConfig, type Modality, type ModelInfo, Noosphere, type NoosphereConfig, NoosphereError, type NoosphereErrorCode, type NoosphereProvider, type NoosphereResult, type NoosphereStream, type ProviderInfo, type SpeakOptions, type StreamEvent, type SyncResult, type UsageEvent, type UsageQueryOptions, type UsageSummary, type VideoOptions };
263
+ interface ProviderLogo {
264
+ svg?: string;
265
+ png?: string;
266
+ }
267
+ /**
268
+ * Known provider logos from official brand assets and CDNs.
269
+ * Keys match provider IDs used throughout noosphere.
270
+ */
271
+ declare const PROVIDER_LOGOS: Record<string, ProviderLogo>;
272
+ /**
273
+ * Get logo for a provider by its ID.
274
+ * Tries exact match first, then case-insensitive partial match.
275
+ */
276
+ declare function getProviderLogo(providerId: string | undefined | null): ProviderLogo | undefined;
277
+
278
+ export { type BaseOptions, type ChatOptions, type ImageOptions, type LocalServiceConfig, type Modality, type ModelInfo, Noosphere, type NoosphereConfig, NoosphereError, type NoosphereErrorCode, type NoosphereProvider, type NoosphereResult, type NoosphereStream, PROVIDER_LOGOS, type ProviderInfo, type ProviderLogo$1 as ProviderLogo, type SpeakOptions, type StreamEvent, type SyncResult, type UsageEvent, type UsageQueryOptions, type UsageSummary, type VideoOptions, getProviderLogo };
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/errors.ts
2
9
  var RETRYABLE_CODES = /* @__PURE__ */ new Set([
3
10
  "PROVIDER_UNAVAILABLE",
@@ -26,6 +33,16 @@ var NoosphereError = class extends Error {
26
33
  };
27
34
 
28
35
  // src/config.ts
36
+ var _envLoaded = false;
37
+ function loadEnv() {
38
+ if (_envLoaded) return;
39
+ _envLoaded = true;
40
+ try {
41
+ const dotenvx = __require("@dotenvx/dotenvx");
42
+ dotenvx.config({ quiet: true });
43
+ } catch {
44
+ }
45
+ }
29
46
  var ENV_KEY_MAP = {
30
47
  openai: "OPENAI_API_KEY",
31
48
  anthropic: "ANTHROPIC_API_KEY",
@@ -49,6 +66,7 @@ var DEFAULT_RETRYABLE = [
49
66
  "TIMEOUT"
50
67
  ];
51
68
  function resolveConfig(input) {
69
+ loadEnv();
52
70
  const keys = {};
53
71
  for (const [name, envVar] of Object.entries(ENV_KEY_MAP)) {
54
72
  keys[name] = input.keys?.[name] ?? process.env[envVar];
@@ -90,6 +108,132 @@ function resolveConfig(input) {
90
108
  };
91
109
  }
92
110
 
111
+ // src/logos.ts
112
+ var PROVIDER_LOGOS = {
113
+ // --- Cloud LLM Providers ---
114
+ openai: {
115
+ svg: "https://cdn.simpleicons.org/openai",
116
+ png: "https://cdn.brandfetch.io/idR3duQxYl/w/512/h/512/theme/dark/icon.png"
117
+ },
118
+ anthropic: {
119
+ svg: "https://cdn.simpleicons.org/anthropic",
120
+ png: "https://cdn.brandfetch.io/id2S-kXbuM/w/512/h/512/theme/dark/icon.png"
121
+ },
122
+ google: {
123
+ svg: "https://cdn.simpleicons.org/google",
124
+ png: "https://cdn.brandfetch.io/id6O2oGzv-/w/512/h/512/theme/dark/icon.png"
125
+ },
126
+ groq: {
127
+ svg: "https://cdn.simpleicons.org/groq",
128
+ png: "https://cdn.brandfetch.io/idTEBPz5KO/w/512/h/512/theme/dark/icon.png"
129
+ },
130
+ mistral: {
131
+ svg: "https://cdn.simpleicons.org/mistral",
132
+ png: "https://cdn.brandfetch.io/idnBOFq5eF/w/512/h/512/theme/dark/icon.png"
133
+ },
134
+ xai: {
135
+ svg: "https://cdn.simpleicons.org/x",
136
+ png: "https://cdn.brandfetch.io/idS5WhqBbM/w/512/h/512/theme/dark/icon.png"
137
+ },
138
+ openrouter: {
139
+ svg: "https://openrouter.ai/favicon.svg",
140
+ png: "https://openrouter.ai/favicon.png"
141
+ },
142
+ cerebras: {
143
+ svg: "https://cdn.simpleicons.org/cerebras",
144
+ png: "https://cdn.brandfetch.io/idGa4PRFP0/w/512/h/512/theme/dark/icon.png"
145
+ },
146
+ // --- Media Providers ---
147
+ fal: {
148
+ svg: "https://fal.ai/favicon.svg",
149
+ png: "https://fal.ai/favicon.png"
150
+ },
151
+ huggingface: {
152
+ svg: "https://cdn.simpleicons.org/huggingface",
153
+ png: "https://cdn.brandfetch.io/idnrPPHe87/w/512/h/512/theme/dark/icon.png"
154
+ },
155
+ // --- Local Providers ---
156
+ comfyui: {
157
+ svg: "https://raw.githubusercontent.com/comfyanonymous/ComfyUI/master/web/assets/icon.svg",
158
+ png: "https://raw.githubusercontent.com/comfyanonymous/ComfyUI/master/web/assets/icon.png"
159
+ },
160
+ piper: {
161
+ png: "https://raw.githubusercontent.com/rhasspy/piper/master/logo.png"
162
+ },
163
+ kokoro: {
164
+ png: "https://raw.githubusercontent.com/hexgrad/kokoro/main/assets/icon.png"
165
+ },
166
+ ollama: {
167
+ svg: "https://cdn.simpleicons.org/ollama",
168
+ png: "https://cdn.brandfetch.io/idtesMoSFj/w/512/h/512/theme/dark/icon.png"
169
+ },
170
+ // --- Model Org Providers (from OpenRouter model prefixes) ---
171
+ meta: {
172
+ svg: "https://cdn.simpleicons.org/meta",
173
+ png: "https://cdn.brandfetch.io/idmKk_rq7Y/w/512/h/512/theme/dark/icon.png"
174
+ },
175
+ deepseek: {
176
+ png: "https://cdn.brandfetch.io/id1BWKUVWI/w/512/h/512/theme/dark/icon.png"
177
+ },
178
+ microsoft: {
179
+ svg: "https://cdn.simpleicons.org/microsoft",
180
+ png: "https://cdn.brandfetch.io/idchmboHEZ/w/512/h/512/theme/dark/icon.png"
181
+ },
182
+ nvidia: {
183
+ svg: "https://cdn.simpleicons.org/nvidia",
184
+ png: "https://cdn.brandfetch.io/id1JcGHuZN/w/512/h/512/theme/dark/icon.png"
185
+ },
186
+ qwen: {
187
+ png: "https://img.alicdn.com/imgextra/i1/O1CN01BUp2gU1sRZigvazUo_!!6000000005764-2-tps-228-228.png"
188
+ },
189
+ cohere: {
190
+ svg: "https://cdn.simpleicons.org/cohere",
191
+ png: "https://cdn.brandfetch.io/idiDnz1fvB/w/512/h/512/theme/dark/icon.png"
192
+ },
193
+ perplexity: {
194
+ svg: "https://cdn.simpleicons.org/perplexity",
195
+ png: "https://cdn.brandfetch.io/idwWX3Neii/w/512/h/512/theme/dark/icon.png"
196
+ },
197
+ amazon: {
198
+ svg: "https://cdn.simpleicons.org/amazonaws",
199
+ png: "https://cdn.brandfetch.io/idawORoPJZ/w/512/h/512/theme/dark/icon.png"
200
+ },
201
+ // --- HuggingFace Inference Providers ---
202
+ "hf-inference": {
203
+ svg: "https://cdn.simpleicons.org/huggingface",
204
+ png: "https://cdn.brandfetch.io/idnrPPHe87/w/512/h/512/theme/dark/icon.png"
205
+ },
206
+ "sambanova": {
207
+ png: "https://cdn.brandfetch.io/id__2e5yMY/w/512/h/512/theme/dark/icon.png"
208
+ },
209
+ "together": {
210
+ svg: "https://cdn.simpleicons.org/togetherai",
211
+ png: "https://cdn.brandfetch.io/idH5EoFVaH/w/512/h/512/theme/dark/icon.png"
212
+ },
213
+ "fireworks-ai": {
214
+ png: "https://cdn.brandfetch.io/idj1VQ2O4C/w/512/h/512/theme/dark/icon.png"
215
+ },
216
+ "replicate": {
217
+ svg: "https://cdn.simpleicons.org/replicate",
218
+ png: "https://cdn.brandfetch.io/idWKE4rRaH/w/512/h/512/theme/dark/icon.png"
219
+ },
220
+ "nebius": {
221
+ png: "https://cdn.brandfetch.io/idiUqSQ52b/w/512/h/512/theme/dark/icon.png"
222
+ },
223
+ "novita": {
224
+ png: "https://novita.ai/favicon.png"
225
+ }
226
+ };
227
+ function getProviderLogo(providerId) {
228
+ if (!providerId) return void 0;
229
+ if (PROVIDER_LOGOS[providerId]) return PROVIDER_LOGOS[providerId];
230
+ const normalized = providerId.toLowerCase().replace(/[-_\s]/g, "");
231
+ for (const [key, logo] of Object.entries(PROVIDER_LOGOS)) {
232
+ if (key.replace(/[-_\s]/g, "") === normalized) return logo;
233
+ }
234
+ return void 0;
235
+ }
236
+
93
237
  // src/registry.ts
94
238
  var Registry = class {
95
239
  providers = /* @__PURE__ */ new Map();
@@ -193,7 +337,8 @@ var Registry = class {
193
337
  local: provider.isLocal,
194
338
  status: "online",
195
339
  // ping-based status is set externally
196
- modelCount: cached?.models.length ?? 0
340
+ modelCount: cached?.models.length ?? 0,
341
+ logo: getProviderLogo(provider.id)
197
342
  });
198
343
  }
199
344
  return infos;
@@ -252,7 +397,6 @@ var UsageTracker = class {
252
397
  // src/providers/pi-ai.ts
253
398
  import { getModels, getProviders, complete, stream, setApiKey } from "@mariozechner/pi-ai";
254
399
  var KNOWN_PROVIDERS = ["anthropic", "google", "openai", "xai", "groq", "cerebras", "openrouter", "zai"];
255
- var LOCAL_PROVIDERS = /* @__PURE__ */ new Set(["ollama"]);
256
400
  var FETCH_TIMEOUT_MS = 8e3;
257
401
  var OPENAI_CHAT_PREFIXES = ["gpt-", "o1", "o3", "o4", "chatgpt-", "codex-"];
258
402
  var OPENAI_REASONING_PREFIXES = ["o1", "o3", "o4"];
@@ -393,35 +537,9 @@ var PiAiProvider = class {
393
537
  if (modality && modality !== "llm") return [];
394
538
  await this.ensureDynamicModels();
395
539
  const models = [];
396
- const seenIds = /* @__PURE__ */ new Set();
397
- for (const provider of KNOWN_PROVIDERS) {
398
- try {
399
- const providerModels = getModels(provider);
400
- for (const m of providerModels) {
401
- seenIds.add(m.id);
402
- models.push({
403
- id: m.id,
404
- provider: "pi-ai",
405
- name: m.name || m.id,
406
- modality: "llm",
407
- local: LOCAL_PROVIDERS.has(String(m.provider)),
408
- cost: {
409
- price: m.cost.input ?? 0,
410
- unit: m.cost.input > 0 ? "per_1m_tokens" : "free"
411
- },
412
- capabilities: {
413
- contextWindow: m.contextWindow,
414
- maxTokens: m.maxTokens,
415
- supportsVision: m.input.includes("image"),
416
- supportsStreaming: true
417
- }
418
- });
419
- }
420
- } catch {
421
- }
422
- }
423
- for (const [id, m] of this.dynamicModels) {
424
- if (seenIds.has(id)) continue;
540
+ for (const [, m] of this.dynamicModels) {
541
+ const providerName = String(m.provider);
542
+ const logoProvider = this.inferLogoProvider(m.id, providerName);
425
543
  models.push({
426
544
  id: m.id,
427
545
  provider: "pi-ai",
@@ -432,6 +550,7 @@ var PiAiProvider = class {
432
550
  price: m.cost.input ?? 0,
433
551
  unit: m.cost.input > 0 ? "per_1m_tokens" : "free"
434
552
  },
553
+ logo: getProviderLogo(logoProvider),
435
554
  capabilities: {
436
555
  contextWindow: m.contextWindow,
437
556
  maxTokens: m.maxTokens,
@@ -556,24 +675,15 @@ var PiAiProvider = class {
556
675
  async ensureDynamicModels() {
557
676
  if (this.dynamicModelsFetched) return;
558
677
  this.dynamicModelsFetched = true;
559
- const staticIds = /* @__PURE__ */ new Set();
560
- for (const provider of KNOWN_PROVIDERS) {
561
- try {
562
- for (const m of getModels(provider)) {
563
- staticIds.add(m.id);
564
- }
565
- } catch {
566
- }
567
- }
568
678
  const fetchPromises = [];
569
679
  for (const [providerKey, configFactory] of Object.entries(PROVIDER_APIS)) {
570
680
  const apiKey = this.keys[providerKey];
571
681
  if (!apiKey) continue;
572
- fetchPromises.push(this.fetchProviderModels(configFactory(apiKey), apiKey, staticIds));
682
+ fetchPromises.push(this.fetchProviderModels(configFactory(apiKey), apiKey));
573
683
  }
574
684
  await Promise.allSettled(fetchPromises);
575
685
  }
576
- async fetchProviderModels(config, apiKey, staticIds) {
686
+ async fetchProviderModels(config, apiKey) {
577
687
  try {
578
688
  const controller = new AbortController();
579
689
  const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
@@ -586,11 +696,11 @@ var PiAiProvider = class {
586
696
  if (!res.ok) return;
587
697
  const data = await res.json();
588
698
  const entries = config.extractEntries(data);
589
- const templateModel = this.findStaticTemplate(config.providerName);
699
+ const staticTemplate = this.findStaticTemplate(config.providerName);
590
700
  for (const entry of entries) {
591
701
  const id = entry.id;
592
702
  if (!config.filterChat(id)) continue;
593
- if (staticIds.has(id)) continue;
703
+ const staticMatch = this.findStaticModel(config.providerName, id);
594
704
  this.dynamicModels.set(id, {
595
705
  id,
596
706
  name: entry.name ?? id,
@@ -598,10 +708,10 @@ var PiAiProvider = class {
598
708
  provider: config.providerName,
599
709
  baseUrl: config.piBaseUrl,
600
710
  reasoning: config.isReasoning(id),
601
- input: ["text", "image"],
602
- cost: templateModel?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
603
- contextWindow: entry.contextWindow ?? templateModel?.contextWindow ?? 128e3,
604
- maxTokens: entry.maxTokens ?? templateModel?.maxTokens ?? 16384
711
+ input: staticMatch?.input ?? ["text", "image"],
712
+ cost: staticMatch?.cost ?? staticTemplate?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
713
+ contextWindow: entry.contextWindow ?? staticMatch?.contextWindow ?? staticTemplate?.contextWindow ?? 128e3,
714
+ maxTokens: entry.maxTokens ?? staticMatch?.maxTokens ?? staticTemplate?.maxTokens ?? 16384
605
715
  });
606
716
  }
607
717
  } finally {
@@ -618,25 +728,75 @@ var PiAiProvider = class {
618
728
  return null;
619
729
  }
620
730
  }
731
+ findStaticModel(providerName, modelId) {
732
+ try {
733
+ const models = getModels(providerName);
734
+ return models.find((m) => m.id === modelId) ?? null;
735
+ } catch {
736
+ return null;
737
+ }
738
+ }
621
739
  /** Force re-fetch of dynamic models from provider APIs */
622
740
  async refreshDynamicModels() {
623
741
  this.dynamicModelsFetched = false;
624
742
  this.dynamicModels.clear();
625
743
  await this.ensureDynamicModels();
626
744
  }
745
+ /**
746
+ * Infer the real provider from model ID for logo resolution.
747
+ * e.g. "x-ai/grok-4" → "xai", "anthropic/claude-4" → "anthropic"
748
+ */
749
+ inferLogoProvider(modelId, fallback) {
750
+ const MODEL_PREFIX_TO_PROVIDER = {
751
+ "openai/": "openai",
752
+ "gpt-": "openai",
753
+ "o1-": "openai",
754
+ "o3-": "openai",
755
+ "o4-": "openai",
756
+ "chatgpt-": "openai",
757
+ "anthropic/": "anthropic",
758
+ "claude-": "anthropic",
759
+ "google/": "google",
760
+ "gemini-": "google",
761
+ "gemma-": "google",
762
+ "x-ai/": "xai",
763
+ "grok-": "xai",
764
+ "meta-llama/": "meta",
765
+ "mistralai/": "mistral",
766
+ "mistral-": "mistral",
767
+ "deepseek/": "deepseek",
768
+ "microsoft/": "microsoft",
769
+ "nvidia/": "nvidia",
770
+ "qwen/": "qwen",
771
+ "cohere/": "cohere",
772
+ "perplexity/": "perplexity",
773
+ "amazon/": "amazon"
774
+ };
775
+ const lower = modelId.toLowerCase();
776
+ for (const [prefix, provider] of Object.entries(MODEL_PREFIX_TO_PROVIDER)) {
777
+ if (lower.startsWith(prefix)) return provider;
778
+ }
779
+ return fallback;
780
+ }
627
781
  findModel(modelId) {
782
+ if (modelId) {
783
+ const dynamic = this.dynamicModels.get(modelId);
784
+ if (dynamic) return { model: dynamic, provider: String(dynamic.provider) };
785
+ }
786
+ if (!modelId) {
787
+ const first = this.dynamicModels.values().next();
788
+ if (!first.done && first.value) {
789
+ return { model: first.value, provider: String(first.value.provider) };
790
+ }
791
+ }
628
792
  for (const provider of KNOWN_PROVIDERS) {
629
793
  try {
630
794
  const models = getModels(provider);
631
- const found = modelId ? models.find((m) => m.id === modelId) : models[0];
795
+ const found = modelId ? models.find((m) => m.id === modelId) : void 0;
632
796
  if (found) return { model: found, provider };
633
797
  } catch {
634
798
  }
635
799
  }
636
- if (modelId) {
637
- const dynamic = this.dynamicModels.get(modelId);
638
- if (dynamic) return { model: dynamic, provider: String(dynamic.provider) };
639
- }
640
800
  return { model: null, provider: null };
641
801
  }
642
802
  };
@@ -677,7 +837,8 @@ var FalProvider = class {
677
837
  name: entry.modelId.replace("fal-ai/", ""),
678
838
  modality: inferredModality,
679
839
  local: false,
680
- cost: { price: entry.price, unit: entry.unit }
840
+ cost: { price: entry.price, unit: entry.unit },
841
+ logo: getProviderLogo("fal")
681
842
  });
682
843
  }
683
844
  return models;
@@ -830,6 +991,7 @@ var ComfyUIProvider = class {
830
991
  const res = await fetch(`${this.baseUrl}/object_info`);
831
992
  if (!res.ok) return [];
832
993
  const models = [];
994
+ const logo = getProviderLogo("comfyui");
833
995
  if (!modality || modality === "image") {
834
996
  models.push({
835
997
  id: "comfyui-txt2img",
@@ -838,6 +1000,7 @@ var ComfyUIProvider = class {
838
1000
  modality: "image",
839
1001
  local: true,
840
1002
  cost: { price: 0, unit: "free" },
1003
+ logo,
841
1004
  capabilities: { maxWidth: 2048, maxHeight: 2048, supportsNegativePrompt: true }
842
1005
  });
843
1006
  }
@@ -849,6 +1012,7 @@ var ComfyUIProvider = class {
849
1012
  modality: "video",
850
1013
  local: true,
851
1014
  cost: { price: 0, unit: "free" },
1015
+ logo,
852
1016
  capabilities: { maxDuration: 10, supportsImageToVideo: true }
853
1017
  });
854
1018
  }
@@ -960,6 +1124,7 @@ var LocalTTSProvider = class {
960
1124
  voices = data.data ?? [];
961
1125
  }
962
1126
  }
1127
+ const logo = getProviderLogo(this.id);
963
1128
  return voices.map((v) => ({
964
1129
  id: v.id,
965
1130
  provider: this.id,
@@ -967,6 +1132,7 @@ var LocalTTSProvider = class {
967
1132
  modality: "tts",
968
1133
  local: true,
969
1134
  cost: { price: 0, unit: "free" },
1135
+ logo,
970
1136
  capabilities: { voices: voices.map((vv) => vv.id) }
971
1137
  }));
972
1138
  } catch {
@@ -1017,11 +1183,6 @@ var PIPELINE_TAG_MAP = {
1017
1183
  "text-to-image": { modality: "image", limit: 50 },
1018
1184
  "text-to-speech": { modality: "tts", limit: 30 }
1019
1185
  };
1020
- var DEFAULT_MODELS = [
1021
- { id: "stabilityai/stable-diffusion-xl-base-1.0", provider: "huggingface", name: "SDXL Base", modality: "image", local: false, cost: { price: 0, unit: "free" } },
1022
- { id: "facebook/mms-tts-eng", provider: "huggingface", name: "MMS TTS English", modality: "tts", local: false, cost: { price: 0, unit: "free" } },
1023
- { id: "meta-llama/Llama-3.1-8B-Instruct", provider: "huggingface", name: "Llama 3.1 8B", modality: "llm", local: false, cost: { price: 0, unit: "free" } }
1024
- ];
1025
1186
  var HuggingFaceProvider = class {
1026
1187
  id = "huggingface";
1027
1188
  name = "HuggingFace Inference";
@@ -1041,17 +1202,13 @@ var HuggingFaceProvider = class {
1041
1202
  if (!this.dynamicModels) {
1042
1203
  await this.fetchHubModels();
1043
1204
  }
1044
- const all = this.dynamicModels ?? DEFAULT_MODELS;
1205
+ const all = this.dynamicModels ?? [];
1045
1206
  if (modality) return all.filter((m) => m.modality === modality);
1046
1207
  return all;
1047
1208
  }
1048
1209
  async fetchHubModels() {
1049
1210
  const seenIds = /* @__PURE__ */ new Set();
1050
1211
  const models = [];
1051
- for (const d of DEFAULT_MODELS) {
1052
- seenIds.add(d.id);
1053
- models.push(d);
1054
- }
1055
1212
  const fetches = Object.entries(PIPELINE_TAG_MAP).map(
1056
1213
  ([tag, { modality, limit }]) => this.fetchByPipelineTag(tag, modality, limit)
1057
1214
  );
@@ -1086,7 +1243,13 @@ var HuggingFaceProvider = class {
1086
1243
  const data = await res.json();
1087
1244
  return data.filter((entry) => entry.id || entry.modelId).map((entry) => {
1088
1245
  const id = entry.id ?? entry.modelId;
1089
- const providers = (entry.inferenceProviderMapping ?? []).filter((p) => p.status === "live").map((p) => p.provider);
1246
+ const liveProviders = (entry.inferenceProviderMapping ?? []).filter((p) => p.status === "live");
1247
+ const providers = liveProviders.map((p) => p.provider);
1248
+ const inferenceProviderLogos = {};
1249
+ for (const p of liveProviders) {
1250
+ const pLogo = getProviderLogo(p.provider);
1251
+ if (pLogo) inferenceProviderLogos[p.provider] = pLogo;
1252
+ }
1090
1253
  const pricingProvider = (entry.inferenceProviderMapping ?? []).find((p) => p.providerDetails?.pricing);
1091
1254
  const pricing = pricingProvider?.providerDetails?.pricing;
1092
1255
  const contextLength = (entry.inferenceProviderMapping ?? []).find((p) => p.providerDetails?.context_length)?.providerDetails?.context_length;
@@ -1100,12 +1263,14 @@ var HuggingFaceProvider = class {
1100
1263
  price: pricing?.input ?? 0,
1101
1264
  unit: pricing ? "per_1m_tokens" : "free"
1102
1265
  },
1266
+ logo: getProviderLogo("huggingface"),
1103
1267
  capabilities: {
1104
1268
  ...modality === "llm" ? {
1105
1269
  contextWindow: contextLength,
1106
1270
  supportsStreaming: true
1107
1271
  } : {},
1108
- ...providers.length > 0 ? { inferenceProviders: providers } : {}
1272
+ ...providers.length > 0 ? { inferenceProviders: providers } : {},
1273
+ ...Object.keys(inferenceProviderLogos).length > 0 ? { inferenceProviderLogos } : {}
1109
1274
  }
1110
1275
  };
1111
1276
  });
@@ -1556,6 +1721,8 @@ var Noosphere = class {
1556
1721
  };
1557
1722
  export {
1558
1723
  Noosphere,
1559
- NoosphereError
1724
+ NoosphereError,
1725
+ PROVIDER_LOGOS,
1726
+ getProviderLogo
1560
1727
  };
1561
1728
  //# sourceMappingURL=index.js.map