clay-server 2.32.0-beta.1 → 2.32.0-beta.10

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.
@@ -746,12 +746,14 @@
746
746
  display: flex;
747
747
  align-items: center;
748
748
  justify-content: space-between;
749
+ gap: 4px;
749
750
  }
750
751
 
751
752
  #input-bottom-right {
752
753
  display: flex;
753
754
  align-items: center;
754
755
  gap: 4px;
756
+ flex-shrink: 0;
755
757
  }
756
758
 
757
759
  /* --- Vendor toggle (split toggle) --- */
@@ -812,22 +814,31 @@
812
814
  .vendor-toggle-label {
813
815
  pointer-events: none;
814
816
  }
815
- @media (max-width: 600px) {
817
+ @media (max-width: 900px) {
816
818
  .vendor-toggle-label { display: none; }
819
+ .vendor-toggle-btn { padding: 0 8px; }
817
820
  }
818
821
 
819
822
  /* --- Attach buttons & menu --- */
820
823
  #attach-wrap {
821
824
  position: relative;
822
- flex-shrink: 0;
825
+ min-width: 0;
823
826
  display: flex;
824
827
  align-items: center;
825
828
  gap: 2px;
829
+ flex-wrap: nowrap;
830
+ overflow: hidden;
831
+ }
832
+
833
+ /* Allow popovers (context picker) to escape when open */
834
+ #attach-wrap:has(#context-sources-picker:not(.hidden)) {
835
+ overflow: visible;
826
836
  }
827
837
 
828
838
  #attach-file-btn,
829
839
  #attach-image-btn,
830
- #schedule-btn {
840
+ #schedule-btn,
841
+ #input-more-btn {
831
842
  width: 36px;
832
843
  height: 36px;
833
844
  border-radius: 50%;
@@ -844,11 +855,13 @@
844
855
 
845
856
  #attach-file-btn .lucide,
846
857
  #attach-image-btn .lucide,
847
- #schedule-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
858
+ #schedule-btn .lucide,
859
+ #input-more-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
848
860
 
849
861
  #attach-file-btn:hover,
850
862
  #attach-image-btn:hover,
851
- #schedule-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
863
+ #schedule-btn:hover,
864
+ #input-more-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
852
865
 
853
866
  #ask-mate-btn {
854
867
  width: 36px;
@@ -1137,6 +1150,146 @@
1137
1150
  body.keyboard-open #input-area {
1138
1151
  padding-bottom: 8px;
1139
1152
  }
