aicodeman 1.8.3 → 1.9.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.
- package/README.md +80 -103
- package/README.zh-CN.md +80 -103
- package/dist/types/common.d.ts +25 -0
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/common.js +1 -0
- package/dist/types/common.js.map +1 -1
- package/dist/web/middleware/auth.d.ts.map +1 -1
- package/dist/web/middleware/auth.js +39 -1
- package/dist/web/middleware/auth.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.adc992cd.js.gz +0 -0
- package/dist/web/public/constants.e7175b95.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/i18n.4dcf1b87.js.gz +0 -0
- package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
- package/dist/web/public/index.html +10 -7
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.63794d0b.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.3f91acef.js → keyboard-accessory.9936227d.js} +361 -2
- package/dist/web/public/keyboard-accessory.9936227d.js.br +0 -0
- package/dist/web/public/keyboard-accessory.9936227d.js.gz +0 -0
- package/dist/web/public/mobile-handlers.bc2b8c1d.js.gz +0 -0
- package/dist/web/public/mobile.40e2d64e.css +1 -0
- package/dist/web/public/mobile.40e2d64e.css.br +0 -0
- package/dist/web/public/mobile.40e2d64e.css.gz +0 -0
- package/dist/web/public/notification-manager.fca811fd.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/panels-ui.3910e1e2.js.gz +0 -0
- package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
- package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
- package/dist/web/public/respawn-ui.2d249da9.js.gz +0 -0
- package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
- package/dist/web/public/{session-ui.fd39c53c.js → session-ui.ab6dd9aa.js} +15 -15
- package/dist/web/public/session-ui.ab6dd9aa.js.br +0 -0
- package/dist/web/public/session-ui.ab6dd9aa.js.gz +0 -0
- package/dist/web/public/settings-ui.b8def032.js.gz +0 -0
- package/dist/web/public/styles.30e64547.css +1 -0
- package/dist/web/public/styles.30e64547.css.br +0 -0
- package/dist/web/public/styles.30e64547.css.gz +0 -0
- package/dist/web/public/subagent-windows.69b60c35.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/{terminal-ui.feaf75c2.js → terminal-ui.f3a51974.js} +1 -1
- package/dist/web/public/terminal-ui.f3a51974.js.br +0 -0
- package/dist/web/public/terminal-ui.f3a51974.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/dist/web/public/webview-tabs.js +43 -13
- package/dist/web/public/webview-tabs.js.br +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +313 -8
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +173 -99
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +10 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +30 -0
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +13 -6
- package/dist/web/server.js.map +1 -1
- package/dist/web/webview-proxy.d.ts +23 -6
- package/dist/web/webview-proxy.d.ts.map +1 -1
- package/dist/web/webview-proxy.js +154 -6
- package/dist/web/webview-proxy.js.map +1 -1
- package/package.json +17 -6
- package/dist/web/public/keyboard-accessory.3f91acef.js.br +0 -0
- package/dist/web/public/keyboard-accessory.3f91acef.js.gz +0 -0
- package/dist/web/public/mobile.6153d275.css +0 -1
- package/dist/web/public/mobile.6153d275.css.br +0 -0
- package/dist/web/public/mobile.6153d275.css.gz +0 -0
- package/dist/web/public/session-ui.fd39c53c.js.br +0 -0
- package/dist/web/public/session-ui.fd39c53c.js.gz +0 -0
- package/dist/web/public/styles.bd210c71.css +0 -1
- package/dist/web/public/styles.bd210c71.css.br +0 -0
- package/dist/web/public/styles.bd210c71.css.gz +0 -0
- package/dist/web/public/terminal-ui.feaf75c2.js.br +0 -0
- package/dist/web/public/terminal-ui.feaf75c2.js.gz +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Mobile keyboard accessory bar and modal focus trap.
|
|
3
3
|
*
|
|
4
|
-
* Defines
|
|
4
|
+
* Defines three exports:
|
|
5
5
|
*
|
|
6
6
|
* - KeyboardAccessoryBar (singleton object) — Quick action buttons shown above the virtual
|
|
7
7
|
* keyboard on mobile: arrow up/down, /init, /clear, /compact, paste, Esc, and dismiss.
|
|
@@ -10,12 +10,15 @@
|
|
|
10
10
|
* Destructive actions (/clear, /compact) require double-tap confirmation (2s amber state).
|
|
11
11
|
* Commands are sent as text + Enter separately for Ink compatibility.
|
|
12
12
|
* Only initializes on touch devices (MobileDetection.isTouchDevice guard).
|
|
13
|
+
* - PathPicker (singleton object) — Lazy server-side file/folder browser shared
|
|
14
|
+
* by Link Existing and the extended mobile keyboard bar.
|
|
13
15
|
*
|
|
14
16
|
* - FocusTrap (class) — Traps Tab/Shift+Tab keyboard focus within a modal element.
|
|
15
17
|
* Saves and restores previously focused element on deactivate. Used by Ralph wizard
|
|
16
18
|
* and other modal dialogs.
|
|
17
19
|
*
|
|
18
20
|
* @globals {object} KeyboardAccessoryBar
|
|
21
|
+
* @globals {object} PathPicker
|
|
19
22
|
* @globals {class} FocusTrap
|
|
20
23
|
*
|
|
21
24
|
* @dependency mobile-handlers.js (MobileDetection.isTouchDevice)
|
|
@@ -26,6 +29,338 @@
|
|
|
26
29
|
// Codeman — Keyboard accessory bar and focus trap for modals
|
|
27
30
|
// Loaded after mobile-handlers.js, before app.js
|
|
28
31
|
|
|
32
|
+
// ═══════════════════════════════════════════════════════════════
|
|
33
|
+
// Shared Filesystem Path Picker
|
|
34
|
+
// ═══════════════════════════════════════════════════════════════
|
|
35
|
+
|
|
36
|
+
const PathPicker = {
|
|
37
|
+
overlay: null,
|
|
38
|
+
_options: null,
|
|
39
|
+
_selectedPath: '',
|
|
40
|
+
_previousFocus: null,
|
|
41
|
+
_keydownHandler: null,
|
|
42
|
+
_loadSequence: 0,
|
|
43
|
+
_previewOverlay: null,
|
|
44
|
+
_previewRequestSequence: 0,
|
|
45
|
+
_previewPreviousFocus: null,
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Open the lazy filesystem browser.
|
|
49
|
+
* @param {{sessionId?: string, initialPath?: string, directoriesOnly?: boolean,
|
|
50
|
+
* title?: string, onSelect: (path: string) => void}} options
|
|
51
|
+
*/
|
|
52
|
+
open(options) {
|
|
53
|
+
this.close(false);
|
|
54
|
+
this._options = options;
|
|
55
|
+
this._selectedPath = '';
|
|
56
|
+
this._previousFocus = document.activeElement;
|
|
57
|
+
this._previousFocus?.blur?.();
|
|
58
|
+
|
|
59
|
+
const overlay = document.createElement('div');
|
|
60
|
+
overlay.className = 'path-picker-overlay';
|
|
61
|
+
overlay.setAttribute('role', 'dialog');
|
|
62
|
+
overlay.setAttribute('aria-modal', 'true');
|
|
63
|
+
overlay.setAttribute('aria-label', options.title || 'Select a path');
|
|
64
|
+
overlay.innerHTML = `
|
|
65
|
+
<div class="path-picker-dialog">
|
|
66
|
+
<div class="path-picker-header">
|
|
67
|
+
<strong class="path-picker-title"></strong>
|
|
68
|
+
<button type="button" class="path-picker-close" aria-label="Close">×</button>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="path-picker-roots-row">
|
|
71
|
+
<label for="pathPickerRoot">Location</label>
|
|
72
|
+
<select id="pathPickerRoot" class="path-picker-roots"></select>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="path-picker-nav">
|
|
75
|
+
<button type="button" class="path-picker-up" title="Parent folder" aria-label="Parent folder">↑</button>
|
|
76
|
+
<div class="path-picker-current" title="Current folder"></div>
|
|
77
|
+
<button type="button" class="path-picker-refresh" title="Refresh" aria-label="Refresh">↻</button>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="path-picker-status" aria-live="polite">Loading...</div>
|
|
80
|
+
<div class="path-picker-list" role="listbox"></div>
|
|
81
|
+
<div class="path-picker-selection">
|
|
82
|
+
<span class="path-picker-selection-label">Selected</span>
|
|
83
|
+
<span class="path-picker-selection-value">None</span>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="path-picker-actions">
|
|
86
|
+
<button type="button" class="path-picker-current-select">Select Current Folder</button>
|
|
87
|
+
<span class="path-picker-action-spacer"></span>
|
|
88
|
+
<button type="button" class="path-picker-cancel">Cancel</button>
|
|
89
|
+
<button type="button" class="path-picker-confirm" disabled>Select</button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>`;
|
|
92
|
+
|
|
93
|
+
this.overlay = overlay;
|
|
94
|
+
overlay.querySelector('.path-picker-title').textContent = options.title || 'Select a Path';
|
|
95
|
+
overlay.querySelector('.path-picker-close').addEventListener('click', () => this.close(true));
|
|
96
|
+
overlay.querySelector('.path-picker-cancel').addEventListener('click', () => this.close(true));
|
|
97
|
+
overlay.querySelector('.path-picker-confirm').addEventListener('click', () => this.confirm());
|
|
98
|
+
overlay.querySelector('.path-picker-current-select').addEventListener('click', () => {
|
|
99
|
+
const current = overlay.querySelector('.path-picker-current').textContent;
|
|
100
|
+
if (current) this.select(current);
|
|
101
|
+
});
|
|
102
|
+
overlay.querySelector('.path-picker-refresh').addEventListener('click', () => this.load());
|
|
103
|
+
overlay.querySelector('.path-picker-up').addEventListener('click', () => {
|
|
104
|
+
const parent = overlay.querySelector('.path-picker-up').dataset.parent;
|
|
105
|
+
if (parent) this.load(parent);
|
|
106
|
+
});
|
|
107
|
+
overlay.querySelector('.path-picker-roots').addEventListener('change', (event) => this.load(event.target.value));
|
|
108
|
+
overlay.addEventListener('click', (event) => {
|
|
109
|
+
if (event.target === overlay) this.close(true);
|
|
110
|
+
});
|
|
111
|
+
this._keydownHandler = (event) => {
|
|
112
|
+
if (event.key === 'Escape') {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
if (this._previewOverlay) this.closePreview(true);
|
|
115
|
+
else this.close(true);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
document.addEventListener('keydown', this._keydownHandler);
|
|
119
|
+
document.body.appendChild(overlay);
|
|
120
|
+
this.load(options.initialPath || '');
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
async load(path) {
|
|
124
|
+
if (!this.overlay || !this._options) return;
|
|
125
|
+
const loadSequence = ++this._loadSequence;
|
|
126
|
+
const list = this.overlay.querySelector('.path-picker-list');
|
|
127
|
+
const status = this.overlay.querySelector('.path-picker-status');
|
|
128
|
+
list.replaceChildren();
|
|
129
|
+
status.textContent = 'Loading...';
|
|
130
|
+
|
|
131
|
+
const params = new URLSearchParams();
|
|
132
|
+
if (path) params.set('path', path);
|
|
133
|
+
if (this._options.sessionId) params.set('sessionId', this._options.sessionId);
|
|
134
|
+
try {
|
|
135
|
+
const response = await fetch(`/api/filesystem/browse?${params.toString()}`);
|
|
136
|
+
const result = await response.json();
|
|
137
|
+
if (!response.ok || !result.success) throw new Error(result.error || 'Failed to browse this folder');
|
|
138
|
+
if (!this.overlay || loadSequence !== this._loadSequence) return;
|
|
139
|
+
this.render(result.data);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (!this.overlay || loadSequence !== this._loadSequence) return;
|
|
142
|
+
if (path) {
|
|
143
|
+
this.load('');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
status.textContent = error.message || 'Failed to browse this folder';
|
|
147
|
+
status.classList.add('error');
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
render(data) {
|
|
152
|
+
const rootSelect = this.overlay.querySelector('.path-picker-roots');
|
|
153
|
+
rootSelect.replaceChildren();
|
|
154
|
+
for (const root of data.roots) {
|
|
155
|
+
const option = document.createElement('option');
|
|
156
|
+
option.value = root.path;
|
|
157
|
+
option.textContent = `${root.label} — ${root.path}`;
|
|
158
|
+
option.selected = data.path === root.path || data.root === root.path;
|
|
159
|
+
rootSelect.appendChild(option);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.overlay.querySelector('.path-picker-current').textContent = data.path;
|
|
163
|
+
const up = this.overlay.querySelector('.path-picker-up');
|
|
164
|
+
up.dataset.parent = data.parent || '';
|
|
165
|
+
up.disabled = !data.parent;
|
|
166
|
+
const status = this.overlay.querySelector('.path-picker-status');
|
|
167
|
+
status.classList.remove('error');
|
|
168
|
+
status.textContent = data.entries.length === 0
|
|
169
|
+
? 'This folder is empty'
|
|
170
|
+
: `${data.entries.length} item${data.entries.length === 1 ? '' : 's'}${data.truncated ? ' (first 500)' : ''}`;
|
|
171
|
+
|
|
172
|
+
const list = this.overlay.querySelector('.path-picker-list');
|
|
173
|
+
list.replaceChildren();
|
|
174
|
+
for (const entry of data.entries) {
|
|
175
|
+
const row = document.createElement('div');
|
|
176
|
+
row.className = 'path-picker-item';
|
|
177
|
+
if (entry.type === 'file' && this._options.directoriesOnly && !entry.previewKind) {
|
|
178
|
+
row.classList.add('not-selectable');
|
|
179
|
+
}
|
|
180
|
+
row.dataset.path = entry.path;
|
|
181
|
+
row.dataset.type = entry.type;
|
|
182
|
+
row.setAttribute('role', 'option');
|
|
183
|
+
|
|
184
|
+
const open = document.createElement('button');
|
|
185
|
+
open.type = 'button';
|
|
186
|
+
open.className = 'path-picker-item-main';
|
|
187
|
+
const icon = document.createElement('span');
|
|
188
|
+
icon.className = 'path-picker-item-icon';
|
|
189
|
+
icon.textContent = entry.type === 'directory' ? '\uD83D\uDCC1' : '\uD83D\uDCC4';
|
|
190
|
+
const name = document.createElement('span');
|
|
191
|
+
name.className = 'path-picker-item-name';
|
|
192
|
+
name.textContent = entry.name;
|
|
193
|
+
open.append(icon, name);
|
|
194
|
+
if (entry.symlink) {
|
|
195
|
+
const link = document.createElement('span');
|
|
196
|
+
link.className = 'path-picker-item-link';
|
|
197
|
+
link.textContent = '\u2197';
|
|
198
|
+
open.appendChild(link);
|
|
199
|
+
}
|
|
200
|
+
if (entry.type === 'directory') {
|
|
201
|
+
const chevron = document.createElement('span');
|
|
202
|
+
chevron.className = 'path-picker-item-chevron';
|
|
203
|
+
chevron.textContent = '\u203A';
|
|
204
|
+
open.appendChild(chevron);
|
|
205
|
+
open.addEventListener('click', () => this.load(entry.path));
|
|
206
|
+
} else if (entry.previewKind) {
|
|
207
|
+
const preview = document.createElement('span');
|
|
208
|
+
preview.className = 'path-picker-item-preview';
|
|
209
|
+
preview.textContent = '\uD83D\uDC41';
|
|
210
|
+
open.appendChild(preview);
|
|
211
|
+
open.title = `Preview ${entry.name}`;
|
|
212
|
+
open.setAttribute('aria-label', `Preview ${entry.name}`);
|
|
213
|
+
open.addEventListener('click', () => this.openPreview(entry));
|
|
214
|
+
} else if (!this._options.directoriesOnly) {
|
|
215
|
+
open.addEventListener('click', () => this.select(entry.path));
|
|
216
|
+
} else {
|
|
217
|
+
open.disabled = true;
|
|
218
|
+
}
|
|
219
|
+
row.appendChild(open);
|
|
220
|
+
|
|
221
|
+
if (entry.type === 'directory' || !this._options.directoriesOnly) {
|
|
222
|
+
const choose = document.createElement('button');
|
|
223
|
+
choose.type = 'button';
|
|
224
|
+
choose.className = 'path-picker-item-select';
|
|
225
|
+
choose.textContent = 'Choose';
|
|
226
|
+
choose.addEventListener('click', () => this.select(entry.path));
|
|
227
|
+
row.appendChild(choose);
|
|
228
|
+
}
|
|
229
|
+
list.appendChild(row);
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
select(path) {
|
|
234
|
+
if (!this.overlay) return;
|
|
235
|
+
this._selectedPath = path;
|
|
236
|
+
this.overlay.querySelector('.path-picker-selection-value').textContent = path;
|
|
237
|
+
this.overlay.querySelector('.path-picker-confirm').disabled = false;
|
|
238
|
+
this.overlay.querySelectorAll('.path-picker-item').forEach((row) => {
|
|
239
|
+
const selected = row.dataset.path === path;
|
|
240
|
+
row.classList.toggle('selected', selected);
|
|
241
|
+
row.setAttribute('aria-selected', selected ? 'true' : 'false');
|
|
242
|
+
});
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
openPreview(entry) {
|
|
246
|
+
this.closePreview(false);
|
|
247
|
+
this._previewPreviousFocus = document.activeElement;
|
|
248
|
+
const requestSequence = ++this._previewRequestSequence;
|
|
249
|
+
const params = new URLSearchParams({ path: entry.path });
|
|
250
|
+
if (this._options?.sessionId) params.set('sessionId', this._options.sessionId);
|
|
251
|
+
const previewUrl = `/api/filesystem/preview?${params.toString()}`;
|
|
252
|
+
|
|
253
|
+
const overlay = document.createElement('div');
|
|
254
|
+
overlay.className = 'path-preview-overlay';
|
|
255
|
+
overlay.setAttribute('role', 'dialog');
|
|
256
|
+
overlay.setAttribute('aria-modal', 'true');
|
|
257
|
+
overlay.setAttribute('aria-label', `Preview ${entry.name}`);
|
|
258
|
+
overlay.innerHTML = `
|
|
259
|
+
<div class="path-preview-dialog">
|
|
260
|
+
<div class="path-preview-header">
|
|
261
|
+
<div class="path-preview-heading">
|
|
262
|
+
<strong class="path-preview-title"></strong>
|
|
263
|
+
<span class="path-preview-path"></span>
|
|
264
|
+
</div>
|
|
265
|
+
<a class="path-preview-open" target="_blank" rel="noopener noreferrer">Open</a>
|
|
266
|
+
<button type="button" class="path-preview-close" aria-label="Close preview">×</button>
|
|
267
|
+
</div>
|
|
268
|
+
<div class="path-preview-body"><div class="path-preview-loading">Loading preview...</div></div>
|
|
269
|
+
</div>`;
|
|
270
|
+
overlay.querySelector('.path-preview-title').textContent = entry.name;
|
|
271
|
+
overlay.querySelector('.path-preview-path').textContent = entry.path;
|
|
272
|
+
overlay.querySelector('.path-preview-open').href = previewUrl;
|
|
273
|
+
overlay.querySelector('.path-preview-close').addEventListener('click', () => this.closePreview(true));
|
|
274
|
+
overlay.addEventListener('click', (event) => {
|
|
275
|
+
if (event.target === overlay) this.closePreview(true);
|
|
276
|
+
});
|
|
277
|
+
document.body.appendChild(overlay);
|
|
278
|
+
this._previewOverlay = overlay;
|
|
279
|
+
|
|
280
|
+
const body = overlay.querySelector('.path-preview-body');
|
|
281
|
+
if (entry.previewKind === 'image') {
|
|
282
|
+
const image = document.createElement('img');
|
|
283
|
+
image.className = 'path-preview-image';
|
|
284
|
+
image.alt = entry.name;
|
|
285
|
+
image.addEventListener('load', () => body.querySelector('.path-preview-loading')?.remove());
|
|
286
|
+
image.addEventListener('error', () => this.showPreviewError('Image preview failed to load'));
|
|
287
|
+
image.src = previewUrl;
|
|
288
|
+
body.appendChild(image);
|
|
289
|
+
} else if (entry.previewKind === 'text') {
|
|
290
|
+
fetch(previewUrl)
|
|
291
|
+
.then(async (response) => {
|
|
292
|
+
const content = await response.text();
|
|
293
|
+
if (!response.ok) {
|
|
294
|
+
let message = 'Text preview failed to load';
|
|
295
|
+
try {
|
|
296
|
+
message = JSON.parse(content).error || message;
|
|
297
|
+
} catch {}
|
|
298
|
+
throw new Error(message);
|
|
299
|
+
}
|
|
300
|
+
return content;
|
|
301
|
+
})
|
|
302
|
+
.then((content) => {
|
|
303
|
+
if (!this._previewOverlay || requestSequence !== this._previewRequestSequence) return;
|
|
304
|
+
const pre = document.createElement('pre');
|
|
305
|
+
pre.className = 'path-preview-text';
|
|
306
|
+
pre.textContent = content;
|
|
307
|
+
body.replaceChildren(pre);
|
|
308
|
+
})
|
|
309
|
+
.catch((error) => {
|
|
310
|
+
if (requestSequence === this._previewRequestSequence) this.showPreviewError(error.message);
|
|
311
|
+
});
|
|
312
|
+
} else {
|
|
313
|
+
const frame = document.createElement('iframe');
|
|
314
|
+
frame.className = 'path-preview-frame';
|
|
315
|
+
frame.title = entry.name;
|
|
316
|
+
frame.addEventListener('load', () => body.querySelector('.path-preview-loading')?.remove());
|
|
317
|
+
frame.src = previewUrl;
|
|
318
|
+
body.appendChild(frame);
|
|
319
|
+
}
|
|
320
|
+
overlay.querySelector('.path-preview-close').focus();
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
showPreviewError(message) {
|
|
324
|
+
const body = this._previewOverlay?.querySelector('.path-preview-body');
|
|
325
|
+
if (!body) return;
|
|
326
|
+
const error = document.createElement('div');
|
|
327
|
+
error.className = 'path-preview-error';
|
|
328
|
+
error.textContent = message || 'Preview failed to load';
|
|
329
|
+
body.replaceChildren(error);
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
closePreview(restoreFocus = true) {
|
|
333
|
+
this._previewRequestSequence += 1;
|
|
334
|
+
this._previewOverlay?.remove();
|
|
335
|
+
this._previewOverlay = null;
|
|
336
|
+
const previousFocus = this._previewPreviousFocus;
|
|
337
|
+
this._previewPreviousFocus = null;
|
|
338
|
+
if (restoreFocus) previousFocus?.focus?.();
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
confirm() {
|
|
342
|
+
if (!this._selectedPath || !this._options) return;
|
|
343
|
+
const selectedPath = this._selectedPath;
|
|
344
|
+
const onSelect = this._options.onSelect;
|
|
345
|
+
this.close(false);
|
|
346
|
+
onSelect(selectedPath);
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
close(restoreFocus = true) {
|
|
350
|
+
if (this._keydownHandler) document.removeEventListener('keydown', this._keydownHandler);
|
|
351
|
+
this._keydownHandler = null;
|
|
352
|
+
this._loadSequence += 1;
|
|
353
|
+
this.closePreview(false);
|
|
354
|
+
this.overlay?.remove();
|
|
355
|
+
this.overlay = null;
|
|
356
|
+
const previousFocus = this._previousFocus;
|
|
357
|
+
this._previousFocus = null;
|
|
358
|
+
this._options = null;
|
|
359
|
+
this._selectedPath = '';
|
|
360
|
+
if (restoreFocus) previousFocus?.focus?.();
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
|
|
29
364
|
// ═══════════════════════════════════════════════════════════════
|
|
30
365
|
// Mobile Keyboard Accessory Bar
|
|
31
366
|
// ═══════════════════════════════════════════════════════════════
|
|
@@ -92,6 +427,8 @@ const KeyboardAccessoryBar = {
|
|
|
92
427
|
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"/>
|
|
93
428
|
</svg>
|
|
94
429
|
</button>
|
|
430
|
+
<button class="accessory-btn" data-action="pick-path" title="Insert a file or folder path">📁 Path</button>
|
|
431
|
+
<button class="accessory-btn" data-action="clear-input" title="Clear the current unsent input">⌫ All</button>
|
|
95
432
|
<button class="accessory-btn" data-action="tab" title="Tab">Tab</button>
|
|
96
433
|
<button class="accessory-btn" data-action="shift-tab" title="Shift+Tab">⇧Tab</button>
|
|
97
434
|
<button class="accessory-btn" data-action="effort-max" title="/effort max">Max</button>
|
|
@@ -128,7 +465,7 @@ const KeyboardAccessoryBar = {
|
|
|
128
465
|
this.handleAction(action, btn);
|
|
129
466
|
|
|
130
467
|
// Refocus terminal so keyboard stays open (tap blurs terminal → keyboard dismisses → toolbar shifts)
|
|
131
|
-
const refocusActions = new Set(['scroll-up', 'scroll-down', 'arrow-left', 'arrow-right', 'tab', 'shift-tab', 'ctrl-o', 'opt-enter', 'esc', 'effort-max']);
|
|
468
|
+
const refocusActions = new Set(['scroll-up', 'scroll-down', 'arrow-left', 'arrow-right', 'tab', 'shift-tab', 'ctrl-o', 'opt-enter', 'esc', 'effort-max', 'clear-input']);
|
|
132
469
|
if (refocusActions.has(action) ||
|
|
133
470
|
((action === 'clear' || action === 'compact') && this._confirmAction)) {
|
|
134
471
|
if (typeof app !== 'undefined' && app.terminal) {
|
|
@@ -207,6 +544,12 @@ const KeyboardAccessoryBar = {
|
|
|
207
544
|
case 'paste':
|
|
208
545
|
this.pasteFromClipboard();
|
|
209
546
|
break;
|
|
547
|
+
case 'pick-path':
|
|
548
|
+
this.pickPath();
|
|
549
|
+
break;
|
|
550
|
+
case 'clear-input':
|
|
551
|
+
app.clearTerminalInput?.();
|
|
552
|
+
break;
|
|
210
553
|
case 'dismiss':
|
|
211
554
|
// Blur active element to dismiss keyboard
|
|
212
555
|
document.activeElement?.blur();
|
|
@@ -265,6 +608,22 @@ const KeyboardAccessoryBar = {
|
|
|
265
608
|
}).catch(() => {});
|
|
266
609
|
},
|
|
267
610
|
|
|
611
|
+
/** Browse the active session's workspace and insert a selected path without Enter. */
|
|
612
|
+
pickPath() {
|
|
613
|
+
if (!app.activeSessionId) return;
|
|
614
|
+
const session = app.sessions?.get(app.activeSessionId);
|
|
615
|
+
PathPicker.open({
|
|
616
|
+
title: 'Insert File or Folder Path',
|
|
617
|
+
sessionId: app.activeSessionId,
|
|
618
|
+
initialPath: session?.workingDir || '',
|
|
619
|
+
directoriesOnly: false,
|
|
620
|
+
onSelect: (path) => {
|
|
621
|
+
app.insertTerminalText?.(path);
|
|
622
|
+
setTimeout(() => app.terminal?.focus(), 100);
|
|
623
|
+
},
|
|
624
|
+
});
|
|
625
|
+
},
|
|
626
|
+
|
|
268
627
|
/** Show a paste overlay for iOS compatibility.
|
|
269
628
|
* Handles three input paths from one dialog:
|
|
270
629
|
* - Text: long-press the textarea → Paste → Send (unchanged).
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
html.mobile-init .header-font-controls,html.mobile-init .header-system-stats,html.mobile-init .header-tokens,html.mobile-init .monitor-panel,html.mobile-init .subagents-panel,html.mobile-init .project-insights-panel,html.mobile-init .file-browser-panel{display:none!important}@media(max-width:768px){input,textarea,select{font-size:16px!important}html{touch-action:manipulation}.session-tab .tab-detach{display:none!important}}@media(max-width:768px)and (min-width:430px){.header{position:fixed;top:0;left:0;right:0;min-height:48px;max-height:48px;padding:.35rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));background:#0a0a0a;border-bottom:1px solid rgba(255,255,255,.08);contain:none;overflow:visible;z-index:1200}.ios-device .header{padding-top:calc(.35rem + var(--safe-area-top));min-height:calc(48px + var(--safe-area-top));max-height:calc(48px + var(--safe-area-top))}.app{padding-top:54px}.ios-device .app{padding-top:calc(54px + var(--safe-area-top))}.header-font-controls{gap:.15rem;padding:.15rem .25rem}.header-font-controls .btn-icon-sm{width:18px;height:18px}.header-system-stats{font-size:.6rem;gap:.25rem}.header-right{gap:.35rem}.btn-icon-header:not(.btn-sm){width:44px;height:44px}.session-tabs,.session-tabs.tabs-two-rows{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:none;max-height:52px;gap:3px}.session-tabs::-webkit-scrollbar{display:none}.session-tab{padding:.4rem .6rem;font-size:.75rem;min-height:40px}.session-tab .tab-name{max-width:80px}.toolbar{padding:.4rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));gap:.4rem}.tab-count-group{display:none}.btn-toolbar{padding:.4rem .8rem;font-size:.8rem;min-height:40px}.case-select-group{max-width:none}.case-combobox{width:160px}.toolbar-select{font-size:.75rem}.monitor-panel,.subagents-panel{width:100%;max-width:100%;left:0;right:0;border-radius:8px 8px 0 0;max-height:40vh}.project-insights-panel{max-width:280px;font-size:.7rem}.modal{z-index:1300}.command-palette-modal{padding:10vh .75rem 0}.command-palette-shell{width:100%;max-height:74vh}.command-palette-input-row{grid-template-columns:20px minmax(0,1fr)}.command-palette-input-row kbd{display:none}.command-palette-item{min-height:56px}.modal-tabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;flex-wrap:nowrap}.modal-tabs::-webkit-scrollbar{display:none}.modal-tab-btn{padding:.4rem .75rem;font-size:.7rem;white-space:nowrap;flex-shrink:0}.settings-grid{gap:.4rem .75rem}.settings-item{font-size:.7rem}.event-type-grid{grid-template-columns:1fr 40px 40px 40px;gap:5px 6px}.event-label{font-size:.7rem}.subagent-window{width:320px;height:280px;min-width:240px;min-height:160px}.subagent-window-header{padding:.35rem .5rem}.subagent-window-title .id{font-size:.7rem;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.subagent-window-title .status{font-size:.55rem}.subagent-window-body{font-size:.7rem}.respawn-banner{padding:.25rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));font-size:.65rem}.respawn-compact-layout{gap:.75rem}.respawn-status-row1{gap:.4rem}.respawn-action-log{max-height:2.6em;font-size:.6rem}.respawn-countdown-timer{font-size:.55rem}.respawn-timer-bar{width:24px}.toolbar-center .btn-toolbar.btn-voice{display:flex!important}.toolbar{padding:0 .5rem;gap:.5rem}.toolbar-left,.toolbar-right,.toolbar-group{gap:.5rem}.btn-toolbar{padding:.4rem .75rem;font-size:.75rem;min-height:unset}}@media(max-width:430px){.header-brand{padding-right:.25rem;margin-right:.2rem;border-right:none}.header-brand .logo{font-size:.85rem}.header-brand .logo .logo-text{display:none}.header-brand .logo .logo-compact{display:inline}.header-font-controls{gap:.1rem;padding:.1rem .2rem}.header-font-controls .btn-icon-sm{width:16px;height:16px}.header-font-controls .font-size-display{font-size:.6rem;min-width:14px}.header-system-stats{font-size:.55rem;gap:.15rem}.header-tokens{font-size:.6rem;padding:.1rem .3rem}.header{position:fixed;top:0;left:0;right:0;min-height:36px;max-height:36px;padding:.15rem .3rem;padding-left:calc(.3rem + var(--safe-area-left));padding-right:calc(.3rem + var(--safe-area-right));gap:.15rem;overflow:hidden;background:#0a0a0a;border-bottom:1px solid rgba(255,255,255,.08);contain:none;z-index:1200}.ios-device .header{padding-top:calc(.15rem + var(--safe-area-top));min-height:calc(36px + var(--safe-area-top));max-height:calc(36px + var(--safe-area-top))}.app{padding-top:42px}.ios-device .app{padding-top:calc(42px + var(--safe-area-top))}.main{padding-bottom:calc(40px + var(--safe-area-bottom))}.ios-device.safari-browser .main{padding-bottom:calc(40px + var(--safe-area-bottom) + (100vh - var(--app-height, 100vh)))}.header-right{padding-left:.2rem;gap:.1rem;flex-shrink:0;border-left:none}.btn-icon-header{width:26px;height:26px;padding:0}.btn-icon-header svg{width:12px;height:12px}.btn-icon-header.btn-settings,.btn-icon-header.btn-lifecycle-log,.btn-icon-header.btn-away-digest,.btn-icon-header.btn-session-manager,.btn-icon-header.btn-file-viewer,.btn-admin-panel{display:none!important}.btn-voice-mobile{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;background:#1a2a3f;border:1px solid rgba(59,130,246,.3);border-radius:4px;color:#93c5fd;cursor:pointer;flex-shrink:0;order:5}.btn-voice-mobile svg{width:13px;height:13px}.btn-voice-mobile:active{background:#2a3a5f}.btn-voice-mobile.recording{background:#ef444440;border-color:#ef444499;color:#ef4444;animation:mobile-voice-pulse 1.2s ease-in-out infinite}@keyframes mobile-voice-pulse{0%,to{box-shadow:inset 0 0 0 1px #ef444459;background:#ef444433}50%{box-shadow:inset 0 0 0 2px #ef4444bf;background:#ef444459}}.btn-settings-mobile{display:inline-flex!important;align-items:center;justify-content:center;width:26px;height:26px;background:transparent;border:1px solid rgba(255,255,255,.2);border-radius:4px;color:#9ca3af;font-size:.85rem;cursor:pointer;flex-shrink:0;order:6;position:relative}.btn-settings-mobile svg{width:13px;height:13px}.btn-settings-mobile:active{background:#ffffff1a;color:#fff}.app{overflow:hidden;position:relative}.keyboard-visible .app{position:fixed;inset:0 0 auto;height:var(--app-height, 100dvh)}.session-tabs,.session-tabs.tabs-two-rows{flex:1;flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:none;max-height:36px;gap:2px;padding:0}.session-tabs::-webkit-scrollbar{display:none}.session-tab{flex-shrink:0;min-height:32px;max-height:32px;padding:.35rem .5rem;font-size:.7rem;gap:.25rem;border-radius:4px}.session-tab .tab-status{width:4px;height:4px}.session-tab .tab-name{max-width:50px;overflow:hidden;text-overflow:ellipsis}.session-tab .tab-close,.session-tab .tab-gear{display:none}.session-tab.active .tab-gear{display:inline-flex;align-items:center;justify-content:center;font-size:.65rem;line-height:1;width:32px;height:32px;margin-left:auto;opacity:.6}.session-tab.active .tab-close{display:inline-flex;align-items:center;justify-content:center;font-size:1.1rem;line-height:1;width:20px;height:18px;margin-left:-2px}.toolbar{position:fixed;bottom:var(--safe-area-bottom);left:0;right:0;height:40px;min-height:40px;max-height:40px;padding:.3rem .4rem;padding-left:calc(.4rem + var(--safe-area-left));padding-right:calc(.4rem + var(--safe-area-right));flex-wrap:nowrap;gap:.3rem;align-items:center;justify-content:space-between;background:#111;border-top:1px solid rgba(255,255,255,.1);z-index:50;transition:transform .15s ease-out;will-change:transform}.ios-device.safari-browser .toolbar{bottom:calc(var(--safe-area-bottom) + (100vh - var(--app-height, 100vh)))}.keyboard-visible.ios-device.safari-browser .toolbar{bottom:var(--safe-area-bottom)}.keyboard-visible.ios-device.safari-browser .keyboard-accessory-bar{bottom:calc(var(--safe-area-bottom) + 40px)}.toolbar-center{display:flex!important;align-items:center}.toolbar-center .btn-toolbar.btn-voice,.toolbar-right,.version-display{display:none!important}.toolbar-left{flex:1 1 0;min-width:0;align-items:center;gap:.3rem}.toolbar-left .toolbar-group{display:flex;flex:1 1 0;min-width:0;align-items:center;gap:.3rem}.toolbar-left .toolbar-group:first-child{flex:1 1 0;min-width:0;justify-content:space-between;gap:.3rem;flex-wrap:nowrap;align-items:center}.tab-count-group{display:none!important}.btn-toolbar{min-height:26px!important;max-height:26px!important;height:26px!important;padding:0 .5rem!important;font-size:.65rem!important;border-radius:4px;line-height:26px;display:inline-flex;align-items:center;justify-content:center;font-weight:500;letter-spacing:.01em;color:#fff}.run-btn-group{display:flex;flex:0 0 auto}.btn-toolbar.btn-run{flex:0 0 auto;padding:0 .6rem!important;font-weight:500;border-radius:4px 0 0 4px!important;border-right:none!important}.btn-toolbar.btn-run svg{width:10px;height:10px;margin-right:3px}.btn-toolbar.btn-run-gear{flex:0 0 auto;padding:0 .35rem!important;min-width:unset!important;border-radius:0 4px 4px 0!important;border-left:1px solid rgba(255,255,255,.15)!important}.btn-toolbar.btn-run-gear svg{width:10px;height:10px}.btn-toolbar.btn-run.mode-claude,.btn-toolbar.btn-run-gear.mode-claude{background:#1e3a5f;border-color:#3b82f64d;color:#93c5fd}.btn-toolbar.btn-run.mode-claude:active,.btn-toolbar.btn-run-gear.mode-claude:active{background:#2563eb;border-color:#3b82f680}.btn-toolbar.btn-run.mode-opencode,.btn-toolbar.btn-run-gear.mode-opencode{background:#0a2e2a;border-color:#10b9814d;color:#6ee7b7}.btn-toolbar.btn-run.mode-opencode:active,.btn-toolbar.btn-run-gear.mode-opencode:active{background:#0d4a40;border-color:#10b98180}.btn-toolbar.btn-run.mode-gemini,.btn-toolbar.btn-run-gear.mode-gemini{background:#10243f;border-color:#60a5fa4d;color:#dbeafe}.btn-toolbar.btn-run.mode-gemini:active,.btn-toolbar.btn-run-gear.mode-gemini:active{background:#174ea6;border-color:#60a5fa80}.run-mode-menu{bottom:100%;left:0;margin-bottom:6px;min-width:160px;max-width:80vw}.run-mode-option{padding:10px 12px;font-size:.8rem;cursor:pointer;-webkit-tap-highlight-color:rgba(255,255,255,.1)}.run-mode-row-btn{width:34px;height:34px;font-size:1rem;-webkit-tap-highlight-color:rgba(255,255,255,.1)}.run-mode-webview-delete{font-size:1.2rem}.run-mode-history{-webkit-overflow-scrolling:touch;touch-action:manipulation}.btn-toolbar.btn-stop{display:flex!important;flex:0 0 auto;padding:0 8px!important;min-width:unset;order:3}.btn-toolbar.btn-stop svg{width:10px;height:10px;margin-right:0}.btn-toolbar.btn-shell{display:none!important}.btn-toolbar.btn-enter{display:flex!important;flex:0 0 auto;align-items:center;justify-content:center;min-width:54px;width:54px;white-space:nowrap;padding:0 8px!important;overflow:hidden;font-size:.65rem;font-weight:600;letter-spacing:.01em;background:#1e3a5fd9!important;border:1px solid rgba(59,130,246,.45)!important;color:#dbeafe!important;order:4}.btn-toolbar.btn-enter:hover,.btn-toolbar.btn-enter:active{background:#254a7af2!important;border-color:#3b82f6b3!important;color:#fff!important}.case-select-group{display:none!important}.toolbar-left .toolbar-group:first-child{width:100%;gap:8px}.btn-toolbar.btn-case-mobile{display:flex!important;flex:1 1 0!important;min-width:0;padding:0 8px!important;order:2;overflow:hidden;justify-content:center;gap:4px}.btn-toolbar.btn-case-mobile #mobileCaseName{max-width:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.btn-case-settings-mobile{display:inline-flex!important;align-items:center;justify-content:center;width:26px;height:26px;background:transparent;border:1px solid rgba(255,255,255,.2);border-radius:4px;color:#9ca3af;cursor:pointer;flex-shrink:0;order:1}.btn-case-settings-mobile:active{background:#ffffff1a;color:#fff}@media(max-width:374px){.toolbar{padding:0 2px}.toolbar-left,.toolbar-left .toolbar-group,.toolbar-left .toolbar-group:first-child{gap:2px}}.btn-case-settings-mobile{display:none!important}.case-settings-popover-mobile{position:fixed;bottom:calc(var(--safe-area-bottom) + 46px);left:8px;right:8px;background:#1e1e1e;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:.6rem .75rem;z-index:1000;box-shadow:0 4px 16px #00000080;display:block}.case-settings-popover-mobile.hidden{display:none!important}.case-settings-popover-mobile .checkbox-inline{display:flex;align-items:center;gap:6px;font-size:.75rem;color:#e5e7eb}.case-settings-popover-mobile .form-hint{display:block;margin-top:.2rem;font-size:.6rem;color:#6b7280}.keyboard-accessory-bar{display:none;position:fixed;bottom:calc(var(--safe-area-bottom) + 40px);left:0;right:0;height:44px;background:#1a1a1a;border-top:1px solid rgba(255,255,255,.1);padding:6px 8px;padding-left:calc(8px + var(--safe-area-left));padding-right:calc(8px + var(--safe-area-right));gap:8px;align-items:center;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;z-index:51;transition:transform .15s ease-out;will-change:transform}.keyboard-accessory-bar.visible{display:flex}.keyboard-accessory-bar::-webkit-scrollbar{display:none}.accessory-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;gap:4px;padding:6px 12px;background:#2a2a2a;border:1px solid rgba(255,255,255,.15);border-radius:6px;color:#e5e5e5;font-size:.65rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s}.accessory-btn.confirming{background:#6b4f00;border-color:#b8860b;color:#ffd54f}.accessory-btn:active{background:#3a3a3a}.accessory-btn svg{width:14px;height:14px}.accessory-btn-arrow{padding:6px 10px;background:#2563eb;border-color:#3b82f680;color:#fff}.accessory-btn-arrow:active{background:#1d4ed8}.accessory-btn-dismiss{margin-left:auto;flex:1 1 0;max-width:100px;padding:10px 8px;background:#2563eb;border-color:#3b82f680;color:#fff;font-weight:600}.accessory-btn-dismiss svg{width:22px;height:22px}.accessory-btn-dismiss:active{background:#1d4ed8}.voice-preview{bottom:calc(var(--safe-area-bottom) + 94px);font-size:.8rem;max-width:90%;padding:6px 14px}.btn-case-add,.btn-case-settings,.toolbar-select{display:none!important}.toolbar .btn-case-add{min-width:26px!important;max-width:26px!important;width:26px!important;min-height:26px!important;max-height:26px!important;height:26px!important;padding:0!important;font-size:.9rem;font-weight:700;display:inline-flex!important;align-items:center;justify-content:center;line-height:1;border-radius:4px;background:transparent;border:1px solid rgba(255,255,255,.15);color:#9ca3af}.btn-case-add:hover,.btn-case-add:active{background:#ffffff1a;color:#fff}.monitor-panel,.subagents-panel{width:100%;max-width:100%;left:0;right:0;border-radius:8px 8px 0 0;bottom:calc(44px + 2rem + var(--safe-area-bottom));max-height:35vh}.modal{z-index:1300}.modal-content{width:100%;max-width:100%;height:100%;max-height:100%;border-radius:0;margin:0;display:flex;flex-direction:column}.modal-content.modal-sm{height:auto;max-height:85vh;border-radius:12px;margin:1rem;width:calc(100% - 2rem)}.ios-device .modal-content{padding-top:var(--safe-area-top);padding-bottom:var(--safe-area-bottom);padding-left:var(--safe-area-left);padding-right:var(--safe-area-right)}.modal-header{padding:.75rem 1rem}.modal-header h3{font-size:1rem}.modal-body{padding:.75rem 1rem;flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}.away-digest-modal{width:100%;max-width:100%;height:100%;max-height:100%}.away-digest-ranges{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.4rem}.away-digest-ranges .filter-btn{min-height:38px;padding:.4rem .5rem}.away-digest-custom-range,.away-digest-custom-range.active{grid-template-columns:1fr}.away-digest-summary{grid-template-columns:repeat(2,minmax(0,1fr));gap:.5rem}.away-digest-item{grid-template-columns:1fr;gap:.5rem}.away-digest-action{width:100%;min-height:38px}.modal-footer,.form-actions{padding:.75rem 1rem;padding-bottom:calc(.75rem + var(--safe-area-bottom))}.ios-device .terminal-container{padding-bottom:var(--safe-area-bottom)}.main{flex:1;min-height:0}.cli-info-bar{display:block}.terminal-container{height:100%;min-height:0;position:relative;overflow:visible;touch-action:none}.terminal-container .xterm,.terminal-container .xterm-viewport,.terminal-container .xterm-screen{touch-action:none}.response-viewer{padding-bottom:var(--safe-area-bottom, 0px);max-height:88vh;max-height:92dvh}.response-viewer-body{font-size:14.5px;line-height:1.65;padding:16px 16px 24px;--rv-content-max: 100%}.response-viewer-body .rv-text pre,.response-viewer-body pre{padding:12px 14px;margin-left:-4px;margin-right:-4px;border-radius:6px}.response-viewer-body .rv-text pre code,.response-viewer-body pre code{font-size:11.5px;line-height:1.5}.response-viewer-body .rv-text h1,.response-viewer-body>h1{font-size:1.35em}.response-viewer-body .rv-text h2,.response-viewer-body>h2{font-size:1.2em}.response-viewer-body .rv-text h3,.response-viewer-body>h3{font-size:1.08em}.welcome-content{max-width:calc(100vw - 1.5rem);padding:1rem .75rem}.welcome-title{font-size:1.2rem;margin-bottom:.5rem}.welcome-desc{font-size:.8rem;margin-bottom:.4rem}.welcome-actions{flex-direction:column;gap:.5rem;margin-top:1rem}.welcome-btn{width:100%;justify-content:center;min-height:44px;padding:.75rem 1rem;font-size:.85rem}.history-show-more{display:block;margin-bottom:.75rem}.welcome-ralph-link{display:block;margin:.75rem auto 0}.welcome-hint{font-size:.7rem;margin-top:.75rem}.modal-wizard{display:flex;flex-direction:column}.wizard-progress{padding:.5rem}.wizard-step{padding:.3rem}.wizard-step-number{width:24px;height:24px;font-size:.7rem}.wizard-step-label{display:none}.timer-banner{padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right))}.respawn-banner{padding:.3rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));font-size:.65rem}.respawn-compact-layout{flex-direction:column;gap:.15rem}.respawn-status-col{flex-shrink:1;min-width:0;gap:.1rem}.respawn-status-row1{flex-wrap:wrap;gap:.25rem;row-gap:.1rem}.respawn-state{font-size:.6rem;padding:.05rem .3rem}.respawn-banner .detection-confidence{font-size:.5rem;padding:.02rem .2rem}.respawn-cycles{font-size:.55rem}.respawn-timer{font-size:.55rem;padding:0 .25rem}.respawn-tokens{font-size:.55rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px}.respawn-indicator{font-size:.65rem}.respawn-banner .btn-icon-only{min-width:36px;min-height:36px;font-size:1rem;display:flex;align-items:center;justify-content:center;margin-left:auto;border-radius:6px;flex-shrink:0}.respawn-status-row2{font-size:.55rem;gap:.3rem;min-height:0;flex-wrap:wrap}.respawn-banner .detection-hook,.respawn-banner .detection-ai-check,.respawn-banner .detection-status{font-size:.55rem;padding:.02rem .2rem}.respawn-countdown-timers{gap:.2rem}.respawn-countdown-timer{font-size:.5rem;padding:.02rem .2rem;gap:.15rem}.respawn-countdown-timer .respawn-timer-bar{display:none}.respawn-action-log{border-left:none;border-top:1px solid rgba(34,197,94,.15);padding-left:0;padding-top:.15rem;max-height:1.4em;font-size:.55rem;overflow:hidden}.respawn-header{flex-direction:row;gap:.4rem;align-items:center}.respawn-header .respawn-actions{display:flex;gap:.3rem;flex-shrink:0}.respawn-header .respawn-actions .btn-toolbar{min-height:28px!important;font-size:.7rem!important;padding:.2rem .5rem!important;border-radius:5px}.duration-presets{display:flex;flex-wrap:wrap;gap:.2rem}.duration-preset-btn{min-height:24px;padding:.1rem .4rem;font-size:.6rem;border-radius:4px;text-align:center}.duration-custom{display:flex;gap:.2rem;align-items:center}.duration-custom-input.visible{flex:0 1 auto}.duration-custom-input input{width:64px;min-height:24px;font-size:16px;padding:.1rem .3rem}.preset-selector{display:grid;grid-template-columns:1fr 1fr;gap:.25rem}.preset-selector select{grid-column:1 / -1;min-height:32px;font-size:16px;border-radius:5px;padding:.2rem .4rem}.preset-selector .btn{min-height:32px;font-size:.65rem;border-radius:5px;padding:.2rem .4rem}#sessionOptionsModal textarea{font-size:16px;min-height:32px!important;max-height:56px;height:auto!important;border-radius:6px;padding:.3rem .5rem}#modalRespawnPrompt{min-height:32px!important;max-height:56px}#modalRespawnKickstart{min-height:32px!important;max-height:48px}#sessionOptionsModal .checkbox-inline{min-height:30px;font-size:.75rem;padding:.15rem 0;gap:.4rem}#sessionOptionsModal .checkbox-inline input[type=checkbox]{width:18px;height:18px}#sessionOptionsModal .respawn-loop-title{font-size:.75rem}#sessionOptionsModal .respawn-loop-box .checkbox-inline{font-size:.65rem}#sessionOptionsModal .respawn-options-row{gap:.5rem}#sessionOptionsModal .form-section-header{margin-top:.75rem;padding-top:.5rem;font-size:.65rem}#sessionOptionsModal .form-row{margin-bottom:.5rem}#sessionOptionsModal .form-row label{font-size:.65rem;margin-bottom:.2rem}#sessionOptionsModal .form-hint{font-size:.6rem;margin-top:.2rem}.context-setting{padding:.625rem}.context-setting-header{flex-wrap:wrap;gap:.4rem}.context-setting-header .input-suffix-sm input{width:60px;font-size:16px;min-height:36px}.context-setting input[type=text]{font-size:16px;min-height:36px;padding:.4rem .6rem;border-radius:6px}.color-picker{gap:8px}.color-swatch{width:36px;height:36px;border-radius:6px}.form-row-switch{min-height:40px;gap:.4rem}.context-settings-grid input[type=number]{font-size:16px;min-height:36px}.ralph-limits-grid{grid-template-columns:1fr 1fr;gap:.5rem}.ralph-limits-grid .form-col input[type=number]{font-size:16px;min-height:36px;padding:.4rem .5rem;border-radius:6px}#modalRalphPhrase{font-size:16px;min-height:40px;border-radius:6px}.ralph-config-actions{margin-top:1rem}.ralph-config-actions .btn-toolbar{width:100%;min-height:44px;font-size:.85rem;border-radius:8px}.run-summary-filters{gap:.3rem;margin-bottom:.5rem}.filter-btn{padding:.35rem .75rem;font-size:.7rem;min-height:32px}.timeline-event{padding:.4rem .5rem;margin-bottom:.25rem;font-size:.7rem}.run-summary-footer{flex-direction:column;gap:.4rem;padding:.5rem 0}.run-summary-actions{flex-wrap:wrap;gap:.3rem}.run-summary-actions .btn-toolbar{flex:1;min-height:36px;font-size:.7rem;white-space:nowrap}.auto-refresh-label{font-size:.7rem}.ralph-panel{font-size:.75rem}.ralph-summary{padding:.4rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right))}.project-insights-panel{max-width:100%;font-size:.65rem;bottom:calc(44px + 2rem + var(--safe-area-bottom))}.file-browser-panel{max-width:100%;max-height:50vh;bottom:calc(44px + 2rem + var(--safe-area-bottom))}.notification-drawer{width:100%;max-width:100%;right:0;border-radius:0;padding-left:var(--safe-area-left);padding-right:var(--safe-area-right);padding-bottom:var(--safe-area-bottom)}input,textarea,[contenteditable]{scroll-margin-bottom:200px;scroll-margin-top:80px}.keyboard-visible .modal-body{max-height:40vh;overflow-y:auto}.keyboard-visible #createCaseModal .modal-body{max-height:60vh}.mobile-case-picker .modal-backdrop{background:#00000080}.mobile-case-picker-sheet{max-height:60vh;padding-bottom:var(--safe-area-bottom);animation:slideUp .2s ease-out}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.mobile-case-picker-header .modal-close{width:32px;height:32px;font-size:1.5rem}.mobile-case-picker-footer{padding-bottom:calc(12px + var(--safe-area-bottom))}.modal-tabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;gap:.25rem;padding:0 .75rem .5rem;flex-wrap:nowrap}.modal-tabs::-webkit-scrollbar{display:none}.modal-tab-btn{padding:.35rem .6rem;font-size:.65rem;white-space:nowrap;flex-shrink:0}#createCaseModal .modal-tabs{gap:.5rem;padding:.5rem 1rem .75rem}#createCaseModal .modal-tab-btn{flex:1;min-height:44px;padding:.6rem 1rem;font-size:.8rem;font-weight:500;border-radius:8px;justify-content:center;text-align:center}#createCaseModal .form-row{margin-bottom:1rem}#createCaseModal .form-row label{font-size:.8rem;margin-bottom:.4rem;font-weight:500;color:#e5e7eb}#createCaseModal .form-row input[type=text]{min-height:44px;font-size:16px;padding:.5rem .75rem;border-radius:8px}#createCaseModal .form-row .form-hint{font-size:.65rem;margin-top:.35rem;line-height:1.4}#createCaseModal .form-actions{padding:.75rem 1rem;padding-bottom:calc(.75rem + var(--safe-area-bottom));gap:.75rem}#createCaseModal .form-actions .btn-toolbar{min-height:44px!important;max-height:44px!important;height:44px!important;font-size:.85rem!important;font-weight:500;border-radius:8px}#caseModalSubmit.loading{opacity:.6;pointer-events:none}#createCaseModal.from-mobile .modal-content{animation:caseModalSlideUp .25s ease-out}@keyframes caseModalSlideUp{0%{transform:translateY(30px);opacity:0}to{transform:translateY(0);opacity:1}}.btn-case-create-mobile{min-height:48px!important;max-height:48px!important;height:48px!important;font-size:.85rem!important;font-weight:500;border-radius:10px}.settings-grid{grid-template-columns:1fr;gap:.35rem}.settings-grid-3col{grid-template-columns:1fr 1fr 1fr}.settings-item{padding:.35rem .5rem;font-size:.7rem}.settings-item-label{font-size:.7rem}.settings-section-header{font-size:.6rem;padding:.35rem 0 .2rem;margin-top:.5rem}.form-row{margin-bottom:.5rem}.form-row label{font-size:.7rem;margin-bottom:.2rem}.form-row .form-hint{font-size:.6rem}.form-row input[type=text],.form-row input[type=number],.form-row textarea,.form-row .form-select,.form-row select{font-size:.75rem;padding:.35rem .5rem;min-height:32px}.form-row-switch{gap:.3rem}.form-row-switch>label:first-child{font-size:.7rem}.form-section-header{font-size:.6rem;margin-top:.75rem}.event-type-grid{grid-template-columns:1fr 36px 36px 36px;gap:4px 4px;padding:6px;margin-top:6px}.event-header{font-size:.55rem}.event-label{font-size:.65rem}.event-type-grid input[type=checkbox]{width:12px;height:12px}.form-actions{gap:.5rem}.form-actions .btn-toolbar{flex:1;min-height:36px!important;max-height:36px!important;height:36px!important;font-size:.75rem!important}.subagent-window{position:fixed;width:calc(100% - 8px);max-width:calc(100% - 8px);height:110px;min-height:80px;max-height:110px;min-width:200px;border-radius:6px;resize:none;box-shadow:0 2px 8px #0006}.subagent-window:after{display:none}.subagent-window-header{padding:.2rem .4rem;min-height:24px}.subagent-window-title{gap:.2rem;overflow:hidden}.subagent-window-title .icon{font-size:.7rem}.subagent-window-title .id{font-size:.6rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:45vw}.subagent-window-title .status{font-size:.45rem;padding:.05rem .15rem}.subagent-model-badge{font-size:.45rem!important;padding:.05rem .15rem!important}.subagent-window-actions button{font-size:.7rem;padding:.15rem .35rem;min-width:26px;min-height:26px;display:flex;align-items:center;justify-content:center}.subagent-window-body{font-size:.6rem;padding:.2rem .35rem}.subagent-window-body .activity-line{gap:.15rem;padding:.05rem 0}.subagent-window-body .activity-line .time{font-size:.5rem}.subagent-window-body .activity-line .tool-name,.subagent-window-body .activity-line .tool-detail{font-size:.55rem}.subagent-window-parent{display:none}.session-tab .tab-subagent-badge{height:14px;padding:0 3px;border-radius:7px;margin-left:2px}.session-tab .tab-subagent-badge .subagent-label{font-size:.45rem}.subagent-dropdown{position:fixed!important;left:8px!important;right:8px!important;bottom:auto!important;min-width:auto!important;max-width:none!important;border-radius:8px;transform:none!important}}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.header,.toolbar,.keyboard-accessory-bar){background:var(--glass-bg);border-color:var(--glass-border);color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-voice-mobile,.btn-settings-mobile,.btn-toolbar.btn-shell,.toolbar .btn-case-add,.accessory-btn){background:var(--control-bg);border-color:var(--control-border);color:var(--text-dim)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-voice-mobile:active,.btn-settings-mobile:active,.btn-toolbar.btn-shell:hover,.btn-toolbar.btn-shell:active,.btn-case-add:hover,.btn-case-add:active,.accessory-btn:active){background:var(--control-bg-hover);border-color:var(--control-border-hover);color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-claude,.btn-toolbar.btn-run-gear.mode-claude){background:linear-gradient(135deg,var(--accent-grad-a),var(--accent-grad-b));border-color:var(--accent);color:var(--accent-ink)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-opencode,.btn-toolbar.btn-run-gear.mode-opencode){background:linear-gradient(135deg,var(--accent-d),var(--accent-grad-b));border-color:var(--accent);color:var(--accent-ink)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-gemini,.btn-toolbar.btn-run-gear.mode-gemini){background:linear-gradient(135deg,#174ea6,#4f46e5);border-color:#315fc3;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .btn-toolbar.btn-run-gear{border-left-color:var(--control-border-hover)!important}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.case-settings-popover-mobile,.mobile-case-picker-sheet){background:var(--floating-bg);border-color:var(--control-border);color:var(--text);box-shadow:var(--elevated-shadow)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.case-settings-popover-mobile .checkbox-inline,#createCaseModal .form-row label){color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .case-settings-popover-mobile .form-hint{color:var(--text-muted)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .mobile-case-picker .modal-backdrop{background:var(--modal-backdrop)}.ios-device.safari-browser{overscroll-behavior:none}@media(hover:none)and (pointer:coarse){.session-tab .tab-close,.session-tab .tab-gear{opacity:1;width:auto;padding:.15rem .25rem;align-items:center;justify-content:center}.btn-toolbar:hover,.btn-icon-header:hover{transform:none}.subagent-dropdown-trigger:active+.subagent-dropdown-menu,.subagent-dropdown-trigger:focus+.subagent-dropdown-menu{display:block}}@media(max-width:430px){.attachment-history-drawer{top:0;bottom:0;width:100%;max-width:100%;height:100vh;height:100dvh;border-left:none;border-radius:0;padding-top:var(--safe-area-top);padding-left:var(--safe-area-left);padding-right:var(--safe-area-right);padding-bottom:var(--safe-area-bottom)}.attachment-history-header{padding:12px}.attachment-history-list{padding:6px}.attachment-history-item{grid-template-columns:104px minmax(0,1fr);gap:8px;padding:8px 6px}.attachment-history-thumb{width:104px}.attachment-history-actions{gap:4px}.attachment-history-actions button{padding:4px 7px}}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|