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
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { refreshIcons } from './icons.js';
|
|
3
3
|
import { showToast } from './utils.js';
|
|
4
4
|
import { parseEmojis } from './markdown.js';
|
|
5
|
+
import { closeFileViewer } from './filebrowser.js';
|
|
6
|
+
import { renderModelList, renderModeList, renderEffortBar, renderThinkingBar, renderBetaCard } from './settings-defaults.js';
|
|
5
7
|
|
|
6
8
|
var ctx = null;
|
|
7
9
|
var panelEl = null;
|
|
@@ -13,25 +15,6 @@ var currentProject = null; // { slug, name, icon }
|
|
|
13
15
|
// Emoji categories (reuse from sidebar)
|
|
14
16
|
var EMOJI_CATEGORIES = null;
|
|
15
17
|
|
|
16
|
-
var MODE_OPTIONS = [
|
|
17
|
-
{ value: "default", label: "Default", desc: "Claude asks for permission before running tools and editing files." },
|
|
18
|
-
{ value: "plan", label: "Plan", desc: "Claude creates a plan first and asks for approval before making changes." },
|
|
19
|
-
{ value: "acceptEdits", label: "Auto-accept edits", desc: "File edits are applied automatically. Claude still asks before running commands." },
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
var EFFORT_LEVELS = [
|
|
23
|
-
{ value: "low", desc: "Quick, concise responses. Best for simple questions." },
|
|
24
|
-
{ value: "medium", desc: "Balanced responses with moderate reasoning. Good for most tasks." },
|
|
25
|
-
{ value: "high", desc: "Thorough responses with deeper analysis. Good for complex tasks." },
|
|
26
|
-
{ value: "max", desc: "Maximum reasoning depth. Best for the most difficult problems." },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
var MODEL_DESCRIPTIONS = {
|
|
30
|
-
"default": "Automatically selects the best model for the task.",
|
|
31
|
-
"sonnet": "Fast and capable. Great balance of speed and intelligence.",
|
|
32
|
-
"haiku": "Fastest model. Best for quick tasks and simple questions.",
|
|
33
|
-
"opus": "Most powerful model. Best for complex reasoning and analysis.",
|
|
34
|
-
};
|
|
35
18
|
|
|
36
19
|
// ===== Init =====
|
|
37
20
|
export function initProjectSettings(appCtx, emojiCategories) {
|
|
@@ -151,6 +134,26 @@ export function initProjectSettings(appCtx, emojiCategories) {
|
|
|
151
134
|
autoSaveSharedEnv();
|
|
152
135
|
});
|
|
153
136
|
}
|
|
137
|
+
|
|
138
|
+
// Owner: transfer
|
|
139
|
+
var transferBtn = document.getElementById("ps-transfer-btn");
|
|
140
|
+
if (transferBtn) {
|
|
141
|
+
transferBtn.addEventListener("click", function () {
|
|
142
|
+
showTransferForm();
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
var transferSave = document.getElementById("ps-transfer-save");
|
|
146
|
+
if (transferSave) {
|
|
147
|
+
transferSave.addEventListener("click", function () {
|
|
148
|
+
commitTransfer();
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
var transferCancel = document.getElementById("ps-transfer-cancel");
|
|
152
|
+
if (transferCancel) {
|
|
153
|
+
transferCancel.addEventListener("click", function () {
|
|
154
|
+
hideTransferForm();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
154
157
|
}
|
|
155
158
|
|
|
156
159
|
// ===== Open / Close =====
|
|
@@ -169,6 +172,9 @@ export function openProjectSettings(slug, project) {
|
|
|
169
172
|
// Populate profile
|
|
170
173
|
populateProfile();
|
|
171
174
|
|
|
175
|
+
// Close file viewer if open (prevent split-screen)
|
|
176
|
+
closeFileViewer();
|
|
177
|
+
|
|
172
178
|
// Show panel
|
|
173
179
|
panelEl.classList.remove("hidden");
|
|
174
180
|
refreshIcons();
|
|
@@ -225,6 +231,52 @@ function populateProfile() {
|
|
|
225
231
|
|
|
226
232
|
// Icon
|
|
227
233
|
updateIconPreview(currentProject ? currentProject.icon : null);
|
|
234
|
+
|
|
235
|
+
// Owner (only in multi-user mode)
|
|
236
|
+
var ownerField = document.getElementById("ps-owner-field");
|
|
237
|
+
if (ownerField) {
|
|
238
|
+
var ownerId = currentProject ? currentProject.projectOwnerId : null;
|
|
239
|
+
var isMultiUser = ctx.multiUser;
|
|
240
|
+
if (isMultiUser) {
|
|
241
|
+
ownerField.style.display = "";
|
|
242
|
+
var ownerNameEl = document.getElementById("ps-owner-name");
|
|
243
|
+
var transferBtn = document.getElementById("ps-transfer-btn");
|
|
244
|
+
if (transferBtn) transferBtn.style.display = "none";
|
|
245
|
+
// Fetch user list (only succeeds for admin)
|
|
246
|
+
fetch("/api/admin/users").then(function (r) {
|
|
247
|
+
if (!r.ok) throw new Error("not admin");
|
|
248
|
+
return r.json();
|
|
249
|
+
}).then(function (data) {
|
|
250
|
+
var users = data.users || [];
|
|
251
|
+
// Show owner name
|
|
252
|
+
if (ownerId) {
|
|
253
|
+
var owner = null;
|
|
254
|
+
for (var i = 0; i < users.length; i++) {
|
|
255
|
+
if (users[i].id === ownerId) { owner = users[i]; break; }
|
|
256
|
+
}
|
|
257
|
+
if (ownerNameEl) ownerNameEl.textContent = owner ? (owner.displayName || owner.username) : ownerId;
|
|
258
|
+
} else {
|
|
259
|
+
if (ownerNameEl) ownerNameEl.textContent = "Not set";
|
|
260
|
+
}
|
|
261
|
+
// Admin can always transfer
|
|
262
|
+
if (transferBtn) transferBtn.style.display = "";
|
|
263
|
+
}).catch(function () {
|
|
264
|
+
// Not admin, show owner name from limited info
|
|
265
|
+
if (ownerId) {
|
|
266
|
+
if (ownerNameEl) ownerNameEl.textContent = ownerId;
|
|
267
|
+
// Project owner can also transfer
|
|
268
|
+
if (ctx.myUserId && ctx.myUserId === ownerId && transferBtn) {
|
|
269
|
+
transferBtn.style.display = "";
|
|
270
|
+
}
|
|
271
|
+
} else {
|
|
272
|
+
if (ownerNameEl) ownerNameEl.textContent = "Not set";
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
hideTransferForm();
|
|
276
|
+
} else {
|
|
277
|
+
ownerField.style.display = "none";
|
|
278
|
+
}
|
|
279
|
+
}
|
|
228
280
|
}
|
|
229
281
|
|
|
230
282
|
function commitRename() {
|
|
@@ -248,6 +300,49 @@ function cancelRename() {
|
|
|
248
300
|
if (renameBtn) renameBtn.classList.remove("hidden");
|
|
249
301
|
}
|
|
250
302
|
|
|
303
|
+
// ===== Owner transfer =====
|
|
304
|
+
function showTransferForm() {
|
|
305
|
+
var form = document.getElementById("ps-transfer-form");
|
|
306
|
+
var btn = document.getElementById("ps-transfer-btn");
|
|
307
|
+
var select = document.getElementById("ps-transfer-select");
|
|
308
|
+
if (!form || !select) return;
|
|
309
|
+
|
|
310
|
+
// Fetch user list and populate select
|
|
311
|
+
select.innerHTML = '<option value="">Loading...</option>';
|
|
312
|
+
fetch("/api/admin/users").then(function (r) { return r.json(); }).then(function (data) {
|
|
313
|
+
var users = data.users || [];
|
|
314
|
+
select.innerHTML = "";
|
|
315
|
+
for (var i = 0; i < users.length; i++) {
|
|
316
|
+
var u = users[i];
|
|
317
|
+
var opt = document.createElement("option");
|
|
318
|
+
opt.value = u.id;
|
|
319
|
+
opt.textContent = (u.displayName || u.username) + (u.linuxUser ? " (" + u.linuxUser + ")" : "");
|
|
320
|
+
if (currentProject && u.id === currentProject.projectOwnerId) opt.selected = true;
|
|
321
|
+
select.appendChild(opt);
|
|
322
|
+
}
|
|
323
|
+
}).catch(function () {
|
|
324
|
+
select.innerHTML = '<option value="">Failed to load users</option>';
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
form.classList.remove("hidden");
|
|
328
|
+
if (btn) btn.classList.add("hidden");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function hideTransferForm() {
|
|
332
|
+
var form = document.getElementById("ps-transfer-form");
|
|
333
|
+
var btn = document.getElementById("ps-transfer-btn");
|
|
334
|
+
if (form) form.classList.add("hidden");
|
|
335
|
+
if (btn) btn.classList.remove("hidden");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function commitTransfer() {
|
|
339
|
+
var select = document.getElementById("ps-transfer-select");
|
|
340
|
+
var userId = select ? select.value : "";
|
|
341
|
+
if (!userId || !ctx.ws || !ctx.connected) return;
|
|
342
|
+
ctx.ws.send(JSON.stringify({ type: "transfer_project_owner", slug: currentSlug, userId: userId }));
|
|
343
|
+
hideTransferForm();
|
|
344
|
+
}
|
|
345
|
+
|
|
251
346
|
function updateIconPreview(icon) {
|
|
252
347
|
var preview = document.getElementById("ps-icon-preview");
|
|
253
348
|
var removeBtn = document.getElementById("ps-icon-remove-btn");
|
|
@@ -358,158 +453,40 @@ function showPsEmojiPicker() {
|
|
|
358
453
|
}
|
|
359
454
|
|
|
360
455
|
// ===== Defaults =====
|
|
361
|
-
function
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
456
|
+
function psSendMsg(type, data) {
|
|
457
|
+
var ws = ctx.ws;
|
|
458
|
+
if (ws && ws.readyState === 1) {
|
|
459
|
+
var msg = Object.assign({ type: type }, data);
|
|
460
|
+
ws.send(JSON.stringify(msg));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function psDefaultsOpts() {
|
|
465
|
+
return {
|
|
466
|
+
models: ctx.currentModels || [],
|
|
467
|
+
currentModel: ctx.currentModel || "",
|
|
468
|
+
currentMode: ctx.currentMode || "default",
|
|
469
|
+
currentEffort: ctx.currentEffort || "medium",
|
|
470
|
+
currentThinking: ctx.currentThinking || "adaptive",
|
|
471
|
+
currentThinkingBudget: ctx.currentThinkingBudget || 10000,
|
|
472
|
+
currentBetas: ctx.currentBetas || [],
|
|
473
|
+
sendMsg: psSendMsg,
|
|
474
|
+
modelMsgType: "set_project_default_model",
|
|
475
|
+
modeMsgType: "set_project_default_mode",
|
|
476
|
+
effortMsgType: "set_project_default_effort",
|
|
477
|
+
onModelSelect: function (model) {
|
|
478
|
+
renderBetaCard("ps", Object.assign({}, psDefaultsOpts(), { overrideModel: model }));
|
|
479
|
+
},
|
|
480
|
+
};
|
|
373
481
|
}
|
|
374
482
|
|
|
375
483
|
function populateDefaults() {
|
|
376
|
-
var
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
// Model list
|
|
383
|
-
var modelList = document.getElementById("ps-model-list");
|
|
384
|
-
if (modelList) {
|
|
385
|
-
modelList.innerHTML = "";
|
|
386
|
-
for (var i = 0; i < models.length; i++) {
|
|
387
|
-
(function (m) {
|
|
388
|
-
var item = document.createElement("div");
|
|
389
|
-
item.className = "settings-model-item" + (m.value === model ? " active" : "");
|
|
390
|
-
|
|
391
|
-
var nameSpan = document.createElement("span");
|
|
392
|
-
nameSpan.className = "settings-model-name";
|
|
393
|
-
nameSpan.textContent = m.displayName || m.value;
|
|
394
|
-
item.appendChild(nameSpan);
|
|
395
|
-
|
|
396
|
-
var desc = getModelDesc(m.value);
|
|
397
|
-
if (desc) {
|
|
398
|
-
var descSpan = document.createElement("span");
|
|
399
|
-
descSpan.className = "settings-model-desc";
|
|
400
|
-
descSpan.textContent = desc;
|
|
401
|
-
item.appendChild(descSpan);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
item.addEventListener("click", function () {
|
|
405
|
-
if (ctx.ws && ctx.connected) {
|
|
406
|
-
ctx.ws.send(JSON.stringify({ type: "set_project_default_model", model: m.value }));
|
|
407
|
-
}
|
|
408
|
-
var items = modelList.querySelectorAll(".settings-model-item");
|
|
409
|
-
for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
|
|
410
|
-
item.classList.add("active");
|
|
411
|
-
// Show/hide beta card based on Sonnet
|
|
412
|
-
updateBetaCard("ps", m.value);
|
|
413
|
-
});
|
|
414
|
-
modelList.appendChild(item);
|
|
415
|
-
})(models[i]);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Beta 1M toggle
|
|
420
|
-
updateBetaCard("ps", model);
|
|
421
|
-
var beta1m = document.getElementById("ps-beta-1m");
|
|
422
|
-
if (beta1m) {
|
|
423
|
-
var hasBeta = false;
|
|
424
|
-
for (var bi = 0; bi < betas.length; bi++) {
|
|
425
|
-
if (betas[bi].indexOf("context-1m") !== -1) { hasBeta = true; break; }
|
|
426
|
-
}
|
|
427
|
-
beta1m.checked = hasBeta;
|
|
428
|
-
beta1m.onchange = function () {
|
|
429
|
-
toggleBeta1m(this.checked);
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// Mode list
|
|
434
|
-
var modeList = document.getElementById("ps-mode-list");
|
|
435
|
-
if (modeList) {
|
|
436
|
-
modeList.innerHTML = "";
|
|
437
|
-
for (var k = 0; k < MODE_OPTIONS.length; k++) {
|
|
438
|
-
(function (opt) {
|
|
439
|
-
var item = document.createElement("div");
|
|
440
|
-
item.className = "settings-model-item" + (opt.value === mode ? " active" : "");
|
|
441
|
-
|
|
442
|
-
var nameSpan = document.createElement("span");
|
|
443
|
-
nameSpan.className = "settings-model-name";
|
|
444
|
-
nameSpan.textContent = opt.label;
|
|
445
|
-
item.appendChild(nameSpan);
|
|
446
|
-
|
|
447
|
-
var descSpan = document.createElement("span");
|
|
448
|
-
descSpan.className = "settings-model-desc";
|
|
449
|
-
descSpan.textContent = opt.desc;
|
|
450
|
-
item.appendChild(descSpan);
|
|
451
|
-
|
|
452
|
-
item.addEventListener("click", function () {
|
|
453
|
-
if (ctx.ws && ctx.connected) {
|
|
454
|
-
ctx.ws.send(JSON.stringify({ type: "set_project_default_mode", mode: opt.value }));
|
|
455
|
-
}
|
|
456
|
-
var items = modeList.querySelectorAll(".settings-model-item");
|
|
457
|
-
for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
|
|
458
|
-
item.classList.add("active");
|
|
459
|
-
});
|
|
460
|
-
modeList.appendChild(item);
|
|
461
|
-
})(MODE_OPTIONS[k]);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// Effort bar
|
|
466
|
-
var effortBar = document.getElementById("ps-effort-bar");
|
|
467
|
-
if (effortBar) {
|
|
468
|
-
effortBar.innerHTML = "";
|
|
469
|
-
for (var e = 0; e < EFFORT_LEVELS.length; e++) {
|
|
470
|
-
(function (lvl) {
|
|
471
|
-
var btn = document.createElement("button");
|
|
472
|
-
btn.className = "settings-btn-option" + (lvl.value === effort ? " active" : "");
|
|
473
|
-
btn.textContent = lvl.value.charAt(0).toUpperCase() + lvl.value.slice(1);
|
|
474
|
-
btn.title = lvl.desc;
|
|
475
|
-
btn.addEventListener("click", function () {
|
|
476
|
-
if (ctx.ws && ctx.connected) {
|
|
477
|
-
ctx.ws.send(JSON.stringify({ type: "set_project_default_effort", effort: lvl.value }));
|
|
478
|
-
}
|
|
479
|
-
var btns = effortBar.querySelectorAll(".settings-btn-option");
|
|
480
|
-
for (var j = 0; j < btns.length; j++) btns[j].classList.remove("active");
|
|
481
|
-
btn.classList.add("active");
|
|
482
|
-
});
|
|
483
|
-
effortBar.appendChild(btn);
|
|
484
|
-
})(EFFORT_LEVELS[e]);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
function updateBetaCard(prefix, model) {
|
|
490
|
-
var card = document.getElementById(prefix + "-beta-card");
|
|
491
|
-
if (card) {
|
|
492
|
-
card.style.display = isSonnetModel(model) ? "" : "none";
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
function toggleBeta1m(enable) {
|
|
497
|
-
var betas = ctx.currentBetas || [];
|
|
498
|
-
var newBetas;
|
|
499
|
-
if (enable) {
|
|
500
|
-
newBetas = betas.slice();
|
|
501
|
-
newBetas.push("context-1m-2025-08-07");
|
|
502
|
-
} else {
|
|
503
|
-
newBetas = [];
|
|
504
|
-
for (var i = 0; i < betas.length; i++) {
|
|
505
|
-
if (betas[i].indexOf("context-1m") === -1) {
|
|
506
|
-
newBetas.push(betas[i]);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
if (ctx.ws && ctx.connected) {
|
|
511
|
-
ctx.ws.send(JSON.stringify({ type: "set_betas", betas: newBetas }));
|
|
512
|
-
}
|
|
484
|
+
var opts = psDefaultsOpts();
|
|
485
|
+
renderModelList("ps", opts);
|
|
486
|
+
renderBetaCard("ps", opts);
|
|
487
|
+
renderModeList("ps", opts);
|
|
488
|
+
renderEffortBar("ps", opts);
|
|
489
|
+
renderThinkingBar("ps", opts);
|
|
513
490
|
}
|
|
514
491
|
|
|
515
492
|
// ===== Instructions (CLAUDE.md) =====
|
|
@@ -899,3 +876,12 @@ export function updateProjectSettingsName(name) {
|
|
|
899
876
|
var navTitle = document.getElementById("ps-nav-title");
|
|
900
877
|
if (navTitle) navTitle.textContent = name || "-";
|
|
901
878
|
}
|
|
879
|
+
|
|
880
|
+
export function handleProjectOwnerChanged(msg) {
|
|
881
|
+
if (currentProject) {
|
|
882
|
+
currentProject.projectOwnerId = msg.ownerId;
|
|
883
|
+
}
|
|
884
|
+
var ownerNameEl = document.getElementById("ps-owner-name");
|
|
885
|
+
if (ownerNameEl) ownerNameEl.textContent = msg.ownerName || msg.ownerId || "Not set";
|
|
886
|
+
showToast("Project ownership transferred to " + (msg.ownerName || "new owner"));
|
|
887
|
+
}
|