clay-server 2.10.0 → 2.11.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/bin/cli.js +157 -1
- package/lib/daemon.js +341 -2
- package/lib/dm.js +135 -0
- package/lib/os-users.js +301 -0
- package/lib/pages.js +36 -0
- package/lib/project.js +386 -67
- package/lib/public/app.js +675 -17
- package/lib/public/css/admin.css +99 -10
- package/lib/public/css/filebrowser.css +22 -0
- package/lib/public/css/icon-strip.css +162 -1
- package/lib/public/css/menus.css +23 -0
- package/lib/public/css/messages.css +245 -0
- package/lib/public/css/overlays.css +88 -0
- package/lib/public/css/server-settings.css +30 -2
- package/lib/public/css/sidebar.css +4 -0
- package/lib/public/index.html +140 -66
- package/lib/public/modules/admin.js +179 -12
- package/lib/public/modules/input.js +13 -2
- package/lib/public/modules/notifications.js +3 -1
- package/lib/public/modules/project-settings.js +154 -168
- package/lib/public/modules/server-settings.js +78 -189
- package/lib/public/modules/settings-defaults.js +243 -0
- package/lib/public/modules/sidebar.js +112 -6
- package/lib/public/modules/terminal.js +48 -10
- package/lib/public/modules/tools.js +214 -1
- package/lib/sdk-bridge.js +634 -6
- package/lib/sdk-worker.js +446 -0
- package/lib/server.js +335 -3
- package/lib/sessions.js +26 -0
- package/lib/terminal-manager.js +2 -2
- package/lib/terminal.js +20 -4
- package/lib/updater.js +38 -11
- package/lib/users.js +79 -0
- package/package.json +2 -2
|
@@ -1651,7 +1651,7 @@ function showProjectCtxMenu(anchorEl, slug, name, icon, position) {
|
|
|
1651
1651
|
settingsItem.addEventListener("click", function (e) {
|
|
1652
1652
|
e.stopPropagation();
|
|
1653
1653
|
closeProjectCtxMenu();
|
|
1654
|
-
openProjectSettings(slug, { slug: slug, name: name, icon: icon });
|
|
1654
|
+
openProjectSettings(slug, { slug: slug, name: name, icon: icon, projectOwnerId: ctx.projectOwnerId });
|
|
1655
1655
|
});
|
|
1656
1656
|
menu.appendChild(settingsItem);
|
|
1657
1657
|
|
|
@@ -2087,7 +2087,8 @@ export function renderIconStrip(projects, currentSlug) {
|
|
|
2087
2087
|
for (var i = 0; i < projects.length; i++) {
|
|
2088
2088
|
var p = projects[i];
|
|
2089
2089
|
var el = document.createElement("a");
|
|
2090
|
-
|
|
2090
|
+
var isActive = p.slug === currentSlug && !currentDmUserId;
|
|
2091
|
+
el.className = "icon-strip-item" + (isActive ? " active" : "");
|
|
2091
2092
|
el.href = "/p/" + p.slug + "/";
|
|
2092
2093
|
el.dataset.slug = p.slug;
|
|
2093
2094
|
|
|
@@ -2144,7 +2145,7 @@ export function renderIconStrip(projects, currentSlug) {
|
|
|
2144
2145
|
// Update home icon active state
|
|
2145
2146
|
var homeIcon = document.querySelector(".icon-strip-home");
|
|
2146
2147
|
if (homeIcon) {
|
|
2147
|
-
if (!currentSlug || projects.length === 0) {
|
|
2148
|
+
if ((!currentSlug || projects.length === 0) && !currentDmUserId) {
|
|
2148
2149
|
homeIcon.classList.add("active");
|
|
2149
2150
|
} else {
|
|
2150
2151
|
homeIcon.classList.remove("active");
|
|
@@ -2193,13 +2194,118 @@ function renderProjectList(projects, currentSlug) {
|
|
|
2193
2194
|
|
|
2194
2195
|
export function getEmojiCategories() { return EMOJI_CATEGORIES; }
|
|
2195
2196
|
|
|
2197
|
+
// --- User strip (DM targets) ---
|
|
2198
|
+
var cachedAllUsers = [];
|
|
2199
|
+
var cachedOnlineUserIds = [];
|
|
2200
|
+
var currentDmUserId = null;
|
|
2201
|
+
|
|
2202
|
+
export function renderUserStrip(allUsers, onlineUserIds, myUserId) {
|
|
2203
|
+
cachedAllUsers = allUsers || [];
|
|
2204
|
+
cachedOnlineUserIds = onlineUserIds || [];
|
|
2205
|
+
var container = document.getElementById("icon-strip-users");
|
|
2206
|
+
if (!container) return;
|
|
2207
|
+
|
|
2208
|
+
// Filter out self, only show other users
|
|
2209
|
+
var others = cachedAllUsers.filter(function (u) { return u.id !== myUserId; });
|
|
2210
|
+
|
|
2211
|
+
// Hide section if no other users (single-user mode or alone)
|
|
2212
|
+
if (others.length === 0) {
|
|
2213
|
+
container.innerHTML = "";
|
|
2214
|
+
container.classList.add("hidden");
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
container.classList.remove("hidden");
|
|
2219
|
+
container.innerHTML = "";
|
|
2220
|
+
|
|
2221
|
+
for (var i = 0; i < others.length; i++) {
|
|
2222
|
+
(function (u) {
|
|
2223
|
+
var el = document.createElement("div");
|
|
2224
|
+
el.className = "icon-strip-user";
|
|
2225
|
+
el.dataset.userId = u.id;
|
|
2226
|
+
if (u.id === currentDmUserId) el.classList.add("active");
|
|
2227
|
+
if (onlineUserIds.indexOf(u.id) !== -1) el.classList.add("online");
|
|
2228
|
+
|
|
2229
|
+
var pill = document.createElement("span");
|
|
2230
|
+
pill.className = "icon-strip-pill";
|
|
2231
|
+
el.appendChild(pill);
|
|
2232
|
+
|
|
2233
|
+
var avatar = document.createElement("img");
|
|
2234
|
+
avatar.className = "icon-strip-user-avatar";
|
|
2235
|
+
avatar.src = "https://api.dicebear.com/9.x/" + (u.avatarStyle || "thumbs") + "/svg?seed=" + encodeURIComponent(u.avatarSeed || u.username) + "&size=34";
|
|
2236
|
+
avatar.alt = u.displayName;
|
|
2237
|
+
el.appendChild(avatar);
|
|
2238
|
+
|
|
2239
|
+
var onlineDot = document.createElement("span");
|
|
2240
|
+
onlineDot.className = "icon-strip-user-online";
|
|
2241
|
+
el.appendChild(onlineDot);
|
|
2242
|
+
|
|
2243
|
+
var badge = document.createElement("span");
|
|
2244
|
+
badge.className = "icon-strip-user-badge";
|
|
2245
|
+
badge.dataset.userId = u.id;
|
|
2246
|
+
el.appendChild(badge);
|
|
2247
|
+
|
|
2248
|
+
// Tooltip
|
|
2249
|
+
el.addEventListener("mouseenter", function () { showIconTooltip(el, u.displayName); });
|
|
2250
|
+
el.addEventListener("mouseleave", hideIconTooltip);
|
|
2251
|
+
|
|
2252
|
+
// Click: open DM
|
|
2253
|
+
el.addEventListener("click", function () {
|
|
2254
|
+
if (ctx.openDm) ctx.openDm(u.id);
|
|
2255
|
+
});
|
|
2256
|
+
|
|
2257
|
+
container.appendChild(el);
|
|
2258
|
+
})(others[i]);
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
// Invite button at bottom of user strip (hidden for now)
|
|
2262
|
+
// var inviteBtn = document.createElement("button");
|
|
2263
|
+
// inviteBtn.className = "icon-strip-invite";
|
|
2264
|
+
// inviteBtn.innerHTML = iconHtml("user-plus");
|
|
2265
|
+
// inviteBtn.addEventListener("click", function () { triggerShare(); });
|
|
2266
|
+
// inviteBtn.addEventListener("mouseenter", function () { showIconTooltip(inviteBtn, "Invite"); });
|
|
2267
|
+
// inviteBtn.addEventListener("mouseleave", hideIconTooltip);
|
|
2268
|
+
// container.appendChild(inviteBtn);
|
|
2269
|
+
refreshIcons();
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
export function setCurrentDmUser(userId) {
|
|
2273
|
+
currentDmUserId = userId;
|
|
2274
|
+
// Update active state on user icons immediately
|
|
2275
|
+
var container = document.getElementById("icon-strip-users");
|
|
2276
|
+
if (!container) return;
|
|
2277
|
+
var items = container.querySelectorAll(".icon-strip-user");
|
|
2278
|
+
for (var i = 0; i < items.length; i++) {
|
|
2279
|
+
if (items[i].dataset.userId === userId) {
|
|
2280
|
+
items[i].classList.add("active");
|
|
2281
|
+
} else {
|
|
2282
|
+
items[i].classList.remove("active");
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
export function updateDmBadge(userId, count) {
|
|
2288
|
+
var badge = document.querySelector('.icon-strip-user-badge[data-user-id="' + userId + '"]');
|
|
2289
|
+
if (!badge) return;
|
|
2290
|
+
if (count > 0) {
|
|
2291
|
+
badge.textContent = count > 99 ? "99+" : String(count);
|
|
2292
|
+
badge.classList.add("has-unread");
|
|
2293
|
+
} else {
|
|
2294
|
+
badge.textContent = "";
|
|
2295
|
+
badge.classList.remove("has-unread");
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2196
2299
|
export function initIconStrip(_ctx) {
|
|
2197
2300
|
var addBtn = document.getElementById("icon-strip-add");
|
|
2198
2301
|
if (addBtn) {
|
|
2199
2302
|
addBtn.addEventListener("click", function () {
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2303
|
+
if (_ctx.openAddProjectModal) {
|
|
2304
|
+
_ctx.openAddProjectModal();
|
|
2305
|
+
} else {
|
|
2306
|
+
var modal = _ctx.$("add-project-modal");
|
|
2307
|
+
if (modal) modal.classList.remove("hidden");
|
|
2308
|
+
}
|
|
2203
2309
|
});
|
|
2204
2310
|
addBtn.addEventListener("mouseenter", function () { showIconTooltip(addBtn, "Add project"); });
|
|
2205
2311
|
addBtn.addEventListener("mouseleave", hideIconTooltip);
|
|
@@ -225,6 +225,11 @@ function createXtermForTab(tab) {
|
|
|
225
225
|
xterm.loadAddon(fitAddon);
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
// Web links addon: make URLs clickable
|
|
229
|
+
if (typeof WebLinksAddon !== "undefined") {
|
|
230
|
+
xterm.loadAddon(new WebLinksAddon.WebLinksAddon());
|
|
231
|
+
}
|
|
232
|
+
|
|
228
233
|
// Create a container div for this tab's terminal
|
|
229
234
|
var bodyEl = document.createElement("div");
|
|
230
235
|
bodyEl.className = "terminal-tab-body";
|
|
@@ -239,16 +244,35 @@ function createXtermForTab(tab) {
|
|
|
239
244
|
}
|
|
240
245
|
});
|
|
241
246
|
|
|
242
|
-
// Ctrl+V paste
|
|
243
|
-
|
|
247
|
+
// Cmd/Ctrl+C copy and Cmd/Ctrl+V paste: intercept before xterm swallows the event
|
|
248
|
+
xterm.attachCustomKeyEventHandler(function (e) {
|
|
249
|
+
if (e.type !== "keydown") return true;
|
|
250
|
+
// Cmd/Ctrl+C: copy selection if any, otherwise send SIGINT
|
|
251
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "c") {
|
|
252
|
+
var sel = xterm.getSelection();
|
|
253
|
+
if (sel) {
|
|
254
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
255
|
+
navigator.clipboard.writeText(sel).catch(function () {});
|
|
256
|
+
}
|
|
257
|
+
return false; // prevent xterm from handling
|
|
258
|
+
}
|
|
259
|
+
// No selection on macOS Cmd+C: do nothing (not SIGINT)
|
|
260
|
+
if (e.metaKey) return false;
|
|
261
|
+
}
|
|
262
|
+
// Cmd/Ctrl+V: let browser handle paste event
|
|
244
263
|
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
|
|
264
|
+
return false; // let browser fire paste event
|
|
265
|
+
}
|
|
266
|
+
return true;
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Handle paste via browser paste event (works for Cmd+V, Ctrl+V, right-click paste)
|
|
270
|
+
bodyEl.addEventListener("paste", function (e) {
|
|
271
|
+
var text = (e.clipboardData || window.clipboardData).getData("text");
|
|
272
|
+
if (text) {
|
|
245
273
|
e.preventDefault();
|
|
246
|
-
if (
|
|
247
|
-
|
|
248
|
-
if (text && ctx.ws && ctx.connected) {
|
|
249
|
-
ctx.ws.send(JSON.stringify({ type: "term_input", id: tab.id, data: text }));
|
|
250
|
-
}
|
|
251
|
-
}).catch(function () { /* permission denied or not available */ });
|
|
274
|
+
if (ctx.ws && ctx.connected) {
|
|
275
|
+
ctx.ws.send(JSON.stringify({ type: "term_input", id: tab.id, data: text }));
|
|
252
276
|
}
|
|
253
277
|
}
|
|
254
278
|
});
|
|
@@ -598,10 +622,24 @@ function showTermCtxMenu(e, tab) {
|
|
|
598
622
|
var menu = document.createElement("div");
|
|
599
623
|
menu.className = "term-ctx-menu";
|
|
600
624
|
|
|
601
|
-
// Copy
|
|
625
|
+
// Copy selection
|
|
626
|
+
var sel = tab.xterm ? tab.xterm.getSelection() : "";
|
|
627
|
+
if (sel) {
|
|
628
|
+
var copySelItem = document.createElement("button");
|
|
629
|
+
copySelItem.className = "term-ctx-item";
|
|
630
|
+
copySelItem.innerHTML = iconHtml("copy") + " <span>Copy</span>";
|
|
631
|
+
copySelItem.addEventListener("click", function (ev) {
|
|
632
|
+
ev.stopPropagation();
|
|
633
|
+
closeTermCtxMenu();
|
|
634
|
+
if (sel) copyToClipboard(sel);
|
|
635
|
+
});
|
|
636
|
+
menu.appendChild(copySelItem);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Copy entire console
|
|
602
640
|
var copyItem = document.createElement("button");
|
|
603
641
|
copyItem.className = "term-ctx-item";
|
|
604
|
-
copyItem.innerHTML = iconHtml("clipboard-copy") + " <span>Copy
|
|
642
|
+
copyItem.innerHTML = iconHtml("clipboard-copy") + " <span>Copy Console</span>";
|
|
605
643
|
copyItem.addEventListener("click", function (ev) {
|
|
606
644
|
ev.stopPropagation();
|
|
607
645
|
closeTermCtxMenu();
|
|
@@ -693,6 +693,207 @@ export function markPermissionCancelled(requestId) {
|
|
|
693
693
|
delete pendingPermissions[requestId];
|
|
694
694
|
}
|
|
695
695
|
|
|
696
|
+
// --- MCP elicitation rendering ---
|
|
697
|
+
|
|
698
|
+
var pendingElicitations = {};
|
|
699
|
+
|
|
700
|
+
export function renderElicitationRequest(msg) {
|
|
701
|
+
if (pendingElicitations[msg.requestId]) return;
|
|
702
|
+
ctx.finalizeAssistantBlock();
|
|
703
|
+
stopThinking();
|
|
704
|
+
closeToolGroup();
|
|
705
|
+
|
|
706
|
+
var container = document.createElement("div");
|
|
707
|
+
container.className = "permission-container elicitation-container";
|
|
708
|
+
container.dataset.requestId = msg.requestId;
|
|
709
|
+
|
|
710
|
+
// Header
|
|
711
|
+
var header = document.createElement("div");
|
|
712
|
+
header.className = "permission-header";
|
|
713
|
+
header.innerHTML =
|
|
714
|
+
'<span class="permission-icon">' + iconHtml("key") + '</span>' +
|
|
715
|
+
'<span class="permission-title">' + escapeHtml(msg.serverName || "MCP Server") + ' requests input</span>';
|
|
716
|
+
|
|
717
|
+
// Body
|
|
718
|
+
var body = document.createElement("div");
|
|
719
|
+
body.className = "permission-body";
|
|
720
|
+
|
|
721
|
+
if (msg.message) {
|
|
722
|
+
var messageEl = document.createElement("div");
|
|
723
|
+
messageEl.className = "permission-reason";
|
|
724
|
+
messageEl.textContent = msg.message;
|
|
725
|
+
body.appendChild(messageEl);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Form fields (form mode) or URL button (url mode)
|
|
729
|
+
var formData = {};
|
|
730
|
+
|
|
731
|
+
if (msg.mode === "url" && msg.url) {
|
|
732
|
+
var urlInfo = document.createElement("div");
|
|
733
|
+
urlInfo.className = "elicitation-url-info";
|
|
734
|
+
urlInfo.style.cssText = "margin-top: 8px; font-size: 12px; color: var(--text-muted);";
|
|
735
|
+
urlInfo.textContent = "Opens: " + msg.url;
|
|
736
|
+
body.appendChild(urlInfo);
|
|
737
|
+
} else if (msg.requestedSchema && msg.requestedSchema.properties) {
|
|
738
|
+
var formEl = document.createElement("div");
|
|
739
|
+
formEl.className = "elicitation-form";
|
|
740
|
+
formEl.style.cssText = "margin-top: 8px; display: flex; flex-direction: column; gap: 8px;";
|
|
741
|
+
|
|
742
|
+
var props = msg.requestedSchema.properties;
|
|
743
|
+
var required = msg.requestedSchema.required || [];
|
|
744
|
+
var propNames = Object.keys(props);
|
|
745
|
+
for (var i = 0; i < propNames.length; i++) {
|
|
746
|
+
var propName = propNames[i];
|
|
747
|
+
var prop = props[propName];
|
|
748
|
+
var isRequired = required.indexOf(propName) !== -1;
|
|
749
|
+
|
|
750
|
+
var fieldWrapper = document.createElement("div");
|
|
751
|
+
fieldWrapper.style.cssText = "display: flex; flex-direction: column; gap: 2px;";
|
|
752
|
+
|
|
753
|
+
var label = document.createElement("label");
|
|
754
|
+
label.style.cssText = "font-size: 12px; font-weight: 500; color: var(--text-secondary);";
|
|
755
|
+
label.textContent = propName + (isRequired ? " *" : "");
|
|
756
|
+
if (prop.description) {
|
|
757
|
+
label.title = prop.description;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
var input;
|
|
761
|
+
if (prop.type === "boolean") {
|
|
762
|
+
input = document.createElement("input");
|
|
763
|
+
input.type = "checkbox";
|
|
764
|
+
input.dataset.propName = propName;
|
|
765
|
+
input.dataset.propType = "boolean";
|
|
766
|
+
} else if (prop.enum) {
|
|
767
|
+
input = document.createElement("select");
|
|
768
|
+
input.dataset.propName = propName;
|
|
769
|
+
input.dataset.propType = "enum";
|
|
770
|
+
input.style.cssText = "padding: 4px 8px; border-radius: 4px; border: 1px solid var(--border); background: var(--input-bg); color: var(--text-primary); font-size: 13px;";
|
|
771
|
+
for (var ei = 0; ei < prop.enum.length; ei++) {
|
|
772
|
+
var opt = document.createElement("option");
|
|
773
|
+
opt.value = prop.enum[ei];
|
|
774
|
+
opt.textContent = prop.enum[ei];
|
|
775
|
+
input.appendChild(opt);
|
|
776
|
+
}
|
|
777
|
+
} else {
|
|
778
|
+
input = document.createElement("input");
|
|
779
|
+
input.type = prop.type === "number" || prop.type === "integer" ? "number" : "text";
|
|
780
|
+
input.dataset.propName = propName;
|
|
781
|
+
input.dataset.propType = prop.type || "string";
|
|
782
|
+
input.placeholder = prop.description || propName;
|
|
783
|
+
input.style.cssText = "padding: 4px 8px; border-radius: 4px; border: 1px solid var(--border); background: var(--input-bg); color: var(--text-primary); font-size: 13px;";
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
fieldWrapper.appendChild(label);
|
|
787
|
+
fieldWrapper.appendChild(input);
|
|
788
|
+
formEl.appendChild(fieldWrapper);
|
|
789
|
+
}
|
|
790
|
+
body.appendChild(formEl);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Actions
|
|
794
|
+
var actions = document.createElement("div");
|
|
795
|
+
actions.className = "permission-actions";
|
|
796
|
+
|
|
797
|
+
var acceptBtn = document.createElement("button");
|
|
798
|
+
acceptBtn.className = "permission-btn permission-allow";
|
|
799
|
+
|
|
800
|
+
if (msg.mode === "url" && msg.url) {
|
|
801
|
+
acceptBtn.textContent = "Open & Approve";
|
|
802
|
+
acceptBtn.addEventListener("click", function () {
|
|
803
|
+
window.open(msg.url, "_blank");
|
|
804
|
+
sendElicitationResponse(container, msg.requestId, "accept", {});
|
|
805
|
+
});
|
|
806
|
+
} else {
|
|
807
|
+
acceptBtn.textContent = "Submit";
|
|
808
|
+
acceptBtn.addEventListener("click", function () {
|
|
809
|
+
// Collect form values
|
|
810
|
+
var content = {};
|
|
811
|
+
var inputs = container.querySelectorAll("[data-prop-name]");
|
|
812
|
+
for (var j = 0; j < inputs.length; j++) {
|
|
813
|
+
var inp = inputs[j];
|
|
814
|
+
var name = inp.dataset.propName;
|
|
815
|
+
var pType = inp.dataset.propType;
|
|
816
|
+
if (pType === "boolean") {
|
|
817
|
+
content[name] = inp.checked;
|
|
818
|
+
} else if (pType === "number" || pType === "integer") {
|
|
819
|
+
content[name] = Number(inp.value);
|
|
820
|
+
} else {
|
|
821
|
+
content[name] = inp.value;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
sendElicitationResponse(container, msg.requestId, "accept", content);
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
var denyBtn = document.createElement("button");
|
|
829
|
+
denyBtn.className = "permission-btn permission-deny";
|
|
830
|
+
denyBtn.textContent = "Deny";
|
|
831
|
+
denyBtn.addEventListener("click", function () {
|
|
832
|
+
sendElicitationResponse(container, msg.requestId, "reject", null);
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
actions.appendChild(acceptBtn);
|
|
836
|
+
actions.appendChild(denyBtn);
|
|
837
|
+
|
|
838
|
+
container.appendChild(header);
|
|
839
|
+
container.appendChild(body);
|
|
840
|
+
container.appendChild(actions);
|
|
841
|
+
ctx.addToMessages(container);
|
|
842
|
+
|
|
843
|
+
pendingElicitations[msg.requestId] = container;
|
|
844
|
+
refreshIcons();
|
|
845
|
+
ctx.setActivity(null);
|
|
846
|
+
ctx.scrollToBottom();
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function sendElicitationResponse(container, requestId, action, content) {
|
|
850
|
+
if (container.classList.contains("resolved")) return;
|
|
851
|
+
container.classList.add("resolved");
|
|
852
|
+
if (ctx.stopUrgentBlink) ctx.stopUrgentBlink();
|
|
853
|
+
|
|
854
|
+
var label = action === "reject" ? "Denied" : "Submitted";
|
|
855
|
+
var resolvedClass = action === "reject" ? "resolved-denied" : "resolved-allowed";
|
|
856
|
+
container.classList.add(resolvedClass);
|
|
857
|
+
|
|
858
|
+
var actions = container.querySelector(".permission-actions");
|
|
859
|
+
if (actions) {
|
|
860
|
+
actions.innerHTML = '<span class="permission-decision-label">' + label + '</span>';
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
if (ctx.ws && ctx.connected) {
|
|
864
|
+
var msg = {
|
|
865
|
+
type: "elicitation_response",
|
|
866
|
+
requestId: requestId,
|
|
867
|
+
action: action,
|
|
868
|
+
};
|
|
869
|
+
if (action === "accept" && content) {
|
|
870
|
+
msg.content = content;
|
|
871
|
+
}
|
|
872
|
+
ctx.ws.send(JSON.stringify(msg));
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
delete pendingElicitations[requestId];
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
export function markElicitationResolved(requestId, action) {
|
|
879
|
+
var container = pendingElicitations[requestId];
|
|
880
|
+
if (!container) {
|
|
881
|
+
container = ctx.messagesEl.querySelector('.elicitation-container[data-request-id="' + requestId + '"]');
|
|
882
|
+
}
|
|
883
|
+
if (!container || container.classList.contains("resolved")) return;
|
|
884
|
+
|
|
885
|
+
container.classList.add("resolved");
|
|
886
|
+
var isDeny = action === "reject";
|
|
887
|
+
container.classList.add(isDeny ? "resolved-denied" : "resolved-allowed");
|
|
888
|
+
|
|
889
|
+
var label = isDeny ? "Denied" : "Submitted";
|
|
890
|
+
var actionsEl = container.querySelector(".permission-actions");
|
|
891
|
+
if (actionsEl) {
|
|
892
|
+
actionsEl.innerHTML = '<span class="permission-decision-label">' + label + '</span>';
|
|
893
|
+
}
|
|
894
|
+
delete pendingElicitations[requestId];
|
|
895
|
+
}
|
|
896
|
+
|
|
696
897
|
// --- Plan mode rendering ---
|
|
697
898
|
export function renderPlanBanner(type) {
|
|
698
899
|
ctx.finalizeAssistantBlock();
|
|
@@ -1504,7 +1705,7 @@ function fmtDuration(ms) {
|
|
|
1504
1705
|
return secs + "s";
|
|
1505
1706
|
}
|
|
1506
1707
|
|
|
1507
|
-
export function updateSubagentProgress(parentToolId, usage, lastToolName) {
|
|
1708
|
+
export function updateSubagentProgress(parentToolId, usage, lastToolName, summary) {
|
|
1508
1709
|
var tool = tools[parentToolId];
|
|
1509
1710
|
if (!tool || !tool.el) return;
|
|
1510
1711
|
var progressEl = tool.el.querySelector(".subagent-progress");
|
|
@@ -1523,6 +1724,17 @@ export function updateSubagentProgress(parentToolId, usage, lastToolName) {
|
|
|
1523
1724
|
}
|
|
1524
1725
|
if (lastToolName) parts.push(lastToolName);
|
|
1525
1726
|
progressEl.textContent = parts.join(" · ");
|
|
1727
|
+
|
|
1728
|
+
// AI-generated progress summary (agentProgressSummaries)
|
|
1729
|
+
if (summary) {
|
|
1730
|
+
var summaryEl = tool.el.querySelector(".subagent-summary");
|
|
1731
|
+
if (!summaryEl) {
|
|
1732
|
+
summaryEl = document.createElement("div");
|
|
1733
|
+
summaryEl.className = "subagent-summary";
|
|
1734
|
+
progressEl.parentNode.insertBefore(summaryEl, progressEl.nextSibling);
|
|
1735
|
+
}
|
|
1736
|
+
summaryEl.textContent = summary;
|
|
1737
|
+
}
|
|
1526
1738
|
}
|
|
1527
1739
|
|
|
1528
1740
|
export function initSubagentStop(parentToolId, taskId) {
|
|
@@ -1640,6 +1852,7 @@ export function resetToolState() {
|
|
|
1640
1852
|
todoWidgetVisible = true;
|
|
1641
1853
|
if (todoObserver) { todoObserver.disconnect(); todoObserver = null; }
|
|
1642
1854
|
pendingPermissions = {};
|
|
1855
|
+
pendingElicitations = {};
|
|
1643
1856
|
currentToolGroup = null;
|
|
1644
1857
|
toolGroupCounter = 0;
|
|
1645
1858
|
toolGroups = {};
|