claude-opencode-viewer 2.6.55 → 2.6.57

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
@@ -731,6 +731,31 @@
731
731
  overflow: auto;
732
732
  padding: 16px;
733
733
  }
734
+ .docs-toolbar {
735
+ display: flex;
736
+ justify-content: flex-end;
737
+ margin-bottom: 8px;
738
+ border-bottom: 1px solid #333;
739
+ padding-bottom: 8px;
740
+ }
741
+ .docs-copy-btn {
742
+ display: inline-flex;
743
+ align-items: center;
744
+ gap: 4px;
745
+ padding: 4px 10px;
746
+ background: transparent;
747
+ border: 1px solid #555;
748
+ color: #aaa;
749
+ font-size: 12px;
750
+ border-radius: 4px;
751
+ cursor: pointer;
752
+ transition: all 0.2s;
753
+ }
754
+ .docs-copy-btn:hover {
755
+ background: #333;
756
+ border-color: #777;
757
+ color: #fff;
758
+ }
734
759
  .docs-content-area pre {
735
760
  margin: 0;
736
761
  white-space: pre-wrap;
@@ -1121,7 +1146,7 @@
1121
1146
  var isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
1122
1147
  var isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
1123
1148
  var MOBILE_COLS = 60;
1124
- var fontSize = isMobile ? 11 : 13;
1149
+ var fontSize = isMobile ? 11 : 14;
1125
1150
  var currentMode = 'claude';
1126
1151
  var isTransitioning = false;
1127
1152
  var transitionEndTimer = null;
@@ -1134,7 +1159,7 @@
1134
1159
  cursorBlink: !isMobile,
1135
1160
  fontSize: fontSize,
1136
1161
  fontFamily: 'Menlo, Monaco, "Courier New", monospace',
1137
- lineHeight: 1.15,
1162
+ lineHeight: 1.25,
1138
1163
  letterSpacing: 0,
1139
1164
  theme: {
1140
1165
  background: '#0a0a0a',
@@ -1786,6 +1811,11 @@
1786
1811
  document.getElementById('mode-label').textContent = '';
1787
1812
  }
1788
1813
  if (msg.running) {
1814
+ var mLabel = msg.mode === 'claude' ? 'Claude' : msg.mode === 'qoder' ? 'Qoder' : msg.mode === 'shell' ? 'Shell' : 'OpenCode';
1815
+ var initOv = document.getElementById('init-overlay');
1816
+ initOv.textContent = '正在启动 ' + mLabel + '...';
1817
+ initOv.classList.add('visible');
1818
+ waitingInitData = true;
1789
1819
  preloadData();
1790
1820
  }
1791
1821
  // 服务端无运行进程,显示启动对话框
@@ -2674,7 +2704,22 @@
2674
2704
  area.innerHTML = '<div class="docs-loading" style="color:#ff6b6b;">' + escapeHtml(data.error) + '</div>';
2675
2705
  return;
2676
2706
  }
2677
- area.innerHTML = '<div class="docs-md-content">' + formatDocContent(data.content) + '</div>';
2707
+ var rawContent = data.content || '';
2708
+ var html = '<div class="docs-toolbar">' +
2709
+ '<button class="docs-copy-btn" title="复制">' +
2710
+ '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' +
2711
+ '<rect x="9" y="9" width="13" height="13" rx="2"></rect>' +
2712
+ '<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>' +
2713
+ '</svg></button></div>' +
2714
+ '<div class="docs-md-content">' + formatDocContent(rawContent) + '</div>';
2715
+ area.innerHTML = html;
2716
+ area.querySelector('.docs-copy-btn').addEventListener('click', function() {
2717
+ var btn = area.querySelector('.docs-copy-btn');
2718
+ navigator.clipboard.writeText(rawContent).then(function() {
2719
+ btn.title = '已复制';
2720
+ btn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#58d68d" stroke-width="2.5"><polyline points="20 6 9 17 4 12"></polyline></svg>';
2721
+ });
2722
+ });
2678
2723
  })
2679
2724
  .catch(function(err) {
2680
2725
  area.innerHTML = '<div class="docs-loading" style="color:#ff6b6b;">加载失败</div>';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-opencode-viewer",
3
- "version": "2.6.55",
3
+ "version": "2.6.57",
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
@@ -247,7 +247,7 @@ async function spawnProcess(mode, sessionId = null) {
247
247
  } else if (mode === 'shell') {
248
248
  // 普通 shell 终端: 优先使用 $SHELL,回退到 zsh/bash
249
249
  command = process.env.SHELL || (existsSync('/bin/zsh') ? '/bin/zsh' : '/bin/bash');
250
- args = ['-l']; // 登录 shell,加载 PATH/alias
250
+ args = ['-l', '-i']; // 登录 + 交互模式,加载 PATH/alias 并确保 complete 等命令可用
251
251
  LOG(`[shell] 启动 shell: ${command} ${args.join(' ')}`);
252
252
  } else if (mode === 'qoder') {
253
253
  command = findCommand('qodercli');
@@ -489,7 +489,7 @@ function resizePty(cols, rows) {
489
489
  lastPtyCols = cols;
490
490
  lastPtyRows = rows;
491
491
  if (sameSize) return;
492
- [claudeProcess, opencodeProcess].forEach(proc => {
492
+ [claudeProcess, opencodeProcess, shellProcess, qoderProcess].forEach(proc => {
493
493
  if (proc) {
494
494
  try {
495
495
  // 先设不同尺寸再设目标尺寸,保证即使进程已是该尺寸也能触发 SIGWINCH
@@ -1284,7 +1284,7 @@ wssInst.on('connection', (ws, req) => {
1284
1284
  // 进程已退出时,自动重新启动(参考 cc-viewer 逻辑)
1285
1285
  // 模式切换/新建会话期间不触发 respawn
1286
1286
  // shell 模式不自动 respawn,避免用户输入 exit 后又被重新拉起
1287
- if (!currentProcess && !isSwitching && currentMode !== 'shell' && currentMode !== 'qoder') {
1287
+ if (!currentProcess && !isSwitching && currentMode !== 'shell') {
1288
1288
  try {
1289
1289
  LOG(`[respawn] 进程已退出,自动重新启动 ${currentMode}`);
1290
1290
  outputBuffer = '';