@gringow/gringow 0.1.4 → 0.2.1

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.
Files changed (53) hide show
  1. package/README.md +31 -36
  2. package/dist/config.d.mts +4 -6
  3. package/dist/config.mjs +30 -20
  4. package/dist/config.test.mjs +42 -30
  5. package/dist/constants/default-config.mjs +3 -3
  6. package/dist/create-cache-id.test.mjs +5 -5
  7. package/dist/data/check-cache.mjs +31 -63
  8. package/dist/data/clear-cache.mjs +30 -20
  9. package/dist/data/create-cache-dir.mjs +30 -20
  10. package/dist/data/delete-cache-item.mjs +30 -20
  11. package/dist/data/get-cache.mjs +30 -20
  12. package/dist/data/get-or-create-cache.mjs +30 -20
  13. package/dist/data/md5.test.mjs +5 -5
  14. package/dist/data/save-cache.mjs +30 -20
  15. package/dist/data/write-cache-to-disk.mjs +30 -20
  16. package/dist/flat-template-string.test.mjs +5 -5
  17. package/dist/gringow.mjs +82 -491
  18. package/dist/index.mjs +82 -491
  19. package/dist/io/ask-llm.d.mts +3 -1
  20. package/dist/io/ask-llm.mjs +75 -449
  21. package/dist/logger.test.mjs +5 -5
  22. package/dist/schemas/config.shcema.d.mts +23 -35
  23. package/dist/schemas/config.shcema.mjs +25 -15
  24. package/dist/types/index.d.mts +3 -25
  25. package/gringow.config.js.example +2 -4
  26. package/gringow.config.json.example +4 -2
  27. package/package.json +2 -5
  28. package/dist/io/anthropic/ask.d.mts +0 -11
  29. package/dist/io/anthropic/ask.mjs +0 -192
  30. package/dist/io/anthropic/commit-response.d.mts +0 -21
  31. package/dist/io/anthropic/commit-response.mjs +0 -10
  32. package/dist/io/anthropic/index.d.mts +0 -14
  33. package/dist/io/anthropic/index.mjs +0 -210
  34. package/dist/io/anthropic/parse.d.mts +0 -20
  35. package/dist/io/anthropic/parse.mjs +0 -10
  36. package/dist/io/gemini/ask.d.mts +0 -11
  37. package/dist/io/gemini/ask.mjs +0 -234
  38. package/dist/io/gemini/commit-response.d.mts +0 -11
  39. package/dist/io/gemini/commit-response.mjs +0 -7
  40. package/dist/io/gemini/index.d.mts +0 -14
  41. package/dist/io/gemini/index.mjs +0 -250
  42. package/dist/io/gemini/parse.d.mts +0 -20
  43. package/dist/io/gemini/parse.mjs +0 -11
  44. package/dist/io/huggingface/ask.d.mts +0 -13
  45. package/dist/io/huggingface/ask.mjs +0 -407
  46. package/dist/io/huggingface/commit-response.d.mts +0 -39
  47. package/dist/io/huggingface/commit-response.mjs +0 -14
  48. package/dist/io/huggingface/index.d.mts +0 -13
  49. package/dist/io/huggingface/index.mjs +0 -428
  50. package/dist/io/huggingface/languages-map.d.mts +0 -191
  51. package/dist/io/huggingface/languages-map.mjs +0 -187
  52. package/dist/io/huggingface/parse.d.mts +0 -20
  53. package/dist/io/huggingface/parse.mjs +0 -9
@@ -1,12 +1,9 @@
1
+ import { igniteEngine, Message } from 'multi-llm-ts';
1
2
  import { cosmiconfig } from 'cosmiconfig';
2
3
  import merge from 'lodash.merge';
3
4
  import { z } from 'zod';
4
- import Anthropic from '@anthropic-ai/sdk';
5
- import { GoogleGenerativeAI } from '@google/generative-ai';
6
- import { env, pipeline } from '@huggingface/transformers';
7
- import 'fs';
8
5
 
9
- // src/config.ts
6
+ // src/io/ask-llm.ts
10
7
 
