clay-server 2.31.0 → 2.32.0-beta.1

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.
Files changed (74) hide show
  1. package/lib/browser-mcp-server.js +32 -44
  2. package/lib/debate-mcp-server.js +14 -31
  3. package/lib/mcp-local.js +31 -1
  4. package/lib/project-connection.js +4 -2
  5. package/lib/project-filesystem.js +47 -1
  6. package/lib/project-http.js +75 -8
  7. package/lib/project-mcp.js +4 -0
  8. package/lib/project-sessions.js +88 -51
  9. package/lib/project-user-message.js +12 -7
  10. package/lib/project.js +204 -90
  11. package/lib/public/app.js +123 -448
  12. package/lib/public/codex-avatar.png +0 -0
  13. package/lib/public/css/debate.css +3 -2
  14. package/lib/public/css/filebrowser.css +91 -1
  15. package/lib/public/css/icon-strip.css +21 -5
  16. package/lib/public/css/input.css +181 -100
  17. package/lib/public/css/mates.css +43 -0
  18. package/lib/public/css/mention.css +48 -4
  19. package/lib/public/css/menus.css +1 -1
  20. package/lib/public/css/messages.css +2 -0
  21. package/lib/public/css/notifications-center.css +19 -0
  22. package/lib/public/index.html +46 -24
  23. package/lib/public/modules/app-connection.js +138 -37
  24. package/lib/public/modules/app-cursors.js +18 -17
  25. package/lib/public/modules/app-debate-ui.js +9 -9
  26. package/lib/public/modules/app-dm.js +170 -131
  27. package/lib/public/modules/app-favicon.js +28 -26
  28. package/lib/public/modules/app-header.js +79 -68
  29. package/lib/public/modules/app-home-hub.js +55 -47
  30. package/lib/public/modules/app-loop-ui.js +34 -18
  31. package/lib/public/modules/app-loop-wizard.js +6 -6
  32. package/lib/public/modules/app-messages.js +195 -152
  33. package/lib/public/modules/app-misc.js +23 -12
  34. package/lib/public/modules/app-notifications.js +91 -3
  35. package/lib/public/modules/app-panels.js +203 -49
  36. package/lib/public/modules/app-projects.js +159 -150
  37. package/lib/public/modules/app-rate-limit.js +5 -4
  38. package/lib/public/modules/app-rendering.js +149 -101
  39. package/lib/public/modules/app-skills-install.js +4 -4
  40. package/lib/public/modules/context-sources.js +12 -41
  41. package/lib/public/modules/dom-refs.js +21 -0
  42. package/lib/public/modules/filebrowser.js +173 -2
  43. package/lib/public/modules/input.js +86 -0
  44. package/lib/public/modules/mate-sidebar.js +38 -0
  45. package/lib/public/modules/mention.js +24 -6
  46. package/lib/public/modules/scheduler.js +1 -1
  47. package/lib/public/modules/sidebar-mates.js +66 -34
  48. package/lib/public/modules/sidebar-mobile.js +34 -30
  49. package/lib/public/modules/sidebar-projects.js +60 -57
  50. package/lib/public/modules/sidebar-sessions.js +75 -69
  51. package/lib/public/modules/sidebar.js +12 -20
  52. package/lib/public/modules/skills.js +8 -9
  53. package/lib/public/modules/sticky-notes.js +1 -2
  54. package/lib/public/modules/store.js +9 -2
  55. package/lib/public/modules/stt.js +4 -1
  56. package/lib/public/modules/tools.js +14 -9
  57. package/lib/sdk-bridge.js +511 -1113
  58. package/lib/sdk-message-processor.js +123 -134
  59. package/lib/sdk-worker.js +4 -0
  60. package/lib/server-dm.js +1 -0
  61. package/lib/server.js +86 -1
  62. package/lib/sessions.js +47 -36
  63. package/lib/ws-schema.js +2 -0
  64. package/lib/yoke/adapters/claude-worker.js +559 -0
  65. package/lib/yoke/adapters/claude.js +1418 -0
  66. package/lib/yoke/adapters/codex.js +968 -0
  67. package/lib/yoke/adapters/gemini.js +668 -0
  68. package/lib/yoke/codex-app-server.js +307 -0
  69. package/lib/yoke/index.js +199 -0
  70. package/lib/yoke/instructions.js +62 -0
  71. package/lib/yoke/interface.js +92 -0
  72. package/lib/yoke/mcp-bridge-server.js +294 -0
  73. package/lib/yoke/package.json +7 -0
  74. package/package.json +3 -1