1153
+
1154
+ /* Mobile visibility utilities for input toolbar */
1155
+ .desktop-only { display: none !important; }
1156
+ .mobile-only { display: inline-flex !important; }
1157
+ }
1158
+
1159
+ /* Desktop: hide mobile-only, show desktop-only */
1160
+ @media (min-width: 769px) {
1161
+ .mobile-only { display: none !important; }
1162
+ }
1163
+
1164
+ /* ==========================================================================
1165
+ Input More Bottom Sheet (mobile)
1166
+ ========================================================================== */
1167
+
1168
+ #input-more-sheet {
1169
+ position: fixed;
1170
+ inset: 0;
1171
+ z-index: 10000;
1172
+ pointer-events: none;
1173
+ }
1174
+
1175
+ #input-more-sheet.hidden {
1176
+ display: none;
1177
+ }
1178
+
1179
+ .input-more-backdrop {
1180
+ position: absolute;
1181
+ inset: 0;
1182
+ background: rgba(0, 0, 0, 0.4);
1183
+ opacity: 0;
1184
+ transition: opacity 0.2s ease;
1185
+ pointer-events: auto;
1186
+ }
1187
+
1188
+ #input-more-sheet.open .input-more-backdrop {
1189
+ opacity: 1;
1190
+ }
1191
+
1192
+ .input-more-content {
1193
+ position: absolute;
1194
+ left: 0;
1195
+ right: 0;
1196
+ bottom: 0;
1197
+ background: var(--bg);
1198
+ border-top-left-radius: 16px;
1199
+ border-top-right-radius: 16px;
1200
+ padding: 8px 0 calc(var(--safe-bottom) + 16px);
1201
+ transform: translateY(100%);
1202
+ transition: transform 0.25s ease;
1203
+ pointer-events: auto;
1204
+ box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.15);
1205
+ }
1206
+
1207
+ #input-more-sheet.open .input-more-content {
1208
+ transform: translateY(0);
1209
+ }
1210
+
1211
+ .input-more-handle {
1212
+ width: 40px;
1213
+ height: 4px;
1214
+ border-radius: 2px;
1215
+ background: var(--border-subtle);
1216
+ margin: 8px auto 12px;
1217
+ }
1218
+
1219
+ .input-more-actions {
1220
+ display: grid;
1221
+ grid-template-columns: 1fr 1fr;
1222
+ gap: 8px;
1223
+ padding: 4px 16px 12px;
1224
+ }
1225
+
1226
+ .input-more-action {
1227
+ display: flex;
1228
+ flex-direction: column;
1229
+ align-items: center;
1230
+ justify-content: center;
1231
+ gap: 6px;
1232
+ padding: 16px 8px;
1233
+ background: var(--hover);
1234
+ border: 1px solid var(--border-subtle);
1235
+ border-radius: 10px;
1236
+ font-size: 13px;
1237
+ color: var(--text);
1238
+ cursor: pointer;
1239
+ }
1240
+
1241
+ .input-more-action:active {
1242
+ opacity: 0.7;
1243
+ }
1244
+
1245
+ .input-more-action .lucide {
1246
+ width: 22px;
1247
+ height: 22px;
1248
+ color: var(--text-secondary);
1249
+ }
1250
+
1251
+ .input-more-divider {
1252
+ height: 1px;
1253
+ background: var(--border-subtle);
1254
+ margin: 0 16px;
1255
+ }
1256
+
1257
+ .input-more-section-label {
1258
+ display: flex;
1259
+ align-items: center;
1260
+ gap: 8px;
1261
+ padding: 14px 20px 6px;
1262
+ font-size: 13px;
1263
+ font-weight: 500;
1264
+ color: var(--text-secondary);
1265
+ text-transform: uppercase;
1266
+ letter-spacing: 0.04em;
1267
+ }
1268
+
1269
+ .input-more-section-label .lucide {
1270
+ width: 16px;
1271
+ height: 16px;
1272
+ }
1273
+
1274
+ .input-more-context-body {
1275
+ max-height: 50vh;
1276
+ overflow-y: auto;
1277
+ padding: 0 8px 8px;
1278
+ }
1279
+
1280
+ .input-more-context-body .context-picker-item {
1281
+ padding: 12px 16px;
1282
+ font-size: 15px;
1283
+ border-radius: 8px;
1284
+ }
1285
+
1286
+ .input-more-context-body .context-picker-item .lucide {
1287
+ width: 18px;
1288
+ height: 18px;
1289
+ }
1290
+
1291
+ .input-more-context-body .context-picker-section-label {
1292
+ padding: 10px 16px 4px;
1140
1293
  }
1141
1294
 
