@probeo/anymodel 0.1.0 → 0.2.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 CHANGED
@@ -49,18 +49,39 @@ for await (const chunk of stream) {
49
49
  }
50
50
  ```
51
51
 
52
+ ## Supported Providers
53
+
54
+ Set the env var and go. Models are auto-discovered from each provider's API.
55
+
56
+ | Provider | Env Var | Example Model |
57
+ |----------|---------|---------------|
58
+ | OpenAI | `OPENAI_API_KEY` | `openai/gpt-4o` |
59
+ | Anthropic | `ANTHROPIC_API_KEY` | `anthropic/claude-sonnet-4-6` |
60
+ | Google | `GOOGLE_API_KEY` | `google/gemini-2.5-pro` |
61
+ | Mistral | `MISTRAL_API_KEY` | `mistral/mistral-large-latest` |
62
+ | Groq | `GROQ_API_KEY` | `groq/llama-3.3-70b-versatile` |
63
+ | DeepSeek | `DEEPSEEK_API_KEY` | `deepseek/deepseek-chat` |
64
+ | xAI | `XAI_API_KEY` | `xai/grok-3` |
65
+ | Together | `TOGETHER_API_KEY` | `together/meta-llama/Llama-3.3-70B-Instruct-Turbo` |
66
+ | Fireworks | `FIREWORKS_API_KEY` | `fireworks/accounts/fireworks/models/llama-v3p3-70b-instruct` |
67
+ | Perplexity | `PERPLEXITY_API_KEY` | `perplexity/sonar-pro` |
68
+ | Ollama | `OLLAMA_BASE_URL` | `ollama/llama3.3` |
69
+
70
+ Ollama runs locally with no API key — just set `OLLAMA_BASE_URL` (defaults to `http://localhost:11434/v1`).
71
+
52
72
  ## Model Naming
53
73
 
54
74
  Models use `provider/model` format:
55
75
 
56
76
  ```
57
77
  anthropic/claude-sonnet-4-6
58
- anthropic/claude-opus-4-6
59
- anthropic/claude-haiku-4-5
60
78
  openai/gpt-4o
61
- openai/o3
62
79
  google/gemini-2.5-pro
63
- google/gemini-2.5-flash
80
+ mistral/mistral-large-latest
81
+ groq/llama-3.3-70b-versatile
82
+ deepseek/deepseek-chat
83
+ xai/grok-3
84
+ ollama/llama3.3
64
85
  ```
65
86
 
66
87
  ## Fallback Routing
