@gringow/gringow 0.1.2 → 0.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.
Files changed (54) hide show
  1. package/README.md +82 -40
  2. package/dist/browser.d.mts +2 -1
  3. package/dist/browser.mjs +61 -4
  4. package/dist/config.mjs +3 -3
  5. package/dist/config.test.mjs +50 -67
  6. package/dist/{data/create-cache-id.d.mts → create-cache-id.d.mts} +2 -2
  7. package/dist/create-cache-id.mjs +54 -0
  8. package/dist/create-cache-id.test.d.mts +2 -0
  9. package/dist/create-cache-id.test.mjs +18464 -0
  10. package/dist/data/check-cache.d.mts +1 -1
  11. package/dist/data/check-cache.mjs +12 -7
  12. package/dist/data/clear-cache.mjs +12 -7
  13. package/dist/data/create-cache-dir.mjs +3 -3
  14. package/dist/data/delete-cache-item.d.mts +1 -1
  15. package/dist/data/delete-cache-item.mjs +12 -7
  16. package/dist/data/get-cache.mjs +3 -3
  17. package/dist/data/get-or-create-cache.d.mts +1 -1
  18. package/dist/data/get-or-create-cache.mjs +12 -7
  19. package/dist/data/md5.d.mts +13 -0
  20. package/dist/data/md5.mjs +47 -0
  21. package/dist/data/md5.test.d.mts +2 -0
  22. package/dist/data/md5.test.mjs +18457 -0
  23. package/dist/data/save-cache.d.mts +2 -2
  24. package/dist/data/save-cache.mjs +12 -7
  25. package/dist/data/write-cache-to-disk.d.mts +1 -1
  26. package/dist/data/write-cache-to-disk.mjs +12 -7
  27. package/dist/flat-template-string.test.mjs +10 -10
  28. package/dist/gringow.d.mts +1 -1
  29. package/dist/gringow.mjs +98 -35
  30. package/dist/index.d.mts +1 -1
  31. package/dist/index.mjs +98 -35
  32. package/dist/interpolate-template.d.mts +3 -0
  33. package/dist/interpolate-template.mjs +14 -0
  34. package/dist/io/anthropic/ask.mjs +3 -3
  35. package/dist/io/anthropic/commit-response.d.mts +1 -1
  36. package/dist/io/anthropic/index.d.mts +1 -1
  37. package/dist/io/anthropic/index.mjs +3 -3
  38. package/dist/io/anthropic/parse.d.mts +1 -1
  39. package/dist/io/ask-llm.d.mts +1 -1
  40. package/dist/io/ask-llm.mjs +36 -25
  41. package/dist/io/gemini/ask.mjs +36 -25
  42. package/dist/io/gemini/index.d.mts +1 -1
  43. package/dist/io/gemini/index.mjs +36 -25
  44. package/dist/io/gemini/parse.d.mts +1 -1
  45. package/dist/io/huggingface/ask.d.mts +1 -1
  46. package/dist/io/huggingface/ask.mjs +3 -3
  47. package/dist/io/huggingface/commit-response.d.mts +1 -1
  48. package/dist/io/huggingface/index.d.mts +1 -1
  49. package/dist/io/huggingface/index.mjs +3 -3
  50. package/dist/io/huggingface/parse.d.mts +1 -1
  51. package/dist/logger.test.mjs +10 -10
  52. package/dist/types/index.d.mts +1 -1
  53. package/package.json +10 -10
  54. package/dist/data/create-cache-id.mjs +0 -10
@@ -3,8 +3,8 @@ import '../config.mjs';
3
3
  import '../constants/default-config.mjs';
4
4
  import 'zod';
5
5
  import '../schemas/config.shcema.mjs';
6
+ import '../create-cache-id.mjs';
6
7
  import './clear-cache.mjs';
7
- import './create-cache-id.mjs';
8
8
  import './get-cache.mjs';
9
9
  import '../flat-template-string.mjs';
10
10
 
@@ -14,6 +14,6 @@ import '../flat-template-string.mjs';
14
14
  * @param cache - The cache to save.
15
15
  * @returns The cache.
16
16
  */
17
- declare function saveCache(cache: GringowCache): Promise<void>;
17
+ declare function saveCache(cache: GringowCache): Promise<GringowCache>;
18
18
 