1142
1295
  /* ==========================================================================
@@ -81,6 +81,13 @@
81
81
  }
82
82
  .notif-banner-icon .lucide { width: 16px; height: 16px; }
83
83
  .notif-banner-emoji { font-size: 18px; line-height: 1; }
84
+ .notif-banner-avatar {
85
+ width: 100%;
86
+ height: 100%;
87
+ object-fit: cover;
88
+ border-radius: 8px;
89
+ display: block;
90
+ }
84
91
 
85
92
  .notif-banner-body {
86
93
  flex: 1;
@@ -18,3 +18,50 @@
18
18
  }
19
19
 
20
20
  .tooltip.visible { opacity: 1; }
21
+
22
+ .tooltip.multi-line {
23
+ white-space: pre-line;
24
+ text-align: left;
25
+ max-width: 320px;
26
+ line-height: 1.5;
27
+ }
28
+
29
+ /* Context sources tooltip */
30
+ .ctx-tip-header {
31
+ font-size: 11px;
32
+ font-weight: 600;
33
+ text-transform: uppercase;
34
+ letter-spacing: 0.04em;
35
+ color: var(--text-muted);
36
+ margin-bottom: 6px;
37
+ }
38
+
39
+ .ctx-tip-row {
40
+ display: flex;
41
+ align-items: center;
42
+ gap: 8px;
43
+ padding: 4px 0;
44
+ color: var(--text);
45
+ font-size: 12px;
46
+ }
47
+
48
+ .ctx-tip-row .lucide {
49
+ width: 14px;
50
+ height: 14px;
51
+ flex-shrink: 0;
52
+ color: var(--text-secondary);
53
+ }
54
+
55
+ .ctx-tip-favicon {
56
+ width: 14px;
57
+ height: 14px;
58
+ flex-shrink: 0;
59
+ border-radius: 2px;
60
+ }
61
+
62
+ .ctx-tip-row span {
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ white-space: nowrap;
66
+ max-width: 260px;
67
+ }
@@ -352,6 +352,7 @@
352
352
  <div class="status">
353
353
  <button id="debate-pdf-btn" class="hidden" title="Export debate as PDF"><i data-lucide="download"></i></button>
354
354
  <button id="find-in-session-btn" title="Search in session (Ctrl+F)"><i data-lucide="search"></i></button>
355
+ <button id="terminal-toggle-btn" title="Terminal"><i data-lucide="square-terminal"></i><span id="terminal-count" class="hidden"></span></button>
355
356
  </div>
356
357
  </div>
357
358
  <div id="main-panels">
@@ -459,13 +460,14 @@
459
460
  </div>
460
461
  <div id="input-bottom">
461
462
  <div id="attach-wrap">
462
- <button id="attach-file-btn" type="button" aria-label="Attach file" title="Attach file"><i data-lucide="paperclip"></i></button>
463
- <button id="attach-image-btn" type="button" aria-label="Attach image" title="Attach image"><i data-lucide="image"></i></button>
463
+ <button id="input-more-btn" type="button" aria-label="More options" title="More options" class="mobile-only"><i data-lucide="plus"></i></button>
464
+ <button id="attach-file-btn" type="button" aria-label="Attach file" title="Attach file" class="desktop-only"><i data-lucide="paperclip"></i></button>
465
+ <button id="attach-image-btn" type="button" aria-label="Attach image" title="Attach image" class="desktop-only"><i data-lucide="image"></i></button>
464
466
  <button id="stt-btn" type="button" aria-label="Voice input" title="Voice input"><i data-lucide="mic"></i></button>
465
467
  <button id="schedule-btn" type="button" aria-label="Schedule message" title="Schedule message"><i data-lucide="clock"></i></button>
466
468
  <button id="ask-mate-btn" type="button" aria-label="Ask Mate" title="Ask a Mate for advice on this session"><i data-lucide="at-sign"></i></button>
467
- <div id="context-sources-btn-wrap">
468
- <button id="context-sources-add" type="button" title="Add context sources"><i data-lucide="plus"></i><span class="ctx-label">Context</span></button>
469
+ <div id="context-sources-btn-wrap" class="desktop-only">
470
+ <button id="context-sources-add" type="button" title="Add context sources"><i data-lucide="library"></i><span class="ctx-label">Context</span></button>
469
471
  <div id="context-sources-picker" class="hidden">
470
472
  <div class="context-picker-section" id="context-picker-email"></div>
471
473
  <div class="context-picker-section" id="context-picker-terminals"></div>
@@ -542,6 +544,34 @@
542
544
  </div>
543
545
  </div>
544
546
  </div>
