Skip to content

Commit 5f179dc

Browse files
committed
chore: ai panel fixes
1 parent ac2f6e8 commit 5f179dc

4 files changed

Lines changed: 84 additions & 22 deletions

File tree

src-node/claude-code-agent.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ exports.cancelQuery = async function () {
157157
if (currentAbortController) {
158158
currentAbortController.abort();
159159
currentAbortController = null;
160+
// Clear session so next query starts fresh instead of resuming a killed session
161+
currentSessionId = null;
160162
return { success: true };
161163
}
162164
return { success: false };
@@ -376,11 +378,15 @@ async function _runQuery(requestId, prompt, projectPath, model, signal) {
376378
});
377379

378380
} catch (err) {
379-
if (signal.aborted) {
380-
// Query was cancelled, not an error
381+
const errMsg = err.message || String(err);
382+
const isAbort = signal.aborted || /abort/i.test(errMsg);
383+
384+
if (isAbort) {
385+
// Query was cancelled — clear session so next query starts fresh
386+
currentSessionId = null;
381387
nodeConnector.triggerPeer("aiComplete", {
382388
requestId: requestId,
383-
sessionId: currentSessionId
389+
sessionId: null
384390
});
385391
return;
386392
}
@@ -395,7 +401,13 @@ async function _runQuery(requestId, prompt, projectPath, model, signal) {
395401

396402
nodeConnector.triggerPeer("aiError", {
397403
requestId: requestId,
398-
error: err.message || String(err)
404+
error: errMsg
405+
});
406+
407+
// Always send aiComplete after aiError so the UI exits streaming state
408+
nodeConnector.triggerPeer("aiComplete", {
409+
requestId: requestId,
410+
sessionId: currentSessionId
399411
});
400412
}
401413
}

src/core-ai/AIChatPanel.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ define(function (require, exports, module) {
3939
let _hasReceivedContent = false; // tracks if we've received any text/tool in current response
4040

4141
// DOM references
42-
let $panel, $messages, $status, $statusText, $textarea, $sendBtn;
42+
let $panel, $messages, $status, $statusText, $textarea, $sendBtn, $stopBtn;
4343

4444
const PANEL_HTML =
4545
'<div class="ai-chat-panel">' +
@@ -58,7 +58,10 @@ define(function (require, exports, module) {
5858
'<div class="ai-chat-input-wrap">' +
5959
'<textarea class="ai-chat-textarea" placeholder="Ask Claude..." rows="1"></textarea>' +
6060
'<button class="ai-send-btn" title="Send message">' +
61-
'<i class="fa-solid fa-arrow-up"></i>' +
61+
'<i class="fa-solid fa-paper-plane"></i>' +
62+
'</button>' +
63+
'<button class="ai-stop-btn" title="Stop generation (Esc)" style="display:none">' +
64+
'<i class="fa-solid fa-stop"></i>' +
6265
'</button>' +
6366
'</div>' +
6467
'</div>' +
@@ -143,11 +146,16 @@ define(function (require, exports, module) {
143146
$statusText = $panel.find(".ai-status-text");
144147
$textarea = $panel.find(".ai-chat-textarea");
145148
$sendBtn = $panel.find(".ai-send-btn");
149+
$stopBtn = $panel.find(".ai-stop-btn");
146150

147151
// Event handlers
148152
$sendBtn.on("click", _sendMessage);
153+
$stopBtn.on("click", _cancelQuery);
149154
$panel.find(".ai-new-session-btn").on("click", _newSession);
150155

156+
// Hide "+ New" button initially (no conversation yet)
157+
$panel.find(".ai-new-session-btn").hide();
158+
151159
$textarea.on("keydown", function (e) {
152160
if (e.key === "Enter" && !e.shiftKey) {
153161
e.preventDefault();
@@ -198,6 +206,9 @@ define(function (require, exports, module) {
198206
return;
199207
}
200208

209+
// Show "+ New" button once a conversation starts
210+
$panel.find(".ai-new-session-btn").show();
211+
201212
// Append user message
202213
_appendUserMessage(text);
203214

@@ -255,6 +266,10 @@ define(function (require, exports, module) {
255266
if ($messages) {
256267
$messages.empty();
257268
}
269+
// Hide "+ New" button since we're back to empty state
270+
if ($panel) {
271+
$panel.find(".ai-new-session-btn").hide();
272+
}
258273
if ($status) {
259274
$status.removeClass("active");
260275
}
@@ -607,8 +622,14 @@ define(function (require, exports, module) {
607622
$textarea[0].focus({ preventScroll: true });
608623
}
609624
}
610-
if ($sendBtn) {
611-
$sendBtn.prop("disabled", streaming);
625+
if ($sendBtn && $stopBtn) {
626+
if (streaming) {
627+
$sendBtn.hide();
628+
$stopBtn.show();
629+
} else {
630+
$stopBtn.hide();
631+
$sendBtn.show();
632+
}
612633
}
613634
if (!streaming && $messages) {
614635
// Clean up thinking indicator if still present

src/styles/Extn-AIChatPanel.less

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,26 @@
3636
display: flex;
3737
align-items: center;
3838
justify-content: space-between;
39-
padding: 6px 10px;
39+
padding: 10px 10px 9px 12px;
4040
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
4141
flex-shrink: 0;
4242

4343
.ai-chat-title {
44-
font-weight: 600;
45-
font-size: 11px;
44+
font-weight: 400;
45+
font-size: 15px;
4646
color: @project-panel-text-2;
47-
letter-spacing: 0.3px;
47+
line-height: 19px;
4848
}
4949

5050
.ai-new-session-btn {
51+
display: flex;
52+
align-items: center;
53+
gap: 4px;
5154
background: none;
5255
border: none;
5356
color: @project-panel-text-2;
54-
font-size: 11px;
55-
padding: 2px 6px;
57+
font-size: 13px;
58+
padding: 0 8px;
5659
border-radius: 3px;
5760
cursor: pointer;
5861
opacity: 0.7;
@@ -475,7 +478,7 @@
475478
overflow: hidden;
476479

477480
&:focus-within {
478-
border-color: rgba(255, 255, 255, 0.18);
481+
border-color: @bc-btn-border-focused;
479482
}
480483

481484
&.disabled {
@@ -487,16 +490,18 @@
487490
flex: 1;
488491
min-width: 0;
489492
background: none;
490-
border: none;
493+
border: none !important;
491494
color: @project-panel-text-1;
492495
font-size: 12px;
493496
font-family: inherit;
494497
padding: 7px 0 7px 10px;
498+
margin: 0;
495499
resize: none;
496500
min-height: 20px;
497501
max-height: 96px;
498502
line-height: 1.4;
499-
outline: none;
503+
outline: none !important;
504+
box-shadow: none !important;
500505

501506
&:disabled {
502507
cursor: not-allowed;
@@ -508,16 +513,15 @@
508513
border: none;
509514
color: @project-panel-text-2;
510515
width: 30px;
511-
height: 30px;
512516
cursor: pointer;
513517
display: flex;
514518
align-items: center;
515519
justify-content: center;
516520
flex-shrink: 0;
521+
align-self: stretch;
517522
border-radius: 0 7px 7px 0;
518523
opacity: 0.5;
519524
transition: opacity 0.15s ease, color 0.15s ease;
520-
margin-bottom: 1px;
521525

522526
&:hover {
523527
opacity: 1;
@@ -533,6 +537,30 @@
533537
font-size: 12px;
534538
}
535539
}
540+
541+
.ai-stop-btn {
542+
background: none;
543+
border: none;
544+
color: #e06c75;
545+
width: 30px;
546+
cursor: pointer;
547+
display: flex;
548+
align-items: center;
549+
justify-content: center;
550+
flex-shrink: 0;
551+
align-self: stretch;
552+
border-radius: 0 7px 7px 0;
553+
opacity: 0.7;
554+
transition: opacity 0.15s ease;
555+
556+
&:hover {
557+
opacity: 1;
558+
}
559+
560+
i {
561+
font-size: 12px;
562+
}
563+
}
536564
}
537565

538566
/* ── Unavailable / placeholder state ────────────────────────────────── */

src/styles/Extn-SidebarTabs.less

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
height: 2rem;
2828
overflow: hidden;
2929
user-select: none;
30+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
3031

3132
&.has-tabs {
3233
display: flex;
@@ -42,8 +43,7 @@
4243
cursor: pointer;
4344
position: relative;
4445
color: @project-panel-text-2;
45-
font-size: 0.8rem;
46-
letter-spacing: 0.3px;
46+
font-size: 0.85rem;
4747
transition: color 0.15s ease, background-color 0.15s ease;
4848

4949
i {
@@ -57,6 +57,7 @@
5757

5858
&.active {
5959
color: @project-panel-text-1;
60+
background-color: rgba(255, 255, 255, 0.04);
6061

6162
&::after {
6263
content: "";
@@ -65,7 +66,7 @@
6566
left: 0;
6667
right: 0;
6768
height: 2px;
68-
background-color: @project-panel-text-2;
69+
background-color: @project-panel-text-1;
6970
}
7071
}
7172
}

0 commit comments

Comments
 (0)