package/dist/cli.cjs CHANGED
@@ -623,7 +623,19 @@ function createOpenAIAdapter(apiKey, baseURL) {
623
623
  async listModels() {
624
624
  const res = await makeRequest("/models", void 0, "GET");
625
625
  const data = await res.json();
626
- return (data.data || []).filter((m) => m.id.startsWith("gpt-") || m.id.startsWith("o") || m.id.startsWith("chatgpt-")).map((m) => ({
626
+ return (data.data || []).filter((m) => {
627
+ const id = m.id;
628
+ if (id.includes("embedding")) return false;
629
+ if (id.includes("whisper")) return false;
630
+ if (id.includes("tts")) return false;
631
+ if (id.includes("dall-e")) return false;
632
+ if (id.includes("davinci")) return false;
633
+ if (id.includes("babbage")) return false;
634
+ if (id.includes("moderation")) return false;
635
+ if (id.includes("realtime")) return false;
636
+ if (id.startsWith("ft:")) return false;
637
+ return id.startsWith("gpt-") || id.startsWith("o1") || id.startsWith("o3") || id.startsWith("o4") || id.startsWith("chatgpt-");
638
+ }).map((m) => ({
627
639
  id: `openai/${m.id}`,
628
640
  name: m.id,
629
641
  created: m.created,
@@ -689,10 +701,16 @@ var SUPPORTED_PARAMS2 = /* @__PURE__ */ new Set([
689
701
  "tool_choice",
690
702
  "response_format"
691
703
  ]);
692
- var KNOWN_MODELS = [
693
- { id: "anthropic/claude-opus-4-6", name: "Claude Opus 4.6", created: 0, description: "Most capable model", context_length: 2e5, pricing: { prompt: "0.000005", completion: "0.000025" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 32768, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) },
704
+ var FALLBACK_MODELS = [
705
+ // Claude 4.6
706
+ { id: "anthropic/claude-opus-4-6", name: "Claude Opus 4.6", created: 0, description: "Most capable model", context_length: 2e5, pricing: { prompt: "0.000015", completion: "0.000075" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 32768, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) },
694
707
  { id: "anthropic/claude-sonnet-4-6", name: "Claude Sonnet 4.6", created: 0, description: "Best balance of speed and capability", context_length: 2e5, pricing: { prompt: "0.000003", completion: "0.000015" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 16384, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) },
695
- { id: "anthropic/claude-haiku-4-5", name: "Claude Haiku 4.5", created: 0, description: "Fastest and most compact", context_length: 2e5, pricing: { prompt: "0.000001", completion: "0.000005" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 8192, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) }
708
+ // Claude 4.5
709
+ { id: "anthropic/claude-sonnet-4-5-20251022", name: "Claude Sonnet 4.5", created: 0, description: "Previous generation balanced model", context_length: 2e5, pricing: { prompt: "0.000003", completion: "0.000015" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 16384, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) },
710
+ { id: "anthropic/claude-haiku-4-5", name: "Claude Haiku 4.5", created: 0, description: "Fast and compact", context_length: 2e5, pricing: { prompt: "0.000001", completion: "0.000005" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 8192, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) },
711
+ // Claude 3.5
712
+ { id: "anthropic/claude-3-5-sonnet-20241022", name: "Claude 3.5 Sonnet", created: 0, description: "Legacy balanced model", context_length: 2e5, pricing: { prompt: "0.000003", completion: "0.000015" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 8192, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) },
713
+ { id: "anthropic/claude-3-5-haiku-20241022", name: "Claude 3.5 Haiku", created: 0, description: "Legacy fast model", context_length: 2e5, pricing: { prompt: "0.0000008", completion: "0.000004" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image"], output_modalities: ["text"], tokenizer: "claude" }, top_provider: { context_length: 2e5, max_completion_tokens: 8192, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS2) }
696
714
  ];
697
715
  function createAnthropicAdapter(apiKey) {
698
716
  async function makeRequest(path, body, stream = false) {
@@ -952,7 +970,40 @@ ${body.system}` : jsonInstruction;
952
970
  };
953
971
  },
954
972
  async listModels() {
955
- return KNOWN_MODELS;
973
+ try {
974
+ const res = await fetch(`${ANTHROPIC_API_BASE}/models`, {
975
+ method: "GET",
976
+ headers: {
977
+ "x-api-key": apiKey,
978
+ "anthropic-version": ANTHROPIC_VERSION
979
+ }
980
+ });
981
+ if (!res.ok) return FALLBACK_MODELS;
982
+ const data = await res.json();
983
+ const models = data.data || [];
984
+ return models.filter((m) => m.type === "model").map((m) => ({
985
+ id: `anthropic/${m.id}`,
986
+ name: m.display_name || m.id,
987
+ created: m.created_at ? new Date(m.created_at).getTime() / 1e3 : 0,
988
+ description: m.display_name || "",
989
+ context_length: 2e5,
990
+ pricing: { prompt: "0", completion: "0" },
991
+ architecture: {
992
+ modality: "text+image->text",
993
+ input_modalities: ["text", "image"],
994
+ output_modalities: ["text"],
995
+ tokenizer: "claude"
996
+ },
997
+ top_provider: {
998
+ context_length: 2e5,
999
+ max_completion_tokens: 16384,
1000
+ is_moderated: false
1001
+ },
1002
+ supported_parameters: Array.from(SUPPORTED_PARAMS2)
1003
+ }));
1004
+ } catch {
1005
+ return FALLBACK_MODELS;
1006
+ }
956
1007
  },
957
1008
  supportsParameter(param) {
958
1009
  return SUPPORTED_PARAMS2.has(param);
@@ -990,9 +1041,16 @@ var SUPPORTED_PARAMS3 = /* @__PURE__ */ new Set([
990
1041
  "tool_choice",
991
1042
  "response_format"
992
1043
  ]);
993
- var KNOWN_MODELS2 = [
1044
+ var FALLBACK_MODELS2 = [
1045
+ // Gemini 2.5
994
1046
  { id: "google/gemini-2.5-pro", name: "Gemini 2.5 Pro", created: 0, description: "Most capable Gemini model", context_length: 1048576, pricing: { prompt: "0.00000125", completion: "0.000005" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 1048576, max_completion_tokens: 65536, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) },
995
- { id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash", created: 0, description: "Fast and efficient", context_length: 1048576, pricing: { prompt: "0.00000015", completion: "0.0000006" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 1048576, max_completion_tokens: 65536, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) }
1047
+ { id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash", created: 0, description: "Fast and efficient", context_length: 1048576, pricing: { prompt: "0.00000015", completion: "0.0000006" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 1048576, max_completion_tokens: 65536, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) },
1048
+ // Gemini 2.0
1049
+ { id: "google/gemini-2.0-flash", name: "Gemini 2.0 Flash", created: 0, description: "Fast multimodal model", context_length: 1048576, pricing: { prompt: "0.0000001", completion: "0.0000004" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 1048576, max_completion_tokens: 65536, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) },
1050
+ { id: "google/gemini-2.0-flash-lite", name: "Gemini 2.0 Flash Lite", created: 0, description: "Lightweight and fast", context_length: 1048576, pricing: { prompt: "0.00000005", completion: "0.0000002" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 1048576, max_completion_tokens: 65536, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) },
1051
+ // Gemini 1.5
1052
+ { id: "google/gemini-1.5-pro", name: "Gemini 1.5 Pro", created: 0, description: "Previous generation pro model", context_length: 2097152, pricing: { prompt: "0.00000125", completion: "0.000005" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 2097152, max_completion_tokens: 8192, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) },
1053
+ { id: "google/gemini-1.5-flash", name: "Gemini 1.5 Flash", created: 0, description: "Previous generation flash model", context_length: 1048576, pricing: { prompt: "0.000000075", completion: "0.0000003" }, architecture: { modality: "text+image->text", input_modalities: ["text", "image", "video", "audio"], output_modalities: ["text"], tokenizer: "gemini" }, top_provider: { context_length: 1048576, max_completion_tokens: 8192, is_moderated: false }, supported_parameters: Array.from(SUPPORTED_PARAMS3) }
996
1054
  ];
997
1055
  function createGoogleAdapter(apiKey) {
998
1056
  function getModelEndpoint(model, stream) {
@@ -1194,7 +1252,37 @@ function createGoogleAdapter(apiKey) {
1194
1252
  };
1195
1253
  },
1196
1254
  async listModels() {
1197
- return KNOWN_MODELS2;
1255
+ try {
1256
+ const res = await fetch(`${GEMINI_API_BASE}/models?key=${apiKey}`);
1257
+ if (!res.ok) return FALLBACK_MODELS2;
1258
+ const data = await res.json();
1259
+ const models = data.models || [];
1260
+ return models.filter((m) => m.name?.startsWith("models/gemini-") && m.supportedGenerationMethods?.includes("generateContent")).map((m) => {
1261
+ const modelId = m.name.replace("models/", "");
1262
+ return {
1263
+ id: `google/${modelId}`,
1264
+ name: m.displayName || modelId,
1265
+ created: 0,
1266
+ description: m.description || "",
1267
+ context_length: m.inputTokenLimit || 1048576,
1268
+ pricing: { prompt: "0", completion: "0" },
1269
+ architecture: {
1270
+ modality: "text+image->text",
1271
+ input_modalities: ["text", "image", "video", "audio"],
1272
+ output_modalities: ["text"],
1273
+ tokenizer: "gemini"
1274
+ },
1275
+ top_provider: {
1276
+ context_length: m.inputTokenLimit || 1048576,
1277
+ max_completion_tokens: m.outputTokenLimit || 65536,
1278
+ is_moderated: false
1279
+ },
1280
+ supported_parameters: Array.from(SUPPORTED_PARAMS3)
1281
+ };
1282
+ });
1283
+ } catch {
1284
+ return FALLBACK_MODELS2;
1285
+ }
1198
1286
  },
1199
1287
  supportsParameter(param) {
1200
1288
  return SUPPORTED_PARAMS3.has(param);
@@ -1358,14 +1446,22 @@ function deepMerge(target, source) {
1358
1446
  }
1359
1447
  function envConfig() {
1360
1448
  const config = {};
1361
- if (process.env.ANTHROPIC_API_KEY) {
1362
- config.anthropic = { apiKey: process.env.ANTHROPIC_API_KEY };
1363
- }
1364
- if (process.env.OPENAI_API_KEY) {
1365
- config.openai = { apiKey: process.env.OPENAI_API_KEY };
1366
- }
1367
- if (process.env.GOOGLE_API_KEY) {
1368
- config.google = { apiKey: process.env.GOOGLE_API_KEY };
1449
+ const envMap = [
1450
+ ["openai", "OPENAI_API_KEY"],
1451
+ ["anthropic", "ANTHROPIC_API_KEY"],
1452
+ ["google", "GOOGLE_API_KEY"],
1453
+ ["mistral", "MISTRAL_API_KEY"],
1454
+ ["groq", "GROQ_API_KEY"],
1455
+ ["deepseek", "DEEPSEEK_API_KEY"],
1456
+ ["xai", "XAI_API_KEY"],
1457
+ ["together", "TOGETHER_API_KEY"],
1458
+ ["fireworks", "FIREWORKS_API_KEY"],
1459
+ ["perplexity", "PERPLEXITY_API_KEY"]
1460
+ ];
1461
+ for (const [key, envVar] of envMap) {
1462
+ if (process.env[envVar]) {
1463
+ config[key] = { apiKey: process.env[envVar] };
1464
+ }
1369
1465
  }
1370
1466
  return config;
1371
1467
  }
@@ -1780,21 +1876,42 @@ var AnyModel = class {
1780
1876
  };
1781
1877
  }
1782
1878
  registerProviders() {
1783
- const { anthropic, openai, google } = this.config;
1784
- const anthropicKey = anthropic?.apiKey || process.env.ANTHROPIC_API_KEY;
1785
- const openaiKey = openai?.apiKey || process.env.OPENAI_API_KEY;
1786
- const googleKey = google?.apiKey || process.env.GOOGLE_API_KEY;
1879
+ const config = this.config;
1880
+ const openaiKey = config.openai?.apiKey || process.env.OPENAI_API_KEY;
1787
1881
  if (openaiKey) {
1788
1882
  this.registry.register("openai", createOpenAIAdapter(openaiKey));
1789
1883
  }
1884
+ const anthropicKey = config.anthropic?.apiKey || process.env.ANTHROPIC_API_KEY;
1790
1885
  if (anthropicKey) {
1791
1886
  this.registry.register("anthropic", createAnthropicAdapter(anthropicKey));
1792
1887
  }
1888
+ const googleKey = config.google?.apiKey || process.env.GOOGLE_API_KEY;
1793
1889
  if (googleKey) {
1794
1890
  this.registry.register("google", createGoogleAdapter(googleKey));
1795
1891
  }
1796
- if (this.config.custom) {
1797
- for (const [name, customConfig] of Object.entries(this.config.custom)) {
1892
+ const builtinProviders = [
1893
+ { name: "mistral", baseURL: "https://api.mistral.ai/v1", configKey: "mistral", envVar: "MISTRAL_API_KEY" },
1894
+ { name: "groq", baseURL: "https://api.groq.com/openai/v1", configKey: "groq", envVar: "GROQ_API_KEY" },
1895
+ { name: "deepseek", baseURL: "https://api.deepseek.com", configKey: "deepseek", envVar: "DEEPSEEK_API_KEY" },
1896
+ { name: "xai", baseURL: "https://api.x.ai/v1", configKey: "xai", envVar: "XAI_API_KEY" },
1897
+ { name: "together", baseURL: "https://api.together.xyz/v1", configKey: "together", envVar: "TOGETHER_API_KEY" },
1898
+ { name: "fireworks", baseURL: "https://api.fireworks.ai/inference/v1", configKey: "fireworks", envVar: "FIREWORKS_API_KEY" },
1899
+ { name: "perplexity", baseURL: "https://api.perplexity.ai", configKey: "perplexity", envVar: "PERPLEXITY_API_KEY" }
1900
+ ];
1901
+ for (const { name, baseURL, configKey, envVar } of builtinProviders) {
1902
+ const providerConfig = config[configKey];
1903
+ const key = providerConfig?.apiKey || process.env[envVar];
1904
+ if (key) {
1905
+ this.registry.register(name, createCustomAdapter(name, { baseURL, apiKey: key }));
1906
+ }
1907
+ }
1908
+ const ollamaConfig = config.ollama;
1909
+ const ollamaURL = ollamaConfig?.baseURL || process.env.OLLAMA_BASE_URL || "http://localhost:11434/v1";
1910
+ if (ollamaConfig || process.env.OLLAMA_BASE_URL) {
1911
+ this.registry.register("ollama", createCustomAdapter("ollama", { baseURL: ollamaURL }));
1912
+ }
1913
+ if (config.custom) {
1914
+ for (const [name, customConfig] of Object.entries(config.custom)) {
1798
1915
  this.registry.register(name, createCustomAdapter(name, customConfig));
1799
1916
  }
1800
1917
  }