clay-server 2.5.1 → 2.7.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/bin/claude-relay.js +6 -0
- package/bin/cli.js +77 -11
- package/lib/cli-sessions.js +2 -7
- package/lib/config.js +86 -7
- package/lib/daemon.js +279 -6
- package/lib/ipc.js +12 -0
- package/lib/notes.js +4 -3
- package/lib/project.js +1174 -28
- package/lib/public/app.js +879 -31
- package/lib/public/css/diff.css +15 -4
- package/lib/public/css/filebrowser.css +363 -3
- package/lib/public/css/icon-strip.css +317 -1
- package/lib/public/css/input.css +127 -50
- package/lib/public/css/loop.css +780 -0
- package/lib/public/css/messages.css +1 -1
- package/lib/public/css/mobile-nav.css +6 -2
- package/lib/public/css/rewind.css +23 -0
- package/lib/public/css/server-settings.css +67 -20
- package/lib/public/css/sidebar.css +10 -4
- package/lib/public/css/skills.css +789 -0
- package/lib/public/css/sticky-notes.css +486 -0
- package/lib/public/css/title-bar.css +157 -7
- package/lib/public/index.html +366 -55
- package/lib/public/modules/diff.js +3 -3
- package/lib/public/modules/filebrowser.js +169 -45
- package/lib/public/modules/input.js +123 -56
- package/lib/public/modules/project-settings.js +906 -0
- package/lib/public/modules/qrcode.js +23 -26
- package/lib/public/modules/server-settings.js +449 -53
- package/lib/public/modules/sidebar.js +732 -1
- package/lib/public/modules/skills.js +794 -0
- package/lib/public/modules/sticky-notes.js +617 -52
- package/lib/public/modules/terminal.js +7 -0
- package/lib/public/modules/theme.js +9 -19
- package/lib/public/modules/tools.js +16 -2
- package/lib/public/style.css +2 -0
- package/lib/sdk-bridge.js +46 -7
- package/lib/server.js +305 -1
- package/lib/sessions.js +11 -5
- package/lib/utils.js +18 -0
- package/package.json +3 -2
|
@@ -9,33 +9,32 @@ function getShareUrl() {
|
|
|
9
9
|
return url;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function
|
|
13
|
-
var
|
|
14
|
-
var qrBtn = $("qr-btn");
|
|
15
|
-
var qrOverlay = $("qr-overlay");
|
|
16
|
-
var qrCanvas = $("qr-canvas");
|
|
17
|
-
var qrUrl = $("qr-url");
|
|
12
|
+
export function triggerShare() {
|
|
13
|
+
var url = getShareUrl();
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
// Use Web Share API if available
|
|
16
|
+
if (navigator.share) {
|
|
17
|
+
navigator.share({ title: document.title || "Clay", url: url }).catch(function () {});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
21
|
+
// Fallback: show QR overlay
|
|
22
|
+
var qrOverlay = document.getElementById("qr-overlay");
|
|
23
|
+
var qrCanvas = document.getElementById("qr-canvas");
|
|
24
|
+
var qrUrl = document.getElementById("qr-url");
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
qrUrl.innerHTML = url + '<span class="qr-hint">click to copy</span>';
|
|
26
|
+
var qr = qrcode(0, "M");
|
|
27
|
+
qr.addData(url);
|
|
28
|
+
qr.make();
|
|
29
|
+
qrCanvas.innerHTML = qr.createSvgTag(5, 0);
|
|
30
|
+
qrUrl.innerHTML = url + '<span class="qr-hint">click to copy</span>';
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
qrOverlay.classList.remove("hidden");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function initQrCode() {
|
|
36
|
+
var qrOverlay = document.getElementById("qr-overlay");
|
|
37
|
+
var qrUrl = document.getElementById("qr-url");
|
|
39
38
|
|
|
40
39
|
// click URL to copy
|
|
41
40
|
qrUrl.addEventListener("click", function () {
|
|
@@ -52,11 +51,10 @@ export function initQrCode() {
|
|
|
52
51
|
|
|
53
52
|
qrOverlay.addEventListener("click", function () {
|
|
54
53
|
qrOverlay.classList.add("hidden");
|
|
55
|
-
qrBtn.classList.remove("active");
|
|
56
54
|
});
|
|
57
55
|
|
|
58
56
|
// prevent closing when clicking the inner card
|
|
59
|
-
|
|
57
|
+
document.getElementById("qr-overlay-inner").addEventListener("click", function (e) {
|
|
60
58
|
e.stopPropagation();
|
|
61
59
|
});
|
|
62
60
|
|
|
@@ -64,7 +62,6 @@ export function initQrCode() {
|
|
|
64
62
|
document.addEventListener("keydown", function (e) {
|
|
65
63
|
if (e.key === "Escape" && !qrOverlay.classList.contains("hidden")) {
|
|
66
64
|
qrOverlay.classList.add("hidden");
|
|
67
|
-
qrBtn.classList.remove("active");
|
|
68
65
|
}
|
|
69
66
|
});
|
|
70
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// server-settings.js — Full-screen server settings overlay
|
|
2
2
|
import { refreshIcons } from './icons.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { showToast, copyToClipboard } from './utils.js';
|
|
4
|
+
import { parseEnvString, looksLikeEnv } from './project-settings.js';
|
|
5
5
|
|
|
6
6
|
var ctx = null;
|
|
7
7
|
var settingsEl = null;
|
|
@@ -11,6 +11,26 @@ var navItems = null;
|
|
|
11
11
|
var sections = null;
|
|
12
12
|
var statsTimer = null;
|
|
13
13
|
|
|
14
|
+
var SS_MODE_OPTIONS = [
|
|
15
|
+
{ value: "default", label: "Default", desc: "Claude asks for permission before running tools and editing files." },
|
|
16
|
+
{ value: "plan", label: "Plan", desc: "Claude creates a plan first and asks for approval before making changes." },
|
|
17
|
+
{ value: "acceptEdits", label: "Auto-accept edits", desc: "File edits are applied automatically. Claude still asks before running commands." },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
var SS_EFFORT_LEVELS = [
|
|
21
|
+
{ value: "low", desc: "Quick, concise responses. Best for simple questions." },
|
|
22
|
+
{ value: "medium", desc: "Balanced responses with moderate reasoning. Good for most tasks." },
|
|
23
|
+
{ value: "high", desc: "Thorough responses with deeper analysis. Good for complex tasks." },
|
|
24
|
+
{ value: "max", desc: "Maximum reasoning depth. Best for the most difficult problems." },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
var SS_MODEL_DESCRIPTIONS = {
|
|
28
|
+
"default": "Automatically selects the best model for the task.",
|
|
29
|
+
"sonnet": "Fast and capable. Great balance of speed and intelligence.",
|
|
30
|
+
"haiku": "Fastest model. Best for quick tasks and simple questions.",
|
|
31
|
+
"opus": "Most powerful model. Best for complex reasoning and analysis.",
|
|
32
|
+
};
|
|
33
|
+
|
|
14
34
|
export function initServerSettings(appCtx) {
|
|
15
35
|
ctx = appCtx;
|
|
16
36
|
settingsEl = document.getElementById("server-settings");
|
|
@@ -47,18 +67,22 @@ export function initServerSettings(appCtx) {
|
|
|
47
67
|
});
|
|
48
68
|
}
|
|
49
69
|
|
|
50
|
-
//
|
|
51
|
-
var
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
70
|
+
// Copyable command blocks
|
|
71
|
+
var copyables = settingsEl.querySelectorAll(".settings-copyable");
|
|
72
|
+
for (var c = 0; c < copyables.length; c++) {
|
|
73
|
+
copyables[c].addEventListener("click", function () {
|
|
74
|
+
var text = this.dataset.copy;
|
|
75
|
+
if (!text) return;
|
|
76
|
+
var btn = this.querySelector(".settings-copy-btn");
|
|
77
|
+
copyToClipboard(text).then(function () {
|
|
78
|
+
if (btn) {
|
|
79
|
+
var orig = btn.textContent;
|
|
80
|
+
btn.textContent = "✓";
|
|
81
|
+
setTimeout(function () { btn.textContent = orig; }, 1500);
|
|
82
|
+
}
|
|
83
|
+
showToast("Copied to clipboard");
|
|
60
84
|
});
|
|
61
|
-
}
|
|
85
|
+
});
|
|
62
86
|
}
|
|
63
87
|
|
|
64
88
|
// Notification toggles
|
|
@@ -104,7 +128,7 @@ export function initServerSettings(appCtx) {
|
|
|
104
128
|
if (!model) return;
|
|
105
129
|
var ws = ctx.ws;
|
|
106
130
|
if (ws && ws.readyState === 1) {
|
|
107
|
-
ws.send(JSON.stringify({ type: "
|
|
131
|
+
ws.send(JSON.stringify({ type: "set_server_default_model", model: model }));
|
|
108
132
|
}
|
|
109
133
|
});
|
|
110
134
|
|
|
@@ -140,6 +164,34 @@ export function initServerSettings(appCtx) {
|
|
|
140
164
|
});
|
|
141
165
|
}
|
|
142
166
|
|
|
167
|
+
// Global CLAUDE.md: save button
|
|
168
|
+
var ssClaudeMdSave = document.getElementById("ss-claudemd-save");
|
|
169
|
+
if (ssClaudeMdSave) {
|
|
170
|
+
ssClaudeMdSave.addEventListener("click", function () { saveGlobalClaudeMd(); });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Shared environment: add button
|
|
174
|
+
var ssEnvAddBtn = document.getElementById("ss-env-add-btn");
|
|
175
|
+
if (ssEnvAddBtn) {
|
|
176
|
+
ssEnvAddBtn.addEventListener("click", function () {
|
|
177
|
+
addSharedEnvRow("", "", true);
|
|
178
|
+
autoSaveSharedEnv();
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Restart server
|
|
183
|
+
var restartBtn = document.getElementById("settings-restart-btn");
|
|
184
|
+
if (restartBtn) {
|
|
185
|
+
restartBtn.addEventListener("click", function () {
|
|
186
|
+
var ws = ctx.ws;
|
|
187
|
+
if (ws && ws.readyState === 1) {
|
|
188
|
+
restartBtn.disabled = true;
|
|
189
|
+
restartBtn.textContent = "Restarting...";
|
|
190
|
+
ws.send(JSON.stringify({ type: "restart_server" }));
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
143
195
|
// Shutdown server
|
|
144
196
|
var shutdownInput = document.getElementById("settings-shutdown-input");
|
|
145
197
|
var shutdownBtn = document.getElementById("settings-shutdown-btn");
|
|
@@ -184,6 +236,10 @@ function switchSection(sectionName) {
|
|
|
184
236
|
var isActive2 = sections[j].dataset.section === sectionName;
|
|
185
237
|
sections[j].classList.toggle("active", isActive2);
|
|
186
238
|
}
|
|
239
|
+
|
|
240
|
+
// Lazy-load section data
|
|
241
|
+
if (sectionName === "claudemd") loadGlobalClaudeMd();
|
|
242
|
+
if (sectionName === "environment") loadSharedEnv();
|
|
187
243
|
}
|
|
188
244
|
|
|
189
245
|
function openSettings() {
|
|
@@ -192,6 +248,7 @@ function openSettings() {
|
|
|
192
248
|
refreshIcons(settingsEl);
|
|
193
249
|
populateSettings();
|
|
194
250
|
requestDaemonConfig();
|
|
251
|
+
resetRestartButton();
|
|
195
252
|
resetShutdownForm();
|
|
196
253
|
|
|
197
254
|
// Start periodic stats refresh
|
|
@@ -199,6 +256,13 @@ function openSettings() {
|
|
|
199
256
|
statsTimer = setInterval(requestStats, 5000);
|
|
200
257
|
}
|
|
201
258
|
|
|
259
|
+
function resetRestartButton() {
|
|
260
|
+
var btn = document.getElementById("settings-restart-btn");
|
|
261
|
+
var errorEl = document.getElementById("settings-restart-error");
|
|
262
|
+
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 Server'; }
|
|
263
|
+
if (errorEl) errorEl.classList.add("hidden");
|
|
264
|
+
}
|
|
265
|
+
|
|
202
266
|
function resetShutdownForm() {
|
|
203
267
|
var input = document.getElementById("settings-shutdown-input");
|
|
204
268
|
var btn = document.getElementById("settings-shutdown-btn");
|
|
@@ -262,14 +326,11 @@ function populateSettings() {
|
|
|
262
326
|
// Sync notification toggles
|
|
263
327
|
syncNotifToggles();
|
|
264
328
|
|
|
265
|
-
//
|
|
266
|
-
updateThemeDisplay();
|
|
267
|
-
|
|
268
|
-
// Context view
|
|
269
|
-
updateContextViewButtons();
|
|
270
|
-
|
|
271
|
-
// Models
|
|
329
|
+
// Session defaults
|
|
272
330
|
updateModelList();
|
|
331
|
+
updateModeList();
|
|
332
|
+
updateEffortBar();
|
|
333
|
+
updateSsBetaCard();
|
|
273
334
|
}
|
|
274
335
|
|
|
275
336
|
function syncNotifToggles() {
|
|
@@ -285,39 +346,26 @@ function syncNotifToggles() {
|
|
|
285
346
|
}
|
|
286
347
|
}
|
|
287
348
|
|
|
288
|
-
function
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
349
|
+
function ssGetModelDesc(model) {
|
|
350
|
+
if (!model) return "";
|
|
351
|
+
var lower = model.toLowerCase();
|
|
352
|
+
for (var key in SS_MODEL_DESCRIPTIONS) {
|
|
353
|
+
if (lower.indexOf(key) !== -1) return SS_MODEL_DESCRIPTIONS[key];
|
|
292
354
|
}
|
|
355
|
+
return "";
|
|
293
356
|
}
|
|
294
357
|
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
var btns = document.querySelectorAll("#settings-context-view .settings-btn-option");
|
|
299
|
-
for (var i = 0; i < btns.length; i++) {
|
|
300
|
-
btns[i].classList.toggle("active", btns[i].dataset.view === view);
|
|
301
|
-
}
|
|
358
|
+
function ssIsSonnetModel(model) {
|
|
359
|
+
if (!model) return false;
|
|
360
|
+
return model.toLowerCase().indexOf("sonnet") !== -1;
|
|
302
361
|
}
|
|
303
362
|
|
|
304
363
|
function updateModelList() {
|
|
305
364
|
var listEl = document.getElementById("settings-model-list");
|
|
306
|
-
var currentEl = document.getElementById("settings-current-model");
|
|
307
365
|
if (!listEl) return;
|
|
308
366
|
|
|
309
367
|
var models = ctx.currentModels || [];
|
|
310
|
-
var currentModel = ctx._currentModelValue || "";
|
|
311
|
-
|
|
312
|
-
// Look up display name for settings panel
|
|
313
|
-
var displayName = currentModel;
|
|
314
|
-
for (var j = 0; j < models.length; j++) {
|
|
315
|
-
if (models[j].value === currentModel && models[j].displayName) {
|
|
316
|
-
displayName = models[j].displayName;
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
if (currentEl) currentEl.textContent = displayName || "-";
|
|
368
|
+
var currentModel = ctx.currentModel || ctx._currentModelValue || "";
|
|
321
369
|
|
|
322
370
|
listEl.innerHTML = "";
|
|
323
371
|
if (models.length === 0) {
|
|
@@ -326,15 +374,145 @@ function updateModelList() {
|
|
|
326
374
|
}
|
|
327
375
|
|
|
328
376
|
for (var i = 0; i < models.length; i++) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
377
|
+
(function (m) {
|
|
378
|
+
var value = m.value || "";
|
|
379
|
+
var label = m.displayName || value;
|
|
380
|
+
var item = document.createElement("div");
|
|
381
|
+
item.className = "settings-model-item";
|
|
382
|
+
if (value === currentModel) item.classList.add("active");
|
|
383
|
+
item.dataset.model = value;
|
|
384
|
+
|
|
385
|
+
var nameSpan = document.createElement("span");
|
|
386
|
+
nameSpan.className = "settings-model-name";
|
|
387
|
+
nameSpan.textContent = label;
|
|
388
|
+
item.appendChild(nameSpan);
|
|
389
|
+
|
|
390
|
+
var desc = ssGetModelDesc(value);
|
|
391
|
+
if (desc) {
|
|
392
|
+
var descSpan = document.createElement("span");
|
|
393
|
+
descSpan.className = "settings-model-desc";
|
|
394
|
+
descSpan.textContent = desc;
|
|
395
|
+
item.appendChild(descSpan);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
item.addEventListener("click", function () {
|
|
399
|
+
var ws = ctx.ws;
|
|
400
|
+
if (ws && ws.readyState === 1) {
|
|
401
|
+
ws.send(JSON.stringify({ type: "set_model", model: value }));
|
|
402
|
+
}
|
|
403
|
+
var items = listEl.querySelectorAll(".settings-model-item");
|
|
404
|
+
for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
|
|
405
|
+
item.classList.add("active");
|
|
406
|
+
updateSsBetaCard(value);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
listEl.appendChild(item);
|
|
410
|
+
})(models[i]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function updateModeList() {
|
|
415
|
+
var listEl = document.getElementById("ss-mode-list");
|
|
416
|
+
if (!listEl) return;
|
|
417
|
+
|
|
418
|
+
var currentMode = ctx.currentMode || "default";
|
|
419
|
+
listEl.innerHTML = "";
|
|
420
|
+
|
|
421
|
+
for (var i = 0; i < SS_MODE_OPTIONS.length; i++) {
|
|
422
|
+
(function (opt) {
|
|
423
|
+
var item = document.createElement("div");
|
|
424
|
+
item.className = "settings-model-item" + (opt.value === currentMode ? " active" : "");
|
|
425
|
+
|
|
426
|
+
var nameSpan = document.createElement("span");
|
|
427
|
+
nameSpan.className = "settings-model-name";
|
|
428
|
+
nameSpan.textContent = opt.label;
|
|
429
|
+
item.appendChild(nameSpan);
|
|
430
|
+
|
|
431
|
+
var descSpan = document.createElement("span");
|
|
432
|
+
descSpan.className = "settings-model-desc";
|
|
433
|
+
descSpan.textContent = opt.desc;
|
|
434
|
+
item.appendChild(descSpan);
|
|
435
|
+
|
|
436
|
+
item.addEventListener("click", function () {
|
|
437
|
+
var ws = ctx.ws;
|
|
438
|
+
if (ws && ws.readyState === 1) {
|
|
439
|
+
ws.send(JSON.stringify({ type: "set_server_default_mode", mode: opt.value }));
|
|
440
|
+
}
|
|
441
|
+
var items = listEl.querySelectorAll(".settings-model-item");
|
|
442
|
+
for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
|
|
443
|
+
item.classList.add("active");
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
listEl.appendChild(item);
|
|
447
|
+
})(SS_MODE_OPTIONS[i]);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function updateEffortBar() {
|
|
452
|
+
var bar = document.getElementById("ss-effort-bar");
|
|
453
|
+
if (!bar) return;
|
|
454
|
+
|
|
455
|
+
var currentEffort = ctx.currentEffort || "medium";
|
|
456
|
+
bar.innerHTML = "";
|
|
457
|
+
|
|
458
|
+
for (var i = 0; i < SS_EFFORT_LEVELS.length; i++) {
|
|
459
|
+
(function (lvl) {
|
|
460
|
+
var btn = document.createElement("button");
|
|
461
|
+
btn.className = "settings-btn-option" + (lvl.value === currentEffort ? " active" : "");
|
|
462
|
+
btn.textContent = lvl.value.charAt(0).toUpperCase() + lvl.value.slice(1);
|
|
463
|
+
btn.title = lvl.desc;
|
|
464
|
+
btn.addEventListener("click", function () {
|
|
465
|
+
var ws = ctx.ws;
|
|
466
|
+
if (ws && ws.readyState === 1) {
|
|
467
|
+
ws.send(JSON.stringify({ type: "set_server_default_effort", effort: lvl.value }));
|
|
468
|
+
}
|
|
469
|
+
var btns = bar.querySelectorAll(".settings-btn-option");
|
|
470
|
+
for (var j = 0; j < btns.length; j++) btns[j].classList.remove("active");
|
|
471
|
+
btn.classList.add("active");
|
|
472
|
+
});
|
|
473
|
+
bar.appendChild(btn);
|
|
474
|
+
})(SS_EFFORT_LEVELS[i]);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function updateSsBetaCard(overrideModel) {
|
|
479
|
+
var model = overrideModel || ctx.currentModel || ctx._currentModelValue || "";
|
|
480
|
+
var card = document.getElementById("ss-beta-card");
|
|
481
|
+
if (card) {
|
|
482
|
+
card.style.display = ssIsSonnetModel(model) ? "" : "none";
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
var toggle = document.getElementById("ss-beta-1m");
|
|
486
|
+
if (toggle) {
|
|
487
|
+
var betas = ctx.currentBetas || [];
|
|
488
|
+
var hasBeta = false;
|
|
489
|
+
for (var i = 0; i < betas.length; i++) {
|
|
490
|
+
if (betas[i].indexOf("context-1m") !== -1) { hasBeta = true; break; }
|
|
491
|
+
}
|
|
492
|
+
toggle.checked = hasBeta;
|
|
493
|
+
toggle.onchange = function () {
|
|
494
|
+
ssToggleBeta1m(this.checked);
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function ssToggleBeta1m(enable) {
|
|
500
|
+
var betas = ctx.currentBetas || [];
|
|
501
|
+
var newBetas;
|
|
502
|
+
if (enable) {
|
|
503
|
+
newBetas = betas.slice();
|
|
504
|
+
newBetas.push("context-1m-2025-08-07");
|
|
505
|
+
} else {
|
|
506
|
+
newBetas = [];
|
|
507
|
+
for (var i = 0; i < betas.length; i++) {
|
|
508
|
+
if (betas[i].indexOf("context-1m") === -1) {
|
|
509
|
+
newBetas.push(betas[i]);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
var ws = ctx.ws;
|
|
514
|
+
if (ws && ws.readyState === 1) {
|
|
515
|
+
ws.send(JSON.stringify({ type: "set_betas", betas: newBetas }));
|
|
338
516
|
}
|
|
339
517
|
}
|
|
340
518
|
|
|
@@ -359,6 +537,9 @@ export function updateSettingsModels(current, models) {
|
|
|
359
537
|
ctx._currentModelValue = current;
|
|
360
538
|
if (isSettingsOpen()) {
|
|
361
539
|
updateModelList();
|
|
540
|
+
updateModeList();
|
|
541
|
+
updateEffortBar();
|
|
542
|
+
updateSsBetaCard();
|
|
362
543
|
}
|
|
363
544
|
}
|
|
364
545
|
|
|
@@ -420,6 +601,25 @@ export function handleKeepAwakeChanged(msg) {
|
|
|
420
601
|
if (keepAwakeToggle) keepAwakeToggle.checked = !!msg.keepAwake;
|
|
421
602
|
}
|
|
422
603
|
|
|
604
|
+
export function handleRestartResult(msg) {
|
|
605
|
+
var restartBtn = document.getElementById("settings-restart-btn");
|
|
606
|
+
var errorEl = document.getElementById("settings-restart-error");
|
|
607
|
+
|
|
608
|
+
if (msg.ok) {
|
|
609
|
+
if (restartBtn) restartBtn.textContent = "Server restarting...";
|
|
610
|
+
showToast("Server is restarting...");
|
|
611
|
+
} else {
|
|
612
|
+
if (restartBtn) {
|
|
613
|
+
restartBtn.textContent = "Restart Server";
|
|
614
|
+
restartBtn.disabled = false;
|
|
615
|
+
}
|
|
616
|
+
if (errorEl) {
|
|
617
|
+
errorEl.textContent = msg.error || "Restart failed";
|
|
618
|
+
errorEl.classList.remove("hidden");
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
423
623
|
export function handleShutdownResult(msg) {
|
|
424
624
|
var shutdownInput = document.getElementById("settings-shutdown-input");
|
|
425
625
|
var shutdownBtn = document.getElementById("settings-shutdown-btn");
|
|
@@ -492,6 +692,202 @@ function updatePinStatus(enabled) {
|
|
|
492
692
|
if (actionLabel) actionLabel.textContent = enabled ? "Change PIN" : "Set PIN";
|
|
493
693
|
}
|
|
494
694
|
|
|
695
|
+
// ===== Global CLAUDE.md =====
|
|
696
|
+
function loadGlobalClaudeMd() {
|
|
697
|
+
var editor = document.getElementById("ss-claudemd-editor");
|
|
698
|
+
var status = document.getElementById("ss-claudemd-status");
|
|
699
|
+
var saveStatus = document.getElementById("ss-claudemd-save-status");
|
|
700
|
+
if (saveStatus) saveStatus.textContent = "";
|
|
701
|
+
if (status) status.textContent = "Loading...";
|
|
702
|
+
|
|
703
|
+
var ws = ctx.ws;
|
|
704
|
+
if (ws && ws.readyState === 1) {
|
|
705
|
+
ws.send(JSON.stringify({ type: "read_global_claude_md" }));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
export function handleGlobalClaudeMdRead(msg) {
|
|
710
|
+
var editor = document.getElementById("ss-claudemd-editor");
|
|
711
|
+
var status = document.getElementById("ss-claudemd-status");
|
|
712
|
+
if (!editor) return;
|
|
713
|
+
|
|
714
|
+
if (msg.error) {
|
|
715
|
+
editor.value = "";
|
|
716
|
+
if (status) status.textContent = "No global CLAUDE.md found. Save to create one.";
|
|
717
|
+
} else {
|
|
718
|
+
editor.value = msg.content || "";
|
|
719
|
+
if (status) status.textContent = "";
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
function saveGlobalClaudeMd() {
|
|
724
|
+
var editor = document.getElementById("ss-claudemd-editor");
|
|
725
|
+
var saveStatus = document.getElementById("ss-claudemd-save-status");
|
|
726
|
+
if (!editor) return;
|
|
727
|
+
|
|
728
|
+
var ws = ctx.ws;
|
|
729
|
+
if (ws && ws.readyState === 1) {
|
|
730
|
+
ws.send(JSON.stringify({ type: "write_global_claude_md", content: editor.value }));
|
|
731
|
+
if (saveStatus) saveStatus.textContent = "Saving...";
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
export function handleGlobalClaudeMdWrite(msg) {
|
|
736
|
+
var saveStatus = document.getElementById("ss-claudemd-save-status");
|
|
737
|
+
if (!saveStatus) return;
|
|
738
|
+
if (msg.ok) {
|
|
739
|
+
saveStatus.textContent = "Saved";
|
|
740
|
+
setTimeout(function () { saveStatus.textContent = ""; }, 2000);
|
|
741
|
+
} else {
|
|
742
|
+
saveStatus.textContent = "Error: " + (msg.error || "Failed to save");
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// ===== Shared Environment Variables =====
|
|
747
|
+
var sharedEnvSaveTimer = null;
|
|
748
|
+
|
|
749
|
+
function loadSharedEnv() {
|
|
750
|
+
var saveStatus = document.getElementById("ss-env-save-status");
|
|
751
|
+
if (saveStatus) saveStatus.textContent = "";
|
|
752
|
+
|
|
753
|
+
var ws = ctx.ws;
|
|
754
|
+
if (ws && ws.readyState === 1) {
|
|
755
|
+
ws.send(JSON.stringify({ type: "get_shared_env" }));
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
export function handleSharedEnv(msg) {
|
|
760
|
+
var list = document.getElementById("ss-env-list");
|
|
761
|
+
if (!list) return;
|
|
762
|
+
list.innerHTML = "";
|
|
763
|
+
|
|
764
|
+
var pairs = parseEnvString(msg.envrc || "");
|
|
765
|
+
for (var i = 0; i < pairs.length; i++) {
|
|
766
|
+
addSharedEnvRow(pairs[i].key, pairs[i].value, false);
|
|
767
|
+
}
|
|
768
|
+
refreshIcons();
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
export function handleSharedEnvSaved(msg) {
|
|
772
|
+
var saveStatus = document.getElementById("ss-env-save-status");
|
|
773
|
+
if (!saveStatus) return;
|
|
774
|
+
if (msg.ok) {
|
|
775
|
+
saveStatus.textContent = "Saved";
|
|
776
|
+
setTimeout(function () { saveStatus.textContent = ""; }, 2000);
|
|
777
|
+
} else {
|
|
778
|
+
saveStatus.textContent = "Error: " + (msg.error || "Failed to save");
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function buildSharedEnvString() {
|
|
783
|
+
var list = document.getElementById("ss-env-list");
|
|
784
|
+
if (!list) return "";
|
|
785
|
+
var rows = list.querySelectorAll(".ps-env-row");
|
|
786
|
+
var lines = [];
|
|
787
|
+
for (var i = 0; i < rows.length; i++) {
|
|
788
|
+
var keyInput = rows[i].querySelector(".ps-env-key");
|
|
789
|
+
var valInput = rows[i].querySelector(".ps-env-val");
|
|
790
|
+
var key = keyInput ? keyInput.value.trim() : "";
|
|
791
|
+
var val = valInput ? valInput.value : "";
|
|
792
|
+
if (key) lines.push("export " + key + "=" + val);
|
|
793
|
+
}
|
|
794
|
+
return lines.join("\n");
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function addSharedEnvRow(key, value, focus) {
|
|
798
|
+
var list = document.getElementById("ss-env-list");
|
|
799
|
+
if (!list) return;
|
|
800
|
+
|
|
801
|
+
var row = document.createElement("div");
|
|
802
|
+
row.className = "ps-env-row";
|
|
803
|
+
|
|
804
|
+
var keyInput = document.createElement("input");
|
|
805
|
+
keyInput.type = "text";
|
|
806
|
+
keyInput.className = "ps-env-key";
|
|
807
|
+
keyInput.placeholder = "KEY";
|
|
808
|
+
keyInput.value = key;
|
|
809
|
+
keyInput.spellcheck = false;
|
|
810
|
+
keyInput.autocomplete = "off";
|
|
811
|
+
|
|
812
|
+
var valInput = document.createElement("input");
|
|
813
|
+
valInput.type = "text";
|
|
814
|
+
valInput.className = "ps-env-val";
|
|
815
|
+
valInput.placeholder = "value";
|
|
816
|
+
valInput.value = value;
|
|
817
|
+
valInput.spellcheck = false;
|
|
818
|
+
valInput.autocomplete = "off";
|
|
819
|
+
|
|
820
|
+
var delBtn = document.createElement("button");
|
|
821
|
+
delBtn.className = "ps-env-del";
|
|
822
|
+
delBtn.title = "Remove";
|
|
823
|
+
delBtn.innerHTML = '<i data-lucide="x"></i>';
|
|
824
|
+
|
|
825
|
+
delBtn.addEventListener("click", function () {
|
|
826
|
+
row.remove();
|
|
827
|
+
autoSaveSharedEnv();
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
keyInput.addEventListener("input", function () { autoSaveSharedEnv(); });
|
|
831
|
+
valInput.addEventListener("input", function () { autoSaveSharedEnv(); });
|
|
832
|
+
|
|
833
|
+
// Paste detection
|
|
834
|
+
keyInput.addEventListener("paste", function (e) {
|
|
835
|
+
var text = (e.clipboardData || window.clipboardData).getData("text");
|
|
836
|
+
if (text && looksLikeEnv(text)) {
|
|
837
|
+
e.preventDefault();
|
|
838
|
+
var pairs = parseEnvString(text);
|
|
839
|
+
if (pairs.length > 0) {
|
|
840
|
+
keyInput.value = pairs[0].key;
|
|
841
|
+
valInput.value = pairs[0].value;
|
|
842
|
+
for (var p = 1; p < pairs.length; p++) {
|
|
843
|
+
addSharedEnvRow(pairs[p].key, pairs[p].value, false);
|
|
844
|
+
}
|
|
845
|
+
autoSaveSharedEnv();
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
valInput.addEventListener("paste", function (e) {
|
|
851
|
+
var text = (e.clipboardData || window.clipboardData).getData("text");
|
|
852
|
+
if (text && text.indexOf("\n") !== -1 && text.indexOf("=") !== -1) {
|
|
853
|
+
e.preventDefault();
|
|
854
|
+
var pairs = parseEnvString(text);
|
|
855
|
+
if (pairs.length > 0) {
|
|
856
|
+
keyInput.value = pairs[0].key;
|
|
857
|
+
valInput.value = pairs[0].value;
|
|
858
|
+
for (var p = 1; p < pairs.length; p++) {
|
|
859
|
+
addSharedEnvRow(pairs[p].key, pairs[p].value, false);
|
|
860
|
+
}
|
|
861
|
+
autoSaveSharedEnv();
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
row.appendChild(keyInput);
|
|
867
|
+
row.appendChild(valInput);
|
|
868
|
+
row.appendChild(delBtn);
|
|
869
|
+
list.appendChild(row);
|
|
870
|
+
refreshIcons();
|
|
871
|
+
|
|
872
|
+
if (focus) keyInput.focus();
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
function autoSaveSharedEnv() {
|
|
876
|
+
if (sharedEnvSaveTimer) clearTimeout(sharedEnvSaveTimer);
|
|
877
|
+
sharedEnvSaveTimer = setTimeout(function () {
|
|
878
|
+
var envrc = buildSharedEnvString();
|
|
879
|
+
var ws = ctx.ws;
|
|
880
|
+
if (ws && ws.readyState === 1) {
|
|
881
|
+
ws.send(JSON.stringify({ type: "set_shared_env", envrc: envrc }));
|
|
882
|
+
var saveStatus = document.getElementById("ss-env-save-status");
|
|
883
|
+
if (saveStatus) {
|
|
884
|
+
saveStatus.textContent = "Saved";
|
|
885
|
+
setTimeout(function () { saveStatus.textContent = ""; }, 2000);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}, 800);
|
|
889
|
+
}
|
|
890
|
+
|
|
495
891
|
function formatBytes(n) {
|
|
496
892
|
if (n >= 1073741824) return (n / 1073741824).toFixed(1) + " GB";
|
|
497
893
|
if (n >= 1048576) return (n / 1048576).toFixed(1) + " MB";
|