lingo.dev 0.97.5 → 0.99.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/build/cli.cjs +197 -104
- package/build/cli.cjs.map +1 -1
- package/build/cli.mjs +112 -19
- package/build/cli.mjs.map +1 -1
- package/package.json +7 -5
package/build/cli.mjs
CHANGED
|
@@ -30,7 +30,8 @@ function getSettings(explicitApiKey) {
|
|
|
30
30
|
openaiApiKey: env.OPENAI_API_KEY || systemFile.llm?.openaiApiKey,
|
|
31
31
|
anthropicApiKey: env.ANTHROPIC_API_KEY || systemFile.llm?.anthropicApiKey,
|
|
32
32
|
groqApiKey: env.GROQ_API_KEY || systemFile.llm?.groqApiKey,
|
|
33
|
-
googleApiKey: env.GOOGLE_API_KEY || systemFile.llm?.googleApiKey
|
|
33
|
+
googleApiKey: env.GOOGLE_API_KEY || systemFile.llm?.googleApiKey,
|
|
34
|
+
openrouterApiKey: env.OPENROUTER_API_KEY || systemFile.llm?.openrouterApiKey
|
|
34
35
|
}
|
|
35
36
|
};
|
|
36
37
|
}
|
|
@@ -59,7 +60,8 @@ var SettingsSchema = Z.object({
|
|
|
59
60
|
openaiApiKey: Z.string().optional(),
|
|
60
61
|
anthropicApiKey: Z.string().optional(),
|
|
61
62
|
groqApiKey: Z.string().optional(),
|
|
62
|
-
googleApiKey: Z.string().optional()
|
|
63
|
+
googleApiKey: Z.string().optional(),
|
|
64
|
+
openrouterApiKey: Z.string().optional()
|
|
63
65
|
})
|
|
64
66
|
});
|
|
65
67
|
var SETTINGS_KEYS = flattenZodObject(
|
|
@@ -83,7 +85,8 @@ function _loadEnv() {
|
|
|
83
85
|
OPENAI_API_KEY: Z.string().optional(),
|
|
84
86
|
ANTHROPIC_API_KEY: Z.string().optional(),
|
|
85
87
|
GROQ_API_KEY: Z.string().optional(),
|
|
86
|
-
GOOGLE_API_KEY: Z.string().optional()
|
|
88
|
+
GOOGLE_API_KEY: Z.string().optional(),
|
|
89
|
+
OPENROUTER_API_KEY: Z.string().optional()
|
|
87
90
|
}).passthrough().parse(process.env);
|
|
88
91
|
}
|
|
89
92
|
function _loadSystemFile() {
|
|
@@ -100,7 +103,8 @@ function _loadSystemFile() {
|
|
|
100
103
|
openaiApiKey: Z.string().optional(),
|
|
101
104
|
anthropicApiKey: Z.string().optional(),
|
|
102
105
|
groqApiKey: Z.string().optional(),
|
|
103
|
-
googleApiKey: Z.string().optional()
|
|
106
|
+
googleApiKey: Z.string().optional(),
|
|
107
|
+
openrouterApiKey: Z.string().optional()
|
|
104
108
|
}).optional()
|
|
105
109
|
}).passthrough().parse(data);
|
|
106
110
|
}
|
|
@@ -163,6 +167,12 @@ function _envVarsInfo() {
|
|
|
163
167
|
`\u2139\uFE0F Using GOOGLE_API_KEY env var instead of key from user config`
|
|
164
168
|
);
|
|
165
169
|
}
|
|
170
|
+
if (env.OPENROUTER_API_KEY && systemFile.llm?.openrouterApiKey) {
|
|
171
|
+
console.info(
|
|
172
|
+
"\x1B[36m%s\x1B[0m",
|
|
173
|
+
`\u2139\uFE0F Using OPENROUTER_API_KEY env var instead of key from user config`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
166
176
|
if (env.LINGODOTDEV_API_URL) {
|
|
167
177
|
console.info(
|
|
168
178
|
"\x1B[36m%s\x1B[0m",
|
|
@@ -204,6 +214,26 @@ var CLIError = class extends Error {
|
|
|
204
214
|
}
|
|
205
215
|
};
|
|
206
216
|
|
|
217
|
+
// src/cli/utils/cloudflare-status.ts
|
|
218
|
+
async function checkCloudflareStatus() {
|
|
219
|
+
try {
|
|
220
|
+
const response = await fetch("https://www.cloudflarestatus.com/api/v2/status.json", {
|
|
221
|
+
signal: AbortSignal.timeout(5e3)
|
|
222
|
+
});
|
|
223
|
+
if (response.ok) {
|
|
224
|
+
return await response.json();
|
|
225
|
+
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
function formatCloudflareStatusMessage(status) {
|
|
231
|
+
if (status.status.indicator === "none") {
|
|
232
|
+
return "";
|
|
233
|
+
}
|
|
234
|
+
return `Cloudflare is experiencing ${status.status.indicator} issues: ${status.status.description}. This may be affecting the API connection.`;
|
|
235
|
+
}
|
|
236
|
+
|
|
207
237
|
// src/cli/utils/auth.ts
|
|
208
238
|
function createAuthenticator(params) {
|
|
209
239
|
return {
|
|
@@ -226,8 +256,32 @@ function createAuthenticator(params) {
|
|
|
226
256
|
id: payload.id
|
|
227
257
|
};
|
|
228
258
|
}
|
|
259
|
+
if (res.status >= 500 && res.status < 600) {
|
|
260
|
+
const originalErrorMessage = `Server error (${res.status}): ${res.statusText}. Please try again later.`;
|
|
261
|
+
const cloudflareStatus = await checkCloudflareStatus();
|
|
262
|
+
if (!cloudflareStatus) {
|
|
263
|
+
throw new CLIError({
|
|
264
|
+
message: originalErrorMessage,
|
|
265
|
+
docUrl: "connectionFailed"
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (cloudflareStatus.status.indicator !== "none") {
|
|
269
|
+
const cloudflareMessage = formatCloudflareStatusMessage(cloudflareStatus);
|
|
270
|
+
throw new CLIError({
|
|
271
|
+
message: cloudflareMessage,
|
|
272
|
+
docUrl: "connectionFailed"
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
throw new CLIError({
|
|
276
|
+
message: originalErrorMessage,
|
|
277
|
+
docUrl: "connectionFailed"
|
|
278
|
+
});
|
|
279
|
+
}
|
|
229
280
|
return null;
|
|
230
281
|
} catch (error) {
|
|
282
|
+
if (error instanceof CLIError) {
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
231
285
|
const isNetworkError = error instanceof TypeError && error.message === "fetch failed";
|
|
232
286
|
if (isNetworkError) {
|
|
233
287
|
throw new CLIError({
|
|
@@ -4493,6 +4547,8 @@ function countWordsInRecord(payload) {
|
|
|
4493
4547
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
4494
4548
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
4495
4549
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
4550
|
+
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
|
4551
|
+
import { createOllama } from "ollama-ai-provider";
|
|
4496
4552
|
function createProcessor(provider, params) {
|
|
4497
4553
|
if (!provider) {
|
|
4498
4554
|
const result = createLingoLocalizer(params);
|
|
@@ -4505,10 +4561,10 @@ function createProcessor(provider, params) {
|
|
|
4505
4561
|
}
|
|
4506
4562
|
function getPureModelProvider(provider) {
|
|
4507
4563
|
const createMissingKeyErrorMessage = (providerId, envVar) => dedent4`
|
|
4508
|
-
You're trying to use raw ${chalk5.dim(providerId)} API for translation
|
|
4564
|
+
You're trying to use raw ${chalk5.dim(providerId)} API for translation. ${envVar ? `However, ${chalk5.dim(envVar)} environment variable is not set.` : "However, that provider is unavailable."}
|
|
4509
4565
|
|
|
4510
4566
|
To fix this issue:
|
|
4511
|
-
1. Set ${chalk5.dim(envVar)} in your environment variables, or
|
|
4567
|
+
1. ${envVar ? `Set ${chalk5.dim(envVar)} in your environment variables` : "Set the environment variable for your provider (if required)"}, or
|
|
4512
4568
|
2. Remove the ${chalk5.italic("provider")} node from your i18n.json configuration to switch to ${chalk5.hex(colors.green)("Lingo.dev")}
|
|
4513
4569
|
|
|
4514
4570
|
${chalk5.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
|
|
@@ -4523,7 +4579,7 @@ function getPureModelProvider(provider) {
|
|
|
4523
4579
|
${chalk5.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
|
|
4524
4580
|
`;
|
|
4525
4581
|
switch (provider?.id) {
|
|
4526
|
-
case "openai":
|
|
4582
|
+
case "openai": {
|
|
4527
4583
|
if (!process.env.OPENAI_API_KEY) {
|
|
4528
4584
|
throw new Error(
|
|
4529
4585
|
createMissingKeyErrorMessage("OpenAI", "OPENAI_API_KEY")
|
|
@@ -4533,7 +4589,8 @@ function getPureModelProvider(provider) {
|
|
|
4533
4589
|
apiKey: process.env.OPENAI_API_KEY,
|
|
4534
4590
|
baseURL: provider.baseUrl
|
|
4535
4591
|
})(provider.model);
|
|
4536
|
-
|
|
4592
|
+
}
|
|
4593
|
+
case "anthropic": {
|
|
4537
4594
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
4538
4595
|
throw new Error(
|
|
4539
4596
|
createMissingKeyErrorMessage("Anthropic", "ANTHROPIC_API_KEY")
|
|
@@ -4542,7 +4599,8 @@ function getPureModelProvider(provider) {
|
|
|
4542
4599
|
return createAnthropic({
|
|
4543
4600
|
apiKey: process.env.ANTHROPIC_API_KEY
|
|
4544
4601
|
})(provider.model);
|
|
4545
|
-
|
|
4602
|
+
}
|
|
4603
|
+
case "google": {
|
|
4546
4604
|
if (!process.env.GOOGLE_API_KEY) {
|
|
4547
4605
|
throw new Error(
|
|
4548
4606
|
createMissingKeyErrorMessage("Google", "GOOGLE_API_KEY")
|
|
@@ -4551,8 +4609,24 @@ function getPureModelProvider(provider) {
|
|
|
4551
4609
|
return createGoogleGenerativeAI({
|
|
4552
4610
|
apiKey: process.env.GOOGLE_API_KEY
|
|
4553
4611
|
})(provider.model);
|
|
4554
|
-
|
|
4612
|
+
}
|
|
4613
|
+
case "openrouter": {
|
|
4614
|
+
if (!process.env.OPENROUTER_API_KEY) {
|
|
4615
|
+
throw new Error(
|
|
4616
|
+
createMissingKeyErrorMessage("OpenRouter", "OPENROUTER_API_KEY")
|
|
4617
|
+
);
|
|
4618
|
+
}
|
|
4619
|
+
return createOpenRouter({
|
|
4620
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
4621
|
+
baseURL: provider.baseUrl
|
|
4622
|
+
})(provider.model);
|
|
4623
|
+
}
|
|
4624
|
+
case "ollama": {
|
|
4625
|
+
return createOllama()(provider.model);
|
|
4626
|
+
}
|
|
4627
|
+
default: {
|
|
4555
4628
|
throw new Error(createUnsupportedProviderErrorMessage(provider?.id));
|
|
4629
|
+
}
|
|
4556
4630
|
}
|
|
4557
4631
|
}
|
|
4558
4632
|
|
|
@@ -5648,10 +5722,12 @@ function createLingoDotDevLocalizer(explicitApiKey) {
|
|
|
5648
5722
|
import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
|
|
5649
5723
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
5650
5724
|
import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
|
|
5725
|
+
import { createOpenRouter as createOpenRouter2 } from "@openrouter/ai-sdk-provider";
|
|
5651
5726
|
import chalk9 from "chalk";
|
|
5652
5727
|
import dedent6 from "dedent";
|
|
5653
5728
|
import { generateText as generateText2 } from "ai";
|
|
5654
5729
|
import { jsonrepair as jsonrepair3 } from "jsonrepair";
|
|
5730
|
+
import { createOllama as createOllama2 } from "ollama-ai-provider";
|
|
5655
5731
|
function createExplicitLocalizer(provider) {
|
|
5656
5732
|
switch (provider.id) {
|
|
5657
5733
|
default:
|
|
@@ -5690,27 +5766,42 @@ function createExplicitLocalizer(provider) {
|
|
|
5690
5766
|
apiKeyName: "GOOGLE_API_KEY",
|
|
5691
5767
|
baseUrl: provider.baseUrl
|
|
5692
5768
|
});
|
|
5769
|
+
case "openrouter":
|
|
5770
|
+
return createAiSdkLocalizer({
|
|
5771
|
+
factory: (params) => createOpenRouter2(params).languageModel(provider.model),
|
|
5772
|
+
id: provider.id,
|
|
5773
|
+
prompt: provider.prompt,
|
|
5774
|
+
apiKeyName: "OPENROUTER_API_KEY",
|
|
5775
|
+
baseUrl: provider.baseUrl
|
|
5776
|
+
});
|
|
5777
|
+
case "ollama":
|
|
5778
|
+
return createAiSdkLocalizer({
|
|
5779
|
+
factory: (_params) => createOllama2().languageModel(provider.model),
|
|
5780
|
+
id: provider.id,
|
|
5781
|
+
prompt: provider.prompt,
|
|
5782
|
+
skipAuth: true
|
|
5783
|
+
});
|
|
5693
5784
|
}
|
|
5694
5785
|
}
|
|
5695
5786
|
function createAiSdkLocalizer(params) {
|
|
5696
|
-
const
|
|
5697
|
-
|
|
5787
|
+
const skipAuth = params.skipAuth === true;
|
|
5788
|
+
const apiKey = process.env[params?.apiKeyName ?? ""];
|
|
5789
|
+
if (!skipAuth && !apiKey || !params.apiKeyName) {
|
|
5698
5790
|
throw new Error(
|
|
5699
5791
|
dedent6`
|
|
5700
|
-
You're trying to use raw ${chalk9.dim(params.id)} API for translation
|
|
5792
|
+
You're trying to use raw ${chalk9.dim(params.id)} API for translation. ${params.apiKeyName ? `However, ${chalk9.dim(params.apiKeyName)} environment variable is not set.` : "However, that provider is unavailable."}
|
|
5701
5793
|
|
|
5702
5794
|
To fix this issue:
|
|
5703
|
-
1. Set ${chalk9.dim(params.apiKeyName)} in your environment variables, or
|
|
5795
|
+
1. ${params.apiKeyName ? `Set ${chalk9.dim(params.apiKeyName)} in your environment variables` : "Set the environment variable for your provider (if required)"}, or
|
|
5704
5796
|
2. Remove the ${chalk9.italic("provider")} node from your i18n.json configuration to switch to ${chalk9.hex(colors.green)("Lingo.dev")}
|
|
5705
5797
|
|
|
5706
5798
|
${chalk9.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
|
|
5707
5799
|
`
|
|
5708
5800
|
);
|
|
5709
5801
|
}
|
|
5710
|
-
const model = params.factory(
|
|
5711
|
-
apiKey,
|
|
5712
|
-
|
|
5713
|
-
});
|
|
5802
|
+
const model = params.factory(
|
|
5803
|
+
skipAuth ? {} : { apiKey, baseUrl: params.baseUrl }
|
|
5804
|
+
);
|
|
5714
5805
|
return {
|
|
5715
5806
|
id: params.id,
|
|
5716
5807
|
checkAuth: async () => {
|
|
@@ -7494,7 +7585,7 @@ async function renderHero2() {
|
|
|
7494
7585
|
// package.json
|
|
7495
7586
|
var package_default = {
|
|
7496
7587
|
name: "lingo.dev",
|
|
7497
|
-
version: "0.
|
|
7588
|
+
version: "0.99.0",
|
|
7498
7589
|
description: "Lingo.dev CLI",
|
|
7499
7590
|
private: false,
|
|
7500
7591
|
publishConfig: {
|
|
@@ -7622,6 +7713,7 @@ var package_default = {
|
|
|
7622
7713
|
"@lingo.dev/_sdk": "workspace:*",
|
|
7623
7714
|
"@lingo.dev/_spec": "workspace:*",
|
|
7624
7715
|
"@modelcontextprotocol/sdk": "^1.5.0",
|
|
7716
|
+
"@openrouter/ai-sdk-provider": "^0.7.1",
|
|
7625
7717
|
"@paralleldrive/cuid2": "^2.2.2",
|
|
7626
7718
|
ai: "^4.3.15",
|
|
7627
7719
|
bitbucket: "^2.12.0",
|
|
@@ -7663,6 +7755,7 @@ var package_default = {
|
|
|
7663
7755
|
"node-webvtt": "^1.9.4",
|
|
7664
7756
|
"object-hash": "^3.0.0",
|
|
7665
7757
|
octokit: "^4.0.2",
|
|
7758
|
+
"ollama-ai-provider": "^1.2.0",
|
|
7666
7759
|
open: "^10.1.2",
|
|
7667
7760
|
ora: "^8.1.1",
|
|
7668
7761
|
"p-limit": "^6.2.0",
|