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.
- package/lib/browser-mcp-server.js +32 -44
- package/lib/debate-mcp-server.js +14 -31
- package/lib/mcp-local.js +31 -1
- package/lib/project-connection.js +4 -2
- package/lib/project-filesystem.js +47 -1
- package/lib/project-http.js +75 -8
- package/lib/project-mcp.js +4 -0
- package/lib/project-sessions.js +88 -51
- package/lib/project-user-message.js +12 -7
- package/lib/project.js +204 -90
- package/lib/public/app.js +123 -448
- package/lib/public/codex-avatar.png +0 -0
- package/lib/public/css/debate.css +3 -2
- package/lib/public/css/filebrowser.css +91 -1
- package/lib/public/css/icon-strip.css +21 -5
- package/lib/public/css/input.css +181 -100
- package/lib/public/css/mates.css +43 -0
- package/lib/public/css/mention.css +48 -4
- package/lib/public/css/menus.css +1 -1
- package/lib/public/css/messages.css +2 -0
- package/lib/public/css/notifications-center.css +19 -0
- package/lib/public/index.html +46 -24
- package/lib/public/modules/app-connection.js +138 -37
- package/lib/public/modules/app-cursors.js +18 -17
- package/lib/public/modules/app-debate-ui.js +9 -9
- package/lib/public/modules/app-dm.js +170 -131
- package/lib/public/modules/app-favicon.js +28 -26
- package/lib/public/modules/app-header.js +79 -68
- package/lib/public/modules/app-home-hub.js +55 -47
- package/lib/public/modules/app-loop-ui.js +34 -18
- package/lib/public/modules/app-loop-wizard.js +6 -6
- package/lib/public/modules/app-messages.js +195 -152
- package/lib/public/modules/app-misc.js +23 -12
- package/lib/public/modules/app-notifications.js +91 -3
- package/lib/public/modules/app-panels.js +203 -49
- package/lib/public/modules/app-projects.js +159 -150
- package/lib/public/modules/app-rate-limit.js +5 -4
- package/lib/public/modules/app-rendering.js +149 -101
- package/lib/public/modules/app-skills-install.js +4 -4
- package/lib/public/modules/context-sources.js +12 -41
- package/lib/public/modules/dom-refs.js +21 -0
- package/lib/public/modules/filebrowser.js +173 -2
- package/lib/public/modules/input.js +86 -0
- package/lib/public/modules/mate-sidebar.js +38 -0
- package/lib/public/modules/mention.js +24 -6
- package/lib/public/modules/scheduler.js +1 -1
- package/lib/public/modules/sidebar-mates.js +66 -34
- package/lib/public/modules/sidebar-mobile.js +34 -30
- package/lib/public/modules/sidebar-projects.js +60 -57
- package/lib/public/modules/sidebar-sessions.js +75 -69
- package/lib/public/modules/sidebar.js +12 -20
- package/lib/public/modules/skills.js +8 -9
- package/lib/public/modules/sticky-notes.js +1 -2
- package/lib/public/modules/store.js +9 -2
- package/lib/public/modules/stt.js +4 -1
- package/lib/public/modules/tools.js +14 -9
- package/lib/sdk-bridge.js +511 -1113
- package/lib/sdk-message-processor.js +123 -134
- package/lib/sdk-worker.js +4 -0
- package/lib/server-dm.js +1 -0
- package/lib/server.js +86 -1
- package/lib/sessions.js +47 -36
- package/lib/ws-schema.js +2 -0
- package/lib/yoke/adapters/claude-worker.js +559 -0
- package/lib/yoke/adapters/claude.js +1418 -0
- package/lib/yoke/adapters/codex.js +968 -0
- package/lib/yoke/adapters/gemini.js +668 -0
- package/lib/yoke/codex-app-server.js +307 -0
- package/lib/yoke/index.js +199 -0
- package/lib/yoke/instructions.js +62 -0
- package/lib/yoke/interface.js +92 -0
- package/lib/yoke/mcp-bridge-server.js +294 -0
- package/lib/yoke/package.json +7 -0
- package/package.json +3 -1
|
@@ -5,8 +5,14 @@ import { avatarUrl, userAvatarUrl } from './avatar.js';
|
|
|
5
5
|
import { escapeHtml } from './utils.js';
|
|
6
6
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
7
7
|
import { openSearch as openSessionSearch } from './session-search.js';
|
|
8
|
+
import { store } from './store.js';
|
|
9
|
+
import { getWs } from './ws-ref.js';
|
|
10
|
+
import { getSessionListEl } from './dom-refs.js';
|
|
11
|
+
import { dismissOverlayPanels, closeSidebar, updatePageTitle } from './sidebar.js';
|
|
12
|
+
import { showConfirm } from './app-misc.js';
|
|
13
|
+
import { getUpcomingSchedules } from './scheduler.js';
|
|
14
|
+
import { refreshMobileChatSheet } from './sidebar-mobile.js';
|
|
8
15
|
|
|
9
|
-
var _ctx = null;
|
|
10
16
|
|
|
11
17
|
// --- Session state ---
|
|
12
18
|
var cachedSessions = [];
|
|
@@ -27,16 +33,15 @@ var countdownContainer = null;
|
|
|
27
33
|
var sessionCtxMenu = null;
|
|
28
34
|
var sessionCtxSessionId = null;
|
|
29
35
|
|
|
30
|
-
export function initSidebarSessions(
|
|
31
|
-
_ctx = ctx;
|
|
36
|
+
export function initSidebarSessions() {
|
|
32
37
|
|
|
33
38
|
document.addEventListener("click", function () { closeSessionCtxMenu(); });
|
|
34
39
|
|
|
35
40
|
// --- Session search ---
|
|
36
|
-
var searchBtn =
|
|
37
|
-
var searchBox =
|
|
38
|
-
var searchInput =
|
|
39
|
-
var searchClear =
|
|
41
|
+
var searchBtn = document.getElementById("search-session-btn");
|
|
42
|
+
var searchBox = document.getElementById("session-search");
|
|
43
|
+
var searchInput = document.getElementById("session-search-input");
|
|
44
|
+
var searchClear = document.getElementById("session-search-clear");
|
|
40
45
|
|
|
41
46
|
function openSearch() {
|
|
42
47
|
searchBox.classList.remove("hidden");
|
|
@@ -79,8 +84,8 @@ export function initSidebarSessions(ctx) {
|
|
|
79
84
|
return;
|
|
80
85
|
}
|
|
81
86
|
searchDebounce = setTimeout(function () {
|
|
82
|
-
if (
|
|
83
|
-
|
|
87
|
+
if (getWs() && store.get('connected')) {
|
|
88
|
+
getWs().send(JSON.stringify({ type: "search_sessions", query: searchQuery }));
|
|
84
89
|
}
|
|
85
90
|
}, 200);
|
|
86
91
|
});
|
|
@@ -93,11 +98,11 @@ export function initSidebarSessions(ctx) {
|
|
|
93
98
|
});
|
|
94
99
|
|
|
95
100
|
// --- Resume session picker ---
|
|
96
|
-
var resumeModal =
|
|
97
|
-
var resumeCancel =
|
|
98
|
-
var pickerLoading =
|
|
99
|
-
var pickerEmpty =
|
|
100
|
-
var pickerList =
|
|
101
|
+
var resumeModal = document.getElementById("resume-modal");
|
|
102
|
+
var resumeCancel = document.getElementById("resume-cancel");
|
|
103
|
+
var pickerLoading = document.getElementById("resume-picker-loading");
|
|
104
|
+
var pickerEmpty = document.getElementById("resume-picker-empty");
|
|
105
|
+
var pickerList = document.getElementById("resume-picker-list");
|
|
101
106
|
|
|
102
107
|
function openResumeModal() {
|
|
103
108
|
resumeModal.classList.remove("hidden");
|
|
@@ -105,8 +110,8 @@ export function initSidebarSessions(ctx) {
|
|
|
105
110
|
pickerEmpty.classList.add("hidden");
|
|
106
111
|
pickerList.classList.add("hidden");
|
|
107
112
|
pickerList.innerHTML = "";
|
|
108
|
-
if (
|
|
109
|
-
|
|
113
|
+
if (getWs() && store.get('connected')) {
|
|
114
|
+
getWs().send(JSON.stringify({ type: "list_cli_sessions" }));
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
117
|
|
|
@@ -114,7 +119,8 @@ export function initSidebarSessions(ctx) {
|
|
|
114
119
|
resumeModal.classList.add("hidden");
|
|
115
120
|
}
|
|
116
121
|
|
|
117
|
-
|
|
122
|
+
var resumeBtn = document.getElementById("resume-session-btn");
|
|
123
|
+
if (resumeBtn) resumeBtn.addEventListener("click", openResumeModal);
|
|
118
124
|
resumeCancel.addEventListener("click", closeResumeModal);
|
|
119
125
|
resumeModal.querySelector(".confirm-backdrop").addEventListener("click", closeResumeModal);
|
|
120
126
|
|
|
@@ -172,7 +178,7 @@ function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData) {
|
|
|
172
178
|
menu.appendChild(renameItem);
|
|
173
179
|
|
|
174
180
|
// Session visibility toggle (only the session owner can change)
|
|
175
|
-
if (
|
|
181
|
+
if (store.get('isMultiUserMode') && sessionData && sessionData.ownerId && sessionData.ownerId === store.get('myUserId')) {
|
|
176
182
|
var currentVis = (sessionData && sessionData.sessionVisibility) || "shared";
|
|
177
183
|
var isPrivate = currentVis === "private";
|
|
178
184
|
var visItem = document.createElement("button");
|
|
@@ -182,23 +188,23 @@ function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData) {
|
|
|
182
188
|
e.stopPropagation();
|
|
183
189
|
closeSessionCtxMenu();
|
|
184
190
|
var newVis = isPrivate ? "shared" : "private";
|
|
185
|
-
if (
|
|
186
|
-
|
|
191
|
+
if (getWs() && store.get('connected')) {
|
|
192
|
+
getWs().send(JSON.stringify({ type: "set_session_visibility", sessionId: sessionId, visibility: newVis }));
|
|
187
193
|
}
|
|
188
194
|
});
|
|
189
195
|
menu.appendChild(visItem);
|
|
190
196
|
}
|
|
191
197
|
|
|
192
|
-
if (!
|
|
198
|
+
if (!store.get('permissions') || store.get('permissions').sessionDelete !== false) {
|
|
193
199
|
var deleteItem = document.createElement("button");
|
|
194
200
|
deleteItem.className = "session-ctx-item session-ctx-delete";
|
|
195
201
|
deleteItem.innerHTML = iconHtml("trash-2") + " <span>Delete</span>";
|
|
196
202
|
deleteItem.addEventListener("click", function (e) {
|
|
197
203
|
e.stopPropagation();
|
|
198
204
|
closeSessionCtxMenu();
|
|
199
|
-
|
|
200
|
-
var ws =
|
|
201
|
-
if (ws &&
|
|
205
|
+
showConfirm('Delete "' + (title || "New Session") + '"? This session and its history will be permanently removed.', function () {
|
|
206
|
+
var ws = getWs();
|
|
207
|
+
if (ws && store.get('connected')) {
|
|
202
208
|
ws.send(JSON.stringify({ type: "delete_session", id: sessionId }));
|
|
203
209
|
}
|
|
204
210
|
});
|
|
@@ -241,7 +247,7 @@ function showLoopCtxMenu(anchorBtn, loopId, loopName, childCount) {
|
|
|
241
247
|
});
|
|
242
248
|
menu.appendChild(renameItem);
|
|
243
249
|
|
|
244
|
-
if (!
|
|
250
|
+
if (!store.get('permissions') || store.get('permissions').sessionDelete !== false) {
|
|
245
251
|
var deleteItem = document.createElement("button");
|
|
246
252
|
deleteItem.className = "session-ctx-item session-ctx-delete";
|
|
247
253
|
deleteItem.innerHTML = iconHtml("trash-2") + " <span>Delete</span>";
|
|
@@ -251,9 +257,9 @@ function showLoopCtxMenu(anchorBtn, loopId, loopName, childCount) {
|
|
|
251
257
|
var msg = 'Delete "' + (loopName || "Loop") + '"';
|
|
252
258
|
if (childCount > 1) msg += " and its " + childCount + " sessions";
|
|
253
259
|
msg += "? This cannot be undone.";
|
|
254
|
-
|
|
255
|
-
if (
|
|
256
|
-
|
|
260
|
+
showConfirm(msg, function () {
|
|
261
|
+
if (getWs() && store.get('connected')) {
|
|
262
|
+
getWs().send(JSON.stringify({ type: "delete_loop_group", loopId: loopId }));
|
|
257
263
|
}
|
|
258
264
|
});
|
|
259
265
|
});
|
|
@@ -280,7 +286,7 @@ function showLoopCtxMenu(anchorBtn, loopId, loopName, childCount) {
|
|
|
280
286
|
// --- Inline rename ---
|
|
281
287
|
|
|
282
288
|
function startInlineRename(sessionId, currentTitle) {
|
|
283
|
-
var el =
|
|
289
|
+
var el = getSessionListEl().querySelector('.session-item[data-session-id="' + sessionId + '"]');
|
|
284
290
|
if (!el) return;
|
|
285
291
|
var textSpan = el.querySelector(".session-item-text");
|
|
286
292
|
if (!textSpan) return;
|
|
@@ -298,8 +304,8 @@ function startInlineRename(sessionId, currentTitle) {
|
|
|
298
304
|
|
|
299
305
|
function commitRename() {
|
|
300
306
|
var newTitle = input.value.trim();
|
|
301
|
-
if (newTitle && newTitle !== currentTitle &&
|
|
302
|
-
|
|
307
|
+
if (newTitle && newTitle !== currentTitle && getWs() && store.get('connected')) {
|
|
308
|
+
getWs().send(JSON.stringify({ type: "rename_session", id: sessionId, title: newTitle }));
|
|
303
309
|
}
|
|
304
310
|
// Restore text (server will send updated session_list)
|
|
305
311
|
textSpan.innerHTML = originalHtml;
|
|
@@ -317,7 +323,7 @@ function startInlineRename(sessionId, currentTitle) {
|
|
|
317
323
|
}
|
|
318
324
|
|
|
319
325
|
function startLoopInlineRename(loopId, currentName) {
|
|
320
|
-
var el =
|
|
326
|
+
var el = getSessionListEl().querySelector('.session-loop-group[data-loop-id="' + loopId + '"]');
|
|
321
327
|
if (!el) return;
|
|
322
328
|
var textSpan = el.querySelector(".session-item-text");
|
|
323
329
|
if (!textSpan) return;
|
|
@@ -335,8 +341,8 @@ function startLoopInlineRename(loopId, currentName) {
|
|
|
335
341
|
|
|
336
342
|
function commitRename() {
|
|
337
343
|
var newName = input.value.trim();
|
|
338
|
-
if (newName && newName !== currentName &&
|
|
339
|
-
|
|
344
|
+
if (newName && newName !== currentName && getWs() && store.get('connected')) {
|
|
345
|
+
getWs().send(JSON.stringify({ type: "loop_registry_rename", id: loopId, name: newName }));
|
|
340
346
|
}
|
|
341
347
|
textSpan.innerHTML = originalHtml;
|
|
342
348
|
if (newName && newName !== currentName) {
|
|
@@ -407,10 +413,10 @@ function renderLoopChild(s) {
|
|
|
407
413
|
|
|
408
414
|
el.addEventListener("click", (function (id) {
|
|
409
415
|
return function () {
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
416
|
+
if (getWs() && store.get('connected')) {
|
|
417
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
418
|
+
dismissOverlayPanels();
|
|
419
|
+
closeSidebar();
|
|
414
420
|
}
|
|
415
421
|
};
|
|
416
422
|
})(s.id));
|
|
@@ -530,10 +536,10 @@ function renderLoopGroup(loopId, children, groupKey) {
|
|
|
530
536
|
// Click row (not chevron/more) -> switch to latest session
|
|
531
537
|
el.addEventListener("click", (function (id) {
|
|
532
538
|
return function () {
|
|
533
|
-
if (
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
539
|
+
if (getWs() && store.get('connected')) {
|
|
540
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
541
|
+
dismissOverlayPanels();
|
|
542
|
+
closeSidebar();
|
|
537
543
|
}
|
|
538
544
|
};
|
|
539
545
|
})(latestSession.id));
|
|
@@ -617,10 +623,10 @@ function renderLoopRun(parentGk, startedAtKey, sessions, isRalph) {
|
|
|
617
623
|
// Click row -> switch to latest session of this run
|
|
618
624
|
el.addEventListener("click", (function (id) {
|
|
619
625
|
return function () {
|
|
620
|
-
if (
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
626
|
+
if (getWs() && store.get('connected')) {
|
|
627
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
628
|
+
dismissOverlayPanels();
|
|
629
|
+
closeSidebar();
|
|
624
630
|
}
|
|
625
631
|
};
|
|
626
632
|
})(latestSession.id));
|
|
@@ -657,7 +663,7 @@ function renderSessionItem(s) {
|
|
|
657
663
|
if (s.loop && s.loop.source === "debate") {
|
|
658
664
|
textHtml += '<span class="session-debate-icon" title="Debate">' + iconHtml("mic") + '</span>';
|
|
659
665
|
}
|
|
660
|
-
if (
|
|
666
|
+
if (store.get('isMultiUserMode') && s.sessionVisibility === "private") {
|
|
661
667
|
textHtml += '<span class="session-private-icon" title="Private session">' + iconHtml("lock") + '</span>';
|
|
662
668
|
}
|
|
663
669
|
textHtml += highlightMatch(s.title || "New Session", searchQuery);
|
|
@@ -685,11 +691,11 @@ function renderSessionItem(s) {
|
|
|
685
691
|
|
|
686
692
|
el.addEventListener("click", (function (id) {
|
|
687
693
|
return function () {
|
|
688
|
-
if (
|
|
694
|
+
if (getWs() && store.get('connected')) {
|
|
689
695
|
var pendingQuery = searchQuery || "";
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
696
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
697
|
+
dismissOverlayPanels();
|
|
698
|
+
closeSidebar();
|
|
693
699
|
if (pendingQuery) {
|
|
694
700
|
setTimeout(function () { openSessionSearch(pendingQuery); }, 400);
|
|
695
701
|
}
|
|
@@ -709,9 +715,9 @@ export function renderSessionList(sessions) {
|
|
|
709
715
|
if (sessions) cachedSessions = sessions;
|
|
710
716
|
|
|
711
717
|
// If mobile chat sheet is open, refresh it
|
|
712
|
-
if (
|
|
718
|
+
if (refreshMobileChatSheet) refreshMobileChatSheet();
|
|
713
719
|
|
|
714
|
-
|
|
720
|
+
getSessionListEl().innerHTML = "";
|
|
715
721
|
|
|
716
722
|
// Partition: loop sessions vs normal sessions
|
|
717
723
|
// Group by loopId + date so all runs of the same task on the same day are merged
|
|
@@ -765,16 +771,16 @@ export function renderSessionList(sessions) {
|
|
|
765
771
|
var header = document.createElement("div");
|
|
766
772
|
header.className = "session-group-header";
|
|
767
773
|
header.textContent = group;
|
|
768
|
-
|
|
774
|
+
getSessionListEl().appendChild(header);
|
|
769
775
|
}
|
|
770
776
|
if (item.type === "loop") {
|
|
771
|
-
|
|
777
|
+
getSessionListEl().appendChild(renderLoopGroup(item.loopId, item.children, item.groupKey));
|
|
772
778
|
} else {
|
|
773
|
-
|
|
779
|
+
getSessionListEl().appendChild(renderSessionItem(item.data));
|
|
774
780
|
}
|
|
775
781
|
}
|
|
776
782
|
refreshIcons();
|
|
777
|
-
if (
|
|
783
|
+
if (updatePageTitle) updatePageTitle();
|
|
778
784
|
}
|
|
779
785
|
|
|
780
786
|
// --- Search results ---
|
|
@@ -794,7 +800,7 @@ export function handleSearchResults(msg) {
|
|
|
794
800
|
export function updateSessionPresence(presence) {
|
|
795
801
|
sessionPresence = presence;
|
|
796
802
|
// Update presence avatars on existing session items without full re-render
|
|
797
|
-
var items =
|
|
803
|
+
var items = getSessionListEl().querySelectorAll("[data-session-id]");
|
|
798
804
|
for (var i = 0; i < items.length; i++) {
|
|
799
805
|
renderPresenceAvatars(items[i], items[i].dataset.sessionId);
|
|
800
806
|
}
|
|
@@ -866,11 +872,11 @@ function startCountdownTimer() {
|
|
|
866
872
|
}
|
|
867
873
|
|
|
868
874
|
function updateCountdowns() {
|
|
869
|
-
if (!
|
|
870
|
-
var upcoming =
|
|
875
|
+
if (!getSessionListEl()) return;
|
|
876
|
+
var upcoming = getUpcomingSchedules(3 * 60 * 1000); // 3 minutes
|
|
871
877
|
|
|
872
878
|
// Remove stale container
|
|
873
|
-
if (countdownContainer && !
|
|
879
|
+
if (countdownContainer && !getSessionListEl().contains(countdownContainer)) {
|
|
874
880
|
countdownContainer = null;
|
|
875
881
|
}
|
|
876
882
|
|
|
@@ -885,7 +891,7 @@ function updateCountdowns() {
|
|
|
885
891
|
if (!countdownContainer) {
|
|
886
892
|
countdownContainer = document.createElement("div");
|
|
887
893
|
countdownContainer.className = "session-countdown-group";
|
|
888
|
-
|
|
894
|
+
getSessionListEl().insertBefore(countdownContainer, getSessionListEl().firstChild);
|
|
889
895
|
}
|
|
890
896
|
|
|
891
897
|
var html = "";
|
|
@@ -922,9 +928,9 @@ function relativeTime(isoString) {
|
|
|
922
928
|
}
|
|
923
929
|
|
|
924
930
|
export function populateCliSessionList(sessions) {
|
|
925
|
-
var pickerLoading =
|
|
926
|
-
var pickerEmpty =
|
|
927
|
-
var pickerList =
|
|
931
|
+
var pickerLoading = document.getElementById("resume-picker-loading");
|
|
932
|
+
var pickerEmpty = document.getElementById("resume-picker-empty");
|
|
933
|
+
var pickerList = document.getElementById("resume-picker-list");
|
|
928
934
|
if (!pickerLoading || !pickerList) return;
|
|
929
935
|
|
|
930
936
|
pickerLoading.classList.add("hidden");
|
|
@@ -972,12 +978,12 @@ export function populateCliSessionList(sessions) {
|
|
|
972
978
|
|
|
973
979
|
(function (sessionId) {
|
|
974
980
|
item.addEventListener("click", function () {
|
|
975
|
-
if (
|
|
976
|
-
|
|
981
|
+
if (getWs() && store.get('connected')) {
|
|
982
|
+
getWs().send(JSON.stringify({ type: "resume_session", cliSessionId: sessionId }));
|
|
977
983
|
}
|
|
978
|
-
var modal =
|
|
984
|
+
var modal = document.getElementById("resume-modal");
|
|
979
985
|
if (modal) modal.classList.add("hidden");
|
|
980
|
-
|
|
986
|
+
closeSidebar();
|
|
981
987
|
});
|
|
982
988
|
})(s.sessionId);
|
|
983
989
|
|
|
@@ -13,8 +13,13 @@ import {
|
|
|
13
13
|
import { initSidebarMobile } from './sidebar-mobile.js';
|
|
14
14
|
|
|
15
15
|
var ctx;
|
|
16
|
+
var _syncResizeHandles = null;
|
|
16
17
|
|
|
17
|
-
function
|
|
18
|
+
export function syncResizeHandles() {
|
|
19
|
+
if (_syncResizeHandles) _syncResizeHandles();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function dismissOverlayPanels() {
|
|
18
23
|
closeArchive();
|
|
19
24
|
closeScheduler();
|
|
20
25
|
}
|
|
@@ -56,21 +61,11 @@ export function closeSidebar() {
|
|
|
56
61
|
export function initSidebar(_ctx) {
|
|
57
62
|
ctx = _ctx;
|
|
58
63
|
|
|
59
|
-
// Initialize
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
ctx.showIconTooltipHtml = showIconTooltipHtml;
|
|
65
|
-
ctx.hideIconTooltip = hideIconTooltip;
|
|
66
|
-
ctx.closeUserCtxMenu = closeUserCtxMenu;
|
|
67
|
-
ctx.closeProjectCtxMenu = closeProjectCtxMenu;
|
|
68
|
-
ctx.getCurrentDmUserId = getCurrentDmUserId;
|
|
69
|
-
ctx.spawnDustParticles = spawnDustParticles;
|
|
70
|
-
initSidebarSessions(ctx);
|
|
71
|
-
initSidebarProjects(ctx);
|
|
72
|
-
initSidebarMates(ctx);
|
|
73
|
-
initSidebarMobile(ctx);
|
|
64
|
+
// Initialize sidebar sub-modules (they import their own deps directly)
|
|
65
|
+
initSidebarSessions();
|
|
66
|
+
initSidebarProjects();
|
|
67
|
+
initSidebarMates();
|
|
68
|
+
initSidebarMobile();
|
|
74
69
|
|
|
75
70
|
ctx.hamburgerBtn.addEventListener("click", function () {
|
|
76
71
|
ctx.sidebar.classList.contains("open") ? closeSidebar() : openSidebar();
|
|
@@ -128,7 +123,6 @@ export function initSidebar(_ctx) {
|
|
|
128
123
|
var sessionsPanel = ctx.$("sidebar-panel-sessions");
|
|
129
124
|
var filesPanel = ctx.$("sidebar-panel-files");
|
|
130
125
|
var sessionsHeaderContent = ctx.$("sessions-header-content");
|
|
131
|
-
var filesHeaderContent = ctx.$("files-header-content");
|
|
132
126
|
var filePanelClose = ctx.$("file-panel-close");
|
|
133
127
|
|
|
134
128
|
function hideAllPanels() {
|
|
@@ -136,7 +130,6 @@ export function initSidebar(_ctx) {
|
|
|
136
130
|
if (sessionsPanel) sessionsPanel.classList.add("hidden");
|
|
137
131
|
if (filesPanel) filesPanel.classList.add("hidden");
|
|
138
132
|
if (sessionsHeaderContent) sessionsHeaderContent.classList.add("hidden");
|
|
139
|
-
if (filesHeaderContent) filesHeaderContent.classList.add("hidden");
|
|
140
133
|
}
|
|
141
134
|
|
|
142
135
|
function showProjectsPanel() {
|
|
@@ -157,7 +150,6 @@ export function initSidebar(_ctx) {
|
|
|
157
150
|
filesPanel.classList.remove("fb-exit");
|
|
158
151
|
filesPanel.classList.add("fb-enter");
|
|
159
152
|
}
|
|
160
|
-
if (filesHeaderContent) filesHeaderContent.classList.remove("hidden");
|
|
161
153
|
if (ctx.onFilesTabOpen) ctx.onFilesTabOpen();
|
|
162
154
|
}
|
|
163
155
|
|
|
@@ -364,7 +356,7 @@ export function initSidebar(_ctx) {
|
|
|
364
356
|
}
|
|
365
357
|
|
|
366
358
|
// Expose for external callers (e.g. after DM exit)
|
|
367
|
-
ctx.syncResizeHandles = function () {
|
|
359
|
+
_syncResizeHandles = ctx.syncResizeHandles = function () {
|
|
368
360
|
// Restore project sidebar width from localStorage (may have changed during DM)
|
|
369
361
|
try {
|
|
370
362
|
var sw = localStorage.getItem("sidebar-width");
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
2
2
|
import { escapeHtml, copyToClipboard, showToast } from './utils.js';
|
|
3
|
+
import { store } from './store.js';
|
|
3
4
|
|
|
4
|
-
var ctx;
|
|
5
5
|
var modal;
|
|
6
6
|
var contentEl;
|
|
7
7
|
var activeTab = "all";
|
|
8
8
|
var currentView = "list"; // "list" or "detail"
|
|
9
9
|
var skillsData = {}; // cache per tab
|
|
10
|
-
var basePath = "";
|
|
11
10
|
var installedSkills = {}; // { skillName: { scope: "global"|"project"|"both" } }
|
|
12
11
|
var searchQuery = "";
|
|
13
12
|
var searchTimer = null;
|
|
14
13
|
var searchCache = {}; // cache per query
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
function basePath() { return store.get('basePath') || ""; }
|
|
16
|
+
|
|
17
|
+
export function initSkills() {
|
|
19
18
|
|
|
20
19
|
modal = document.getElementById("skills-modal");
|
|
21
20
|
contentEl = document.getElementById("skills-content");
|
|
@@ -134,7 +133,7 @@ export function initSkills(_ctx) {
|
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
function fetchInstalledSkills() {
|
|
137
|
-
return fetch(basePath + "api/installed-skills")
|
|
136
|
+
return fetch(basePath() + "api/installed-skills")
|
|
138
137
|
.then(function (res) { return res.json(); })
|
|
139
138
|
.then(function (data) {
|
|
140
139
|
installedSkills = data.installed || {};
|
|
@@ -225,7 +224,7 @@ function loadSkills(tab) {
|
|
|
225
224
|
function loadInstalledSkills() {
|
|
226
225
|
contentEl.innerHTML = '<div class="skills-loading"><div class="skills-spinner"></div> Loading installed skills...</div>';
|
|
227
226
|
|
|
228
|
-
fetch(basePath + "api/installed-skills")
|
|
227
|
+
fetch(basePath() + "api/installed-skills")
|
|
229
228
|
.then(function (res) { return res.json(); })
|
|
230
229
|
.then(function (data) {
|
|
231
230
|
installedSkills = data.installed || {};
|
|
@@ -563,7 +562,7 @@ function installSkill(source, skill, scope) {
|
|
|
563
562
|
btns[i].innerHTML = '<div class="skills-btn-spinner"></div> Installing...';
|
|
564
563
|
}
|
|
565
564
|
|
|
566
|
-
fetch(basePath + "api/install-skill", {
|
|
565
|
+
fetch(basePath() + "api/install-skill", {
|
|
567
566
|
method: "POST",
|
|
568
567
|
headers: { "Content-Type": "application/json" },
|
|
569
568
|
body: JSON.stringify({ url: url, skill: skill, scope: scope }),
|
|
@@ -631,7 +630,7 @@ function uninstallSkill(skill, scope) {
|
|
|
631
630
|
unBtn.innerHTML = '<div class="skills-btn-spinner small"></div>';
|
|
632
631
|
}
|
|
633
632
|
|
|
634
|
-
fetch(basePath + "api/uninstall-skill", {
|
|
633
|
+
fetch(basePath() + "api/uninstall-skill", {
|
|
635
634
|
method: "POST",
|
|
636
635
|
headers: { "Content-Type": "application/json" },
|
|
637
636
|
body: JSON.stringify({ skill: skill, scope: scope }),
|
|
@@ -885,8 +885,7 @@ export function handleNotesList(msg) {
|
|
|
885
885
|
updateBadge();
|
|
886
886
|
updateSidebarBadge();
|
|
887
887
|
|
|
888
|
-
// If user already has notes, they know the feature
|
|
889
|
-
if (list.length > 0) dismissOnboarding();
|
|
888
|
+
// If user already has notes, they know the feature (no onboarding needed)
|
|
890
889
|
|
|
891
890
|
// Auto-show if there are notes
|
|
892
891
|
if (list.length > 0 && !notesVisible) {
|
|
@@ -10,12 +10,19 @@ function createStore(initial) {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
var store = {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// Read a single field: store.get('dmMode')
|
|
14
|
+
get: function (key) { return _state[key]; },
|
|
15
|
+
// Grab full snapshot for multi-field reads: var s = store.snap();
|
|
16
|
+
snap: function () { return _state; },
|
|
17
|
+
// Shallow-merge update: store.set({ dmMode: true, dmKey: 'abc' })
|
|
18
|
+
set: function (partial) {
|
|
15
19
|
var prev = _state;
|
|
16
20
|
_state = Object.assign({}, _state, partial);
|
|
17
21
|
for (var i = 0; i < _listeners.length; i++) _listeners[i](_state, prev);
|
|
18
22
|
},
|
|
23
|
+
// Keep legacy aliases for gradual migration
|
|
24
|
+
getState: function () { return _state; },
|
|
25
|
+
setState: function (partial) { store.set(partial); },
|
|
19
26
|
subscribe: function (listener) {
|
|
20
27
|
_listeners.push(listener);
|
|
21
28
|
return function () {
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
5
5
|
import { autoResize } from './input.js';
|
|
6
|
+
import { store } from './store.js';
|
|
7
|
+
import { VENDOR_NAMES } from './app-rendering.js';
|
|
6
8
|
|
|
7
9
|
var ctx;
|
|
8
10
|
|
|
@@ -253,7 +255,8 @@ function stopRecording() {
|
|
|
253
255
|
if (document.body.classList.contains("mate-dm-active") && document.body.dataset.mateName) {
|
|
254
256
|
ctx.inputEl.setAttribute('placeholder', 'Message ' + document.body.dataset.mateName + '...');
|
|
255
257
|
} else {
|
|
256
|
-
|
|
258
|
+
var _v = store.get('currentVendor') || "claude";
|
|
259
|
+
ctx.inputEl.setAttribute('placeholder', 'Message ' + (VENDOR_NAMES[_v] || VENDOR_NAMES.claude) + '...');
|
|
257
260
|
}
|
|
258
261
|
}
|
|
259
262
|
|
|
@@ -5,6 +5,8 @@ import { renderUnifiedDiff, renderSplitDiff, renderPatchDiff } from './diff.js';
|
|
|
5
5
|
import { openFile } from './filebrowser.js';
|
|
6
6
|
import { mateAvatarUrl } from './avatar.js';
|
|
7
7
|
import { getChatLayout } from './theme.js';
|
|
8
|
+
import { store } from './store.js';
|
|
9
|
+
import { VENDOR_NAMES } from './app-rendering.js';
|
|
8
10
|
|
|
9
11
|
var ctx;
|
|
10
12
|
|
|
@@ -367,7 +369,8 @@ export function enableMainInput() {
|
|
|
367
369
|
if (document.body.classList.contains("mate-dm-active") && document.body.dataset.mateName) {
|
|
368
370
|
ctx.inputEl.placeholder = "Message " + document.body.dataset.mateName + "...";
|
|
369
371
|
} else {
|
|
370
|
-
|
|
372
|
+
var _v = store.get('currentVendor') || "claude";
|
|
373
|
+
ctx.inputEl.placeholder = "Message " + (VENDOR_NAMES[_v] || VENDOR_NAMES.claude) + "...";
|
|
371
374
|
}
|
|
372
375
|
}
|
|
373
376
|
|
|
@@ -485,7 +488,7 @@ function permissionInputSummary(toolName, input) {
|
|
|
485
488
|
}
|
|
486
489
|
}
|
|
487
490
|
|
|
488
|
-
export function renderPermissionRequest(requestId, toolName, toolInput, decisionReason, mateId) {
|
|
491
|
+
export function renderPermissionRequest(requestId, toolName, toolInput, decisionReason, mateId, vendor) {
|
|
489
492
|
if (pendingPermissions[requestId]) return;
|
|
490
493
|
ctx.finalizeAssistantBlock();
|
|
491
494
|
stopThinking();
|
|
@@ -499,7 +502,7 @@ export function renderPermissionRequest(requestId, toolName, toolInput, decision
|
|
|
499
502
|
|
|
500
503
|
// Channel layout or Mate DM: conversational "Can I ...?" style
|
|
501
504
|
if ((ctx.isMateDm && ctx.isMateDm()) || getChatLayout() === "channel") {
|
|
502
|
-
renderConversationalPermission(requestId, toolName, toolInput, mateId);
|
|
505
|
+
renderConversationalPermission(requestId, toolName, toolInput, mateId, vendor);
|
|
503
506
|
return;
|
|
504
507
|
}
|
|
505
508
|
|
|
@@ -761,7 +764,7 @@ function matePermissionInfo(toolName, toolInput) {
|
|
|
761
764
|
return { verb: verb, target: target };
|
|
762
765
|
}
|
|
763
766
|
|
|
764
|
-
function resolvePermissionIdentity(mateId) {
|
|
767
|
+
function resolvePermissionIdentity(mateId, vendor) {
|
|
765
768
|
// Mate DM: use DM target mate info
|
|
766
769
|
if (ctx.isMateDm && ctx.isMateDm()) {
|
|
767
770
|
var name = ctx.getMateName();
|
|
@@ -786,15 +789,17 @@ function resolvePermissionIdentity(mateId) {
|
|
|
786
789
|
};
|
|
787
790
|
}
|
|
788
791
|
}
|
|
789
|
-
// Project chat
|
|
792
|
+
// Project chat: use vendor name and avatar
|
|
793
|
+
var vendorAvatars = { claude: "/claude-code-avatar.png", codex: "/codex-avatar.png", gemini: "/gemini-avatar.png" };
|
|
794
|
+
var vendorName = (vendor && VENDOR_NAMES[vendor]) || VENDOR_NAMES.claude;
|
|
790
795
|
return {
|
|
791
|
-
name:
|
|
792
|
-
avatar:
|
|
796
|
+
name: vendorName,
|
|
797
|
+
avatar: (vendor && vendorAvatars[vendor]) || vendorAvatars.claude,
|
|
793
798
|
};
|
|
794
799
|
}
|
|
795
800
|
|
|
796
|
-
function renderConversationalPermission(requestId, toolName, toolInput, mateId) {
|
|
797
|
-
var identity = resolvePermissionIdentity(mateId);
|
|
801
|
+
function renderConversationalPermission(requestId, toolName, toolInput, mateId, vendor) {
|
|
802
|
+
var identity = resolvePermissionIdentity(mateId, vendor);
|
|
798
803
|
var info = matePermissionInfo(toolName, toolInput);
|
|
799
804
|
var askMsg = "Can I " + info.verb + (info.target ? " " + info.target : "") + "?";
|
|
800
805
|
|