547
+ <!-- Mobile input-more bottom sheet: attach / image + context sources -->
548
+ <div id="input-more-sheet" class="hidden">
549
+ <div class="input-more-backdrop"></div>
550
+ <div class="input-more-content">
551
+ <div class="input-more-handle"></div>
552
+ <div class="input-more-actions">
553
+ <button class="input-more-action" id="input-more-attach">
554
+ <i data-lucide="paperclip"></i>
555
+ <span>Attach file</span>
556
+ </button>
557
+ <button class="input-more-action" id="input-more-image">
558
+ <i data-lucide="image"></i>
559
+ <span>Image</span>
560
+ </button>
561
+ </div>
562
+ <div class="input-more-divider"></div>
563
+ <div class="input-more-section-label">
564
+ <i data-lucide="library"></i>
565
+ <span>Context sources</span>
566
+ </div>
567
+ <div class="input-more-context-body" id="input-more-context-body">
568
+ <div class="context-picker-section" id="context-picker-email-mobile"></div>
569
+ <div class="context-picker-section" id="context-picker-terminals-mobile"></div>
570
+ <div class="context-picker-section" id="context-picker-tabs-mobile"></div>
571
+ </div>
572
+ </div>
573
+ </div>
574
+
545
575
  <!-- Mobile fullscreen sheet overlay (Projects / Sessions) -->
546
576
  <div id="mobile-sheet" class="hidden">
547
577
  <div class="mobile-sheet-backdrop"></div>
