claude-opencode-viewer 2.6.10 → 2.6.11

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
@@ -87,170 +87,6 @@
87
87
  -webkit-overflow-scrolling: touch;
88
88
  }
89
89
 
90
- #session-detail-view {
91
- display: none;
92
- flex-direction: column;
93
- flex: 1;
94
- min-height: 0;
95
- }
96
-
97
- #session-detail-view.visible {
98
- display: flex;
99
- }
100
-
101
- #session-detail-header {
102
- padding: 12px 16px;
103
- background: #0d0d0d;
104
- border-bottom: 1px solid #222;
105
- flex-shrink: 0;
106
- }
107
-
108
- #session-detail-title {
109
- font-size: 14px;
110
- color: #ddd;
111
- font-weight: 500;
112
- margin-bottom: 4px;
113
- }
114
-
115
- #session-detail-meta {
116
- font-size: 11px;
117
- color: #888;
118
- display: flex;
119
- gap: 12px;
120
- }
121
-
122
- #session-detail-content {
123
- flex: 1;
124
- overflow-y: auto;
125
- padding: 16px;
126
- -webkit-overflow-scrolling: touch;
127
- }
128
-
129
- .message-item {
130
- margin-bottom: 20px;
131
- display: flex;
132
- gap: 12px;
133
- align-items: flex-start;
134
- }
135
-
136
- /* User 消息:左对齐 */
137
- .message-user {
138
- justify-content: flex-start;
139
- }
140
-
141
- /* Assistant 消息:右对齐 */
142
- .message-assistant {
143
- justify-content: flex-end;
144
- flex-direction: row-reverse;
145
- }
146
-
147
- .message-avatar {
148
- flex-shrink: 0;
149
- width: 32px;
150
- height: 32px;
151
- border-radius: 50%;
152
- background: #2a4a7c;
153
- display: flex;
154
- align-items: center;
155
- justify-content: center;
156
- font-size: 14px;
157
- }
158
-
159
- .message-assistant .message-avatar {
160
- background: #1a5a3a;
161
- }
162
-
163
- .message-content {
164
- flex: 1;
165
- min-width: 0;
166
- max-width: 80%;
167
- }
168
-
169
- .message-header {
170
- display: flex;
171
- align-items: center;
172
- gap: 8px;
173
- margin-bottom: 6px;
174
- }
175
-
176
- /* User 的标题左对齐 */
177
- .message-user .message-header {
178
- justify-content: flex-start;
179
- }
180
-
181
- /* Assistant 的标题右对齐 */
182
- .message-assistant .message-header {
183
- justify-content: flex-end;
184
- flex-direction: row-reverse;
185
- }
186
-
187
- .message-role {
188
- font-size: 11px;
189
- color: #888;
190
- font-weight: 600;
191
- text-transform: uppercase;
192
- letter-spacing: 0.5px;
193
- }
194
-
195
- .message-text {
196
- color: #ddd;
197
- font-size: 13px;
198
- line-height: 1.6;
199
- white-space: pre-wrap;
200
- word-break: break-word;
201
- background: #141414;
202
- padding: 12px;
203
- border-radius: 8px;
204
- border: 1px solid #222;
205
- }
206
-
207
- /* User 消息气泡 */
208
- .message-user .message-text {
209
- background: #1a2332;
210
- border-color: #2a4a7c;
211
- }
212
-
213
- /* Assistant 消息气泡 */
214
- .message-assistant .message-text {
215
- background: #1a2e1a;
216
- border-color: #2a5a3a;
217
- }
218
-
219
- .message-tool-call {
220
- margin-top: 8px;
221
- padding: 8px 12px;
222
- background: #1a1a0a;
223
- border: 1px solid #333;
224
- border-radius: 6px;
225
- font-size: 12px;
226
- }
227
-
228
- .message-tool-name {
229
- color: #f0ad4e;
230
- font-weight: 600;
231
- display: flex;
232
- align-items: center;
233
- gap: 6px;
234
- }
235
-
236
- .message-tool-result {
237
- margin-top: 6px;
238
- padding: 8px;
239
- background: #0a0a0a;
240
- border-radius: 4px;
241
- font-size: 11px;
242
- color: #999;
243
- max-height: 100px;
244
- overflow-y: auto;
245
- }
246
-
247
- .message-empty {
248
- text-align: center;
249
- padding: 40px 20px;
250
- color: #666;
251
- font-size: 13px;
252
- }
253
-
254
90
  #session-list {