@@ -5,8 +5,18 @@ import { userAvatarUrl, mateAvatarUrl } from './avatar.js';
5
5
  import { escapeHtml } from './utils.js';
6
6
  import { iconHtml, refreshIcons } from './icons.js';
7
7
  import { showMateProfilePopover } from './profile.js';
8
-
9
- var _ctx = null;
8
+ import { store } from './store.js';
9
+ import { getWs } from './ws-ref.js';
10
+ import { closeProjectCtxMenu } from './sidebar-projects.js';
11
+ import { spawnDustParticles } from './sidebar.js';
12
+ import { openDm } from './app-dm.js';
13
+ import { openMateWizard } from './mate-wizard.js';
14
+ import { getCachedProjects } from './app-projects.js';
15
+
16
+ function sendWs(msg) {
17
+ var ws = getWs();
18
+ if (ws && ws.readyState === 1) ws.send(JSON.stringify(msg));
19
+ }
10
20
 
11
21
  // --- User strip state ---
12
22
  var cachedAllUsers = [];
@@ -27,8 +37,20 @@ var iconStripTooltip = null;
27
37
  // --- DM user context menu ---
28
38
  var userCtxMenu = null;
29
39
 
30
- export function initSidebarMates(ctx) {
31
- _ctx = ctx;
40
+ export function initSidebarMates() {
41
+ // --- Reactive UI sync for user strip ---
42
+ store.subscribe(function (state, prev) {
43
+ if (state.cachedAllUsers !== prev.cachedAllUsers ||
44
+ state.cachedOnlineIds !== prev.cachedOnlineIds ||
45
+ state.cachedDmFavorites !== prev.cachedDmFavorites ||
46
+ state.cachedDmConversations !== prev.cachedDmConversations ||
47
+ state.dmUnread !== prev.dmUnread ||
48
+ state.dmRemovedUsers !== prev.dmRemovedUsers ||
49
+ state.cachedMatesList !== prev.cachedMatesList ||
50
+ state.myUserId !== prev.myUserId) {
51
+ renderUserStrip();
52
+ }
53
+ });
32
54
  }
33
55
 
34
56
  export function showIconTooltip(el, text) {
@@ -80,7 +102,7 @@ export function closeUserCtxMenu() {
80
102
 
81
103
  function showUserCtxMenu(anchorEl, user) {
82
104
  closeUserCtxMenu();
83
- if (_ctx.closeProjectCtxMenu) _ctx.closeProjectCtxMenu();
105
+ if (closeProjectCtxMenu) closeProjectCtxMenu();
84
106
 
85
107
  var menu = document.createElement("div");
86
108
  menu.className = "project-ctx-menu";
@@ -92,16 +114,14 @@ function showUserCtxMenu(anchorEl, user) {
92
114
  e.stopPropagation();
93
115
  // Spawn dust particles at the user icon position
94
116
  var iconRect = anchorEl.getBoundingClientRect();
95
- if (_ctx.spawnDustParticles) _ctx.spawnDustParticles(iconRect.left + iconRect.width / 2, iconRect.top + iconRect.height / 2);
117
+ if (spawnDustParticles) spawnDustParticles(iconRect.left + iconRect.width / 2, iconRect.top + iconRect.height / 2);
96
118
  closeUserCtxMenu();
97
119
  // Immediately mark as removed so strip re-render hides the icon,
98
120
  // even if the user was only visible via cachedDmConversations (not favorites)
99
121
  cachedDmRemovedUsers[user.id] = true;
100
- if (_ctx.onDmRemoveUser) _ctx.onDmRemoveUser(user.id);
101
- renderUserStrip(cachedAllUsers, cachedOnlineUserIds, cachedMyUserId, cachedDmFavorites, cachedDmConversations, cachedDmUnread, cachedDmRemovedUsers, cachedMates);
102
- if (_ctx.sendWs) {
103
- _ctx.sendWs({ type: "dm_remove_favorite", targetUserId: user.id });
104
- }
122
+ var dr = Object.assign({}, store.get('dmRemovedUsers')); dr[user.id] = true; store.set({ dmRemovedUsers: dr });
123
+ // renderUserStrip is handled by the store subscriber
124
+ sendWs({ type: "dm_remove_favorite", targetUserId: user.id });
105
125
  });
106
126
  menu.appendChild(removeItem);
107
127
 
@@ -140,7 +160,7 @@ function showMateCtxMenu(anchorEl, mate) {
140
160
  if (mate.primary) return;
141
161
 
142
162
  closeUserCtxMenu();
143
- if (_ctx.closeProjectCtxMenu) _ctx.closeProjectCtxMenu();
163
+ if (closeProjectCtxMenu) closeProjectCtxMenu();
144
164
 
145
165
  var menu = document.createElement("div");
146
166
  menu.className = "project-ctx-menu";
@@ -153,9 +173,7 @@ function showMateCtxMenu(anchorEl, mate) {
153
173
  e.stopPropagation();
154
174
  closeUserCtxMenu();
155
175
  showMateProfilePopover(anchorEl, mate, function (updates) {
156
- if (_ctx.sendWs) {
157
- _ctx.sendWs({ type: "mate_update", mateId: mate.id, updates: updates });
158
- }
176
+ sendWs({ type: "mate_update", mateId: mate.id, updates: updates });
159
177
  });
160
178
  });
161
179
  menu.appendChild(editItem);
@@ -168,10 +186,8 @@ function showMateCtxMenu(anchorEl, mate) {
168
186
  closeUserCtxMenu();
169
187
  // Spawn dust particles at the mate icon position
170
188
  var iconRect = anchorEl.getBoundingClientRect();
171
- if (_ctx.spawnDustParticles) _ctx.spawnDustParticles(iconRect.left + iconRect.width / 2, iconRect.top + iconRect.height / 2);
172
- if (_ctx.sendWs) {
173
- _ctx.sendWs({ type: "dm_remove_favorite", targetUserId: mate.id });
174
- }
189
+ if (spawnDustParticles) spawnDustParticles(iconRect.left + iconRect.width / 2, iconRect.top + iconRect.height / 2);
190
+ sendWs({ type: "dm_remove_favorite", targetUserId: mate.id });
175
191
  });
176
192
  menu.appendChild(removeItem);
177
193
 
@@ -238,7 +254,20 @@ function presenceAvatarUrl(userOrStyle) {
238
254
  return userAvatarUrl({ avatarStyle: userOrStyle || "thumbs" }, 24);
239
255
  }
240
256
 
257
+ // renderUserStrip: call with no args to read from store (subscriber pattern),
258
+ // or with all 8 args for legacy compatibility.
241
259
  export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites, dmConversations, dmUnread, dmRemovedUsers, matesList) {
260
+ if (arguments.length === 0) {
261
+ var s = store.snap();
262
+ allUsers = s.cachedAllUsers;
263
+ onlineUserIds = s.cachedOnlineIds;
264
+ myUserId = s.myUserId;
265
+ dmFavorites = s.cachedDmFavorites;
266
+ dmConversations = s.cachedDmConversations;
267
+ dmUnread = s.dmUnread;
268
+ dmRemovedUsers = s.dmRemovedUsers;
269
+ matesList = s.cachedMatesList;
270
+ }
242
271
  // Skip full DOM rebuild if input data hasn't changed
243
272
  var fingerprint = JSON.stringify([allUsers, onlineUserIds, dmFavorites, dmConversations, dmUnread, dmRemovedUsers, matesList]);
244
273
  if (fingerprint === _lastUserStripJson) return;
@@ -311,7 +340,7 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
311
340
 
312
341
  // Click: open DM
313
342
  el.addEventListener("click", function () {
314
- if (_ctx.openDm) _ctx.openDm(u.id);
343
+ if (openDm) openDm(u.id);
315
344
  });
316
345
 
317
346
  // Right-click: show context menu
@@ -327,8 +356,9 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
327
356
 
328
357
  // Build mate project status lookup from project list
329
358
  var mateProjectStatus = {};
330
- if (_ctx && _ctx.projectList) {
331
- var allProjects = _ctx.projectList;
359
+ var _projList = getCachedProjects() || [];
360
+ if (_projList.length) {
361
+ var allProjects = _projList;
332
362
  for (var pi = 0; pi < allProjects.length; pi++) {
333
363
  if (allProjects[pi].isMate) {
334
364
  mateProjectStatus[allProjects[pi].slug] = allProjects[pi];
@@ -380,7 +410,7 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
380
410
  avatar.style.background = mateColor + "30";
381
411
  el.appendChild(avatar);
382
412
 
383
- // Processing status dot (IO blink)
413
+ // Processing status dot (IO blink) - top-left
384
414
  var statusDot = document.createElement("span");
385
415
  statusDot.className = "icon-strip-status";
386
416
  if (mateProj.isProcessing) statusDot.classList.add("processing");
@@ -406,6 +436,8 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
406
436
 
407
437
  // Tooltip
408
438
  var displayName = mp.displayName || mate.name || "New Mate";
439
+ var mateVendor = mate.vendor || "claude";
440
+ var vendorLabels = { claude: "Claude Code", codex: "OpenAI Codex" };
409
441
  el.addEventListener("mouseenter", function () {
410
442
  var html = '<div style="font-weight:600">' + escapeHtml(displayName);
411
443
  if (mate.primary) {
@@ -415,13 +447,15 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
415
447
  if (mate.bio) {
416
448
  html += '<div style="font-weight:400;font-size:12px;color:var(--text-secondary);margin-top:2px">' + escapeHtml(mate.bio) + '</div>';
417
449
  }
450
+ var vendorLabel = vendorLabels[mateVendor] || mateVendor;
451
+ html += '<div style="font-size:11px;color:var(--text-dimmer);margin-top:3px">Powered by ' + escapeHtml(vendorLabel) + '</div>';
418
452
  showIconTooltipHtml(el, html);
419
453
  });
420
454
  el.addEventListener("mouseleave", hideIconTooltip);
421
455
 
422
456
  // Click: open DM with mate
423
457
  el.addEventListener("click", function () {
424
- if (_ctx.openDm) _ctx.openDm(mate.id);
458
+ if (openDm) openDm(mate.id);
425
459
  });
426
460
 
427
461
  // Right-click: context menu for mate
@@ -520,9 +554,7 @@ function toggleDmUserPicker(anchorEl) {
520
554
  item.appendChild(name);
521
555
 
522
556
  item.addEventListener("click", function () {
523
- if (_ctx.sendWs) {
524
- _ctx.sendWs({ type: "dm_add_favorite", targetUserId: u.id });
525
- }
557
+ sendWs({ type: "dm_add_favorite", targetUserId: u.id });
526
558
  closeDmUserPicker();
527
559
  });
528
560
 
@@ -570,7 +602,7 @@ function toggleDmUserPicker(anchorEl) {
570
602
  });
571
603
  }
572
604
  // Build unified list: installed builtins, deleted builtins, user-created
573
- var availBuiltins = (_ctx.availableBuiltins && _ctx.availableBuiltins()) || [];
605
+ var availBuiltins = store.get('cachedAvailableBuiltins') || [];
574
606
  var entries = [];
575
607
  // 1. Installed builtin mates
576
608
  for (var si = 0; si < allMates.length; si++) {
@@ -619,12 +651,12 @@ function toggleDmUserPicker(anchorEl) {
619
651
  bAddBtn.title = "Re-add " + b.displayName;
620
652
  bAddBtn.addEventListener("click", function (e) {
621
653
  e.stopPropagation();
622
- if (_ctx.sendWs) _ctx.sendWs({ type: "mate_readd_builtin", builtinKey: b.key });
654
+ sendWs({ type: "mate_readd_builtin", builtinKey: b.key });
623
655
  closeDmUserPicker();
624
656
  });
625
657
  bItem.appendChild(bAddBtn);
626
658
  bItem.addEventListener("click", function () {
627
- if (_ctx.sendWs) _ctx.sendWs({ type: "mate_readd_builtin", builtinKey: b.key });
659
+ sendWs({ type: "mate_readd_builtin", builtinKey: b.key });
628
660
  closeDmUserPicker();
629
661
  });
630
662
  matesListEl.appendChild(bItem);
@@ -675,7 +707,7 @@ function toggleDmUserPicker(anchorEl) {
675
707
  yesBtn.textContent = m.builtinKey ? "Remove" : "Delete";
676
708
  yesBtn.addEventListener("click", function (e2) {
677
709
  e2.stopPropagation();
678
- if (_ctx.sendWs) _ctx.sendWs({ type: "mate_delete", mateId: m.id });
710
+ sendWs({ type: "mate_delete", mateId: m.id });
679
711
  closeDmUserPicker();
680
712
  });
681
713
  item.appendChild(yesBtn);
@@ -693,8 +725,8 @@ function toggleDmUserPicker(anchorEl) {
693
725
  });
694
726
  item.appendChild(delBtn);
695
727
  item.addEventListener("click", function () {
696
- if (_ctx.openDm) _ctx.openDm(m.id);
697
- if (!isFav && _ctx.sendWs) _ctx.sendWs({ type: "dm_add_favorite", targetUserId: m.id });
728
+ if (openDm) openDm(m.id);
729
+ if (!isFav) sendWs({ type: "dm_add_favorite", targetUserId: m.id });
698
730
  closeDmUserPicker();
699
731
  });
700
732
  matesListEl.appendChild(item);
@@ -720,7 +752,7 @@ function toggleDmUserPicker(anchorEl) {
720
752
  createMateEl.innerHTML = iconHtml("bot") + " <span>" + createMateLabel + "</span>";
721
753
  createMateEl.addEventListener("click", function () {
722
754
  closeDmUserPicker();
723
- if (_ctx.openMateWizard) _ctx.openMateWizard();
755
+ if (openMateWizard) openMateWizard();
724
756
  });
725
757
  picker.appendChild(createMateEl);
726
758
 
@@ -26,7 +26,15 @@ import {
26
26
  getCachedDmRemovedUsers
27
27
  } from './sidebar-mates.js';
28
28
 
29
- var _ctx = null;
29
+ import { store } from './store.js';
30
+ import { getWs } from './ws-ref.js';
31
+ import { dismissOverlayPanels, closeSidebar } from './sidebar.js';
32
+ import { switchProject, getCachedProjects } from './app-projects.js';
33
+ import { openDm } from './app-dm.js';
34
+ import { showHomeHub } from './app-home-hub.js';
35
+ import { openTerminal } from './terminal.js';
36
+ import { requestKnowledgeList } from './mate-knowledge.js';
37
+ import { loadRootDirectory } from './filebrowser.js';
30
38
 
31
39
  // --- Mobile state ---
32
40
  var mobileChatSheetOpen = false;
@@ -76,7 +84,7 @@ export function openMobileSheet(type) {
76
84
  listEl.appendChild(fileTree);
77
85
  fileTree.classList.remove("hidden");
78
86
  }
79
- if (_ctx.onFilesTabOpen) _ctx.onFilesTabOpen();
87
+ loadRootDirectory();
80
88
  } else if (type === "mate-knowledge") {
81
89
  titleEl.textContent = "Knowledge";
82
90
  sheet.classList.add("sheet-knowledge");
@@ -86,7 +94,7 @@ export function openMobileSheet(type) {
86
94
  knowledgeFiles.classList.remove("hidden");
87
95
  }
88
96
  // Request knowledge list if not loaded
89
- if (_ctx.requestKnowledgeList) _ctx.requestKnowledgeList();
97
+ requestKnowledgeList();
90
98
  } else if (type === "mate-profile") {
91
99
  titleEl.textContent = "";
92
100
  renderSheetMateProfile(listEl);
@@ -170,7 +178,7 @@ function renderSheetProjects(listEl) {
170
178
  }
171
179
 
172
180
  el.addEventListener("click", function () {
173
- if (_ctx.switchProject) _ctx.switchProject(p.slug);
181
+ if (switchProject) switchProject(p.slug);
174
182
  closeMobileSheet();
175
183
  });
176
184
 
@@ -270,7 +278,7 @@ function renderSheetSessions(listEl) {
270
278
  // Processing dot: same class as icon strip, same data source
271
279
  var mateSlug = "mate-" + mate.id;
272
280
  var mateProj = null;
273
- var allProjects = (_ctx && _ctx.projectList) || [];
281
+ var allProjects = getCachedProjects() || [];
274
282
  for (var pi = 0; pi < allProjects.length; pi++) {
275
283
  if (allProjects[pi].slug === mateSlug) { mateProj = allProjects[pi]; break; }
276
284
  }
@@ -309,7 +317,7 @@ function renderSheetSessions(listEl) {
309
317
  renderMobileSessionsInto(sessionListEl);
310
318
  } else if (type === "mate") {
311
319
  // Mate DM: open the DM and show mate actions
312
- if (_ctx.openDm) _ctx.openDm(mateId);
320
+ openDm(mateId);
313
321
  renderMateMobileActions(sessionListEl);
314
322
  }
315
323
 
@@ -339,7 +347,7 @@ function renderSheetSessions(listEl) {
339
347
  loading.textContent = "Loading sessions...";
340
348
  sessionListEl.appendChild(loading);
341
349
  }
342
- if (_ctx.switchProject) _ctx.switchProject(slug);
350
+ if (switchProject) switchProject(slug);
343
351
  if (!isDmNow || slug !== getCachedCurrentSlug()) {
344
352
  // renderSessionList will be called by WS, which calls refreshMobileChatSheet
345
353
  } else {
@@ -394,10 +402,10 @@ function createMobileSessionItem(s) {
394
402
 
395
403
  (function (id) {
396
404
  el.addEventListener("click", function () {
397
- if (_ctx.ws && _ctx.connected) {
398
- _ctx.ws.send(JSON.stringify({ type: "switch_session", id: id }));
405
+ if (getWs() && store.get('connected')) {
406
+ getWs().send(JSON.stringify({ type: "switch_session", id: id }));
399
407
  }
400
- if (_ctx.dismissOverlayPanels) _ctx.dismissOverlayPanels();
408
+ if (dismissOverlayPanels) dismissOverlayPanels();
401
409
  closeMobileSheet();
402
410
  });
403
411
  })(s.id);
@@ -432,10 +440,10 @@ function createMobileLoopChild(s) {
432
440
 
433
441
  (function (id) {
434
442
  el.addEventListener("click", function () {
435
- if (_ctx.ws && _ctx.connected) {
436
- _ctx.ws.send(JSON.stringify({ type: "switch_session", id: id }));
443
+ if (getWs() && store.get('connected')) {
444
+ getWs().send(JSON.stringify({ type: "switch_session", id: id }));
437
445
  }
438
- if (_ctx.dismissOverlayPanels) _ctx.dismissOverlayPanels();
446
+ if (dismissOverlayPanels) dismissOverlayPanels();
439
447
  closeMobileSheet();
440
448
  });
441
449
  })(s.id);
@@ -645,8 +653,8 @@ function renderMateMobileActions(container) {
645
653
  newSessionBtn.className = "mobile-session-new";
646
654
  newSessionBtn.innerHTML = '<i data-lucide="plus" style="width:16px;height:16px"></i> New session';
647
655
  newSessionBtn.addEventListener("click", function () {
648
- if (_ctx.ws && _ctx.connected) {
649
- _ctx.ws.send(JSON.stringify({ type: "new_session" }));
656
+ if (getWs() && store.get('connected')) {
657
+ getWs().send(JSON.stringify({ type: "new_session" }));
650
658
  }
651
659
  closeMobileSheet();
652
660
  });
@@ -694,8 +702,8 @@ function renderMobileSessionsInto(container) {
694
702
  newBtn.className = "mobile-session-new";
695
703
  newBtn.innerHTML = '<i data-lucide="plus" style="width:16px;height:16px"></i> New session';
696
704
  newBtn.addEventListener("click", function () {
697
- if (_ctx.ws && _ctx.connected) {
698
- _ctx.ws.send(JSON.stringify({ type: "new_session" }));
705
+ if (getWs() && store.get('connected')) {
706
+ getWs().send(JSON.stringify({ type: "new_session" }));
699
707
  }
700
708
  closeMobileSheet();
701
709
  });
@@ -801,7 +809,7 @@ export function refreshMobileChatSheet() {
801
809
  var statusDot = chip.querySelector(".icon-strip-status");
802
810
  if (statusDot) {
803
811
  var isProcessing = false;
804
- var allProjects = (_ctx && _ctx.projectList) || [];
812
+ var allProjects = getCachedProjects() || [];
805
813
  var lookupSlug = chip.dataset.type === "mate" ? ("mate-" + chip.dataset.mateId) : chip.dataset.slug;
806
814
  for (var pi = 0; pi < allProjects.length; pi++) {
807
815
  if (allProjects[pi].slug === lookupSlug && allProjects[pi].isProcessing) {
@@ -948,10 +956,10 @@ function renderSearchResults(container, query) {
948
956
 
949
957
  (function (id) {
950
958
  el.addEventListener("click", function () {
951
- if (_ctx.ws && _ctx.connected) {
952
- _ctx.ws.send(JSON.stringify({ type: "switch_session", id: id }));
959
+ if (getWs() && store.get('connected')) {
960
+ getWs().send(JSON.stringify({ type: "switch_session", id: id }));
953
961
  }
954
- if (_ctx.dismissOverlayPanels) _ctx.dismissOverlayPanels();
962
+ if (dismissOverlayPanels) dismissOverlayPanels();
955
963
  closeMobileSheet();
956
964
  });
957
965
  })(s.id);
@@ -993,7 +1001,7 @@ function renderSheetTools(listEl) {
993
1001
  if (item.action === "files") {
994
1002
  setTimeout(function () { openMobileSheet("files"); }, 250);
995
1003
  } else if (item.action === "terminal") {
996
- if (_ctx.openTerminal) _ctx.openTerminal();
1004
+ openTerminal();
997
1005
  } else if (item.action === "scheduler") {
998
1006
  targetId = "scheduler-btn";
999
1007
  } else if (item.action === "mate-knowledge") {
@@ -1055,7 +1063,7 @@ function renderSheetSettings(listEl) {
1055
1063
  }
1056
1064
  }
1057
1065
  }
1058
- if (proj && _ctx.ownerLocked) proj = Object.assign({}, proj, { ownerLocked: true });
1066
+ if (proj && store.get('ownerLocked')) proj = Object.assign({}, proj, { ownerLocked: true });
1059
1067
  openProjectSettings(getCachedCurrentSlug(), proj);
1060
1068
  }, 250);
1061
1069
  } else if (item.action === "server-settings") {
@@ -1124,11 +1132,7 @@ function renderSheetSettings(listEl) {
1124
1132
  }
1125
1133
  }
1126
1134
 
1127
- export function initSidebarMobile(ctx) {
1128
- _ctx = ctx;
1129
-
1130
- // Put refreshMobileChatSheet on ctx for external callers
1131
- ctx.refreshMobileChatSheet = refreshMobileChatSheet;
1135
+ export function initSidebarMobile() {
1132
1136
 
1133
1137
  // --- Mobile sheet close handlers ---
1134
1138
  var mobileSheet = document.getElementById("mobile-sheet");
@@ -1262,9 +1266,9 @@ export function initSidebarMobile(ctx) {
1262
1266
 
1263
1267
  if (mobileHomeBtn) {
1264
1268
  mobileHomeBtn.addEventListener("click", function () {
1265
- if (_ctx.closeSidebar) _ctx.closeSidebar();
1269
+ closeSidebar();
1266
1270
  setMobileTabActive("home");
1267
- if (_ctx.showHomeHub) _ctx.showHomeHub();
1271
+ showHomeHub();
1268
1272
  });
1269
1273
  }
1270
1274
  }