@cosmicstack/mercury-agent 1.1.1 → 1.1.3
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 +182 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -80,7 +80,7 @@ function getDefaultConfig() {
|
|
|
80
80
|
ollamaCloud: {
|
|
81
81
|
name: "ollamaCloud",
|
|
82
82
|
apiKey: getEnv("OLLAMA_CLOUD_API_KEY", ""),
|
|
83
|
-
baseUrl: getEnv("OLLAMA_CLOUD_BASE_URL", "https://ollama.com/
|
|
83
|
+
baseUrl: getEnv("OLLAMA_CLOUD_BASE_URL", "https://ollama.com/v1"),
|
|
84
84
|
model: getEnv("OLLAMA_CLOUD_MODEL", "gpt-oss:120b"),
|
|
85
85
|
enabled: getEnvBool("OLLAMA_CLOUD_ENABLED", true)
|
|
86
86
|
},
|
|
@@ -90,6 +90,20 @@ function getDefaultConfig() {
|
|
|
90
90
|
baseUrl: getEnv("OLLAMA_LOCAL_BASE_URL", "http://127.0.0.1:11434/api"),
|
|
91
91
|
model: getEnv("OLLAMA_LOCAL_MODEL", "gpt-oss:20b"),
|
|
92
92
|
enabled: getEnvBool("OLLAMA_LOCAL_ENABLED", false)
|
|
93
|
+
},
|
|
94
|
+
mimo: {
|
|
95
|
+
name: "mimo",
|
|
96
|
+
apiKey: getEnv("MIMO_API_KEY", ""),
|
|
97
|
+
baseUrl: getEnv("MIMO_BASE_URL", "https://api.xiaomimimo.com/v1"),
|
|
98
|
+
model: getEnv("MIMO_MODEL", "mimo-v2.5-pro"),
|
|
99
|
+
enabled: getEnvBool("MIMO_ENABLED", true)
|
|
100
|
+
},
|
|
101
|
+
mimoTokenPlan: {
|
|
102
|
+
name: "mimoTokenPlan",
|
|
103
|
+
apiKey: getEnv("MIMO_TOKEN_PLAN_API_KEY", ""),
|
|
104
|
+
baseUrl: getEnv("MIMO_TOKEN_PLAN_BASE_URL", "https://token-plan-cn.xiaomimimo.com/v1"),
|
|
105
|
+
model: getEnv("MIMO_TOKEN_PLAN_MODEL", "mimo-v2.5-pro"),
|
|
106
|
+
enabled: getEnvBool("MIMO_TOKEN_PLAN_ENABLED", false)
|
|
93
107
|
}
|
|
94
108
|
},
|
|
95
109
|
channels: {
|
|
@@ -131,7 +145,9 @@ function loadConfig() {
|
|
|
131
145
|
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
132
146
|
const fileConfig = parseYaml(raw);
|
|
133
147
|
const defaults = getDefaultConfig();
|
|
134
|
-
return
|
|
148
|
+
return migrateLegacyOllamaCloudBaseUrl(
|
|
149
|
+
migrateLegacyTelegramAccess(deepMerge(defaults, fileConfig))
|
|
150
|
+
);
|
|
135
151
|
}
|
|
136
152
|
return migrateLegacyTelegramAccess(getDefaultConfig());
|
|
137
153
|
}
|
|
@@ -175,6 +191,9 @@ function isProviderConfigured(provider) {
|
|
|
175
191
|
if (provider.name === "ollamaLocal") {
|
|
176
192
|
return provider.baseUrl.length > 0 && provider.model.length > 0;
|
|
177
193
|
}
|
|
194
|
+
if (provider.name === "ollamaCloud") {
|
|
195
|
+
return provider.apiKey.length > 0 && provider.baseUrl.length > 0;
|
|
196
|
+
}
|
|
178
197
|
return provider.apiKey.length > 0;
|
|
179
198
|
}
|
|
180
199
|
function getTelegramApprovedUsers(config) {
|
|
@@ -316,6 +335,13 @@ function migrateLegacyTelegramAccess(config) {
|
|
|
316
335
|
delete telegram.pairedUsername;
|
|
317
336
|
return config;
|
|
318
337
|
}
|
|
338
|
+
function migrateLegacyOllamaCloudBaseUrl(config) {
|
|
339
|
+
if (config.providers.ollamaCloud.baseUrl === "https://ollama.com/api") {
|
|
340
|
+
config.providers.ollamaCloud.baseUrl = "https://ollama.com/v1";
|
|
341
|
+
saveConfig(config);
|
|
342
|
+
}
|
|
343
|
+
return config;
|
|
344
|
+
}
|
|
319
345
|
|
|
320
346
|
// src/utils/logger.ts
|
|
321
347
|
import pino from "pino";
|
|
@@ -1517,7 +1543,7 @@ var OpenAICompatProvider = class extends BaseProvider {
|
|
|
1517
1543
|
model;
|
|
1518
1544
|
client;
|
|
1519
1545
|
modelInstance;
|
|
1520
|
-
constructor(config) {
|
|
1546
|
+
constructor(config, { useChatApi } = {}) {
|
|
1521
1547
|
super(config);
|
|
1522
1548
|
this.name = config.name;
|
|
1523
1549
|
this.model = config.model;
|
|
@@ -1525,7 +1551,7 @@ var OpenAICompatProvider = class extends BaseProvider {
|
|
|
1525
1551
|
apiKey: config.apiKey,
|
|
1526
1552
|
baseURL: config.baseUrl
|
|
1527
1553
|
});
|
|
1528
|
-
this.modelInstance = this.client(config.model);
|
|
1554
|
+
this.modelInstance = useChatApi ? this.client.chat(config.model) : this.client(config.model);
|
|
1529
1555
|
}
|
|
1530
1556
|
async generateText(prompt, systemPrompt) {
|
|
1531
1557
|
const result = await generateText({
|
|
@@ -1672,6 +1698,36 @@ var OllamaProvider = class extends BaseProvider {
|
|
|
1672
1698
|
if (this.name === "ollamaLocal") {
|
|
1673
1699
|
return this.config.baseUrl.length > 0 && this.config.model.length > 0;
|
|
1674
1700
|
}
|
|
1701
|
+
return this.config.apiKey.length > 0 && this.config.baseUrl.length > 0;
|
|
1702
|
+
}
|
|
1703
|
+
getModelInstance() {
|
|
1704
|
+
return this.modelInstance;
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
|
|
1708
|
+
// src/providers/mimo.ts
|
|
1709
|
+
import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
|
|
1710
|
+
var MiMoProvider = class extends BaseProvider {
|
|
1711
|
+
name;
|
|
1712
|
+
model;
|
|
1713
|
+
modelInstance;
|
|
1714
|
+
constructor(config) {
|
|
1715
|
+
super(config);
|
|
1716
|
+
this.name = config.name;
|
|
1717
|
+
this.model = config.model;
|
|
1718
|
+
const client = createOpenAI2({
|
|
1719
|
+
apiKey: config.apiKey,
|
|
1720
|
+
baseURL: config.baseUrl
|
|
1721
|
+
});
|
|
1722
|
+
this.modelInstance = client.chat(config.model);
|
|
1723
|
+
}
|
|
1724
|
+
async generateText(_prompt, _systemPrompt) {
|
|
1725
|
+
throw new Error("Use getModelInstance() with the AI SDK agent loop");
|
|
1726
|
+
}
|
|
1727
|
+
async *streamText(_prompt, _systemPrompt) {
|
|
1728
|
+
throw new Error("Use getModelInstance() with the AI SDK agent loop");
|
|
1729
|
+
}
|
|
1730
|
+
isAvailable() {
|
|
1675
1731
|
return this.config.apiKey.length > 0;
|
|
1676
1732
|
}
|
|
1677
1733
|
getModelInstance() {
|
|
@@ -1692,7 +1748,9 @@ var ProviderRegistry = class {
|
|
|
1692
1748
|
config.providers.anthropic,
|
|
1693
1749
|
config.providers.grok,
|
|
1694
1750
|
config.providers.ollamaCloud,
|
|
1695
|
-
config.providers.ollamaLocal
|
|
1751
|
+
config.providers.ollamaLocal,
|
|
1752
|
+
config.providers.mimo,
|
|
1753
|
+
config.providers.mimoTokenPlan
|
|
1696
1754
|
];
|
|
1697
1755
|
for (const pc of entries) {
|
|
1698
1756
|
if (!isProviderConfigured(pc)) continue;
|
|
@@ -1702,8 +1760,12 @@ var ProviderRegistry = class {
|
|
|
1702
1760
|
provider = new AnthropicProvider(pc);
|
|
1703
1761
|
} else if (pc.name === "deepseek") {
|
|
1704
1762
|
provider = new DeepSeekProvider(pc);
|
|
1705
|
-
} else if (pc.name === "
|
|
1763
|
+
} else if (pc.name === "ollamaLocal") {
|
|
1706
1764
|
provider = new OllamaProvider(pc);
|
|
1765
|
+
} else if (pc.name === "ollamaCloud") {
|
|
1766
|
+
provider = new OpenAICompatProvider(pc, { useChatApi: true });
|
|
1767
|
+
} else if (pc.name === "mimo" || pc.name === "mimoTokenPlan") {
|
|
1768
|
+
provider = new MiMoProvider(pc);
|
|
1707
1769
|
} else {
|
|
1708
1770
|
provider = new OpenAICompatProvider(pc);
|
|
1709
1771
|
}
|
|
@@ -8100,6 +8162,14 @@ var OLLAMA_LOCAL_PREFERRED_MODELS = [
|
|
|
8100
8162
|
"gpt-oss:20b",
|
|
8101
8163
|
"gpt-oss:120b"
|
|
8102
8164
|
];
|
|
8165
|
+
var MIMO_PREFERRED_MODELS = [
|
|
8166
|
+
"mimo-v2.5-pro",
|
|
8167
|
+
"mimo-v2.5",
|
|
8168
|
+
"mimo-v2-pro",
|
|
8169
|
+
"mimo-v2-omni",
|
|
8170
|
+
"mimo-v2-flash"
|
|
8171
|
+
];
|
|
8172
|
+
var MIMO_TOKEN_PLAN_PREFERRED_MODELS = MIMO_PREFERRED_MODELS;
|
|
8103
8173
|
var ProviderModelFetchError = class extends Error {
|
|
8104
8174
|
constructor(message) {
|
|
8105
8175
|
super(message);
|
|
@@ -8154,7 +8224,9 @@ function chooseRecommendedModel(provider, models, currentModel) {
|
|
|
8154
8224
|
anthropic: ANTHROPIC_PREFERRED_MODELS,
|
|
8155
8225
|
grok: GROK_PREFERRED_MODELS,
|
|
8156
8226
|
ollamaCloud: OLLAMA_CLOUD_PREFERRED_MODELS,
|
|
8157
|
-
ollamaLocal: OLLAMA_LOCAL_PREFERRED_MODELS
|
|
8227
|
+
ollamaLocal: OLLAMA_LOCAL_PREFERRED_MODELS,
|
|
8228
|
+
mimo: MIMO_PREFERRED_MODELS,
|
|
8229
|
+
mimoTokenPlan: MIMO_TOKEN_PLAN_PREFERRED_MODELS
|
|
8158
8230
|
};
|
|
8159
8231
|
for (const candidate of preferredByProvider[provider]) {
|
|
8160
8232
|
if (models.includes(candidate)) {
|
|
@@ -8178,7 +8250,9 @@ function buildModelCatalog(provider, models, currentModel) {
|
|
|
8178
8250
|
anthropic: ANTHROPIC_PREFERRED_MODELS,
|
|
8179
8251
|
grok: GROK_PREFERRED_MODELS,
|
|
8180
8252
|
ollamaCloud: OLLAMA_CLOUD_PREFERRED_MODELS,
|
|
8181
|
-
ollamaLocal: OLLAMA_LOCAL_PREFERRED_MODELS
|
|
8253
|
+
ollamaLocal: OLLAMA_LOCAL_PREFERRED_MODELS,
|
|
8254
|
+
mimo: MIMO_PREFERRED_MODELS,
|
|
8255
|
+
mimoTokenPlan: MIMO_TOKEN_PLAN_PREFERRED_MODELS
|
|
8182
8256
|
};
|
|
8183
8257
|
const withoutRecommended = filtered.filter((model) => model !== recommendedModel);
|
|
8184
8258
|
const prioritized = prioritizeModels(withoutRecommended, preferredByProvider[provider]);
|
|
@@ -8232,17 +8306,59 @@ async function fetchGrokModels(config) {
|
|
|
8232
8306
|
const ids = (data.data ?? []).filter((model) => model.output_modalities?.includes("text") || model.output_modalities == null).map((model) => model.id?.trim() ?? "").filter((id) => id.startsWith("grok-"));
|
|
8233
8307
|
return buildModelCatalog("grok", ids, config.model);
|
|
8234
8308
|
}
|
|
8235
|
-
async function
|
|
8236
|
-
const headers = config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : void 0;
|
|
8309
|
+
async function fetchOllamaCloudModels(config) {
|
|
8237
8310
|
const data = await fetchJson(
|
|
8238
|
-
`${trimTrailingSlash(config.baseUrl)}/
|
|
8311
|
+
`${trimTrailingSlash(config.baseUrl)}/models`,
|
|
8239
8312
|
{
|
|
8240
|
-
headers
|
|
8313
|
+
headers: {
|
|
8314
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
8315
|
+
}
|
|
8241
8316
|
},
|
|
8242
|
-
|
|
8317
|
+
"Mercury could not fetch models for this Ollama Cloud key. Please re-enter it."
|
|
8318
|
+
);
|
|
8319
|
+
const ids = (data.data ?? []).map((model) => model.id?.trim() ?? "").filter(Boolean);
|
|
8320
|
+
return buildModelCatalog("ollamaCloud", ids, config.model);
|
|
8321
|
+
}
|
|
8322
|
+
async function fetchOllamaLocalModels(config) {
|
|
8323
|
+
const data = await fetchJson(
|
|
8324
|
+
`${trimTrailingSlash(config.baseUrl)}/tags`,
|
|
8325
|
+
{},
|
|
8326
|
+
"Mercury could not fetch models from this Ollama Local server. Please check the base URL and try again."
|
|
8243
8327
|
);
|
|
8244
8328
|
const ids = (data.models ?? []).map((model) => model.model?.trim() || model.name?.trim() || "").filter(Boolean);
|
|
8245
|
-
return buildModelCatalog(
|
|
8329
|
+
return buildModelCatalog("ollamaLocal", ids, config.model);
|
|
8330
|
+
}
|
|
8331
|
+
async function fetchMiMoModels(config) {
|
|
8332
|
+
const data = await fetchJson(
|
|
8333
|
+
`${trimTrailingSlash(config.baseUrl)}/models`,
|
|
8334
|
+
{
|
|
8335
|
+
headers: {
|
|
8336
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
8337
|
+
}
|
|
8338
|
+
},
|
|
8339
|
+
"Mercury could not fetch models for this MiMo key. Please re-enter it."
|
|
8340
|
+
);
|
|
8341
|
+
const ids = (data.data ?? []).map((model) => model.id?.trim() ?? "").filter((id) => {
|
|
8342
|
+
const lower = id.toLowerCase();
|
|
8343
|
+
return lower.startsWith("mimo-") && !lower.includes("tts");
|
|
8344
|
+
});
|
|
8345
|
+
return buildModelCatalog("mimo", ids, config.model);
|
|
8346
|
+
}
|
|
8347
|
+
async function fetchMiMoTokenPlanModels(config) {
|
|
8348
|
+
const data = await fetchJson(
|
|
8349
|
+
`${trimTrailingSlash(config.baseUrl)}/models`,
|
|
8350
|
+
{
|
|
8351
|
+
headers: {
|
|
8352
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
8353
|
+
}
|
|
8354
|
+
},
|
|
8355
|
+
"Mercury could not fetch models for this MiMo Token Plan key. Please re-enter it."
|
|
8356
|
+
);
|
|
8357
|
+
const ids = (data.data ?? []).map((model) => model.id?.trim() ?? "").filter((id) => {
|
|
8358
|
+
const lower = id.toLowerCase();
|
|
8359
|
+
return lower.startsWith("mimo-") && !lower.includes("tts");
|
|
8360
|
+
});
|
|
8361
|
+
return buildModelCatalog("mimoTokenPlan", ids, config.model);
|
|
8246
8362
|
}
|
|
8247
8363
|
async function fetchProviderModelCatalog(provider, config) {
|
|
8248
8364
|
if (provider === "anthropic") {
|
|
@@ -8251,8 +8367,17 @@ async function fetchProviderModelCatalog(provider, config) {
|
|
|
8251
8367
|
if (provider === "grok") {
|
|
8252
8368
|
return fetchGrokModels(config);
|
|
8253
8369
|
}
|
|
8254
|
-
if (provider === "ollamaCloud"
|
|
8255
|
-
return
|
|
8370
|
+
if (provider === "ollamaCloud") {
|
|
8371
|
+
return fetchOllamaCloudModels(config);
|
|
8372
|
+
}
|
|
8373
|
+
if (provider === "ollamaLocal") {
|
|
8374
|
+
return fetchOllamaLocalModels(config);
|
|
8375
|
+
}
|
|
8376
|
+
if (provider === "mimo") {
|
|
8377
|
+
return fetchMiMoModels(config);
|
|
8378
|
+
}
|
|
8379
|
+
if (provider === "mimoTokenPlan") {
|
|
8380
|
+
return fetchMiMoTokenPlanModels(config);
|
|
8256
8381
|
}
|
|
8257
8382
|
return fetchOpenAICompatModels(provider, config);
|
|
8258
8383
|
}
|
|
@@ -8311,7 +8436,9 @@ var PROVIDER_OPTIONS = [
|
|
|
8311
8436
|
{ key: "anthropic", label: "Anthropic" },
|
|
8312
8437
|
{ key: "grok", label: "Grok (xAI)" },
|
|
8313
8438
|
{ key: "ollamaCloud", label: "Ollama Cloud" },
|
|
8314
|
-
{ key: "ollamaLocal", label: "Ollama Local" }
|
|
8439
|
+
{ key: "ollamaLocal", label: "Ollama Local" },
|
|
8440
|
+
{ key: "mimo", label: "MiMo (Xiaomi)" },
|
|
8441
|
+
{ key: "mimoTokenPlan", label: "MiMo Token Plan (Xiaomi)" }
|
|
8315
8442
|
];
|
|
8316
8443
|
function getConfiguredProviderNames(config) {
|
|
8317
8444
|
return PROVIDER_OPTIONS.map((option) => option.key).filter((key) => isProviderConfigured(config.providers[key]));
|
|
@@ -8412,6 +8539,12 @@ function validateApiKey(provider, value) {
|
|
|
8412
8539
|
if (provider === "ollamaCloud") {
|
|
8413
8540
|
return looksLikeToken(value) ? null : "Ollama Cloud keys must look like a real API token: long, no spaces, and not plain text.";
|
|
8414
8541
|
}
|
|
8542
|
+
if (provider === "mimo") {
|
|
8543
|
+
return /^sk-[A-Za-z0-9_-]{16,}$/i.test(value) ? null : "MiMo keys must start with `sk-`.";
|
|
8544
|
+
}
|
|
8545
|
+
if (provider === "mimoTokenPlan") {
|
|
8546
|
+
return /^tp-[A-Za-z0-9_-]{16,}$/i.test(value) ? null : "MiMo Token Plan keys must start with `tp-`.";
|
|
8547
|
+
}
|
|
8415
8548
|
return null;
|
|
8416
8549
|
}
|
|
8417
8550
|
function validateBaseUrl(value) {
|
|
@@ -8760,6 +8893,38 @@ async function configure(existingConfig) {
|
|
|
8760
8893
|
config.providers.ollamaLocal.model = result.model;
|
|
8761
8894
|
config.providers.ollamaLocal.enabled = true;
|
|
8762
8895
|
}
|
|
8896
|
+
continue;
|
|
8897
|
+
}
|
|
8898
|
+
if (provider === "mimo") {
|
|
8899
|
+
const mask = isReconfig && config.providers.mimo.apiKey ? ` [${maskKey(config.providers.mimo.apiKey)}]` : "";
|
|
8900
|
+
const result = await promptApiKeyWithModelSelection(
|
|
8901
|
+
config,
|
|
8902
|
+
"mimo",
|
|
8903
|
+
"MiMo",
|
|
8904
|
+
chalk7.white(` MiMo API key${mask}${isReconfig ? "" : " (Enter to skip)"}: `),
|
|
8905
|
+
isReconfig
|
|
8906
|
+
);
|
|
8907
|
+
if (!result.skipped && result.apiKey && result.model) {
|
|
8908
|
+
config.providers.mimo.apiKey = result.apiKey;
|
|
8909
|
+
config.providers.mimo.model = result.model;
|
|
8910
|
+
config.providers.mimo.enabled = true;
|
|
8911
|
+
}
|
|
8912
|
+
continue;
|
|
8913
|
+
}
|
|
8914
|
+
if (provider === "mimoTokenPlan") {
|
|
8915
|
+
const mask = isReconfig && config.providers.mimoTokenPlan.apiKey ? ` [${maskKey(config.providers.mimoTokenPlan.apiKey)}]` : "";
|
|
8916
|
+
const result = await promptApiKeyWithModelSelection(
|
|
8917
|
+
config,
|
|
8918
|
+
"mimoTokenPlan",
|
|
8919
|
+
"MiMo Token Plan",
|
|
8920
|
+
chalk7.white(` MiMo Token Plan API key${mask}${isReconfig ? "" : " (Enter to skip)"}: `),
|
|
8921
|
+
isReconfig
|
|
8922
|
+
);
|
|
8923
|
+
if (!result.skipped && result.apiKey && result.model) {
|
|
8924
|
+
config.providers.mimoTokenPlan.apiKey = result.apiKey;
|
|
8925
|
+
config.providers.mimoTokenPlan.model = result.model;
|
|
8926
|
+
config.providers.mimoTokenPlan.enabled = true;
|
|
8927
|
+
}
|
|
8763
8928
|
}
|
|
8764
8929
|
}
|
|
8765
8930
|
const configuredProviders = getConfiguredProviderNames(config);
|