cc-viewer 1.0.13 → 1.0.15
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/README.md +3 -0
- package/dist/assets/index-B05wFUK_.css +1 -0
- package/dist/assets/index-DnNjgun1.js +514 -0
- package/dist/index.html +2 -2
- package/interceptor.js +65 -1
- package/locales/i18n.json +200 -0
- package/package.json +1 -1
- package/server.js +7 -0
- package/dist/assets/index-CYzeFMnR.js +0 -513
- package/dist/assets/index-DaWfq9ke.css +0 -1
package/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Claude Code Viewer</title>
|
|
7
7
|
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DnNjgun1.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B05wFUK_.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/interceptor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// LLM Request Interceptor
|
|
2
2
|
// 拦截并记录所有Claude API请求
|
|
3
|
-
import { appendFileSync, mkdirSync, readdirSync, readFileSync, statSync, renameSync, unlinkSync, existsSync } from 'node:fs';
|
|
3
|
+
import { appendFileSync, mkdirSync, readdirSync, readFileSync, writeFileSync, statSync, renameSync, unlinkSync, existsSync } from 'node:fs';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { dirname, join, basename } from 'node:path';
|
|
@@ -133,13 +133,77 @@ export { LOG_FILE, _initPromise, _resumeState, _choicePromise, resolveResumeChoi
|
|
|
133
133
|
|
|
134
134
|
const MAX_LOG_SIZE = 200 * 1024 * 1024; // 200MB
|
|
135
135
|
|
|
136
|
+
function isPreflightEntry(entry) {
|
|
137
|
+
if (entry.mainAgent || entry.isHeartbeat || entry.isCountTokens) return false;
|
|
138
|
+
const body = entry.body || {};
|
|
139
|
+
if (Array.isArray(body.tools) && body.tools.length > 0) return false;
|
|
140
|
+
const msgs = body.messages || [];
|
|
141
|
+
if (msgs.length !== 1 || msgs[0].role !== 'user') return false;
|
|
142
|
+
const sysText = typeof body.system === 'string' ? body.system :
|
|
143
|
+
Array.isArray(body.system) ? body.system.map(s => s?.text || '').join('') : '';
|
|
144
|
+
return sysText.includes('Claude Code');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function migrateConversationContext(oldFile, newFile) {
|
|
148
|
+
try {
|
|
149
|
+
const content = readFileSync(oldFile, 'utf-8');
|
|
150
|
+
if (!content.trim()) return;
|
|
151
|
+
|
|
152
|
+
const parts = content.split('\n---\n').filter(p => p.trim());
|
|
153
|
+
if (parts.length === 0) return;
|
|
154
|
+
|
|
155
|
+
// 从后向前扫描,找到最近一条 messages.length === 1 的 mainAgent 条目
|
|
156
|
+
let originIndex = -1;
|
|
157
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
158
|
+
if (!parts[i].includes('"mainAgent": true')) continue;
|
|
159
|
+
try {
|
|
160
|
+
const entry = JSON.parse(parts[i]);
|
|
161
|
+
if (entry.mainAgent) {
|
|
162
|
+
const msgs = entry.body?.messages;
|
|
163
|
+
if (Array.isArray(msgs) && msgs.length === 1) {
|
|
164
|
+
originIndex = i;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch {}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (originIndex < 0) return; // 找不到起点,不迁移
|
|
172
|
+
|
|
173
|
+
// 检查前一条是否为 Preflight
|
|
174
|
+
let migrationStart = originIndex;
|
|
175
|
+
if (originIndex > 0) {
|
|
176
|
+
try {
|
|
177
|
+
const prev = JSON.parse(parts[originIndex - 1]);
|
|
178
|
+
if (isPreflightEntry(prev)) {
|
|
179
|
+
migrationStart = originIndex - 1;
|
|
180
|
+
}
|
|
181
|
+
} catch {}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 迁移条目写入新文件
|
|
185
|
+
const migratedParts = parts.slice(migrationStart);
|
|
186
|
+
writeFileSync(newFile, migratedParts.join('\n---\n') + '\n---\n');
|
|
187
|
+
|
|
188
|
+
// 旧文件只保留迁移前的条目
|
|
189
|
+
const remainingParts = parts.slice(0, migrationStart);
|
|
190
|
+
if (remainingParts.length > 0) {
|
|
191
|
+
writeFileSync(oldFile, remainingParts.join('\n---\n') + '\n---\n');
|
|
192
|
+
} else {
|
|
193
|
+
writeFileSync(oldFile, '');
|
|
194
|
+
}
|
|
195
|
+
} catch {}
|
|
196
|
+
}
|
|
197
|
+
|
|
136
198
|
function checkAndRotateLogFile() {
|
|
137
199
|
try {
|
|
138
200
|
if (!existsSync(LOG_FILE)) return;
|
|
139
201
|
const size = statSync(LOG_FILE).size;
|
|
140
202
|
if (size >= MAX_LOG_SIZE) {
|
|
203
|
+
const oldFile = LOG_FILE;
|
|
141
204
|
const { filePath } = generateNewLogFilePath();
|
|
142
205
|
LOG_FILE = filePath;
|
|
206
|
+
migrateConversationContext(oldFile, filePath);
|
|
143
207
|
}
|
|
144
208
|
} catch {}
|
|
145
209
|
}
|
package/locales/i18n.json
CHANGED
|
@@ -679,6 +679,46 @@
|
|
|
679
679
|
"tr": "Ham moda dön",
|
|
680
680
|
"uk": "Повернутися до режиму raw"
|
|
681
681
|
},
|
|
682
|
+
"ui.viewRequest": {
|
|
683
|
+
"zh": "查看请求",
|
|
684
|
+
"en": "View Request",
|
|
685
|
+
"zh-TW": "查看請求",
|
|
686
|
+
"ko": "요청 보기",
|
|
687
|
+
"ja": "リクエストを表示",
|
|
688
|
+
"de": "Anfrage anzeigen",
|
|
689
|
+
"es": "Ver solicitud",
|
|
690
|
+
"fr": "Voir la requête",
|
|
691
|
+
"it": "Visualizza richiesta",
|
|
692
|
+
"da": "Vis forespørgsel",
|
|
693
|
+
"pl": "Zobacz żądanie",
|
|
694
|
+
"ru": "Просмотр запроса",
|
|
695
|
+
"ar": "عرض الطلب",
|
|
696
|
+
"no": "Vis forespørsel",
|
|
697
|
+
"pt-BR": "Ver requisição",
|
|
698
|
+
"th": "ดูคำขอ",
|
|
699
|
+
"tr": "İsteği görüntüle",
|
|
700
|
+
"uk": "Переглянути запит"
|
|
701
|
+
},
|
|
702
|
+
"ui.cannotMap": {
|
|
703
|
+
"zh": "无法映射到对话",
|
|
704
|
+
"en": "Cannot map to conversation",
|
|
705
|
+
"zh-TW": "無法映射到對話",
|
|
706
|
+
"ko": "대화에 매핑할 수 없습니다",
|
|
707
|
+
"ja": "会話にマッピングできません",
|
|
708
|
+
"de": "Kann nicht zur Konversation zugeordnet werden",
|
|
709
|
+
"es": "No se puede mapear a la conversación",
|
|
710
|
+
"fr": "Impossible de mapper à la conversation",
|
|
711
|
+
"it": "Impossibile mappare alla conversazione",
|
|
712
|
+
"da": "Kan ikke mappe til samtale",
|
|
713
|
+
"pl": "Nie można zmapować do rozmowy",
|
|
714
|
+
"ru": "Невозможно сопоставить с диалогом",
|
|
715
|
+
"ar": "لا يمكن الربط بالمحادثة",
|
|
716
|
+
"no": "Kan ikke tilordne til samtale",
|
|
717
|
+
"pt-BR": "Não é possível mapear para a conversa",
|
|
718
|
+
"th": "ไม่สามารถแมปไปยังการสนทนาได้",
|
|
719
|
+
"tr": "Konuşmaya eşlenemedi",
|
|
720
|
+
"uk": "Неможливо зіставити з діалогом"
|
|
721
|
+
},
|
|
682
722
|
"ui.cacheExpired": {
|
|
683
723
|
"zh": "已失效",
|
|
684
724
|
"en": "Expired",
|
|
@@ -879,6 +919,26 @@
|
|
|
879
919
|
"tr": "Log dosyası yok",
|
|
880
920
|
"uk": "Немає файлів логів"
|
|
881
921
|
},
|
|
922
|
+
"ui.footer.contact": {
|
|
923
|
+
"zh": "如需帮助,请联系 @水映天辙(钉钉)",
|
|
924
|
+
"en": "Need help? Contact @水映天辙 (DingTalk)",
|
|
925
|
+
"zh-TW": "如需幫助,請聯繫 @水映天辙(釘釘)",
|
|
926
|
+
"ko": "도움이 필요하면 @水映天辙(DingTalk)에 연락하세요",
|
|
927
|
+
"ja": "ヘルプが必要な場合は @水映天辙(DingTalk) にご連絡ください",
|
|
928
|
+
"de": "Hilfe benötigt? Kontaktieren Sie @水映天辙 (DingTalk)",
|
|
929
|
+
"es": "¿Necesita ayuda? Contacte a @水映天辙 (DingTalk)",
|
|
930
|
+
"fr": "Besoin d'aide ? Contactez @水映天辙 (DingTalk)",
|
|
931
|
+
"it": "Hai bisogno di aiuto? Contatta @水映天辙 (DingTalk)",
|
|
932
|
+
"da": "Brug for hjælp? Kontakt @水映天辙 (DingTalk)",
|
|
933
|
+
"pl": "Potrzebujesz pomocy? Skontaktuj się z @水映天辙 (DingTalk)",
|
|
934
|
+
"ru": "Нужна помощь? Свяжитесь с @水映天辙 (DingTalk)",
|
|
935
|
+
"ar": "تحتاج مساعدة؟ تواصل مع @水映天辙 (DingTalk)",
|
|
936
|
+
"no": "Trenger du hjelp? Kontakt @水映天辙 (DingTalk)",
|
|
937
|
+
"pt-BR": "Precisa de ajuda? Entre em contato com @水映天辙 (DingTalk)",
|
|
938
|
+
"th": "ต้องการความช่วยเหลือ? ติดต่อ @水映天辙 (DingTalk)",
|
|
939
|
+
"tr": "Yardıma mı ihtiyacınız var? @水映天辙 (DingTalk) ile iletişime geçin",
|
|
940
|
+
"uk": "Потрібна допомога? Зв'яжіться з @水映天辙 (DingTalk)"
|
|
941
|
+
},
|
|
882
942
|
"ui.toolReturn": {
|
|
883
943
|
"zh": "工具返回",
|
|
884
944
|
"en": "Tool result",
|
|
@@ -1498,5 +1558,145 @@
|
|
|
1498
1558
|
"th": "โหลด Skill แล้ว",
|
|
1499
1559
|
"tr": "Skill yüklendi",
|
|
1500
1560
|
"uk": "Skill завантажено"
|
|
1561
|
+
},
|
|
1562
|
+
"ui.cacheLoss.ttl": {
|
|
1563
|
+
"zh": "缓存丢失:距上次 MainAgent 请求超过 5 分钟,缓存已过期",
|
|
1564
|
+
"en": "Cache miss: over 5 minutes since last MainAgent request, cache expired",
|
|
1565
|
+
"zh-TW": "快取遺失:距上次 MainAgent 請求超過 5 分鐘,快取已過期",
|
|
1566
|
+
"ko": "캐시 손실: 마지막 MainAgent 요청 후 5분 초과, 캐시 만료",
|
|
1567
|
+
"ja": "キャッシュミス:前回の MainAgent リクエストから5分以上経過、キャッシュ期限切れ",
|
|
1568
|
+
"de": "Cache-Verlust: Über 5 Minuten seit letzter MainAgent-Anfrage, Cache abgelaufen",
|
|
1569
|
+
"es": "Pérdida de caché: más de 5 minutos desde la última solicitud MainAgent, caché expirada",
|
|
1570
|
+
"fr": "Perte de cache : plus de 5 minutes depuis la dernière requête MainAgent, cache expiré",
|
|
1571
|
+
"it": "Cache persa: oltre 5 minuti dall'ultima richiesta MainAgent, cache scaduta",
|
|
1572
|
+
"da": "Cache-tab: over 5 minutter siden sidste MainAgent-forespørgsel, cache udløbet",
|
|
1573
|
+
"pl": "Utrata cache: ponad 5 minut od ostatniego żądania MainAgent, cache wygasł",
|
|
1574
|
+
"ru": "Потеря кэша: прошло более 5 минут с последнего запроса MainAgent, кэш истёк",
|
|
1575
|
+
"ar": "فقدان التخزين المؤقت: مرور أكثر من 5 دقائق منذ آخر طلب MainAgent، انتهت صلاحية التخزين المؤقت",
|
|
1576
|
+
"no": "Cache-tap: over 5 minutter siden siste MainAgent-forespørsel, cache utløpt",
|
|
1577
|
+
"pt-BR": "Perda de cache: mais de 5 minutos desde a última requisição MainAgent, cache expirado",
|
|
1578
|
+
"th": "แคชหาย: เกิน 5 นาทีจากคำขอ MainAgent ล่าสุด แคชหมดอายุ",
|
|
1579
|
+
"tr": "Önbellek kaybı: Son MainAgent isteğinden 5 dakikadan fazla geçti, önbellek süresi doldu",
|
|
1580
|
+
"uk": "Втрата кешу: минуло понад 5 хвилин з останнього запиту MainAgent, кеш закінчився"
|
|
1581
|
+
},
|
|
1582
|
+
"ui.cacheLoss.systemChange": {
|
|
1583
|
+
"zh": "缓存重建:system prompt 发生变更",
|
|
1584
|
+
"en": "Cache rebuild: system prompt changed",
|
|
1585
|
+
"zh-TW": "快取重建:system prompt 發生變更",
|
|
1586
|
+
"ko": "캐시 재생성: 시스템 프롬프트 변경",
|
|
1587
|
+
"ja": "キャッシュ再構築:システムプロンプトが変更されました",
|
|
1588
|
+
"de": "Cache-Neuaufbau: System-Prompt geändert",
|
|
1589
|
+
"es": "Reconstrucción de caché: el prompt del sistema cambió",
|
|
1590
|
+
"fr": "Reconstruction du cache : le prompt système a changé",
|
|
1591
|
+
"it": "Ricostruzione cache: il prompt di sistema è cambiato",
|
|
1592
|
+
"da": "Cache-genopbygning: systemprompt ændret",
|
|
1593
|
+
"pl": "Odbudowa cache: prompt systemowy zmieniony",
|
|
1594
|
+
"ru": "Перестройка кэша: системный промпт изменён",
|
|
1595
|
+
"ar": "إعادة بناء التخزين المؤقت: تم تغيير موجه النظام",
|
|
1596
|
+
"no": "Cache-gjenoppbygging: systemprompt endret",
|
|
1597
|
+
"pt-BR": "Reconstrução de cache: prompt do sistema alterado",
|
|
1598
|
+
"th": "สร้างแคชใหม่: system prompt เปลี่ยนแปลง",
|
|
1599
|
+
"tr": "Önbellek yeniden oluşturma: sistem istemi değişti",
|
|
1600
|
+
"uk": "Перебудова кешу: системний промпт змінено"
|
|
1601
|
+
},
|
|
1602
|
+
"ui.cacheLoss.toolsChange": {
|
|
1603
|
+
"zh": "缓存重建:工具定义发生变更",
|
|
1604
|
+
"en": "Cache rebuild: tool definitions changed",
|
|
1605
|
+
"zh-TW": "快取重建:工具定義發生變更",
|
|
1606
|
+
"ko": "캐시 재생성: 도구 정의 변경",
|
|
1607
|
+
"ja": "キャッシュ再構築:ツール定義が変更されました",
|
|
1608
|
+
"de": "Cache-Neuaufbau: Tool-Definitionen geändert",
|
|
1609
|
+
"es": "Reconstrucción de caché: las definiciones de herramientas cambiaron",
|
|
1610
|
+
"fr": "Reconstruction du cache : les définitions d'outils ont changé",
|
|
1611
|
+
"it": "Ricostruzione cache: le definizioni degli strumenti sono cambiate",
|
|
1612
|
+
"da": "Cache-genopbygning: værktøjsdefinitioner ændret",
|
|
1613
|
+
"pl": "Odbudowa cache: definicje narzędzi zmienione",
|
|
1614
|
+
"ru": "Перестройка кэша: определения инструментов изменены",
|
|
1615
|
+
"ar": "إعادة بناء التخزين المؤقت: تم تغيير تعريفات الأدوات",
|
|
1616
|
+
"no": "Cache-gjenoppbygging: verktøydefinisjoner endret",
|
|
1617
|
+
"pt-BR": "Reconstrução de cache: definições de ferramentas alteradas",
|
|
1618
|
+
"th": "สร้างแคชใหม่: คำจำกัดความเครื่องมือเปลี่ยนแปลง",
|
|
1619
|
+
"tr": "Önbellek yeniden oluşturma: araç tanımları değişti",
|
|
1620
|
+
"uk": "Перебудова кешу: визначення інструментів змінено"
|
|
1621
|
+
},
|
|
1622
|
+
"ui.cacheLoss.modelChange": {
|
|
1623
|
+
"zh": "缓存重建:模型切换",
|
|
1624
|
+
"en": "Cache rebuild: model switched",
|
|
1625
|
+
"zh-TW": "快取重建:模型切換",
|
|
1626
|
+
"ko": "캐시 재생성: 모델 전환",
|
|
1627
|
+
"ja": "キャッシュ再構築:モデルが切り替わりました",
|
|
1628
|
+
"de": "Cache-Neuaufbau: Modell gewechselt",
|
|
1629
|
+
"es": "Reconstrucción de caché: modelo cambiado",
|
|
1630
|
+
"fr": "Reconstruction du cache : modèle changé",
|
|
1631
|
+
"it": "Ricostruzione cache: modello cambiato",
|
|
1632
|
+
"da": "Cache-genopbygning: model skiftet",
|
|
1633
|
+
"pl": "Odbudowa cache: model zmieniony",
|
|
1634
|
+
"ru": "Перестройка кэша: модель переключена",
|
|
1635
|
+
"ar": "إعادة بناء التخزين المؤقت: تم تبديل النموذج",
|
|
1636
|
+
"no": "Cache-gjenoppbygging: modell byttet",
|
|
1637
|
+
"pt-BR": "Reconstrução de cache: modelo alterado",
|
|
1638
|
+
"th": "สร้างแคชใหม่: เปลี่ยนโมเดล",
|
|
1639
|
+
"tr": "Önbellek yeniden oluşturma: model değiştirildi",
|
|
1640
|
+
"uk": "Перебудова кешу: модель переключено"
|
|
1641
|
+
},
|
|
1642
|
+
"ui.cacheLoss.msgTruncated": {
|
|
1643
|
+
"zh": "缓存重建:消息栈被截断(上下文窗口溢出)",
|
|
1644
|
+
"en": "Cache rebuild: message stack truncated (context window overflow)",
|
|
1645
|
+
"zh-TW": "快取重建:訊息堆疊被截斷(上下文視窗溢出)",
|
|
1646
|
+
"ko": "캐시 재생성: 메시지 스택 잘림 (컨텍스트 윈도우 오버플로)",
|
|
1647
|
+
"ja": "キャッシュ再構築:メッセージスタックが切り詰められました(コンテキストウィンドウオーバーフロー)",
|
|
1648
|
+
"de": "Cache-Neuaufbau: Nachrichtenstapel gekürzt (Kontextfenster-Überlauf)",
|
|
1649
|
+
"es": "Reconstrucción de caché: pila de mensajes truncada (desbordamiento de ventana de contexto)",
|
|
1650
|
+
"fr": "Reconstruction du cache : pile de messages tronquée (dépassement de la fenêtre de contexte)",
|
|
1651
|
+
"it": "Ricostruzione cache: stack messaggi troncato (overflow finestra di contesto)",
|
|
1652
|
+
"da": "Cache-genopbygning: beskedstakken afkortet (kontekstvindue-overløb)",
|
|
1653
|
+
"pl": "Odbudowa cache: stos wiadomości obcięty (przepełnienie okna kontekstu)",
|
|
1654
|
+
"ru": "Перестройка кэша: стек сообщений усечён (переполнение контекстного окна)",
|
|
1655
|
+
"ar": "إعادة بناء التخزين المؤقت: تم اقتطاع مكدس الرسائل (تجاوز نافذة السياق)",
|
|
1656
|
+
"no": "Cache-gjenoppbygging: meldingsstakken avkortet (kontekstvindu-overflyt)",
|
|
1657
|
+
"pt-BR": "Reconstrução de cache: pilha de mensagens truncada (estouro da janela de contexto)",
|
|
1658
|
+
"th": "สร้างแคชใหม่: สแต็กข้อความถูกตัด (context window ล้น)",
|
|
1659
|
+
"tr": "Önbellek yeniden oluşturma: mesaj yığını kesildi (bağlam penceresi taşması)",
|
|
1660
|
+
"uk": "Перебудова кешу: стек повідомлень обрізано (переповнення контекстного вікна)"
|
|
1661
|
+
},
|
|
1662
|
+
"ui.cacheLoss.msgModified": {
|
|
1663
|
+
"zh": "缓存重建:历史消息内容被修改",
|
|
1664
|
+
"en": "Cache rebuild: historical message content modified",
|
|
1665
|
+
"zh-TW": "快取重建:歷史訊息內容被修改",
|
|
1666
|
+
"ko": "캐시 재생성: 이전 메시지 내용 수정됨",
|
|
1667
|
+
"ja": "キャッシュ再構築:過去のメッセージ内容が変更されました",
|
|
1668
|
+
"de": "Cache-Neuaufbau: Historische Nachrichteninhalte geändert",
|
|
1669
|
+
"es": "Reconstrucción de caché: contenido de mensajes históricos modificado",
|
|
1670
|
+
"fr": "Reconstruction du cache : contenu des messages historiques modifié",
|
|
1671
|
+
"it": "Ricostruzione cache: contenuto dei messaggi storici modificato",
|
|
1672
|
+
"da": "Cache-genopbygning: historisk beskedindhold ændret",
|
|
1673
|
+
"pl": "Odbudowa cache: treść historycznych wiadomości zmodyfikowana",
|
|
1674
|
+
"ru": "Перестройка кэша: содержимое исторических сообщений изменено",
|
|
1675
|
+
"ar": "إعادة بناء التخزين المؤقت: تم تعديل محتوى الرسائل السابقة",
|
|
1676
|
+
"no": "Cache-gjenoppbygging: historisk meldingsinnhold endret",
|
|
1677
|
+
"pt-BR": "Reconstrução de cache: conteúdo de mensagens históricas modificado",
|
|
1678
|
+
"th": "สร้างแคชใหม่: เนื้อหาข้อความในประวัติถูกแก้ไข",
|
|
1679
|
+
"tr": "Önbellek yeniden oluşturma: geçmiş mesaj içeriği değiştirildi",
|
|
1680
|
+
"uk": "Перебудова кешу: вміст історичних повідомлень змінено"
|
|
1681
|
+
},
|
|
1682
|
+
"ui.cacheLoss.keyChange": {
|
|
1683
|
+
"zh": "缓存重建:缓存键变更(原因未知)",
|
|
1684
|
+
"en": "Cache rebuild: cache key changed (unknown reason)",
|
|
1685
|
+
"zh-TW": "快取重建:快取鍵變更(原因未知)",
|
|
1686
|
+
"ko": "캐시 재생성: 캐시 키 변경 (원인 불명)",
|
|
1687
|
+
"ja": "キャッシュ再構築:キャッシュキーが変更されました(原因不明)",
|
|
1688
|
+
"de": "Cache-Neuaufbau: Cache-Schlüssel geändert (Grund unbekannt)",
|
|
1689
|
+
"es": "Reconstrucción de caché: clave de caché cambiada (razón desconocida)",
|
|
1690
|
+
"fr": "Reconstruction du cache : clé de cache modifiée (raison inconnue)",
|
|
1691
|
+
"it": "Ricostruzione cache: chiave cache cambiata (motivo sconosciuto)",
|
|
1692
|
+
"da": "Cache-genopbygning: cache-nøgle ændret (ukendt årsag)",
|
|
1693
|
+
"pl": "Odbudowa cache: klucz cache zmieniony (nieznana przyczyna)",
|
|
1694
|
+
"ru": "Перестройка кэша: ключ кэша изменён (причина неизвестна)",
|
|
1695
|
+
"ar": "إعادة بناء التخزين المؤقت: تم تغيير مفتاح التخزين المؤقت (سبب غير معروف)",
|
|
1696
|
+
"no": "Cache-gjenoppbygging: cache-nøkkel endret (ukjent årsak)",
|
|
1697
|
+
"pt-BR": "Reconstrução de cache: chave de cache alterada (motivo desconhecido)",
|
|
1698
|
+
"th": "สร้างแคชใหม่: คีย์แคชเปลี่ยนแปลง (ไม่ทราบสาเหตุ)",
|
|
1699
|
+
"tr": "Önbellek yeniden oluşturma: önbellek anahtarı değişti (bilinmeyen neden)",
|
|
1700
|
+
"uk": "Перебудова кешу: ключ кешу змінено (причина невідома)"
|
|
1501
1701
|
}
|
|
1502
1702
|
}
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -118,6 +118,13 @@ function watchLogFile(logFile) {
|
|
|
118
118
|
|
|
119
119
|
// 检测日志文件是否已轮转到新文件
|
|
120
120
|
if (LOG_FILE !== logFile && !watchedFiles.has(LOG_FILE)) {
|
|
121
|
+
// 轮转发生,发送 full_reload 让客户端重新加载新文件
|
|
122
|
+
const newEntries = readLogFile();
|
|
123
|
+
clients.forEach(client => {
|
|
124
|
+
try {
|
|
125
|
+
client.write(`event: full_reload\ndata: ${JSON.stringify(newEntries)}\n\n`);
|
|
126
|
+
} catch {}
|
|
127
|
+
});
|
|
121
128
|
watchLogFile(LOG_FILE);
|
|
122
129
|
}
|
|
123
130
|
} catch (err) {
|