255
91
  display: flex;
256
92
  flex-direction: column;
@@ -894,38 +730,6 @@
894
730
  </div>
895
731
  </div>
896
732
 
897
- <!-- 会话详情视图 -->
898
- <div id="session-detail-view">
899
- <div id="session-history-header">
900
- <div id="session-history-title">会话详情</div>
901
- <div id="session-history-actions">
902
- <button class="history-toggle-btn" id="restore-session" style="background: #1a5a3a; border-color: #2a7a4a;">
903
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
904
- <polyline points="1 4 1 10 7 10"></polyline>
905
- <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
906
- </svg>
907
- <span>恢复会话</span>
908
- </button>
909
- <button class="history-toggle-btn" id="back-to-list">
910
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
911
- <line x1="19" y1="12" x2="5" y2="12"></line>
912
- <polyline points="12 19 5 12 12 5"></polyline>
913
- </svg>
914
- <span>返回列表</span>
915
- </button>
916
- </div>
917
- </div>
918
- <div id="session-detail-header">
919
- <div id="session-detail-title">会话标题</div>
920
- <div id="session-detail-meta">
921
- <span id="session-detail-time">时间</span>
922
- <span id="session-detail-dir">目录</span>
923
- </div>
924
- </div>
925
- <div id="session-detail-content">
926
- <div class="message-empty">加载中...</div>
927
- </div>
928
- </div>
929
733
  </div>
930
734
 
931
735
  <!-- Git Diff 面板 -->
@@ -1722,110 +1526,35 @@
1722
1526
  });
1723
1527
  }
1724
1528
 
1725
- function showSessionDetail() {
1726
- document.getElementById('session-list-view').classList.add('hidden');
1727
- document.getElementById('session-detail-view').classList.add('visible');
1728
- }
1729
1529
 
1730
- function showSessionList() {
1731
- document.getElementById('session-list-view').classList.remove('hidden');
1732
- document.getElementById('session-detail-view').classList.remove('visible');
1733
- }
1734
1530
 
