diff --git a/src/data.js b/src/data.js index 3f0a5ca..601599b 100644 --- a/src/data.js +++ b/src/data.js @@ -1761,7 +1761,7 @@ function scanKiroSessions() { '-separator', '\t', KIRO_DB, 'SELECT key, conversation_id, created_at, updated_at, substr(value, 1, 500), length(value) FROM conversations_v2 ORDER BY updated_at DESC' - ], { encoding: 'utf8', timeout: 5000, windowsHide: true }).trim(); + ], { encoding: 'utf8', timeout: 5000, maxBuffer: 50 * 1024 * 1024, windowsHide: true }).trim(); if (!rows) return sessions; @@ -1808,7 +1808,7 @@ function loadKiroDetail(conversationId) { const raw = execFileSync('sqlite3', [ KIRO_DB, `SELECT value FROM conversations_v2 WHERE conversation_id = '${conversationId.replace(/'/g, "''")}';` - ], { encoding: 'utf8', timeout: 10000, windowsHide: true }).trim(); + ], { encoding: 'utf8', timeout: 10000, maxBuffer: 50 * 1024 * 1024, windowsHide: true }).trim(); if (!raw) return { messages: [] }; @@ -1822,7 +1822,10 @@ function loadKiroDetail(conversationId) { if (text) messages.push({ role: 'user', content: text.slice(0, 2000), uuid: '' }); } if (entry.assistant) { - const resp = entry.assistant.Response || entry.assistant.response || {}; + // assistant can be { Response: {...} } or { ToolUse: {...} } — both carry + // content + message_id. Kiro started emitting ToolUse turns, which were + // dropped when only Response was read. + const resp = entry.assistant.Response || entry.assistant.ToolUse || entry.assistant.response || {}; const text = resp.content || ''; if (text) messages.push({ role: 'assistant', content: text.slice(0, 2000), uuid: resp.message_id || '' }); } diff --git a/src/frontend/workspace.js b/src/frontend/workspace.js index 37a91d1..89600fc 100644 --- a/src/frontend/workspace.js +++ b/src/frontend/workspace.js @@ -404,9 +404,19 @@ function _wsConnectPane(pane) { var fit = new FitAddon.FitAddon(); term.loadAddon(fit); term.open(host); - try { fit.fit(); } catch (e) {} pane.term = term; pane.fit = fit; + // Fit only when the host actually has a size. Fitting a zero-size / not-yet- + // laid-out host (inactive tab, mid-transition pane) computes bogus cols/rows, + // which spawns the pty at the wrong width and garbles full-screen TUIs like + // Claude Code — most visibly on large / hi-DPI displays (see #259). + function _wsFitPane() { + if (!host.clientWidth || !host.clientHeight) return false; + try { fit.fit(); return true; } catch (e) { return false; } + } + _wsFitPane(); // best-effort now (correct URL dims if laid out) + requestAnimationFrame(_wsFitPane); // and again after the first paint + // Track which pane the user is "in": focusing/clicking the terminal marks it // as the focused pane, so saved commands / resume land where you're looking. host.addEventListener('focusin', function () { _wsSetFocusedPane(pane.id); }); @@ -432,6 +442,11 @@ function _wsConnectPane(pane) { pane.cwd = msg.cwd; setStatus(_wsPaneLabel(pane)); _wsAutoNameTab(pane); + // Now that the pane is laid out and connected, re-fit and push the true + // size to the pty so xterm and the pty agree (fixes wrong-width TUIs). + if (_wsFitPane() && sock.readyState === 1) { + sock.send(JSON.stringify({ t: 'resize', cols: term.cols, rows: term.rows })); + } // cmd auto-runs (trailing \r); prefill is typed but NOT executed so the // user can review/edit a resume command before pressing Enter. if (pane.cmd) setTimeout(function () { if (sock.readyState === 1) sock.send(enc.encode(pane.cmd + '\r')); }, 120); @@ -456,8 +471,9 @@ function _wsConnectPane(pane) { pane.ro = new ResizeObserver(function () { clearTimeout(rt); rt = setTimeout(function () { - try { fit.fit(); } catch (e) {} - if (sock.readyState === 1) sock.send(JSON.stringify({ t: 'resize', cols: term.cols, rows: term.rows })); + if (_wsFitPane() && sock.readyState === 1) { + sock.send(JSON.stringify({ t: 'resize', cols: term.cols, rows: term.rows })); + } }, 100); }); try { pane.ro.observe(host.parentNode); } catch (e) {}