clay-server 2.19.0 → 2.20.0-beta.2
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/README.md +51 -91
- package/bin/cli.js +49 -14
- package/lib/builtin-mates.js +360 -0
- package/lib/cli-sessions.js +3 -3
- package/lib/config.js +30 -4
- package/lib/daemon.js +28 -5
- package/lib/mates.js +169 -7
- package/lib/notes.js +20 -0
- package/lib/os-users.js +71 -2
- package/lib/project.js +903 -228
- package/lib/public/app.js +249 -69
- package/lib/public/css/icon-strip.css +55 -2
- package/lib/public/css/input.css +50 -30
- package/lib/public/css/mates.css +316 -2
- package/lib/public/css/mention.css +23 -0
- package/lib/public/css/mobile-nav.css +198 -0
- package/lib/public/css/overlays.css +23 -0
- package/lib/public/css/rewind.css +32 -0
- package/lib/public/css/title-bar.css +3 -0
- package/lib/public/css/user-settings.css +2 -2
- package/lib/public/index.html +65 -14
- package/lib/public/mates/ally.png +0 -0
- package/lib/public/mates/sage.jpg +0 -0
- package/lib/public/mates/scout.png +0 -0
- package/lib/public/modules/command-palette.js +44 -4
- package/lib/public/modules/filebrowser.js +2 -0
- package/lib/public/modules/input.js +158 -16
- package/lib/public/modules/mate-knowledge.js +2 -0
- package/lib/public/modules/mate-memory.js +353 -0
- package/lib/public/modules/mention.js +77 -2
- package/lib/public/modules/notifications.js +0 -8
- package/lib/public/modules/server-settings.js +11 -4
- package/lib/public/modules/sidebar.js +507 -21
- package/lib/public/modules/theme.js +10 -12
- package/lib/public/modules/tools.js +84 -12
- package/lib/public/modules/user-settings.js +45 -12
- package/lib/sdk-bridge.js +122 -61
- package/lib/server.js +209 -13
- package/lib/sessions.js +4 -4
- package/lib/users.js +89 -0
- package/package.json +1 -1
package/lib/public/app.js
CHANGED
|
@@ -5,16 +5,17 @@ import { renderMarkdown, highlightCodeBlocks, renderMermaidBlocks, closeMermaidM
|
|
|
5
5
|
import { initSidebar, renderSessionList, handleSearchResults, updateSessionPresence, updatePageTitle, populateCliSessionList, renderIconStrip, renderSidebarPresence, initIconStrip, getEmojiCategories, renderUserStrip, setCurrentDmUser, updateDmBadge, updateSessionBadge, updateProjectBadge, closeDmUserPicker, spawnDustParticles, openMobileSheet, setMobileSheetMateData } from './modules/sidebar.js';
|
|
6
6
|
import { initMateSidebar, showMateSidebar, hideMateSidebar, renderMateSessionList, updateMateSidebarProfile, handleMateSearchResults } from './modules/mate-sidebar.js';
|
|
7
7
|
import { initMateKnowledge, requestKnowledgeList, renderKnowledgeList, handleKnowledgeContent, hideKnowledge } from './modules/mate-knowledge.js';
|
|
8
|
+
import { initMateMemory, renderMemoryList, hideMemory } from './modules/mate-memory.js';
|
|
8
9
|
import { initRewind, setRewindMode, showRewindModal, clearPendingRewindUuid, addRewindButton } from './modules/rewind.js';
|
|
9
10
|
import { initNotifications, showDoneNotification, playDoneSound, isNotifAlertEnabled, isNotifSoundEnabled } from './modules/notifications.js';
|
|
10
|
-
import { initInput, clearPendingImages, handleInputSync, autoResize, builtinCommands, sendMessage, hasSendableContent } from './modules/input.js';
|
|
11
|
+
import { initInput, clearPendingImages, handleInputSync, autoResize, builtinCommands, sendMessage, hasSendableContent, setScheduleBtnDisabled } from './modules/input.js';
|
|
11
12
|
import { initQrCode, triggerShare } from './modules/qrcode.js';
|
|
12
13
|
import { initFileBrowser, loadRootDirectory, refreshTree, handleFsList, handleFsRead, handleDirChanged, refreshIfOpen, handleFileChanged, handleFileHistory, handleGitDiff, handleFileAt, getPendingNavigate, closeFileViewer, resetFileBrowser } from './modules/filebrowser.js';
|
|
13
14
|
import { initTerminal, openTerminal, closeTerminal, resetTerminals, handleTermList, handleTermCreated, handleTermOutput, handleTermExited, handleTermClosed, sendTerminalCommand } from './modules/terminal.js';
|
|
14
15
|
import { initStickyNotes, handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, openArchive, closeArchive, isArchiveOpen, hideNotes, showNotes, isNotesVisible } from './modules/sticky-notes.js';
|
|
15
16
|
import { initTheme, getThemeColor, getComputedVar, onThemeChange, getCurrentTheme } from './modules/theme.js';
|
|
16
17
|
import { initTools, resetToolState, saveToolState, restoreToolState, renderAskUserQuestion, markAskUserAnswered, renderPermissionRequest, markPermissionResolved, markPermissionCancelled, renderElicitationRequest, markElicitationResolved, renderPlanBanner, renderPlanCard, handleTodoWrite, handleTaskCreate, handleTaskUpdate, startThinking, appendThinking, stopThinking, resetThinkingGroup, createToolItem, updateToolExecuting, updateToolResult, markAllToolsDone, addTurnMeta, enableMainInput, getTools, getPlanContent, setPlanContent, isPlanFilePath, getTodoTools, updateSubagentActivity, addSubagentToolEntry, markSubagentDone, updateSubagentProgress, initSubagentStop, closeToolGroup, removeToolFromGroup } from './modules/tools.js';
|
|
17
|
-
import { initServerSettings, updateSettingsStats, updateSettingsModels, updateDaemonConfig, handleSetPinResult, handleKeepAwakeChanged, handleRestartResult, handleShutdownResult, handleSharedEnv, handleSharedEnvSaved, handleGlobalClaudeMdRead, handleGlobalClaudeMdWrite } from './modules/server-settings.js';
|
|
18
|
+
import { initServerSettings, updateSettingsStats, updateSettingsModels, updateDaemonConfig, handleSetPinResult, handleKeepAwakeChanged, handleAutoContinueChanged, handleRestartResult, handleShutdownResult, handleSharedEnv, handleSharedEnvSaved, handleGlobalClaudeMdRead, handleGlobalClaudeMdWrite } from './modules/server-settings.js';
|
|
18
19
|
import { initProjectSettings, handleInstructionsRead, handleInstructionsWrite, handleProjectEnv, handleProjectEnvSaved, isProjectSettingsOpen, handleProjectSharedEnv, handleProjectSharedEnvSaved, handleProjectOwnerChanged } from './modules/project-settings.js';
|
|
19
20
|
import { initSkills, handleSkillInstalled, handleSkillUninstalled } from './modules/skills.js';
|
|
20
21
|
import { initScheduler, resetScheduler, handleLoopRegistryUpdated, handleScheduleRunStarted, handleScheduleRunFinished, handleLoopScheduled, openSchedulerToTab, isSchedulerOpen, closeScheduler, enterCraftingMode, exitCraftingMode, handleLoopRegistryFiles, getUpcomingSchedules } from './modules/scheduler.js';
|
|
@@ -74,6 +75,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
74
75
|
var cachedDmConversations = [];
|
|
75
76
|
var dmRemovedUsers = {}; // { userId: true } - users explicitly removed from favorites
|
|
76
77
|
var cachedMatesList = []; // Cached list of mates for user strip
|
|
78
|
+
var cachedAvailableBuiltins = []; // Deleted built-in mates available for re-add
|
|
77
79
|
|
|
78
80
|
// --- Mate WS (separate connection to mate project) ---
|
|
79
81
|
var mateWs = null;
|
|
@@ -762,14 +764,16 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
762
764
|
if (resizeHandle) resizeHandle.classList.remove("dm-mode");
|
|
763
765
|
hideMateSidebar();
|
|
764
766
|
hideKnowledge();
|
|
767
|
+
hideMemory();
|
|
765
768
|
if (isSchedulerOpen()) closeScheduler();
|
|
766
769
|
disconnectMateWs();
|
|
767
770
|
// Restore terminal button
|
|
768
771
|
var termBtn = document.getElementById("terminal-toggle-btn");
|
|
769
772
|
if (termBtn) termBtn.style.display = "";
|
|
770
|
-
// Re-request session list from main project to refresh state
|
|
773
|
+
// Re-request session list and notes from main project to refresh state
|
|
771
774
|
if (ws && ws.readyState === 1) {
|
|
772
775
|
ws.send(JSON.stringify({ type: "switch_session", id: activeSessionId }));
|
|
776
|
+
ws.send(JSON.stringify({ type: "note_list_request" }));
|
|
773
777
|
}
|
|
774
778
|
|
|
775
779
|
// Reset DM header
|
|
@@ -832,15 +836,74 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
832
836
|
}
|
|
833
837
|
})();
|
|
834
838
|
|
|
835
|
-
function handleMateCreatedInApp(mate) {
|
|
839
|
+
function handleMateCreatedInApp(mate, msg) {
|
|
836
840
|
if (!mate) return;
|
|
837
841
|
cachedMatesList.push(mate);
|
|
842
|
+
if (msg && msg.availableBuiltins) cachedAvailableBuiltins = msg.availableBuiltins;
|
|
843
|
+
if (msg && msg.dmFavorites) cachedDmFavorites = msg.dmFavorites;
|
|
838
844
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
839
|
-
//
|
|
840
|
-
|
|
845
|
+
// Built-in mates handle their own onboarding via CLAUDE.md, skip auto-interview
|
|
846
|
+
if (!mate.builtinKey) {
|
|
847
|
+
pendingMateInterview = mate;
|
|
848
|
+
}
|
|
841
849
|
openDm(mate.id);
|
|
842
850
|
}
|
|
843
851
|
|
|
852
|
+
function renderAvailableBuiltins(builtins) {
|
|
853
|
+
// Append deleted built-in mates to the mates list in the picker
|
|
854
|
+
var matesList = document.querySelector(".dm-mates-list");
|
|
855
|
+
if (!matesList) return;
|
|
856
|
+
if (!builtins || builtins.length === 0) return;
|
|
857
|
+
|
|
858
|
+
for (var i = 0; i < builtins.length; i++) {
|
|
859
|
+
(function (b) {
|
|
860
|
+
var item = document.createElement("div");
|
|
861
|
+
item.className = "dm-user-picker-item dm-user-picker-builtin-item";
|
|
862
|
+
item.style.opacity = "0.5";
|
|
863
|
+
|
|
864
|
+
var av = document.createElement("img");
|
|
865
|
+
av.className = "dm-user-picker-avatar";
|
|
866
|
+
av.src = b.avatarCustom || "";
|
|
867
|
+
av.alt = b.displayName;
|
|
868
|
+
item.appendChild(av);
|
|
869
|
+
|
|
870
|
+
var nameWrap = document.createElement("div");
|
|
871
|
+
nameWrap.style.cssText = "flex:1;min-width:0;";
|
|
872
|
+
var nameEl = document.createElement("span");
|
|
873
|
+
nameEl.className = "dm-user-picker-name";
|
|
874
|
+
nameEl.textContent = b.displayName;
|
|
875
|
+
nameWrap.appendChild(nameEl);
|
|
876
|
+
var bioEl = document.createElement("div");
|
|
877
|
+
bioEl.style.cssText = "font-size:11px;color:var(--text-dimmer);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;";
|
|
878
|
+
bioEl.textContent = "Deleted";
|
|
879
|
+
nameWrap.appendChild(bioEl);
|
|
880
|
+
item.appendChild(nameWrap);
|
|
881
|
+
|
|
882
|
+
var addBtn = document.createElement("button");
|
|
883
|
+
addBtn.style.cssText = "border:none;background:none;cursor:pointer;padding:2px 6px;color:var(--accent, #6366f1);font-size:12px;font-weight:600;";
|
|
884
|
+
addBtn.textContent = "+ Add";
|
|
885
|
+
addBtn.title = "Re-add " + b.displayName;
|
|
886
|
+
addBtn.addEventListener("click", function (e) {
|
|
887
|
+
e.stopPropagation();
|
|
888
|
+
if (ws && ws.readyState === 1) {
|
|
889
|
+
ws.send(JSON.stringify({ type: "mate_readd_builtin", builtinKey: b.key }));
|
|
890
|
+
}
|
|
891
|
+
closeDmUserPicker();
|
|
892
|
+
});
|
|
893
|
+
item.appendChild(addBtn);
|
|
894
|
+
|
|
895
|
+
item.addEventListener("click", function () {
|
|
896
|
+
if (ws && ws.readyState === 1) {
|
|
897
|
+
ws.send(JSON.stringify({ type: "mate_readd_builtin", builtinKey: b.key }));
|
|
898
|
+
}
|
|
899
|
+
closeDmUserPicker();
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
matesList.appendChild(item);
|
|
903
|
+
})(builtins[i]);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
844
907
|
var pendingMateInterview = null;
|
|
845
908
|
|
|
846
909
|
function buildMateInterviewPrompt(mate) {
|
|
@@ -923,6 +986,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
923
986
|
// Intercept session_list for mate sidebar
|
|
924
987
|
if (msg.type === "init" && msg.sessions) {
|
|
925
988
|
renderMateSessionList(msg.sessions);
|
|
989
|
+
handlePaletteSessionSwitch();
|
|
926
990
|
// Override title bar with mate name (not session/project title)
|
|
927
991
|
if (dmTargetUser && dmTargetUser.isMate) {
|
|
928
992
|
var mateDN = dmTargetUser.displayName || "New Mate";
|
|
@@ -952,6 +1016,13 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
952
1016
|
if (msg.type === "knowledge_saved" || msg.type === "knowledge_deleted" || msg.type === "knowledge_promoted" || msg.type === "knowledge_depromoted") {
|
|
953
1017
|
return; // list update follows separately
|
|
954
1018
|
}
|
|
1019
|
+
if (msg.type === "memory_list") {
|
|
1020
|
+
renderMemoryList(msg.entries, msg.summary);
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
if (msg.type === "memory_deleted") {
|
|
1024
|
+
return; // list update follows separately
|
|
1025
|
+
}
|
|
955
1026
|
// On done: scan DOM for [[MATE_READY: name]], update name, strip marker
|
|
956
1027
|
if (msg.type === "done" && dmTargetUser && dmTargetUser.isMate) {
|
|
957
1028
|
// Ensure last message is fully visible after rendering settles
|
|
@@ -1874,11 +1945,13 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
1874
1945
|
getHistoryFrom: function () { return historyFrom; },
|
|
1875
1946
|
get permissions() { return myPermissions; },
|
|
1876
1947
|
get projectList() { return cachedProjects || []; },
|
|
1948
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
1877
1949
|
};
|
|
1878
1950
|
initSidebar(sidebarCtx);
|
|
1879
1951
|
initIconStrip(sidebarCtx);
|
|
1880
1952
|
initMateSidebar(function () { return mateWs; });
|
|
1881
1953
|
initMateKnowledge(function () { return mateWs; });
|
|
1954
|
+
initMateMemory(function () { return mateWs; }, { onShow: function () { hideKnowledge(); hideNotes(); } });
|
|
1882
1955
|
initMateWizard(
|
|
1883
1956
|
function (msg) { if (ws && ws.readyState === 1) ws.send(JSON.stringify(msg)); },
|
|
1884
1957
|
function (mate) { handleMateCreatedInApp(mate); }
|
|
@@ -1886,9 +1959,10 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
1886
1959
|
|
|
1887
1960
|
initCommandPalette({
|
|
1888
1961
|
switchProject: function (slug) { switchProject(slug); },
|
|
1889
|
-
currentSlug: function () { return currentSlug; },
|
|
1962
|
+
currentSlug: function () { return mateProjectSlug || currentSlug; },
|
|
1890
1963
|
projectList: function () { return cachedProjects || []; },
|
|
1891
1964
|
matesList: function () { return cachedMatesList || []; },
|
|
1965
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
1892
1966
|
allUsers: function () { return cachedAllUsers || []; },
|
|
1893
1967
|
dmConversations: function () { return cachedDmConversations || []; },
|
|
1894
1968
|
myUserId: function () { return myUserId; },
|
|
@@ -2178,10 +2252,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
2178
2252
|
removeMatePreThinking();
|
|
2179
2253
|
var mateName = dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate";
|
|
2180
2254
|
var mateAvatar = document.body.dataset.mateAvatarUrl || "";
|
|
2181
|
-
|
|
2182
|
-
matePreThinkingTimer = null;
|
|
2183
|
-
doShowMatePreThinking(mateName, mateAvatar);
|
|
2184
|
-
}, 1000);
|
|
2255
|
+
doShowMatePreThinking(mateName, mateAvatar);
|
|
2185
2256
|
}
|
|
2186
2257
|
function doShowMatePreThinking(mateName, mateAvatar) {
|
|
2187
2258
|
matePreThinkingEl = document.createElement("div");
|
|
@@ -2189,9 +2260,10 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
2189
2260
|
matePreThinkingEl.innerHTML =
|
|
2190
2261
|
'<img class="dm-bubble-avatar dm-bubble-avatar-mate" src="' + escapeHtml(mateAvatar) + '" alt="" style="display:block">' +
|
|
2191
2262
|
'<div class="dm-bubble-content">' +
|
|
2192
|
-
'<div class="
|
|
2193
|
-
'<
|
|
2194
|
-
'<span class="
|
|
2263
|
+
'<div class="dm-bubble-header"><span class="dm-bubble-name">' + escapeHtml(mateName) + '</span></div>' +
|
|
2264
|
+
'<div class="activity-inline mate-pre-activity">' +
|
|
2265
|
+
'<span class="activity-icon">' + iconHtml("sparkles") + '</span>' +
|
|
2266
|
+
'<span class="activity-text">' + randomThinkingVerb() + '...</span>' +
|
|
2195
2267
|
'</div>' +
|
|
2196
2268
|
'</div>';
|
|
2197
2269
|
if (activityEl && activityEl.parentNode) {
|
|
@@ -2199,6 +2271,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
2199
2271
|
} else {
|
|
2200
2272
|
addToMessages(matePreThinkingEl);
|
|
2201
2273
|
}
|
|
2274
|
+
refreshIcons();
|
|
2202
2275
|
scrollToBottom();
|
|
2203
2276
|
}
|
|
2204
2277
|
function removeMatePreThinking() {
|
|
@@ -2841,6 +2914,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
2841
2914
|
function addToMessages(el) {
|
|
2842
2915
|
if (prependAnchor) messagesEl.insertBefore(el, prependAnchor);
|
|
2843
2916
|
else messagesEl.appendChild(el);
|
|
2917
|
+
if (scheduledMsgEl && el !== scheduledMsgEl && scheduledMsgEl.parentNode === messagesEl) {
|
|
2918
|
+
messagesEl.appendChild(scheduledMsgEl);
|
|
2919
|
+
}
|
|
2844
2920
|
}
|
|
2845
2921
|
|
|
2846
2922
|
var newMsgBtn = $("new-msg-btn");
|
|
@@ -3479,6 +3555,98 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3479
3555
|
}
|
|
3480
3556
|
}
|
|
3481
3557
|
|
|
3558
|
+
// --- Rate Limit Usage (top bar link to check usage + reset time) ---
|
|
3559
|
+
|
|
3560
|
+
var rateLimitUsageEl = null;
|
|
3561
|
+
var rateLimitResetState = {};
|
|
3562
|
+
var rateLimitTickTimer = null;
|
|
3563
|
+
|
|
3564
|
+
function formatResetTime(resetsAt) {
|
|
3565
|
+
if (!resetsAt) return "";
|
|
3566
|
+
var d = new Date(resetsAt);
|
|
3567
|
+
var now = new Date();
|
|
3568
|
+
var diff = resetsAt - now.getTime();
|
|
3569
|
+
if (diff <= 0) return "";
|
|
3570
|
+
var hrs = Math.floor(diff / 3600000);
|
|
3571
|
+
var mins = Math.floor((diff % 3600000) / 60000);
|
|
3572
|
+
if (hrs > 0) return hrs + "h " + mins + "m";
|
|
3573
|
+
return mins + "m";
|
|
3574
|
+
}
|
|
3575
|
+
|
|
3576
|
+
function rateLimitTypeShortLabel(type) {
|
|
3577
|
+
if (type === "five_hour") return "5h";
|
|
3578
|
+
if (type === "seven_day") return "7d";
|
|
3579
|
+
if (type === "seven_day_opus") return "7d opus";
|
|
3580
|
+
if (type === "seven_day_sonnet") return "7d sonnet";
|
|
3581
|
+
return type || "";
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
function updateRateLimitUsage(msg) {
|
|
3585
|
+
if (msg.rateLimitType && msg.resetsAt) {
|
|
3586
|
+
rateLimitResetState[msg.rateLimitType] = { resetsAt: msg.resetsAt, status: msg.status };
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
var topBarActions = document.querySelector("#top-bar .top-bar-actions");
|
|
3590
|
+
if (!topBarActions) return;
|
|
3591
|
+
|
|
3592
|
+
if (!rateLimitUsageEl) {
|
|
3593
|
+
rateLimitUsageEl = document.createElement("a");
|
|
3594
|
+
rateLimitUsageEl.id = "rate-limit-usage-link";
|
|
3595
|
+
rateLimitUsageEl.className = "top-bar-pill pill-dim usage-check-link";
|
|
3596
|
+
rateLimitUsageEl.href = "https://claude.ai/settings/usage";
|
|
3597
|
+
rateLimitUsageEl.target = "_blank";
|
|
3598
|
+
rateLimitUsageEl.rel = "noopener";
|
|
3599
|
+
rateLimitUsageEl.title = "Check usage on claude.ai";
|
|
3600
|
+
var ref = document.getElementById("skip-perms-pill");
|
|
3601
|
+
topBarActions.insertBefore(rateLimitUsageEl, ref);
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3604
|
+
// Build label from available reset times
|
|
3605
|
+
var parts = [];
|
|
3606
|
+
var types = ["five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet"];
|
|
3607
|
+
for (var i = 0; i < types.length; i++) {
|
|
3608
|
+
var entry = rateLimitResetState[types[i]];
|
|
3609
|
+
if (!entry || !entry.resetsAt) continue;
|
|
3610
|
+
var timeStr = formatResetTime(entry.resetsAt);
|
|
3611
|
+
if (!timeStr) continue;
|
|
3612
|
+
parts.push(rateLimitTypeShortLabel(types[i]) + " resets " + timeStr);
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
var label = parts.length > 0 ? parts.join(" · ") : "Check usage";
|
|
3616
|
+
rateLimitUsageEl.innerHTML = iconHtml("activity") + '<span>' + label + '</span>' + iconHtml("external-link");
|
|
3617
|
+
refreshIcons();
|
|
3618
|
+
|
|
3619
|
+
// Start or stop live countdown tick
|
|
3620
|
+
if (parts.length > 0 && !rateLimitTickTimer) {
|
|
3621
|
+
rateLimitTickTimer = setInterval(tickRateLimitUsage, 30000);
|
|
3622
|
+
} else if (parts.length === 0 && rateLimitTickTimer) {
|
|
3623
|
+
clearInterval(rateLimitTickTimer);
|
|
3624
|
+
rateLimitTickTimer = null;
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
function tickRateLimitUsage() {
|
|
3629
|
+
if (!rateLimitUsageEl) return;
|
|
3630
|
+
var parts = [];
|
|
3631
|
+
var types = ["five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet"];
|
|
3632
|
+
for (var i = 0; i < types.length; i++) {
|
|
3633
|
+
var entry = rateLimitResetState[types[i]];
|
|
3634
|
+
if (!entry || !entry.resetsAt) continue;
|
|
3635
|
+
var timeStr = formatResetTime(entry.resetsAt);
|
|
3636
|
+
if (!timeStr) { delete rateLimitResetState[types[i]]; continue; }
|
|
3637
|
+
parts.push(rateLimitTypeShortLabel(types[i]) + " resets " + timeStr);
|
|
3638
|
+
}
|
|
3639
|
+
if (parts.length === 0) {
|
|
3640
|
+
rateLimitUsageEl.innerHTML = iconHtml("activity") + '<span>Check usage</span>' + iconHtml("external-link");
|
|
3641
|
+
refreshIcons();
|
|
3642
|
+
if (rateLimitTickTimer) { clearInterval(rateLimitTickTimer); rateLimitTickTimer = null; }
|
|
3643
|
+
return;
|
|
3644
|
+
}
|
|
3645
|
+
var label = parts.join(" · ");
|
|
3646
|
+
rateLimitUsageEl.innerHTML = iconHtml("activity") + '<span>' + label + '</span>' + iconHtml("external-link");
|
|
3647
|
+
refreshIcons();
|
|
3648
|
+
}
|
|
3649
|
+
|
|
3482
3650
|
function handleRateLimitEvent(msg) {
|
|
3483
3651
|
var isRejected = msg.status === "rejected";
|
|
3484
3652
|
var typeLabel = rateLimitTypeLabel(msg.rateLimitType);
|
|
@@ -3493,13 +3661,12 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3493
3661
|
popoverText = typeLabel + " limit exceeded";
|
|
3494
3662
|
updateRateLimitIndicator(msg);
|
|
3495
3663
|
startRateLimitCountdown(null, msg.resetsAt, null);
|
|
3496
|
-
// Track
|
|
3664
|
+
// Track rate limit reset time
|
|
3497
3665
|
rateLimitResetsAt = msg.resetsAt;
|
|
3498
3666
|
if (rateLimitResetTimer) clearTimeout(rateLimitResetTimer);
|
|
3499
3667
|
rateLimitResetTimer = setTimeout(function () {
|
|
3500
3668
|
rateLimitResetsAt = null;
|
|
3501
3669
|
rateLimitResetTimer = null;
|
|
3502
|
-
exitScheduleMode();
|
|
3503
3670
|
}, msg.resetsAt - Date.now() + 1000);
|
|
3504
3671
|
} else {
|
|
3505
3672
|
var pct = msg.utilization ? Math.round(msg.utilization * 100) : null;
|
|
@@ -3510,32 +3677,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3510
3677
|
showRateLimitPopover(popoverText, isRejected);
|
|
3511
3678
|
}
|
|
3512
3679
|
|
|
3513
|
-
// --- Schedule mode (rate limit) ---
|
|
3514
|
-
|
|
3515
|
-
var scheduleModeActive = false;
|
|
3516
|
-
|
|
3517
|
-
function enterScheduleMode() {
|
|
3518
|
-
if (scheduleModeActive) return;
|
|
3519
|
-
scheduleModeActive = true;
|
|
3520
|
-
var inputRow = document.getElementById("input-row");
|
|
3521
|
-
if (inputRow) inputRow.classList.add("input-rate-limited");
|
|
3522
|
-
if (inputEl) {
|
|
3523
|
-
inputEl.dataset.originalPlaceholder = inputEl.placeholder;
|
|
3524
|
-
inputEl.placeholder = "Schedule message after limit resets...";
|
|
3525
|
-
}
|
|
3526
|
-
}
|
|
3527
|
-
|
|
3528
|
-
function exitScheduleMode() {
|
|
3529
|
-
if (!scheduleModeActive) return;
|
|
3530
|
-
scheduleModeActive = false;
|
|
3531
|
-
var inputRow = document.getElementById("input-row");
|
|
3532
|
-
if (inputRow) inputRow.classList.remove("input-rate-limited");
|
|
3533
|
-
if (inputEl && inputEl.dataset.originalPlaceholder) {
|
|
3534
|
-
inputEl.placeholder = inputEl.dataset.originalPlaceholder;
|
|
3535
|
-
delete inputEl.dataset.originalPlaceholder;
|
|
3536
|
-
}
|
|
3537
|
-
}
|
|
3538
|
-
|
|
3539
3680
|
// --- Scheduled message in chat history ---
|
|
3540
3681
|
|
|
3541
3682
|
var scheduledMsgEl = null;
|
|
@@ -3544,15 +3685,15 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3544
3685
|
function addScheduledMessageBubble(text, resetsAt) {
|
|
3545
3686
|
removeScheduledMessageBubble();
|
|
3546
3687
|
var wrap = document.createElement("div");
|
|
3547
|
-
wrap.className = "scheduled-msg-wrap";
|
|
3688
|
+
wrap.className = "msg-user scheduled-msg-wrap";
|
|
3548
3689
|
wrap.id = "scheduled-msg-bubble";
|
|
3549
3690
|
|
|
3550
3691
|
var bubble = document.createElement("div");
|
|
3551
|
-
bubble.className = "scheduled-msg-bubble";
|
|
3692
|
+
bubble.className = "bubble scheduled-msg-bubble";
|
|
3552
3693
|
|
|
3553
|
-
var textEl = document.createElement("
|
|
3554
|
-
textEl.className = "scheduled-msg-text";
|
|
3694
|
+
var textEl = document.createElement("span");
|
|
3555
3695
|
textEl.textContent = text;
|
|
3696
|
+
bubble.appendChild(textEl);
|
|
3556
3697
|
|
|
3557
3698
|
var metaEl = document.createElement("div");
|
|
3558
3699
|
metaEl.className = "scheduled-msg-meta";
|
|
@@ -3569,7 +3710,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3569
3710
|
var cancelBtn = document.createElement("button");
|
|
3570
3711
|
cancelBtn.className = "scheduled-msg-cancel";
|
|
3571
3712
|
cancelBtn.title = "Cancel scheduled message";
|
|
3572
|
-
cancelBtn.
|
|
3713
|
+
cancelBtn.textContent = "\u00d7";
|
|
3573
3714
|
cancelBtn.addEventListener("click", function () {
|
|
3574
3715
|
if (ws && ws.readyState === 1) {
|
|
3575
3716
|
ws.send(JSON.stringify({ type: "cancel_scheduled_message" }));
|
|
@@ -3577,10 +3718,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3577
3718
|
});
|
|
3578
3719
|
metaEl.appendChild(cancelBtn);
|
|
3579
3720
|
|
|
3580
|
-
bubble.appendChild(textEl);
|
|
3581
|
-
bubble.appendChild(metaEl);
|
|
3582
3721
|
wrap.appendChild(bubble);
|
|
3583
|
-
|
|
3722
|
+
wrap.appendChild(metaEl);
|
|
3723
|
+
addToMessages(wrap);
|
|
3584
3724
|
scheduledMsgEl = wrap;
|
|
3585
3725
|
scrollToBottom();
|
|
3586
3726
|
|
|
@@ -3606,8 +3746,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3606
3746
|
}
|
|
3607
3747
|
updateCountdown();
|
|
3608
3748
|
scheduledCountdownTimer = setInterval(updateCountdown, 1000);
|
|
3609
|
-
|
|
3610
|
-
refreshIcons(wrap);
|
|
3611
3749
|
}
|
|
3612
3750
|
|
|
3613
3751
|
function removeScheduledMessageBubble() {
|
|
@@ -3621,6 +3759,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3621
3759
|
}
|
|
3622
3760
|
}
|
|
3623
3761
|
|
|
3762
|
+
|
|
3624
3763
|
// --- Fast Mode State ---
|
|
3625
3764
|
|
|
3626
3765
|
var fastModeIndicatorEl = null;
|
|
@@ -3745,6 +3884,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3745
3884
|
}
|
|
3746
3885
|
resetFileBrowser();
|
|
3747
3886
|
closeArchive();
|
|
3887
|
+
hideMemory();
|
|
3748
3888
|
if (isSchedulerOpen()) closeScheduler();
|
|
3749
3889
|
resetScheduler(slug);
|
|
3750
3890
|
currentSlug = slug;
|
|
@@ -3854,6 +3994,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3854
3994
|
if (savedMainWs === this) return;
|
|
3855
3995
|
|
|
3856
3996
|
if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
|
|
3997
|
+
closeDmUserPicker();
|
|
3857
3998
|
setStatus("disconnected");
|
|
3858
3999
|
processing = false;
|
|
3859
4000
|
setActivity(null);
|
|
@@ -4016,6 +4157,8 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4016
4157
|
updatePageTitle();
|
|
4017
4158
|
if (msg.version) {
|
|
4018
4159
|
setPaletteVersion(msg.version);
|
|
4160
|
+
var serverVersionEl = document.getElementById("settings-server-version");
|
|
4161
|
+
if (serverVersionEl) serverVersionEl.textContent = msg.version;
|
|
4019
4162
|
}
|
|
4020
4163
|
if (msg.projectOwnerId !== undefined) currentProjectOwnerId = msg.projectOwnerId;
|
|
4021
4164
|
if (msg.osUsers !== undefined) isOsUsers = !!msg.osUsers;
|
|
@@ -4062,6 +4205,29 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4062
4205
|
}
|
|
4063
4206
|
break;
|
|
4064
4207
|
|
|
4208
|
+
case "up_to_date":
|
|
4209
|
+
var utdBtn = $("settings-update-check");
|
|
4210
|
+
if (utdBtn) {
|
|
4211
|
+
utdBtn.innerHTML = "";
|
|
4212
|
+
var utdIcon = document.createElement("i");
|
|
4213
|
+
utdIcon.setAttribute("data-lucide", "check");
|
|
4214
|
+
utdBtn.appendChild(utdIcon);
|
|
4215
|
+
utdBtn.appendChild(document.createTextNode(" Up to date (v" + msg.version + ")"));
|
|
4216
|
+
utdBtn.disabled = true;
|
|
4217
|
+
refreshIcons();
|
|
4218
|
+
setTimeout(function () {
|
|
4219
|
+
utdBtn.innerHTML = "";
|
|
4220
|
+
var rwIcon = document.createElement("i");
|
|
4221
|
+
rwIcon.setAttribute("data-lucide", "refresh-cw");
|
|
4222
|
+
utdBtn.appendChild(rwIcon);
|
|
4223
|
+
utdBtn.appendChild(document.createTextNode(" Check for updates"));
|
|
4224
|
+
utdBtn.disabled = false;
|
|
4225
|
+
utdBtn.classList.remove("settings-btn-update-available");
|
|
4226
|
+
refreshIcons();
|
|
4227
|
+
}, 3000);
|
|
4228
|
+
}
|
|
4229
|
+
break;
|
|
4230
|
+
|
|
4065
4231
|
case "update_started":
|
|
4066
4232
|
var updNowBtn = $("update-now");
|
|
4067
4233
|
if (updNowBtn) {
|
|
@@ -4285,14 +4451,16 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4285
4451
|
case "status":
|
|
4286
4452
|
if (msg.status === "processing") {
|
|
4287
4453
|
setStatus("processing");
|
|
4288
|
-
|
|
4454
|
+
if (!(dmMode && dmTargetUser && dmTargetUser.isMate)) {
|
|
4455
|
+
setActivity(randomThinkingVerb() + "...");
|
|
4456
|
+
}
|
|
4289
4457
|
}
|
|
4290
4458
|
break;
|
|
4291
4459
|
|
|
4292
4460
|
case "compacting":
|
|
4293
4461
|
if (msg.active) {
|
|
4294
4462
|
setActivity("Compacting conversation...");
|
|
4295
|
-
} else {
|
|
4463
|
+
} else if (!(dmMode && dmTargetUser && dmTargetUser.isMate)) {
|
|
4296
4464
|
setActivity(randomThinkingVerb() + "...");
|
|
4297
4465
|
}
|
|
4298
4466
|
break;
|
|
@@ -4308,7 +4476,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4308
4476
|
|
|
4309
4477
|
case "thinking_stop":
|
|
4310
4478
|
stopThinking(msg.duration);
|
|
4311
|
-
|
|
4479
|
+
if (!(dmMode && dmTargetUser && dmTargetUser.isMate)) {
|
|
4480
|
+
setActivity(randomThinkingVerb() + "...");
|
|
4481
|
+
}
|
|
4312
4482
|
break;
|
|
4313
4483
|
|
|
4314
4484
|
case "delta":
|
|
@@ -4393,7 +4563,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4393
4563
|
break;
|
|
4394
4564
|
|
|
4395
4565
|
case "ask_user_answered":
|
|
4396
|
-
markAskUserAnswered(msg.toolId);
|
|
4566
|
+
markAskUserAnswered(msg.toolId, msg.answers);
|
|
4397
4567
|
stopUrgentBlink();
|
|
4398
4568
|
break;
|
|
4399
4569
|
|
|
@@ -4488,10 +4658,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4488
4658
|
if (isNotifAlertEnabled() && !window._pushSubscription) showDoneNotification();
|
|
4489
4659
|
if (isNotifSoundEnabled()) playDoneSound();
|
|
4490
4660
|
}
|
|
4491
|
-
// Enter schedule mode if rate limited
|
|
4492
|
-
if (rateLimitResetsAt && rateLimitResetsAt > Date.now() && msg.code === 1) {
|
|
4493
|
-
enterScheduleMode();
|
|
4494
|
-
}
|
|
4495
4661
|
break;
|
|
4496
4662
|
|
|
4497
4663
|
case "stderr":
|
|
@@ -4522,23 +4688,25 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4522
4688
|
handleRateLimitEvent(msg);
|
|
4523
4689
|
break;
|
|
4524
4690
|
|
|
4691
|
+
case "rate_limit_usage":
|
|
4692
|
+
updateRateLimitUsage(msg);
|
|
4693
|
+
break;
|
|
4694
|
+
|
|
4525
4695
|
case "scheduled_message_queued":
|
|
4526
4696
|
addScheduledMessageBubble(msg.text, msg.resetsAt);
|
|
4527
|
-
|
|
4697
|
+
setScheduleBtnDisabled(true);
|
|
4528
4698
|
break;
|
|
4529
4699
|
|
|
4530
4700
|
case "scheduled_message_sent":
|
|
4531
4701
|
removeScheduledMessageBubble();
|
|
4702
|
+
setScheduleBtnDisabled(false);
|
|
4532
4703
|
processing = true;
|
|
4533
4704
|
setStatus("processing");
|
|
4534
4705
|
break;
|
|
4535
4706
|
|
|
4536
4707
|
case "scheduled_message_cancelled":
|
|
4537
4708
|
removeScheduledMessageBubble();
|
|
4538
|
-
|
|
4539
|
-
if (rateLimitResetsAt && rateLimitResetsAt > Date.now()) {
|
|
4540
|
-
enterScheduleMode();
|
|
4541
|
-
}
|
|
4709
|
+
setScheduleBtnDisabled(false);
|
|
4542
4710
|
break;
|
|
4543
4711
|
|
|
4544
4712
|
case "auto_continue_scheduled":
|
|
@@ -4809,11 +4977,12 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4809
4977
|
break;
|
|
4810
4978
|
|
|
4811
4979
|
case "mate_created":
|
|
4812
|
-
handleMateCreatedInApp(msg.mate);
|
|
4980
|
+
handleMateCreatedInApp(msg.mate, msg);
|
|
4813
4981
|
break;
|
|
4814
4982
|
|
|
4815
4983
|
case "mate_deleted":
|
|
4816
4984
|
cachedMatesList = cachedMatesList.filter(function (m) { return m.id !== msg.mateId; });
|
|
4985
|
+
if (msg.availableBuiltins) cachedAvailableBuiltins = msg.availableBuiltins;
|
|
4817
4986
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
4818
4987
|
// Clean up background WS for deleted mate
|
|
4819
4988
|
var delSlug = "mate-" + msg.mateId;
|
|
@@ -4856,9 +5025,14 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4856
5025
|
|
|
4857
5026
|
case "mate_list":
|
|
4858
5027
|
cachedMatesList = msg.mates || [];
|
|
5028
|
+
cachedAvailableBuiltins = msg.availableBuiltins || [];
|
|
4859
5029
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
4860
5030
|
break;
|
|
4861
5031
|
|
|
5032
|
+
case "mate_available_builtins":
|
|
5033
|
+
// Handled via mate_list.availableBuiltins now
|
|
5034
|
+
break;
|
|
5035
|
+
|
|
4862
5036
|
case "mate_error":
|
|
4863
5037
|
showToast(msg.error || "Mate operation failed", "error");
|
|
4864
5038
|
break;
|
|
@@ -4987,6 +5161,11 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4987
5161
|
handleKeepAwakeChanged(msg);
|
|
4988
5162
|
break;
|
|
4989
5163
|
|
|
5164
|
+
case "set_auto_continue_result":
|
|
5165
|
+
case "auto_continue_changed":
|
|
5166
|
+
handleAutoContinueChanged(msg);
|
|
5167
|
+
break;
|
|
5168
|
+
|
|
4990
5169
|
case "restart_server_result":
|
|
4991
5170
|
handleRestartResult(msg);
|
|
4992
5171
|
break;
|
|
@@ -5293,9 +5472,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5293
5472
|
getMateName: function () { return dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate"; },
|
|
5294
5473
|
getMateAvatarUrl: function () { return document.body.dataset.mateAvatarUrl || ""; },
|
|
5295
5474
|
showMatePreThinking: function () { showMatePreThinking(); },
|
|
5296
|
-
isScheduleMode: function () { return scheduleModeActive; },
|
|
5297
|
-
getRateLimitResetsAt: function () { return rateLimitResetsAt; },
|
|
5298
|
-
exitScheduleMode: exitScheduleMode,
|
|
5299
5475
|
});
|
|
5300
5476
|
|
|
5301
5477
|
// --- @Mention module ---
|
|
@@ -5305,10 +5481,13 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5305
5481
|
inputEl: inputEl,
|
|
5306
5482
|
messagesEl: messagesEl,
|
|
5307
5483
|
matesList: function () { return cachedMatesList || []; },
|
|
5484
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
5308
5485
|
scrollToBottom: scrollToBottom,
|
|
5309
5486
|
addUserMessage: addUserMessage,
|
|
5310
5487
|
addCopyHandler: addCopyHandler,
|
|
5311
5488
|
addToMessages: addToMessages,
|
|
5489
|
+
showImageModal: showImageModal,
|
|
5490
|
+
showPasteModal: showPasteModal,
|
|
5312
5491
|
});
|
|
5313
5492
|
|
|
5314
5493
|
// --- Debate module ---
|
|
@@ -5318,6 +5497,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5318
5497
|
scrollToBottom: scrollToBottom,
|
|
5319
5498
|
addCopyHandler: addCopyHandler,
|
|
5320
5499
|
matesList: function () { return cachedMatesList || []; },
|
|
5500
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
5321
5501
|
currentMateId: function () { return (dmTargetUser && dmTargetUser.isMate) ? dmTargetUser.id : null; },
|
|
5322
5502
|
});
|
|
5323
5503
|
|