1735
1531
  function loadSession(session) {
1736
- console.log('[session] 加载会话:', session.title);
1737
-
1738
- // 保存当前会话数据
1532
+ console.log('[restore] 直接恢复会话:', session.title);
1739
1533
  currentSessionData = session;
1740
1534
 
1741
- // 切换到详情视图
1742
- showSessionDetail();
1743
-
1744
- // 更新详情页标题和元信息
1745
- document.getElementById('session-detail-title').textContent = session.preview || session.title;
1746
- document.getElementById('session-detail-time').textContent = formatTime(session.time_updated);
1747
- document.getElementById('session-detail-dir').textContent = session.directory.replace(/^\/Users\/[^\/]+/, '~');
1748
-
1749
- var contentDiv = document.getElementById('session-detail-content');
1750
- contentDiv.innerHTML = '<div class="message-empty">加载消息中...</div>';
1751
-
1752
- // 获取会话的所有消息
1753
- fetch('/api/session/' + session.id)
1754
- .then(function(response) { return response.json(); })
1755
- .then(function(messages) {
1756
- console.log('[session] 收到', messages.length, '条消息');
1757
-
1758
- if (messages.length === 0) {
1759
- contentDiv.innerHTML = '<div class="message-empty">该会话暂无消息</div>';
1760
- return;
1761
- }
1762
-
1763
- // 渲染消息列表
1764
- var html = '';
1765
- messages.forEach(function(msg) {
1766
- console.log('[render] 消息:', msg);
1767
-
1768
- var roleClass = msg.role === 'assistant' ? 'message-assistant' : 'message-user';
1769
- var avatar = msg.role === 'user' ? '👤' : '🤖';
1770
- var roleName = msg.role === 'user' ? 'User' : 'Assistant';
1771
-
1772
- html += '<div class="message-item ' + roleClass + '">';
1773
- html += '<div class="message-avatar">' + avatar + '</div>';
1774
- html += '<div class="message-content">';
1775
- html += '<div class="message-header">';
1776
- html += '<div class="message-role">' + roleName + '</div>';
1777
- html += '</div>';
1778
-
1779
- // 显示推理过程(仅 assistant)
1780
- if (msg.reasoning) {
1781
- html += '<div class="message-text" style="background: #1a1a0a; border-color: #333;">';
1782
- html += '<div style="color: #f0ad4e; font-size: 11px; font-weight: 600; margin-bottom: 6px;">💭 思考过程</div>';
1783
- html += '<div style="color: #bbb;">' + escapeHtml(msg.reasoning) + '</div>';
1784
- html += '</div>';
1785
- }
1786
-
1787
- // 显示文本内容
1788
- if (msg.text) {
1789
- html += '<div class="message-text">' + escapeHtml(msg.text) + '</div>';
1790
- } else if (!msg.reasoning && !msg.toolCalls && !msg.toolResults) {
1791
- html += '<div class="message-text" style="color: #666; font-style: italic;">(无文本内容)</div>';
1792
- }
1793
-
1794
- // 显示工具调用
1795
- if (msg.toolCalls && msg.toolCalls.length > 0) {
1796
- msg.toolCalls.forEach(function(tool) {
1797
- html += '<div class="message-tool-call">';
1798
- html += '<div class="message-tool-name">🔧 工具调用: ' + escapeHtml(tool.name || '未知工具') + '</div>';
1799
- html += '</div>';
1800
- });
1801
- }
1802
-
1803
- // 显示工具结果
1804
- if (msg.toolResults && msg.toolResults.length > 0) {
1805
- msg.toolResults.forEach(function(result) {
1806
- if (result.text) {
1807
- var resultText = result.text.length > 200 ? result.text.substring(0, 200) + '...' : result.text;
1808
- html += '<div class="message-tool-call">';
1809
- html += '<div class="message-tool-name">📝 工具结果</div>';
1810
- html += '<div class="message-tool-result">' + escapeHtml(resultText) + '</div>';
1811
- html += '</div>';
1812
- }
1813
- });
1814
- }
1535
+ // 关闭历史栏
1536
+ toggleHistoryBar();
1815
1537
 
1816
- html += '</div>';
1817
- html += '</div>';
1818
- });
1538
+ // 清空终端
1539
+ term.clear();
1819
1540
 
1820
- contentDiv.innerHTML = html;
1541
+ // 显示正在恢复的提示
1542
+ term.write('\x1b[1;36m╔══════════════════════════════════════════════════════════════╗\x1b[0m\r\n');
1543
+ term.write('\x1b[1;36m║ \x1b[1;37m正在恢复会话... \x1b[1;36m║\x1b[0m\r\n');
1544
+ term.write('\x1b[1;36m╚══════════════════════════════════════════════════════════════╝\x1b[0m\r\n');
1545
+ term.write('\r\n');
1821
1546
 
1822
- // 滚动到底部
1823
- contentDiv.scrollTop = contentDiv.scrollHeight;
1824
- })
1825
- .catch(function(err) {
1826
- console.error('[session] 加载消息失败:', err);
1827
- contentDiv.innerHTML = '<div class="message-empty">加载失败: ' + escapeHtml(err.message) + '</div>';
1828
- });
1547
+ if (ws && ws.readyState === 1) {
1548
+ if (currentMode !== 'opencode') {
1549
+ term.write('\x1b[31m错误: 请先切换到 OpenCode 模式\x1b[0m\r\n');
1550
+ return;
1551
+ }
1552
+ term.write('\x1b[33m正在重启 OpenCode 并恢复会话: ' + session.id + '\x1b[0m\r\n');
1553
+ term.write('\r\n');
1554
+ ws.send(JSON.stringify({ type: 'restore', sessionId: session.id }));
1555
+ } else {
1556
+ term.write('\x1b[31m错误: WebSocket 未连接\x1b[0m\r\n');
1557
+ }
1829
1558
  }
1830
1559
 
1831
1560
  function escapeHtml(text) {
@@ -1878,53 +1607,6 @@
1878
1607
  toggleHistoryBar();
1879
1608
  });
1880
1609
 
