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/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-DVJLme9U.js"></script>
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}`]) {
@@ -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
- const name = loaded ? loaded.name : file;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-viewer",
3
- "version": "1.4.21",
3
+ "version": "1.4.23",
4
4
  "description": "Claude Code Logger visualization management tool",
5
5
  "license": "MIT",
6
6
  "main": "server.js",
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
- const claudePath = resolveNativePath();
38
+ // 如果没有提供 claudePath,尝试自动查找
39
39
  if (!claudePath) {
40
- throw new Error('claude not found');
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
- const args = ['--settings', settingsJson, ...extraArgs];
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(claudePath, args, {
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;