clay-server 2.6.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +53 -4
- package/lib/config.js +15 -6
- package/lib/daemon.js +47 -5
- package/lib/ipc.js +12 -0
- package/lib/notes.js +2 -2
- package/lib/project.js +883 -2
- package/lib/public/app.js +862 -14
- package/lib/public/css/diff.css +12 -0
- package/lib/public/css/filebrowser.css +1 -1
- package/lib/public/css/loop.css +841 -0
- package/lib/public/css/menus.css +5 -0
- package/lib/public/css/mobile-nav.css +15 -15
- package/lib/public/css/rewind.css +23 -0
- package/lib/public/css/scheduler-modal.css +546 -0
- package/lib/public/css/scheduler.css +944 -0
- package/lib/public/css/sidebar.css +1 -0
- package/lib/public/css/skills.css +59 -0
- package/lib/public/css/sticky-notes.css +486 -0
- package/lib/public/css/title-bar.css +83 -3
- package/lib/public/index.html +181 -3
- package/lib/public/modules/diff.js +3 -3
- package/lib/public/modules/filebrowser.js +169 -45
- package/lib/public/modules/input.js +17 -3
- package/lib/public/modules/markdown.js +10 -0
- package/lib/public/modules/qrcode.js +23 -26
- package/lib/public/modules/scheduler.js +1240 -0
- package/lib/public/modules/server-settings.js +40 -0
- package/lib/public/modules/sidebar.js +12 -0
- package/lib/public/modules/skills.js +84 -0
- package/lib/public/modules/sticky-notes.js +617 -52
- package/lib/public/modules/theme.js +9 -19
- package/lib/public/modules/tools.js +16 -2
- package/lib/public/style.css +3 -0
- package/lib/scheduler.js +362 -0
- package/lib/sdk-bridge.js +36 -0
- package/lib/sessions.js +9 -5
- package/lib/utils.js +49 -3
- package/package.json +1 -1
|
@@ -179,6 +179,19 @@ export function initServerSettings(appCtx) {
|
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
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
|
+
|
|
182
195
|
// Shutdown server
|
|
183
196
|
var shutdownInput = document.getElementById("settings-shutdown-input");
|
|
184
197
|
var shutdownBtn = document.getElementById("settings-shutdown-btn");
|
|
@@ -235,6 +248,7 @@ function openSettings() {
|
|
|
235
248
|
refreshIcons(settingsEl);
|
|
236
249
|
populateSettings();
|
|
237
250
|
requestDaemonConfig();
|
|
251
|
+
resetRestartButton();
|
|
238
252
|
resetShutdownForm();
|
|
239
253
|
|
|
240
254
|
// Start periodic stats refresh
|
|
@@ -242,6 +256,13 @@ function openSettings() {
|
|
|
242
256
|
statsTimer = setInterval(requestStats, 5000);
|
|
243
257
|
}
|
|
244
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
|
+
|
|
245
266
|
function resetShutdownForm() {
|
|
246
267
|
var input = document.getElementById("settings-shutdown-input");
|
|
247
268
|
var btn = document.getElementById("settings-shutdown-btn");
|
|
@@ -580,6 +601,25 @@ export function handleKeepAwakeChanged(msg) {
|
|
|
580
601
|
if (keepAwakeToggle) keepAwakeToggle.checked = !!msg.keepAwake;
|
|
581
602
|
}
|
|
582
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
|
+
|
|
583
623
|
export function handleShutdownResult(msg) {
|
|
584
624
|
var shutdownInput = document.getElementById("settings-shutdown-input");
|
|
585
625
|
var shutdownBtn = document.getElementById("settings-shutdown-btn");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { escapeHtml, copyToClipboard } from './utils.js';
|
|
2
2
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
3
|
import { openProjectSettings } from './project-settings.js';
|
|
4
|
+
import { triggerShare } from './qrcode.js';
|
|
4
5
|
|
|
5
6
|
var ctx;
|
|
6
7
|
|
|
@@ -1225,6 +1226,17 @@ function showProjectCtxMenu(anchorEl, slug, name, icon, position) {
|
|
|
1225
1226
|
});
|
|
1226
1227
|
menu.appendChild(settingsItem);
|
|
1227
1228
|
|
|
1229
|
+
// --- Share ---
|
|
1230
|
+
var shareItem = document.createElement("button");
|
|
1231
|
+
shareItem.className = "project-ctx-item";
|
|
1232
|
+
shareItem.innerHTML = iconHtml("share") + " <span>Share</span>";
|
|
1233
|
+
shareItem.addEventListener("click", function (e) {
|
|
1234
|
+
e.stopPropagation();
|
|
1235
|
+
closeProjectCtxMenu();
|
|
1236
|
+
triggerShare();
|
|
1237
|
+
});
|
|
1238
|
+
menu.appendChild(shareItem);
|
|
1239
|
+
|
|
1228
1240
|
// --- Separator ---
|
|
1229
1241
|
var sep = document.createElement("div");
|
|
1230
1242
|
sep.className = "project-ctx-separator";
|
|
@@ -196,6 +196,12 @@ function loadSkills(tab) {
|
|
|
196
196
|
var searchEl = document.getElementById("skills-search");
|
|
197
197
|
if (searchEl) searchEl.style.display = "";
|
|
198
198
|
|
|
199
|
+
// Installed tab — uses local data, not skills.sh
|
|
200
|
+
if (tab === "installed") {
|
|
201
|
+
loadInstalledSkills();
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
199
205
|
// Check cache
|
|
200
206
|
if (skillsData[tab]) {
|
|
201
207
|
renderList(skillsData[tab], tab);
|
|
@@ -216,6 +222,74 @@ function loadSkills(tab) {
|
|
|
216
222
|
});
|
|
217
223
|
}
|
|
218
224
|
|
|
225
|
+
function loadInstalledSkills() {
|
|
226
|
+
contentEl.innerHTML = '<div class="skills-loading"><div class="skills-spinner"></div> Loading installed skills...</div>';
|
|
227
|
+
|
|
228
|
+
fetch(basePath + "api/installed-skills")
|
|
229
|
+
.then(function (res) { return res.json(); })
|
|
230
|
+
.then(function (data) {
|
|
231
|
+
installedSkills = data.installed || {};
|
|
232
|
+
renderInstalledList(installedSkills);
|
|
233
|
+
})
|
|
234
|
+
.catch(function () {
|
|
235
|
+
contentEl.innerHTML = '<div class="skills-empty">Failed to load installed skills</div>';
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function renderInstalledList(installed) {
|
|
240
|
+
var names = Object.keys(installed);
|
|
241
|
+
if (!names.length) {
|
|
242
|
+
contentEl.innerHTML = '<div class="skills-empty">No skills installed<div class="skills-empty-hint">Browse the other tabs to discover and install skills</div></div>';
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
var html = '<div class="skills-list">';
|
|
247
|
+
|
|
248
|
+
for (var i = 0; i < names.length; i++) {
|
|
249
|
+
var name = names[i];
|
|
250
|
+
var info = installed[name];
|
|
251
|
+
var desc = info.description || "";
|
|
252
|
+
|
|
253
|
+
html += '<div class="skills-installed-item">' +
|
|
254
|
+
'<div class="skills-installed-item-info">' +
|
|
255
|
+
'<div class="skills-installed-item-header">' +
|
|
256
|
+
'<span class="skills-installed-item-name">' + escapeHtml(name) + '</span>' +
|
|
257
|
+
'<span class="skills-installed-badge">' + iconHtml("check") + ' ' + scopeLabel(info.scope) + '</span>' +
|
|
258
|
+
'</div>' +
|
|
259
|
+
(desc ? '<div class="skills-installed-item-desc">' + escapeHtml(desc) + '</div>' : '') +
|
|
260
|
+
'</div>' +
|
|
261
|
+
'<div class="skills-installed-item-actions">' +
|
|
262
|
+
buildUninstallButtons(name, info.scope) +
|
|
263
|
+
'</div>' +
|
|
264
|
+
'</div>';
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
html += '</div>';
|
|
268
|
+
contentEl.innerHTML = html;
|
|
269
|
+
refreshIcons(contentEl);
|
|
270
|
+
|
|
271
|
+
// Attach uninstall handlers
|
|
272
|
+
var unBtns = contentEl.querySelectorAll(".skills-uninstall-btn");
|
|
273
|
+
for (var j = 0; j < unBtns.length; j++) {
|
|
274
|
+
(function (btn) {
|
|
275
|
+
btn.addEventListener("click", function () {
|
|
276
|
+
uninstallSkill(btn.dataset.skill, btn.dataset.scope);
|
|
277
|
+
});
|
|
278
|
+
})(unBtns[j]);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function buildUninstallButtons(skillName, scope) {
|
|
283
|
+
var html = '';
|
|
284
|
+
if (scope === "both") {
|
|
285
|
+
html += '<button class="skills-uninstall-btn" data-skill="' + escapeHtml(skillName) + '" data-scope="project" title="Uninstall (Project)">' + iconHtml("x") + '</button>';
|
|
286
|
+
html += '<button class="skills-uninstall-btn" data-skill="' + escapeHtml(skillName) + '" data-scope="global" title="Uninstall (Global)">' + iconHtml("x") + '</button>';
|
|
287
|
+
} else {
|
|
288
|
+
html += '<button class="skills-uninstall-btn" data-skill="' + escapeHtml(skillName) + '" data-scope="' + escapeHtml(scope) + '" title="Uninstall">' + iconHtml("x") + '</button>';
|
|
289
|
+
}
|
|
290
|
+
return html;
|
|
291
|
+
}
|
|
292
|
+
|
|
219
293
|
function loadSearchResults(q) {
|
|
220
294
|
// Stale check — if query changed since this was scheduled, skip
|
|
221
295
|
if (q !== searchQuery) return;
|
|
@@ -529,6 +603,11 @@ export function handleSkillInstalled(msg) {
|
|
|
529
603
|
updateDetailInstallButtons(skill);
|
|
530
604
|
}
|
|
531
605
|
}
|
|
606
|
+
|
|
607
|
+
// If we're on the installed tab, refresh it
|
|
608
|
+
if (activeTab === "installed" && currentView === "list") {
|
|
609
|
+
loadInstalledSkills();
|
|
610
|
+
}
|
|
532
611
|
} else {
|
|
533
612
|
// Show error toast
|
|
534
613
|
showToast("Failed to install " + skill + (msg.error ? ": " + msg.error : ""), "error");
|
|
@@ -593,6 +672,11 @@ export function handleSkillUninstalled(msg) {
|
|
|
593
672
|
updateDetailInstallButtons(skill);
|
|
594
673
|
}
|
|
595
674
|
}
|
|
675
|
+
|
|
676
|
+
// If we're on the installed tab, refresh it
|
|
677
|
+
if (activeTab === "installed" && currentView === "list") {
|
|
678
|
+
loadInstalledSkills();
|
|
679
|
+
}
|
|
596
680
|
} else {
|
|
597
681
|
showToast("Failed to uninstall " + skill + (msg.error ? ": " + msg.error : ""), "error");
|
|
598
682
|
// Re-enable the uninstall button
|