1881
- // 返回到会话列表
1882
- document.getElementById('back-to-list').addEventListener('click', function(e) {
1883
- e.stopPropagation();
1884
- showSessionList();
1885
- });
1886
-
1887
- // 恢复会话
1888
- document.getElementById('restore-session').addEventListener('click', function(e) {
1889
- e.stopPropagation();
1890
- if (!currentSessionData) {
1891
- console.error('[restore] 没有当前会话数据');
1892
- return;
1893
- }
1894
-
1895
- console.log('[restore] 恢复会话:', currentSessionData.id);
1896
-
1897
- // 关闭历史栏
1898
- toggleHistoryBar();
1899
-
1900
- // 清空终端
1901
- term.clear();
1902
-
1903
- // 显示正在恢复的提示
1904
- term.write('\x1b[1;36m╔══════════════════════════════════════════════════════════════╗\x1b[0m\r\n');
1905
- term.write('\x1b[1;36m║ \x1b[1;37m正在恢复会话... \x1b[1;36m║\x1b[0m\r\n');
1906
- term.write('\x1b[1;36m╚══════════════════════════════════════════════════════════════╝\x1b[0m\r\n');
1907
- term.write('\r\n');
1908
-
1909
- // 发送恢复会话的请求到服务端
1910
- if (ws && ws.readyState === 1) {
1911
- if (currentMode !== 'opencode') {
1912
- term.write('\x1b[31m错误: 请先切换到 OpenCode 模式\x1b[0m\r\n');
1913
- return;
1914
- }
1915
-
1916
- term.write('\x1b[33m正在重启 OpenCode 并恢复会话: ' + currentSessionData.id + '\x1b[0m\r\n');
1917
- term.write('\r\n');
1918
-
1919
- // 发送恢复请求
1920
- ws.send(JSON.stringify({
1921
- type: 'restore',
1922
- sessionId: currentSessionData.id
1923
- }));
1924
- } else {
1925
- term.write('\x1b[31m错误: WebSocket 未连接\x1b[0m\r\n');
1926
- }
1927
- });
1928
1610
 
1929
1611
  // 提取终端缓冲区文本
1930
1612
  function getTerminalText() {
package/index.html CHANGED
@@ -87,170 +87,6 @@
87
87
  -webkit-overflow-scrolling: touch;
88
88
  }
89
89
 
90
- #session-detail-view {
91
- display: none;
92
- flex-direction: column;
93
- flex: 1;
94
- min-height: 0;
95
- }
96
-
97
- #session-detail-view.visible {
98
- display: flex;
99
- }
100
-
101
- #session-detail-header {
102
- padding: 12px 16px;
103
- background: #0d0d0d;
104
- border-bottom: 1px solid #222;
105
- flex-shrink: 0;
106
- }
107
-
108
- #session-detail-title {
109
- font-size: 14px;
110
- color: #ddd;
111
- font-weight: 500;
112
- margin-bottom: 4px;
113
- }
114
-
115
- #session-detail-meta {
116
- font-size: 11px;
117
- color: #888;
118
- display: flex;
119
- gap: 12px;
120
- }
121
-
122
- #session-detail-content {
123
- flex: 1;
124
- overflow-y: auto;
125
- padding: 16px;
126
- -webkit-overflow-scrolling: touch;
127
- }
128
-
129
- .message-item {
130
- margin-bottom: 20px;
131
- display: flex;
132
- gap: 12px;
133
- align-items: flex-start;
134
- }
135
-
136
- /* User 消息:左对齐 */
137
- .message-user {
138
- justify-content: flex-start;
139
- }
140
-
141
- /* Assistant 消息:右对齐 */
142
- .message-assistant {
143
- justify-content: flex-end;
144
- flex-direction: row-reverse;
145
- }
146
-
147
- .message-avatar {
148
- flex-shrink: 0;
149
- width: 32px;
150
- height: 32px;
151
- border-radius: 50%;
152
- background: #2a4a7c;
153
- display: flex;
154
- align-items: center;
155
- justify-content: center;
156
- font-size: 14px;
157
- }
158
-
159
- .message-assistant .message-avatar {
160
- background: #1a5a3a;
161
- }
162
-
163
- .message-content {
164
- flex: 1;
165
- min-width: 0;
166
- max-width: 80%;
167
- }
168
-
169
- .message-header {
170
- display: flex;
171
- align-items: center;
172
- gap: 8px;
173
- margin-bottom: 6px;
174
- }
175
-
176
- /* User 的标题左对齐 */
177
- .message-user .message-header {
178
- justify-content: flex-start;
179
- }
180
-
181
- /* Assistant 的标题右对齐 */
182
- .message-assistant .message-header {
183
- justify-content: flex-end;
184
- flex-direction: row-reverse;
185
- }
186
-
187
- .message-role {
188
- font-size: 11px;
189
- color: #888;
190
- font-weight: 600;
191
- text-transform: uppercase;
192
- letter-spacing: 0.5px;
193
- }
194
-
195
- .message-text {
196
- color: #ddd;
197
- font-size: 13px;
198
- line-height: 1.6;
199
- white-space: pre-wrap;
200
- word-break: break-word;
201
- background: #141414;
202
- padding: 12px;
203
- border-radius: 8px;
204
- border: 1px solid #222;
205
- }
206
-
207
- /* User 消息气泡 */
208
- .message-user .message-text {
209
- background: #1a2332;
210
- border-color: #2a4a7c;
211
- }
212
-
213
- /* Assistant 消息气泡 */
214
- .message-assistant .message-text {
215
- background: #1a2e1a;
216
- border-color: #2a5a3a;
217
- }
218
-
219
- .message-tool-call {
220
- margin-top: 8px;
221
- padding: 8px 12px;
222
- background: #1a1a0a;
223
- border: 1px solid #333;
224
- border-radius: 6px;
225
- font-size: 12px;
226
- }
227
-
228
- .message-tool-name {
229
- color: #f0ad4e;
230
- font-weight: 600;
231
- display: flex;
232
- align-items: center;
233
- gap: 6px;
234
- }
235
-
236
- .message-tool-result {
237
- margin-top: 6px;
238
- padding: 8px;
239
- background: #0a0a0a;
240
- border-radius: 4px;
241
- font-size: 11px;
242
- color: #999;
243
- max-height: 100px;
244
- overflow-y: auto;
245
- }
246
-
247
- .message-empty {
248
- text-align: center;
249
- padding: 40px 20px;
250
- color: #666;
251
- font-size: 13px;
252
- }
253
-
254
90
  #session-list {
