clay-server 2.30.0 → 2.31.0
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/email-accounts.js +299 -0
- package/lib/email-mcp-server.js +646 -0
- package/lib/project-connection.js +26 -2
- package/lib/project-email.js +418 -0
- package/lib/project-sessions.js +16 -0
- package/lib/project-user-message.js +26 -5
- package/lib/project.js +72 -25
- package/lib/public/app.js +18 -5
- package/lib/public/css/filebrowser.css +80 -2
- package/lib/public/css/input.css +196 -0
- package/lib/public/css/notifications-center.css +3 -0
- package/lib/public/css/sidebar.css +77 -2
- package/lib/public/css/sticky-notes.css +0 -48
- package/lib/public/css/user-settings.css +85 -0
- package/lib/public/icons/email/gmail.svg +7 -0
- package/lib/public/icons/email/outlook.svg +35 -0
- package/lib/public/icons/email/yahoo.svg +1 -0
- package/lib/public/index.html +36 -3
- package/lib/public/modules/app-dm.js +4 -9
- package/lib/public/modules/app-messages.js +37 -2
- package/lib/public/modules/app-panels.js +2 -1
- package/lib/public/modules/context-sources.js +527 -1
- package/lib/public/modules/filebrowser.js +72 -0
- package/lib/public/modules/mate-sidebar.js +7 -0
- package/lib/public/modules/sidebar-mobile.js +1 -1
- package/lib/public/modules/sidebar.js +144 -2
- package/lib/public/modules/sticky-notes.js +1 -91
- package/lib/public/modules/terminal.js +0 -12
- package/lib/public/modules/theme.js +4 -0
- package/lib/public/modules/tools.js +23 -0
- package/lib/public/modules/user-settings.js +74 -0
- package/lib/sdk-bridge.js +16 -0
- package/lib/sdk-message-processor.js +33 -0
- package/lib/server-email.js +148 -0
- package/lib/server.js +5 -0
- package/package.json +3 -2
|
@@ -113,6 +113,15 @@ export function initSidebar(_ctx) {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
// --- Tools section collapse/expand ---
|
|
117
|
+
var toolsToggle = ctx.$("sidebar-tools-toggle");
|
|
118
|
+
var toolsSection = ctx.$("sidebar-tools");
|
|
119
|
+
if (toolsToggle && toolsSection) {
|
|
120
|
+
toolsToggle.addEventListener("click", function () {
|
|
121
|
+
toolsSection.classList.toggle("collapsed");
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
116
125
|
// --- Panel switch (sessions / files / projects) ---
|
|
117
126
|
var fileBrowserBtn = ctx.$("file-browser-btn");
|
|
118
127
|
var projectsPanel = ctx.$("sidebar-panel-projects");
|
|
@@ -143,16 +152,37 @@ export function initSidebar(_ctx) {
|
|
|
143
152
|
|
|
144
153
|
function showFilesPanel() {
|
|
145
154
|
hideAllPanels();
|
|
146
|
-
if (filesPanel)
|
|
155
|
+
if (filesPanel) {
|
|
156
|
+
filesPanel.classList.remove("hidden");
|
|
157
|
+
filesPanel.classList.remove("fb-exit");
|
|
158
|
+
filesPanel.classList.add("fb-enter");
|
|
159
|
+
}
|
|
147
160
|
if (filesHeaderContent) filesHeaderContent.classList.remove("hidden");
|
|
148
161
|
if (ctx.onFilesTabOpen) ctx.onFilesTabOpen();
|
|
149
162
|
}
|
|
150
163
|
|
|
164
|
+
function hideFilesPanel(cb) {
|
|
165
|
+
if (!filesPanel || filesPanel.classList.contains("hidden")) { if (cb) cb(); return; }
|
|
166
|
+
filesPanel.classList.remove("fb-enter");
|
|
167
|
+
filesPanel.classList.add("fb-exit");
|
|
168
|
+
function onDone() {
|
|
169
|
+
filesPanel.removeEventListener("animationend", onDone);
|
|
170
|
+
filesPanel.classList.remove("fb-exit");
|
|
171
|
+
filesPanel.classList.add("hidden");
|
|
172
|
+
if (cb) cb();
|
|
173
|
+
}
|
|
174
|
+
filesPanel.addEventListener("animationend", onDone);
|
|
175
|
+
}
|
|
176
|
+
|
|
151
177
|
if (fileBrowserBtn) {
|
|
152
178
|
fileBrowserBtn.addEventListener("click", showFilesPanel);
|
|
153
179
|
}
|
|
154
180
|
if (filePanelClose) {
|
|
155
|
-
filePanelClose.addEventListener("click",
|
|
181
|
+
filePanelClose.addEventListener("click", function() {
|
|
182
|
+
hideFilesPanel(function() {
|
|
183
|
+
showSessionsPanel();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
156
186
|
}
|
|
157
187
|
|
|
158
188
|
// --- User island width sync ---
|
|
@@ -192,6 +222,9 @@ export function initSidebar(_ctx) {
|
|
|
192
222
|
if (newWidth < 192) newWidth = 192;
|
|
193
223
|
if (newWidth > 320) newWidth = 320;
|
|
194
224
|
sidebarColumn.style.width = newWidth + "px";
|
|
225
|
+
// Sync mate sidebar to same width
|
|
226
|
+
var mateSC = document.getElementById("mate-sidebar-column");
|
|
227
|
+
if (mateSC) mateSC.style.width = newWidth + "px";
|
|
195
228
|
syncResizeHandle();
|
|
196
229
|
syncUserIslandWidth();
|
|
197
230
|
}
|
|
@@ -234,6 +267,14 @@ export function initSidebar(_ctx) {
|
|
|
234
267
|
sidebarColumn.style.width = px + "px";
|
|
235
268
|
sidebarColumn.offsetWidth; // force reflow
|
|
236
269
|
sidebarColumn.style.transition = "";
|
|
270
|
+
// Sync mate sidebar
|
|
271
|
+
var mateSC2 = document.getElementById("mate-sidebar-column");
|
|
272
|
+
if (mateSC2) {
|
|
273
|
+
mateSC2.style.transition = "none";
|
|
274
|
+
mateSC2.style.width = px + "px";
|
|
275
|
+
mateSC2.offsetWidth;
|
|
276
|
+
mateSC2.style.transition = "";
|
|
277
|
+
}
|
|
237
278
|
}
|
|
238
279
|
}
|
|
239
280
|
} catch (e) {}
|
|
@@ -242,6 +283,107 @@ export function initSidebar(_ctx) {
|
|
|
242
283
|
syncUserIslandWidth();
|
|
243
284
|
}
|
|
244
285
|
|
|
286
|
+
// --- Mate sidebar resize handle ---
|
|
287
|
+
var mateResizeHandle = document.getElementById("mate-sidebar-resize-handle");
|
|
288
|
+
var mateSidebarCol = document.getElementById("mate-sidebar-column");
|
|
289
|
+
|
|
290
|
+
function syncMateResizeHandle() {
|
|
291
|
+
if (!mateResizeHandle || !mateSidebarCol) return;
|
|
292
|
+
var rect = mateSidebarCol.getBoundingClientRect();
|
|
293
|
+
var parentRect = mateSidebarCol.parentElement.getBoundingClientRect();
|
|
294
|
+
mateResizeHandle.style.left = (rect.right - parentRect.left) + "px";
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (mateResizeHandle && mateSidebarCol) {
|
|
298
|
+
var mateDragging = false;
|
|
299
|
+
|
|
300
|
+
function onMateResizeMove(e) {
|
|
301
|
+
if (!mateDragging) return;
|
|
302
|
+
e.preventDefault();
|
|
303
|
+
var clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
|
304
|
+
var iconStrip = document.getElementById("icon-strip");
|
|
305
|
+
var stripWidth = iconStrip ? iconStrip.offsetWidth : 72;
|
|
306
|
+
var newWidth = clientX - stripWidth;
|
|
307
|
+
if (newWidth < 192) newWidth = 192;
|
|
308
|
+
if (newWidth > 320) newWidth = 320;
|
|
309
|
+
mateSidebarCol.style.width = newWidth + "px";
|
|
310
|
+
syncMateResizeHandle();
|
|
311
|
+
syncUserIslandWidth();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function onMateResizeEnd() {
|
|
315
|
+
if (!mateDragging) return;
|
|
316
|
+
mateDragging = false;
|
|
317
|
+
mateResizeHandle.classList.remove("dragging");
|
|
318
|
+
document.body.style.cursor = "";
|
|
319
|
+
document.body.style.userSelect = "";
|
|
320
|
+
document.removeEventListener("mousemove", onMateResizeMove);
|
|
321
|
+
document.removeEventListener("mouseup", onMateResizeEnd);
|
|
322
|
+
document.removeEventListener("touchmove", onMateResizeMove);
|
|
323
|
+
document.removeEventListener("touchend", onMateResizeEnd);
|
|
324
|
+
var finalWidth = mateSidebarCol.style.width;
|
|
325
|
+
try { localStorage.setItem("sidebar-width", finalWidth); } catch (e) {}
|
|
326
|
+
// Pre-apply to project sidebar so it's ready when dm-mode is removed
|
|
327
|
+
if (sidebarColumn) sidebarColumn.style.width = finalWidth;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function onMateResizeStart(e) {
|
|
331
|
+
e.preventDefault();
|
|
332
|
+
mateDragging = true;
|
|
333
|
+
mateResizeHandle.classList.add("dragging");
|
|
334
|
+
document.body.style.cursor = "col-resize";
|
|
335
|
+
document.body.style.userSelect = "none";
|
|
336
|
+
document.addEventListener("mousemove", onMateResizeMove);
|
|
337
|
+
document.addEventListener("mouseup", onMateResizeEnd);
|
|
338
|
+
document.addEventListener("touchmove", onMateResizeMove, { passive: false });
|
|
339
|
+
document.addEventListener("touchend", onMateResizeEnd);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
mateResizeHandle.addEventListener("mousedown", onMateResizeStart);
|
|
343
|
+
mateResizeHandle.addEventListener("touchstart", onMateResizeStart, { passive: false });
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Show/hide mate resize handle when DM mode changes
|
|
347
|
+
var _mateResizeObserver = new MutationObserver(function () {
|
|
348
|
+
if (!mateResizeHandle || !mateSidebarCol) return;
|
|
349
|
+
var isVisible = !mateSidebarCol.classList.contains("hidden");
|
|
350
|
+
if (isVisible) {
|
|
351
|
+
mateResizeHandle.classList.remove("hidden");
|
|
352
|
+
syncMateResizeHandle();
|
|
353
|
+
} else {
|
|
354
|
+
mateResizeHandle.classList.add("hidden");
|
|
355
|
+
// Mate sidebar just hid = returning to project. Sync project handle.
|
|
356
|
+
requestAnimationFrame(function () {
|
|
357
|
+
syncResizeHandle();
|
|
358
|
+
syncUserIslandWidth();
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
if (mateSidebarCol) {
|
|
363
|
+
_mateResizeObserver.observe(mateSidebarCol, { attributes: true, attributeFilter: ["class"] });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Expose for external callers (e.g. after DM exit)
|
|
367
|
+
ctx.syncResizeHandles = function () {
|
|
368
|
+
// Restore project sidebar width from localStorage (may have changed during DM)
|
|
369
|
+
try {
|
|
370
|
+
var sw = localStorage.getItem("sidebar-width");
|
|
371
|
+
if (sw && sidebarColumn) {
|
|
372
|
+
var px = parseInt(sw, 10);
|
|
373
|
+
if (px >= 192 && px <= 320) {
|
|
374
|
+
sidebarColumn.style.width = px + "px";
|
|
375
|
+
sidebarColumn.offsetWidth; // force reflow
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} catch (e) {}
|
|
379
|
+
// Defer handle sync to next frame so layout settles after display changes
|
|
380
|
+
requestAnimationFrame(function () {
|
|
381
|
+
syncResizeHandle();
|
|
382
|
+
syncMateResizeHandle();
|
|
383
|
+
syncUserIslandWidth();
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
|
|
245
387
|
// Initial sync even if no resize handle
|
|
246
388
|
syncUserIslandWidth();
|
|
247
389
|
|
|
@@ -52,27 +52,6 @@ function reclampAllNotes() {
|
|
|
52
52
|
export function initStickyNotes(_ctx) {
|
|
53
53
|
ctx = _ctx;
|
|
54
54
|
|
|
55
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
56
|
-
if (toggleBtn) {
|
|
57
|
-
toggleBtn.addEventListener("click", function () {
|
|
58
|
-
dismissOnboarding();
|
|
59
|
-
if (!notesVisible && notes.size > 0) {
|
|
60
|
-
// Hidden with existing notes → just show them
|
|
61
|
-
showNotes();
|
|
62
|
-
} else {
|
|
63
|
-
// Visible or no notes → create a new one
|
|
64
|
-
showNotes();
|
|
65
|
-
createNote();
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Long-press or right-click to toggle hide
|
|
70
|
-
toggleBtn.addEventListener("contextmenu", function (e) {
|
|
71
|
-
e.preventDefault();
|
|
72
|
-
if (notesVisible) hideNotes();
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
55
|
// Close format toolbar on outside click
|
|
77
56
|
document.addEventListener("mousedown", function (e) {
|
|
78
57
|
if (formatToolbarEl && !e.target.closest(".sn-format-toolbar") && !e.target.closest(".sticky-note-text") && !e.target.closest(".sticky-note-rendered")) {
|
|
@@ -91,67 +70,6 @@ export function initStickyNotes(_ctx) {
|
|
|
91
70
|
}, 100);
|
|
92
71
|
});
|
|
93
72
|
|
|
94
|
-
// First-time onboarding beacon
|
|
95
|
-
maybeShowOnboarding();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// --- Onboarding beacon (one-time discovery hint) ---
|
|
99
|
-
|
|
100
|
-
var onboardingEl = null;
|
|
101
|
-
var ONBOARDING_KEY = "clay-sticky-notes-discovered";
|
|
102
|
-
|
|
103
|
-
function maybeShowOnboarding() {
|
|
104
|
-
try {
|
|
105
|
-
if (localStorage.getItem(ONBOARDING_KEY)) return;
|
|
106
|
-
} catch (e) { return; }
|
|
107
|
-
|
|
108
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
109
|
-
if (!toggleBtn) return;
|
|
110
|
-
|
|
111
|
-
// Show beacon after a short delay so UI settles
|
|
112
|
-
setTimeout(function () {
|
|
113
|
-
// Don't show if user already has notes (they know the feature)
|
|
114
|
-
if (notes.size > 0) {
|
|
115
|
-
dismissOnboarding();
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
toggleBtn.classList.add("sn-onboarding-pulse");
|
|
120
|
-
|
|
121
|
-
var tooltip = document.createElement("div");
|
|
122
|
-
tooltip.className = "sn-onboarding-tooltip";
|
|
123
|
-
tooltip.innerHTML = '<span>Click here to create a sticky note</span>';
|
|
124
|
-
document.body.appendChild(tooltip);
|
|
125
|
-
onboardingEl = tooltip;
|
|
126
|
-
|
|
127
|
-
// Position tooltip below the button
|
|
128
|
-
var rect = toggleBtn.getBoundingClientRect();
|
|
129
|
-
tooltip.style.left = (rect.left + rect.width / 2) + "px";
|
|
130
|
-
tooltip.style.top = (rect.bottom + 8) + "px";
|
|
131
|
-
|
|
132
|
-
// Auto-dismiss after 8 seconds
|
|
133
|
-
setTimeout(function () {
|
|
134
|
-
dismissOnboarding();
|
|
135
|
-
}, 8000);
|
|
136
|
-
|
|
137
|
-
// Dismiss on click anywhere
|
|
138
|
-
document.addEventListener("click", function onClickDismiss() {
|
|
139
|
-
dismissOnboarding();
|
|
140
|
-
document.removeEventListener("click", onClickDismiss);
|
|
141
|
-
}, { once: true });
|
|
142
|
-
}, 2000);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function dismissOnboarding() {
|
|
146
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
147
|
-
if (toggleBtn) toggleBtn.classList.remove("sn-onboarding-pulse");
|
|
148
|
-
if (onboardingEl) {
|
|
149
|
-
onboardingEl.classList.add("sn-onboarding-fade-out");
|
|
150
|
-
var el = onboardingEl;
|
|
151
|
-
setTimeout(function () { el.remove(); }, 300);
|
|
152
|
-
onboardingEl = null;
|
|
153
|
-
}
|
|
154
|
-
try { localStorage.setItem(ONBOARDING_KEY, "1"); } catch (e) {}
|
|
155
73
|
}
|
|
156
74
|
|
|
157
75
|
// --- Visibility ---
|
|
@@ -159,21 +77,17 @@ function dismissOnboarding() {
|
|
|
159
77
|
export function showNotes() {
|
|
160
78
|
notesVisible = true;
|
|
161
79
|
var container = document.getElementById("sticky-notes-container");
|
|
162
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
163
80
|
if (container) container.classList.remove("hidden");
|
|
164
|
-
if (toggleBtn) toggleBtn.classList.add("active");
|
|
165
81
|
}
|
|
166
82
|
|
|
167
83
|
export function hideNotes() {
|
|
168
84
|
notesVisible = false;
|
|
169
85
|
var container = document.getElementById("sticky-notes-container");
|
|
170
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
171
86
|
if (container) container.classList.add("hidden");
|
|
172
|
-
if (toggleBtn) toggleBtn.classList.remove("active");
|
|
173
87
|
closeColorPicker();
|
|
174
88
|
}
|
|
175
89
|
|
|
176
|
-
function createNote() {
|
|
90
|
+
export function createNote() {
|
|
177
91
|
var container = document.getElementById("sticky-notes-container");
|
|
178
92
|
if (!container) return;
|
|
179
93
|
// Scatter position so notes don't stack exactly
|
|
@@ -978,8 +892,6 @@ export function handleNotesList(msg) {
|
|
|
978
892
|
if (list.length > 0 && !notesVisible) {
|
|
979
893
|
notesVisible = true;
|
|
980
894
|
container.classList.remove("hidden");
|
|
981
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
982
|
-
if (toggleBtn) toggleBtn.classList.add("active");
|
|
983
895
|
}
|
|
984
896
|
}
|
|
985
897
|
|
|
@@ -1003,8 +915,6 @@ export function handleNoteCreated(msg) {
|
|
|
1003
915
|
if (!notesVisible) {
|
|
1004
916
|
notesVisible = true;
|
|
1005
917
|
container.classList.remove("hidden");
|
|
1006
|
-
var toggleBtn = document.getElementById("sticky-notes-toggle-btn");
|
|
1007
|
-
if (toggleBtn) toggleBtn.classList.add("active");
|
|
1008
918
|
}
|
|
1009
919
|
}
|
|
1010
920
|
|
|
@@ -152,18 +152,6 @@ export function initTerminal(_ctx) {
|
|
|
152
152
|
fitTerminal();
|
|
153
153
|
});
|
|
154
154
|
|
|
155
|
-
// Header toggle button
|
|
156
|
-
var toggleBtn = document.getElementById("terminal-toggle-btn");
|
|
157
|
-
if (toggleBtn) {
|
|
158
|
-
toggleBtn.addEventListener("click", function () {
|
|
159
|
-
if (isOpen && !ctx.terminalContainerEl.classList.contains("hidden")) {
|
|
160
|
-
closeTerminal();
|
|
161
|
-
} else {
|
|
162
|
-
openTerminal();
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
155
|
// Sidebar terminal button
|
|
168
156
|
var sidebarTermBtn = document.getElementById("terminal-sidebar-btn");
|
|
169
157
|
if (sidebarTermBtn) {
|
|
@@ -77,6 +77,8 @@ var defaultExactVars = {
|
|
|
77
77
|
"--sidebar-bg": "#242631",
|
|
78
78
|
"--sidebar-hover": "#2f2f3f",
|
|
79
79
|
"--sidebar-active": "#3d3e51",
|
|
80
|
+
"--filebrowser-bg": "#2e3042",
|
|
81
|
+
"--filebrowser-border": "#383a4d",
|
|
80
82
|
"--accent-8": "rgba(255, 184, 108, 0.08)",
|
|
81
83
|
"--accent-12": "rgba(255, 184, 108, 0.12)",
|
|
82
84
|
"--accent-15": "rgba(255, 184, 108, 0.15)",
|
|
@@ -164,6 +166,8 @@ function computeVars(theme) {
|
|
|
164
166
|
"--sidebar-bg": isLight ? darken(b.base00, 0.02) : darken(b.base00, 0.10),
|
|
165
167
|
"--sidebar-hover": isLight ? darken(b.base00, 0.06) : mixColors(b.base00, b.base01, 0.5),
|
|
166
168
|
"--sidebar-active": isLight ? darken(b.base01, 0.05) : mixColors(b.base01, b.base02, 0.5),
|
|
169
|
+
"--filebrowser-bg": isLight ? lighten(b.base00, 0.03) : lighten(b.base00, 0.04),
|
|
170
|
+
"--filebrowser-border": isLight ? darken(b.base00, 0.08) : mixColors(b.base02, b.base00, 0.5),
|
|
167
171
|
"--accent-8": hexToRgba(b.base09, 0.08),
|
|
168
172
|
"--accent-12": hexToRgba(b.base09, 0.12),
|
|
169
173
|
"--accent-15": hexToRgba(b.base09, 0.15),
|
|
@@ -2068,6 +2068,29 @@ export function initSubagentStop(parentToolId, taskId) {
|
|
|
2068
2068
|
header.appendChild(btn);
|
|
2069
2069
|
}
|
|
2070
2070
|
|
|
2071
|
+
export function updateSubagentTaskStatus(parentToolId, patch) {
|
|
2072
|
+
var tool = tools[parentToolId];
|
|
2073
|
+
if (!tool || !tool.el) return;
|
|
2074
|
+
if (patch.description) {
|
|
2075
|
+
var summaryEl = tool.el.querySelector(".subagent-summary");
|
|
2076
|
+
if (!summaryEl) {
|
|
2077
|
+
var progressEl = tool.el.querySelector(".subagent-progress");
|
|
2078
|
+
if (progressEl) {
|
|
2079
|
+
summaryEl = document.createElement("div");
|
|
2080
|
+
summaryEl.className = "subagent-summary";
|
|
2081
|
+
progressEl.parentNode.insertBefore(summaryEl, progressEl.nextSibling);
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
if (summaryEl) summaryEl.textContent = patch.description;
|
|
2085
|
+
}
|
|
2086
|
+
if (patch.status === "failed" || patch.status === "killed") {
|
|
2087
|
+
var subtitleText = tool.el.querySelector(".tool-subtitle-text");
|
|
2088
|
+
if (subtitleText) subtitleText.textContent = patch.status === "failed" ? "Agent failed" : "Agent killed";
|
|
2089
|
+
var stopBtn = tool.el.querySelector(".subagent-stop-btn");
|
|
2090
|
+
if (stopBtn) stopBtn.remove();
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2071
2094
|
export function markSubagentDone(parentToolId, status, summary, usage) {
|
|
2072
2095
|
var tool = tools[parentToolId];
|
|
2073
2096
|
if (!tool || !tool.el) return;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { refreshIcons } from './icons.js';
|
|
5
5
|
import { showToast } from './utils.js';
|
|
6
6
|
import { toggleDarkMode, getCurrentTheme, getChatLayout, setChatLayout } from './theme.js';
|
|
7
|
+
import { showEmailSetupModal, getEmailAccountListCache } from './context-sources.js';
|
|
7
8
|
|
|
8
9
|
var ctx = null;
|
|
9
10
|
var settingsEl = null;
|
|
@@ -142,6 +143,14 @@ export function initUserSettings(appCtx) {
|
|
|
142
143
|
});
|
|
143
144
|
});
|
|
144
145
|
}
|
|
146
|
+
|
|
147
|
+
// Email: Add Account button
|
|
148
|
+
var emailAddBtn = document.getElementById('us-email-add');
|
|
149
|
+
if (emailAddBtn) {
|
|
150
|
+
emailAddBtn.addEventListener('click', function () {
|
|
151
|
+
showEmailSetupModal();
|
|
152
|
+
});
|
|
153
|
+
}
|
|
145
154
|
}
|
|
146
155
|
|
|
147
156
|
function openUserSettings() {
|
|
@@ -170,6 +179,7 @@ function switchSection(sectionName) {
|
|
|
170
179
|
}
|
|
171
180
|
var navDropdown = document.getElementById('user-settings-nav-dropdown');
|
|
172
181
|
if (navDropdown) navDropdown.value = sectionName;
|
|
182
|
+
if (sectionName === 'us-email') renderEmailSettings();
|
|
173
183
|
}
|
|
174
184
|
|
|
175
185
|
function stopProp(e) {
|
|
@@ -265,3 +275,67 @@ function savePin(pin) {
|
|
|
265
275
|
}
|
|
266
276
|
});
|
|
267
277
|
}
|
|
278
|
+
|
|
279
|
+
// --- Email settings ---
|
|
280
|
+
|
|
281
|
+
function renderEmailSettings() {
|
|
282
|
+
var listEl = document.getElementById('us-email-list');
|
|
283
|
+
if (!listEl) return;
|
|
284
|
+
listEl.innerHTML = '';
|
|
285
|
+
|
|
286
|
+
var accounts = getEmailAccountListCache();
|
|
287
|
+
if (!accounts || accounts.length === 0) {
|
|
288
|
+
var empty = document.createElement('div');
|
|
289
|
+
empty.className = 'settings-field';
|
|
290
|
+
empty.innerHTML = '<div class="us-email-empty">No email accounts connected yet.</div>';
|
|
291
|
+
listEl.appendChild(empty);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
for (var i = 0; i < accounts.length; i++) {
|
|
296
|
+
var acc = accounts[i];
|
|
297
|
+
var row = document.createElement('div');
|
|
298
|
+
row.className = 'us-email-row';
|
|
299
|
+
row.innerHTML =
|
|
300
|
+
'<div class="us-email-icon">' + providerIcon(acc.provider) + '</div>' +
|
|
301
|
+
'<div class="us-email-info">' +
|
|
302
|
+
'<div class="us-email-addr">' + escHtml(acc.email) + '</div>' +
|
|
303
|
+
'<div class="us-email-provider">' + escHtml(acc.label || acc.provider || 'Custom') + '</div>' +
|
|
304
|
+
'</div>' +
|
|
305
|
+
'<button class="us-email-remove-btn" data-account-id="' + escHtml(acc.id) + '">Remove</button>';
|
|
306
|
+
|
|
307
|
+
var removeBtn = row.querySelector('button');
|
|
308
|
+
removeBtn.addEventListener('click', function () {
|
|
309
|
+
var accountId = this.getAttribute('data-account-id');
|
|
310
|
+
if (ctx && ctx.ws && ctx.connected) {
|
|
311
|
+
ctx.ws.send(JSON.stringify({ type: 'email_account_remove', accountId: accountId }));
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
listEl.appendChild(row);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function refreshEmailSettings() {
|
|
320
|
+
if (isUserSettingsOpen()) renderEmailSettings();
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
var PROVIDER_ICON_PATHS = {
|
|
324
|
+
gmail: '/icons/email/gmail.svg',
|
|
325
|
+
outlook: '/icons/email/outlook.svg',
|
|
326
|
+
yahoo: '/icons/email/yahoo.svg',
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
function providerIcon(provider) {
|
|
330
|
+
var src = PROVIDER_ICON_PATHS[provider];
|
|
331
|
+
if (src) {
|
|
332
|
+
return '<img src="' + src + '" class="us-email-provider-icon" alt="' + provider + '">';
|
|
333
|
+
}
|
|
334
|
+
return '<i data-lucide="mail" class="us-email-provider-icon-fallback"></i>';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function escHtml(str) {
|
|
338
|
+
var d = document.createElement('div');
|
|
339
|
+
d.textContent = str;
|
|
340
|
+
return d.innerHTML;
|
|
341
|
+
}
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -1068,6 +1068,22 @@ function createSDKBridge(opts) {
|
|
|
1068
1068
|
return { behavior: "allow", updatedInput: input };
|
|
1069
1069
|
}
|
|
1070
1070
|
|
|
1071
|
+
// Auto-approve read-only email MCP tools.
|
|
1072
|
+
// These only read data from accounts the user explicitly checked.
|
|
1073
|
+
// Write operations (send, reply, mark_read) still require permission.
|
|
1074
|
+
var safeEmailTools = {
|
|
1075
|
+
clay_read_email: true,
|
|
1076
|
+
clay_read_email_body: true,
|
|
1077
|
+
clay_search_email: true,
|
|
1078
|
+
clay_list_labels: true,
|
|
1079
|
+
};
|
|
1080
|
+
if (toolName.indexOf("mcp__clay-email__") === 0) {
|
|
1081
|
+
var emailToolName = toolName.substring(toolName.lastIndexOf("__") + 2);
|
|
1082
|
+
if (safeEmailTools[emailToolName]) {
|
|
1083
|
+
return { behavior: "allow", updatedInput: input };
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1071
1087
|
// Auto-approve remote MCP tools that the user explicitly enabled in project settings.
|
|
1072
1088
|
// These are user-owned local MCP servers, so no additional permission prompt needed.
|
|
1073
1089
|
if (toolName.indexOf("mcp__") === 0 && getRemoteMcpServers) {
|
|
@@ -458,6 +458,25 @@ function attachMessageProcessor(ctx) {
|
|
|
458
458
|
});
|
|
459
459
|
}
|
|
460
460
|
|
|
461
|
+
} else if (parsed.type === "system" && parsed.subtype === "task_updated") {
|
|
462
|
+
// Live task state patches (status, description, error, backgrounded)
|
|
463
|
+
var taskId = parsed.task_id;
|
|
464
|
+
var patch = parsed.patch || {};
|
|
465
|
+
var parentId = null;
|
|
466
|
+
if (session.taskIdMap) {
|
|
467
|
+
for (var k in session.taskIdMap) {
|
|
468
|
+
if (session.taskIdMap[k] === taskId) { parentId = k; break; }
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (parentId) {
|
|
472
|
+
sendAndRecord(session, {
|
|
473
|
+
type: "task_updated",
|
|
474
|
+
parentToolId: parentId,
|
|
475
|
+
taskId: taskId,
|
|
476
|
+
patch: patch,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
461
480
|
} else if (parsed.type === "tool_progress") {
|
|
462
481
|
// Sub-agent tool_progress: forward as activity update
|
|
463
482
|
var parentId = parsed.parent_tool_use_id;
|
|
@@ -552,6 +571,20 @@ function attachMessageProcessor(ctx) {
|
|
|
552
571
|
suggestion: parsed.suggestion || "",
|
|
553
572
|
});
|
|
554
573
|
|
|
574
|
+
} else if (parsed.type === "system" && parsed.subtype === "notification") {
|
|
575
|
+
var notifText = parsed.text || "";
|
|
576
|
+
var notifPriority = parsed.priority || "low";
|
|
577
|
+
if (notifText) {
|
|
578
|
+
sendAndRecord(session, {
|
|
579
|
+
type: "sdk_notification",
|
|
580
|
+
key: parsed.key || "",
|
|
581
|
+
text: notifText,
|
|
582
|
+
priority: notifPriority,
|
|
583
|
+
color: parsed.color || null,
|
|
584
|
+
timeoutMs: parsed.timeout_ms || null,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
555
588
|
} else if (parsed.type === "system" && parsed.subtype === "api_retry") {
|
|
556
589
|
// Transient retry notification — show in UI but don't persist in history
|
|
557
590
|
var retryText = parsed.message || parsed.error || "Retrying API request...";
|