cc-viewer 1.4.21 → 1.4.23
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 +22 -7
- package/dist/assets/{index-DVJLme9U.js → index-Cy1FKik6.js} +54 -54
- package/dist/index.html +1 -1
- package/findcc.js +48 -0
- package/lib/plugin-loader.js +20 -1
- package/package.json +1 -1
- package/pty-manager.js +15 -5
- package/server.js +7 -1
package/dist/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>Claude Code Viewer</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico?v=1">
|
|
8
8
|
<link rel="shortcut icon" href="/favicon.ico?v=1">
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-Cy1FKik6.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/index-Daywpj0d.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
package/findcc.js
CHANGED
|
@@ -61,6 +61,54 @@ export function resolveCliPath() {
|
|
|
61
61
|
return join(globalRoot || resolve(__dirname, '..'), PACKAGES[0], CLI_ENTRY);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* 查找 npm 版本的 claude(包括 nvm 安装)
|
|
66
|
+
* 返回 node_modules 中的 claude cli.js 路径
|
|
67
|
+
*/
|
|
68
|
+
export function resolveNpmClaudePath() {
|
|
69
|
+
// 1. 尝试 which/command -v 找到 npm 安装的 claude
|
|
70
|
+
for (const cmd of [`which ${BINARY_NAME}`, `command -v ${BINARY_NAME}`]) {
|
|
71
|
+
try {
|
|
72
|
+
const result = execSync(cmd, { encoding: 'utf-8', shell: true, env: process.env }).trim();
|
|
73
|
+
// 排除 shell function 的输出(多行说明不是路径)
|
|
74
|
+
if (result && !result.includes('\n') && existsSync(result)) {
|
|
75
|
+
// 只接受 npm 安装的符号链接(解析后指向 node_modules)
|
|
76
|
+
try {
|
|
77
|
+
const real = realpathSync(result);
|
|
78
|
+
if (real.includes('node_modules')) {
|
|
79
|
+
// 找到 npm 版本,返回 cli.js 的路径
|
|
80
|
+
// real 可能是 .../node_modules/@anthropic-ai/claude-code/bin/claude
|
|
81
|
+
// 我们需要返回 .../node_modules/@anthropic-ai/claude-code/cli.js
|
|
82
|
+
const match = real.match(/(.*node_modules\/@[^/]+\/[^/]+)\//);
|
|
83
|
+
if (match) {
|
|
84
|
+
const packageDir = match[1];
|
|
85
|
+
const cliPath = join(packageDir, CLI_ENTRY);
|
|
86
|
+
if (existsSync(cliPath)) {
|
|
87
|
+
return cliPath;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} catch {}
|
|
92
|
+
}
|
|
93
|
+
} catch {
|
|
94
|
+
// ignore
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 2. 尝试从全局 node_modules 查找
|
|
99
|
+
const globalRoot = getGlobalNodeModulesDir();
|
|
100
|
+
if (globalRoot) {
|
|
101
|
+
for (const packageName of PACKAGES) {
|
|
102
|
+
const cliPath = join(globalRoot, packageName, CLI_ENTRY);
|
|
103
|
+
if (existsSync(cliPath)) {
|
|
104
|
+
return cliPath;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
64
112
|
export function resolveNativePath() {
|
|
65
113
|
// 1. 尝试 which/command -v(继承当前 process.env PATH)
|
|
66
114
|
for (const cmd of [`which ${BINARY_NAME}`, `command -v ${BINARY_NAME}`]) {
|
package/lib/plugin-loader.js
CHANGED
|
@@ -130,7 +130,26 @@ export function getPluginsInfo() {
|
|
|
130
130
|
|
|
131
131
|
return files.map(file => {
|
|
132
132
|
const loaded = _plugins.find(p => p.file === file);
|
|
133
|
-
|
|
133
|
+
let name = file;
|
|
134
|
+
|
|
135
|
+
// 如果插件已加载,使用加载时的 name
|
|
136
|
+
if (loaded) {
|
|
137
|
+
name = loaded.name;
|
|
138
|
+
} else {
|
|
139
|
+
// 如果插件未加载(可能被禁用),尝试读取文件获取真实的 name
|
|
140
|
+
try {
|
|
141
|
+
const filePath = join(PLUGINS_DIR, file);
|
|
142
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
143
|
+
// 简单匹配 name: 'xxx' 或 name: "xxx"
|
|
144
|
+
const match = content.match(/name\s*:\s*['"]([^'"]+)['"]/);
|
|
145
|
+
if (match) {
|
|
146
|
+
name = match[1];
|
|
147
|
+
}
|
|
148
|
+
} catch {
|
|
149
|
+
// 读取失败,使用文件名
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
134
153
|
const hooks = loaded ? Object.keys(loaded.hooks) : [];
|
|
135
154
|
const enabled = !disabledPlugins.includes(name);
|
|
136
155
|
return { name, file, hooks, enabled };
|
package/package.json
CHANGED
package/pty-manager.js
CHANGED
|
@@ -25,7 +25,7 @@ function fixSpawnHelperPermissions() {
|
|
|
25
25
|
} catch {}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export async function spawnClaude(proxyPort, cwd, extraArgs = []) {
|
|
28
|
+
export async function spawnClaude(proxyPort, cwd, extraArgs = [], claudePath = null, isNpmVersion = false) {
|
|
29
29
|
if (ptyProcess) {
|
|
30
30
|
killPty();
|
|
31
31
|
}
|
|
@@ -35,9 +35,12 @@ export async function spawnClaude(proxyPort, cwd, extraArgs = []) {
|
|
|
35
35
|
|
|
36
36
|
fixSpawnHelperPermissions();
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
// 如果没有提供 claudePath,尝试自动查找
|
|
39
39
|
if (!claudePath) {
|
|
40
|
-
|
|
40
|
+
claudePath = resolveNativePath();
|
|
41
|
+
if (!claudePath) {
|
|
42
|
+
throw new Error('claude not found');
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
const env = { ...process.env };
|
|
@@ -48,13 +51,20 @@ export async function spawnClaude(proxyPort, cwd, extraArgs = []) {
|
|
|
48
51
|
env: { ANTHROPIC_BASE_URL: env.ANTHROPIC_BASE_URL }
|
|
49
52
|
});
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
let command = claudePath;
|
|
55
|
+
let args = ['--settings', settingsJson, ...extraArgs];
|
|
56
|
+
|
|
57
|
+
// 如果是 npm 版本(cli.js),需要使用 node 来运行
|
|
58
|
+
if (isNpmVersion && claudePath.endsWith('.js')) {
|
|
59
|
+
command = process.execPath; // node 可执行文件路径
|
|
60
|
+
args = [claudePath, '--settings', settingsJson, ...extraArgs];
|
|
61
|
+
}
|
|
52
62
|
|
|
53
63
|
lastExitCode = null;
|
|
54
64
|
outputBuffer = '';
|
|
55
65
|
currentWorkspacePath = cwd || process.cwd();
|
|
56
66
|
|
|
57
|
-
ptyProcess = pty.spawn(
|
|
67
|
+
ptyProcess = pty.spawn(command, args, {
|
|
58
68
|
name: 'xterm-256color',
|
|
59
69
|
cols: 120,
|
|
60
70
|
rows: 30,
|
package/server.js
CHANGED
|
@@ -26,10 +26,16 @@ const IGNORED_PATTERNS = new Set([
|
|
|
26
26
|
|
|
27
27
|
// 工作区模式:保存 Claude 额外参数,供 launch API 使用
|
|
28
28
|
let _workspaceClaudeArgs = [];
|
|
29
|
+
let _workspaceClaudePath = null;
|
|
30
|
+
let _workspaceIsNpmVersion = false;
|
|
29
31
|
let _workspaceLaunched = false; // 工作区是否已经启动了会话
|
|
30
32
|
export function setWorkspaceClaudeArgs(args) {
|
|
31
33
|
_workspaceClaudeArgs = args;
|
|
32
34
|
}
|
|
35
|
+
export function setWorkspaceClaudePath(path, isNpm) {
|
|
36
|
+
_workspaceClaudePath = path;
|
|
37
|
+
_workspaceIsNpmVersion = isNpm;
|
|
38
|
+
}
|
|
33
39
|
|
|
34
40
|
|
|
35
41
|
// macOS user profile (avatar + display name), cached once
|
|
@@ -504,7 +510,7 @@ async function handleRequest(req, res) {
|
|
|
504
510
|
const proxyPort = process.env.CCV_PROXY_PORT;
|
|
505
511
|
if (proxyPort) {
|
|
506
512
|
const { spawnClaude } = await import('./pty-manager.js');
|
|
507
|
-
await spawnClaude(parseInt(proxyPort), wsPath, _workspaceClaudeArgs);
|
|
513
|
+
await spawnClaude(parseInt(proxyPort), wsPath, _workspaceClaudeArgs, _workspaceClaudePath, _workspaceIsNpmVersion);
|
|
508
514
|
}
|
|
509
515
|
|
|
510
516
|
_workspaceLaunched = true;
|