255
91
  display: flex;
256
92
  flex-direction: column;
@@ -884,38 +720,6 @@
884
720
  </div>
885
721
  </div>
886
722
 
887
- <!-- 会话详情视图 -->
888
- <div id="session-detail-view">
889
- <div id="session-history-header">
890
- <div id="session-history-title">会话详情</div>
891
- <div id="session-history-actions">
892
- <button class="history-toggle-btn" id="restore-session" style="background: #1a5a3a; border-color: #2a7a4a;">
893
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
894
- <polyline points="1 4 1 10 7 10"></polyline>
895
- <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
896
- </svg>
897
- <span>恢复会话</span>
898
- </button>
899
- <button class="history-toggle-btn" id="back-to-list">
900
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
901
- <line x1="19" y1="12" x2="5" y2="12"></line>
902
- <polyline points="12 19 5 12 12 5"></polyline>
903
- </svg>
904
- <span>返回列表</span>
905
- </button>
906
- </div>
907
- </div>
908
- <div id="session-detail-header">
909
- <div id="session-detail-title">会话标题</div>
910
- <div id="session-detail-meta">
911
- <span id="session-detail-time">时间</span>
912
- <span id="session-detail-dir">目录</span>
913
- </div>
914
- </div>
915
- <div id="session-detail-content">
916
- <div class="message-empty">加载中...</div>
917
- </div>
918
- </div>
919
723
  </div>
920
724
 
921
725
  <!-- Git Diff 面板 -->
@@ -1884,110 +1688,35 @@
1884
1688
  });
1885
1689
  }
1886
1690
 
1887
- function showSessionDetail() {
1888
- document.getElementById('session-list-view').classList.add('hidden');
1889
- document.getElementById('session-detail-view').classList.add('visible');
1890
- }
1891
1691
 
1892
- function showSessionList() {
1893
- document.getElementById('session-list-view').classList.remove('hidden');
1894
- document.getElementById('session-detail-view').classList.remove('visible');
1895
- }
1896
1692
 
