cc-viewer 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +1 -1
- package/interceptor.js +7 -6
- package/lib/assets/index-BMPce72-.js +401 -0
- package/lib/assets/index-C7-c9XfU.css +1 -0
- package/lib/index.html +3 -3
- package/lib/server.js +34 -4
- package/package.json +1 -1
- package/lib/assets/index-B9Z7D9kT.css +0 -1
- package/lib/assets/index-Cz06a4Sw.js +0 -395
|
@@ -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}._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}
|
package/lib/index.html
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Claude Code Viewer</title>
|
|
7
|
-
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BMPce72-.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C7-c9XfU.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/lib/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createServer } from 'node:http';
|
|
2
|
-
import { readFileSync, existsSync, watchFile, unwatchFile, statSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { createServer, request as httpRequest } from 'node:http';
|
|
2
|
+
import { readFileSync, existsSync, watchFile, unwatchFile, statSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname, join, extname } from 'node:path';
|
|
5
5
|
import { LOG_FILE } from '../interceptor.js';
|
|
@@ -11,6 +11,18 @@ const MAX_PORT = 7099;
|
|
|
11
11
|
const HOST = '127.0.0.1';
|
|
12
12
|
const PORT_FILE = '/tmp/cc-viewer-port';
|
|
13
13
|
|
|
14
|
+
function checkPortAlive(port) {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const req = httpRequest({ host: HOST, port, path: '/api/requests', method: 'GET', timeout: 1000 }, (res) => {
|
|
17
|
+
res.resume();
|
|
18
|
+
resolve(true);
|
|
19
|
+
});
|
|
20
|
+
req.on('error', () => resolve(false));
|
|
21
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
22
|
+
req.end();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
let clients = [];
|
|
15
27
|
let server;
|
|
16
28
|
let actualPort = START_PORT;
|
|
@@ -164,7 +176,26 @@ function handleRequest(req, res) {
|
|
|
164
176
|
res.end('Not Found');
|
|
165
177
|
}
|
|
166
178
|
|
|
167
|
-
export function startViewer() {
|
|
179
|
+
export async function startViewer() {
|
|
180
|
+
// 检查是否已有 cc-viewer 实例在运行
|
|
181
|
+
if (existsSync(PORT_FILE)) {
|
|
182
|
+
try {
|
|
183
|
+
const existingPort = parseInt(readFileSync(PORT_FILE, 'utf-8').trim(), 10);
|
|
184
|
+
if (existingPort >= START_PORT && existingPort <= MAX_PORT) {
|
|
185
|
+
const alive = await checkPortAlive(existingPort);
|
|
186
|
+
if (alive) {
|
|
187
|
+
actualPort = existingPort;
|
|
188
|
+
console.log(`\n🔍 CC Viewer 已在运行: http://${HOST}:${existingPort}\n`);
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
} catch {
|
|
193
|
+
// PORT_FILE 读取失败,继续正常启动
|
|
194
|
+
}
|
|
195
|
+
// 旧实例已不存在,清理 PORT_FILE
|
|
196
|
+
try { unlinkSync(PORT_FILE); } catch {}
|
|
197
|
+
}
|
|
198
|
+
|
|
168
199
|
return new Promise((resolve, reject) => {
|
|
169
200
|
function tryListen(port) {
|
|
170
201
|
if (port > MAX_PORT) {
|
|
@@ -186,7 +217,6 @@ export function startViewer() {
|
|
|
186
217
|
|
|
187
218
|
currentServer.on('error', (err) => {
|
|
188
219
|
if (err.code === 'EADDRINUSE') {
|
|
189
|
-
console.log(`⚠️ 端口 ${port} 已被占用,尝试 ${port + 1}...`);
|
|
190
220
|
tryListen(port + 1);
|
|
191
221
|
} else {
|
|
192
222
|
reject(err);
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._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}
|