cc-viewer 1.0.5 → 1.0.7
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 +2 -1
- package/dist/assets/index-Bf2poirE.js +514 -0
- package/dist/assets/index-C_eOlam6.css +1 -0
- package/dist/index.html +2 -2
- package/interceptor.js +148 -9
- package/locales/ar.json +10 -1
- package/locales/da.json +10 -1
- package/locales/de.json +10 -1
- package/locales/en.json +12 -1
- package/locales/es.json +10 -1
- package/locales/fr.json +10 -1
- package/locales/it.json +10 -1
- package/locales/ja.json +10 -1
- package/locales/ko.json +10 -1
- package/locales/no.json +10 -1
- package/locales/pl.json +10 -1
- package/locales/pt-BR.json +10 -1
- package/locales/ru.json +10 -1
- package/locales/th.json +10 -1
- package/locales/tr.json +10 -1
- package/locales/uk.json +10 -1
- package/locales/zh-TW.json +10 -1
- package/locales/zh.json +12 -1
- package/package.json +1 -1
- package/server.js +154 -6
- package/dist/assets/index-C7-c9XfU.css +0 -1
- package/dist/assets/index-DZBQn9fO.js +0 -555
|
@@ -0,0 +1 @@
|
|
|
1
|
+
body{margin:0;background-color:#0d0d0d}*{scrollbar-width:thin;scrollbar-color:#3a3a3a #0d0d0d}*::-webkit-scrollbar{width:6px;height:6px}*::-webkit-scrollbar-track{background:#0d0d0d}*::-webkit-scrollbar-thumb{background:#3a3a3a;border-radius:3px}*::-webkit-scrollbar-thumb:hover{background:#555}.diff-view{background:#1a1a2e;border:1px solid #2a2a3e;border-radius:8px;padding:8px 12px}.diff-line-del{background:#ef444426;color:#fca5a5;padding:0 4px}.diff-line-add{background:#22c55e26;color:#86efac;padding:0 4px}.code-highlight{color:#e6edf3}.hl-keyword{color:#ff7b72}.hl-string{color:#a5d6ff}.hl-comment{color:#8b949e;font-style:italic}.hl-number{color:#79c0ff}.hl-linenum{color:#484f58;-webkit-user-select:none;user-select:none}.chat-md pre{background:#0d1117;border:1px solid #2a2a2a;border-radius:6px;padding:12px;overflow-x:auto;font-size:13px;line-height:1.5}.chat-md code{background:#1a1a2e;padding:2px 6px;border-radius:4px;font-size:13px;color:#e5e7eb}.chat-md pre code{background:none;padding:0}.chat-md p{margin:6px 0}.chat-md ul,.chat-md ol{padding-left:20px;margin:6px 0}.chat-md li{margin:2px 0}.chat-md h1,.chat-md h2,.chat-md h3{margin:12px 0 6px;color:#fff}.chat-md h1{font-size:1.3em}.chat-md h2{font-size:1.15em}.chat-md h3{font-size:1.05em}.chat-md blockquote{border-left:3px solid #3b82f6;margin:8px 0;padding:4px 12px;color:#9ca3af}.chat-md table{border-collapse:collapse;margin:8px 0;font-size:13px}.chat-md th,.chat-md td{border:1px solid #2a2a2a;padding:6px 10px}.chat-md th{background:#1a1a1a;color:#fff}.chat-md a{color:#60a5fa}.chat-md hr{border:none;border-top:1px solid #2a2a2a;margin:12px 0}.chat-md strong{color:#f1f5f9}.chat-md em{color:#cbd5e1}._headerBar_rxz5w_2{display:flex;align-items:center;justify-content:space-between;width:100%;height:100%}._titleText_rxz5w_11{color:#fff;font-size:18px;cursor:pointer}._titleArrow_rxz5w_17{font-size:12px;margin-left:4px}._tokenStatsTag_rxz5w_23{border-radius:12px;cursor:pointer;background:#2a2a2a;border:1px solid #3a3a3a;color:#ccc}._tokenStatsIcon_rxz5w_31{margin-right:4px}._liveTag_rxz5w_36{border-radius:12px}._liveTagText_rxz5w_40{margin-left:4px}._countdownStrong_rxz5w_45{font-variant-numeric:tabular-nums}._langSelector_rxz5w_50{color:#888;font-size:12px;cursor:pointer;-webkit-user-select:none;user-select:none;border:1px solid #555;border-radius:4px;padding:2px 8px}._tokenStatsEmpty_rxz5w_61{padding:8px 4px;color:#999;font-size:13px}._tokenStatsContainer_rxz5w_68{min-width:240px}._modelCard_rxz5w_73{border:1px solid #333;border-radius:6px;padding:8px 10px}._modelCardSpaced_rxz5w_79{margin-bottom:10px}._modelName_rxz5w_85{font-size:13px;font-weight:600;color:#e5e5e5;margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid #333}._statsTable_rxz5w_95{width:100%;border-collapse:collapse}._th_rxz5w_100{padding:2px 12px;font-size:12px;font-family:monospace;white-space:nowrap;color:#888;font-weight:400;text-align:right}._td_rxz5w_110{padding:2px 12px;font-size:12px;font-family:monospace;white-space:nowrap;color:#e5e5e5;text-align:right}._label_rxz5w_119{padding:2px 12px;font-size:12px;font-family:monospace;white-space:nowrap;color:#aaa;font-weight:400;text-align:left}._rowBorder_rxz5w_129{border-bottom:1px solid #2a2a2a}._promptExportBar_rxz5w_134{margin-bottom:12px}._promptScrollArea_rxz5w_138{max-height:500px;overflow:auto}._promptEmpty_rxz5w_143{color:#999;padding:12px}._promptTimestamp_rxz5w_149{text-align:center;color:#666;font-size:12px;margin:12px 0 8px;border-bottom:1px solid #303030;padding-bottom:6px}._textPromptCard_rxz5w_159{margin:4px 0;background:#141414;border-radius:6px;border:1px solid #303030;padding:10px 14px}._preText_rxz5w_168{white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6;color:#d9d9d9;margin:4px 0}._systemCollapse_rxz5w_178{margin:4px 0;background:#1a1a1a;border:1px solid #303030;border-radius:6px}._systemLabel_rxz5w_185{color:#888;font-size:12px}._preSys_rxz5w_190{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:#999;margin:0}._selectionCard_rxz5w_200{margin:4px 0;background:#141414;border-radius:6px;border:1px solid #303030}._selectionClaudeSection_rxz5w_207{padding:10px 14px;border-bottom:1px solid #252525}._selectionRoleLabel_rxz5w_212{font-size:12px;color:#888;margin-bottom:6px}._thinkingCollapse_rxz5w_219{margin-bottom:6px;background:#1a1a1a;border:1px solid #303030;border-radius:6px}._thinkingLabel_rxz5w_226{color:#888;font-size:12px}._preThinking_rxz5w_231{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:#999;margin:0}._preQuestion_rxz5w_241{white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6;color:#bbb;margin:0}._selectionUserSection_rxz5w_251{padding:10px 14px}._preAnswer_rxz5w_255{white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6;color:#d9d9d9;margin:0;font-weight:600}._centerEmpty_1eo6z_1{display:flex;align-items:center;justify-content:center;height:100%}._scrollContainer_1eo6z_8{overflow:auto;height:100%}._listItem_1eo6z_13{cursor:pointer;padding:8px 12px;border-left:3px solid transparent;border-bottom:1px solid #1f1f1f;transition:background .15s}._listItem_1eo6z_13:hover{background:#151515}._listItemActive_1eo6z_25{background:#1a2332;border-left-color:#3b82f6}._listItemActive_1eo6z_25:hover{background:#1a2332}._itemContent_1eo6z_34{width:100%;min-width:0}._itemHeader_1eo6z_39{display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:12px}._tagNoMargin_1eo6z_47{margin:0;font-size:12px}._modelName_1eo6z_52{font-size:12px}._time_1eo6z_56{font-size:12px;color:#6b7280;margin-left:auto}._detailRow_1eo6z_62{display:flex;gap:8px;font-size:12px;align-items:center}._urlText_1eo6z_69{color:#555;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}._duration_1eo6z_78{color:#6b7280;flex-shrink:0}._statusOk_1eo6z_83{color:#10b981;flex-shrink:0}._statusErr_1eo6z_88{color:#ef4444;flex-shrink:0}._statusDefault_1eo6z_93{color:#9ca3af;flex-shrink:0}._usageBox_1eo6z_98{background:#111;border-radius:4px;padding:3px 6px;margin-top:4px;font-size:12px;color:#6b7280;line-height:1.6}._GzYRV{line-height:1.2;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}._3eOF8{margin-right:5px;font-weight:700}._3eOF8+._3eOF8{margin-left:-5px}._1MFti{cursor:pointer}._f10Tu{font-size:1.2em;margin-right:5px;-webkit-user-select:none;-moz-user-select:none;user-select:none}._1UmXx:after{content:"▸"}._1LId0:after{content:"▾"}._1pNG9{margin-right:5px}._1pNG9:after{content:"...";font-size:.8em}._2IvMF{background:#eee}._2bkNM{margin:0;padding:0 10px}._1BXBN{margin:0;padding:0}._1MGIk{font-weight:600;margin-right:5px;color:#000}._3uHL6{color:#000}._2T6PJ,._1Gho6{color:#df113a}._vGjyY{color:#2a3f3c}._1bQdo{color:#0b75f5}._3zQKs{color:#469038}._1xvuR{color:#43413d}._oLqym,._2AXVT,._2KJWg{color:#000}._11RoI{background:#002b36}._17H2C,._3QHg2,._3fDAz{color:#fdf6e3}._2bSDX{font-weight:bolder;margin-right:5px;color:#fdf6e3}._gsbQL{color:#fdf6e3}._LaAZe,._GTKgm{color:#81b5ac}._Chy1W{color:#cb4b16}._2bveF{color:#d33682}._2vRm-{color:#ae81ff}._1prJR{color:#268bd2}._container_1h2lr_1{background:#0d1117;border-radius:6px;border:1px solid #2a2a2a;padding:12px;font-size:13px;font-family:monospace;overflow:auto}._container_1d2jv_1{height:100%;overflow:auto;padding:0 16px}._emptyState_1d2jv_7{display:flex;align-items:center;justify-content:center;height:100%}._urlSection_1d2jv_14{padding:12px 0;border-bottom:1px solid #1f1f1f}._urlText_1d2jv_19{color:#d1d5db;font-size:13px;margin-bottom:8px;word-break:break-all}._metaText_1d2jv_26,._headersContainer_1d2jv_30{font-size:12px}._headerRow_1d2jv_34{display:flex;padding:4px 0;border-bottom:1px solid #1f1f1f}._headerKey_1d2jv_40{min-width:200px;flex-shrink:0}._headerValue_1d2jv_45{word-break:break-all;margin-left:8px}._streamingBox_1d2jv_50{padding:20px;background:#1a1a1a;border-radius:6px;border:1px solid #2a2a2a}._bodyToolbar_1d2jv_57{display:flex;gap:8px;margin-bottom:8px}._rawTextPre_1d2jv_63{background:#0d1117;border:1px solid #2a2a2a;border-radius:6px;padding:12px;font-size:12px;color:#e5e7eb;overflow:auto;max-height:600px;white-space:pre-wrap;word-break:break-all}._tabContent_1d2jv_76{padding:12px 0}._collapseSpacing_1d2jv_80{margin-bottom:16px}._bodyLabel_1d2jv_84{margin:0}._bodyHeader_1d2jv_88{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}._diffSection_1d2jv_95{margin-bottom:16px}._diffToggle_1d2jv_99{display:inline-block;margin-bottom:8px;cursor:pointer}._diffIcon_1d2jv_105{font-size:12px;margin-left:4px}._wrapper_1o255_1{margin:6px 0}._header_1o255_5{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}._filePath_1o255_12{color:#a78bfa;font-size:12px;font-weight:600}._toggle_1o255_18{color:#6b7280;font-size:11px;cursor:pointer;-webkit-user-select:none;user-select:none}._code_1o255_25{margin:0;font-size:12px;line-height:1.5;overflow:auto}._plainResult_19g53_1{background:#111;border-radius:6px;padding:8px 12px;font-size:12px}._plainTitle_19g53_8{font-size:11px;display:block;margin-bottom:4px}._plainPre_19g53_14{color:#d1d5db;margin:0;white-space:pre-wrap;word-break:break-all;font-size:12px}._codeResult_19g53_22{background:#0d1117;border-radius:6px;border:1px solid #1e2a3a;overflow:hidden}._codeHeader_19g53_29{display:flex;justify-content:space-between;align-items:center;padding:4px 10px;background:#161b22;border-bottom:1px solid #1e2a3a}._codeTitle_19g53_38{font-size:11px;color:#8b949e}._codeToggle_19g53_43{font-size:11px;color:#484f58;cursor:pointer;-webkit-user-select:none;user-select:none}._codePre_19g53_50{margin:0;padding:8px 12px;font-size:12px;line-height:1.5;overflow:auto;max-height:500px}._avatar_1uglv_3{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}._avatarImg_1uglv_13{width:32px;height:32px;border-radius:50%;flex-shrink:0;object-fit:cover}._bubble_1uglv_21{border-radius:8px;padding:10px 14px;max-width:100%;font-size:14px;line-height:1.6;word-break:break-word}._messageRow_1uglv_32{display:flex;gap:10px;padding:8px 0}._messageRowEnd_1uglv_38{display:flex;gap:10px;padding:8px 0;justify-content:flex-end}._contentCol_1uglv_47{min-width:0;flex:1}._contentColLimited_1uglv_52{min-width:0;max-width:80%;width:fit-content}._labelRow_1uglv_60{display:flex;justify-content:space-between;align-items:center;margin-bottom:2px}._labelText_1uglv_67{font-size:11px}._timeText_1uglv_71{font-size:10px;color:#6b7280;flex-shrink:0;margin-left:8px}._timeTextNoMargin_1uglv_78{font-size:10px;color:#6b7280;flex-shrink:0}._labelTextRight_1uglv_84{font-size:11px;margin-left:auto}._bubbleUser_1uglv_91{background:#1668dc;color:#e5e7eb}._bubbleAssistant_1uglv_97{background:#141414;color:#e5e7eb}._bubblePlan_1uglv_103{background:#141414;border:1px solid #1668dc;color:#e5e7eb}._bubbleSubAgent_1uglv_110{background:#1a1a2e;color:#e5e7eb}._bubbleSelection_1uglv_116{background:#1a3a1a;color:#e5e7eb}._systemTagLabel_1uglv_124{font-size:12px}._systemTagPre_1uglv_128{font-size:12px;color:#9ca3af;white-space:pre-wrap;word-break:break-all;margin:0}._collapseMargin_1uglv_136{margin:4px 0}._collapseNoMargin_1uglv_140{margin:0}._thinkingLabel_1uglv_146{font-size:12px}._toolBox_1uglv_152{background:#1a1a2e;border:1px solid #2a2a3e;border-radius:8px;padding:8px 12px;margin:6px 0;font-size:12px}._toolLabel_1uglv_161{color:#a78bfa}._codePre_1uglv_167{font-size:12px;margin:4px 0 0;white-space:pre-wrap;word-break:break-all;background:#0d1117;border-radius:4px;padding:6px 8px}._pathTag_1uglv_179{color:#7dd3fc;font-size:11px}._descSpan_1uglv_186{color:#6b7280;font-weight:400}._secondarySpan_1uglv_191{color:#6b7280}._patternSpan_1uglv_195{color:#fbbf24}._kvContainer_1uglv_201{margin-top:4px;font-size:11px}._kvItem_1uglv_206{margin:2px 0}._kvKey_1uglv_210{color:#7dd3fc}._kvValue_1uglv_214{color:#9ca3af}._toolResult_1uglv_220{background:#111827;border:1px solid #1e293b;border-radius:6px;padding:6px 10px;margin:2px 0 6px;font-size:11px}._toolResultLabel_1uglv_229{font-size:11px}._compactLabel_1uglv_235{font-size:12px;color:#93c5fd}._compactPre_1uglv_240{font-size:12px;color:#d1d5db;white-space:pre-wrap;word-break:break-all;margin:0}._optionList_1uglv_250{padding-left:8px}._optionDesc_1uglv_254{color:#555;margin-left:6px;font-weight:400}._questionText_1uglv_262{font-size:13px;color:#ccc;margin-bottom:4px}._questionSpacing_1uglv_268{margin-bottom:10px}._option_1uglv_250{font-size:12px;padding:1px 0}._centerEmpty_1j3v3_1{display:flex;align-items:center;justify-content:center;height:100%}._container_1j3v3_8{height:100%;overflow:auto;padding:16px 24px;display:flex;flex-direction:column}._sessionDividerText_1j3v3_16{font-size:11px;color:#555}._lastResponseLabel_1j3v3_21{font-size:11px}._resizer_yamj2_1{width:6px;cursor:col-resize;background:#1f1f1f;flex-shrink:0;transition:background .2s}._resizer_yamj2_1:hover{background:#3b82f6}._layout_11p5u_1{height:100vh;overflow:hidden}._header_11p5u_6{background:#111;border-bottom:1px solid #1f1f1f;padding:0 24px;height:60px;line-height:60px}._content_11p5u_14{flex:1;overflow:hidden}._mainContainer_11p5u_19{display:flex;height:100%}._leftPanel_11p5u_24{flex-shrink:0;border-right:1px solid #1f1f1f;display:flex;flex-direction:column;background:#0a0a0a}._leftPanelHeader_11p5u_32{padding:10px 16px;border-bottom:1px solid #1f1f1f;font-size:13px;color:#9ca3af;font-weight:500;display:flex;justify-content:space-between;align-items:center}._leftPanelCount_11p5u_43{font-size:12px;color:#555;font-weight:400}._leftPanelBody_11p5u_49{flex:1;overflow:hidden}._rightPanel_11p5u_54{flex:1;overflow:hidden;background:#0d0d0d}._modalActions_11p5u_60{margin-bottom:12px}._spinCenter_11p5u_64{text-align:center;padding:40px}._emptyCenter_11p5u_69{text-align:center;color:#999;padding:40px}._logListItem_11p5u_75{cursor:pointer;padding:8px 12px}._logItemRow_11p5u_80{display:flex;align-items:center;width:100%;justify-content:space-between}._logFileIcon_11p5u_87{margin-right:8px;color:#3b82f6}._folderIcon_11p5u_92{margin-right:8px}._logTag_11p5u_96{margin-left:8px}
|
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-Bf2poirE.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C_eOlam6.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/interceptor.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// LLM Request Interceptor
|
|
2
2
|
// 拦截并记录所有Claude API请求
|
|
3
|
-
import { appendFileSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { appendFileSync, mkdirSync, readdirSync, readFileSync, 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';
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = dirname(__filename);
|
|
10
11
|
|
|
11
|
-
//
|
|
12
|
-
function
|
|
12
|
+
// 生成新的日志文件路径
|
|
13
|
+
function generateNewLogFilePath() {
|
|
13
14
|
const now = new Date();
|
|
14
15
|
const ts = now.getFullYear().toString()
|
|
15
16
|
+ String(now.getMonth() + 1).padStart(2, '0')
|
|
@@ -23,10 +24,134 @@ function generateLogFilePath() {
|
|
|
23
24
|
const projectName = basename(cwd).replace(/[^a-zA-Z0-9_\-\.]/g, '_');
|
|
24
25
|
const dir = join(homedir(), '.claude', 'cc-viewer');
|
|
25
26
|
try { mkdirSync(dir, { recursive: true }); } catch {}
|
|
26
|
-
return join(dir, `${projectName}_${ts}.jsonl`);
|
|
27
|
+
return { filePath: join(dir, `${projectName}_${ts}.jsonl`), dir, projectName };
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
// 查找同项目最近的日志文件,检查最后一条响应是否在1小时内
|
|
31
|
+
function findRecentLog(dir, projectName) {
|
|
32
|
+
try {
|
|
33
|
+
const files = readdirSync(dir)
|
|
34
|
+
.filter(f => f.startsWith(projectName + '_') && f.endsWith('.jsonl'))
|
|
35
|
+
.sort()
|
|
36
|
+
.reverse();
|
|
37
|
+
if (files.length === 0) return null;
|
|
38
|
+
const latestFile = join(dir, files[0]);
|
|
39
|
+
const content = readFileSync(latestFile, 'utf-8');
|
|
40
|
+
const entries = content.split('\n---\n').filter(s => s.trim());
|
|
41
|
+
// 从后往前找最后一条有 response 的记录
|
|
42
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
43
|
+
try {
|
|
44
|
+
const entry = JSON.parse(entries[i]);
|
|
45
|
+
if (entry.response) {
|
|
46
|
+
const ts = new Date(entry.timestamp).getTime();
|
|
47
|
+
if (Date.now() - ts < 3600000) {
|
|
48
|
+
return latestFile;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
} catch {}
|
|
53
|
+
}
|
|
54
|
+
} catch {}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 清理残留的临时文件(rename 为正式文件名,保留数据)
|
|
59
|
+
function cleanupTempFiles(dir, projectName) {
|
|
60
|
+
try {
|
|
61
|
+
const tempFiles = readdirSync(dir)
|
|
62
|
+
.filter(f => f.startsWith(projectName + '_') && f.endsWith('_temp.jsonl'));
|
|
63
|
+
for (const f of tempFiles) {
|
|
64
|
+
try {
|
|
65
|
+
const tempPath = join(dir, f);
|
|
66
|
+
const newPath = tempPath.replace('_temp.jsonl', '.jsonl');
|
|
67
|
+
if (existsSync(newPath)) {
|
|
68
|
+
// 正式文件已存在,追加临时文件内容后删除
|
|
69
|
+
const tempContent = readFileSync(tempPath, 'utf-8');
|
|
70
|
+
if (tempContent.trim()) {
|
|
71
|
+
appendFileSync(newPath, tempContent);
|
|
72
|
+
}
|
|
73
|
+
unlinkSync(tempPath);
|
|
74
|
+
} else {
|
|
75
|
+
renameSync(tempPath, newPath);
|
|
76
|
+
}
|
|
77
|
+
} catch {}
|
|
78
|
+
}
|
|
79
|
+
} catch {}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Resume 状态(供 server.js 使用)
|
|
83
|
+
let _resumeState = null;
|
|
84
|
+
let _resolveChoice = null;
|
|
85
|
+
const _choicePromise = new Promise(resolve => { _resolveChoice = resolve; });
|
|
86
|
+
|
|
87
|
+
function resolveResumeChoice(choice) {
|
|
88
|
+
if (!_resumeState) return;
|
|
89
|
+
const { recentFile, tempFile } = _resumeState;
|
|
90
|
+
try {
|
|
91
|
+
if (choice === 'continue') {
|
|
92
|
+
// 将临时文件内容追加到旧日志
|
|
93
|
+
if (existsSync(tempFile)) {
|
|
94
|
+
const tempContent = readFileSync(tempFile, 'utf-8');
|
|
95
|
+
if (tempContent.trim()) {
|
|
96
|
+
appendFileSync(recentFile, tempContent);
|
|
97
|
+
}
|
|
98
|
+
unlinkSync(tempFile);
|
|
99
|
+
}
|
|
100
|
+
LOG_FILE = recentFile;
|
|
101
|
+
} else {
|
|
102
|
+
// new: 将临时文件 rename 为正式新日志文件名
|
|
103
|
+
const newPath = tempFile.replace('_temp.jsonl', '.jsonl');
|
|
104
|
+
if (existsSync(tempFile)) {
|
|
105
|
+
renameSync(tempFile, newPath);
|
|
106
|
+
}
|
|
107
|
+
LOG_FILE = newPath;
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.error('[CC Viewer] resolveResumeChoice error:', err);
|
|
111
|
+
}
|
|
112
|
+
const result = { logFile: LOG_FILE };
|
|
113
|
+
_resumeState = null;
|
|
114
|
+
_resolveChoice(result);
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 初始化日志文件路径(异步,支持用户交互)
|
|
119
|
+
const { filePath: _newLogFile, dir: _logDir, projectName: _projectName } = generateNewLogFilePath();
|
|
120
|
+
let LOG_FILE = _newLogFile;
|
|
121
|
+
|
|
122
|
+
// 启动时清理残留临时文件
|
|
123
|
+
cleanupTempFiles(_logDir, _projectName);
|
|
124
|
+
|
|
125
|
+
const _initPromise = (async () => {
|
|
126
|
+
try {
|
|
127
|
+
const recentLog = findRecentLog(_logDir, _projectName);
|
|
128
|
+
if (recentLog) {
|
|
129
|
+
// 设置临时文件,不阻塞
|
|
130
|
+
const tempFile = _newLogFile.replace('.jsonl', '_temp.jsonl');
|
|
131
|
+
LOG_FILE = tempFile;
|
|
132
|
+
_resumeState = {
|
|
133
|
+
recentFile: recentLog,
|
|
134
|
+
recentFileName: basename(recentLog),
|
|
135
|
+
tempFile,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
} catch {}
|
|
139
|
+
})();
|
|
140
|
+
|
|
141
|
+
export { LOG_FILE, _initPromise, _resumeState, _choicePromise, resolveResumeChoice };
|
|
142
|
+
|
|
143
|
+
const MAX_LOG_SIZE = 200 * 1024 * 1024; // 200MB
|
|
144
|
+
|
|
145
|
+
function checkAndRotateLogFile() {
|
|
146
|
+
try {
|
|
147
|
+
if (!existsSync(LOG_FILE)) return;
|
|
148
|
+
const size = statSync(LOG_FILE).size;
|
|
149
|
+
if (size >= MAX_LOG_SIZE) {
|
|
150
|
+
const { filePath } = generateNewLogFilePath();
|
|
151
|
+
LOG_FILE = filePath;
|
|
152
|
+
}
|
|
153
|
+
} catch {}
|
|
154
|
+
}
|
|
30
155
|
|
|
31
156
|
// 从环境变量 ANTHROPIC_BASE_URL 提取域名用于请求匹配
|
|
32
157
|
function getBaseUrlHost() {
|
|
@@ -219,12 +344,26 @@ export function setupInterceptor() {
|
|
|
219
344
|
duration: 0,
|
|
220
345
|
isStream: body?.stream === true,
|
|
221
346
|
isHeartbeat: /\/api\/eval\/sdk-/.test(urlStr),
|
|
222
|
-
mainAgent:
|
|
223
|
-
|
|
347
|
+
mainAgent: (() => {
|
|
348
|
+
if (!body?.system || !Array.isArray(body?.tools) || body.tools.length <= 10) return false;
|
|
349
|
+
if (!['Task', 'Edit', 'Bash'].every(n => body.tools.some(t => t.name === n))) return false;
|
|
350
|
+
const sysText = typeof body.system === 'string' ? body.system :
|
|
351
|
+
Array.isArray(body.system) ? body.system.map(s => s?.text || '').join('') : '';
|
|
352
|
+
// 正向:必须包含 MainAgent 身份标识
|
|
353
|
+
if (!sysText.includes('You are Claude Code')) return false;
|
|
354
|
+
// 排除 SubAgent(general-purpose 等也携带完整工具集)
|
|
355
|
+
if (/command execution specialist|file search specialist|planning specialist|general-purpose agent/i.test(sysText)) return false;
|
|
356
|
+
return true;
|
|
357
|
+
})()
|
|
224
358
|
};
|
|
225
359
|
}
|
|
226
360
|
} catch {}
|
|
227
361
|
|
|
362
|
+
// 用户新指令边界:检查日志文件大小,超过 200MB 则切换新文件
|
|
363
|
+
if (requestEntry?.mainAgent) {
|
|
364
|
+
checkAndRotateLogFile();
|
|
365
|
+
}
|
|
366
|
+
|
|
228
367
|
const response = await _originalFetch.apply(this, arguments);
|
|
229
368
|
|
|
230
369
|
if (requestEntry) {
|
|
@@ -345,5 +484,5 @@ export function setupInterceptor() {
|
|
|
345
484
|
// 自动执行拦截器设置
|
|
346
485
|
setupInterceptor();
|
|
347
486
|
|
|
348
|
-
//
|
|
349
|
-
import('cc-viewer/server.js').catch(() => {});
|
|
487
|
+
// 等待日志文件初始化完成后启动 Web Viewer 服务
|
|
488
|
+
_initPromise.then(() => import('cc-viewer/server.js')).catch(() => {});
|
package/locales/ar.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ طي",
|
|
59
59
|
"ui.noChat": "لا توجد بيانات محادثة MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "الفرق مع الطلب السابق",
|
|
61
|
-
"ui.diffSessionChanged": "حجم نص الطلب انخفض، ربما بسبب /clear أو /compact أو تغيير الجلسة"
|
|
61
|
+
"ui.diffSessionChanged": "حجم نص الطلب انخفض، ربما بسبب /clear أو /compact أو تغيير الجلسة",
|
|
62
|
+
"cli.resume.prompt": "تم العثور على سجل حديث (خلال ساعة واحدة): {file}",
|
|
63
|
+
"cli.resume.continue": "متابعة",
|
|
64
|
+
"cli.resume.new": "جديد",
|
|
65
|
+
"ui.resume.title": "تم اكتشاف سجل حديث",
|
|
66
|
+
"ui.resume.message": "تم العثور على سجل حديث (خلال ساعة واحدة): {file}. هل تريد المتابعة؟",
|
|
67
|
+
"ui.resume.continue": "متابعة",
|
|
68
|
+
"ui.resume.new": "سجل جديد",
|
|
69
|
+
"ui.diffTooltip": "لتجنب قراءة النص الكامل الطويل، يتم عرض الأجزاء التزايدية فقط من MainAgent — عادةً فقط الرسائل الجديدة",
|
|
70
|
+
"ui.copy": "نسخ"
|
|
62
71
|
}
|
package/locales/da.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Fold sammen",
|
|
59
59
|
"ui.noChat": "Ingen MainAgent samtaledata",
|
|
60
60
|
"ui.diffWithPrev": "Diff med forrige anmodning",
|
|
61
|
-
"ui.diffSessionChanged": "Anmodningens størrelse er reduceret, muligvis på grund af /clear, /compact eller sessionsændring"
|
|
61
|
+
"ui.diffSessionChanged": "Anmodningens størrelse er reduceret, muligvis på grund af /clear, /compact eller sessionsændring",
|
|
62
|
+
"cli.resume.prompt": "Nylig log fundet (inden for 1 time): {file}",
|
|
63
|
+
"cli.resume.continue": "Fortsæt",
|
|
64
|
+
"cli.resume.new": "Ny",
|
|
65
|
+
"ui.resume.title": "Nylig log fundet",
|
|
66
|
+
"ui.resume.message": "Nylig log fundet (inden for 1 time): {file}. Fortsæt?",
|
|
67
|
+
"ui.resume.continue": "Fortsæt",
|
|
68
|
+
"ui.resume.new": "Ny log",
|
|
69
|
+
"ui.diffTooltip": "For at undgå at læse lange fuldtekster vises kun de inkrementelle dele af MainAgent — typisk kun nye beskeder",
|
|
70
|
+
"ui.copy": "Kopiér"
|
|
62
71
|
}
|
package/locales/de.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Zuklappen",
|
|
59
59
|
"ui.noChat": "Keine MainAgent-Gesprächsdaten",
|
|
60
60
|
"ui.diffWithPrev": "Diff zur vorherigen Anfrage",
|
|
61
|
-
"ui.diffSessionChanged": "Anfragekörper wurde kleiner, möglicherweise durch /clear, /compact oder Sitzungswechsel"
|
|
61
|
+
"ui.diffSessionChanged": "Anfragekörper wurde kleiner, möglicherweise durch /clear, /compact oder Sitzungswechsel",
|
|
62
|
+
"cli.resume.prompt": "Kürzliches Log gefunden (innerhalb 1 Stunde): {file}",
|
|
63
|
+
"cli.resume.continue": "Fortsetzen",
|
|
64
|
+
"cli.resume.new": "Neu",
|
|
65
|
+
"ui.resume.title": "Kürzliches Log erkannt",
|
|
66
|
+
"ui.resume.message": "Kürzliches Log gefunden (innerhalb 1 Stunde): {file}. Fortsetzen?",
|
|
67
|
+
"ui.resume.continue": "Fortsetzen",
|
|
68
|
+
"ui.resume.new": "Neues Log",
|
|
69
|
+
"ui.diffTooltip": "Um das Lesen langer Volltexte zu vermeiden, werden nur die inkrementellen Teile des MainAgent angezeigt — in der Regel nur neue Nachrichten",
|
|
70
|
+
"ui.copy": "Kopieren"
|
|
62
71
|
}
|
package/locales/en.json
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"ui.toolReturnNamed": "{name} result",
|
|
51
51
|
"ui.lastResponse": "Last Response",
|
|
52
52
|
"ui.copySuccess": "Copied",
|
|
53
|
+
"ui.copy": "Copy",
|
|
53
54
|
"ui.noHeaders": "No Headers",
|
|
54
55
|
"ui.noBody": "No Body",
|
|
55
56
|
"ui.streamingResponse": "⚡ Streaming response — This request used SSE streaming, response content cannot be fully captured.",
|
|
@@ -58,5 +59,15 @@
|
|
|
58
59
|
"ui.collapse": "▼ Collapse",
|
|
59
60
|
"ui.noChat": "No MainAgent conversation data",
|
|
60
61
|
"ui.diffWithPrev": "Diff with previous request",
|
|
61
|
-
"ui.diffSessionChanged": "Request body size decreased, possibly due to /clear, /compact, or session change"
|
|
62
|
+
"ui.diffSessionChanged": "Request body size decreased, possibly due to /clear, /compact, or session change",
|
|
63
|
+
"ui.diffTooltip": "To avoid reading lengthy full text, only the incremental parts of MainAgent are shown — typically just new messages",
|
|
64
|
+
|
|
65
|
+
"cli.resume.prompt": "Recent log found (within 1 hour): {file}",
|
|
66
|
+
"cli.resume.continue": "Continue",
|
|
67
|
+
"cli.resume.new": "New",
|
|
68
|
+
|
|
69
|
+
"ui.resume.title": "Recent Log Detected",
|
|
70
|
+
"ui.resume.message": "Recent log found (within 1 hour): {file}. Continue?",
|
|
71
|
+
"ui.resume.continue": "Continue",
|
|
72
|
+
"ui.resume.new": "Start New"
|
|
62
73
|
}
|
package/locales/es.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Contraer",
|
|
59
59
|
"ui.noChat": "Sin datos de conversación de MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Diferencia con la solicitud anterior",
|
|
61
|
-
"ui.diffSessionChanged": "El tamaño del cuerpo de la solicitud disminuyó, posiblemente debido a /clear, /compact o cambio de sesión"
|
|
61
|
+
"ui.diffSessionChanged": "El tamaño del cuerpo de la solicitud disminuyó, posiblemente debido a /clear, /compact o cambio de sesión",
|
|
62
|
+
"cli.resume.prompt": "Log reciente encontrado (dentro de 1 hora): {file}",
|
|
63
|
+
"cli.resume.continue": "Continuar",
|
|
64
|
+
"cli.resume.new": "Nuevo",
|
|
65
|
+
"ui.resume.title": "Log reciente detectado",
|
|
66
|
+
"ui.resume.message": "Log reciente encontrado (dentro de 1 hora): {file}. ¿Continuar?",
|
|
67
|
+
"ui.resume.continue": "Continuar",
|
|
68
|
+
"ui.resume.new": "Nuevo log",
|
|
69
|
+
"ui.diffTooltip": "Para evitar leer textos completos extensos, solo se muestran las partes incrementales del MainAgent — normalmente solo mensajes nuevos",
|
|
70
|
+
"ui.copy": "Copiar"
|
|
62
71
|
}
|
package/locales/fr.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Replier",
|
|
59
59
|
"ui.noChat": "Aucune donnée de conversation MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Diff avec la requête précédente",
|
|
61
|
-
"ui.diffSessionChanged": "La taille du corps de la requête a diminué, possiblement dû à /clear, /compact ou un changement de session"
|
|
61
|
+
"ui.diffSessionChanged": "La taille du corps de la requête a diminué, possiblement dû à /clear, /compact ou un changement de session",
|
|
62
|
+
"cli.resume.prompt": "Log récent trouvé (moins d'1 heure): {file}",
|
|
63
|
+
"cli.resume.continue": "Continuer",
|
|
64
|
+
"cli.resume.new": "Nouveau",
|
|
65
|
+
"ui.resume.title": "Log récent détecté",
|
|
66
|
+
"ui.resume.message": "Log récent trouvé (moins d'1 heure): {file}. Continuer ?",
|
|
67
|
+
"ui.resume.continue": "Continuer",
|
|
68
|
+
"ui.resume.new": "Nouveau log",
|
|
69
|
+
"ui.diffTooltip": "Pour éviter de lire de longs textes complets, seules les parties incrémentales du MainAgent sont affichées — généralement uniquement les nouveaux messages",
|
|
70
|
+
"ui.copy": "Copier"
|
|
62
71
|
}
|
package/locales/it.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Comprimi",
|
|
59
59
|
"ui.noChat": "Nessun dato di conversazione MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Diff con la richiesta precedente",
|
|
61
|
-
"ui.diffSessionChanged": "La dimensione del corpo della richiesta è diminuita, probabilmente a causa di /clear, /compact o cambio di sessione"
|
|
61
|
+
"ui.diffSessionChanged": "La dimensione del corpo della richiesta è diminuita, probabilmente a causa di /clear, /compact o cambio di sessione",
|
|
62
|
+
"cli.resume.prompt": "Log recente trovato (entro 1 ora): {file}",
|
|
63
|
+
"cli.resume.continue": "Continua",
|
|
64
|
+
"cli.resume.new": "Nuovo",
|
|
65
|
+
"ui.resume.title": "Log recente rilevato",
|
|
66
|
+
"ui.resume.message": "Log recente trovato (entro 1 ora): {file}. Continuare?",
|
|
67
|
+
"ui.resume.continue": "Continua",
|
|
68
|
+
"ui.resume.new": "Nuovo log",
|
|
69
|
+
"ui.diffTooltip": "Per evitare di leggere lunghi testi completi, vengono mostrate solo le parti incrementali del MainAgent — di solito solo nuovi messaggi",
|
|
70
|
+
"ui.copy": "Copia"
|
|
62
71
|
}
|
package/locales/ja.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ 折りたたむ",
|
|
59
59
|
"ui.noChat": "MainAgent の会話データがありません",
|
|
60
60
|
"ui.diffWithPrev": "前回リクエストとの差分",
|
|
61
|
-
"ui.diffSessionChanged": "リクエストボディのサイズが減少しました。/clear、/compact、またはセッション変更の可能性があります"
|
|
61
|
+
"ui.diffSessionChanged": "リクエストボディのサイズが減少しました。/clear、/compact、またはセッション変更の可能性があります",
|
|
62
|
+
"cli.resume.prompt": "1時間以内のログを検出: {file}",
|
|
63
|
+
"cli.resume.continue": "続行",
|
|
64
|
+
"cli.resume.new": "新規",
|
|
65
|
+
"ui.resume.title": "最近のログを検出",
|
|
66
|
+
"ui.resume.message": "1時間以内のログを検出: {file}。続行しますか?",
|
|
67
|
+
"ui.resume.continue": "前回の続き",
|
|
68
|
+
"ui.resume.new": "新規ログ",
|
|
69
|
+
"ui.diffTooltip": "MainAgent の増分部分のみを簡略表示しています。長い全文を読む手間を省くため、通常は message の追加のみです",
|
|
70
|
+
"ui.copy": "コピー"
|
|
62
71
|
}
|
package/locales/ko.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ 접기",
|
|
59
59
|
"ui.noChat": "MainAgent 대화 데이터 없음",
|
|
60
60
|
"ui.diffWithPrev": "이전 요청과의 차이",
|
|
61
|
-
"ui.diffSessionChanged": "요청 본문 크기가 줄었습니다. /clear, /compact 또는 세션 변경이 있었을 수 있습니다"
|
|
61
|
+
"ui.diffSessionChanged": "요청 본문 크기가 줄었습니다. /clear, /compact 또는 세션 변경이 있었을 수 있습니다",
|
|
62
|
+
"cli.resume.prompt": "1시간 이내 로그 감지: {file}",
|
|
63
|
+
"cli.resume.continue": "계속",
|
|
64
|
+
"cli.resume.new": "새로 시작",
|
|
65
|
+
"ui.resume.title": "최근 로그 감지됨",
|
|
66
|
+
"ui.resume.message": "1시간 이내 로그 감지: {file}. 계속하시겠습니까?",
|
|
67
|
+
"ui.resume.continue": "이어서 계속",
|
|
68
|
+
"ui.resume.new": "새 로그 시작",
|
|
69
|
+
"ui.diffTooltip": "긴 전체 텍스트를 읽지 않도록 MainAgent의 증분 부분만 간략히 표시합니다. 일반적으로 message 추가만 있습니다",
|
|
70
|
+
"ui.copy": "복사"
|
|
62
71
|
}
|
package/locales/no.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Skjul",
|
|
59
59
|
"ui.noChat": "Ingen MainAgent samtaledata",
|
|
60
60
|
"ui.diffWithPrev": "Diff med forrige forespørsel",
|
|
61
|
-
"ui.diffSessionChanged": "Forespørselens størrelse ble redusert, muligens på grunn av /clear, /compact eller sesjonsendring"
|
|
61
|
+
"ui.diffSessionChanged": "Forespørselens størrelse ble redusert, muligens på grunn av /clear, /compact eller sesjonsendring",
|
|
62
|
+
"cli.resume.prompt": "Nylig logg funnet (innen 1 time): {file}",
|
|
63
|
+
"cli.resume.continue": "Fortsett",
|
|
64
|
+
"cli.resume.new": "Ny",
|
|
65
|
+
"ui.resume.title": "Nylig logg oppdaget",
|
|
66
|
+
"ui.resume.message": "Nylig logg funnet (innen 1 time): {file}. Fortsette?",
|
|
67
|
+
"ui.resume.continue": "Fortsett",
|
|
68
|
+
"ui.resume.new": "Ny logg",
|
|
69
|
+
"ui.diffTooltip": "For å unngå å lese lange fulltekster vises kun de inkrementelle delene av MainAgent — vanligvis bare nye meldinger",
|
|
70
|
+
"ui.copy": "Kopier"
|
|
62
71
|
}
|
package/locales/pl.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Zwiń",
|
|
59
59
|
"ui.noChat": "Brak danych rozmowy MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Różnica z poprzednim żądaniem",
|
|
61
|
-
"ui.diffSessionChanged": "Rozmiar treści żądania zmniejszył się, prawdopodobnie z powodu /clear, /compact lub zmiany sesji"
|
|
61
|
+
"ui.diffSessionChanged": "Rozmiar treści żądania zmniejszył się, prawdopodobnie z powodu /clear, /compact lub zmiany sesji",
|
|
62
|
+
"cli.resume.prompt": "Znaleziono ostatni log (w ciągu 1 godziny): {file}",
|
|
63
|
+
"cli.resume.continue": "Kontynuuj",
|
|
64
|
+
"cli.resume.new": "Nowy",
|
|
65
|
+
"ui.resume.title": "Wykryto ostatni log",
|
|
66
|
+
"ui.resume.message": "Znaleziono ostatni log (w ciągu 1 godziny): {file}. Kontynuować?",
|
|
67
|
+
"ui.resume.continue": "Kontynuuj",
|
|
68
|
+
"ui.resume.new": "Nowy log",
|
|
69
|
+
"ui.diffTooltip": "Aby uniknąć czytania długich pełnych tekstów, wyświetlane są tylko przyrostowe części MainAgent — zwykle tylko nowe wiadomości",
|
|
70
|
+
"ui.copy": "Kopiuj"
|
|
62
71
|
}
|
package/locales/pt-BR.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Recolher",
|
|
59
59
|
"ui.noChat": "Sem dados de conversa do MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Diff com a requisição anterior",
|
|
61
|
-
"ui.diffSessionChanged": "O tamanho do corpo da requisição diminuiu, possivelmente devido a /clear, /compact ou mudança de sessão"
|
|
61
|
+
"ui.diffSessionChanged": "O tamanho do corpo da requisição diminuiu, possivelmente devido a /clear, /compact ou mudança de sessão",
|
|
62
|
+
"cli.resume.prompt": "Log recente encontrado (dentro de 1 hora): {file}",
|
|
63
|
+
"cli.resume.continue": "Continuar",
|
|
64
|
+
"cli.resume.new": "Novo",
|
|
65
|
+
"ui.resume.title": "Log recente detectado",
|
|
66
|
+
"ui.resume.message": "Log recente encontrado (dentro de 1 hora): {file}. Continuar?",
|
|
67
|
+
"ui.resume.continue": "Continuar",
|
|
68
|
+
"ui.resume.new": "Novo log",
|
|
69
|
+
"ui.diffTooltip": "Para evitar ler textos completos longos, apenas as partes incrementais do MainAgent são exibidas — geralmente apenas novas mensagens",
|
|
70
|
+
"ui.copy": "Copiar"
|
|
62
71
|
}
|
package/locales/ru.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Свернуть",
|
|
59
59
|
"ui.noChat": "Нет данных диалога MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Отличия от предыдущего запроса",
|
|
61
|
-
"ui.diffSessionChanged": "Размер тела запроса уменьшился, возможно из-за /clear, /compact или смены сессии"
|
|
61
|
+
"ui.diffSessionChanged": "Размер тела запроса уменьшился, возможно из-за /clear, /compact или смены сессии",
|
|
62
|
+
"cli.resume.prompt": "Обнаружен недавний лог (менее 1 часа): {file}",
|
|
63
|
+
"cli.resume.continue": "Продолжить",
|
|
64
|
+
"cli.resume.new": "Новый",
|
|
65
|
+
"ui.resume.title": "Обнаружен недавний лог",
|
|
66
|
+
"ui.resume.message": "Обнаружен недавний лог (менее 1 часа): {file}. Продолжить?",
|
|
67
|
+
"ui.resume.continue": "Продолжить",
|
|
68
|
+
"ui.resume.new": "Новый лог",
|
|
69
|
+
"ui.diffTooltip": "Чтобы не читать длинный полный текст, отображаются только инкрементальные части MainAgent — обычно только новые сообщения",
|
|
70
|
+
"ui.copy": "Копировать"
|
|
62
71
|
}
|
package/locales/th.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ ย่อ",
|
|
59
59
|
"ui.noChat": "ไม่มีข้อมูลการสนทนา MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "ความแตกต่างกับคำขอก่อนหน้า",
|
|
61
|
-
"ui.diffSessionChanged": "ขนาดเนื้อหาคำขอลดลง อาจเกิดจาก /clear, /compact หรือการเปลี่ยนเซสชัน"
|
|
61
|
+
"ui.diffSessionChanged": "ขนาดเนื้อหาคำขอลดลง อาจเกิดจาก /clear, /compact หรือการเปลี่ยนเซสชัน",
|
|
62
|
+
"cli.resume.prompt": "พบล็อกล่าสุด (ภายใน 1 ชั่วโมง): {file}",
|
|
63
|
+
"cli.resume.continue": "ดำเนินการต่อ",
|
|
64
|
+
"cli.resume.new": "ใหม่",
|
|
65
|
+
"ui.resume.title": "ตรวจพบล็อกล่าสุด",
|
|
66
|
+
"ui.resume.message": "พบล็อกล่าสุด (ภายใน 1 ชั่วโมง): {file} ต้องการดำเนินการต่อหรือไม่?",
|
|
67
|
+
"ui.resume.continue": "ดำเนินการต่อ",
|
|
68
|
+
"ui.resume.new": "ล็อกใหม่",
|
|
69
|
+
"ui.diffTooltip": "เพื่อหลีกเลี่ยงการอ่านข้อความเต็มที่ยาว จึงแสดงเฉพาะส่วนที่เพิ่มขึ้นของ MainAgent เท่านั้น — โดยปกติจะมีเพียง message ใหม่",
|
|
70
|
+
"ui.copy": "คัดลอก"
|
|
62
71
|
}
|
package/locales/tr.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Daralt",
|
|
59
59
|
"ui.noChat": "MainAgent konuşma verisi yok",
|
|
60
60
|
"ui.diffWithPrev": "Önceki istekle fark",
|
|
61
|
-
"ui.diffSessionChanged": "İstek gövdesi boyutu küçüldü, muhtemelen /clear, /compact veya oturum değişikliği nedeniyle"
|
|
61
|
+
"ui.diffSessionChanged": "İstek gövdesi boyutu küçüldü, muhtemelen /clear, /compact veya oturum değişikliği nedeniyle",
|
|
62
|
+
"cli.resume.prompt": "Son günlük bulundu (1 saat içinde): {file}",
|
|
63
|
+
"cli.resume.continue": "Devam",
|
|
64
|
+
"cli.resume.new": "Yeni",
|
|
65
|
+
"ui.resume.title": "Son günlük tespit edildi",
|
|
66
|
+
"ui.resume.message": "Son günlük bulundu (1 saat içinde): {file}. Devam edilsin mi?",
|
|
67
|
+
"ui.resume.continue": "Devam et",
|
|
68
|
+
"ui.resume.new": "Yeni günlük",
|
|
69
|
+
"ui.diffTooltip": "Uzun tam metinleri okumaktan kaçınmak için yalnızca MainAgent'ın artımlı kısımları gösterilir — genellikle yalnızca yeni mesajlar",
|
|
70
|
+
"ui.copy": "Kopyala"
|
|
62
71
|
}
|
package/locales/uk.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ Згорнути",
|
|
59
59
|
"ui.noChat": "Немає даних діалогу MainAgent",
|
|
60
60
|
"ui.diffWithPrev": "Відмінності від попереднього запиту",
|
|
61
|
-
"ui.diffSessionChanged": "Розмір тіла запиту зменшився, можливо через /clear, /compact або зміну сесії"
|
|
61
|
+
"ui.diffSessionChanged": "Розмір тіла запиту зменшився, можливо через /clear, /compact або зміну сесії",
|
|
62
|
+
"cli.resume.prompt": "Знайдено нещодавній лог (менше 1 години): {file}",
|
|
63
|
+
"cli.resume.continue": "Продовжити",
|
|
64
|
+
"cli.resume.new": "Новий",
|
|
65
|
+
"ui.resume.title": "Виявлено нещодавній лог",
|
|
66
|
+
"ui.resume.message": "Знайдено нещодавній лог (менше 1 години): {file}. Продовжити?",
|
|
67
|
+
"ui.resume.continue": "Продовжити",
|
|
68
|
+
"ui.resume.new": "Новий лог",
|
|
69
|
+
"ui.diffTooltip": "Щоб не читати довгий повний текст, відображаються лише інкрементальні частини MainAgent — зазвичай лише нові повідомлення",
|
|
70
|
+
"ui.copy": "Копіювати"
|
|
62
71
|
}
|
package/locales/zh-TW.json
CHANGED
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"ui.collapse": "▼ 收起",
|
|
59
59
|
"ui.noChat": "暫無 MainAgent 對話資料",
|
|
60
60
|
"ui.diffWithPrev": "與上次請求的差異",
|
|
61
|
-
"ui.diffSessionChanged": "請求體大小減小,可能使用了 /clear、/compact 或 session 發生了變化"
|
|
61
|
+
"ui.diffSessionChanged": "請求體大小減小,可能使用了 /clear、/compact 或 session 發生了變化",
|
|
62
|
+
"cli.resume.prompt": "偵測到1小時內的日誌: {file}",
|
|
63
|
+
"cli.resume.continue": "繼續",
|
|
64
|
+
"cli.resume.new": "新開",
|
|
65
|
+
"ui.resume.title": "偵測到近期日誌",
|
|
66
|
+
"ui.resume.message": "偵測到1小時內的日誌: {file},是否繼續?",
|
|
67
|
+
"ui.resume.continue": "繼續上次",
|
|
68
|
+
"ui.resume.new": "新開日誌",
|
|
69
|
+
"ui.diffTooltip": "為了避免閱讀冗長的全文,簡化展示了 MainAgent 的增量部分,通常只有 message 增加",
|
|
70
|
+
"ui.copy": "複製"
|
|
62
71
|
}
|
package/locales/zh.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"ui.lastResponse": "Last Response",
|
|
55
55
|
|
|
56
56
|
"ui.copySuccess": "复制成功",
|
|
57
|
+
"ui.copy": "复制",
|
|
57
58
|
"ui.noHeaders": "无 Headers",
|
|
58
59
|
"ui.noBody": "无 Body",
|
|
59
60
|
"ui.streamingResponse": "⚡ 流式响应 — 此请求使用了 SSE 流式传输,响应内容无法完整捕获。",
|
|
@@ -63,5 +64,15 @@
|
|
|
63
64
|
"ui.collapse": "▼ 收起",
|
|
64
65
|
"ui.noChat": "暂无 MainAgent 对话数据",
|
|
65
66
|
"ui.diffWithPrev": "与上次请求的差异",
|
|
66
|
-
"ui.diffSessionChanged": "请求体大小减小,可能使用了 /clear、/compact 或 session 发生了变化"
|
|
67
|
+
"ui.diffSessionChanged": "请求体大小减小,可能使用了 /clear、/compact 或 session 发生了变化",
|
|
68
|
+
"ui.diffTooltip": "为了避免看冗长的全文,所以为大家简化展示了 MainAgent 的增量部分,通常只有 message 增加",
|
|
69
|
+
|
|
70
|
+
"cli.resume.prompt": "检测到1小时内的日志: {file}",
|
|
71
|
+
"cli.resume.continue": "继续",
|
|
72
|
+
"cli.resume.new": "新开",
|
|
73
|
+
|
|
74
|
+
"ui.resume.title": "检测到近期日志",
|
|
75
|
+
"ui.resume.message": "检测到1小时内的日志: {file},是否继续?",
|
|
76
|
+
"ui.resume.continue": "继续上次",
|
|
77
|
+
"ui.resume.new": "新开日志"
|
|
67
78
|
}
|