clay-server 2.11.0-beta.2 → 2.11.0-beta.4
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/daemon.js +11 -1
- package/lib/project.js +14 -3
- package/lib/public/app.js +19 -5
- package/lib/public/css/admin.css +50 -10
- package/lib/public/css/server-settings.css +30 -2
- package/lib/public/index.html +92 -63
- package/lib/public/modules/admin.js +4 -5
- package/lib/public/modules/notifications.js +3 -1
- package/lib/public/modules/project-settings.js +36 -168
- package/lib/public/modules/server-settings.js +78 -189
- package/lib/public/modules/settings-defaults.js +243 -0
- package/lib/server.js +3 -0
- package/lib/updater.js +38 -11
- package/package.json +1 -1
|
@@ -340,9 +340,9 @@ function renderSmtpTab(body, cfg) {
|
|
|
340
340
|
|
|
341
341
|
var emailEnabled = !!(cfg && cfg.emailLoginEnabled);
|
|
342
342
|
if (hasConfig) {
|
|
343
|
-
html += '<div class="admin-smtp-status admin-smtp-status-ok">' + iconHtml("check-circle") + ' SMTP configured
|
|
343
|
+
html += '<div class="admin-smtp-status admin-smtp-status-ok">' + iconHtml("check-circle") + ' SMTP configured. Invite links and one-time login codes are sent via email.</div>';
|
|
344
344
|
} else {
|
|
345
|
-
html += '<div class="admin-smtp-status admin-smtp-status-off">' + iconHtml("mail-x") + ' SMTP not configured
|
|
345
|
+
html += '<div class="admin-smtp-status admin-smtp-status-off">' + iconHtml("mail-x") + ' SMTP not configured. Users log in with a PIN instead of email codes.</div>';
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
html += '<div class="admin-smtp-fields">';
|
|
@@ -371,13 +371,12 @@ function renderSmtpTab(body, cfg) {
|
|
|
371
371
|
'<label>From Address</label>' +
|
|
372
372
|
'<input type="text" id="smtp-from" class="admin-smtp-input" placeholder="Clay <noreply@example.com>" value="' + escapeHtml((cfg && cfg.from) || "") + '">' +
|
|
373
373
|
'</div>';
|
|
374
|
-
html += '
|
|
375
|
-
|
|
376
|
-
html += '<div class="admin-smtp-row" style="margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color,#e5e7eb)">' +
|
|
374
|
+
html += '<div class="admin-smtp-row admin-smtp-row-otp">' +
|
|
377
375
|
'<label>Email Login (OTP)</label>' +
|
|
378
376
|
'<label class="admin-smtp-toggle"><input type="checkbox" id="smtp-email-login"' + (emailEnabled ? " checked" : "") + (hasConfig ? "" : " disabled") + '>' +
|
|
379
377
|
'<span>' + (hasConfig ? "Require email for user registration and enable OTP login" : "Configure SMTP first to enable") + '</span></label>' +
|
|
380
378
|
'</div>';
|
|
379
|
+
html += '</div>';
|
|
381
380
|
|
|
382
381
|
html += '<div class="admin-smtp-actions">';
|
|
383
382
|
html += '<button class="admin-action-btn" id="smtp-save">' + iconHtml("save") + ' Save</button>';
|
|
@@ -92,7 +92,9 @@ export function initNotifications(_ctx) {
|
|
|
92
92
|
if (copyBtn) {
|
|
93
93
|
copyBtn.addEventListener("click", function (e) {
|
|
94
94
|
e.stopPropagation();
|
|
95
|
-
|
|
95
|
+
var cmdEl = document.getElementById("update-manual-cmd");
|
|
96
|
+
var cmdText = cmdEl ? cmdEl.textContent : "npx clay-server@latest";
|
|
97
|
+
copyToClipboard(cmdText).then(function () {
|
|
96
98
|
copyBtn.classList.add("copied");
|
|
97
99
|
copyBtn.innerHTML = iconHtml("check");
|
|
98
100
|
refreshIcons();
|
|
@@ -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) {
|
|
@@ -169,6 +152,9 @@ export function openProjectSettings(slug, project) {
|
|
|
169
152
|
// Populate profile
|
|
170
153
|
populateProfile();
|
|
171
154
|
|
|
155
|
+
// Close file viewer if open (prevent split-screen)
|
|
156
|
+
closeFileViewer();
|
|
157
|
+
|
|
172
158
|
// Show panel
|
|
173
159
|
panelEl.classList.remove("hidden");
|
|
174
160
|
refreshIcons();
|
|
@@ -358,158 +344,40 @@ function showPsEmojiPicker() {
|
|
|
358
344
|
}
|
|
359
345
|
|
|
360
346
|
// ===== Defaults =====
|
|
361
|
-
function
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
347
|
+
function psSendMsg(type, data) {
|
|
348
|
+
var ws = ctx.ws;
|
|
349
|
+
if (ws && ws.readyState === 1) {
|
|
350
|
+
var msg = Object.assign({ type: type }, data);
|
|
351
|
+
ws.send(JSON.stringify(msg));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function psDefaultsOpts() {
|
|
356
|
+
return {
|
|
357
|
+
models: ctx.currentModels || [],
|
|
358
|
+
currentModel: ctx.currentModel || "",
|
|
359
|
+
currentMode: ctx.currentMode || "default",
|
|
360
|
+
currentEffort: ctx.currentEffort || "medium",
|
|
361
|
+
currentThinking: ctx.currentThinking || "adaptive",
|
|
362
|
+
currentThinkingBudget: ctx.currentThinkingBudget || 10000,
|
|
363
|
+
currentBetas: ctx.currentBetas || [],
|
|
364
|
+
sendMsg: psSendMsg,
|
|
365
|
+
modelMsgType: "set_project_default_model",
|
|
366
|
+
modeMsgType: "set_project_default_mode",
|
|
367
|
+
effortMsgType: "set_project_default_effort",
|
|
368
|
+
onModelSelect: function (model) {
|
|
369
|
+
renderBetaCard("ps", Object.assign({}, psDefaultsOpts(), { overrideModel: model }));
|
|
370
|
+
},
|
|
371
|
+
};
|
|
373
372
|
}
|
|
374
373
|
|
|
375
374
|
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
|
-
}
|
|
375
|
+
var opts = psDefaultsOpts();
|
|
376
|
+
renderModelList("ps", opts);
|
|
377
|
+
renderBetaCard("ps", opts);
|
|
378
|
+
renderModeList("ps", opts);
|
|
379
|
+
renderEffortBar("ps", opts);
|
|
380
|
+
renderThinkingBar("ps", opts);
|
|
513
381
|
}
|
|
514
382
|
|
|
515
383
|
// ===== Instructions (CLAUDE.md) =====
|
|
@@ -3,6 +3,8 @@ import { refreshIcons } from './icons.js';
|
|
|
3
3
|
import { showToast, copyToClipboard } from './utils.js';
|
|
4
4
|
import { parseEnvString, looksLikeEnv } from './project-settings.js';
|
|
5
5
|
import { checkAdminAccess, loadAdminSection } from './admin.js';
|
|
6
|
+
import { closeFileViewer } from './filebrowser.js';
|
|
7
|
+
import { renderModelList, renderModeList, renderEffortBar, renderThinkingBar, renderBetaCard, isSonnetModel } from './settings-defaults.js';
|
|
6
8
|
|
|
7
9
|
var ctx = null;
|
|
8
10
|
var settingsEl = null;
|
|
@@ -12,26 +14,6 @@ var navItems = null;
|
|
|
12
14
|
var sections = null;
|
|
13
15
|
var statsTimer = null;
|
|
14
16
|
|
|
15
|
-
var SS_MODE_OPTIONS = [
|
|
16
|
-
{ value: "default", label: "Default", desc: "Claude asks for permission before running tools and editing files." },
|
|
17
|
-
{ value: "plan", label: "Plan", desc: "Claude creates a plan first and asks for approval before making changes." },
|
|
18
|
-
{ value: "acceptEdits", label: "Auto-accept edits", desc: "File edits are applied automatically. Claude still asks before running commands." },
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
var SS_EFFORT_LEVELS = [
|
|
22
|
-
{ value: "low", desc: "Quick, concise responses. Best for simple questions." },
|
|
23
|
-
{ value: "medium", desc: "Balanced responses with moderate reasoning. Good for most tasks." },
|
|
24
|
-
{ value: "high", desc: "Thorough responses with deeper analysis. Good for complex tasks." },
|
|
25
|
-
{ value: "max", desc: "Maximum reasoning depth. Best for the most difficult problems." },
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
var SS_MODEL_DESCRIPTIONS = {
|
|
29
|
-
"default": "Automatically selects the best model for the task.",
|
|
30
|
-
"sonnet": "Fast and capable. Great balance of speed and intelligence.",
|
|
31
|
-
"haiku": "Fastest model. Best for quick tasks and simple questions.",
|
|
32
|
-
"opus": "Most powerful model. Best for complex reasoning and analysis.",
|
|
33
|
-
};
|
|
34
|
-
|
|
35
17
|
export function initServerSettings(appCtx) {
|
|
36
18
|
ctx = appCtx;
|
|
37
19
|
settingsEl = document.getElementById("server-settings");
|
|
@@ -257,6 +239,7 @@ function switchSection(sectionName) {
|
|
|
257
239
|
}
|
|
258
240
|
|
|
259
241
|
function openSettings() {
|
|
242
|
+
closeFileViewer();
|
|
260
243
|
settingsEl.classList.remove("hidden");
|
|
261
244
|
settingsBtn.classList.add("active");
|
|
262
245
|
refreshIcons(settingsEl);
|
|
@@ -281,7 +264,7 @@ function openSettings() {
|
|
|
281
264
|
function resetRestartButton() {
|
|
282
265
|
var btn = document.getElementById("settings-restart-btn");
|
|
283
266
|
var errorEl = document.getElementById("settings-restart-error");
|
|
284
|
-
if (btn) { btn.disabled = false; btn.innerHTML = '<i data-lucide="refresh-cw" style="width:14px;height:14px;vertical-align:-2px;margin-right:4px;"></i>Restart
|
|
267
|
+
if (btn) { btn.disabled = false; btn.innerHTML = '<i data-lucide="refresh-cw" style="width:14px;height:14px;vertical-align:-2px;margin-right:4px;"></i>Restart'; }
|
|
285
268
|
if (errorEl) errorEl.classList.add("hidden");
|
|
286
269
|
}
|
|
287
270
|
|
|
@@ -315,19 +298,14 @@ function requestStats() {
|
|
|
315
298
|
}
|
|
316
299
|
|
|
317
300
|
function populateSettings() {
|
|
318
|
-
// Server name
|
|
319
301
|
var nameEl = document.getElementById("settings-server-name");
|
|
320
|
-
var projNameEl = document.getElementById("settings-project-name");
|
|
321
|
-
var cwdEl = document.getElementById("settings-project-cwd");
|
|
322
302
|
var versionEl = document.getElementById("settings-server-version");
|
|
323
303
|
var slugEl = document.getElementById("settings-project-slug");
|
|
324
304
|
var wsPathEl = document.getElementById("settings-ws-path");
|
|
325
305
|
var skipPermsEl = document.getElementById("settings-skip-perms");
|
|
326
306
|
|
|
327
|
-
|
|
328
|
-
if (nameEl) nameEl.textContent =
|
|
329
|
-
if (projNameEl) projNameEl.textContent = projectName;
|
|
330
|
-
if (cwdEl) cwdEl.textContent = ctx.projectName || "-";
|
|
307
|
+
// Nav header defaults to hostname (updated by updateDaemonConfig)
|
|
308
|
+
if (nameEl && !nameEl.textContent) nameEl.textContent = "Server";
|
|
331
309
|
|
|
332
310
|
var footerVersion = document.getElementById("footer-version");
|
|
333
311
|
if (versionEl && footerVersion) {
|
|
@@ -352,6 +330,7 @@ function populateSettings() {
|
|
|
352
330
|
updateModelList();
|
|
353
331
|
updateModeList();
|
|
354
332
|
updateEffortBar();
|
|
333
|
+
updateThinkingBar();
|
|
355
334
|
updateSsBetaCard();
|
|
356
335
|
}
|
|
357
336
|
|
|
@@ -368,174 +347,49 @@ function syncNotifToggles() {
|
|
|
368
347
|
}
|
|
369
348
|
}
|
|
370
349
|
|
|
371
|
-
function
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
350
|
+
function ssSendMsg(type, data) {
|
|
351
|
+
var ws = ctx.ws;
|
|
352
|
+
if (ws && ws.readyState === 1) {
|
|
353
|
+
var msg = Object.assign({ type: type }, data);
|
|
354
|
+
ws.send(JSON.stringify(msg));
|
|
376
355
|
}
|
|
377
|
-
return "";
|
|
378
356
|
}
|
|
379
357
|
|
|
380
|
-
function
|
|
381
|
-
|
|
382
|
-
|
|
358
|
+
function ssDefaultsOpts() {
|
|
359
|
+
return {
|
|
360
|
+
models: ctx.currentModels || [],
|
|
361
|
+
currentModel: ctx.currentModel || ctx._currentModelValue || "",
|
|
362
|
+
currentMode: ctx.currentMode || "default",
|
|
363
|
+
currentEffort: ctx.currentEffort || "medium",
|
|
364
|
+
currentThinking: ctx.currentThinking || "adaptive",
|
|
365
|
+
currentThinkingBudget: ctx.currentThinkingBudget || 10000,
|
|
366
|
+
currentBetas: ctx.currentBetas || [],
|
|
367
|
+
sendMsg: ssSendMsg,
|
|
368
|
+
modelMsgType: "set_model",
|
|
369
|
+
modeMsgType: "set_server_default_mode",
|
|
370
|
+
effortMsgType: "set_server_default_effort",
|
|
371
|
+
onModelSelect: function (model) { updateSsBetaCard(model); },
|
|
372
|
+
};
|
|
383
373
|
}
|
|
384
374
|
|
|
385
375
|
function updateModelList() {
|
|
386
|
-
|
|
387
|
-
if (!listEl) return;
|
|
388
|
-
|
|
389
|
-
var models = ctx.currentModels || [];
|
|
390
|
-
var currentModel = ctx.currentModel || ctx._currentModelValue || "";
|
|
391
|
-
|
|
392
|
-
listEl.innerHTML = "";
|
|
393
|
-
if (models.length === 0) {
|
|
394
|
-
listEl.innerHTML = '<div style="font-size:13px;color:var(--text-dimmer);">No models available</div>';
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
for (var i = 0; i < models.length; i++) {
|
|
399
|
-
(function (m) {
|
|
400
|
-
var value = m.value || "";
|
|
401
|
-
var label = m.displayName || value;
|
|
402
|
-
var item = document.createElement("div");
|
|
403
|
-
item.className = "settings-model-item";
|
|
404
|
-
if (value === currentModel) item.classList.add("active");
|
|
405
|
-
item.dataset.model = value;
|
|
406
|
-
|
|
407
|
-
var nameSpan = document.createElement("span");
|
|
408
|
-
nameSpan.className = "settings-model-name";
|
|
409
|
-
nameSpan.textContent = label;
|
|
410
|
-
item.appendChild(nameSpan);
|
|
411
|
-
|
|
412
|
-
var desc = ssGetModelDesc(value);
|
|
413
|
-
if (desc) {
|
|
414
|
-
var descSpan = document.createElement("span");
|
|
415
|
-
descSpan.className = "settings-model-desc";
|
|
416
|
-
descSpan.textContent = desc;
|
|
417
|
-
item.appendChild(descSpan);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
item.addEventListener("click", function () {
|
|
421
|
-
var ws = ctx.ws;
|
|
422
|
-
if (ws && ws.readyState === 1) {
|
|
423
|
-
ws.send(JSON.stringify({ type: "set_model", model: value }));
|
|
424
|
-
}
|
|
425
|
-
var items = listEl.querySelectorAll(".settings-model-item");
|
|
426
|
-
for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
|
|
427
|
-
item.classList.add("active");
|
|
428
|
-
updateSsBetaCard(value);
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
listEl.appendChild(item);
|
|
432
|
-
})(models[i]);
|
|
433
|
-
}
|
|
376
|
+
renderModelList("ss", ssDefaultsOpts());
|
|
434
377
|
}
|
|
435
378
|
|
|
436
379
|
function updateModeList() {
|
|
437
|
-
|
|
438
|
-
if (!listEl) return;
|
|
439
|
-
|
|
440
|
-
var currentMode = ctx.currentMode || "default";
|
|
441
|
-
listEl.innerHTML = "";
|
|
442
|
-
|
|
443
|
-
for (var i = 0; i < SS_MODE_OPTIONS.length; i++) {
|
|
444
|
-
(function (opt) {
|
|
445
|
-
var item = document.createElement("div");
|
|
446
|
-
item.className = "settings-model-item" + (opt.value === currentMode ? " active" : "");
|
|
447
|
-
|
|
448
|
-
var nameSpan = document.createElement("span");
|
|
449
|
-
nameSpan.className = "settings-model-name";
|
|
450
|
-
nameSpan.textContent = opt.label;
|
|
451
|
-
item.appendChild(nameSpan);
|
|
452
|
-
|
|
453
|
-
var descSpan = document.createElement("span");
|
|
454
|
-
descSpan.className = "settings-model-desc";
|
|
455
|
-
descSpan.textContent = opt.desc;
|
|
456
|
-
item.appendChild(descSpan);
|
|
457
|
-
|
|
458
|
-
item.addEventListener("click", function () {
|
|
459
|
-
var ws = ctx.ws;
|
|
460
|
-
if (ws && ws.readyState === 1) {
|
|
461
|
-
ws.send(JSON.stringify({ type: "set_server_default_mode", mode: opt.value }));
|
|
462
|
-
}
|
|
463
|
-
var items = listEl.querySelectorAll(".settings-model-item");
|
|
464
|
-
for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
|
|
465
|
-
item.classList.add("active");
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
listEl.appendChild(item);
|
|
469
|
-
})(SS_MODE_OPTIONS[i]);
|
|
470
|
-
}
|
|
380
|
+
renderModeList("ss", ssDefaultsOpts());
|
|
471
381
|
}
|
|
472
382
|
|
|
473
383
|
function updateEffortBar() {
|
|
474
|
-
|
|
475
|
-
if (!bar) return;
|
|
476
|
-
|
|
477
|
-
var currentEffort = ctx.currentEffort || "medium";
|
|
478
|
-
bar.innerHTML = "";
|
|
479
|
-
|
|
480
|
-
for (var i = 0; i < SS_EFFORT_LEVELS.length; i++) {
|
|
481
|
-
(function (lvl) {
|
|
482
|
-
var btn = document.createElement("button");
|
|
483
|
-
btn.className = "settings-btn-option" + (lvl.value === currentEffort ? " active" : "");
|
|
484
|
-
btn.textContent = lvl.value.charAt(0).toUpperCase() + lvl.value.slice(1);
|
|
485
|
-
btn.title = lvl.desc;
|
|
486
|
-
btn.addEventListener("click", function () {
|
|
487
|
-
var ws = ctx.ws;
|
|
488
|
-
if (ws && ws.readyState === 1) {
|
|
489
|
-
ws.send(JSON.stringify({ type: "set_server_default_effort", effort: lvl.value }));
|
|
490
|
-
}
|
|
491
|
-
var btns = bar.querySelectorAll(".settings-btn-option");
|
|
492
|
-
for (var j = 0; j < btns.length; j++) btns[j].classList.remove("active");
|
|
493
|
-
btn.classList.add("active");
|
|
494
|
-
});
|
|
495
|
-
bar.appendChild(btn);
|
|
496
|
-
})(SS_EFFORT_LEVELS[i]);
|
|
497
|
-
}
|
|
384
|
+
renderEffortBar("ss", ssDefaultsOpts());
|
|
498
385
|
}
|
|
499
386
|
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
var card = document.getElementById("ss-beta-card");
|
|
503
|
-
if (card) {
|
|
504
|
-
card.style.display = ssIsSonnetModel(model) ? "" : "none";
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
var toggle = document.getElementById("ss-beta-1m");
|
|
508
|
-
if (toggle) {
|
|
509
|
-
var betas = ctx.currentBetas || [];
|
|
510
|
-
var hasBeta = false;
|
|
511
|
-
for (var i = 0; i < betas.length; i++) {
|
|
512
|
-
if (betas[i].indexOf("context-1m") !== -1) { hasBeta = true; break; }
|
|
513
|
-
}
|
|
514
|
-
toggle.checked = hasBeta;
|
|
515
|
-
toggle.onchange = function () {
|
|
516
|
-
ssToggleBeta1m(this.checked);
|
|
517
|
-
};
|
|
518
|
-
}
|
|
387
|
+
function updateThinkingBar() {
|
|
388
|
+
renderThinkingBar("ss", ssDefaultsOpts());
|
|
519
389
|
}
|
|
520
390
|
|
|
521
|
-
function
|
|
522
|
-
|
|
523
|
-
var newBetas;
|
|
524
|
-
if (enable) {
|
|
525
|
-
newBetas = betas.slice();
|
|
526
|
-
newBetas.push("context-1m-2025-08-07");
|
|
527
|
-
} else {
|
|
528
|
-
newBetas = [];
|
|
529
|
-
for (var i = 0; i < betas.length; i++) {
|
|
530
|
-
if (betas[i].indexOf("context-1m") === -1) {
|
|
531
|
-
newBetas.push(betas[i]);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
var ws = ctx.ws;
|
|
536
|
-
if (ws && ws.readyState === 1) {
|
|
537
|
-
ws.send(JSON.stringify({ type: "set_betas", betas: newBetas }));
|
|
538
|
-
}
|
|
391
|
+
function updateSsBetaCard(overrideModel) {
|
|
392
|
+
renderBetaCard("ss", Object.assign(ssDefaultsOpts(), { overrideModel: overrideModel }));
|
|
539
393
|
}
|
|
540
394
|
|
|
541
395
|
export function updateSettingsStats(data) {
|
|
@@ -561,6 +415,7 @@ export function updateSettingsModels(current, models) {
|
|
|
561
415
|
updateModelList();
|
|
562
416
|
updateModeList();
|
|
563
417
|
updateEffortBar();
|
|
418
|
+
updateThinkingBar();
|
|
564
419
|
updateSsBetaCard();
|
|
565
420
|
}
|
|
566
421
|
}
|
|
@@ -574,6 +429,20 @@ function requestDaemonConfig() {
|
|
|
574
429
|
}
|
|
575
430
|
|
|
576
431
|
export function updateDaemonConfig(config) {
|
|
432
|
+
// Nav header: show hostname (strip .local suffix, lowercase)
|
|
433
|
+
var nameEl = document.getElementById("settings-server-name");
|
|
434
|
+
if (nameEl && config.hostname) {
|
|
435
|
+
var displayHost = config.hostname.replace(/\.local$/i, "").toLowerCase();
|
|
436
|
+
nameEl.textContent = displayHost;
|
|
437
|
+
nameEl.title = config.hostname;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Host
|
|
441
|
+
var hostnameEl = document.getElementById("settings-hostname");
|
|
442
|
+
var lanIpEl = document.getElementById("settings-lan-ip");
|
|
443
|
+
if (hostnameEl) hostnameEl.textContent = config.hostname || "-";
|
|
444
|
+
if (lanIpEl) lanIpEl.textContent = config.lanIp || "";
|
|
445
|
+
|
|
577
446
|
// Port
|
|
578
447
|
var portEl = document.getElementById("settings-port");
|
|
579
448
|
if (portEl) portEl.textContent = String(config.port || "-");
|
|
@@ -599,14 +468,34 @@ export function updateDaemonConfig(config) {
|
|
|
599
468
|
var keepAwakeToggle = document.getElementById("settings-keep-awake");
|
|
600
469
|
if (keepAwakeToggle) keepAwakeToggle.checked = !!config.keepAwake;
|
|
601
470
|
|
|
602
|
-
//
|
|
603
|
-
var
|
|
604
|
-
if (
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
471
|
+
// Early Access toggle
|
|
472
|
+
var channelToggle = document.getElementById("settings-update-channel");
|
|
473
|
+
if (channelToggle) {
|
|
474
|
+
channelToggle.checked = (config.updateChannel === "beta");
|
|
475
|
+
channelToggle.onchange = function () {
|
|
476
|
+
var channel = channelToggle.checked ? "beta" : "stable";
|
|
477
|
+
if (ctx.ws && ctx.ws.readyState === 1) {
|
|
478
|
+
ctx.ws.send(JSON.stringify({ type: "set_update_channel", channel: channel }));
|
|
479
|
+
// Auto-trigger update check after channel change
|
|
480
|
+
setTimeout(function () {
|
|
481
|
+
ctx.ws.send(JSON.stringify({ type: "check_update" }));
|
|
482
|
+
}, 200);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Show keep awake section/nav only on macOS
|
|
488
|
+
var keepAwakeSection = document.getElementById("settings-keep-awake-section");
|
|
489
|
+
var keepAwakeNav = document.getElementById("settings-keep-awake-nav");
|
|
490
|
+
var keepAwakeOpt = document.getElementById("settings-keep-awake-opt");
|
|
491
|
+
if (config.platform === "darwin") {
|
|
492
|
+
if (keepAwakeSection) keepAwakeSection.classList.remove("hidden");
|
|
493
|
+
if (keepAwakeNav) keepAwakeNav.classList.remove("hidden");
|
|
494
|
+
if (keepAwakeOpt) keepAwakeOpt.classList.remove("hidden");
|
|
495
|
+
} else {
|
|
496
|
+
if (keepAwakeSection) keepAwakeSection.classList.add("hidden");
|
|
497
|
+
if (keepAwakeNav) keepAwakeNav.classList.add("hidden");
|
|
498
|
+
if (keepAwakeOpt) keepAwakeOpt.classList.add("hidden");
|
|
610
499
|
}
|
|
611
500
|
}
|
|
612
501
|
|
|
@@ -632,7 +521,7 @@ export function handleRestartResult(msg) {
|
|
|
632
521
|
showToast("Server is restarting...");
|
|
633
522
|
} else {
|
|
634
523
|
if (restartBtn) {
|
|
635
|
-
restartBtn.textContent = "Restart
|
|
524
|
+
restartBtn.textContent = "Restart";
|
|
636
525
|
restartBtn.disabled = false;
|
|
637
526
|
}
|
|
638
527
|
if (errorEl) {
|