diff --git a/static/index.html b/static/index.html
index d27965e..c1f53fa 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1490,26 +1490,40 @@
General
term.write('\x1b[90m 3. Paste it below\x1b[0m\r\n');
term.write('\r\n');
term.write('\x1b[1;37m Token: \x1b[0m');
+ term.focus();
// Collect token input from the terminal
let tokenInput = '';
await new Promise((resolve) => {
const disposable = term.onData(data => {
if (data === '\r' || data === '\n') {
- // Enter pressed — submit token
term.write('\r\n');
disposable.dispose();
resolve();
- } else if (data === '\x7f' || data === '\b') {
- // Backspace
+ return;
+ }
+ if (data === '\x7f' || data === '\b') {
if (tokenInput.length > 0) {
tokenInput = tokenInput.slice(0, -1);
term.write('\b \b');
}
- } else if (data >= ' ') {
- // Printable character — mask with asterisks
- tokenInput += data;
- term.write('*');
+ return;
+ }
+ let chunk = data;
+ let submitAfter = false;
+ if (/[\r\n]$/.test(chunk)) {
+ chunk = chunk.replace(/[\r\n]+$/, '');
+ submitAfter = true;
+ }
+ const printable = Array.from(chunk).filter(c => c >= ' ');
+ if (printable.length) {
+ tokenInput += printable.join('');
+ term.write('*'.repeat(printable.length));
+ }
+ if (submitAfter) {
+ term.write('\r\n');
+ disposable.dispose();
+ resolve();
}
});
});
@@ -2028,17 +2042,21 @@ General
// Use capture phase (3rd arg = true) so we fire BEFORE xterm.js consumes the event
document.addEventListener('paste', async (e) => {
const active = getActivePane();
- if (!active || !active.sessionId) {
- console.log('[paste] No active pane or session');
- return;
- }
-
const items = e.clipboardData?.items;
if (!items) {
console.log('[paste] No clipboardData items');
return;
}
+ // Image paste needs a live session to upload to. Text paste must always
+ // fall through to xterm (the PAT prompt fires before sessionId is set).
+ const hasImage = Array.from(items).some(i => i.type.startsWith('image/'));
+ if (!hasImage) return;
+ if (!active || !active.sessionId) {
+ console.log('[paste] image paste ignored — no active session');
+ return;
+ }
+
console.log('[paste] Items:', Array.from(items).map(i => i.type));
for (const item of items) {