1897
1693
  function loadSession(session) {
1898
- console.log('[session] 加载会话:', session.title);
1899
-
1900
- // 保存当前会话数据
1694
+ console.log('[restore] 直接恢复会话:', session.title);
1901
1695
  currentSessionData = session;
1902
1696
 
1903
- // 切换到详情视图
1904
- showSessionDetail();
1905
-
1906
- // 更新详情页标题和元信息
1907
- document.getElementById('session-detail-title').textContent = session.preview || session.title;
1908
- document.getElementById('session-detail-time').textContent = formatTime(session.time_updated);
1909
- document.getElementById('session-detail-dir').textContent = session.directory.replace(/^\/Users\/[^\/]+/, '~');
1910
-
1911
- var contentDiv = document.getElementById('session-detail-content');
1912
- contentDiv.innerHTML = '<div class="message-empty">加载消息中...</div>';
1913
-
1914
- // 获取会话的所有消息
1915
- fetch('/api/session/' + session.id)
1916
- .then(function(response) { return response.json(); })
1917
- .then(function(messages) {
1918
- console.log('[session] 收到', messages.length, '条消息');
1919
-
1920
- if (messages.length === 0) {
1921
- contentDiv.innerHTML = '<div class="message-empty">该会话暂无消息</div>';
1922
- return;
1923
- }
1924
-
1925
- // 渲染消息列表
1926
- var html = '';
1927
- messages.forEach(function(msg) {
1928
- console.log('[render] 消息:', msg);
1929
-
1930
- var roleClass = msg.role === 'assistant' ? 'message-assistant' : 'message-user';
1931
- var avatar = msg.role === 'user' ? '👤' : '🤖';
1932
- var roleName = msg.role === 'user' ? 'User' : 'Assistant';
1933
-
1934
- html += '<div class="message-item ' + roleClass + '">';
1935
- html += '<div class="message-avatar">' + avatar + '</div>';
1936
- html += '<div class="message-content">';
1937
- html += '<div class="message-header">';
1938
- html += '<div class="message-role">' + roleName + '</div>';
1939
- html += '</div>';
1940
-
1941
- // 显示推理过程(仅 assistant)
1942
- if (msg.reasoning) {
1943
- html += '<div class="message-text" style="background: #1a1a0a; border-color: #333;">';
1944
- html += '<div style="color: #f0ad4e; font-size: 11px; font-weight: 600; margin-bottom: 6px;">💭 思考过程</div>';
1945
- html += '<div style="color: #bbb;">' + escapeHtml(msg.reasoning) + '</div>';
1946
- html += '</div>';
1947
- }
1948
-
1949
- // 显示文本内容
1950
- if (msg.text) {
1951
- html += '<div class="message-text">' + escapeHtml(msg.text) + '</div>';
1952
- } else if (!msg.reasoning && !msg.toolCalls && !msg.toolResults) {
1953
- html += '<div class="message-text" style="color: #666; font-style: italic;">(无文本内容)</div>';
1954
- }
1955
-
1956
- // 显示工具调用
1957
- if (msg.toolCalls && msg.toolCalls.length > 0) {
1958
- msg.toolCalls.forEach(function(tool) {
1959
- html += '<div class="message-tool-call">';
1960
- html += '<div class="message-tool-name">🔧 工具调用: ' + escapeHtml(tool.name || '未知工具') + '</div>';
1961
- html += '</div>';
1962
- });
1963
- }
1964
-
1965
- // 显示工具结果
1966
- if (msg.toolResults && msg.toolResults.length > 0) {
1967
- msg.toolResults.forEach(function(result) {
1968
- if (result.text) {
1969
- var resultText = result.text.length > 200 ? result.text.substring(0, 200) + '...' : result.text;
1970
- html += '<div class="message-tool-call">';
1971
- html += '<div class="message-tool-name">📝 工具结果</div>';
1972
- html += '<div class="message-tool-result">' + escapeHtml(resultText) + '</div>';
1973
- html += '</div>';
1974
- }
1975
- });
1976
- }
1697
+ // 关闭历史栏
1698
+ toggleHistoryBar();
1977
1699
 
1978
- html += '</div>';
1979
- html += '</div>';
1980
- });
1700
+ // 清空终端
1701
+ term.clear();
1981
1702
 
1982
- contentDiv.innerHTML = html;
1703
+ // 显示正在恢复的提示
1704
+ term.write('\x1b[1;36m╔══════════════════════════════════════════════════════════════╗\x1b[0m\r\n');
1705
+ term.write('\x1b[1;36m║ \x1b[1;37m正在恢复会话... \x1b[1;36m║\x1b[0m\r\n');
1706
+ term.write('\x1b[1;36m╚══════════════════════════════════════════════════════════════╝\x1b[0m\r\n');
1707
+ term.write('\r\n');
1983
1708
 
1984
- // 滚动到底部
1985
- contentDiv.scrollTop = contentDiv.scrollHeight;
1986
- })
1987
- .catch(function(err) {
1988
- console.error('[session] 加载消息失败:', err);
1989
- contentDiv.innerHTML = '<div class="message-empty">加载失败: ' + escapeHtml(err.message) + '</div>';
1990
- });
1709
+ if (ws && ws.readyState === 1) {
1710
+ if (currentMode !== 'opencode') {
1711
+ term.write('\x1b[31m错误: 请先切换到 OpenCode 模式\x1b[0m\r\n');
1712
+ return;
1713
+ }
1714
+ term.write('\x1b[33m正在重启 OpenCode 并恢复会话: ' + session.id + '\x1b[0m\r\n');
1715
+ term.write('\r\n');
1716
+ ws.send(JSON.stringify({ type: 'restore', sessionId: session.id }));
1717
+ } else {
1718
+ term.write('\x1b[31m错误: WebSocket 未连接\x1b[0m\r\n');
1719
+ }
1991
1720
  }
