claude-opencode-viewer 2.6.35 → 2.6.37

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/index-pc.html CHANGED
@@ -2241,7 +2241,7 @@
2241
2241
  fileList.innerHTML = '<div class="docs-loading" style="color:#666;">无文档</div>';
2242
2242
  return;
2243
2243
  }
2244
- var html = '';
2244
+ var html = '<div style="padding:4px 12px;font-size:11px;color:#666;border-bottom:1px solid #2a2a2a;">📁 ' + escapeHtml(data.cwd || 'PROJECT_DIR') + '</div>';
2245
2245
  docs.forEach(function(doc) {
2246
2246
  var activeClass = docsSelectedFile === doc.name ? ' active' : '';
2247
2247
  var time = new Date(doc.mtime).toLocaleString('zh-CN', { month:'2-digit', day:'2-digit', hour:'2-digit', minute:'2-digit' });
package/index.html CHANGED
@@ -2505,7 +2505,7 @@
2505
2505
  fileList.innerHTML = '<div class="docs-loading" style="color:#666;">无文档</div>';
2506
2506
  return;
2507
2507
  }
2508
- var html = '';
2508
+ var html = '<div style="padding:4px 12px;font-size:11px;color:#666;border-bottom:1px solid #2a2a2a;">📁 ' + escapeHtml(data.cwd || 'PROJECT_DIR') + '</div>';
2509
2509
  docs.forEach(function(doc) {
2510
2510
  var activeClass = docsSelectedFile === doc.name ? ' active' : '';
2511
2511
  var time = new Date(doc.mtime).toLocaleString('zh-CN', { month:'2-digit', day:'2-digit', hour:'2-digit', minute:'2-digit' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-opencode-viewer",
3
- "version": "2.6.35",
3
+ "version": "2.6.37",
4
4
  "description": "A unified terminal viewer for Claude Code and OpenCode with seamless switching",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -643,16 +643,16 @@ const requestHandler = async (req, res) => {
643
643
  });
644
644
  try {
645
645
  const gitCwd = process.env.PROJECT_DIR || process.cwd();
646
- const { stdout } = await execFileAsync('git', ['status', '--porcelain'], {
647
- cwd: gitCwd, encoding: 'utf-8', timeout: 5000,
646
+ const { stdout } = await execFileAsync('git', ['-c', 'safe.directory=*', 'status', '--porcelain'], {
647
+ cwd: gitCwd, encoding: 'utf-8', timeout: 60000,
648
648
  });
649
649
  const changes = stdout.split('\n').filter(Boolean).map(line => ({
650
650
  status: line.substring(0, 2).trim(),
651
651
  file: line.substring(3),
652
652
  })).filter(c => !/^core-/.test(c.file));
653
653
  res.end(JSON.stringify({ changes, cwd: gitCwd }));
654
- } catch {
655
- res.end(JSON.stringify({ changes: [], cwd: process.env.PROJECT_DIR || process.cwd() }));
654
+ } catch (err) {
655
+ res.end(JSON.stringify({ changes: [], cwd: process.env.PROJECT_DIR || process.cwd(), error: err.message }));
656
656
  }
657
657
  return;
658
658
  }
@@ -675,7 +675,7 @@ const requestHandler = async (req, res) => {
675
675
  for (const file of fileList) {
676
676
  if (file.includes('..') || file.startsWith('/')) continue;
677
677
  try {
678
- const { stdout: statusOut } = await execFileAsync('git', ['status', '--porcelain', '--', file], { cwd, encoding: 'utf-8', timeout: 3000 });
678
+ const { stdout: statusOut } = await execFileAsync('git', ['-c', 'safe.directory=*', 'status', '--porcelain', '--', file], { cwd, encoding: 'utf-8', timeout: 30000 });
679
679
  if (!statusOut.trim()) continue;
680
680
  const status = statusOut.substring(0, 2).trim();
681
681
  const is_new = status === 'A' || status === '??';
@@ -683,7 +683,7 @@ const requestHandler = async (req, res) => {
683
683
  let is_binary = false;
684
684
  if (!is_deleted) {
685
685
  try {
686
- const { stdout: dc } = await execFileAsync('git', ['diff', '--numstat', 'HEAD', '--', file], { cwd, encoding: 'utf-8', timeout: 3000 });
686
+ const { stdout: dc } = await execFileAsync('git', ['-c', 'safe.directory=*', 'diff', '--numstat', 'HEAD', '--', file], { cwd, encoding: 'utf-8', timeout: 30000 });
687
687
  if (dc.includes('-\t-\t')) is_binary = true;
688
688
  } catch {}
689
689
  }
@@ -691,7 +691,7 @@ const requestHandler = async (req, res) => {
691
691
  if (!is_binary) {
692
692
  if (!is_new) {
693
693
  try {
694
- const { stdout } = await execFileAsync('git', ['show', `HEAD:${file}`], { cwd, encoding: 'utf-8', timeout: 5000, maxBuffer: 5 * 1024 * 1024 });
694
+ const { stdout } = await execFileAsync('git', ['-c', 'safe.directory=*', 'show', `HEAD:${file}`], { cwd, encoding: 'utf-8', timeout: 60000, maxBuffer: 5 * 1024 * 1024 });
695
695
  old_content = stdout;
696
696
  } catch {}
697
697
  }
@@ -711,9 +711,9 @@ const requestHandler = async (req, res) => {
711
711
  // 获取 unified diff
712
712
  try {
713
713
  const diffArgs = is_new
714
- ? ['diff', '--no-color', '-U3', '--no-index', '/dev/null', file]
715
- : ['diff', '--no-color', '-U3', 'HEAD', '--', file];
716
- const { stdout } = await execFileAsync('git', diffArgs, { cwd, encoding: 'utf-8', timeout: 5000, maxBuffer: 5 * 1024 * 1024 });
714
+ ? ['-c', 'safe.directory=*', 'diff', '--no-color', '-U3', '--no-index', '/dev/null', file]
715
+ : ['-c', 'safe.directory=*', 'diff', '--no-color', '-U3', 'HEAD', '--', file];
716
+ const { stdout } = await execFileAsync('git', diffArgs, { cwd, encoding: 'utf-8', timeout: 60000, maxBuffer: 5 * 1024 * 1024 });
717
717
  unified_diff = stdout;
718
718
  } catch (e) {
719
719
  if (e.stdout) unified_diff = e.stdout;
@@ -730,7 +730,7 @@ const requestHandler = async (req, res) => {
730
730
  if (req.url === '/api/docs') {
731
731
  res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
732
732
  try {
733
- const docsRoot = existsSync('/halo') ? '/halo' : process.cwd();
733
+ const docsRoot = process.env.PROJECT_DIR || process.cwd();
734
734
  const EXCLUDE = new Set(['readme.md', 'changelog.md', 'license.md', 'claude.md', 'agents.md', 'contributing.md', 'security.md', 'context.md']);
735
735
  const files = [];
736
736
  const SKIP_DIRS = new Set(['node_modules', '.git', '.opencode', '.claude', '.idea', '.vscode']);
@@ -752,7 +752,7 @@ const requestHandler = async (req, res) => {
752
752
  };
753
753
  scanDir(docsRoot, '', 0);
754
754
  files.sort((a, b) => b.mtime - a.mtime);
755
- res.end(JSON.stringify({ docs: files }));
755
+ res.end(JSON.stringify({ docs: files, cwd: docsRoot }));
756
756
  } catch (err) {
757
757
  res.end(JSON.stringify({ docs: [], error: err.message }));
758
758
  }
@@ -1297,6 +1297,7 @@ function startServer() {
1297
1297
  // 清理上次 cov 崩溃残留的孤儿进程
1298
1298
  cleanupOrphanProcesses();
1299
1299
 
1300
+
1300
1301
  // 尝试恢复最近的会话,如果没有则新建
1301
1302
  if (currentMode === 'opencode') {
1302
1303
  let lastSessionId = null;