clay-server 2.31.0 → 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.
- package/lib/browser-mcp-server.js +32 -44
- package/lib/codex-defaults.js +18 -0
- package/lib/debate-mcp-server.js +14 -31
- package/lib/mcp-local.js +31 -1
- package/lib/project-connection.js +9 -6
- package/lib/project-debate.js +8 -0
- package/lib/project-filesystem.js +47 -1
- package/lib/project-http.js +75 -8
- package/lib/project-mate-interaction.js +102 -16
- package/lib/project-mcp.js +4 -0
- package/lib/project-notifications.js +9 -0
- package/lib/project-sessions.js +94 -51
- package/lib/project-user-message.js +12 -7
- package/lib/project.js +234 -99
- package/lib/public/app.js +135 -454
- 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 +338 -104
- 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 +26 -0
- package/lib/public/css/tooltip.css +47 -0
- package/lib/public/index.html +78 -26
- 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 +175 -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 +199 -153
- package/lib/public/modules/app-misc.js +23 -12
- package/lib/public/modules/app-notifications.js +119 -9
- package/lib/public/modules/app-panels.js +203 -49
- package/lib/public/modules/app-projects.js +161 -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 +102 -66
- package/lib/public/modules/dom-refs.js +21 -0
- package/lib/public/modules/filebrowser.js +173 -2
- package/lib/public/modules/input.js +122 -0
- package/lib/public/modules/markdown.js +5 -1
- 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 +79 -35
- 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/terminal.js +12 -0
- package/lib/public/modules/tools.js +18 -13
- package/lib/public/modules/tooltip.js +32 -5
- package/lib/sdk-bridge.js +562 -1114
- package/lib/sdk-message-processor.js +150 -135
- package/lib/sdk-worker.js +4 -0
- package/lib/server-dm.js +1 -0
- package/lib/server.js +86 -1
- package/lib/sessions.js +81 -37
- package/lib/ws-schema.js +2 -0
- package/lib/yoke/adapters/claude-worker.js +559 -0
- package/lib/yoke/adapters/claude.js +1483 -0
- package/lib/yoke/adapters/codex.js +1121 -0
- package/lib/yoke/adapters/gemini.js +709 -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 +98 -0
- package/lib/yoke/mcp-bridge-server.js +294 -0
- package/lib/yoke/package.json +7 -0
- package/package.json +3 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { avatarUrl, mateAvatarUrl } from './avatar.js';
|
|
2
2
|
import { escapeHtml } from './utils.js';
|
|
3
3
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
4
|
+
import { store } from './store.js';
|
|
4
5
|
import { hideKnowledge } from './mate-knowledge.js';
|
|
5
6
|
import { isSchedulerOpen, closeScheduler } from './scheduler.js';
|
|
6
7
|
import { hideNotes } from './sticky-notes.js';
|
|
@@ -150,6 +151,43 @@ export function showMateSidebar(mateId, mateData) {
|
|
|
150
151
|
if (avatarEl) avatarEl.src = mateAvUrl;
|
|
151
152
|
if (nameEl) nameEl.textContent = displayName;
|
|
152
153
|
|
|
154
|
+
// Vendor toggle in header
|
|
155
|
+
var mateVendorWrap = document.getElementById("mate-vendor-toggle");
|
|
156
|
+
if (mateVendorWrap) {
|
|
157
|
+
var available = store.get('availableVendors') || [];
|
|
158
|
+
var mateVendor = mateData.vendor || "claude";
|
|
159
|
+
var vendorIcons = { claude: "/claude-code-avatar.png", codex: "/codex-avatar.png" };
|
|
160
|
+
var vendorNames = { claude: "Claude Code", codex: "Codex" };
|
|
161
|
+
var vendorKeys = ["claude", "codex"];
|
|
162
|
+
mateVendorWrap.innerHTML = "";
|
|
163
|
+
for (var vi = 0; vi < vendorKeys.length; vi++) {
|
|
164
|
+
var vk = vendorKeys[vi];
|
|
165
|
+
var vBtn = document.createElement("button");
|
|
166
|
+
vBtn.className = "mate-vendor-btn" + (vk === mateVendor ? " active" : "");
|
|
167
|
+
if (available.indexOf(vk) === -1) vBtn.classList.add("disabled");
|
|
168
|
+
vBtn.dataset.vendor = vk;
|
|
169
|
+
vBtn.innerHTML = '<img src="' + vendorIcons[vk] + '" class="mate-vendor-icon" alt="' + vendorNames[vk] + '"><span class="mate-vendor-label">' + vendorNames[vk] + '</span>';
|
|
170
|
+
vBtn.addEventListener("click", function() {
|
|
171
|
+
var v = this.dataset.vendor;
|
|
172
|
+
var avail = store.get('availableVendors') || [];
|
|
173
|
+
if (avail.indexOf(v) === -1) return;
|
|
174
|
+
if (v === (currentMate && currentMate.vendor || "claude")) return;
|
|
175
|
+
if (!currentMateId) return;
|
|
176
|
+
var ws = getWs();
|
|
177
|
+
if (ws) ws.send(JSON.stringify({ type: "mate_update", mateId: currentMateId, updates: { vendor: v } }));
|
|
178
|
+
// Update UI immediately
|
|
179
|
+
mateVendorWrap.querySelectorAll(".mate-vendor-btn").forEach(function(b) {
|
|
180
|
+
b.classList.toggle("active", b.dataset.vendor === v);
|
|
181
|
+
});
|
|
182
|
+
if (currentMate) currentMate.vendor = v;
|
|
183
|
+
// If current session is new (no history), sync vendor to input toggle
|
|
184
|
+
var _hTotal = store.get('historyTotal') || 0;
|
|
185
|
+
if (_hTotal === 0) store.set({ currentVendor: v });
|
|
186
|
+
});
|
|
187
|
+
mateVendorWrap.appendChild(vBtn);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
153
191
|
// Also populate collapsed header info
|
|
154
192
|
var collapsedAvatar = document.getElementById("mate-collapsed-avatar");
|
|
155
193
|
var collapsedName = document.getElementById("mate-collapsed-name");
|
|
@@ -2,6 +2,7 @@ import { mateAvatarUrl, userAvatarUrl } from './avatar.js';
|
|
|
2
2
|
import { renderMarkdown, highlightCodeBlocks } from './markdown.js';
|
|
3
3
|
import { escapeHtml, copyToClipboard } from './utils.js';
|
|
4
4
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
5
|
+
import { store } from './store.js';
|
|
5
6
|
|
|
6
7
|
var ctx;
|
|
7
8
|
|
|
@@ -77,13 +78,17 @@ export function showMentionMenu(query) {
|
|
|
77
78
|
var menuEl = document.getElementById("mention-menu");
|
|
78
79
|
if (!menuEl) return;
|
|
79
80
|
|
|
80
|
-
menuEl.innerHTML =
|
|
81
|
+
menuEl.innerHTML = '<div class="mention-hint">Mention a Mate to get advice on your current session<button class="mention-close-btn" aria-label="Close">×</button></div>' +
|
|
82
|
+
mentionFiltered.map(function (m, i) {
|
|
81
83
|
var name = (m.profile && m.profile.displayName) || m.name || "Mate";
|
|
82
84
|
var color = (m.profile && m.profile.avatarColor) || "#6c5ce7";
|
|
83
85
|
var bio = m.bio || (m.profile && m.profile.bio) || "";
|
|
84
86
|
var avatarSrc = mateAvatarUrl(m, 24);
|
|
87
|
+
var mVendor = m.vendor || "claude";
|
|
88
|
+
var vendorIcons = { claude: "/claude-code-avatar.png", codex: "/codex-avatar.png" };
|
|
89
|
+
var vendorBadge = vendorIcons[mVendor] ? '<img class="mention-item-vendor-badge" src="' + vendorIcons[mVendor] + '" alt="' + mVendor + '">' : '';
|
|
85
90
|
return '<div class="mention-item' + (i === 0 ? ' active' : '') + '" data-idx="' + i + '">' +
|
|
86
|
-
'<img class="mention-item-avatar" src="' + escapeHtml(avatarSrc) + '" width="24" height="24" />' +
|
|
91
|
+
'<div class="mention-item-avatar-wrap"><img class="mention-item-avatar" src="' + escapeHtml(avatarSrc) + '" width="24" height="24" />' + vendorBadge + '</div>' +
|
|
87
92
|
'<div class="mention-item-info">' +
|
|
88
93
|
'<span class="mention-item-name">' + escapeHtml(name) +
|
|
89
94
|
(m.primary ? ' <span class="mention-item-badge">SYSTEM</span>' : '') +
|
|
@@ -95,6 +100,18 @@ export function showMentionMenu(query) {
|
|
|
95
100
|
}).join("");
|
|
96
101
|
menuEl.classList.add("visible");
|
|
97
102
|
|
|
103
|
+
var closeBtn = menuEl.querySelector(".mention-close-btn");
|
|
104
|
+
if (closeBtn) closeBtn.addEventListener("click", function (e) {
|
|
105
|
+
e.preventDefault();
|
|
106
|
+
e.stopPropagation();
|
|
107
|
+
hideMentionMenu();
|
|
108
|
+
clearMentionState();
|
|
109
|
+
if (ctx && ctx.inputEl) {
|
|
110
|
+
ctx.inputEl.value = ctx.inputEl.value.replace(/@\S*$/, "");
|
|
111
|
+
ctx.inputEl.focus();
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
98
115
|
menuEl.querySelectorAll(".mention-item").forEach(function (el) {
|
|
99
116
|
el.addEventListener("click", function (e) {
|
|
100
117
|
e.preventDefault();
|
|
@@ -215,10 +232,11 @@ function showInputMentionChip(name, color, avatarSrc) {
|
|
|
215
232
|
'<button class="input-mention-chip-remove" type="button" aria-label="Remove mention">×</button>';
|
|
216
233
|
chip.style.setProperty("--chip-color", color);
|
|
217
234
|
|
|
218
|
-
// Insert before the textarea inside input-row
|
|
235
|
+
// Insert before the textarea wrapper inside input-row
|
|
219
236
|
var inputRow = document.getElementById("input-row");
|
|
220
|
-
|
|
221
|
-
|
|
237
|
+
var textareaWrap = document.getElementById("input-textarea-wrap");
|
|
238
|
+
if (inputRow && textareaWrap) {
|
|
239
|
+
inputRow.insertBefore(chip, textareaWrap);
|
|
222
240
|
}
|
|
223
241
|
|
|
224
242
|
chip.querySelector(".input-mention-chip-remove").addEventListener("click", function (e) {
|
|
@@ -713,7 +731,7 @@ export function renderMentionUser(entry) {
|
|
|
713
731
|
'<span class="msg-action-time">' + ts2 + '</span>' +
|
|
714
732
|
'<button class="msg-action-btn msg-action-copy" type="button" title="Copy">' + iconHtml("copy") + '</button>' +
|
|
715
733
|
'<button class="msg-action-btn msg-action-fork" type="button" title="Fork">' + iconHtml("git-branch") + '</button>' +
|
|
716
|
-
'<button class="msg-action-btn msg-action-rewind msg-user-rewind-btn" type="button" title="Rewind">' + iconHtml("rotate-ccw") + '</button>' +
|
|
734
|
+
(((store.get('vendorCapabilities') || {}).rewind !== false) ? '<button class="msg-action-btn msg-action-rewind msg-user-rewind-btn" type="button" title="Rewind">' + iconHtml("rotate-ccw") + '</button>' : '') +
|
|
717
735
|
'<button class="msg-action-btn msg-action-hidden msg-action-edit" type="button" title="Edit">' + iconHtml("pencil") + '</button>';
|
|
718
736
|
div.appendChild(actions);
|
|
719
737
|
|
|
@@ -790,7 +790,7 @@ function renderModelTab(bodyEl, rec) {
|
|
|
790
790
|
}
|
|
791
791
|
|
|
792
792
|
var opts = {
|
|
793
|
-
models: store.
|
|
793
|
+
models: store.get('currentModels') || [],
|
|
794
794
|
currentModel: settings.model || "",
|
|
795
795
|
currentMode: settings.permissionMode || "default",
|
|
796
796
|
currentEffort: settings.effort || "medium",
|
|
@@ -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
|
-
|
|
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 = [];
|
|
@@ -19,6 +29,16 @@ var currentDmUserId = null;
|
|
|
19
29
|
var dmPickerOpen = false;
|
|
20
30
|
var cachedDmRemovedUsers = {};
|
|
21
31
|
var cachedMates = [];
|
|
32
|
+
var activeMentionMateIds = {};
|
|
33
|
+
|
|
34
|
+
export function setMentionActive(mateId, active) {
|
|
35
|
+
if (active) { activeMentionMateIds[mateId] = true; }
|
|
36
|
+
else { delete activeMentionMateIds[mateId]; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function clearAllMentionActive() {
|
|
40
|
+
activeMentionMateIds = {};
|
|
41
|
+
}
|
|
22
42
|
var _lastUserStripJson = "";
|
|
23
43
|
|
|
24
44
|
// --- Icon strip tooltip ---
|
|
@@ -27,8 +47,20 @@ var iconStripTooltip = null;
|
|
|
27
47
|
// --- DM user context menu ---
|
|
28
48
|
var userCtxMenu = null;
|
|
29
49
|
|
|
30
|
-
export function initSidebarMates(
|
|
31
|
-
|
|
50
|
+
export function initSidebarMates() {
|
|
51
|
+
// --- Reactive UI sync for user strip ---
|
|
52
|
+
store.subscribe(function (state, prev) {
|
|
53
|
+
if (state.cachedAllUsers !== prev.cachedAllUsers ||
|
|
54
|
+
state.cachedOnlineIds !== prev.cachedOnlineIds ||
|
|
55
|
+
state.cachedDmFavorites !== prev.cachedDmFavorites ||
|
|
56
|
+
state.cachedDmConversations !== prev.cachedDmConversations ||
|
|
57
|
+
state.dmUnread !== prev.dmUnread ||
|
|
58
|
+
state.dmRemovedUsers !== prev.dmRemovedUsers ||
|
|
59
|
+
state.cachedMatesList !== prev.cachedMatesList ||
|
|
60
|
+
state.myUserId !== prev.myUserId) {
|
|
61
|
+
renderUserStrip();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
32
64
|
}
|
|
33
65
|
|
|
34
66
|
export function showIconTooltip(el, text) {
|
|
@@ -80,7 +112,7 @@ export function closeUserCtxMenu() {
|
|
|
80
112
|
|
|
81
113
|
function showUserCtxMenu(anchorEl, user) {
|
|
82
114
|
closeUserCtxMenu();
|
|
83
|
-
if (
|
|
115
|
+
if (closeProjectCtxMenu) closeProjectCtxMenu();
|
|
84
116
|
|
|
85
117
|
var menu = document.createElement("div");
|
|
86
118
|
menu.className = "project-ctx-menu";
|
|
@@ -92,16 +124,14 @@ function showUserCtxMenu(anchorEl, user) {
|
|
|
92
124
|
e.stopPropagation();
|
|
93
125
|
// Spawn dust particles at the user icon position
|
|
94
126
|
var iconRect = anchorEl.getBoundingClientRect();
|
|
95
|
-
if (
|
|
127
|
+
if (spawnDustParticles) spawnDustParticles(iconRect.left + iconRect.width / 2, iconRect.top + iconRect.height / 2);
|
|
96
128
|
closeUserCtxMenu();
|
|
97
129
|
// Immediately mark as removed so strip re-render hides the icon,
|
|
98
130
|
// even if the user was only visible via cachedDmConversations (not favorites)
|
|
99
131
|
cachedDmRemovedUsers[user.id] = true;
|
|
100
|
-
|
|
101
|
-
renderUserStrip
|
|
102
|
-
|
|
103
|
-
_ctx.sendWs({ type: "dm_remove_favorite", targetUserId: user.id });
|
|
104
|
-
}
|
|
132
|
+
var dr = Object.assign({}, store.get('dmRemovedUsers')); dr[user.id] = true; store.set({ dmRemovedUsers: dr });
|
|
133
|
+
// renderUserStrip is handled by the store subscriber
|
|
134
|
+
sendWs({ type: "dm_remove_favorite", targetUserId: user.id });
|
|
105
135
|
});
|
|
106
136
|
menu.appendChild(removeItem);
|
|
107
137
|
|
|
@@ -140,7 +170,7 @@ function showMateCtxMenu(anchorEl, mate) {
|
|
|
140
170
|
if (mate.primary) return;
|
|
141
171
|
|
|
142
172
|
closeUserCtxMenu();
|
|
143
|
-
if (
|
|
173
|
+
if (closeProjectCtxMenu) closeProjectCtxMenu();
|
|
144
174
|
|
|
145
175
|
var menu = document.createElement("div");
|
|
146
176
|
menu.className = "project-ctx-menu";
|
|
@@ -153,9 +183,7 @@ function showMateCtxMenu(anchorEl, mate) {
|
|
|
153
183
|
e.stopPropagation();
|
|
154
184
|
closeUserCtxMenu();
|
|
155
185
|
showMateProfilePopover(anchorEl, mate, function (updates) {
|
|
156
|
-
|
|
157
|
-
_ctx.sendWs({ type: "mate_update", mateId: mate.id, updates: updates });
|
|
158
|
-
}
|
|
186
|
+
sendWs({ type: "mate_update", mateId: mate.id, updates: updates });
|
|
159
187
|
});
|
|
160
188
|
});
|
|
161
189
|
menu.appendChild(editItem);
|
|
@@ -168,10 +196,8 @@ function showMateCtxMenu(anchorEl, mate) {
|
|
|
168
196
|
closeUserCtxMenu();
|
|
169
197
|
// Spawn dust particles at the mate icon position
|
|
170
198
|
var iconRect = anchorEl.getBoundingClientRect();
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
_ctx.sendWs({ type: "dm_remove_favorite", targetUserId: mate.id });
|
|
174
|
-
}
|
|
199
|
+
if (spawnDustParticles) spawnDustParticles(iconRect.left + iconRect.width / 2, iconRect.top + iconRect.height / 2);
|
|
200
|
+
sendWs({ type: "dm_remove_favorite", targetUserId: mate.id });
|
|
175
201
|
});
|
|
176
202
|
menu.appendChild(removeItem);
|
|
177
203
|
|
|
@@ -238,7 +264,20 @@ function presenceAvatarUrl(userOrStyle) {
|
|
|
238
264
|
return userAvatarUrl({ avatarStyle: userOrStyle || "thumbs" }, 24);
|
|
239
265
|
}
|
|
240
266
|
|
|
267
|
+
// renderUserStrip: call with no args to read from store (subscriber pattern),
|
|
268
|
+
// or with all 8 args for legacy compatibility.
|
|
241
269
|
export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites, dmConversations, dmUnread, dmRemovedUsers, matesList) {
|
|
270
|
+
if (arguments.length === 0) {
|
|
271
|
+
var s = store.snap();
|
|
272
|
+
allUsers = s.cachedAllUsers;
|
|
273
|
+
onlineUserIds = s.cachedOnlineIds;
|
|
274
|
+
myUserId = s.myUserId;
|
|
275
|
+
dmFavorites = s.cachedDmFavorites;
|
|
276
|
+
dmConversations = s.cachedDmConversations;
|
|
277
|
+
dmUnread = s.dmUnread;
|
|
278
|
+
dmRemovedUsers = s.dmRemovedUsers;
|
|
279
|
+
matesList = s.cachedMatesList;
|
|
280
|
+
}
|
|
242
281
|
// Skip full DOM rebuild if input data hasn't changed
|
|
243
282
|
var fingerprint = JSON.stringify([allUsers, onlineUserIds, dmFavorites, dmConversations, dmUnread, dmRemovedUsers, matesList]);
|
|
244
283
|
if (fingerprint === _lastUserStripJson) return;
|
|
@@ -311,7 +350,7 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
|
|
|
311
350
|
|
|
312
351
|
// Click: open DM
|
|
313
352
|
el.addEventListener("click", function () {
|
|
314
|
-
if (
|
|
353
|
+
if (openDm) openDm(u.id);
|
|
315
354
|
});
|
|
316
355
|
|
|
317
356
|
// Right-click: show context menu
|
|
@@ -327,8 +366,9 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
|
|
|
327
366
|
|
|
328
367
|
// Build mate project status lookup from project list
|
|
329
368
|
var mateProjectStatus = {};
|
|
330
|
-
|
|
331
|
-
|
|
369
|
+
var _projList = getCachedProjects() || [];
|
|
370
|
+
if (_projList.length) {
|
|
371
|
+
var allProjects = _projList;
|
|
332
372
|
for (var pi = 0; pi < allProjects.length; pi++) {
|
|
333
373
|
if (allProjects[pi].isMate) {
|
|
334
374
|
mateProjectStatus[allProjects[pi].slug] = allProjects[pi];
|
|
@@ -380,10 +420,12 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
|
|
|
380
420
|
avatar.style.background = mateColor + "30";
|
|
381
421
|
el.appendChild(avatar);
|
|
382
422
|
|
|
383
|
-
// Processing status dot (IO blink)
|
|
423
|
+
// Processing status dot (IO blink) - top-left
|
|
384
424
|
var statusDot = document.createElement("span");
|
|
385
425
|
statusDot.className = "icon-strip-status";
|
|
386
|
-
|
|
426
|
+
var isMentionActive = !!activeMentionMateIds[mate.id];
|
|
427
|
+
if (mateProj.isProcessing || isMentionActive) statusDot.classList.add("processing");
|
|
428
|
+
if (isMentionActive) el.classList.add("mention-active");
|
|
387
429
|
el.appendChild(statusDot);
|
|
388
430
|
|
|
389
431
|
// Mate badge (bot icon)
|
|
@@ -406,6 +448,8 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
|
|
|
406
448
|
|
|
407
449
|
// Tooltip
|
|
408
450
|
var displayName = mp.displayName || mate.name || "New Mate";
|
|
451
|
+
var mateVendor = mate.vendor || "claude";
|
|
452
|
+
var vendorLabels = { claude: "Claude Code", codex: "OpenAI Codex" };
|
|
409
453
|
el.addEventListener("mouseenter", function () {
|
|
410
454
|
var html = '<div style="font-weight:600">' + escapeHtml(displayName);
|
|
411
455
|
if (mate.primary) {
|
|
@@ -415,13 +459,15 @@ export function renderUserStrip(allUsers, onlineUserIds, myUserId, dmFavorites,
|
|
|
415
459
|
if (mate.bio) {
|
|
416
460
|
html += '<div style="font-weight:400;font-size:12px;color:var(--text-secondary);margin-top:2px">' + escapeHtml(mate.bio) + '</div>';
|
|
417
461
|
}
|
|
462
|
+
var vendorLabel = vendorLabels[mateVendor] || mateVendor;
|
|
463
|
+
html += '<div style="font-size:11px;color:var(--text-dimmer);margin-top:3px">Powered by ' + escapeHtml(vendorLabel) + '</div>';
|
|
418
464
|
showIconTooltipHtml(el, html);
|
|
419
465
|
});
|
|
420
466
|
el.addEventListener("mouseleave", hideIconTooltip);
|
|
421
467
|
|
|
422
468
|
// Click: open DM with mate
|
|
423
469
|
el.addEventListener("click", function () {
|
|
424
|
-
if (
|
|
470
|
+
if (openDm) openDm(mate.id);
|
|
425
471
|
});
|
|
426
472
|
|
|
427
473
|
// Right-click: context menu for mate
|
|
@@ -520,9 +566,7 @@ function toggleDmUserPicker(anchorEl) {
|
|
|
520
566
|
item.appendChild(name);
|
|
521
567
|
|
|
522
568
|
item.addEventListener("click", function () {
|
|
523
|
-
|
|
524
|
-
_ctx.sendWs({ type: "dm_add_favorite", targetUserId: u.id });
|
|
525
|
-
}
|
|
569
|
+
sendWs({ type: "dm_add_favorite", targetUserId: u.id });
|
|
526
570
|
closeDmUserPicker();
|
|
527
571
|
});
|
|
528
572
|
|
|
@@ -570,7 +614,7 @@ function toggleDmUserPicker(anchorEl) {
|
|
|
570
614
|
});
|
|
571
615
|
}
|
|
572
616
|
// Build unified list: installed builtins, deleted builtins, user-created
|
|
573
|
-
var availBuiltins =
|
|
617
|
+
var availBuiltins = store.get('cachedAvailableBuiltins') || [];
|
|
574
618
|
var entries = [];
|
|
575
619
|
// 1. Installed builtin mates
|
|
576
620
|
for (var si = 0; si < allMates.length; si++) {
|
|
@@ -619,12 +663,12 @@ function toggleDmUserPicker(anchorEl) {
|
|
|
619
663
|
bAddBtn.title = "Re-add " + b.displayName;
|
|
620
664
|
bAddBtn.addEventListener("click", function (e) {
|
|
621
665
|
e.stopPropagation();
|
|
622
|
-
|
|
666
|
+
sendWs({ type: "mate_readd_builtin", builtinKey: b.key });
|
|
623
667
|
closeDmUserPicker();
|
|
624
668
|
});
|
|
625
669
|
bItem.appendChild(bAddBtn);
|
|
626
670
|
bItem.addEventListener("click", function () {
|
|
627
|
-
|
|
671
|
+
sendWs({ type: "mate_readd_builtin", builtinKey: b.key });
|
|
628
672
|
closeDmUserPicker();
|
|
629
673
|
});
|
|
630
674
|
matesListEl.appendChild(bItem);
|
|
@@ -675,7 +719,7 @@ function toggleDmUserPicker(anchorEl) {
|
|
|
675
719
|
yesBtn.textContent = m.builtinKey ? "Remove" : "Delete";
|
|
676
720
|
yesBtn.addEventListener("click", function (e2) {
|
|
677
721
|
e2.stopPropagation();
|
|
678
|
-
|
|
722
|
+
sendWs({ type: "mate_delete", mateId: m.id });
|
|
679
723
|
closeDmUserPicker();
|
|
680
724
|
});
|
|
681
725
|
item.appendChild(yesBtn);
|
|
@@ -693,8 +737,8 @@ function toggleDmUserPicker(anchorEl) {
|
|
|
693
737
|
});
|
|
694
738
|
item.appendChild(delBtn);
|
|
695
739
|
item.addEventListener("click", function () {
|
|
696
|
-
if (
|
|
697
|
-
if (!isFav
|
|
740
|
+
if (openDm) openDm(m.id);
|
|
741
|
+
if (!isFav) sendWs({ type: "dm_add_favorite", targetUserId: m.id });
|
|
698
742
|
closeDmUserPicker();
|
|
699
743
|
});
|
|
700
744
|
matesListEl.appendChild(item);
|
|
@@ -720,7 +764,7 @@ function toggleDmUserPicker(anchorEl) {
|
|
|
720
764
|
createMateEl.innerHTML = iconHtml("bot") + " <span>" + createMateLabel + "</span>";
|
|
721
765
|
createMateEl.addEventListener("click", function () {
|
|
722
766
|
closeDmUserPicker();
|
|
723
|
-
if (
|
|
767
|
+
if (openMateWizard) openMateWizard();
|
|
724
768
|
});
|
|
725
769
|
picker.appendChild(createMateEl);
|
|
726
770
|
|
|
@@ -26,7 +26,15 @@ import {
|
|
|
26
26
|
getCachedDmRemovedUsers
|
|
27
27
|
} from './sidebar-mates.js';
|
|
28
28
|
|
|
29
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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 = (
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
398
|
-
|
|
405
|
+
if (getWs() && store.get('connected')) {
|
|
406
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
399
407
|
}
|
|
400
|
-
if (
|
|
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 (
|
|
436
|
-
|
|
443
|
+
if (getWs() && store.get('connected')) {
|
|
444
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
437
445
|
}
|
|
438
|
-
if (
|
|
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 (
|
|
649
|
-
|
|
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 (
|
|
698
|
-
|
|
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 = (
|
|
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 (
|
|
952
|
-
|
|
959
|
+
if (getWs() && store.get('connected')) {
|
|
960
|
+
getWs().send(JSON.stringify({ type: "switch_session", id: id }));
|
|
953
961
|
}
|
|
954
|
-
if (
|
|
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
|
-
|
|
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 &&
|
|
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(
|
|
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
|
-
|
|
1269
|
+
closeSidebar();
|
|
1266
1270
|
setMobileTabActive("home");
|
|
1267
|
-
|
|
1271
|
+
showHomeHub();
|
|
1268
1272
|
});
|
|
1269
1273
|
}
|
|
1270
1274
|
}
|