19
19
  export { saveCache };
@@ -104,9 +104,9 @@ async function loadUserConfig() {
104
104
  var awaitedConfig = loadUserConfig();
105
105
  function defaultPrePrompt(config, extraInstructions) {
106
106
  return `
107
- You are a translation generator.
107
+ You are a ultimate translation generator server api.
108
108
 
109
- Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting outside the JSON**.
109
+ Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
110
110
 
111
111
  Follow these rules strictly:
112
112
 
@@ -116,7 +116,7 @@ Follow these rules strictly:
116
116
  - Apply these creatively but **without altering the meaning or punctuation** of the original text.
117
117
  3. Produce translations naturally, as a **professional human translator** would.
118
118
  4. Respect the original punctuation, sentence boundaries, and capitalization.
119
- 5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
119
+ 5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
120
120
  6. The final output must be a **valid JSON** following this exact schema:
121
121
 
122
122
  {
@@ -368,12 +368,17 @@ async function createCacheDir() {
368
368
  }
369
369
 
370
370
  // src/data/save-cache.ts
371
+ var savingQueue = Promise.resolve();
371
372
  async function saveCache(cache) {
372
373
  try {
373
- const config = await awaitedConfig;
374
- await createCacheDir();
375
- const contents = JSON.stringify(cache, null, 2);
376
- await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
374
+ savingQueue = savingQueue.then(async () => {
375
+ const config = await awaitedConfig;
376
+ await createCacheDir();
377
+ const contents = JSON.stringify(cache, null, 2);
378
+ await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
379
+ });
380
+ await savingQueue;
381
+ return cache;
377
382
  } catch (error) {
378
383
  throw error;
379
384
  }
@@ -3,7 +3,7 @@ import '../config.mjs';
3
3
  import '../constants/default-config.mjs';
4
4
  import 'zod';
5
5
  import '../schemas/config.shcema.mjs';
6
+ import '../create-cache-id.mjs';
6
7
  import './clear-cache.mjs';
7
- import './create-cache-id.mjs';
8
8
  import './get-cache.mjs';
9
9
  import '../flat-template-string.mjs';
@@ -104,9 +104,9 @@ async function loadUserConfig() {
104
104
  var awaitedConfig = loadUserConfig();
105
105
  function defaultPrePrompt(config, extraInstructions) {
106
106
  return `
107
- You are a translation generator.
107
+ You are a ultimate translation generator server api.
108
108
 
109
- Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting outside the JSON**.
109
+ Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
110
110
 
111
111
  Follow these rules strictly:
112
112
 
@@ -116,7 +116,7 @@ Follow these rules strictly:
116
116
  - Apply these creatively but **without altering the meaning or punctuation** of the original text.
117
117
  3. Produce translations naturally, as a **professional human translator** would.
118
118
  4. Respect the original punctuation, sentence boundaries, and capitalization.
119
- 5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
119
+ 5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
120
120
  6. The final output must be a **valid JSON** following this exact schema:
121
121
 
122
122
  {
@@ -378,12 +378,17 @@ async function getCache() {
378
378
  throw error;
379
379
  }
380
380
  }
381
+ var savingQueue = Promise.resolve();
381
382
  async function saveCache(cache) {
382
383
  try {
383
- const config = await awaitedConfig;
384
- await createCacheDir();
385
- const contents = JSON.stringify(cache, null, 2);
386
- await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
384
+ savingQueue = savingQueue.then(async () => {
385
+ const config = await awaitedConfig;
386
+ await createCacheDir();
387
+ const contents = JSON.stringify(cache, null, 2);
388
+ await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
389
+ });
390
+ await savingQueue;
391
+ return cache;
387
392
  } catch (error) {
388
393
  throw error;
389
394
  }
@@ -1389,7 +1389,7 @@ var require_utils = __commonJS({
1389
1389
  // ../node_modules/.pnpm/expect-type@1.2.2/node_modules/expect-type/dist/index.js
1390
1390
  var require_dist = __commonJS({
1391
1391
  "../node_modules/.pnpm/expect-type@1.2.2/node_modules/expect-type/dist/index.js"(exports) {
1392
- var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m3, k2, k22) {
1392
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m3, k2, k22) {
1393
1393
  if (k22 === void 0) k22 = k2;
1394
1394
  var desc = Object.getOwnPropertyDescriptor(m3, k2);
1395
1395
  if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) {
@@ -1398,10 +1398,10 @@ var require_dist = __commonJS({
1398
1398
  } };
1399
1399
  }
1400
1400
  Object.defineProperty(o, k22, desc);
1401
- } : function(o, m3, k2, k22) {
1401
+ }) : (function(o, m3, k2, k22) {
1402
1402
  if (k22 === void 0) k22 = k2;
1403
1403
  o[k22] = m3[k2];
1404
- });
1404
+ }));
1405
1405
  var __exportStar = exports && exports.__exportStar || function(m3, exports2) {
1406
1406
  for (var p4 in m3) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p4)) __createBinding(exports2, m3, p4);
1407
1407
  };