11
8
  // src/constants/default-config.ts
12
9
  var defaultConfig = {
@@ -20,20 +17,34 @@ var defaultConfig = {
20
17
  prefix: "grw",
21
18
  write: true
22
19
  },
23
- keys: {},
24
20
  sourceLanguage: "en-US",
25
21
  defaultLanguage: "pt-BR",
26
22
  languages: ["pt-BR", "fr-CA"],
27
23
  llm: {
28
- choice: "huggingface",
29
- model: "Xenova/nllb-200-distilled-600M",
24
+ provider: "openai",
25
+ apiKey: void 0,
26
+ model: "gpt-4o-mini",
30
27
  temperature: 1,
31
28
  sleep: 0
32
29
  },
33
30
  globby: "./src/**/*.{js,jsx,ts,tsx}"
34
31
  };
35
32
  var languageSchema = z.string().regex(/^[a-z]{2,3}(-[A-Z]{2})?$/);
36
- var llmOptionsSchema = z.enum(["gemini", "anthropic", "huggingface"]);
33
+ var llmProviderSchema = z.enum([
34
+ "anthropic",
35
+ "gemini",
36
+ "openai",
37
+ "groq",
38
+ "mistral",
39
+ "ollama",
40
+ "xai",
41
+ "deepseek",
42
+ "openrouter",
43
+ "cerebras",
44
+ "lmstudio",
45
+ "azure",
46
+ "meta"
47
+ ]);
37
48
  var configSchema = z.object({
38
49
  debug: z.boolean().optional(),
39
50
  log: z.object({
@@ -45,15 +56,13 @@ var configSchema = z.object({
45
56
  prefix: z.string(),
46
57
  write: z.boolean().optional()
47
58
  }),
48
- keys: z.object({
49
- anthropicApiKey: z.string().optional(),
50
- geminiApiKey: z.string().optional()
51
- }),
52
59
  sourceLanguage: languageSchema,
53
60
  defaultLanguage: languageSchema,
54
61
  languages: z.array(languageSchema),
55
62
  llm: z.object({
56
- choice: llmOptionsSchema,
63
+ provider: llmProviderSchema,
64
+ apiKey: z.string().optional(),
65
+ baseURL: z.string().optional(),
57
66
  model: z.string().nullable(),
58
67
  temperature: z.number().optional(),
59
68
  sleep: z.number().optional(),
@@ -67,17 +76,15 @@ var configSchema = z.object({
67
76
  globby: z.string().regex(/^\.\/.*/).optional()
68
77
  }).refine(
69
78
  (data) => {
70
- if (data.llm.choice === "gemini" && !data.keys.geminiApiKey) {
71
- return false;
79
+ const noApiKeyRequired = ["ollama", "lmstudio"];
80
+ if (noApiKeyRequired.includes(data.llm.provider)) {
81
+ return true;
72
82
  }
73
- if (data.llm.choice === "anthropic" && !data.keys.anthropicApiKey) {
74
- return false;
75
- }
76
- return true;
83
+ return !!data.llm.apiKey;
77
84
  },
78
85
  {
79
- message: "The API key corresponding to the chosen LLM must be present.",
80
- path: ["keys"]
86
+ message: "The API key must be present in llm.apiKey for the chosen provider.",
87
+ path: ["llm", "apiKey"]
81
88
  }
82
89
  );
83
90
 
@@ -113,7 +120,7 @@ Your task is to translate a given text and output **only one valid JSON object**
113
120
 
114
121
  Follow these rules strictly:
115
122
 
116
- 1. The original text is written in English.
123
+ 1. The original text is written in English or Spanish.
117
124
  2. You will receive additional user parameters under the variable 'extraInstructions'. These may specify tone, persona, style, context, or any relevant translation guideline.
118
125
  - Examples: \u201Ctranslate as if you were a Shakespearean narrator\u201D or \u201Cuse a formal business tone suitable for a corporate presentation.\u201D
119
126
  - Apply these creatively but **without altering the meaning or punctuation** of the original text.
@@ -146,10 +153,10 @@ Translate the following text faithfully:
146
153
  function defaultPostPrompt(_config) {
147
154
  return "";
148
155
  }
149
- function prePrompt(config, append, replace) {
156
+ function prePrompt(config, prepend, replace) {
150
157
  return [
151
158
  // ...(append ? ['[SPECIFIC_INPUTS]', String(append), '[/SPECIFIC_INPUTS]'] : []),
152
- replace ? String(replace) : defaultPrePrompt(config, append)
159
+ replace ? String(replace) : defaultPrePrompt(config, prepend)
153
160
  ].join(" ").trim();
154
161
  }
155
162
  function postPrompt(config, prepend, replace) {
@@ -158,445 +165,64 @@ function postPrompt(config, prepend, replace) {
158
165
  replace ? String(replace) : defaultPostPrompt()
159
166
  ].join(" ").trim();
160
167
  }
161
- async function askAnthropic(prompt, prePrompt2, postPrompt2) {
162
- const config = await awaitedConfig;
163
- if (Number(config.llm.sleep)) {
164
- await new Promise((resolve) => setTimeout(resolve, config.llm.sleep ?? 1));
165
- }
166
- if (!config.keys.anthropicApiKey) {
167
- throw new Error("Anthropic API key is not set in the config");
168
- }
169
- const anthropic = new Anthropic({
170
- apiKey: config.keys.anthropicApiKey,
171
- dangerouslyAllowBrowser: true
172
- });
173
- const fullPrompt = String(`${prePrompt2}
174
168
 
175
-
176
- ${prompt}
177
-
178
-
179
- ${postPrompt2}`).trim();
180
- const response = await anthropic.messages.create({
181
- model: config.llm.model,
182
- max_tokens: 1024,
183
- messages: [
184
- {
185
- role: "user",
186
- content: fullPrompt
187
- }
188
- ]
189
- });
190
- return response;
191
- }
192
-
193
- // src/io/anthropic/commit-response.ts
194
- function commitResponseAnthropic(response) {
195
- const result2 = response.content.reduce((acc, item) => {
196
- const nextAcc = acc + (item.type === "text" ? item.text : "");
197
- return nextAcc;
198
- }, "");
199
- return result2;
200
- }
201
-
202
- // src/io/anthropic/parse.ts
203
- function parseAnthropic(unparsed) {
204
- if (typeof unparsed !== "string") {
205
- throw new Error("CommitResponse should be a string here.");
206
- }
207
- const parsed = JSON.parse(unparsed);
169
+ // src/io/ask-llm.ts
170
+ var providerEngineMap = {
171
+ anthropic: "anthropic",
172
+ gemini: "google",
173
+ openai: "openai",
174
+ groq: "groq",
175
+ mistral: "mistralai",
176
+ ollama: "ollama",
177
+ xai: "xai",
178
+ deepseek: "deepseek",
179
+ openrouter: "openrouter",
180
+ cerebras: "cerebras",
181
+ lmstudio: "lmstudio",
182
+ azure: "azure",
183
+ meta: "meta"
184
+ };
185
+ function parseResponse(responseText) {
186
+ const cleaned = responseText.replace(/```json/g, "").replace(/```/g, "").trim();
187
+ const parsed = JSON.parse(cleaned);
208
188
  return parsed;
209
189
  }
210
- async function generateResponse(prompt, config) {
211
- try {
212
- if (!config.keys.geminiApiKey) {
213
- throw new Error("Gemini API key is not set in the config");
214
- }
215
- const generativeAIClient = new GoogleGenerativeAI(config.keys.geminiApiKey);
216
- const model = generativeAIClient.getGenerativeModel({
217
- model: config.llm.model,
218
- generationConfig: {
219
- temperature: config.llm.temperature ?? 0.8
220
- }
221
- });
222
- if (config.debug) {
223
- console.log("Gemini model prompt:", JSON.stringify({ prompt }));
224
- }
225
- const response = await model.generateContent([prompt]);
226
- return response;
227
- } catch (err) {
228
- const error = err;
229
- console.log("Error details from Gemini model", JSON.stringify({ error }, null, 2));
230
- const retryDelay = error?.errorDetails?.find(
231
- (detail) => detail?.["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
232
- )?.retryDelay ?? void 0;
233
- if (error.status === 429 && retryDelay !== void 0) {
234
- const sleepTime = config.llm.sleep ?? 3;
235
- console.warn(
236
- `Rate limit exceeded when generating response from Gemini model, retrying in... ${retryDelay} + ${sleepTime / 1e3}s`
237
- );
238
- await new Promise((resolve) => setTimeout(resolve, (parseInt(retryDelay, 10) + sleepTime / 1e3) * 1e3));
239
- return generateResponse(prompt, config);
240
- }
241
- console.error("Error generating response from Gemini model", { error });
242
- throw error;
243
- }
244
- }
245
- async function askGemini(prompt, prePrompt2, postPrompt2) {
190
+ async function askLLM(prompt, prePrompt2, postPrompt2) {
246
191
  const config = await awaitedConfig;
247
- if (Number(config.llm.sleep)) {
248
- await new Promise((resolve) => setTimeout(resolve, config.llm.sleep ?? 1));
192
+ const provider = config.llm.provider;
193
+ const engineName = providerEngineMap[provider];
194
+ if (!engineName) {
195
+ throw new Error(`Unknown LLM provider: ${provider}`);
249
196
  }
250
- if (!config.keys.geminiApiKey) {
251
- throw new Error("Gemini API key is not set in the config");
197
+ if (!config.llm.apiKey) {
198
+ throw new Error(`API key for ${provider} is not configured in llm.apiKey`);
252
199
  }
253
- if (config.debug) {
254
- console.log("\nAsking Gemini model:", JSON.stringify({ model: config.llm.model, message: prompt }));
200
+ if (config.llm.sleep && config.llm.sleep > 0) {
201
+ await new Promise((resolve) => setTimeout(resolve, config.llm.sleep));
255
202
  }
256
- const fullPrompt = String(`${prePrompt2}
203
+ const engine = igniteEngine(engineName, {
204
+ apiKey: config.llm.apiKey,
205
+ ...config.llm.baseURL ? { baseURL: config.llm.baseURL } : {}
206
+ });
207
+ const fullPrompt = `${prePrompt2}
257
208
 
258
209
 
259
210
  ${prompt}
260
211
 
261
212
 
262
- ${postPrompt2}`).trim();
263
- let response;
264
- for (let i = 0; i < 3; i++) {
265
- const maybeResponse = await generateResponse(fullPrompt, config);
266
- const responseString = String(maybeResponse.response.candidates?.[0]?.content?.parts?.[0]?.text ?? "").replace(/```json/g, "").replace(/```/g, "").trim();
267
- if (responseString.startsWith("{") && responseString.endsWith("}")) {
268
- response = maybeResponse;
269
- break;
270
- }
271
- if (config.debug) {
272
- console.log("Gemini model response is not valid, contains no JSON:", JSON.stringify({ maybeResponse }));
273
- }
274
- }
275
- if (config.debug) {
276
- console.log("Gemini model response:", JSON.stringify({ response }));
277
- }
278
- if (!response) {
279
- throw new Error("Gemini model response is not valid");
280
- }
281
- return response;
282
- }
283
-
284
- // src/io/gemini/commit-response.ts
285
- function commitResponseGemini(response) {
286
- const result2 = response.response.text();
287
- return result2;
288
- }
289
-
290
- // src/io/gemini/parse.ts
291
- function parseGemini(unparsed) {
292
- if (typeof unparsed !== "string") {
293
- throw new Error("CommitResponse should be a string here.");
294
- }
295
- const cleaned = unparsed.replace(/```json/g, "").replace(/```/g, "");
296
- const parsed = JSON.parse(cleaned);
297
- return parsed;
298
- }
299
-
300
- // src/io/huggingface/languages-map.ts
301
- var languagesMap = {
302
- "en-US": "eng_Latn",
303
- "en-GB": "eng_Latn",
304
- "pt-BR": "por_Latn",
305
- "pt-PT": "por_Latn",
306
- "es-ES": "spa_Latn",
307
- "es-MX": "spa_Latn",
308
- "fr-FR": "fra_Latn",
309
- "fr-CA": "fra_Latn",
310
- "de-DE": "deu_Latn",
311
- "it-IT": "ita_Latn",
312
- "nl-NL": "nld_Latn",
313
- "pl-PL": "pol_Latn",
314
- "ru-RU": "rus_Cyrl",
315
- "uk-UA": "ukr_Cyrl",
316
- "bg-BG": "bul_Cyrl",
317
- "hr-HR": "hrv_Latn",
318
- "cs-CZ": "ces_Latn",
319
- "sk-SK": "slk_Latn",
320
- "hu-HU": "hun_Latn",
321
- "ro-RO": "ron_Latn",
322
- "fi-FI": "fin_Latn",
323
- "sv-SE": "swe_Latn",
324
- "da-DK": "dan_Latn",
325
- "no-NO": "nob_Latn",
326
- "is-IS": "isl_Latn",
327
- "et-EE": "est_Latn",
328
- "lv-LV": "lav_Latn",
329
- "lt-LT": "lit_Latn",
330
- "mt-MT": "mlt_Latn",
331
- "ga-IE": "gle_Latn",
332
- "cy-GB": "cym_Latn",
333
- "eu-ES": "eus_Latn",
334
- "ca-ES": "cat_Latn",
335
- "gl-ES": "glg_Latn",
336
- "oc-FR": "oci_Latn",
337
- "br-FR": "bre_Latn",
338
- "gd-GB": "gla_Latn",
339
- "kw-GB": "cor_Latn",
340
- "fur-IT": "fur_Latn",
341
- "rm-CH": "roh_Latn",
342
- "lb-LU": "ltz_Latn",
343
- "fy-NL": "fry_Latn",
344
- "af-ZA": "afr_Latn",
345
- "zh-CN": "zho_Hans",
346
- "zh-TW": "zho_Hant",
347
- "zh-HK": "zho_Hant",
348
- "ja-JP": "jpn_Jpan",
349
- "ko-KR": "kor_Hang",
350
- "th-TH": "tha_Thai",
351
- "vi-VN": "vie_Latn",
352
- "id-ID": "ind_Latn",
353
- "ms-MY": "zsm_Latn",
354
- "tl-PH": "tgl_Latn",
355
- "my-MM": "mya_Mymr",
356
- "km-KH": "khm_Khmr",
357
- "lo-LA": "lao_Laoo",
358
- "bn-BD": "ben_Beng",
359
- "bn-IN": "ben_Beng",
360
- "hi-IN": "hin_Deva",
361
- "ur-PK": "urd_Arab",
362
- "ur-IN": "urd_Arab",
363
- "pa-IN": "pan_Guru",
364
- "gu-IN": "guj_Gujr",
365
- "or-IN": "ory_Orya",
366
- "as-IN": "asm_Beng",
367
- "ml-IN": "mal_Mlym",
368
- "ta-IN": "tam_Tamil",
369
- "te-IN": "tel_Telu",
370
- "kn-IN": "kan_Knda",
371
- "si-LK": "sin_Sinh",
372
- "ne-NP": "nep_Deva",
373
- "dz-BT": "dzo_Tibt",
374
- "bo-CN": "bod_Tibt",
375
- "mn-MN": "khk_Cyrl",
376
- "ka-GE": "kat_Geor",
377
- "hy-AM": "hye_Armn",
378
- "az-AZ": "azj_Latn",
379
- "tr-TR": "tur_Latn",
380
- "fa-IR": "pes_Arab",
381
- "fa-AF": "pes_Arab",
382
- "ps-AF": "pbt_Arab",
383
- "ku-TR": "kmr_Latn",
384
- "he-IL": "heb_Hebr",
385
- "ar-SA": "arb_Arab",
386
- "ar-EG": "arb_Arab",
387
- "ar-MA": "arb_Arab",
388
- "ar-DZ": "arb_Arab",
389
- "ar-TN": "arb_Arab",
390
- "ar-LY": "arb_Arab",
391
- "ar-SD": "arb_Arab",
392
- "ar-IQ": "arb_Arab",
393
- "ar-SY": "arb_Arab",
394
- "ar-JO": "arb_Arab",
395
- "ar-LB": "arb_Arab",
396
- "ar-KW": "arb_Arab",
397
- "ar-AE": "arb_Arab",
398
- "ar-QA": "arb_Arab",
399
- "ar-BH": "arb_Arab",
400
- "ar-OM": "arb_Arab",
401
- "ar-YE": "arb_Arab",
402
- "ar-SO": "arb_Arab",
403
- "ar-DJ": "arb_Arab",
404
- "ar-KM": "arb_Arab",
405
- "ar-TD": "arb_Arab",
406
- "ar-ER": "arb_Arab",
407
- "ar-IL": "arb_Arab",
408
- "ar-PS": "arb_Arab",
409
- "ar-001": "arb_Arab",
410
- "sw-KE": "swh_Latn",
411
- "sw-TZ": "swh_Latn",
412
- "am-ET": "amh_Ethi",
413
- "om-ET": "gaz_Latn",
414
- "so-SO": "som_Latn",
415
- "ha-NG": "hau_Latn",
416
- "yo-NG": "yor_Latn",
417
- "ig-NG": "ibo_Latn",
418
- "zu-ZA": "zul_Latn",
419
- "xh-ZA": "xho_Latn",
420
- "rw-RW": "kin_Latn",
421
- "lg-UG": "lug_Latn",
422
- "ak-GH": "aka_Latn",
423
- "tw-GH": "twi_Latn",
424
- "ee-GH": "ewe_Latn",
425
- "ff-SN": "fuv_Latn",
426
- "wo-SN": "wol_Latn",
427
- "sn-ZW": "sna_Latn",
428
- "nd-ZW": "nde_Latn",
429
- "ny-MW": "nya_Latn",
430
- "st-ZA": "sot_Latn",
431
- "tn-BW": "tsn_Latn",
432
- "ts-ZA": "tso_Latn",
433
- "ve-ZA": "ven_Latn",
434
- "ss-ZA": "ssw_Latn",
435
- "nr-ZA": "nbl_Latn",
436
- "qu-PE": "quy_Latn",
437
- "qu-BO": "quy_Latn",
438
- "qu-EC": "quy_Latn",
439
- "ay-BO": "aym_Latn",
440
- "gn-PY": "grn_Latn",
441
- "ht-HT": "hat_Latn",
442
- "jv-ID": "jav_Latn",
443
- "su-ID": "sun_Latn",
444
- "ceb-PH": "ceb_Latn",
445
- "ilo-PH": "ilo_Latn",
446
- "war-PH": "war_Latn",
447
- "bjn-ID": "bjn_Latn",
448
- "ban-ID": "ban_Latn",
449
- "mad-ID": "mad_Latn",
450
- "min-ID": "min_Latn",
451
- "ace-ID": "ace_Latn",
452
- "bug-ID": "bug_Latn",
453
- "gor-ID": "gor_Latn",
454
- "mak-ID": "mak_Latn",
455
- "mdr-ID": "mdr_Latn",
456
- "sas-ID": "sas_Latn",
457
- "shn-MM": "shn_Mymr",
458
- "kac-MM": "kac_Latn",
459
- "lzh-CN": "lzh_Hant",
460
- "wuu-CN": "wuu_Hans",
461
- "yue-CN": "yue_Hant",
462
- "nan-TW": "nan_Hant",
463
- "hak-TW": "hak_Hant",
464
- "cjy-CN": "cjy_Hans",
465
- "cmn-CN": "cmn_Hans",
466
- "cmn-TW": "cmn_Hant",
467
- "cmn-SG": "cmn_Hans",
468
- "cmn-HK": "cmn_Hant",
469
- "cmn-MO": "cmn_Hant",
470
- "cmn-001": "cmn_Hans",
471
- "haw-US": "haw_Latn",
472
- "mi-NZ": "mri_Latn",
473
- "sm-WS": "smo_Latn",
474
- "to-TO": "ton_Latn",
475
- "fj-FJ": "fij_Latn",
476
- "ty-PF": "tah_Latn",
477
- "co-FR": "cos_Latn",
478
- "eu-FR": "eus_Latn",
479
- "kk-KZ": "kaz_Cyrl",
480
- "ky-KG": "kir_Cyrl",
481
- "uz-UZ": "uzn_Latn",
482
- "tg-TJ": "tgk_Cyrl",
483
- "tk-TM": "tuk_Latn"
484
- };
485
-
486
- // src/io/huggingface/ask.ts
487
- function getLanguageCode(language) {
488
- return languagesMap[language];
489
- }
490
- function progressCallback(progress) {
491
- process.stdout.clearLine(0);
492
- process.stdout.cursorTo(0);
493
- if (progress.status === "download") {
494
- process.stdout.write("Downloading...");
495
- } else if (progress.status === "initiate") {
496
- process.stdout.write("Initializing...");
497
- } else if (progress.status === "done") {
498
- process.stdout.write("Done!");
499
- } else if (progress.status === "progress" && "progress" in progress && "loaded" in progress && "total" in progress) {
500
- process.stdout.write(
501
- `Downloading: ${Number(progress.progress).toFixed(2)}%, loaded: ${progress.loaded}/${progress.total}`
502
- );
503
- }
504
- }
505
- async function pipeLanguage(pipe, original, srcLanguage, targetLanguage) {
506
- const response = await pipe(original, {
507
- src_lang: srcLanguage,
508
- tgt_lang: targetLanguage,
509
- temperature: 1
213
+ ${postPrompt2}`.trim();
214
+ const messages = [new Message("user", fullPrompt)];
215
+ const model = config.llm.model ?? "gpt-4o-mini";
216
+ const response = await engine.complete(engine.buildModel(model), messages, {
217
+ temperature: config.llm.temperature
510
218
  });
511
- return response;
512
- }
513
- async function askHuggingface(original) {
514
- const config = await awaitedConfig;
515
- const cacheDir = `${config.cache.dir}/.cache`;
516
- env.cacheDir = cacheDir;
517
- const pipe = await pipeline("translation", config.llm.model, {
518
- progress_callback: progressCallback,
519
- cache_dir: cacheDir
520
- });
521
- const { languages } = config;
522
- let responses = [];
523
- for await (const language of languages) {
524
- const response = await pipeLanguage(
525
- pipe,
526
- original,
527
- getLanguageCode(config.sourceLanguage),
528
- getLanguageCode(language)
529
- );
530
- if (Array.isArray(response)) {
531
- responses = responses.concat(
532
- response.map((r) => ({
533
- ...r,
534
- targetLanguage: language
535
- }))
536
- );
537
- } else {
538
- responses.push({
539
- ...response,
540
- targetLanguage: language
541
- });
542
- }
543
- }
544
- return { responses, original };
545
- }
546
-
547
- // src/io/huggingface/commit-response.ts
548
- function commitResponseHuggingface(response) {
549
- const { responses, original } = response;
550
- const translation = responses.reduce((acc, curr) => {
551
- acc[curr.targetLanguage] = curr.translation_text;
552
- return acc;
553
- }, {});
554
- return {
555
- translation,
556
- original
557
- };
558
- }
559
-
560
- // src/io/huggingface/parse.ts
561
- function parseHuggingface(unparsed) {
562
- if (typeof unparsed === "string") {
563
- throw new Error("CommitResponse should not be a string here.");
564
- }
565
- return unparsed;
566
- }
567
-
568
- // src/io/ask-llm.ts
569
- var llmChoices = {
570
- anthropic: {
571
- ask: askAnthropic,
572
- commitResponse: commitResponseAnthropic,
573
- parse: parseAnthropic
574
- },
575
- gemini: {
576
- ask: askGemini,
577
- commitResponse: commitResponseGemini,
578
- parse: parseGemini
579
- },
580
- huggingface: {
581
- ask: askHuggingface,
582
- commitResponse: commitResponseHuggingface,
583
- parse: parseHuggingface
219
+ if (config.debug) {
220
+ console.log("LLM response:", JSON.stringify({ provider, model: config.llm.model, response: response.content }));
584
221
  }
585
- };
586
- async function processLLMChoice(llmChoice, prompt, prePrompt2, postPrompt2) {
587
- const response = await llmChoice.ask(prompt, prePrompt2, postPrompt2);
588
- const unparsed = llmChoice.commitResponse(response);
589
- const parsed = llmChoice.parse(unparsed);
590
- return parsed;
591
- }
592
- async function askLLM(prompt, prePrompt2, postPrompt2) {
593
- const config = await awaitedConfig;
594
- const llmChoiceName = config.llm.choice;
595
- const llmChoice = llmChoices[llmChoiceName];
596
- if (!llmChoice) {
597
- throw new Error("LLMChoice not found");
222
+ if (!response.content) {
223
+ throw new Error("LLM response content is empty");
598
224
  }
599
- return processLLMChoice(llmChoice, prompt, prePrompt2, postPrompt2);
225
+ return parseResponse(response.content);
600
226
  }
601
227
 
602
228
  export { askLLM };
@@ -13257,7 +13257,7 @@ function afterEach(fn2, timeout) {
13257
13257
  globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
13258
13258
  globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
13259
13259
 
13260
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_terser@5.44.1/node_modules/vitest/dist/chunks/utils.C8RiOc4B.js
13260
+ // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_msw@2.12.8_@types+node@22.16.4_typescript@5.7.3__terser@5.44.1/node_modules/vitest/dist/chunks/utils.C8RiOc4B.js
13261
13261
  var NAME_WORKER_STATE = "__vitest_worker__";
13262
13262
  function getWorkerState() {
13263
13263
  const workerState = globalThis[NAME_WORKER_STATE];
@@ -13317,7 +13317,7 @@ async function waitForImportsToResolve() {
13317
13317
  await waitForImportsToResolve();
13318
13318
  }
13319
13319
 
13320
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_terser@5.44.1/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js
13320
+ // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_msw@2.12.8_@types+node@22.16.4_typescript@5.7.3__terser@5.44.1/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js
13321
13321
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
13322
13322
  function getDefaultExportFromCjs2(x2) {
13323
13323
  return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2;
@@ -15351,7 +15351,7 @@ var SnapshotClient = class {
15351
15351
  }
15352
15352
  };
15353
15353
 
15354
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_terser@5.44.1/node_modules/vitest/dist/chunks/date.W2xKR2qe.js
15354
+ // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_msw@2.12.8_@types+node@22.16.4_typescript@5.7.3__terser@5.44.1/node_modules/vitest/dist/chunks/date.W2xKR2qe.js
15355
15355
  var RealDate = Date;
15356
15356
  var now2 = null;
15357
15357
  var MockDate = class _MockDate extends RealDate {
@@ -15404,7 +15404,7 @@ function resetDate() {
15404
15404
  globalThis.Date = RealDate;
15405
15405
  }
15406
15406
 
15407
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_terser@5.44.1/node_modules/vitest/dist/chunks/vi.DgezovHB.js
15407
+ // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_msw@2.12.8_@types+node@22.16.4_typescript@5.7.3__terser@5.44.1/node_modules/vitest/dist/chunks/vi.DgezovHB.js
15408
15408
  var unsupported = [
15409
15409
  // .poll is meant to retry matchers until they succeed, and
15410
15410
  // snapshots will always succeed as long as the poll method doesn't thow an error
@@ -18136,7 +18136,7 @@ function getImporter(name) {
18136
18136
  return stack?.file || "";
18137
18137
  }
18138
18138
 
18139
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_terser@5.44.1/node_modules/vitest/dist/index.js
18139
+ // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4_lightningcss@1.30.2_msw@2.12.8_@types+node@22.16.4_typescript@5.7.3__terser@5.44.1/node_modules/vitest/dist/index.js
18140
18140
  __toESM(require_dist(), 1);
18141
18141
 
18142
18142
  // src/logger.ts