claude-remote 0.6.0 → 0.6.1

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.
@@ -1,74 +1,101 @@
1
- // ============================================================
2
- // Settings
3
- // ============================================================
4
- import { $ } from './utils.js';
5
- import { S, approvalMode, setApprovalModeValue } from './state.js';
6
- import { showConfirm } from './confirm.js';
7
- import { updateSettingsCwd } from './dir-picker.js';
8
-
9
- function updateSettingsActive() {
10
- document.querySelectorAll('.settings-opt').forEach(el => {
11
- el.classList.toggle('active', el.dataset.mode === approvalMode);
12
- });
13
- }
14
-
15
- function setApprovalMode(mode) {
16
- setApprovalModeValue(mode);
17
- localStorage.setItem('approvalMode', mode);
18
- updateSettingsActive();
19
- if (S.ws && S.ws.readyState === WebSocket.OPEN) {
20
- S.ws.send(JSON.stringify({ type: 'set_approval_mode', mode }));
21
- }
22
- }
23
-
24
- export function initSettingsValues() {
25
- const radio = document.querySelector(`input[name="approval-mode"][value="${approvalMode}"]`);
26
- if (radio) radio.checked = true;
27
- updateSettingsActive();
28
- }
29
-
30
- function openSettings() {
31
- initSettingsValues();
32
- updateSettingsCwd();
33
- $('settings-overlay').classList.add('visible');
34
- }
35
-
36
- function closeSettings() {
37
- $('settings-overlay').classList.remove('visible');
38
- }
39
-
40
- export { closeSettings };
41
-
42
- export function initSettings() {
43
- $('btn-settings').addEventListener('click', openSettings);
44
- $('settings-close').addEventListener('click', closeSettings);
45
- $('settings-overlay').addEventListener('click', e => {
46
- if (e.target === $('settings-overlay')) closeSettings();
47
- });
48
-
49
- document.querySelectorAll('input[name="approval-mode"]').forEach(radio => {
50
- radio.addEventListener('change', async (e) => {
51
- const mode = e.target.value;
52
- if (mode === 'all') {
53
- const ok = await showConfirm(
54
- '全部自动审批将允许所有命令(包括 Bash、系统命令)无需确认直接执行,这可能存在风险。确定要开启吗?'
55
- );
56
- if (!ok) {
57
- const prev = document.querySelector(`input[name="approval-mode"][value="${approvalMode}"]`);
58
- if (prev) prev.checked = true;
59
- return;
60
- }
61
- } else if (mode === 'partial') {
62
- const ok = await showConfirm(
63
- '部分自动审批将自动放行 Read、Write、Edit、Glob、Grep 命令,无需手动确认。确定要开启吗?'
64
- );
65
- if (!ok) {
66
- const prev = document.querySelector(`input[name="approval-mode"][value="${approvalMode}"]`);
67
- if (prev) prev.checked = true;
68
- return;
69
- }
70
- }
71
- setApprovalMode(mode);
72
- });
73
- });
74
- }
1
+ // ============================================================
2
+ // Settings
3
+ // ============================================================
4
+ import { $ } from './utils.js';
5
+ import { S, approvalMode, setApprovalModeValue, themeMode, setThemeModeValue } from './state.js';
6
+ import { showConfirm } from './confirm.js';
7
+ import { updateSettingsCwd } from './dir-picker.js';
8
+
9
+ function updateApprovalActive() {
10
+ document.querySelectorAll('#approval-options .settings-opt').forEach(el => {
11
+ el.classList.toggle('active', el.dataset.mode === approvalMode);
12
+ });
13
+ }
14
+
15
+ function updateThemeActive() {
16
+ document.querySelectorAll('#theme-options .settings-opt').forEach(el => {
17
+ el.classList.toggle('active', el.dataset.themeMode === themeMode);
18
+ });
19
+ }
20
+
21
+ function setApprovalMode(mode) {
22
+ setApprovalModeValue(mode);
23
+ localStorage.setItem('approvalMode', mode);
24
+ updateApprovalActive();
25
+ if (S.ws && S.ws.readyState === WebSocket.OPEN) {
26
+ S.ws.send(JSON.stringify({ type: 'set_approval_mode', mode }));
27
+ }
28
+ }
29
+
30
+ function applyTheme(mode) {
31
+ setThemeModeValue(mode);
32
+ localStorage.setItem('theme', mode);
33
+ if (mode === 'light' || mode === 'dark') {
34
+ document.documentElement.setAttribute('data-theme', mode);
35
+ } else {
36
+ document.documentElement.removeAttribute('data-theme');
37
+ }
38
+ updateThemeActive();
39
+ }
40
+
41
+ export function initSettingsValues() {
42
+ const approvalRadio = document.querySelector(`input[name="approval-mode"][value="${approvalMode}"]`);
43
+ if (approvalRadio) approvalRadio.checked = true;
44
+ updateApprovalActive();
45
+
46
+ const themeRadio = document.querySelector(`input[name="theme-mode"][value="${themeMode}"]`);
47
+ if (themeRadio) themeRadio.checked = true;
48
+ updateThemeActive();
49
+ }
50
+
51
+ function openSettings() {
52
+ initSettingsValues();
53
+ updateSettingsCwd();
54
+ $('settings-overlay').classList.add('visible');
55
+ }
56
+
57
+ function closeSettings() {
58
+ $('settings-overlay').classList.remove('visible');
59
+ }
60
+
61
+ export { closeSettings };
62
+
63
+ export function initSettings() {
64
+ $('btn-settings').addEventListener('click', openSettings);
65
+ $('settings-close').addEventListener('click', closeSettings);
66
+ $('settings-overlay').addEventListener('click', e => {
67
+ if (e.target === $('settings-overlay')) closeSettings();
68
+ });
69
+
70
+ document.querySelectorAll('input[name="approval-mode"]').forEach(radio => {
71
+ radio.addEventListener('change', async (e) => {
72
+ const mode = e.target.value;
73
+ if (mode === 'all') {
74
+ const ok = await showConfirm(
75
+ '全部自动审批将允许所有命令(包括 Bash、系统命令)无需确认直接执行,这可能存在风险。确定要开启吗?'
76
+ );
77
+ if (!ok) {
78
+ const prev = document.querySelector(`input[name="approval-mode"][value="${approvalMode}"]`);
79
+ if (prev) prev.checked = true;
80
+ return;
81
+ }
82
+ } else if (mode === 'partial') {
83
+ const ok = await showConfirm(
84
+ '部分自动审批将自动放行 Read、Write、Edit、Glob、Grep 命令,无需手动确认。确定要开启吗?'
85
+ );
86
+ if (!ok) {
87
+ const prev = document.querySelector(`input[name="approval-mode"][value="${approvalMode}"]`);
88
+ if (prev) prev.checked = true;
89
+ return;
90
+ }
91
+ }
92
+ setApprovalMode(mode);
93
+ });
94
+ });
95
+
96
+ document.querySelectorAll('input[name="theme-mode"]').forEach(radio => {
97
+ radio.addEventListener('change', (e) => {
98
+ applyTheme(e.target.value);
99
+ });
100
+ });
101
+ }
@@ -50,6 +50,7 @@ export let serverCacheAddr = '';
50
50
  export let serverToken = '';
