cc-viewer 1.2.2 → 1.2.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 CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { readFileSync, writeFileSync, existsSync } from 'node:fs';
4
- import { resolve } from 'node:path';
4
+ import { resolve, join } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
+ import { execSync } from 'node:child_process';
6
7
  import { homedir } from 'node:os';
7
8
  import { t } from './i18n.js';
8
9
 
@@ -17,7 +18,41 @@ const INJECT_BLOCK = `${INJECT_START}\n${INJECT_IMPORT}\n${INJECT_END}`;
17
18
  const SHELL_HOOK_START = '# >>> CC-Viewer Auto-Inject >>>';
18
19
  const SHELL_HOOK_END = '# <<< CC-Viewer Auto-Inject <<<';
19
20
 
20
- const cliPath = resolve(__dirname, '../@anthropic-ai/claude-code/cli.js');
21
+ // Claude Code cli.js 包名候选列表,按优先级排列
22
+ const CLAUDE_CODE_PACKAGES = [
23
+ '@anthropic-ai/claude-code',
24
+ '@ali/claude-code',
25
+ ];
26
+
27
+ function getGlobalNodeModulesDir() {
28
+ try {
29
+ return execSync('npm root -g', { encoding: 'utf-8' }).trim();
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ function resolveClaudeCodeCliPath() {
36
+ // 候选基础目录:__dirname 的上级(适用于常规 npm 安装)+ 全局 node_modules(适用于符号链接安装)
37
+ const baseDirs = [resolve(__dirname, '..')];
38
+ const globalRoot = getGlobalNodeModulesDir();
39
+ if (globalRoot && globalRoot !== resolve(__dirname, '..')) {
40
+ baseDirs.push(globalRoot);
41
+ }
42
+
43
+ for (const baseDir of baseDirs) {
44
+ for (const packageName of CLAUDE_CODE_PACKAGES) {
45
+ const candidate = join(baseDir, packageName, 'cli.js');
46
+ if (existsSync(candidate)) {
47
+ return candidate;
48
+ }
49
+ }
50
+ }
51
+ // 兜底:返回全局目录下的默认路径,便于错误提示
52
+ return join(globalRoot || resolve(__dirname, '..'), CLAUDE_CODE_PACKAGES[0], 'cli.js');
53
+ }
54
+
55
+ const cliPath = resolveClaudeCodeCliPath();
21
56
 
22
57
  function getShellConfigPath() {
23
58
  const shell = process.env.SHELL || '';
@@ -33,8 +68,14 @@ function getShellConfigPath() {
33
68
  function buildShellHook() {
34
69
  return `${SHELL_HOOK_START}
35
70
  claude() {
36
- local cli_js="$HOME/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js"
37
- if [ -f "$cli_js" ] && ! grep -q "CC Viewer" "$cli_js" 2>/dev/null; then
71
+ local cli_js=""
72
+ for candidate in "$HOME/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js" "$HOME/.npm-global/lib/node_modules/@ali/claude-code/cli.js"; do
73
+ if [ -f "$candidate" ]; then
74
+ cli_js="$candidate"
75
+ break
76
+ fi
77
+ done
78
+ if [ -n "$cli_js" ] && ! grep -q "CC Viewer" "$cli_js" 2>/dev/null; then
38
79
  ccv 2>/dev/null
39
80
  fi
40
81
  command claude "$@"
package/interceptor.js CHANGED
@@ -514,19 +514,23 @@ export function setupInterceptor() {
514
514
  .map(block => {
515
515
  // SSE 块可能包含多行: event: xxx\ndata: {...}
516
516
  const lines = block.split('\n');
517
- const dataLine = lines.find(l => l.startsWith('data: '));
517
+ const dataLine = lines.find(l => l.startsWith('data:'));
518
518
  if (dataLine) {
519
+ // 处理 "data:" 或 "data: " 两种格式
520
+ const jsonStr = dataLine.startsWith('data: ')
521
+ ? dataLine.substring(6)
522
+ : dataLine.substring(5);
519
523
  try {
520
- return JSON.parse(dataLine.substring(6));
524
+ return JSON.parse(jsonStr);
521
525
  } catch {
522
- return dataLine.substring(6);
526
+ return jsonStr;
523
527
  }
524
528
  }
525
529
  return null;
526
530
  })
527
531
  .filter(Boolean);
528
532
 
529
- // 组装完整的 message 对象
533
+ // 组装完整的 message 对象(GLM 使用标准格式,但 data: 后无空格)
530
534
  const assembledMessage = assembleStreamMessage(events);
531
535
 
532
536
  // 直接使用组装后的 message 对象作为 response.body
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-viewer",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Claude Code Logger visualization management tool",
5
5
  "license": "MIT",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -598,7 +598,7 @@ export async function startViewer() {
598
598
  return new Promise((resolve, reject) => {
599
599
  function tryListen(port) {
600
600
  if (port > MAX_PORT) {
601
- console.log(t('server.portsBusy', { start: START_PORT, end: MAX_PORT }));
601
+ console.error(t('server.portsBusy', { start: START_PORT, end: MAX_PORT }));
602
602
  resolve(null);
603
603
  return;
604
604
  }
@@ -609,7 +609,7 @@ export async function startViewer() {
609
609
  server = currentServer;
610
610
  actualPort = port;
611
611
  const url = `http://${HOST}:${port}`;
612
- console.log(t('server.started', { host: HOST, port }));
612
+ console.error(t('server.started', { host: HOST, port }));
613
613
  // v2.0.69 之前的版本会清空控制台,自动打开浏览器确保用户能看到界面
614
614
  try {
615
615
  const ccPkgPath = join(__dirname, '..', '@anthropic-ai', 'claude-code', 'package.json');