@cosmicstack/mercury-agent 1.1.3 → 1.1.4

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.js CHANGED
@@ -91,6 +91,13 @@ function getDefaultConfig() {
91
91
  model: getEnv("OLLAMA_LOCAL_MODEL", "gpt-oss:20b"),
92
92
  enabled: getEnvBool("OLLAMA_LOCAL_ENABLED", false)
93
93
  },
94
+ openaiCompat: {
95
+ name: "openaiCompat",
96
+ apiKey: getEnv("OPENAI_COMPAT_API_KEY", ""),
97
+ baseUrl: getEnv("OPENAI_COMPAT_BASE_URL", ""),
98
+ model: getEnv("OPENAI_COMPAT_MODEL", ""),
99
+ enabled: getEnvBool("OPENAI_COMPAT_ENABLED", false)
100
+ },
94
101
  mimo: {
95
102
  name: "mimo",
96
103
  apiKey: getEnv("MIMO_API_KEY", ""),
@@ -194,6 +201,9 @@ function isProviderConfigured(provider) {
194
201
  if (provider.name === "ollamaCloud") {
195
202
  return provider.apiKey.length > 0 && provider.baseUrl.length > 0;
196
203
  }
204
+ if (provider.name === "openaiCompat") {
205
+ return provider.baseUrl.length > 0 && provider.model.length > 0;
206
+ }
197
207
  return provider.apiKey.length > 0;
198
208
  }
199
209
  function getTelegramApprovedUsers(config) {
@@ -1548,7 +1558,7 @@ var OpenAICompatProvider = class extends BaseProvider {
1548
1558
  this.name = config.name;
1549
1559
  this.model = config.model;
1550
1560
  this.client = createOpenAI({
1551
- apiKey: config.apiKey,
1561
+ apiKey: config.apiKey || "no-key",
1552
1562
  baseURL: config.baseUrl
1553
1563
  });
1554
1564
  this.modelInstance = useChatApi ? this.client.chat(config.model) : this.client(config.model);
@@ -1749,6 +1759,7 @@ var ProviderRegistry = class {
1749
1759
  config.providers.grok,
1750
1760
  config.providers.ollamaCloud,
1751
1761
  config.providers.ollamaLocal,
1762
+ config.providers.openaiCompat,
1752
1763
  config.providers.mimo,
1753
1764
  config.providers.mimoTokenPlan
1754
1765
  ];
@@ -1764,6 +1775,8 @@ var ProviderRegistry = class {
1764
1775
  provider = new OllamaProvider(pc);
1765
1776
  } else if (pc.name === "ollamaCloud") {
1766
1777
  provider = new OpenAICompatProvider(pc, { useChatApi: true });
1778
+ } else if (pc.name === "openaiCompat") {
1779
+ provider = new OpenAICompatProvider(pc, { useChatApi: true });
1767
1780
  } else if (pc.name === "mimo" || pc.name === "mimoTokenPlan") {
1768
1781
  provider = new MiMoProvider(pc);
1769
1782
  } else {
@@ -8170,6 +8183,7 @@ var MIMO_PREFERRED_MODELS = [
8170
8183
  "mimo-v2-flash"
8171
8184
  ];
8172
8185
  var MIMO_TOKEN_PLAN_PREFERRED_MODELS = MIMO_PREFERRED_MODELS;
8186
+ var OPENAI_COMPAT_PREFERRED_MODELS = [];
8173
8187
  var ProviderModelFetchError = class extends Error {
8174
8188
  constructor(message) {
8175
8189
  super(message);
@@ -8225,6 +8239,7 @@ function chooseRecommendedModel(provider, models, currentModel) {
8225
8239
  grok: GROK_PREFERRED_MODELS,
8226
8240
  ollamaCloud: OLLAMA_CLOUD_PREFERRED_MODELS,
8227
8241
  ollamaLocal: OLLAMA_LOCAL_PREFERRED_MODELS,
8242
+ openaiCompat: OPENAI_COMPAT_PREFERRED_MODELS,
8228
8243
  mimo: MIMO_PREFERRED_MODELS,
8229
8244
  mimoTokenPlan: MIMO_TOKEN_PLAN_PREFERRED_MODELS
8230
8245
  };
@@ -8251,6 +8266,7 @@ function buildModelCatalog(provider, models, currentModel) {
8251
8266
  grok: GROK_PREFERRED_MODELS,
8252
8267
  ollamaCloud: OLLAMA_CLOUD_PREFERRED_MODELS,
8253
8268
  ollamaLocal: OLLAMA_LOCAL_PREFERRED_MODELS,
8269
+ openaiCompat: OPENAI_COMPAT_PREFERRED_MODELS,
8254
8270
  mimo: MIMO_PREFERRED_MODELS,
8255
8271
  mimoTokenPlan: MIMO_TOKEN_PLAN_PREFERRED_MODELS
8256
8272
  };
@@ -8262,19 +8278,32 @@ function buildModelCatalog(provider, models, currentModel) {
8262
8278
  };
8263
8279
  }
8264
8280
  async function fetchOpenAICompatModels(provider, config) {
8281
+ const headers = {};
8282
+ if (config.apiKey) {
8283
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
8284
+ }
8285
+ let errorMessage;
8286
+ if (provider === "grok") {
8287
+ errorMessage = "Mercury could not fetch models for this Grok key. Please re-enter it.";
8288
+ } else if (provider === "deepseek") {
8289
+ errorMessage = "Mercury could not fetch models for this DeepSeek key. Please re-enter it.";
8290
+ } else if (provider === "openaiCompat") {
8291
+ errorMessage = "Mercury could not fetch models from this server. Please check the base URL and try again.";
8292
+ } else {
8293
+ errorMessage = "Mercury could not fetch models for this OpenAI key. Please re-enter it.";
8294
+ }
8265
8295
  const data = await fetchJson(
8266
8296
  `${trimTrailingSlash(config.baseUrl)}/models`,
8267
- {
8268
- headers: {
8269
- Authorization: `Bearer ${config.apiKey}`
8270
- }
8271
- },
8272
- `Mercury could not fetch models for this ${provider === "grok" ? "Grok" : provider === "deepseek" ? "DeepSeek" : "OpenAI"} key. Please re-enter it.`
8297
+ { headers },
8298
+ errorMessage
8273
8299
  );
8274
8300
  const ids = (data.data ?? []).map((model) => model.id?.trim() ?? "").filter((id) => {
8275
8301
  if (provider === "deepseek") {
8276
8302
  return id.startsWith("deepseek-");
8277
8303
  }
8304
+ if (provider === "openaiCompat") {
8305
+ return id.length > 0;
8306
+ }
8278
8307
  return isOpenAIChatModel(id);
8279
8308
  });
8280
8309
  return buildModelCatalog(provider, ids, config.model);
@@ -8373,6 +8402,9 @@ async function fetchProviderModelCatalog(provider, config) {
8373
8402
  if (provider === "ollamaLocal") {
8374
8403
  return fetchOllamaLocalModels(config);
8375
8404
  }
8405
+ if (provider === "openaiCompat") {
8406
+ return fetchOpenAICompatModels(provider, config);
8407
+ }
8376
8408
  if (provider === "mimo") {
8377
8409
  return fetchMiMoModels(config);
8378
8410
  }
@@ -8437,6 +8469,7 @@ var PROVIDER_OPTIONS = [
8437
8469
  { key: "grok", label: "Grok (xAI)" },
8438
8470
  { key: "ollamaCloud", label: "Ollama Cloud" },
8439
8471
  { key: "ollamaLocal", label: "Ollama Local" },
8472
+ { key: "openaiCompat", label: "OpenAI Compilations" },
8440
8473
  { key: "mimo", label: "MiMo (Xiaomi)" },
8441
8474
  { key: "mimoTokenPlan", label: "MiMo Token Plan (Xiaomi)" }
8442
8475
  ];
@@ -8662,6 +8695,40 @@ async function promptOllamaLocalModelSelection(config) {
8662
8695
  }
8663
8696
  }
8664
8697
  }
8698
+ async function promptOpenAICompatSetup(config, isReconfig) {
8699
+ const existingConfig = config.providers.openaiCompat;
8700
+ const baseUrl = await promptValidatedValue(
8701
+ chalk7.white(` Server base URL${isReconfig && existingConfig.baseUrl ? ` [${existingConfig.baseUrl}]` : ""}: `),
8702
+ validateBaseUrl,
8703
+ existingConfig.baseUrl
8704
+ );
8705
+ if (!baseUrl) return { skipped: true };
8706
+ const apiKeyPrompt = isReconfig && existingConfig.apiKey ? chalk7.white(` API key (optional, press Enter to keep current) [${maskKey(existingConfig.apiKey)}]: `) : chalk7.white(" API key (optional, press Enter to skip): ");
8707
+ const apiKey = await ask(apiKeyPrompt);
8708
+ const resolvedApiKey = apiKey || existingConfig.apiKey || "";
8709
+ console.log(chalk7.dim(" Fetching models from server..."));
8710
+ try {
8711
+ const catalog = await fetchProviderModelCatalog("openaiCompat", {
8712
+ ...existingConfig,
8713
+ baseUrl,
8714
+ apiKey: resolvedApiKey
8715
+ });
8716
+ const model = await chooseProviderModel(
8717
+ "OpenAI Compilations",
8718
+ catalog.recommendedModel,
8719
+ catalog.models
8720
+ );
8721
+ return { baseUrl, apiKey: resolvedApiKey, model, skipped: false };
8722
+ } catch {
8723
+ console.log(chalk7.yellow(" Could not fetch models from this server. You can enter the model name manually."));
8724
+ const model = await promptValidatedValue(
8725
+ chalk7.white(" Model name: "),
8726
+ validateModelName
8727
+ );
8728
+ if (!model) return { baseUrl, apiKey: resolvedApiKey, model: existingConfig.model, skipped: false };
8729
+ return { baseUrl, apiKey: resolvedApiKey, model, skipped: false };
8730
+ }
8731
+ }
8665
8732
  async function promptValidatedValue(prompt, validator, existingValue, options) {
8666
8733
  while (true) {
8667
8734
  const value = await ask(prompt);
@@ -8895,6 +8962,18 @@ async function configure(existingConfig) {
8895
8962
  }
8896
8963
  continue;
8897
8964
  }
8965
+ if (provider === "openaiCompat") {
8966
+ const result = await promptOpenAICompatSetup(config, isReconfig);
8967
+ if (!result.skipped && result.baseUrl && result.model) {
8968
+ config.providers.openaiCompat.baseUrl = result.baseUrl;
8969
+ config.providers.openaiCompat.model = result.model;
8970
+ config.providers.openaiCompat.enabled = true;
8971
+ if (result.apiKey) {
8972
+ config.providers.openaiCompat.apiKey = result.apiKey;
8973
+ }
8974
+ }
8975
+ continue;
8976
+ }
8898
8977
  if (provider === "mimo") {
8899
8978
  const mask = isReconfig && config.providers.mimo.apiKey ? ` [${maskKey(config.providers.mimo.apiKey)}]` : "";
8900
8979
  const result = await promptApiKeyWithModelSelection(
@@ -9081,16 +9160,21 @@ async function runAgent(isDaemon = false) {
9081
9160
  process.exit(1);
9082
9161
  }
9083
9162
  const available = providers.listAvailable();
9084
- const providerLabels = available.map((provider) => getProviderLabel(provider));
9085
- const providerModels = available.map((provider) => {
9086
- const key = provider;
9087
- return `${getProviderLabel(key)}: ${config.providers[key].model}`;
9088
- });
9163
+ const defaultProvider = config.providers.default;
9164
+ const defaultModel = config.providers[defaultProvider]?.model ?? "unknown";
9089
9165
  if (!isDaemon) {
9090
- console.log(chalk7.dim(` Providers: ${providerLabels.join(", ")}`));
9091
- console.log(chalk7.dim(` Models: ${providerModels.join(" | ")}`));
9166
+ const providerSummary = available.map((provider) => {
9167
+ const key = provider;
9168
+ const label = getProviderLabel(key);
9169
+ const model = config.providers[key]?.model ?? "?";
9170
+ const marker = key === defaultProvider ? " \u2190 default" : "";
9171
+ return `${label}: ${model}${marker}`;
9172
+ });
9173
+ console.log("");
9174
+ console.log(chalk7.bgMagenta.black.bold(` \u26A1 ${getProviderLabel(defaultProvider)} \xB7 ${defaultModel} `));
9175
+ console.log(chalk7.dim(` Providers: ${providerSummary.join(" \xB7 ")}`));
9092
9176
  } else {
9093
- logger.info({ providers: available }, "Providers loaded");
9177
+ logger.info({ providers: available, default: defaultProvider }, "Providers loaded");
9094
9178
  }
9095
9179
  const skillLoader = new SkillLoader();
9096
9180
  const skills = skillLoader.discover();