@@ -13236,7 +13236,7 @@ function findTestFileStackTrace(error, each) {
13236
13236
  globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
13237
13237
  globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
13238
13238
 
13239
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4/node_modules/vitest/dist/chunks/utils.C8RiOc4B.js
13239
+ // ../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
13240
13240
  var NAME_WORKER_STATE = "__vitest_worker__";
13241
13241
  function getWorkerState() {
13242
13242
  const workerState = globalThis[NAME_WORKER_STATE];
@@ -13296,7 +13296,7 @@ async function waitForImportsToResolve() {
13296
13296
  await waitForImportsToResolve();
13297
13297
  }
13298
13298
 
13299
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js
13299
+ // ../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
13300
13300
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
13301
13301
  function getDefaultExportFromCjs2(x2) {
13302
13302
  return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2;
@@ -15330,7 +15330,7 @@ var SnapshotClient = class {
15330
15330
  }
15331
15331
  };
15332
15332
 
15333
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4/node_modules/vitest/dist/chunks/date.W2xKR2qe.js
15333
+ // ../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
15334
15334
  var RealDate = Date;
15335
15335
  var now2 = null;
15336
15336
  var MockDate = class _MockDate extends RealDate {
@@ -15383,7 +15383,7 @@ function resetDate() {
15383
15383
  globalThis.Date = RealDate;
15384
15384
  }
15385
15385
 
15386
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4/node_modules/vitest/dist/chunks/vi.DgezovHB.js
15386
+ // ../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
15387
15387
  var unsupported = [
15388
15388
  // .poll is meant to retry matchers until they succeed, and
15389
15389
  // snapshots will always succeed as long as the poll method doesn't thow an error
@@ -16212,7 +16212,7 @@ function requireTypeDetect() {
16212
16212
  (function(module, exports) {
16213
16213
  (function(global3, factory) {
16214
16214
  module.exports = factory();
16215
- })(typeDetect, function() {
16215
+ })(typeDetect, (function() {
16216
16216
  var promiseExists = typeof Promise === "function";
16217
16217
  var globalObject = typeof self === "object" ? self : commonjsGlobal;
16218
16218
  var symbolExists = typeof Symbol !== "undefined";
@@ -16321,7 +16321,7 @@ function requireTypeDetect() {
16321
16321
  return Object.prototype.toString.call(obj).slice(toStringLeftSliceLength, toStringRightSliceLength);
16322
16322
  }
16323
16323
  return typeDetect2;
16324
- });
16324
+ }));
16325
16325
  })(typeDetect$1);
16326
16326
  return typeDetect$1.exports;
16327
16327
  }
@@ -18115,7 +18115,7 @@ function getImporter(name) {
18115
18115
  return stack?.file || "";
18116
18116
  }
18117
18117
 
18118
- // ../node_modules/.pnpm/vitest@2.1.9_@types+node@22.16.4/node_modules/vitest/dist/index.js
18118
+ // ../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
18119
18119
  __toESM(require_dist(), 1);
18120
18120
 
18121
18121
  // src/flat-template-string.ts
@@ -3,7 +3,7 @@ import './config.mjs';
3
3
  import './constants/default-config.mjs';
4
4
  import 'zod';
5
5
  import './schemas/config.shcema.mjs';
6
+ import './create-cache-id.mjs';
6
7
  import './data/clear-cache.mjs';
7
- import './data/create-cache-id.mjs';
8
8
  import './data/get-cache.mjs';
9
9
  import './flat-template-string.mjs';
package/dist/gringow.mjs CHANGED
@@ -4,7 +4,6 @@ import { z } from 'zod';
4
4
  import fs from 'fs/promises';
5
5
  import { dirname, resolve, parse } from 'path';
6
6
  import { mkdir, stat, statSync, mkdirSync } from 'fs';
7
- import CryptoJS from 'crypto-js';
8
7
  import Anthropic from '@anthropic-ai/sdk';
9
8
  import { GoogleGenerativeAI } from '@google/generative-ai';
10
9
  import { env, pipeline } from '@huggingface/transformers';
@@ -108,9 +107,9 @@ async function loadUserConfig() {
108
107
  var awaitedConfig = loadUserConfig();
109
108
  function defaultPrePrompt(config, extraInstructions) {
110
109
  return `
111
- You are a translation generator.
110
+ You are a ultimate translation generator server api.
112
111
 
113
- Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting outside the JSON**.
112
+ Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
114
113
 
115
114
  Follow these rules strictly:
116
115
 
@@ -120,7 +119,7 @@ Follow these rules strictly:
120
119
  - Apply these creatively but **without altering the meaning or punctuation** of the original text.
121
120
  3. Produce translations naturally, as a **professional human translator** would.
122
121
  4. Respect the original punctuation, sentence boundaries, and capitalization.
123
- 5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
122
+ 5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
124
123
  6. The final output must be a **valid JSON** following this exact schema:
125
124
 
126
125
  {
@@ -159,6 +158,59 @@ function postPrompt(config, prepend, replace) {
159
158
  replace ? String(replace) : defaultPostPrompt()
160
159
  ].join(" ").trim();
161
160
  }
161
+
162
+ // src/data/md5.ts
163
+ var INITIAL_STATE = [1831565813, 461845907, 2246822507, 3266489909];
164
+ var MULTIPLIERS = [668265261, 374761393, 2654435769, 2496678331];
165
+ var AVA_MULT1 = 2146121005;
166
+ var AVA_MULT2 = 2221713035;
167
+ function seedState(input) {
168
+ const state = [...INITIAL_STATE];
169
+ for (const char of input) {
170
+ const codePoint = char.codePointAt(0) ?? 0;
171
+ for (let i = 0; i < state.length; i++) {
172
+ state[i] = Math.imul(state[i] ^ codePoint, MULTIPLIERS[i]);
173
+ state[i] = rotateLeft(state[i], (i + 1) * 3);
174
+ }
175
+ state[0] ^= state[3] >>> 11;
176
+ state[1] ^= state[0] << 7;
177
+ state[2] ^= state[1] >>> 13;
178
+ state[3] ^= state[2] << 5;
179
+ }
180
+ return state;
181
+ }
182
+ function rotateLeft(value, shift) {
183
+ return value << shift | value >>> 32 - shift;
184
+ }
185
+ function avalanche(value) {
186
+ value ^= value >>> 16;
187
+ value = Math.imul(value, AVA_MULT1);
188
+ value ^= value >>> 15;
189
+ value = Math.imul(value, AVA_MULT2);
190
+ value ^= value >>> 16;
191
+ return value >>> 0;
192
+ }
193
+ function toHex(value) {
194
+ return (value >>> 0).toString(16).padStart(8, "0");
195
+ }
196
+ function mixState([h1, h2, h3, h4]) {
197
+ h1 = avalanche(h1 ^ h3);
198
+ h2 = avalanche(h2 ^ h4);
199
+ h3 = avalanche(h3 ^ h1);
200
+ h4 = avalanche(h4 ^ h2);
201
+ return [h1, h2, h3, h4];
202
+ }
203
+ function md5(input) {
204
+ const state = mixState(seedState(input));
205
+ return state.map(toHex).join("");
206
+ }
207
+
208
+ // src/create-cache-id.ts
209
+ function createCacheId(text) {
210
+ const hexHash = md5(text);
211
+ const cacheId = `gid_${hexHash}`;
212
+ return cacheId;
213
+ }
162
214
  var optsArg = (opts) => {
163
215
  if (!opts) {
164
216
  opts = { mode: 511 };
@@ -382,12 +434,17 @@ async function getCache() {
382
434
  throw error;
383
435
  }
384
436
  }
437
+ var savingQueue = Promise.resolve();
385
438
  async function saveCache(cache) {
386
439
  try {
387
- const config = await awaitedConfig;
388
- await createCacheDir();
389
- const contents = JSON.stringify(cache, null, 2);
390
- await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
440
+ savingQueue = savingQueue.then(async () => {
441
+ const config = await awaitedConfig;
442
+ await createCacheDir();
443
+ const contents = JSON.stringify(cache, null, 2);
444
+ await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
445
+ });
446
+ await savingQueue;
447
+ return cache;
391
448
  } catch (error) {
392
449
  throw error;
393
450
  }
@@ -460,11 +517,6 @@ async function checkCache(cacheId) {
460
517
  }
461
518
  return void 0;
462
519
  }
463
- function createCacheId(text) {
464
- const hexHash = CryptoJS.MD5(text).toString();
465
- const cacheId = `gid_${hexHash}`;
466
- return cacheId;
467
- }
468
520
 
469
521
  // src/data/write-cache-to-disk.ts
470
522
  async function writeCacheToDisk(cacheId, cached) {
@@ -537,23 +589,40 @@ function parseAnthropic(unparsed) {
537
589
  const parsed = JSON.parse(unparsed);
538
590
  return parsed;
539
591
  }
540
- async function generateResponse(prompt, temperature = 1) {
541
- const config = await awaitedConfig;
542
- if (!config.keys.geminiApiKey) {
543
- throw new Error("Gemini API key is not set in the config");
544
- }
545
- const generativeAIClient = new GoogleGenerativeAI(config.keys.geminiApiKey);
546
- const model = generativeAIClient.getGenerativeModel({
547
- model: config.llm.model,
548
- generationConfig: {
549
- temperature
592
+ async function generateResponse(prompt, config) {
593
+ try {
594
+ if (!config.keys.geminiApiKey) {
595
+ throw new Error("Gemini API key is not set in the config");
550
596
  }
551
- });
552
- if (config.debug) {
553
- console.log("Gemini model prompt:", JSON.stringify({ prompt }));
597
+ const generativeAIClient = new GoogleGenerativeAI(config.keys.geminiApiKey);
598
+ const model = generativeAIClient.getGenerativeModel({
599
+ model: config.llm.model,
600
+ generationConfig: {
601
+ temperature: config.llm.temperature ?? 0.8
602
+ }
603
+ });
604
+ if (config.debug) {
605
+ console.log("Gemini model prompt:", JSON.stringify({ prompt }));
606
+ }
607
+ const response = await model.generateContent([prompt]);
608
+ return response;
609
+ } catch (err) {
610
+ const error = err;
611
+ console.log("Error details from Gemini model", JSON.stringify({ error }, null, 2));
612
+ const retryDelay = error?.errorDetails?.find(
613
+ (detail) => detail?.["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
614
+ )?.retryDelay ?? void 0;
615
+ if (error.status === 429 && retryDelay !== void 0) {
616
+ const sleepTime = config.llm.sleep ?? 3;
617
+ console.warn(
618
+ `Rate limit exceeded when generating response from Gemini model, retrying in... ${retryDelay} + ${sleepTime / 1e3}s`
619
+ );
620
+ await new Promise((resolve2) => setTimeout(resolve2, (parseInt(retryDelay, 10) + sleepTime / 1e3) * 1e3));
621
+ return generateResponse(prompt, config);
622
+ }
623
+ console.error("Error generating response from Gemini model", { error });
624
+ throw error;
554
625
  }
555
- const response = await model.generateContent([prompt]);
556
- return response;
557
626
  }
558
627
  async function askGemini(prompt, prePrompt2, postPrompt2) {
559
628
  const config = await awaitedConfig;
@@ -575,13 +644,7 @@ ${prompt}
575
644
  ${postPrompt2}`).trim();
576
645
  let response;
577
646
  for (let i = 0; i < 3; i++) {
578
- const maybeResponse = await generateResponse(fullPrompt, config.llm.temperature);
579
- console.log(
580
- "maybeResponse:",
581
- "\n\n",
582
- JSON.stringify({ maybeResponse: maybeResponse.response.candidates?.[0]?.content?.parts?.[0]?.text }),
583
- "\n"
584
- );
647
+ const maybeResponse = await generateResponse(fullPrompt, config);
585
648
  const responseString = String(maybeResponse.response.candidates?.[0]?.content?.parts?.[0]?.text ?? "").replace(/```json/g, "").replace(/```/g, "").trim();
586
649
  if (responseString.startsWith("{") && responseString.endsWith("}")) {
587
650
  response = maybeResponse;
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { awaitedConfig, getConfigSource, isLocalConfigFound } from './config.mjs';
2
+ export { createCacheId } from './create-cache-id.mjs';
2
3
  export { clearCache } from './data/clear-cache.mjs';
3
- export { createCacheId } from './data/create-cache-id.mjs';
4
4
  export { getCache } from './data/get-cache.mjs';
5
5
  export { flatTemplateString } from './flat-template-string.mjs';
6
6
  export { GringowConfig } from './constants/default-config.mjs';
package/dist/index.mjs CHANGED
@@ -4,7 +4,6 @@ import { z } from 'zod';
4
4
  import fs from 'fs/promises';
5
5
  import { dirname, resolve, parse } from 'path';
6
6
  import { mkdir, stat, statSync, mkdirSync } from 'fs';
7
- import CryptoJS from 'crypto-js';
8
7
  import Anthropic from '@anthropic-ai/sdk';
9
8
  import { GoogleGenerativeAI } from '@google/generative-ai';
10
9
  import { env, pipeline } from '@huggingface/transformers';
@@ -114,9 +113,9 @@ async function loadUserConfig() {
114
113
  var awaitedConfig = loadUserConfig();
115
114
  function defaultPrePrompt(config, extraInstructions) {
116
115
  return `
117
- You are a translation generator.
116
+ You are a ultimate translation generator server api.
118
117
 
119
- Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting outside the JSON**.
118
+ Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
120
119
 
121
120
  Follow these rules strictly:
122
121
 
@@ -126,7 +125,7 @@ Follow these rules strictly:
126
125
  - Apply these creatively but **without altering the meaning or punctuation** of the original text.
127
126
  3. Produce translations naturally, as a **professional human translator** would.
128
127
  4. Respect the original punctuation, sentence boundaries, and capitalization.
129
- 5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
128
+ 5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
130
129
  6. The final output must be a **valid JSON** following this exact schema:
131
130
 
132
131
  {
@@ -165,6 +164,59 @@ function postPrompt(config, prepend, replace) {
165
164
  replace ? String(replace) : defaultPostPrompt()
166
165
  ].join(" ").trim();
167
166
  }
167
+
168
+ // src/data/md5.ts
169
+ var INITIAL_STATE = [1831565813, 461845907, 2246822507, 3266489909];
170
+ var MULTIPLIERS = [668265261, 374761393, 2654435769, 2496678331];
171
+ var AVA_MULT1 = 2146121005;
172
+ var AVA_MULT2 = 2221713035;
173
+ function seedState(input) {
174
+ const state = [...INITIAL_STATE];
175
+ for (const char of input) {
176
+ const codePoint = char.codePointAt(0) ?? 0;
177
+ for (let i = 0; i < state.length; i++) {
178
+ state[i] = Math.imul(state[i] ^ codePoint, MULTIPLIERS[i]);
179
+ state[i] = rotateLeft(state[i], (i + 1) * 3);
180
+ }
181
+ state[0] ^= state[3] >>> 11;
182
+ state[1] ^= state[0] << 7;
183
+ state[2] ^= state[1] >>> 13;
184
+ state[3] ^= state[2] << 5;
185
+ }
186
+ return state;
187
+ }
188
+ function rotateLeft(value, shift) {
189
+ return value << shift | value >>> 32 - shift;
190
+ }
191
+ function avalanche(value) {
192
+ value ^= value >>> 16;
193
+ value = Math.imul(value, AVA_MULT1);
194
+ value ^= value >>> 15;
195
+ value = Math.imul(value, AVA_MULT2);
196
+ value ^= value >>> 16;
197
+ return value >>> 0;
198
+ }
199
+ function toHex(value) {
200
+ return (value >>> 0).toString(16).padStart(8, "0");
201
+ }
202
+ function mixState([h1, h2, h3, h4]) {
203
+ h1 = avalanche(h1 ^ h3);
204
+ h2 = avalanche(h2 ^ h4);
205
+ h3 = avalanche(h3 ^ h1);
206
+ h4 = avalanche(h4 ^ h2);
207
+ return [h1, h2, h3, h4];
208
+ }
209
+ function md5(input) {
210
+ const state = mixState(seedState(input));
211
+ return state.map(toHex).join("");
212
+ }
213
+
214
+ // src/create-cache-id.ts
215
+ function createCacheId(text) {
216
+ const hexHash = md5(text);
217
+ const cacheId = `gid_${hexHash}`;
218
+ return cacheId;
219
+ }
168
220
  var optsArg = (opts) => {
169
221
  if (!opts) {
170
222
  opts = { mode: 511 };
@@ -388,12 +440,17 @@ async function getCache() {
388
440
  throw error;
389
441
  }
390
442
  }
443
+ var savingQueue = Promise.resolve();
391
444
  async function saveCache(cache) {
392
445
  try {
393
- const config = await awaitedConfig;
394
- await createCacheDir();
395
- const contents = JSON.stringify(cache, null, 2);
396
- await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
446
+ savingQueue = savingQueue.then(async () => {
447
+ const config = await awaitedConfig;
448
+ await createCacheDir();
449
+ const contents = JSON.stringify(cache, null, 2);
450
+ await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
451
+ });
452
+ await savingQueue;
453
+ return cache;
397
454
  } catch (error) {
398
455
  throw error;
399
456
  }
@@ -471,11 +528,6 @@ async function checkCache(cacheId) {
471
528
  async function clearCache() {
472
529
  await saveCache({});
473
530
  }
474
- function createCacheId(text) {
475
- const hexHash = CryptoJS.MD5(text).toString();
476
- const cacheId = `gid_${hexHash}`;
477
- return cacheId;
478
- }
479
531
 
480
532
  // src/data/delete-cache-item.ts
481
533
  async function deleteCacheItem(cacheId) {
@@ -559,23 +611,40 @@ function parseAnthropic(unparsed) {
559
611
  const parsed = JSON.parse(unparsed);
560
612
  return parsed;
561
613
  }
562
- async function generateResponse(prompt, temperature = 1) {
563
- const config = await awaitedConfig;
564
- if (!config.keys.geminiApiKey) {
565
- throw new Error("Gemini API key is not set in the config");
566
- }
567
- const generativeAIClient = new GoogleGenerativeAI(config.keys.geminiApiKey);
568
- const model = generativeAIClient.getGenerativeModel({
569
- model: config.llm.model,
570
- generationConfig: {
571
- temperature
614
+ async function generateResponse(prompt, config) {
615
+ try {
616
+ if (!config.keys.geminiApiKey) {
617
+ throw new Error("Gemini API key is not set in the config");
572
618
  }
573
- });
574
- if (config.debug) {
575
- console.log("Gemini model prompt:", JSON.stringify({ prompt }));
619
+ const generativeAIClient = new GoogleGenerativeAI(config.keys.geminiApiKey);
620
+ const model = generativeAIClient.getGenerativeModel({
621
+ model: config.llm.model,
622
+ generationConfig: {
623
+ temperature: config.llm.temperature ?? 0.8
624
+ }
625
+ });
626
+ if (config.debug) {
627
+ console.log("Gemini model prompt:", JSON.stringify({ prompt }));
628
+ }
629
+ const response = await model.generateContent([prompt]);
630
+ return response;
631
+ } catch (err) {
632
+ const error = err;
633
+ console.log("Error details from Gemini model", JSON.stringify({ error }, null, 2));
634
+ const retryDelay = error?.errorDetails?.find(
635
+ (detail) => detail?.["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
636
+ )?.retryDelay ?? void 0;
637
+ if (error.status === 429 && retryDelay !== void 0) {
638
+ const sleepTime = config.llm.sleep ?? 3;
639
+ console.warn(
640
+ `Rate limit exceeded when generating response from Gemini model, retrying in... ${retryDelay} + ${sleepTime / 1e3}s`
641
+ );
642
+ await new Promise((resolve2) => setTimeout(resolve2, (parseInt(retryDelay, 10) + sleepTime / 1e3) * 1e3));
643
+ return generateResponse(prompt, config);
644
+ }
645
+ console.error("Error generating response from Gemini model", { error });
646
+ throw error;
576
647
  }
577
- const response = await model.generateContent([prompt]);
578
- return response;
579
648
  }
580
649
  async function askGemini(prompt, prePrompt2, postPrompt2) {
581
650
  const config = await awaitedConfig;
@@ -597,13 +666,7 @@ ${prompt}
597
666
  ${postPrompt2}`).trim();
598
667
  let response;
599
668
  for (let i = 0; i < 3; i++) {
600
- const maybeResponse = await generateResponse(fullPrompt, config.llm.temperature);
601
- console.log(
602
- "maybeResponse:",
603
- "\n\n",
604
- JSON.stringify({ maybeResponse: maybeResponse.response.candidates?.[0]?.content?.parts?.[0]?.text }),
605
- "\n"
606
- );
669
+ const maybeResponse = await generateResponse(fullPrompt, config);
607
670
  const responseString = String(maybeResponse.response.candidates?.[0]?.content?.parts?.[0]?.text ?? "").replace(/```json/g, "").replace(/```/g, "").trim();
608
671
  if (responseString.startsWith("{") && responseString.endsWith("}")) {
609
672
  response = maybeResponse;
@@ -0,0 +1,3 @@
1
+ declare function interpolateTemplate(template: string, values: unknown[]): string;
2
+
3
+ export { interpolateTemplate };
@@ -0,0 +1,14 @@
1
+ // src/interpolate-template.ts
2
+ function interpolateTemplate(template, values) {
3
+ if (!values || values.length === 0) return template;
4
+ let valueIndex = 0;
5
+ return template.replace(/\$\{[^}]*\}/g, () => {
6
+ if (valueIndex < values.length) {
7
+ const value = values[valueIndex++];
8
+ return value === null || value === void 0 ? "" : String(value);
9
+ }
10
+ return "";
11
+ });
12
+ }
13
+
14
+ export { interpolateTemplate };
@@ -102,9 +102,9 @@ async function loadUserConfig() {
102
102
  var awaitedConfig = loadUserConfig();
103
103
  function defaultPrePrompt(config, extraInstructions) {
104
104
  return `
105
- You are a translation generator.
105
+ You are a ultimate translation generator server api.
106
106
 
107
- Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting outside the JSON**.
107
+ Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
108
108
 
109
109
  Follow these rules strictly:
110
110
 
@@ -114,7 +114,7 @@ Follow these rules strictly:
114
114
  - Apply these creatively but **without altering the meaning or punctuation** of the original text.
115
115
  3. Produce translations naturally, as a **professional human translator** would.
116
116
  4. Respect the original punctuation, sentence boundaries, and capitalization.
117
- 5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
117
+ 5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
118
118
  6. The final output must be a **valid JSON** following this exact schema:
119
119
 
120
120
  {
@@ -5,8 +5,8 @@ import '../../index.mjs';
5
5
  import '../../config.mjs';
6
6
  import '../../constants/default-config.mjs';
7
7
  import '../../schemas/config.shcema.mjs';
8
+ import '../../create-cache-id.mjs';
8
9
  import '../../data/clear-cache.mjs';
9
- import '../../data/create-cache-id.mjs';
10
10
  import '../../data/get-cache.mjs';
11
11
  import '../../flat-template-string.mjs';
12
12
 
@@ -8,7 +8,7 @@ import '../../index.mjs';
8
8
  import '../../config.mjs';
9
9
  import '../../constants/default-config.mjs';
10
10
  import '../../schemas/config.shcema.mjs';
11
+ import '../../create-cache-id.mjs';
11
12
  import '../../data/clear-cache.mjs';
12
- import '../../data/create-cache-id.mjs';
13
13
  import '../../data/get-cache.mjs';
14
14
  import '../../flat-template-string.mjs';