clay-server 2.9.3 → 2.10.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/public/app.js +14 -3
- package/lib/public/css/messages.css +19 -0
- package/lib/public/modules/tools.js +31 -1
- package/lib/sdk-bridge.js +14 -2
- package/lib/sessions.js +1 -0
- package/package.json +1 -1
package/lib/public/app.js
CHANGED
|
@@ -1825,6 +1825,7 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
|
1825
1825
|
scrollToBottom: function() { scrollToBottom(); },
|
|
1826
1826
|
setActivity: function(text) { setActivity(text); },
|
|
1827
1827
|
stopUrgentBlink: function() { stopUrgentBlink(); },
|
|
1828
|
+
showImageModal: showImageModal,
|
|
1828
1829
|
getContextPercent: function() {
|
|
1829
1830
|
var used = contextData.input;
|
|
1830
1831
|
var win = contextData.contextWindow;
|
|
@@ -2896,8 +2897,8 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
|
2896
2897
|
var tr = getTools()[msg.id];
|
|
2897
2898
|
if (tr && tr.hidden) break; // skip hidden plan tools
|
|
2898
2899
|
// Always call updateToolResult for Edit (to show diff from input), or when content exists
|
|
2899
|
-
if (msg.content != null || (tr && tr.name === "Edit" && tr.input && tr.input.old_string)) {
|
|
2900
|
-
updateToolResult(msg.id, msg.content || "", msg.is_error || false);
|
|
2900
|
+
if (msg.content != null || msg.images || (tr && tr.name === "Edit" && tr.input && tr.input.old_string)) {
|
|
2901
|
+
updateToolResult(msg.id, msg.content || "", msg.is_error || false, msg.images);
|
|
2901
2902
|
}
|
|
2902
2903
|
// Refresh file browser if an Edit/Write tool modified the open file
|
|
2903
2904
|
if (!msg.is_error && tr && (tr.name === "Edit" || tr.name === "Write") && tr.input && tr.input.file_path) {
|
|
@@ -3450,7 +3451,17 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
|
3450
3451
|
if (reconnectTimer) return;
|
|
3451
3452
|
reconnectTimer = setTimeout(function () {
|
|
3452
3453
|
reconnectTimer = null;
|
|
3453
|
-
|
|
3454
|
+
// Check if auth is still valid before reconnecting
|
|
3455
|
+
fetch("/info").then(function (res) {
|
|
3456
|
+
if (res.status === 401) {
|
|
3457
|
+
location.reload();
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
connect();
|
|
3461
|
+
}).catch(function () {
|
|
3462
|
+
// Server still down, try connecting anyway
|
|
3463
|
+
connect();
|
|
3464
|
+
});
|
|
3454
3465
|
}, reconnectDelay);
|
|
3455
3466
|
reconnectDelay = Math.min(reconnectDelay * 1.5, 10000);
|
|
3456
3467
|
}
|
|
@@ -858,6 +858,25 @@ pre.mermaid-error {
|
|
|
858
858
|
font-size: 12px;
|
|
859
859
|
}
|
|
860
860
|
|
|
861
|
+
/* --- Image viewer (Read tool) --- */
|
|
862
|
+
.tool-result-image {
|
|
863
|
+
display: flex;
|
|
864
|
+
align-items: center;
|
|
865
|
+
justify-content: center;
|
|
866
|
+
padding: 12px;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.tool-result-image img {
|
|
870
|
+
max-width: 100%;
|
|
871
|
+
max-height: 400px;
|
|
872
|
+
border-radius: 8px;
|
|
873
|
+
border: 1px solid var(--border-subtle);
|
|
874
|
+
cursor: pointer;
|
|
875
|
+
transition: opacity 0.15s;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
.tool-result-image img:hover { opacity: 0.85; }
|
|
879
|
+
|
|
861
880
|
/* --- Code viewer (Read tool) --- */
|
|
862
881
|
.code-viewer {
|
|
863
882
|
display: flex;
|
|
@@ -1281,7 +1281,16 @@ function parseLineNumberedContent(text) {
|
|
|
1281
1281
|
return { numbers: numbers, code: code };
|
|
1282
1282
|
}
|
|
1283
1283
|
|
|
1284
|
-
|
|
1284
|
+
var IMAGE_EXTS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico"]);
|
|
1285
|
+
|
|
1286
|
+
function isImagePath(filePath) {
|
|
1287
|
+
if (!filePath) return false;
|
|
1288
|
+
var dotIdx = filePath.lastIndexOf(".");
|
|
1289
|
+
if (dotIdx === -1) return false;
|
|
1290
|
+
return IMAGE_EXTS.has(filePath.substring(dotIdx).toLowerCase());
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
export function updateToolResult(id, content, isError, images) {
|
|
1285
1294
|
var tool = tools[id];
|
|
1286
1295
|
if (!tool) return;
|
|
1287
1296
|
|
|
@@ -1309,6 +1318,27 @@ export function updateToolResult(id, content, isError) {
|
|
|
1309
1318
|
} else if (!isError && isDiffContent(displayContent)) {
|
|
1310
1319
|
var patchLang = tool.input && tool.input.file_path ? getLanguageFromPath(tool.input.file_path) : null;
|
|
1311
1320
|
resultBlock.appendChild(renderPatchDiff(displayContent, patchLang));
|
|
1321
|
+
} else if (!isError && tool.name === "Read" && tool.input && tool.input.file_path && isImagePath(tool.input.file_path)) {
|
|
1322
|
+
// Image file: show inline preview
|
|
1323
|
+
var imgWrap = document.createElement("div");
|
|
1324
|
+
imgWrap.className = "tool-result-image";
|
|
1325
|
+
var img = document.createElement("img");
|
|
1326
|
+
if (images && images.length > 0) {
|
|
1327
|
+
img.src = "data:" + images[0].mediaType + ";base64," + images[0].data;
|
|
1328
|
+
} else {
|
|
1329
|
+
img.src = "api/file?path=" + encodeURIComponent(tool.input.file_path);
|
|
1330
|
+
}
|
|
1331
|
+
img.alt = tool.input.file_path.split("/").pop();
|
|
1332
|
+
img.draggable = false;
|
|
1333
|
+
img.addEventListener("click", function (e) {
|
|
1334
|
+
e.stopPropagation();
|
|
1335
|
+
e.preventDefault();
|
|
1336
|
+
if (ctx.showImageModal) ctx.showImageModal(this.src);
|
|
1337
|
+
});
|
|
1338
|
+
imgWrap.appendChild(img);
|
|
1339
|
+
resultBlock.appendChild(imgWrap);
|
|
1340
|
+
resultBlock.className = "tool-result-block";
|
|
1341
|
+
tool.el.classList.add("expanded");
|
|
1312
1342
|
} else if (!isError && tool.name === "Read" && tool.input && tool.input.file_path) {
|
|
1313
1343
|
var parsed = parseLineNumberedContent(displayContent);
|
|
1314
1344
|
if (parsed) {
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -279,6 +279,7 @@ function createSDKBridge(opts) {
|
|
|
279
279
|
delete session.activeTaskToolIds[block.tool_use_id];
|
|
280
280
|
}
|
|
281
281
|
var resultText = "";
|
|
282
|
+
var resultImages = [];
|
|
282
283
|
if (typeof block.content === "string") {
|
|
283
284
|
resultText = block.content;
|
|
284
285
|
} else if (Array.isArray(block.content)) {
|
|
@@ -286,14 +287,25 @@ function createSDKBridge(opts) {
|
|
|
286
287
|
.filter(function(c) { return c.type === "text"; })
|
|
287
288
|
.map(function(c) { return c.text; })
|
|
288
289
|
.join("\n");
|
|
290
|
+
for (var ri = 0; ri < block.content.length; ri++) {
|
|
291
|
+
var rc = block.content[ri];
|
|
292
|
+
if (rc.type === "image" && rc.source) {
|
|
293
|
+
resultImages.push({
|
|
294
|
+
mediaType: rc.source.media_type,
|
|
295
|
+
data: rc.source.data,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
289
299
|
}
|
|
290
300
|
session.sentToolResults[block.tool_use_id] = true;
|
|
291
|
-
|
|
301
|
+
var toolResultMsg = {
|
|
292
302
|
type: "tool_result",
|
|
293
303
|
id: block.tool_use_id,
|
|
294
304
|
content: resultText,
|
|
295
305
|
is_error: block.is_error || false,
|
|
296
|
-
}
|
|
306
|
+
};
|
|
307
|
+
if (resultImages.length > 0) toolResultMsg.images = resultImages;
|
|
308
|
+
sendAndRecord(session, toolResultMsg);
|
|
297
309
|
}
|
|
298
310
|
}
|
|
299
311
|
}
|
package/lib/sessions.js
CHANGED
|
@@ -325,6 +325,7 @@ function createSessionManager(opts) {
|
|
|
325
325
|
if (!session) return;
|
|
326
326
|
|
|
327
327
|
activeSessionId = localId;
|
|
328
|
+
if (targetWs) targetWs._clayActiveSession = localId;
|
|
328
329
|
|
|
329
330
|
// In multi-user mode with a specific client, only send to that client
|
|
330
331
|
var _send = (targetWs && sendTo) ? function (obj) { sendTo(targetWs, obj); } : send;
|