1992
1721
 
1993
1722
  function escapeHtml(text) {
@@ -2040,53 +1769,6 @@
2040
1769
  toggleHistoryBar();
2041
1770
  });
2042
1771
 
2043
- // 返回到会话列表
2044
- document.getElementById('back-to-list').addEventListener('click', function(e) {
2045
- e.stopPropagation();
2046
- showSessionList();
2047
- });
2048
-
2049
- // 恢复会话
2050
- document.getElementById('restore-session').addEventListener('click', function(e) {
2051
- e.stopPropagation();
2052
- if (!currentSessionData) {
2053
- console.error('[restore] 没有当前会话数据');
2054
- return;
2055
- }
2056
-
2057
- console.log('[restore] 恢复会话:', currentSessionData.id);
2058
-
2059
- // 关闭历史栏
2060
- toggleHistoryBar();
2061
-
2062
- // 清空终端
2063
- term.clear();
2064
-
2065
- // 显示正在恢复的提示
2066
- term.write('\x1b[1;36m╔══════════════════════════════════════════════════════════════╗\x1b[0m\r\n');
2067
- term.write('\x1b[1;36m║ \x1b[1;37m正在恢复会话... \x1b[1;36m║\x1b[0m\r\n');
2068
- term.write('\x1b[1;36m╚══════════════════════════════════════════════════════════════╝\x1b[0m\r\n');
2069
- term.write('\r\n');
2070
-
2071
- // 发送恢复会话的请求到服务端
2072
- if (ws && ws.readyState === 1) {
2073
- if (currentMode !== 'opencode') {
2074
- term.write('\x1b[31m错误: 请先切换到 OpenCode 模式\x1b[0m\r\n');
2075
- return;
2076
- }
2077
-
2078
- term.write('\x1b[33m正在重启 OpenCode 并恢复会话: ' + currentSessionData.id + '\x1b[0m\r\n');
2079
- term.write('\r\n');
2080
-
2081
- // 发送恢复请求
2082
- ws.send(JSON.stringify({
2083
- type: 'restore',
2084
- sessionId: currentSessionData.id
2085
- }));
2086
- } else {
2087
- term.write('\x1b[31m错误: WebSocket 未连接\x1b[0m\r\n');
2088
- }
2089
- });
2090
1772
 
2091
1773
  // 提取终端缓冲区文本
2092
1774
  function getTerminalText() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-opencode-viewer",
3
- "version": "2.6.10",
3
+ "version": "2.6.11",
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
@@ -30,7 +30,7 @@ async function getOrCreateCert() {
30
30
  return { key: readFileSync(keyPath), cert: readFileSync(certPath) };
31
31
  }
32
32
 
33
- console.log('🔐 首次使用 HTTPS,生成自签名证书...');
33
+ if (!JSON_OUTPUT) console.log('🔐 首次使用 HTTPS,生成自签名证书...');
34
34
  mkdirSync(certDir, { recursive: true });
35
35
 
36
36
  const { default: selfsigned } = await import('selfsigned');
@@ -48,7 +48,7 @@ async function getOrCreateCert() {
48
48
 
49
49
  writeFileSync(keyPath, pems.private);
50
50
  writeFileSync(certPath, pems.cert);
51
- console.log(`📁 证书已保存到 ${certDir}`);
51
+ if (!JSON_OUTPUT) console.log(`📁 证书已保存到 ${certDir}`);
52
52
  return { key: pems.private, cert: pems.cert };
53
53
  }
54
54