51
51
  export let pendingImage = null;
52
52
  export let approvalMode = localStorage.getItem('approvalMode') || 'default';
53
+ export let themeMode = localStorage.getItem('theme') || 'system';
53
54
 
54
55
  export function setServerAddr(v) { serverAddr = v; }
55
56
  export function setServerWsUrl(v) { serverWsUrl = v; }
@@ -57,3 +58,4 @@ export function setServerCacheAddr(v) { serverCacheAddr = v; }
57
58
  export function setServerToken(v) { serverToken = v; }
58
59
  export function setPendingImage(v) { pendingImage = v; }
59
60
  export function setApprovalModeValue(v) { approvalMode = v; }
61
+ export function setThemeModeValue(v) { themeMode = v; }
@@ -21,7 +21,7 @@ import { showPermission, dismissPermissionById, clearPermissions } from './permi
21
21
  import { handleUploadStatus, updateImagePreviewUi } from './image-upload.js';
22
22
  import { renderSessionList } from './sessions.js';
23
23
  import { renderDirBrowser, updateSettingsCwd } from './dir-picker.js';
24
- import { presentNextPendingInteraction } from './interactions.js';
24
+ import { presentNextPendingInteraction, handleQuestionSubmissionError } from './interactions.js';
25
25
 
26
26
  export function isAuthReadyMessage(msg) {
27
27
  return !!msg && (
@@ -370,12 +370,15 @@ export function connect() {
370
370
  if (m.cwd) { S.cwd = m.cwd; updateHeaderInfo(); }
371
371
  if ('sessionId' in m) await syncSessionState(m.sessionId, m.lastSeq);
372
372
  }
373
- else if (m.type === 'turn_state') {
374
- if (S.replaying) cacheTurnState(m);
375
- else applyTurnState(m, 'turn_state');
376
- }
377
- else if (m.type === 'pty_exit') { setStatus('disconnected'); if (S.waiting) setWaiting(false, 'pty_exit'); }
378
- else if (m.type === 'permission_request') showPermission(m);
373
+ else if (m.type === 'turn_state') {
374
+ if (S.replaying) cacheTurnState(m);
375
+ else applyTurnState(m, 'turn_state');
376
+ }
377
+ else if (m.type === 'question_submission_error') {
378
+ handleQuestionSubmissionError(m.toolUseId, m.error);
379
+ }
380
+ else if (m.type === 'pty_exit') { setStatus('disconnected'); if (S.waiting) setWaiting(false, 'pty_exit'); }
381
+ else if (m.type === 'permission_request') showPermission(m);
379
382
  else if (m.type === 'permission_resolved') dismissPermissionById(m.id);
380
383
  else if (m.type === 'clear_permissions') clearPermissions();
381
384
  else if (m.type === 'sessions') {