@cachly-dev/mcp-server 0.5.50 → 0.5.60
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 +346 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +289 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cachly-dev/mcp-server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.60",
|
|
4
4
|
"mcpName": "io.github.cachly-dev/mcp-server",
|
|
5
5
|
"description": "AI memory brain for Claude Code, Cursor, Copilot & Windsurf — persistent sessions, lessons learned, semantic search, team brain. 51 MCP tools.",
|
|
6
6
|
"type": "module",
|
package/src/index.ts
CHANGED
|
@@ -55,7 +55,7 @@ import { Redis } from 'ioredis';
|
|
|
55
55
|
const API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
|
|
56
56
|
const JWT = process.env.CACHLY_JWT ?? '';
|
|
57
57
|
const EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
|
|
58
|
-
const CURRENT_VERSION = '0.5.
|
|
58
|
+
const CURRENT_VERSION = '0.5.60';
|
|
59
59
|
/**
|
|
60
60
|
* ┌──────────────────────────────────────────────────────────────────────┐
|
|
61
61
|
* │ EMBEDDING PROVIDER — pluggable, client-side first │
|
|
@@ -434,6 +434,23 @@ const STOPWORDS = new Set([
|
|
|
434
434
|
'मैं', 'तुम', 'उन', 'इन', 'ने', 'बहुत', 'सब', 'कुछ', 'फिर',
|
|
435
435
|
'अब', 'तो', 'ही', 'तरह', 'जैसे', 'करना', 'होना', 'रहा', 'रही',
|
|
436
436
|
'रहे', 'गया', 'गई', 'गए', 'किया', 'किए', 'कर', 'हुआ', 'हुई',
|
|
437
|
+
// ── Russian — common prepositions, pronouns, auxiliary verbs ───────────────
|
|
438
|
+
'в', 'на', 'не', 'с', 'и', 'а', 'но', 'по', 'за', 'из', 'от', 'до',
|
|
439
|
+
'к', 'у', 'о', 'об', 'во', 'при', 'под', 'над', 'без', 'для',
|
|
440
|
+
'что', 'как', 'это', 'все', 'так', 'уже', 'или', 'же', 'ли',
|
|
441
|
+
'если', 'то', 'да', 'нет', 'был', 'была', 'были', 'быть', 'есть',
|
|
442
|
+
'его', 'её', 'их', 'этот', 'эта', 'эти', 'который', 'которая',
|
|
443
|
+
'которые', 'который', 'мой', 'моя', 'мои', 'ваш', 'ваша', 'ваши',
|
|
444
|
+
'он', 'она', 'они', 'мы', 'вы', 'я', 'ты', 'тот', 'та', 'те',
|
|
445
|
+
'очень', 'тоже', 'также', 'когда', 'где', 'как', 'почему', 'зачем',
|
|
446
|
+
'сейчас', 'здесь', 'там', 'потому', 'поэтому', 'чтобы', 'тут',
|
|
447
|
+
// ── Turkish — common particles, postpositions, copulas ─────────────────────
|
|
448
|
+
'bir', 'bu', 'şu', 'o', 've', 'ile', 'de', 'da', 'için', 'gibi',
|
|
449
|
+
'ama', 'fakat', 'ancak', 'ya', 'ne', 'ki', 'mi', 'mı', 'mu', 'mü',
|
|
450
|
+
'var', 'yok', 'olan', 'oldu', 'olur', 'olarak', 'ise', 'daha',
|
|
451
|
+
'çok', 'en', 'her', 'hiç', 'bazı', 'tüm', 'bütün', 'hem', 'veya',
|
|
452
|
+
'bu', 'şu', 'ben', 'sen', 'biz', 'siz', 'onlar', 'benim', 'senin',
|
|
453
|
+
'nasıl', 'neden', 'niçin', 'nerede', 'ne', 'hangi', 'kaç',
|
|
437
454
|
]);
|
|
438
455
|
|
|
439
456
|
|
|
@@ -450,6 +467,10 @@ const ARABIC_CHAR_RE = /[\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb50-\ufdff\u
|
|
|
450
467
|
const FARSI_CHAR_RE = /[\u067e\u0686\u0698\u06af\u06cc]/;
|
|
451
468
|
// Devanagari (Hindi, Sanskrit, Marathi …) — U+0900–U+097F + extended
|
|
452
469
|
const DEVANAGARI_RE = /[\u0900-\u097f]/;
|
|
470
|
+
// Cyrillic (Russian, Bulgarian, Ukrainian, Serbian …) — U+0400–U+04FF
|
|
471
|
+
const CYRILLIC_RE = /[\u0400-\u04ff]/;
|
|
472
|
+
// Turkish uses Latin alphabet but has unique chars (ğ, ş, ı, ö, ü, ç) — detected by these
|
|
473
|
+
const TURKISH_CHAR_RE = /[\u011f\u015f\u0131\u0130\u00e7]/; // ğ ş ı İ ç
|
|
453
474
|
|
|
454
475
|
// ── Katakana → Romaji conversion table (Hepburn system) ──────────────────────
|
|
455
476
|
// Digraphs must be listed before single chars so they match first.
|
|
@@ -611,10 +632,102 @@ function hindiLightStem(word: string): string {
|
|
|
611
632
|
if (result.endsWith('\u0915\u0930') && result.length > 4) return result.slice(0, -2); // \u0915\u0930 (kar) conjunctive
|
|
612
633
|
if (result.endsWith('\u0913\u0902') && result.length > 4) return result.slice(0, -2); // \u0913\u0902 (oṃ) oblique plural
|
|
613
634
|
if (result.endsWith('\u0907\u092f\u093e\u0902') && result.length > 5) return result.slice(0, -4); // \u0907\u092f\u093e\u0902 (iyāṃ) f plural
|
|
614
|
-
if (result.endsWith('\u0940\u092f\u093e\u0902') && result.length > 5) return result.slice(0, -4); // \u0940\u092f\u093e\
|
|
635
|
+
if (result.endsWith('\u0940\u092f\u093e\u0902') && result.length > 5) return result.slice(0, -4); // \u0940\u092f\u093e\u0102 (īyāṃ)
|
|
615
636
|
return result;
|
|
616
637
|
}
|
|
617
638
|
|
|
639
|
+
/**
|
|
640
|
+
* Russian light stemmer — strips common inflectional suffixes.
|
|
641
|
+
* Handles the most frequent verb/noun/adjective endings to improve recall.
|
|
642
|
+
* Only strips when result is still ≥ 3 chars.
|
|
643
|
+
*
|
|
644
|
+
* Covers:
|
|
645
|
+
* ошибки/ошибка → ошибк (noun plural/genitive)
|
|
646
|
+
* развёртывание → развёртыва (gerund → stem)
|
|
647
|
+
* установить → установ (infinitive)
|
|
648
|
+
* настройки → настройк (genitive plural)
|
|
649
|
+
*/
|
|
650
|
+
function russianLightStem(word: string): string {
|
|
651
|
+
let w = word;
|
|
652
|
+
// Longest first to avoid partial stripping
|
|
653
|
+
// Verb infinitives / gerunds
|
|
654
|
+
if (w.endsWith('ывание') && w.length > 7) return w.slice(0, -6);
|
|
655
|
+
if (w.endsWith('ивание') && w.length > 7) return w.slice(0, -6);
|
|
656
|
+
if (w.endsWith('ование') && w.length > 7) return w.slice(0, -6);
|
|
657
|
+
if (w.endsWith('вание') && w.length > 6) return w.slice(0, -5);
|
|
658
|
+
if (w.endsWith('ение') && w.length > 5) return w.slice(0, -4);
|
|
659
|
+
if (w.endsWith('ание') && w.length > 5) return w.slice(0, -4);
|
|
660
|
+
if (w.endsWith('ить') && w.length > 4) return w.slice(0, -3);
|
|
661
|
+
if (w.endsWith('ать') && w.length > 4) return w.slice(0, -3);
|
|
662
|
+
if (w.endsWith('еть') && w.length > 4) return w.slice(0, -3);
|
|
663
|
+
if (w.endsWith('уть') && w.length > 4) return w.slice(0, -3);
|
|
664
|
+
// Noun plural/genitive
|
|
665
|
+
if (w.endsWith('ки') && w.length > 4) return w.slice(0, -2);
|
|
666
|
+
if (w.endsWith('ги') && w.length > 4) return w.slice(0, -2);
|
|
667
|
+
if (w.endsWith('ов') && w.length > 4) return w.slice(0, -2);
|
|
668
|
+
if (w.endsWith('ев') && w.length > 4) return w.slice(0, -2);
|
|
669
|
+
if (w.endsWith('ей') && w.length > 4) return w.slice(0, -2);
|
|
670
|
+
if (w.endsWith('ий') && w.length > 4) return w.slice(0, -2);
|
|
671
|
+
if (w.endsWith('ый') && w.length > 4) return w.slice(0, -2);
|
|
672
|
+
if (w.endsWith('ая') && w.length > 4) return w.slice(0, -2);
|
|
673
|
+
if (w.endsWith('ое') && w.length > 4) return w.slice(0, -2);
|
|
674
|
+
if (w.endsWith('ую') && w.length > 4) return w.slice(0, -2);
|
|
675
|
+
// Verb present tense
|
|
676
|
+
if (w.endsWith('ет') && w.length > 4) return w.slice(0, -2);
|
|
677
|
+
if (w.endsWith('ют') && w.length > 4) return w.slice(0, -2);
|
|
678
|
+
if (w.endsWith('ут') && w.length > 4) return w.slice(0, -2);
|
|
679
|
+
if (w.endsWith('ят') && w.length > 4) return w.slice(0, -2);
|
|
680
|
+
return w;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Turkish light stemmer — strips common agglutinative suffixes.
|
|
685
|
+
* Turkish is highly agglutinative; this covers the most common inflectional ends.
|
|
686
|
+
*
|
|
687
|
+
* Covers:
|
|
688
|
+
* hatalar → hata (-lar/-ler plural)
|
|
689
|
+
* sunucuda → sunucu (-da/-de locative)
|
|
690
|
+
* dağıtımı → dağıtım (-ı/-i/-u/-ü accusative)
|
|
691
|
+
* yüklemek → yükle (-mek/-mak infinitive)
|
|
692
|
+
*/
|
|
693
|
+
function turkishLightStem(word: string): string {
|
|
694
|
+
let w = word;
|
|
695
|
+
// Suffixes longest-first
|
|
696
|
+
if (w.endsWith('lardaki') && w.length > 7) return w.slice(0, -7);
|
|
697
|
+
if (w.endsWith('lerdeki') && w.length > 7) return w.slice(0, -7);
|
|
698
|
+
if (w.endsWith('ların') && w.length > 6) return w.slice(0, -5);
|
|
699
|
+
if (w.endsWith('lerin') && w.length > 6) return w.slice(0, -5);
|
|
700
|
+
if (w.endsWith('larda') && w.length > 6) return w.slice(0, -5);
|
|
701
|
+
if (w.endsWith('lerde') && w.length > 6) return w.slice(0, -5);
|
|
702
|
+
if (w.endsWith('ları') && w.length > 5) return w.slice(0, -4);
|
|
703
|
+
if (w.endsWith('leri') && w.length > 5) return w.slice(0, -4);
|
|
704
|
+
if (w.endsWith('mek') && w.length > 4) return w.slice(0, -3);
|
|
705
|
+
if (w.endsWith('mak') && w.length > 4) return w.slice(0, -3);
|
|
706
|
+
if (w.endsWith('ler') && w.length > 4) return w.slice(0, -3);
|
|
707
|
+
if (w.endsWith('lar') && w.length > 4) return w.slice(0, -3);
|
|
708
|
+
if (w.endsWith('nın') && w.length > 4) return w.slice(0, -3);
|
|
709
|
+
if (w.endsWith('nin') && w.length > 4) return w.slice(0, -3);
|
|
710
|
+
if (w.endsWith('nun') && w.length > 4) return w.slice(0, -3);
|
|
711
|
+
if (w.endsWith('nün') && w.length > 4) return w.slice(0, -3);
|
|
712
|
+
if (w.endsWith('da') && w.length > 4) return w.slice(0, -2);
|
|
713
|
+
if (w.endsWith('de') && w.length > 4) return w.slice(0, -2);
|
|
714
|
+
if (w.endsWith('ta') && w.length > 4) return w.slice(0, -2);
|
|
715
|
+
if (w.endsWith('te') && w.length > 4) return w.slice(0, -2);
|
|
716
|
+
if (w.endsWith('dan') && w.length > 4) return w.slice(0, -3);
|
|
717
|
+
if (w.endsWith('den') && w.length > 4) return w.slice(0, -3);
|
|
718
|
+
if (w.endsWith('tan') && w.length > 4) return w.slice(0, -3);
|
|
719
|
+
if (w.endsWith('ten') && w.length > 4) return w.slice(0, -3);
|
|
720
|
+
if (w.endsWith('ın') && w.length > 4) return w.slice(0, -2);
|
|
721
|
+
if (w.endsWith('in') && w.length > 4) return w.slice(0, -2);
|
|
722
|
+
if (w.endsWith('un') && w.length > 4) return w.slice(0, -2);
|
|
723
|
+
if (w.endsWith('ün') && w.length > 4) return w.slice(0, -2);
|
|
724
|
+
if (w.endsWith('ı') && w.length > 4) return w.slice(0, -1);
|
|
725
|
+
if (w.endsWith('i') && w.length > 4) return w.slice(0, -1);
|
|
726
|
+
if (w.endsWith('u') && w.length > 4) return w.slice(0, -1);
|
|
727
|
+
if (w.endsWith('ü') && w.length > 4) return w.slice(0, -1);
|
|
728
|
+
return w;
|
|
729
|
+
}
|
|
730
|
+
|
|
618
731
|
|
|
619
732
|
// Maps tokens (English, Japanese katakana, Chinese, Korean, Arabic, Hebrew)
|
|
620
733
|
// to their equivalents in other languages. Used to expand tokens at search time
|
|
@@ -623,45 +736,45 @@ function hindiLightStem(word: string): string {
|
|
|
623
736
|
// Keys must be lowercase. CJK values will be bigram-expanded at use time.
|
|
624
737
|
const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
625
738
|
// English → all
|
|
626
|
-
['deploy', ['デプロイ', '部署', '배포', 'deployment', 'deploying', 'نشر', 'פריסה', 'استقرار', 'तैनाती', 'bereitstellen', 'bereitstellung', 'déployer', 'déploiement', 'desplegar', 'despliegue', 'distribuire', 'distribuzione', 'implantar', 'implantação']],
|
|
627
|
-
['deployment', ['デプロイ', '部署', '배포', 'deploy', 'نشر', 'פריסה', 'استقرار', 'तैनाती', 'bereitstellung', 'déploiement', 'despliegue', 'distribuzione', 'implantação']],
|
|
739
|
+
['deploy', ['デプロイ', '部署', '배포', 'deployment', 'deploying', 'نشر', 'פריסה', 'استقرار', 'तैनाती', 'bereitstellen', 'bereitstellung', 'déployer', 'déploiement', 'desplegar', 'despliegue', 'distribuire', 'distribuzione', 'implantar', 'implantação', 'развёртывание', 'развертывание', 'dağıtım', 'dağıtmak']],
|
|
740
|
+
['deployment', ['デプロイ', '部署', '배포', 'deploy', 'نشر', 'פריסה', 'استقرار', 'तैनाती', 'bereitstellung', 'déploiement', 'despliegue', 'distribuzione', 'implantação', 'развёртывание', 'dağıtım']],
|
|
628
741
|
['container', ['コンテナ', '容器', '컨테이너', 'docker']],
|
|
629
|
-
['server', ['サーバー', 'サーバ', '服务器', '서버', 'سيرفر', 'שרת', 'سرور', 'सर्वर']],
|
|
742
|
+
['server', ['サーバー', 'サーバ', '服务器', '서버', 'سيرفر', 'שרת', 'سرور', 'सर्वर', 'сервер', 'sunucu']],
|
|
630
743
|
['database', ['データベース', '数据库', '데이터베이스', 'db', 'قاعدة البيانات', 'datenbank', 'پایگاه داده', 'डेटाबेس', 'base de données', 'base de datos', 'banco de dados']],
|
|
631
|
-
['cache', ['キャッシュ', '缓存', '캐시', 'كاش', 'מטמון', 'کش', 'कैश']],
|
|
632
|
-
['error', ['エラー', '错误', '오류', 'خطأ', '
|
|
744
|
+
['cache', ['キャッシュ', '缓存', '캐시', 'كاش', 'מטמון', 'کش', 'कैश', 'кэш', 'önbellek']],
|
|
745
|
+
['error', ['エラー', '错误', '오류', 'خطأ', 'שגיאה', 'خطا', 'त्रुटि', 'गलती', 'exception', 'err', 'fehler', 'erreur', 'fallo', 'errore', 'erro', 'ошибка', 'hata', 'hatalı']],
|
|
633
746
|
['bug', ['バグ', '缺陷', '버그', 'issue', 'defect', 'خلل', 'اشکال', 'बग']],
|
|
634
|
-
['fix', ['修正', '修复', '수정', 'bugfix', 'patch', 'hotfix', 'إصلاح', 'תיקון', 'رفع', 'सुधार', 'beheben', 'behoben', 'réparer', 'correction', 'arreglar', 'corrección', 'correggere', 'corrigir']],
|
|
635
|
-
['build', ['ビルド', '构建', '빌드', 'بناء', 'בנייה', 'ساخت', 'निर्माण', 'bauen', 'construire', 'construir', 'costruire']],
|
|
636
|
-
['test', ['テスト', '测试', '테스트', 'اختبار', 'בדיקה', 'آزمایش', 'परीक्षण', 'testen', 'tester', 'probar', 'testare', 'testar']],
|
|
637
|
-
['auth', ['認証', '认证', '인증', 'authentication', 'login', 'oauth', 'مصادقة', 'אימות', 'احراز هویت', 'प्रमाणीकरण', 'authentifizierung', 'authentification', 'autenticación', 'autenticazione', 'autenticação']],
|
|
638
|
-
['authentication', ['auth', 'مصادقة', 'אימות', 'احراز هویت', 'प्रमाणीकरण', '認証', '认证', '인증', 'login', 'oauth']],
|
|
639
|
-
['environment', ['環境', '环境', '환경', 'env', 'بيئة', 'סביבה', 'umgebung', 'environnement', 'entorno', 'ambiente']],
|
|
640
|
-
['secret', ['key', 'token', 'password', 'jwt', 'مفتاح', 'מפתח', 'geheimnis', 'schlüssel', 'clave', 'clé', 'chiave', 'chave']],
|
|
641
|
-
['problem', ['error', 'issue', 'bug', 'failure', 'مشكلة', '
|
|
747
|
+
['fix', ['修正', '修复', '수정', 'bugfix', 'patch', 'hotfix', 'إصلاح', 'תיקון', 'رفع', 'सुधार', 'beheben', 'behoben', 'réparer', 'correction', 'arreglar', 'corrección', 'correggere', 'corrigir', 'исправить', 'исправление', 'düzeltmek', 'düzeltme']],
|
|
748
|
+
['build', ['ビルド', '构建', '빌드', 'بناء', 'בנייה', 'ساخت', 'निर्माण', 'bauen', 'construire', 'construir', 'costruire', 'сборка', 'собрать', 'derleme', 'derlemek']],
|
|
749
|
+
['test', ['テスト', '测试', '테스트', 'اختبار', 'בדיקה', 'آزمایش', 'परीक्षण', 'testen', 'tester', 'probar', 'testare', 'testar', 'тест', 'тестирование', 'test', 'testlemek']],
|
|
750
|
+
['auth', ['認証', '认证', '인증', 'authentication', 'login', 'oauth', 'مصادقة', 'אימות', 'احراز هویت', 'प्रमाणीकरण', 'authentifizierung', 'authentification', 'autenticación', 'autenticazione', 'autenticação', 'аутентификация', 'авторизация', 'kimlik doğrulama', 'yetkilendirme']],
|
|
751
|
+
['authentication', ['auth', 'مصادقة', 'אימות', 'احراز هویت', 'प्रमाणीकरण', '認証', '认证', '인증', 'login', 'oauth', 'аутентификация', 'авторизация', 'kimlik doğrulama']],
|
|
752
|
+
['environment', ['環境', '环境', '환경', 'env', 'بيئة', 'סביבה', 'umgebung', 'environnement', 'entorno', 'ambiente', 'среда', 'окружение', 'ortam']],
|
|
753
|
+
['secret', ['key', 'token', 'password', 'jwt', 'مفتاح', 'מפתח', 'geheimnis', 'schlüssel', 'clave', 'clé', 'chiave', 'chave', 'секрет', 'ключ', 'gizli', 'anahtar']],
|
|
754
|
+
['problem', ['error', 'issue', 'bug', 'failure', 'مشكلة', '問題', '오류', 'fehler', 'problème', 'problema', 'проблема', 'ошибка', 'sorun', 'problem']],
|
|
642
755
|
['kubernetes', ['クベルネテス', 'k8s', 'kube']],
|
|
643
|
-
['network', ['ネットワーク', '网络', '네트워크', 'شبكة', 'רשת', 'شبکه', 'नेटवर्क', 'netzwerk', 'réseau', 'red', 'rete', 'rede']],
|
|
756
|
+
['network', ['ネットワーク', '网络', '네트워크', 'شبكة', 'רשת', 'شبکه', 'नेटवर्क', 'netzwerk', 'réseau', 'red', 'rete', 'rede', 'сеть', 'ağ']],
|
|
644
757
|
['timeout', ['タイムアウト', '超时', '타임아웃', 'مهلة']],
|
|
645
|
-
['memory', ['メモリ', '内存', '메모리', 'ram', 'ذاكرة', 'זיכרון', 'حافظه', 'मेमोरी', 'speicher', 'mémoire', 'memoria', 'memória']],
|
|
646
|
-
['config', ['設定', '配置', '설정', 'configuration', 'settings', 'conf', 'إعدادات', 'הגדרות', 'پیکربندی', 'कॉन्फ़िग', 'konfiguration', 'einstellungen', 'configuración', 'configurazione', 'configuração']],
|
|
647
|
-
['install', ['インストール', '安装', '설치', 'تثبيت', 'התקנה', 'نصب', 'इंस्टॉल', 'installieren', 'installer', 'instalar', 'installare']],
|
|
648
|
-
['update', ['アップデート', '更新', '업데이트', 'upgrade', 'تحديث', 'עדכון', 'بهروزرسانی', 'अपडेट', 'aktualisieren', 'aktualisierung', 'actualizar', 'aggiornare', 'atualizar']],
|
|
649
|
-
['log', ['ログ', '日志', '로그', 'logging', 'سجل', 'יומן', 'ثبت', 'लॉग', 'protokoll', 'protokolle', 'journal', 'registro']],
|
|
758
|
+
['memory', ['メモリ', '内存', '메모리', 'ram', 'ذاكرة', 'זיכרון', 'حافظه', 'मेमोरी', 'speicher', 'mémoire', 'memoria', 'memória', 'память', 'bellek', 'hafıza']],
|
|
759
|
+
['config', ['設定', '配置', '설정', 'configuration', 'settings', 'conf', 'إعدادات', 'הגדרות', 'پیکربندی', 'कॉन्फ़िग', 'konfiguration', 'einstellungen', 'configuración', 'configurazione', 'configuração', 'конфигурация', 'настройки', 'yapılandırma', 'ayarlar']],
|
|
760
|
+
['install', ['インストール', '安装', '설치', 'تثبيت', 'התקנה', 'نصب', 'इंस्टॉल', 'installieren', 'installer', 'instalar', 'installare', 'установить', 'установка', 'yüklemek', 'kurulum']],
|
|
761
|
+
['update', ['アップデート', '更新', '업데이트', 'upgrade', 'تحديث', 'עדכון', 'بهروزرسانی', 'अपडेट', 'aktualisieren', 'aktualisierung', 'actualizar', 'aggiornare', 'atualizar', 'обновление', 'обновить', 'güncelleme']],
|
|
762
|
+
['log', ['ログ', '日志', '로그', 'logging', 'سجل', 'יומן', 'ثبت', 'लॉग', 'protokoll', 'protokolle', 'journal', 'registro', 'журнал', 'лог', 'günlük']],
|
|
650
763
|
['port', ['ポート', '端口', '포트', 'منفذ', 'פורט']],
|
|
651
764
|
['file', ['ファイル', '文件', '파일', 'ملف', 'קובץ']],
|
|
652
765
|
['image', ['イメージ', '镜像', '이미지', 'صورة', 'תמונה', 'abbild', 'imagen', 'imagem']],
|
|
653
766
|
['volume', ['ボリューム', '卷', '볼륨']],
|
|
654
767
|
['cluster', ['クラスター', '集群', '클러스터']],
|
|
655
768
|
['node', ['ノード', '节点', '노드']],
|
|
656
|
-
['service', ['サービス', '服务', '서비스', 'svc', 'خدمة', 'שירות', 'dienst', 'servicio', 'servizio', 'serviço']],
|
|
769
|
+
['service', ['サービス', '服务', '서비스', 'svc', 'خدمة', 'שירות', 'dienst', 'servicio', 'servizio', 'serviço', 'сервис', 'служба', 'servis', 'hizmet']],
|
|
657
770
|
['certificate', ['証明書', '证书', '인증서', 'cert', 'ssl', 'tls', 'شهادة', 'תעודה']],
|
|
658
771
|
['password', ['パスワード', '密码', '비밀번호', 'passwd', 'pwd', 'كلمة المرور', 'סיסמה']],
|
|
659
772
|
['token', ['トークン', '令牌', '토큰', 'jwt', 'secret', 'رمز', 'אסימון']],
|
|
660
773
|
['health', ['ヘルス', '健康', '헬스', 'healthcheck', 'probe', 'صحة']],
|
|
661
774
|
['migration', ['マイグレーション', '迁移', '마이그레이션', 'migrate', 'هجرة']],
|
|
662
|
-
['backup', ['バックアップ', '备份', '백업', 'نسخ احتياطي', 'גיבוי', 'پشتیبانگیری', 'बैकअप', 'sicherung', 'sauvegarde', 'respaldo', 'cópia de segurança']],
|
|
663
|
-
['monitor', ['モニター', '监控', '모니터링', 'monitoring', 'metrics', 'alert', 'مراقبة', 'ניטור', 'نظارت', 'निगरानी', 'überwachung', 'surveiller', 'monitoreo', 'monitorare', 'monitorar']],
|
|
664
|
-
['performance', ['パフォーマンス', '性能', '성능', 'latency', 'throughput', 'عملکرد', 'प्रदर्शन', 'leistung', 'performances', 'rendimiento', 'prestazioni', 'desempenho']],
|
|
775
|
+
['backup', ['バックアップ', '备份', '백업', 'نسخ احتياطي', 'גיבוי', 'پشتیبانگیری', 'बैकअप', 'sicherung', 'sauvegarde', 'respaldo', 'cópia de segurança', 'резервная копия', 'резерв', 'yedekleme']],
|
|
776
|
+
['monitor', ['モニター', '监控', '모니터링', 'monitoring', 'metrics', 'alert', 'مراقبة', 'ניטור', 'نظارت', 'निगरानी', 'überwachung', 'surveiller', 'monitoreo', 'monitorare', 'monitorar', 'мониторинг', 'наблюдение', 'izleme']],
|
|
777
|
+
['performance', ['パフォーマンス', '性能', '성능', 'latency', 'throughput', 'عملکرد', 'प्रदर्शन', 'leistung', 'performances', 'rendimiento', 'prestazioni', 'desempenho', 'производительность', 'быстродействие', 'performans']],
|
|
665
778
|
['connection', ['接続', '连接', '연결', 'conn', 'socket', 'اتصال', 'חיבור', 'اتصال', 'कनेक्शन', 'verbindung', 'connexion', 'conexión', 'connessione', 'conexão']],
|
|
666
779
|
['queue', ['キュー', '队列', '큐', 'طابور', 'warteschlange', 'file d\'attente', 'cola', 'coda', 'fila']],
|
|
667
780
|
['redis', ['レディス', '레디스']],
|
|
@@ -676,10 +789,10 @@ const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
|
676
789
|
['git', ['version control', 'repo', 'repository', 'commit', 'push', 'pull']],
|
|
677
790
|
['ci', ['pipeline', 'github actions', 'gitlab', 'jenkins', 'build']],
|
|
678
791
|
['cd', ['deploy', 'deployment', 'release']],
|
|
679
|
-
['debug', ['デバッグ', '调试', '디버그', 'debugging', 'breakpoint', 'تصحيح', 'איתור באגים', 'اشکالزدایی', 'डीबग', 'debuggen', 'déboguer', 'depurar']],
|
|
680
|
-
['crash', ['クラッシュ', '崩溃', '크래시', 'panic', 'segfault', 'انهيار', 'קריסה', 'خرابی', 'क्रैश', 'absturz', 'panne', 'plantage', 'caída', 'falha']],
|
|
792
|
+
['debug', ['デバッグ', '调试', '디버그', 'debugging', 'breakpoint', 'تصحيح', 'איתור באגים', 'اشکالزدایی', 'डीबग', 'debuggen', 'déboguer', 'depurar', 'отладка', 'дебаг', 'hata ayıklama']],
|
|
793
|
+
['crash', ['クラッシュ', '崩溃', '크래시', 'panic', 'segfault', 'انهيار', 'קריסה', 'خرابی', 'क्रैश', 'absturz', 'panne', 'plantage', 'caída', 'falha', 'сбой', 'крэш', 'çökme', 'çöküş']],
|
|
681
794
|
['restart', ['再起動', '重启', '재시작', 'reboot', 'إعادة تشغيل', 'הפעלה מחדש', 'راهاندازی مجدد', 'पुنरारंभ', 'neustart', 'redémarrer', 'reiniciar', 'riavviare']],
|
|
682
|
-
['permission', ['権限', '权限', '권한', 'access', 'acl', 'chmod', 'صلاحية', 'הרשאה', 'مجوز', 'अनुमति', 'berechtigung', 'berechtigungen', 'permiso', 'permesso', 'permissão']],
|
|
795
|
+
['permission', ['権限', '权限', '권한', 'access', 'acl', 'chmod', 'صلاحية', 'הרשאה', 'مجوز', 'अनुमति', 'berechtigung', 'berechtigungen', 'permiso', 'permesso', 'permissão', 'разрешение', 'доступ', 'izin', 'yetki']],
|
|
683
796
|
// Japanese katakana → English
|
|
684
797
|
['デプロイ', ['deploy', 'deployment']],
|
|
685
798
|
['コンテナ', ['container', 'docker']],
|
|
@@ -1114,6 +1227,105 @@ const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
|
1114
1227
|
['ambiente', ['environment', 'env']],
|
|
1115
1228
|
['fila', ['queue']],
|
|
1116
1229
|
['imagem', ['image']],
|
|
1230
|
+
|
|
1231
|
+
// ── Russian (Cyrillic) → English ──────────────────────────────────────────
|
|
1232
|
+
['ошибка', ['error', 'err']],
|
|
1233
|
+
['ошибки', ['error', 'err']],
|
|
1234
|
+
['сбой', ['crash', 'failure', 'error']],
|
|
1235
|
+
['крэш', ['crash', 'panic']],
|
|
1236
|
+
['баг', ['bug', 'issue']],
|
|
1237
|
+
['исправить', ['fix', 'bugfix']],
|
|
1238
|
+
['исправление', ['fix', 'patch']],
|
|
1239
|
+
['сборка', ['build']],
|
|
1240
|
+
['собрать', ['build']],
|
|
1241
|
+
['тест', ['test']],
|
|
1242
|
+
['тестирование', ['test', 'testing']],
|
|
1243
|
+
['аутентификация', ['auth', 'authentication']],
|
|
1244
|
+
['авторизация', ['auth', 'authorization']],
|
|
1245
|
+
['конфигурация', ['config', 'configuration']],
|
|
1246
|
+
['настройки', ['config', 'settings']],
|
|
1247
|
+
['установить', ['install']],
|
|
1248
|
+
['установка', ['install']],
|
|
1249
|
+
['обновление', ['update', 'upgrade']],
|
|
1250
|
+
['обновить', ['update', 'upgrade']],
|
|
1251
|
+
['журнал', ['log']],
|
|
1252
|
+
['лог', ['log', 'logs']],
|
|
1253
|
+
['сервер', ['server']],
|
|
1254
|
+
['база данных', ['database', 'db']],
|
|
1255
|
+
['сеть', ['network']],
|
|
1256
|
+
['память', ['memory', 'ram']],
|
|
1257
|
+
['кэш', ['cache']],
|
|
1258
|
+
['отладка', ['debug', 'debugging']],
|
|
1259
|
+
['перезапуск', ['restart', 'reboot']],
|
|
1260
|
+
['перезагрузка', ['restart', 'reboot']],
|
|
1261
|
+
['разрешение', ['permission', 'access']],
|
|
1262
|
+
['доступ', ['permission', 'access']],
|
|
1263
|
+
['резерв', ['backup']],
|
|
1264
|
+
['производительность', ['performance']],
|
|
1265
|
+
['проблема', ['problem', 'issue', 'error']],
|
|
1266
|
+
['сервис', ['service']],
|
|
1267
|
+
['служба', ['service']],
|
|
1268
|
+
['подключение', ['connection', 'conn']],
|
|
1269
|
+
['соединение', ['connection', 'conn']],
|
|
1270
|
+
['развёртывание', ['deploy', 'deployment']],
|
|
1271
|
+
['развертывание', ['deploy', 'deployment']],
|
|
1272
|
+
['контейнер', ['container', 'docker']],
|
|
1273
|
+
['образ', ['image']],
|
|
1274
|
+
['кластер', ['cluster']],
|
|
1275
|
+
['узел', ['node']],
|
|
1276
|
+
['секрет', ['secret', 'key', 'token']],
|
|
1277
|
+
['ключ', ['key', 'token', 'secret']],
|
|
1278
|
+
['пароль', ['password']],
|
|
1279
|
+
['токен', ['token', 'secret']],
|
|
1280
|
+
['мониторинг', ['monitor', 'monitoring']],
|
|
1281
|
+
['наблюдение', ['monitor', 'monitoring']],
|
|
1282
|
+
['мигрировать', ['migrate', 'migration']],
|
|
1283
|
+
['миграция', ['migrate', 'migration']],
|
|
1284
|
+
|
|
1285
|
+
// ── Turkish (Latin + special chars ğ/ş/ı) → English ─────────────────────
|
|
1286
|
+
['hata', ['error', 'err']],
|
|
1287
|
+
['hatalı', ['error', 'err']],
|
|
1288
|
+
['çökme', ['crash', 'panic']],
|
|
1289
|
+
['çöküş', ['crash', 'failure']],
|
|
1290
|
+
['düzeltmek', ['fix', 'bugfix']],
|
|
1291
|
+
['düzeltme', ['fix', 'patch']],
|
|
1292
|
+
['derleme', ['build']],
|
|
1293
|
+
['derlemek', ['build']],
|
|
1294
|
+
['test', ['test']],
|
|
1295
|
+
['testlemek', ['test', 'testing']],
|
|
1296
|
+
['kimlik doğrulama',['auth', 'authentication']],
|
|
1297
|
+
['yetkilendirme', ['auth', 'authorization']],
|
|
1298
|
+
['yapılandırma', ['config', 'configuration']],
|
|
1299
|
+
['ayarlar', ['config', 'settings']],
|
|
1300
|
+
['yüklemek', ['install']],
|
|
1301
|
+
['kurulum', ['install']],
|
|
1302
|
+
['güncelleme', ['update', 'upgrade']],
|
|
1303
|
+
['günlük', ['log']],
|
|
1304
|
+
['sunucu', ['server']],
|
|
1305
|
+
['veritabanı', ['database', 'db']],
|
|
1306
|
+
['ağ', ['network']],
|
|
1307
|
+
['bellek', ['memory', 'ram']],
|
|
1308
|
+
['önbellek', ['cache']],
|
|
1309
|
+
['hata ayıklama', ['debug', 'debugging']],
|
|
1310
|
+
['yeniden başlatma',['restart', 'reboot']],
|
|
1311
|
+
['izin', ['permission', 'access']],
|
|
1312
|
+
['yetki', ['permission', 'access', 'acl']],
|
|
1313
|
+
['yedekleme', ['backup']],
|
|
1314
|
+
['performans', ['performance']],
|
|
1315
|
+
['sorun', ['problem', 'issue', 'error']],
|
|
1316
|
+
['servis', ['service']],
|
|
1317
|
+
['hizmet', ['service']],
|
|
1318
|
+
['bağlantı', ['connection', 'conn']],
|
|
1319
|
+
['dağıtım', ['deploy', 'deployment']],
|
|
1320
|
+
['dağıtmak', ['deploy']],
|
|
1321
|
+
['konteyner', ['container', 'docker']],
|
|
1322
|
+
['küme', ['cluster']],
|
|
1323
|
+
['düğüm', ['node']],
|
|
1324
|
+
['gizli', ['secret', 'key']],
|
|
1325
|
+
['anahtar', ['key', 'token', 'secret']],
|
|
1326
|
+
['şifre', ['password']],
|
|
1327
|
+
['izleme', ['monitor', 'monitoring']],
|
|
1328
|
+
['göç', ['migrate', 'migration']],
|
|
1117
1329
|
]);
|
|
1118
1330
|
|
|
1119
1331
|
/**
|
|
@@ -1196,13 +1408,31 @@ function tokenize(text: string): string[] {
|
|
|
1196
1408
|
const stemmed = hindiLightStem(deva);
|
|
1197
1409
|
if (stemmed.length > 1 && !STOPWORDS.has(stemmed)) tokens.push(stemmed);
|
|
1198
1410
|
}
|
|
1411
|
+
} else if (CYRILLIC_RE.test(seg)) {
|
|
1412
|
+
// Cyrillic segment (Russian, Bulgarian, Ukrainian, Serbian …)
|
|
1413
|
+
const words = seg.trim().split(/\s+/);
|
|
1414
|
+
for (const w of words) {
|
|
1415
|
+
const cyr = w.replace(/[^\u0400-\u04ff]/g, '');
|
|
1416
|
+
if (cyr.length <= 1 || STOPWORDS.has(cyr)) continue;
|
|
1417
|
+
const stemmed = russianLightStem(cyr);
|
|
1418
|
+
if (stemmed.length > 1 && !STOPWORDS.has(stemmed)) tokens.push(stemmed);
|
|
1419
|
+
}
|
|
1199
1420
|
} else {
|
|
1200
|
-
// Latin / other
|
|
1421
|
+
// Latin / other (includes Turkish with special chars ğ/ş/ı)
|
|
1201
1422
|
const words = seg
|
|
1202
|
-
.replace(/[^a-
|
|
1423
|
+
.replace(/[^a-záàâãäåæçéèêëíìîïñóòôõöúùûüýÿßœğşıİ0-9:_\-./]/g, ' ')
|
|
1203
1424
|
.split(/\s+/)
|
|
1204
1425
|
.filter(w => w.length > 1 && !STOPWORDS.has(w));
|
|
1205
|
-
|
|
1426
|
+
// Turkish: apply light stemmer to words with Turkish-specific chars
|
|
1427
|
+
for (const w of words) {
|
|
1428
|
+
if (TURKISH_CHAR_RE.test(w)) {
|
|
1429
|
+
const stemmed = turkishLightStem(w);
|
|
1430
|
+
if (stemmed !== w && stemmed.length > 1 && !STOPWORDS.has(stemmed)) {
|
|
1431
|
+
tokens.push(stemmed);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
tokens.push(w);
|
|
1435
|
+
}
|
|
1206
1436
|
}
|
|
1207
1437
|
}
|
|
1208
1438
|
|
|
@@ -1237,10 +1467,27 @@ function tokenize(text: string): string[] {
|
|
|
1237
1467
|
// Devanagari synonym (Hindi)
|
|
1238
1468
|
const stemmed = hindiLightStem(syn);
|
|
1239
1469
|
if (stemmed.length > 1 && !STOPWORDS.has(stemmed)) expansions.push(stemmed);
|
|
1470
|
+
} else if (CYRILLIC_RE.test(syn)) {
|
|
1471
|
+
// Cyrillic synonym (Russian)
|
|
1472
|
+
const cyr = syn.replace(/[^\u0400-\u04ff]/g, '');
|
|
1473
|
+
const stemmed = russianLightStem(cyr);
|
|
1474
|
+
if (stemmed.length > 1 && !STOPWORDS.has(stemmed)) expansions.push(stemmed);
|
|
1240
1475
|
} else {
|
|
1241
|
-
// Latin synonym — split in case of multi-word
|
|
1242
|
-
const parts = syn.split(/\s+/).filter(w =>
|
|
1243
|
-
|
|
1476
|
+
// Latin synonym (includes Turkish) — split in case of multi-word
|
|
1477
|
+
const parts = syn.split(/\s+/).filter(w => {
|
|
1478
|
+
if (w.length <= 1 || STOPWORDS.has(w)) return false;
|
|
1479
|
+
return true;
|
|
1480
|
+
});
|
|
1481
|
+
for (const p of parts) {
|
|
1482
|
+
expansions.push(p);
|
|
1483
|
+
// Apply Turkish stemmer if it has Turkish-specific characters
|
|
1484
|
+
if (TURKISH_CHAR_RE.test(p)) {
|
|
1485
|
+
const stemmed = turkishLightStem(p);
|
|
1486
|
+
if (stemmed !== p && stemmed.length > 1 && !STOPWORDS.has(stemmed)) {
|
|
1487
|
+
expansions.push(stemmed);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1244
1491
|
}
|
|
1245
1492
|
}
|
|
1246
1493
|
}
|
|
@@ -1268,9 +1515,9 @@ function splitMultiQuery(query: string): string[] {
|
|
|
1268
1515
|
const semiParts = query.split(/[;\n]+/).filter(s => s.trim().length > 2);
|
|
1269
1516
|
if (semiParts.length >= 2) return semiParts.map(s => s.trim());
|
|
1270
1517
|
|
|
1271
|
-
// Conjunctions (EN + DE + FR + ES)
|
|
1518
|
+
// Conjunctions (EN + DE + FR + ES + IT + PT + RU + TR)
|
|
1272
1519
|
const conjParts = query.split(
|
|
1273
|
-
/\b(?:and also|also noch|außerdem|plus|additionally|furthermore|de plus|además|inoltre|além disso)\b/i
|
|
1520
|
+
/\b(?:and also|also noch|außerdem|plus|additionally|furthermore|de plus|además|inoltre|além disso|а также|и также|кроме того|плюс|ayrıca|bunun yanı sıra|همچنین|وأيضاً|وكذلك|وهمچنین|और भी|इसके अलावा)\b/i
|
|
1274
1521
|
).filter(s => s.trim().length > 2);
|
|
1275
1522
|
if (conjParts.length >= 2) return conjParts.map(s => s.trim());
|
|
1276
1523
|
|
|
@@ -1535,6 +1782,12 @@ async function keywordSearch(
|
|
|
1535
1782
|
}
|
|
1536
1783
|
}
|
|
1537
1784
|
|
|
1785
|
+
// Phrase-match boost: if the raw (lowercased) query appears verbatim in content, 2× boost
|
|
1786
|
+
// This rewards docs where the exact phrase exists (vs scattered tokens).
|
|
1787
|
+
if (sq.length >= 4 && doc.content.toLowerCase().includes(sq.toLowerCase())) {
|
|
1788
|
+
score *= 2.0;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1538
1791
|
// Recency boost
|
|
1539
1792
|
score *= recencyBoost(doc.timestamp);
|
|
1540
1793
|
|