@@ -210,6 +210,8 @@ export function enterDmMode(key, targetUser, messages) {
210
210
  // Close file viewer and terminal panel BEFORE switching WS (needs old WS still open)
211
211
  try { closeFileViewer(); } catch(e) {}
212
212
  closeTerminal();
213
+ var termBtn = document.getElementById("terminal-toggle-btn");
214
+ if (termBtn) termBtn.style.display = "none";
213
215
  // Apply mate color to chat title bar and panels
214
216
  var mateColor = (targetUser.profile && targetUser.profile.avatarColor) || targetUser.avatarColor || "#7c3aed";
215
217
  document.body.style.setProperty("--mate-color", mateColor);
@@ -323,6 +325,9 @@ export function exitDmMode(skipProjectSwitch) {
323
325
  hideKnowledge();
324
326
  hideMemory();
325
327
  if (isSchedulerOpen()) closeScheduler();
328
+ // Restore terminal button
329
+ var termBtn = document.getElementById("terminal-toggle-btn");
330
+ if (termBtn) termBtn.style.display = "";
326
331
  // Reset DM header
327
332
  var dmHeaderBar = document.getElementById("dm-header-bar");
328
333
  if (dmHeaderBar) {
@@ -11,7 +11,7 @@ import { refreshIcons, iconHtml } from './icons.js';
11
11
  import { renderMarkdown } from './markdown.js';
12
12
  import { updatePageTitle } from './sidebar.js';
13
13
  import { renderSessionList, updateSessionPresence, populateCliSessionList, handleSearchResults, updateSessionBadge } from './sidebar-sessions.js';
14
- import { updateDmBadge, renderSidebarPresence } from './sidebar-mates.js';
14
+ import { updateDmBadge, renderSidebarPresence, setMentionActive, renderUserStrip } from './sidebar-mates.js';
15
15
  import { refreshMobileChatSheet } from './sidebar-mobile.js';
16
16
  import { renderMateSessionList, handleMateSearchResults, updateMateSidebarProfile } from './mate-sidebar.js';
17
17
  import { renderKnowledgeList, handleKnowledgeContent } from './mate-knowledge.js';
@@ -38,7 +38,7 @@ import { handleLoopRegistryUpdated, handleScheduleRunStarted, handleScheduleRunF
38
38
 
39
39
  // --- App module imports ---
40
40
  import { scrollToBottom, addToMessages, addUserMessage, addSystemMessage, removeMatePreThinking, appendDelta, finalizeAssistantBlock, addConflictMessage, addContextOverflowMessage, addAuthRequiredMessage, showSuggestionChips } from './app-rendering.js';
41
- import { setActivity, startUrgentBlink, stopUrgentBlink, blinkSessionDot } from './app-favicon.js';
41
+ import { setActivity, startUrgentBlink, stopUrgentBlink, blinkSessionDot, updateCrossProjectBlink } from './app-favicon.js';
42
42
  import { setStatus } from './app-connection.js';
43
43
  import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel } from './app-panels.js';
44
44
  import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress } from './app-projects.js';
@@ -369,9 +369,9 @@ export function processMessage(msg) {
369
369
 
370
370
  case "codex_config":
371
371
  store.set({
372
- codexApproval: msg.approval || "on-failure",
373
- codexSandbox: msg.sandbox || "workspace-write",
374
- codexWebSearch: msg.webSearch || "disabled",
372
+ codexApproval: msg.approval,
373
+ codexSandbox: msg.sandbox,
374
+ codexWebSearch: msg.webSearch,
375
375
  });
376
376
  break;
377
377
 
@@ -1171,6 +1171,7 @@ export function processMessage(msg) {
1171
1171
 
1172
1172
  case "projects_updated":
1173
1173
  updateProjectList(msg);
1174
+ renderUserStrip();
1174
1175
  break;
1175
1176
 
1176
1177
  case "project_owner_changed":
@@ -1324,6 +1325,7 @@ export function processMessage(msg) {
1324
1325
  case "mention_processing":
1325
1326
  // Broadcast: show/hide activity dot on mate avatar across all tabs
1326
1327
  if (msg.mateId) {
1328
+ setMentionActive(msg.mateId, msg.active);
1327
1329
  var mateContainers = document.querySelectorAll('.icon-strip-mate[data-user-id="' + msg.mateId + '"]');
1328
1330
  for (var mi = 0; mi < mateContainers.length; mi++) {
1329
1331
  var dot = mateContainers[mi].querySelector(".icon-strip-status");
@@ -1335,6 +1337,7 @@ export function processMessage(msg) {
1335
1337
  mateContainers[mi].classList.remove("mention-active");
1336
1338
  }
1337
1339
  }
1340
+ updateCrossProjectBlink();
1338
1341
  }
1339
1342
  break;
1340
1343
 
@@ -9,6 +9,7 @@ import { getWs } from './ws-ref.js';
9
9
  import { openDm } from './app-dm.js';
10
10
  import { getCachedProjects } from './app-projects.js';
11
11
  import { switchProject } from './app-projects.js';
12
+ import { mateAvatarUrl } from './avatar.js';
12
13
  var notifications = [];
13
14
  var unreadCount = 0;
14
15
  var bannerContainer = null;
@@ -16,9 +17,10 @@ var bellBtn = null;
16
17
  var badgeEl = null;
17
18
 
18
19
  // --- Update available banner state ---
20
+ // Server pushes update_available on an hourly boundary; dismissal is
21
+ // per-banner-instance and doesn't need to persist. The next server push
22
+ // (next hour) acts as a fresh ping.
19
23
  var pendingUpdateMsg = null;
20
- var updateReshowTimer = null;
21
- var UPDATE_RESHOW_INTERVAL = 60 * 60 * 1000; // 1 hour
22
24
 
23
25
  // ========================================================
24
26
  // Init
@@ -49,10 +51,12 @@ function showAllBanners() {
49
51
  // Clear existing banners first
50
52
  if (bannerContainer) bannerContainer.innerHTML = "";
51
53
 
52
- // Re-add update banner if present
54
+ // Re-add update banner if present (may be suppressed by recent dismiss)
53
55
  if (pendingUpdateMsg) showUpdateBanner(pendingUpdateMsg);
54
56
 
55
- if (notifications.length === 0 && !pendingUpdateMsg) {
57
+ // Check if any banner actually got rendered (update banner can be suppressed)
58
+ var hasVisibleBanner = bannerContainer.children.length > 0;
59
+ if (notifications.length === 0 && !hasVisibleBanner) {
56
60
  showBanner({
57
61
  id: "_empty",
58
62
  type: "info",
@@ -79,14 +83,17 @@ function showBanner(notif, autoDismissMs) {
79
83
  var projectIcon = isEmpty ? null : getProjectIcon(notif.slug);
80
84
  var projectName = isEmpty ? "" : getProjectName(notif.slug);
81
85
  var isPermission = notif.type === "permission_request" && notif.meta && notif.meta.requestId;
86
+ var mate = isEmpty ? null : getMateForNotification(notif);
82
87
 
83
88
  var banner = document.createElement("div");
84
89
  banner.className = "notif-banner" + (isPermission ? " notif-banner-permission" : "");
85
90
  if (!isEmpty) banner.setAttribute("data-notif-id", notif.id);
86
91
 
87
- var iconHtmlStr = projectIcon
88
- ? '<span class="notif-banner-emoji">' + projectIcon + '</span>'
89
- : iconHtml(isEmpty ? "check-circle" : "folder");
92
+ var iconHtmlStr = mate
93
+ ? '<img class="notif-banner-avatar" src="' + escapeHtml(mateAvatarUrl(mate, 32)) + '" alt="' + escapeHtml(mate.displayName || mate.name || "Mate") + '">'
94
+ : projectIcon
95
+ ? '<span class="notif-banner-emoji">' + projectIcon + '</span>'
96
+ : iconHtml(isEmpty ? "check-circle" : "folder");
90
97
 
91
98
  // Format permission title as "Can I ..." style
92
99
  if (isPermission && notif.meta) {
@@ -101,7 +108,7 @@ function showBanner(notif, autoDismissMs) {
101
108
  actionsHtml =
102
109
  '<div class="notif-banner-actions">' +
103
110
  '<button class="notif-banner-allow">Sure</button>' +
104
- '<button class="notif-banner-always">Always allow</button>' +
111
+ '<button class="notif-banner-always">Allow for session</button>' +
105
112
  '<button class="notif-banner-deny">No</button>' +
106
113
  '<button class="notif-banner-goto" title="Go to session">' + iconHtml("external-link") + '</button>' +
107
114
  '</div>';
@@ -300,8 +307,12 @@ function updateBadge() {
300
307
  // ========================================================
301
308
 
302
309
  function navigateToNotification(notif) {
303
- if (notif.mateId) {
304
- openDm(notif.mateId);
310
+ var mateId = notif.mateId || deriveMateIdFromNotification(notif);
311
+ if (mateId) {
312
+ if (notif.sessionId) {
313
+ try { sessionStorage.setItem("pending-notif-session", notif.sessionId); } catch (e) {}
314
+ }
315
+ openDm(mateId);
305
316
  return;
306
317
  }
307
318
 
@@ -322,6 +333,25 @@ function navigateToNotification(notif) {
322
333
  }
323
334
  }
324
335
 
336
+ function deriveMateIdFromNotification(notif) {
337
+ if (!notif) return null;
338
+ if (typeof notif.slug === "string" && notif.slug.indexOf("mate-") === 0) {
339
+ return notif.slug.substring(5) || null;
340
+ }
341
+ return null;
342
+ }
343
+
344
+ function getMateForNotification(notif) {
345
+ var mateId = notif && notif.meta ? notif.meta.avatarMateId : null;
346
+ if (!mateId) mateId = deriveMateIdFromNotification(notif);
347
+ if (!mateId) return null;
348
+ var mates = store.get('cachedMatesList') || [];
349
+ for (var i = 0; i < mates.length; i++) {
350
+ if (mates[i] && mates[i].id === mateId) return mates[i];
351
+ }
352
+ return { id: mateId };
353
+ }
354
+
325
355
  // ========================================================
326
356
  // Update available banner
327
357
  // ========================================================
@@ -383,25 +413,17 @@ export function showUpdateBanner(msg) {
383
413
  });
384
414
  }
385
415
 
386
- // Close button -> dismiss, re-show in 1 hour
416
+ // Close button -> dismiss. No local throttle; the server pushes a new
417
+ // update_available on the next hour boundary, which re-shows naturally.
387
418
  var closeBtn = banner.querySelector(".notif-banner-close");
388
419
  if (closeBtn) {
389
420
  closeBtn.addEventListener("click", function (e) {
390
421
  e.stopPropagation();
391
422
  removeBanner(banner);
392
- scheduleUpdateReshow();
393
423
  });
394
424
  }
395
425
  }
396
426
 
397
- function scheduleUpdateReshow() {
398
- if (updateReshowTimer) clearTimeout(updateReshowTimer);
399
- updateReshowTimer = setTimeout(function () {
400
- updateReshowTimer = null;
401
- if (pendingUpdateMsg) showUpdateBanner(pendingUpdateMsg);
402
- }, UPDATE_RESHOW_INTERVAL);
403
- }
404
-
405
427
  // ========================================================
406
428
  // Helpers
407
429
  // ========================================================
@@ -335,15 +335,15 @@ function rebuildCodexSections() {
335
335
 
336
336
  if (configApprovalSection) {
337
337
  configApprovalSection.style.display = isCodex ? "" : "none";
338
- if (isCodex) buildSegmentedBar(configApprovalBar, CODEX_APPROVAL_OPTIONS, s.codexApproval || "on-failure", "set_codex_approval", "approval");
338
+ if (isCodex) buildSegmentedBar(configApprovalBar, CODEX_APPROVAL_OPTIONS, s.codexApproval, "set_codex_approval", "approval");
339
339
  }
340
340
  if (configSandboxSection) {
341
341
  configSandboxSection.style.display = isCodex ? "" : "none";
342
- if (isCodex) buildSegmentedBar(configSandboxBar, CODEX_SANDBOX_OPTIONS, s.codexSandbox || "workspace-write", "set_codex_sandbox", "sandbox");
342
+ if (isCodex) buildSegmentedBar(configSandboxBar, CODEX_SANDBOX_OPTIONS, s.codexSandbox, "set_codex_sandbox", "sandbox");
343
343
  }
344
344
  if (configWebsearchSection) {
345
345
  configWebsearchSection.style.display = isCodex ? "" : "none";
346
- if (isCodex) buildSegmentedBar(configWebsearchBar, CODEX_WEBSEARCH_OPTIONS, s.codexWebSearch || "disabled", "set_codex_websearch", "webSearch");
346
+ if (isCodex) buildSegmentedBar(configWebsearchBar, CODEX_WEBSEARCH_OPTIONS, s.codexWebSearch, "set_codex_websearch", "webSearch");
347
347
  }
348
348
  }
349
349
 
@@ -24,6 +24,7 @@ import { connect, cancelReconnect, setStatus } from './app-connection.js';
24
24
  import { setTurnCounter, setPrependAnchor, setActivityEl, setIsUserScrolledUp, hideSuggestionChips } from './app-rendering.js';
25
25
  import { resetToolState, enableMainInput, resetTurnMetaCost } from './tools.js';
26
26
  import { clearPendingImages } from './input.js';
27
+ import { clearAllMentionActive } from './sidebar-mates.js';
27
28
  import { setRewindMode } from './rewind.js';
28
29
  import { resetUsage, resetContext } from './app-panels.js';
29
30
  import { resetRateLimitState } from './app-rate-limit.js';
@@ -366,6 +367,7 @@ export function resetClientState() {
366
367
  store.set({ currentFullText: "" });
367
368
  resetToolState();
368
369
  clearPendingImages();
370
+ clearAllMentionActive();
369
371
  setActivityEl(null);
370
372
  store.set({ processing: false });
371
373
  setTurnCounter(0);