Skip to content

Commit 1911177

Browse files
committed
fix final assistant response not streamed to WebUI; replace confirm() dialog
server/loop.go: append final assistant message to messages slice before returning from runLoop. The final text was only returned as the first return value, never added to the messages slice, so handlePrompt in serve.go never streamed it as a token event. Effect: WebUI showed tool calls + tool results but no assistant text response after 'done'. WebUI: replace native confirm() with custom HTML dialog - New #confirm-overlay with backdrop blur, same pattern as approval dialog - Shows 'Delete session abc12345...?' with Cancel/Delete buttons - Escape key closes the dialog - Cleaner UX matching the dark theme
1 parent 732a588 commit 1911177

2 files changed

Lines changed: 72 additions & 5 deletions

File tree

cmd/kode/ui/index.html

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,38 @@
690690
border-radius: 4px; padding: 2px 8px; color: var(--text-secondary);
691691
}
692692

693+
/* ── Confirm Dialog ── */
694+
#confirm-overlay {
695+
display: none;
696+
position: fixed; inset: 0; z-index: 1001;
697+
background: rgba(0,0,0,0.6);
698+
backdrop-filter: blur(4px);
699+
align-items: center; justify-content: center;
700+
}
701+
#confirm-overlay.active { display: flex; animation: fadeIn 0.15s ease-out; }
702+
#confirm-dialog {
703+
background: var(--bg-card);
704+
border: 1px solid var(--border-subtle);
705+
border-radius: 16px;
706+
padding: 24px;
707+
max-width: 400px;
708+
width: 90%;
709+
box-shadow: 0 16px 64px rgba(0,0,0,0.5);
710+
animation: dialogEnter 0.2s ease-out;
711+
}
712+
#confirm-dialog h3 { font-size: 16px; margin-bottom: 8px; color: var(--text-primary); }
713+
#confirm-dialog p { font-size: 14px; color: var(--text-secondary); margin-bottom: 20px; line-height: 1.5; }
714+
#confirm-actions { display: flex; gap: 8px; justify-content: flex-end; }
715+
#confirm-actions button {
716+
padding: 8px 16px; border-radius: 8px; border: none;
717+
font-family: var(--font-sans); font-size: 13px; font-weight: 600;
718+
cursor: pointer; transition: all 0.15s;
719+
}
720+
#confirm-actions .cancel { background: var(--bg-primary); color: var(--text-secondary); border: 1px solid var(--border-subtle); }
721+
#confirm-actions .cancel:hover { background: var(--accent-subtle); color: var(--text-primary); }
722+
#confirm-actions .delete-confirm { background: #ef4444; color: white; }
723+
#confirm-actions .delete-confirm:hover { opacity: 0.9; }
724+
693725
/* ── Toast ── */
694726
.toast {
695727
position: fixed; bottom: 80px; left: 50%; transform: translateX(-50%);
@@ -803,6 +835,18 @@ <h3>⌨ Keyboard Shortcuts</h3>
803835
</div>
804836
</div>
805837

838+
<!-- Confirm Dialog -->
839+
<div id="confirm-overlay">
840+
<div id="confirm-dialog">
841+
<h3>Delete session?</h3>
842+
<p id="confirm-msg">This action cannot be undone.</p>
843+
<div id="confirm-actions">
844+
<button class="cancel" onclick="hideConfirmDialog()">Cancel</button>
845+
<button class="delete-confirm" id="confirm-delete-btn" onclick="executeDeleteSession()">Delete</button>
846+
</div>
847+
</div>
848+
</div>
849+
806850
<!-- Toast -->
807851
<div class="toast" id="toast"></div>
808852

@@ -1353,6 +1397,22 @@ <h3>⌨ Keyboard Shortcuts</h3>
13531397
approvalId = null;
13541398
};
13551399

1400+
// ── Confirm Dialog ──
1401+
window.hideConfirmDialog = function() {
1402+
document.getElementById('confirm-overlay').classList.remove('active');
1403+
pendingDeleteId = null;
1404+
};
1405+
1406+
window.executeDeleteSession = function() {
1407+
if (!pendingDeleteId) return;
1408+
const sid = pendingDeleteId;
1409+
pendingDeleteId = null;
1410+
document.getElementById('confirm-overlay').classList.remove('active');
1411+
fetch('/api/sessions/' + encodeURIComponent(sid), { method: 'DELETE' })
1412+
.then(() => loadSessions())
1413+
.catch(() => showToast('Failed to delete session'));
1414+
};
1415+
13561416
// ── Shortcuts ──
13571417
window.toggleShortcuts = function() {
13581418
document.getElementById('shortcuts-overlay').classList.toggle('active');
@@ -1655,6 +1715,7 @@ <h3>⌨ Keyboard Shortcuts</h3>
16551715

16561716
// ── Sessions ──
16571717
let allSessions = [];
1718+
let pendingDeleteId = null;
16581719

16591720
sessionListEl.addEventListener('click', (e) => {
16601721
// Delete button
@@ -1664,11 +1725,9 @@ <h3>⌨ Keyboard Shortcuts</h3>
16641725
const sid = item.dataset.id;
16651726
if (!sid) return;
16661727
e.stopPropagation();
1667-
if (confirm('Delete session ' + sid.slice(0, 8) + '?')) {
1668-
fetch('/api/sessions/' + encodeURIComponent(sid), { method: 'DELETE' })
1669-
.then(() => loadSessions())
1670-
.catch(() => showToast('Failed to delete session'));
1671-
}
1728+
pendingDeleteId = sid;
1729+
document.getElementById('confirm-msg').textContent = 'Delete session ' + sid.slice(0, 8) + '...?';
1730+
document.getElementById('confirm-overlay').classList.add('active');
16721731
return;
16731732
}
16741733

@@ -1731,6 +1790,8 @@ <h3>⌨ Keyboard Shortcuts</h3>
17311790
if (e.key === 'Escape') {
17321791
document.getElementById('shortcuts-overlay').classList.remove('active');
17331792
document.getElementById('approval-overlay').classList.remove('active');
1793+
document.getElementById('confirm-overlay').classList.remove('active');
1794+
pendingDeleteId = null;
17341795
}
17351796
// Ctrl+R refreshes sessions
17361797
if (e.key === 'r' && (e.ctrlKey || e.metaKey)) {

internal/loop/loop.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ func (e *Engine) runLoop(ctx context.Context, messages []llm.Message) (string, [
239239
if e.renderer != nil {
240240
e.renderer.FinalAnswer(result.Content)
241241
}
242+
// Append final assistant message so callers (e.g. WebUI) get
243+
// the final text in the messages slice and can stream it.
244+
messages = append(messages, llm.Message{
245+
Role: "assistant",
246+
Content: result.Content,
247+
})
242248
return result.Content, messages, nil
243249
}
244250

0 commit comments

Comments
 (0)