arendi-cli 0.1.0 → 0.1.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.
- package/dist/index.js +411 -11
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -46,7 +46,9 @@ var optionsSchema = z.object({
|
|
|
46
46
|
apiKey: z.string().min(1, "LLM provider API key is required"),
|
|
47
47
|
tavilyApiKey: z.string().min(1, "Tavily API key is required"),
|
|
48
48
|
/** Optional ISO 3166-1 alpha-2 code for Google Trends (e.g. "US", "ID"). Auto-detected from `country` if omitted. */
|
|
49
|
-
geo: z.string().length(2).optional()
|
|
49
|
+
geo: z.string().length(2).optional(),
|
|
50
|
+
/** Optional ISO 639-1 language code (e.g. "id", "es", "fr"). Auto-detected from `country` if omitted. Used for local-language source discovery and Google Trends `hl` parameter. */
|
|
51
|
+
language: z.string().optional()
|
|
50
52
|
});
|
|
51
53
|
var tavilyResultSchema = z.object({
|
|
52
54
|
title: z.string(),
|
|
@@ -211,6 +213,364 @@ import { createHash } from "crypto";
|
|
|
211
213
|
|
|
212
214
|
// ../../packages/arendi/dist/trends.js
|
|
213
215
|
import googleTrends from "google-trends-api";
|
|
216
|
+
|
|
217
|
+
// ../../packages/arendi/dist/languages.js
|
|
218
|
+
var COUNTRY_LANGUAGE_MAP = {
|
|
219
|
+
afghanistan: "fa",
|
|
220
|
+
albania: "sq",
|
|
221
|
+
algeria: "ar",
|
|
222
|
+
argentina: "es",
|
|
223
|
+
austria: "de",
|
|
224
|
+
bangladesh: "bn",
|
|
225
|
+
belgium: "nl",
|
|
226
|
+
bolivia: "es",
|
|
227
|
+
brazil: "pt",
|
|
228
|
+
cambodia: "km",
|
|
229
|
+
cameroon: "fr",
|
|
230
|
+
chile: "es",
|
|
231
|
+
china: "zh",
|
|
232
|
+
colombia: "es",
|
|
233
|
+
"costa rica": "es",
|
|
234
|
+
croatia: "hr",
|
|
235
|
+
"czech republic": "cs",
|
|
236
|
+
czechia: "cs",
|
|
237
|
+
denmark: "da",
|
|
238
|
+
"dominican republic": "es",
|
|
239
|
+
ecuador: "es",
|
|
240
|
+
egypt: "ar",
|
|
241
|
+
"el salvador": "es",
|
|
242
|
+
ethiopia: "am",
|
|
243
|
+
finland: "fi",
|
|
244
|
+
france: "fr",
|
|
245
|
+
germany: "de",
|
|
246
|
+
greece: "el",
|
|
247
|
+
guatemala: "es",
|
|
248
|
+
honduras: "es",
|
|
249
|
+
"hong kong": "zh",
|
|
250
|
+
hungary: "hu",
|
|
251
|
+
india: "hi",
|
|
252
|
+
indonesia: "id",
|
|
253
|
+
iran: "fa",
|
|
254
|
+
iraq: "ar",
|
|
255
|
+
israel: "he",
|
|
256
|
+
italy: "it",
|
|
257
|
+
japan: "ja",
|
|
258
|
+
jordan: "ar",
|
|
259
|
+
kazakhstan: "kk",
|
|
260
|
+
kuwait: "ar",
|
|
261
|
+
laos: "lo",
|
|
262
|
+
lebanon: "ar",
|
|
263
|
+
libya: "ar",
|
|
264
|
+
malaysia: "ms",
|
|
265
|
+
mexico: "es",
|
|
266
|
+
morocco: "ar",
|
|
267
|
+
myanmar: "my",
|
|
268
|
+
nepal: "ne",
|
|
269
|
+
netherlands: "nl",
|
|
270
|
+
nicaragua: "es",
|
|
271
|
+
norway: "no",
|
|
272
|
+
oman: "ar",
|
|
273
|
+
pakistan: "ur",
|
|
274
|
+
panama: "es",
|
|
275
|
+
paraguay: "es",
|
|
276
|
+
peru: "es",
|
|
277
|
+
philippines: "tl",
|
|
278
|
+
poland: "pl",
|
|
279
|
+
portugal: "pt",
|
|
280
|
+
qatar: "ar",
|
|
281
|
+
romania: "ro",
|
|
282
|
+
russia: "ru",
|
|
283
|
+
"saudi arabia": "ar",
|
|
284
|
+
senegal: "fr",
|
|
285
|
+
serbia: "sr",
|
|
286
|
+
spain: "es",
|
|
287
|
+
"sri lanka": "si",
|
|
288
|
+
sweden: "sv",
|
|
289
|
+
switzerland: "de",
|
|
290
|
+
taiwan: "zh",
|
|
291
|
+
tanzania: "sw",
|
|
292
|
+
thailand: "th",
|
|
293
|
+
tunisia: "ar",
|
|
294
|
+
turkey: "tr",
|
|
295
|
+
turkiye: "tr",
|
|
296
|
+
ukraine: "uk",
|
|
297
|
+
"united arab emirates": "ar",
|
|
298
|
+
uae: "ar",
|
|
299
|
+
uruguay: "es",
|
|
300
|
+
uzbekistan: "uz",
|
|
301
|
+
venezuela: "es",
|
|
302
|
+
vietnam: "vi"
|
|
303
|
+
};
|
|
304
|
+
var LANGUAGE_INFO = {
|
|
305
|
+
// --- Southeast Asia -------------------------------------------------------
|
|
306
|
+
id: {
|
|
307
|
+
name: "Indonesian",
|
|
308
|
+
nativeName: "Bahasa Indonesia",
|
|
309
|
+
discoveryQueries: [
|
|
310
|
+
"situs berita bisnis lokal terbaik di {location}",
|
|
311
|
+
"media online ekonomi startup {location}",
|
|
312
|
+
"koran digital bisnis {location} terpopuler"
|
|
313
|
+
]
|
|
314
|
+
},
|
|
315
|
+
ms: {
|
|
316
|
+
name: "Malay",
|
|
317
|
+
nativeName: "Bahasa Melayu",
|
|
318
|
+
discoveryQueries: [
|
|
319
|
+
"laman web berita perniagaan tempatan terbaik di {location}",
|
|
320
|
+
"media dalam talian ekonomi startup {location}",
|
|
321
|
+
"akhbar digital perniagaan {location} paling popular"
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
th: {
|
|
325
|
+
name: "Thai",
|
|
326
|
+
nativeName: "\u0E20\u0E32\u0E29\u0E32\u0E44\u0E17\u0E22",
|
|
327
|
+
discoveryQueries: [
|
|
328
|
+
"\u0E40\u0E27\u0E47\u0E1A\u0E44\u0E0B\u0E15\u0E4C\u0E02\u0E48\u0E32\u0E27\u0E18\u0E38\u0E23\u0E01\u0E34\u0E08\u0E17\u0E49\u0E2D\u0E07\u0E16\u0E34\u0E48\u0E19\u0E17\u0E35\u0E48\u0E14\u0E35\u0E17\u0E35\u0E48\u0E2A\u0E38\u0E14\u0E43\u0E19 {location}",
|
|
329
|
+
"\u0E2A\u0E37\u0E48\u0E2D\u0E14\u0E34\u0E08\u0E34\u0E17\u0E31\u0E25 \u0E40\u0E28\u0E23\u0E29\u0E10\u0E01\u0E34\u0E08 \u0E2A\u0E15\u0E32\u0E23\u0E4C\u0E17\u0E2D\u0E31\u0E1E {location}",
|
|
330
|
+
"\u0E2B\u0E19\u0E31\u0E07\u0E2A\u0E37\u0E2D\u0E1E\u0E34\u0E21\u0E1E\u0E4C\u0E2D\u0E2D\u0E19\u0E44\u0E25\u0E19\u0E4C\u0E18\u0E38\u0E23\u0E01\u0E34\u0E08 {location} \u0E22\u0E2D\u0E14\u0E19\u0E34\u0E22\u0E21"
|
|
331
|
+
]
|
|
332
|
+
},
|
|
333
|
+
vi: {
|
|
334
|
+
name: "Vietnamese",
|
|
335
|
+
nativeName: "Ti\u1EBFng Vi\u1EC7t",
|
|
336
|
+
discoveryQueries: [
|
|
337
|
+
"trang web tin t\u1EE9c kinh doanh \u0111\u1ECBa ph\u01B0\u01A1ng t\u1ED1t nh\u1EA5t t\u1EA1i {location}",
|
|
338
|
+
"truy\u1EC1n th\xF4ng s\u1ED1 kinh t\u1EBF startup {location}",
|
|
339
|
+
"b\xE1o \u0111i\u1EC7n t\u1EED kinh doanh {location} ph\u1ED5 bi\u1EBFn nh\u1EA5t"
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
tl: {
|
|
343
|
+
name: "Filipino",
|
|
344
|
+
nativeName: "Tagalog",
|
|
345
|
+
discoveryQueries: [
|
|
346
|
+
"pinakamahusay na lokal na website ng balita sa negosyo sa {location}",
|
|
347
|
+
"digital media ekonomiya startup {location}",
|
|
348
|
+
"pinakasikat na online na pahayagan ng negosyo {location}"
|
|
349
|
+
]
|
|
350
|
+
},
|
|
351
|
+
// --- East Asia ------------------------------------------------------------
|
|
352
|
+
ja: {
|
|
353
|
+
name: "Japanese",
|
|
354
|
+
nativeName: "\u65E5\u672C\u8A9E",
|
|
355
|
+
discoveryQueries: [
|
|
356
|
+
"{location} \u30D3\u30B8\u30CD\u30B9\u30CB\u30E5\u30FC\u30B9\u30B5\u30A4\u30C8 \u304A\u3059\u3059\u3081",
|
|
357
|
+
"{location} \u7D4C\u6E08 \u30B9\u30BF\u30FC\u30C8\u30A2\u30C3\u30D7 \u30E1\u30C7\u30A3\u30A2",
|
|
358
|
+
"{location} \u30D3\u30B8\u30CD\u30B9 \u30AA\u30F3\u30E9\u30A4\u30F3\u65B0\u805E \u4EBA\u6C17"
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
ko: {
|
|
362
|
+
name: "Korean",
|
|
363
|
+
nativeName: "\uD55C\uAD6D\uC5B4",
|
|
364
|
+
discoveryQueries: [
|
|
365
|
+
"{location} \uBE44\uC988\uB2C8\uC2A4 \uB274\uC2A4 \uC0AC\uC774\uD2B8 \uCD94\uCC9C",
|
|
366
|
+
"{location} \uACBD\uC81C \uC2A4\uD0C0\uD2B8\uC5C5 \uBBF8\uB514\uC5B4",
|
|
367
|
+
"{location} \uBE44\uC988\uB2C8\uC2A4 \uC628\uB77C\uC778 \uC2E0\uBB38 \uC778\uAE30"
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
zh: {
|
|
371
|
+
name: "Chinese",
|
|
372
|
+
nativeName: "\u4E2D\u6587",
|
|
373
|
+
discoveryQueries: [
|
|
374
|
+
"{location} \u5546\u4E1A\u65B0\u95FB\u7F51\u7AD9 \u63A8\u8350",
|
|
375
|
+
"{location} \u7ECF\u6D4E \u521B\u4E1A \u5A92\u4F53",
|
|
376
|
+
"{location} \u5546\u4E1A \u5728\u7EBF\u62A5\u7EB8 \u70ED\u95E8"
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
// --- South Asia -----------------------------------------------------------
|
|
380
|
+
hi: {
|
|
381
|
+
name: "Hindi",
|
|
382
|
+
nativeName: "\u0939\u093F\u0928\u094D\u0926\u0940",
|
|
383
|
+
discoveryQueries: [
|
|
384
|
+
"{location} \u092E\u0947\u0902 \u0938\u0930\u094D\u0935\u0936\u094D\u0930\u0947\u0937\u094D\u0920 \u0938\u094D\u0925\u093E\u0928\u0940\u092F \u0935\u094D\u092F\u093E\u092A\u093E\u0930 \u0938\u092E\u093E\u091A\u093E\u0930 \u0935\u0947\u092C\u0938\u093E\u0907\u091F",
|
|
385
|
+
"{location} \u0905\u0930\u094D\u0925\u0935\u094D\u092F\u0935\u0938\u094D\u0925\u093E \u0938\u094D\u091F\u093E\u0930\u094D\u091F\u0905\u092A \u0921\u093F\u091C\u093F\u091F\u0932 \u092E\u0940\u0921\u093F\u092F\u093E",
|
|
386
|
+
"{location} \u0935\u094D\u092F\u093E\u092A\u093E\u0930 \u0911\u0928\u0932\u093E\u0907\u0928 \u0938\u092E\u093E\u091A\u093E\u0930 \u092A\u0924\u094D\u0930 \u0932\u094B\u0915\u092A\u094D\u0930\u093F\u092F"
|
|
387
|
+
]
|
|
388
|
+
},
|
|
389
|
+
bn: {
|
|
390
|
+
name: "Bengali",
|
|
391
|
+
nativeName: "\u09AC\u09BE\u0982\u09B2\u09BE",
|
|
392
|
+
discoveryQueries: [
|
|
393
|
+
"{location} \u09B8\u09C7\u09B0\u09BE \u09B8\u09CD\u09A5\u09BE\u09A8\u09C0\u09AF\u09BC \u09AC\u09CD\u09AF\u09AC\u09B8\u09BE \u09B8\u0982\u09AC\u09BE\u09A6 \u0993\u09AF\u09BC\u09C7\u09AC\u09B8\u09BE\u0987\u099F",
|
|
394
|
+
"{location} \u0985\u09B0\u09CD\u09A5\u09A8\u09C0\u09A4\u09BF \u09B8\u09CD\u099F\u09BE\u09B0\u09CD\u099F\u0986\u09AA \u09A1\u09BF\u099C\u09BF\u099F\u09BE\u09B2 \u09AE\u09BF\u09A1\u09BF\u09AF\u09BC\u09BE",
|
|
395
|
+
"{location} \u09AC\u09CD\u09AF\u09AC\u09B8\u09BE \u0985\u09A8\u09B2\u09BE\u0987\u09A8 \u09B8\u0982\u09AC\u09BE\u09A6\u09AA\u09A4\u09CD\u09B0 \u099C\u09A8\u09AA\u09CD\u09B0\u09BF\u09AF\u09BC"
|
|
396
|
+
]
|
|
397
|
+
},
|
|
398
|
+
ur: {
|
|
399
|
+
name: "Urdu",
|
|
400
|
+
nativeName: "\u0627\u0631\u062F\u0648",
|
|
401
|
+
discoveryQueries: [
|
|
402
|
+
"{location} \u0628\u06C1\u062A\u0631\u06CC\u0646 \u0645\u0642\u0627\u0645\u06CC \u06A9\u0627\u0631\u0648\u0628\u0627\u0631\u06CC \u062E\u0628\u0631\u0648\u06BA \u06A9\u06CC \u0648\u06CC\u0628 \u0633\u0627\u0626\u0679\u0633",
|
|
403
|
+
"{location} \u0645\u0639\u06CC\u0634\u062A \u0627\u0633\u0679\u0627\u0631\u0679 \u0627\u067E \u0688\u06CC\u062C\u06CC\u0679\u0644 \u0645\u06CC\u0688\u06CC\u0627",
|
|
404
|
+
"{location} \u06A9\u0627\u0631\u0648\u0628\u0627\u0631 \u0622\u0646 \u0644\u0627\u0626\u0646 \u0627\u062E\u0628\u0627\u0631\u0627\u062A \u0645\u0642\u0628\u0648\u0644"
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
// --- Western Europe -------------------------------------------------------
|
|
408
|
+
es: {
|
|
409
|
+
name: "Spanish",
|
|
410
|
+
nativeName: "Espa\xF1ol",
|
|
411
|
+
discoveryQueries: [
|
|
412
|
+
"mejores sitios de noticias de negocios locales en {location}",
|
|
413
|
+
"medios digitales econom\xEDa startups {location}",
|
|
414
|
+
"peri\xF3dicos digitales de negocios {location} m\xE1s populares"
|
|
415
|
+
]
|
|
416
|
+
},
|
|
417
|
+
pt: {
|
|
418
|
+
name: "Portuguese",
|
|
419
|
+
nativeName: "Portugu\xEAs",
|
|
420
|
+
discoveryQueries: [
|
|
421
|
+
"melhores sites de not\xEDcias de neg\xF3cios em {location}",
|
|
422
|
+
"m\xEDdia digital economia startups {location}",
|
|
423
|
+
"jornais digitais de neg\xF3cios {location} mais populares"
|
|
424
|
+
]
|
|
425
|
+
},
|
|
426
|
+
fr: {
|
|
427
|
+
name: "French",
|
|
428
|
+
nativeName: "Fran\xE7ais",
|
|
429
|
+
discoveryQueries: [
|
|
430
|
+
"meilleurs sites d'actualit\xE9s business \xE0 {location}",
|
|
431
|
+
"m\xE9dias num\xE9riques \xE9conomie startups {location}",
|
|
432
|
+
"journaux en ligne business {location} les plus populaires"
|
|
433
|
+
]
|
|
434
|
+
},
|
|
435
|
+
de: {
|
|
436
|
+
name: "German",
|
|
437
|
+
nativeName: "Deutsch",
|
|
438
|
+
discoveryQueries: [
|
|
439
|
+
"beste lokale Wirtschaftsnachrichten Webseiten in {location}",
|
|
440
|
+
"digitale Medien Wirtschaft Startups {location}",
|
|
441
|
+
"beliebteste Online-Wirtschaftszeitungen {location}"
|
|
442
|
+
]
|
|
443
|
+
},
|
|
444
|
+
it: {
|
|
445
|
+
name: "Italian",
|
|
446
|
+
nativeName: "Italiano",
|
|
447
|
+
discoveryQueries: [
|
|
448
|
+
"migliori siti di notizie business locali a {location}",
|
|
449
|
+
"media digitali economia startup {location}",
|
|
450
|
+
"giornali online business {location} pi\xF9 popolari"
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
nl: {
|
|
454
|
+
name: "Dutch",
|
|
455
|
+
nativeName: "Nederlands",
|
|
456
|
+
discoveryQueries: [
|
|
457
|
+
"beste lokale zakennieuws websites in {location}",
|
|
458
|
+
"digitale media economie startups {location}",
|
|
459
|
+
"populairste online zakenkranten {location}"
|
|
460
|
+
]
|
|
461
|
+
},
|
|
462
|
+
sv: {
|
|
463
|
+
name: "Swedish",
|
|
464
|
+
nativeName: "Svenska",
|
|
465
|
+
discoveryQueries: [
|
|
466
|
+
"b\xE4sta lokala aff\xE4rsnyheter webbplatser i {location}",
|
|
467
|
+
"digitala medier ekonomi startups {location}",
|
|
468
|
+
"popul\xE4raste online aff\xE4rstidningar {location}"
|
|
469
|
+
]
|
|
470
|
+
},
|
|
471
|
+
// --- Eastern Europe -------------------------------------------------------
|
|
472
|
+
pl: {
|
|
473
|
+
name: "Polish",
|
|
474
|
+
nativeName: "Polski",
|
|
475
|
+
discoveryQueries: [
|
|
476
|
+
"najlepsze lokalne strony z wiadomo\u015Bciami biznesowymi w {location}",
|
|
477
|
+
"media cyfrowe gospodarka startupy {location}",
|
|
478
|
+
"najpopularniejsze gazety biznesowe online {location}"
|
|
479
|
+
]
|
|
480
|
+
},
|
|
481
|
+
ro: {
|
|
482
|
+
name: "Romanian",
|
|
483
|
+
nativeName: "Rom\xE2n\u0103",
|
|
484
|
+
discoveryQueries: [
|
|
485
|
+
"cele mai bune site-uri de \u0219tiri de afaceri locale din {location}",
|
|
486
|
+
"media digital\u0103 economie startup-uri {location}",
|
|
487
|
+
"cele mai populare ziare online de afaceri {location}"
|
|
488
|
+
]
|
|
489
|
+
},
|
|
490
|
+
ru: {
|
|
491
|
+
name: "Russian",
|
|
492
|
+
nativeName: "\u0420\u0443\u0441\u0441\u043A\u0438\u0439",
|
|
493
|
+
discoveryQueries: [
|
|
494
|
+
"\u043B\u0443\u0447\u0448\u0438\u0435 \u0441\u0430\u0439\u0442\u044B \u0434\u0435\u043B\u043E\u0432\u044B\u0445 \u043D\u043E\u0432\u043E\u0441\u0442\u0435\u0439 \u0432 {location}",
|
|
495
|
+
"\u0446\u0438\u0444\u0440\u043E\u0432\u044B\u0435 \u043C\u0435\u0434\u0438\u0430 \u044D\u043A\u043E\u043D\u043E\u043C\u0438\u043A\u0430 \u0441\u0442\u0430\u0440\u0442\u0430\u043F\u044B {location}",
|
|
496
|
+
"\u0441\u0430\u043C\u044B\u0435 \u043F\u043E\u043F\u0443\u043B\u044F\u0440\u043D\u044B\u0435 \u043E\u043D\u043B\u0430\u0439\u043D \u0434\u0435\u043B\u043E\u0432\u044B\u0435 \u0433\u0430\u0437\u0435\u0442\u044B {location}"
|
|
497
|
+
]
|
|
498
|
+
},
|
|
499
|
+
uk: {
|
|
500
|
+
name: "Ukrainian",
|
|
501
|
+
nativeName: "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",
|
|
502
|
+
discoveryQueries: [
|
|
503
|
+
"\u043D\u0430\u0439\u043A\u0440\u0430\u0449\u0456 \u0441\u0430\u0439\u0442\u0438 \u0434\u0456\u043B\u043E\u0432\u0438\u0445 \u043D\u043E\u0432\u0438\u043D \u0432 {location}",
|
|
504
|
+
"\u0446\u0438\u0444\u0440\u043E\u0432\u0456 \u043C\u0435\u0434\u0456\u0430 \u0435\u043A\u043E\u043D\u043E\u043C\u0456\u043A\u0430 \u0441\u0442\u0430\u0440\u0442\u0430\u043F\u0438 {location}",
|
|
505
|
+
"\u043D\u0430\u0439\u043F\u043E\u043F\u0443\u043B\u044F\u0440\u043D\u0456\u0448\u0456 \u043E\u043D\u043B\u0430\u0439\u043D \u0434\u0456\u043B\u043E\u0432\u0456 \u0433\u0430\u0437\u0435\u0442\u0438 {location}"
|
|
506
|
+
]
|
|
507
|
+
},
|
|
508
|
+
// --- Middle East / North Africa -------------------------------------------
|
|
509
|
+
ar: {
|
|
510
|
+
name: "Arabic",
|
|
511
|
+
nativeName: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629",
|
|
512
|
+
discoveryQueries: [
|
|
513
|
+
"\u0623\u0641\u0636\u0644 \u0645\u0648\u0627\u0642\u0639 \u0623\u062E\u0628\u0627\u0631 \u0627\u0644\u0623\u0639\u0645\u0627\u0644 \u0627\u0644\u0645\u062D\u0644\u064A\u0629 \u0641\u064A {location}",
|
|
514
|
+
"\u0648\u0633\u0627\u0626\u0644 \u0625\u0639\u0644\u0627\u0645 \u0631\u0642\u0645\u064A\u0629 \u0627\u0642\u062A\u0635\u0627\u062F \u0634\u0631\u0643\u0627\u062A \u0646\u0627\u0634\u0626\u0629 {location}",
|
|
515
|
+
"\u0635\u062D\u0641 \u0631\u0642\u0645\u064A\u0629 \u0623\u0639\u0645\u0627\u0644 {location} \u0627\u0644\u0623\u0643\u062B\u0631 \u0634\u0639\u0628\u064A\u0629"
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
he: {
|
|
519
|
+
name: "Hebrew",
|
|
520
|
+
nativeName: "\u05E2\u05D1\u05E8\u05D9\u05EA",
|
|
521
|
+
discoveryQueries: [
|
|
522
|
+
"\u05D0\u05EA\u05E8\u05D9 \u05D7\u05D3\u05E9\u05D5\u05EA \u05E2\u05E1\u05E7\u05D9\u05D5\u05EA \u05DE\u05E7\u05D5\u05DE\u05D9\u05D5\u05EA \u05D4\u05D8\u05D5\u05D1\u05D9\u05DD \u05D1\u05D9\u05D5\u05EA\u05E8 \u05D1{location}",
|
|
523
|
+
"\u05DE\u05D3\u05D9\u05D4 \u05D3\u05D9\u05D2\u05D9\u05D8\u05DC\u05D9\u05EA \u05DB\u05DC\u05DB\u05DC\u05D4 \u05E1\u05D8\u05D0\u05E8\u05D8\u05D0\u05E4\u05D9\u05DD {location}",
|
|
524
|
+
"\u05E2\u05D9\u05EA\u05D5\u05E0\u05D9\u05DD \u05D3\u05D9\u05D2\u05D9\u05D8\u05DC\u05D9\u05D9\u05DD \u05E2\u05E1\u05E7\u05D9\u05D9\u05DD {location} \u05D4\u05E4\u05D5\u05E4\u05D5\u05DC\u05E8\u05D9\u05D9\u05DD \u05D1\u05D9\u05D5\u05EA\u05E8"
|
|
525
|
+
]
|
|
526
|
+
},
|
|
527
|
+
fa: {
|
|
528
|
+
name: "Persian",
|
|
529
|
+
nativeName: "\u0641\u0627\u0631\u0633\u06CC",
|
|
530
|
+
discoveryQueries: [
|
|
531
|
+
"\u0628\u0647\u062A\u0631\u06CC\u0646 \u0633\u0627\u06CC\u062A\u200C\u0647\u0627\u06CC \u062E\u0628\u0631\u06CC \u06A9\u0633\u0628\u200C\u0648\u06A9\u0627\u0631 \u0645\u062D\u0644\u06CC \u062F\u0631 {location}",
|
|
532
|
+
"\u0631\u0633\u0627\u0646\u0647 \u062F\u06CC\u062C\u06CC\u062A\u0627\u0644 \u0627\u0642\u062A\u0635\u0627\u062F \u0627\u0633\u062A\u0627\u0631\u062A\u0627\u067E {location}",
|
|
533
|
+
"\u0645\u062D\u0628\u0648\u0628\u200C\u062A\u0631\u06CC\u0646 \u0631\u0648\u0632\u0646\u0627\u0645\u0647\u200C\u0647\u0627\u06CC \u0622\u0646\u0644\u0627\u06CC\u0646 \u06A9\u0633\u0628\u200C\u0648\u06A9\u0627\u0631 {location}"
|
|
534
|
+
]
|
|
535
|
+
},
|
|
536
|
+
// --- Turkey ---------------------------------------------------------------
|
|
537
|
+
tr: {
|
|
538
|
+
name: "Turkish",
|
|
539
|
+
nativeName: "T\xFCrk\xE7e",
|
|
540
|
+
discoveryQueries: [
|
|
541
|
+
"{location} en iyi yerel i\u015F haberleri web siteleri",
|
|
542
|
+
"{location} dijital medya ekonomi startup",
|
|
543
|
+
"{location} en pop\xFCler online i\u015F gazeteleri"
|
|
544
|
+
]
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
function getLanguageForCountry(country) {
|
|
548
|
+
const code = COUNTRY_LANGUAGE_MAP[country.trim().toLowerCase()];
|
|
549
|
+
if (!code)
|
|
550
|
+
return null;
|
|
551
|
+
return code;
|
|
552
|
+
}
|
|
553
|
+
function resolveLanguage(options) {
|
|
554
|
+
if (options.language) {
|
|
555
|
+
const code = options.language.trim().toLowerCase();
|
|
556
|
+
return code === "en" ? null : code;
|
|
557
|
+
}
|
|
558
|
+
if (options.country) {
|
|
559
|
+
return getLanguageForCountry(options.country);
|
|
560
|
+
}
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
function getLocalizedDiscoveryQueries(location, languageCode) {
|
|
564
|
+
const info = LANGUAGE_INFO[languageCode];
|
|
565
|
+
if (!info)
|
|
566
|
+
return [];
|
|
567
|
+
return info.discoveryQueries.map((q) => q.replace("{location}", location));
|
|
568
|
+
}
|
|
569
|
+
function getLanguageName(code) {
|
|
570
|
+
return LANGUAGE_INFO[code]?.name ?? null;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// ../../packages/arendi/dist/trends.js
|
|
214
574
|
var COUNTRY_GEO_MAP = {
|
|
215
575
|
afghanistan: "AF",
|
|
216
576
|
albania: "AL",
|
|
@@ -325,9 +685,17 @@ function countryToGeo(country) {
|
|
|
325
685
|
}
|
|
326
686
|
return COUNTRY_GEO_MAP[trimmed.toLowerCase()] ?? null;
|
|
327
687
|
}
|
|
328
|
-
|
|
688
|
+
function looksLikeHtml(raw) {
|
|
689
|
+
const trimmed = raw.trimStart();
|
|
690
|
+
return trimmed.startsWith("<!") || trimmed.startsWith("<html");
|
|
691
|
+
}
|
|
692
|
+
async function fetchDailyTrends(geo, hl) {
|
|
329
693
|
try {
|
|
330
|
-
const raw = await googleTrends.dailyTrends({ geo });
|
|
694
|
+
const raw = await googleTrends.dailyTrends({ geo, hl });
|
|
695
|
+
if (looksLikeHtml(raw)) {
|
|
696
|
+
console.warn(`Warning: Google Trends returned an HTML page instead of data for geo "${geo}" (daily trends). This usually means the geo is unsupported or Google is rate-limiting requests. Skipping.`);
|
|
697
|
+
return [];
|
|
698
|
+
}
|
|
331
699
|
const parsed = JSON.parse(raw);
|
|
332
700
|
const days = parsed?.["default"];
|
|
333
701
|
const trendingDays = days?.["trendingSearchesDays"] ?? [];
|
|
@@ -350,7 +718,7 @@ async function fetchDailyTrends(geo) {
|
|
|
350
718
|
return [];
|
|
351
719
|
}
|
|
352
720
|
}
|
|
353
|
-
async function fetchRelatedQueries(keywords, geo) {
|
|
721
|
+
async function fetchRelatedQueries(keywords, geo, hl) {
|
|
354
722
|
const ninetyDaysAgo = /* @__PURE__ */ new Date();
|
|
355
723
|
ninetyDaysAgo.setDate(ninetyDaysAgo.getDate() - 90);
|
|
356
724
|
const results = await Promise.all(keywords.map(async (keyword) => {
|
|
@@ -358,8 +726,13 @@ async function fetchRelatedQueries(keywords, geo) {
|
|
|
358
726
|
const raw = await googleTrends.relatedQueries({
|
|
359
727
|
keyword,
|
|
360
728
|
startTime: ninetyDaysAgo,
|
|
361
|
-
geo: geo ?? ""
|
|
729
|
+
geo: geo ?? "",
|
|
730
|
+
hl
|
|
362
731
|
});
|
|
732
|
+
if (looksLikeHtml(raw)) {
|
|
733
|
+
console.warn(`Warning: Google Trends returned an HTML page for related queries "${keyword}" (geo "${geo ?? "global"}"). Skipping.`);
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
363
736
|
const parsed = JSON.parse(raw);
|
|
364
737
|
const rankedList = parsed?.["default"]?.["rankedList"];
|
|
365
738
|
if (!rankedList || rankedList.length === 0) {
|
|
@@ -383,7 +756,7 @@ async function fetchRelatedQueries(keywords, geo) {
|
|
|
383
756
|
}));
|
|
384
757
|
return results.filter((r) => r !== null);
|
|
385
758
|
}
|
|
386
|
-
async function fetchRelatedTopics(keywords, geo) {
|
|
759
|
+
async function fetchRelatedTopics(keywords, geo, hl) {
|
|
387
760
|
const ninetyDaysAgo = /* @__PURE__ */ new Date();
|
|
388
761
|
ninetyDaysAgo.setDate(ninetyDaysAgo.getDate() - 90);
|
|
389
762
|
const results = await Promise.all(keywords.map(async (keyword) => {
|
|
@@ -391,8 +764,13 @@ async function fetchRelatedTopics(keywords, geo) {
|
|
|
391
764
|
const raw = await googleTrends.relatedTopics({
|
|
392
765
|
keyword,
|
|
393
766
|
startTime: ninetyDaysAgo,
|
|
394
|
-
geo: geo ?? ""
|
|
767
|
+
geo: geo ?? "",
|
|
768
|
+
hl
|
|
395
769
|
});
|
|
770
|
+
if (looksLikeHtml(raw)) {
|
|
771
|
+
console.warn(`Warning: Google Trends returned an HTML page for related topics "${keyword}" (geo "${geo ?? "global"}"). Skipping.`);
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
396
774
|
const parsed = JSON.parse(raw);
|
|
397
775
|
const rankedList = parsed?.["default"]?.["rankedList"];
|
|
398
776
|
if (!rankedList || rankedList.length === 0) {
|
|
@@ -430,10 +808,11 @@ async function trendsResearch(options) {
|
|
|
430
808
|
if (options.categories?.length && keywords.length === 0) {
|
|
431
809
|
keywords.push(...options.categories);
|
|
432
810
|
}
|
|
811
|
+
const hl = resolveLanguage(options) ?? void 0;
|
|
433
812
|
const [dailyTrends, relatedQueries, relatedTopics] = await Promise.all([
|
|
434
|
-
geo ? fetchDailyTrends(geo) : Promise.resolve([]),
|
|
435
|
-
keywords.length > 0 ? fetchRelatedQueries(keywords, geo ?? void 0) : Promise.resolve([]),
|
|
436
|
-
keywords.length > 0 ? fetchRelatedTopics(keywords, geo ?? void 0) : Promise.resolve([])
|
|
813
|
+
geo ? fetchDailyTrends(geo, hl) : Promise.resolve([]),
|
|
814
|
+
keywords.length > 0 ? fetchRelatedQueries(keywords, geo ?? void 0, hl) : Promise.resolve([]),
|
|
815
|
+
keywords.length > 0 ? fetchRelatedTopics(keywords, geo ?? void 0, hl) : Promise.resolve([])
|
|
437
816
|
]);
|
|
438
817
|
return { dailyTrends, relatedQueries, relatedTopics };
|
|
439
818
|
}
|
|
@@ -593,6 +972,15 @@ async function discoverLocalSources(options, cacheStats) {
|
|
|
593
972
|
`popular local media sources ${location} economy startups`,
|
|
594
973
|
`${location} local online newspapers business publications`
|
|
595
974
|
];
|
|
975
|
+
const languageCode = resolveLanguage(options);
|
|
976
|
+
if (languageCode) {
|
|
977
|
+
const localizedQueries = getLocalizedDiscoveryQueries(location, languageCode);
|
|
978
|
+
discoveryQueries.push(...localizedQueries);
|
|
979
|
+
const langName = getLanguageName(languageCode);
|
|
980
|
+
if (langName) {
|
|
981
|
+
discoveryQueries.push(`${location} local news media websites in ${langName} language`);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
596
984
|
const allResults = await Promise.all(discoveryQueries.map((q) => tavilySearch(q, options.tavilyApiKey, {
|
|
597
985
|
cache: options.cache,
|
|
598
986
|
cacheStats
|
|
@@ -631,6 +1019,13 @@ function buildLocalSearchQueries(options) {
|
|
|
631
1019
|
if (kw) {
|
|
632
1020
|
queries.push([kw, `market demand`, location, year].filter(Boolean).join(" "));
|
|
633
1021
|
}
|
|
1022
|
+
const languageCode = resolveLanguage(options);
|
|
1023
|
+
if (languageCode) {
|
|
1024
|
+
const langName = getLanguageName(languageCode);
|
|
1025
|
+
if (langName) {
|
|
1026
|
+
queries.push([`${langName} language`, cats, `business trends`, location, year].filter(Boolean).join(" "));
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
634
1029
|
return queries;
|
|
635
1030
|
}
|
|
636
1031
|
function buildGlobalSearchQueries(options) {
|
|
@@ -908,7 +1303,8 @@ async function generateIdeas(rawOptions, callbacks) {
|
|
|
908
1303
|
limit: options.limit,
|
|
909
1304
|
provider: options.provider,
|
|
910
1305
|
model: options.model,
|
|
911
|
-
geo: options.geo
|
|
1306
|
+
geo: options.geo,
|
|
1307
|
+
language: options.language
|
|
912
1308
|
},
|
|
913
1309
|
sourceDiscovery: {
|
|
914
1310
|
domains: localDomains,
|
|
@@ -1260,6 +1656,9 @@ program.name("arendi").description(
|
|
|
1260
1656
|
).option(
|
|
1261
1657
|
"--geo <code>",
|
|
1262
1658
|
"ISO 3166-1 alpha-2 country code for Google Trends (e.g., US, ID). Auto-detected from --country if omitted."
|
|
1659
|
+
).option(
|
|
1660
|
+
"--language <code>",
|
|
1661
|
+
"ISO 639-1 language code for local-language results (e.g., id, es, fr). Auto-detected from --country if omitted."
|
|
1263
1662
|
).option(
|
|
1264
1663
|
"--db <path>",
|
|
1265
1664
|
"Path to the SQLite database for caching and run history",
|
|
@@ -1351,6 +1750,7 @@ program.action(async (opts) => {
|
|
|
1351
1750
|
apiKey,
|
|
1352
1751
|
tavilyApiKey,
|
|
1353
1752
|
geo: opts["geo"],
|
|
1753
|
+
language: opts["language"],
|
|
1354
1754
|
cache,
|
|
1355
1755
|
store
|
|
1356
1756
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arendi-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "CLI for AI-powered business idea generation with web research",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"build": "tsup",
|
|
26
26
|
"dev": "tsx src/index.ts",
|
|
27
27
|
"dev:id": "tsx src/index.ts --country Indonesia --categories health,finance --format json --output ideas.json",
|
|
28
|
+
"dev:jakarta": "tsx src/index.ts --country Indonesia --city Jakarta --categories entertainment,lifestyle --format json --output ideas.json",
|
|
28
29
|
"prepublishOnly": "pnpm run build",
|
|
29
30
|
"test": "vitest run",
|
|
30
31
|
"test:coverage": "vitest run --coverage"
|