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.
@@ -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 Server'; }
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
- var projectName = ctx.projectName || "-";
328
- if (nameEl) nameEl.textContent = projectName;
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 ssGetModelDesc(model) {
372
- if (!model) return "";
373
- var lower = model.toLowerCase();
374
- for (var key in SS_MODEL_DESCRIPTIONS) {
375
- if (lower.indexOf(key) !== -1) return SS_MODEL_DESCRIPTIONS[key];
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 ssIsSonnetModel(model) {
381
- if (!model) return false;
382
- return model.toLowerCase().indexOf("sonnet") !== -1;
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
- var listEl = document.getElementById("settings-model-list");
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
- var listEl = document.getElementById("ss-mode-list");
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
- var bar = document.getElementById("ss-effort-bar");
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 updateSsBetaCard(overrideModel) {
501
- var model = overrideModel || ctx.currentModel || ctx._currentModelValue || "";
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 ssToggleBeta1m(enable) {
522
- var betas = ctx.currentBetas || [];
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
- // Show keep awake card only on macOS
603
- var keepAwakeCard = document.getElementById("settings-keep-awake-card");
604
- if (keepAwakeCard) {
605
- if (config.platform === "darwin") {
606
- keepAwakeCard.classList.remove("hidden");
607
- } else {
608
- keepAwakeCard.classList.add("hidden");
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 Server";
524
+ restartBtn.textContent = "Restart";
636
525
  restartBtn.disabled = false;
637
526
  }
638
527
  if (errorEl) {
@@ -0,0 +1,243 @@
1
+ // settings-defaults.js — Shared rendering for model/mode/effort/thinking controls
2
+ // Used by both server-settings.js and project-settings.js
3
+
4
+ export var MODE_OPTIONS = [
5
+ { value: "default", label: "Default", desc: "Claude asks for permission before running tools and editing files." },
6
+ { value: "plan", label: "Plan", desc: "Claude creates a plan first and asks for approval before making changes." },
7
+ { value: "acceptEdits", label: "Auto-accept edits", desc: "File edits are applied automatically. Claude still asks before running commands." },
8
+ ];
9
+
10
+ export var EFFORT_LEVELS = [
11
+ { value: "low", desc: "Quick, concise responses. Best for simple questions." },
12
+ { value: "medium", desc: "Balanced responses with moderate reasoning. Good for most tasks." },
13
+ { value: "high", desc: "Thorough responses with deeper analysis. Good for complex tasks." },
14
+ { value: "max", desc: "Maximum reasoning depth. Best for the most difficult problems." },
15
+ ];
16
+
17
+ export var THINKING_OPTIONS = [
18
+ { value: "disabled", label: "Off", desc: "Disable extended thinking." },
19
+ { value: "adaptive", label: "Adaptive", desc: "Claude decides when to use extended thinking." },
20
+ { value: "budget", label: "Budget", desc: "Set a token budget for extended thinking." },
21
+ ];
22
+
23
+ export var MODEL_DESCRIPTIONS = {
24
+ "default": "Automatically selects the best model for the task.",
25
+ "sonnet": "Fast and capable. Great balance of speed and intelligence.",
26
+ "haiku": "Fastest model. Best for quick tasks and simple questions.",
27
+ "opus": "Most powerful model. Best for complex reasoning and analysis.",
28
+ };
29
+
30
+ export function getModelDesc(model) {
31
+ if (!model) return "";
32
+ var lower = (model.value || model).toLowerCase();
33
+ for (var key in MODEL_DESCRIPTIONS) {
34
+ if (lower.indexOf(key) !== -1) return MODEL_DESCRIPTIONS[key];
35
+ }
36
+ return "";
37
+ }
38
+
39
+ export function isSonnetModel(model) {
40
+ if (!model) return false;
41
+ return model.toLowerCase().indexOf("sonnet") !== -1;
42
+ }
43
+
44
+ // --- Render functions ---
45
+ // Each takes an element ID prefix (e.g. "ss" or "ps"), a send function, and state getters.
46
+
47
+ /**
48
+ * Render model list into `${prefix}-model-list`
49
+ * @param {string} prefix - Element ID prefix
50
+ * @param {object} opts - { models, currentModel, sendMsg, onModelSelect }
51
+ */
52
+ export function renderModelList(prefix, opts) {
53
+ var listEl = document.getElementById(prefix + "-model-list");
54
+ if (!listEl) return;
55
+
56
+ var models = opts.models || [];
57
+ var currentModel = opts.currentModel || "";
58
+
59
+ listEl.innerHTML = "";
60
+ if (models.length === 0) {
61
+ listEl.innerHTML = '<div style="font-size:13px;color:var(--text-dimmer);">No models available</div>';
62
+ return;
63
+ }
64
+
65
+ for (var i = 0; i < models.length; i++) {
66
+ (function (m) {
67
+ var value = m.value || "";
68
+ var label = m.displayName || value;
69
+ var item = document.createElement("div");
70
+ item.className = "settings-model-item" + (value === currentModel ? " active" : "");
71
+ item.dataset.model = value;
72
+
73
+ var nameSpan = document.createElement("span");
74
+ nameSpan.className = "settings-model-name";
75
+ nameSpan.textContent = label;
76
+ item.appendChild(nameSpan);
77
+
78
+ var desc = getModelDesc(value);
79
+ if (desc) {
80
+ var descSpan = document.createElement("span");
81
+ descSpan.className = "settings-model-desc";
82
+ descSpan.textContent = desc;
83
+ item.appendChild(descSpan);
84
+ }
85
+
86
+ item.addEventListener("click", function () {
87
+ opts.sendMsg(opts.modelMsgType, { model: value });
88
+ var items = listEl.querySelectorAll(".settings-model-item");
89
+ for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
90
+ item.classList.add("active");
91
+ if (opts.onModelSelect) opts.onModelSelect(value);
92
+ });
93
+
94
+ listEl.appendChild(item);
95
+ })(models[i]);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Render mode list into `${prefix}-mode-list`
101
+ */
102
+ export function renderModeList(prefix, opts) {
103
+ var listEl = document.getElementById(prefix + "-mode-list");
104
+ if (!listEl) return;
105
+
106
+ var currentMode = opts.currentMode || "default";
107
+ listEl.innerHTML = "";
108
+
109
+ for (var i = 0; i < MODE_OPTIONS.length; i++) {
110
+ (function (opt) {
111
+ var item = document.createElement("div");
112
+ item.className = "settings-model-item" + (opt.value === currentMode ? " active" : "");
113
+
114
+ var nameSpan = document.createElement("span");
115
+ nameSpan.className = "settings-model-name";
116
+ nameSpan.textContent = opt.label;
117
+ item.appendChild(nameSpan);
118
+
119
+ var descSpan = document.createElement("span");
120
+ descSpan.className = "settings-model-desc";
121
+ descSpan.textContent = opt.desc;
122
+ item.appendChild(descSpan);
123
+
124
+ item.addEventListener("click", function () {
125
+ opts.sendMsg(opts.modeMsgType, { mode: opt.value });
126
+ var items = listEl.querySelectorAll(".settings-model-item");
127
+ for (var j = 0; j < items.length; j++) items[j].classList.remove("active");
128
+ item.classList.add("active");
129
+ });
130
+
131
+ listEl.appendChild(item);
132
+ })(MODE_OPTIONS[i]);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Render effort bar into `${prefix}-effort-bar`
138
+ */
139
+ export function renderEffortBar(prefix, opts) {
140
+ var bar = document.getElementById(prefix + "-effort-bar");
141
+ if (!bar) return;
142
+
143
+ var currentEffort = opts.currentEffort || "medium";
144
+ bar.innerHTML = "";
145
+
146
+ for (var i = 0; i < EFFORT_LEVELS.length; i++) {
147
+ (function (lvl) {
148
+ var btn = document.createElement("button");
149
+ btn.className = "settings-btn-option" + (lvl.value === currentEffort ? " active" : "");
150
+ btn.textContent = lvl.value.charAt(0).toUpperCase() + lvl.value.slice(1);
151
+ btn.title = lvl.desc;
152
+ btn.addEventListener("click", function () {
153
+ opts.sendMsg(opts.effortMsgType, { effort: lvl.value });
154
+ var btns = bar.querySelectorAll(".settings-btn-option");
155
+ for (var j = 0; j < btns.length; j++) btns[j].classList.remove("active");
156
+ btn.classList.add("active");
157
+ });
158
+ bar.appendChild(btn);
159
+ })(EFFORT_LEVELS[i]);
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Render thinking bar into `${prefix}-thinking-bar`
165
+ */
166
+ export function renderThinkingBar(prefix, opts) {
167
+ var bar = document.getElementById(prefix + "-thinking-bar");
168
+ if (!bar) return;
169
+
170
+ var currentThinking = opts.currentThinking || "adaptive";
171
+ var currentBudget = opts.currentThinkingBudget || 10000;
172
+ var budgetRow = document.getElementById(prefix + "-thinking-budget-row");
173
+ var budgetInput = document.getElementById(prefix + "-thinking-budget");
174
+ bar.innerHTML = "";
175
+
176
+ for (var i = 0; i < THINKING_OPTIONS.length; i++) {
177
+ (function (opt) {
178
+ var btn = document.createElement("button");
179
+ btn.className = "settings-btn-option" + (opt.value === currentThinking ? " active" : "");
180
+ btn.textContent = opt.label;
181
+ btn.title = opt.desc;
182
+ btn.addEventListener("click", function () {
183
+ var msg = { thinking: opt.value };
184
+ if (opt.value === "budget") {
185
+ msg.budgetTokens = budgetInput ? parseInt(budgetInput.value, 10) || 10000 : 10000;
186
+ }
187
+ opts.sendMsg("set_thinking", msg);
188
+ var btns = bar.querySelectorAll(".settings-btn-option");
189
+ for (var j = 0; j < btns.length; j++) btns[j].classList.remove("active");
190
+ btn.classList.add("active");
191
+ if (budgetRow) budgetRow.style.display = opt.value === "budget" ? "" : "none";
192
+ });
193
+ bar.appendChild(btn);
194
+ })(THINKING_OPTIONS[i]);
195
+ }
196
+
197
+ if (budgetRow) budgetRow.style.display = currentThinking === "budget" ? "" : "none";
198
+ if (budgetInput) {
199
+ budgetInput.value = currentBudget;
200
+ budgetInput.addEventListener("change", function () {
201
+ var val = Math.max(1024, Math.min(128000, parseInt(this.value, 10) || 10000));
202
+ this.value = val;
203
+ opts.sendMsg("set_thinking", { thinking: "budget", budgetTokens: val });
204
+ });
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Update beta card visibility and bind toggle
210
+ */
211
+ export function renderBetaCard(prefix, opts) {
212
+ var model = opts.overrideModel || opts.currentModel || "";
213
+ var card = document.getElementById(prefix + "-beta-card");
214
+ if (card) {
215
+ card.style.display = isSonnetModel(model) ? "" : "none";
216
+ }
217
+
218
+ var toggle = document.getElementById(prefix + "-beta-1m");
219
+ if (toggle) {
220
+ var betas = opts.currentBetas || [];
221
+ var hasBeta = false;
222
+ for (var i = 0; i < betas.length; i++) {
223
+ if (betas[i].indexOf("context-1m") !== -1) { hasBeta = true; break; }
224
+ }
225
+ toggle.checked = hasBeta;
226
+ toggle.onchange = function () {
227
+ var currentBetas = opts.currentBetas || [];
228
+ var newBetas;
229
+ if (this.checked) {
230
+ newBetas = currentBetas.slice();
231
+ newBetas.push("context-1m-2025-08-07");
232
+ } else {
233
+ newBetas = [];
234
+ for (var j = 0; j < currentBetas.length; j++) {
235
+ if (currentBetas[j].indexOf("context-1m") === -1) {
236
+ newBetas.push(currentBetas[j]);
237
+ }
238
+ }
239
+ }
240
+ opts.sendMsg("set_betas", { betas: newBetas });
241
+ };
242
+ }
243
+ }