clay-server 2.20.0-beta.1 → 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/lib/builtin-mates.js +360 -0
- package/lib/mates.js +108 -0
- package/lib/project.js +53 -44
- package/lib/public/app.js +91 -55
- package/lib/public/css/icon-strip.css +55 -2
- package/lib/public/css/input.css +50 -30
- package/lib/public/index.html +1 -0
- 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/input.js +147 -13
- package/lib/public/modules/sidebar.js +223 -15
- package/lib/sdk-bridge.js +8 -26
- package/lib/server.js +125 -7
- package/lib/users.js +63 -0
- package/package.json +1 -1
package/lib/public/app.js
CHANGED
|
@@ -8,7 +8,7 @@ import { initMateKnowledge, requestKnowledgeList, renderKnowledgeList, handleKno
|
|
|
8
8
|
import { initMateMemory, renderMemoryList, hideMemory } from './modules/mate-memory.js';
|
|
9
9
|
import { initRewind, setRewindMode, showRewindModal, clearPendingRewindUuid, addRewindButton } from './modules/rewind.js';
|
|
10
10
|
import { initNotifications, showDoneNotification, playDoneSound, isNotifAlertEnabled, isNotifSoundEnabled } from './modules/notifications.js';
|
|
11
|
-
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';
|
|
12
12
|
import { initQrCode, triggerShare } from './modules/qrcode.js';
|
|
13
13
|
import { initFileBrowser, loadRootDirectory, refreshTree, handleFsList, handleFsRead, handleDirChanged, refreshIfOpen, handleFileChanged, handleFileHistory, handleGitDiff, handleFileAt, getPendingNavigate, closeFileViewer, resetFileBrowser } from './modules/filebrowser.js';
|
|
14
14
|
import { initTerminal, openTerminal, closeTerminal, resetTerminals, handleTermList, handleTermCreated, handleTermOutput, handleTermExited, handleTermClosed, sendTerminalCommand } from './modules/terminal.js';
|
|
@@ -75,6 +75,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
75
75
|
var cachedDmConversations = [];
|
|
76
76
|
var dmRemovedUsers = {}; // { userId: true } - users explicitly removed from favorites
|
|
77
77
|
var cachedMatesList = []; // Cached list of mates for user strip
|
|
78
|
+
var cachedAvailableBuiltins = []; // Deleted built-in mates available for re-add
|
|
78
79
|
|
|
79
80
|
// --- Mate WS (separate connection to mate project) ---
|
|
80
81
|
var mateWs = null;
|
|
@@ -835,15 +836,74 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
835
836
|
}
|
|
836
837
|
})();
|
|
837
838
|
|
|
838
|
-
function handleMateCreatedInApp(mate) {
|
|
839
|
+
function handleMateCreatedInApp(mate, msg) {
|
|
839
840
|
if (!mate) return;
|
|
840
841
|
cachedMatesList.push(mate);
|
|
842
|
+
if (msg && msg.availableBuiltins) cachedAvailableBuiltins = msg.availableBuiltins;
|
|
843
|
+
if (msg && msg.dmFavorites) cachedDmFavorites = msg.dmFavorites;
|
|
841
844
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
842
|
-
//
|
|
843
|
-
|
|
845
|
+
// Built-in mates handle their own onboarding via CLAUDE.md, skip auto-interview
|
|
846
|
+
if (!mate.builtinKey) {
|
|
847
|
+
pendingMateInterview = mate;
|
|
848
|
+
}
|
|
844
849
|
openDm(mate.id);
|
|
845
850
|
}
|
|
846
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
|
+
|
|
847
907
|
var pendingMateInterview = null;
|
|
848
908
|
|
|
849
909
|
function buildMateInterviewPrompt(mate) {
|
|
@@ -1885,6 +1945,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
1885
1945
|
getHistoryFrom: function () { return historyFrom; },
|
|
1886
1946
|
get permissions() { return myPermissions; },
|
|
1887
1947
|
get projectList() { return cachedProjects || []; },
|
|
1948
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
1888
1949
|
};
|
|
1889
1950
|
initSidebar(sidebarCtx);
|
|
1890
1951
|
initIconStrip(sidebarCtx);
|
|
@@ -1901,6 +1962,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
1901
1962
|
currentSlug: function () { return mateProjectSlug || currentSlug; },
|
|
1902
1963
|
projectList: function () { return cachedProjects || []; },
|
|
1903
1964
|
matesList: function () { return cachedMatesList || []; },
|
|
1965
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
1904
1966
|
allUsers: function () { return cachedAllUsers || []; },
|
|
1905
1967
|
dmConversations: function () { return cachedDmConversations || []; },
|
|
1906
1968
|
myUserId: function () { return myUserId; },
|
|
@@ -2852,6 +2914,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
2852
2914
|
function addToMessages(el) {
|
|
2853
2915
|
if (prependAnchor) messagesEl.insertBefore(el, prependAnchor);
|
|
2854
2916
|
else messagesEl.appendChild(el);
|
|
2917
|
+
if (scheduledMsgEl && el !== scheduledMsgEl && scheduledMsgEl.parentNode === messagesEl) {
|
|
2918
|
+
messagesEl.appendChild(scheduledMsgEl);
|
|
2919
|
+
}
|
|
2855
2920
|
}
|
|
2856
2921
|
|
|
2857
2922
|
var newMsgBtn = $("new-msg-btn");
|
|
@@ -3596,13 +3661,12 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3596
3661
|
popoverText = typeLabel + " limit exceeded";
|
|
3597
3662
|
updateRateLimitIndicator(msg);
|
|
3598
3663
|
startRateLimitCountdown(null, msg.resetsAt, null);
|
|
3599
|
-
// Track
|
|
3664
|
+
// Track rate limit reset time
|
|
3600
3665
|
rateLimitResetsAt = msg.resetsAt;
|
|
3601
3666
|
if (rateLimitResetTimer) clearTimeout(rateLimitResetTimer);
|
|
3602
3667
|
rateLimitResetTimer = setTimeout(function () {
|
|
3603
3668
|
rateLimitResetsAt = null;
|
|
3604
3669
|
rateLimitResetTimer = null;
|
|
3605
|
-
exitScheduleMode();
|
|
3606
3670
|
}, msg.resetsAt - Date.now() + 1000);
|
|
3607
3671
|
} else {
|
|
3608
3672
|
var pct = msg.utilization ? Math.round(msg.utilization * 100) : null;
|
|
@@ -3613,32 +3677,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3613
3677
|
showRateLimitPopover(popoverText, isRejected);
|
|
3614
3678
|
}
|
|
3615
3679
|
|
|
3616
|
-
// --- Schedule mode (rate limit) ---
|
|
3617
|
-
|
|
3618
|
-
var scheduleModeActive = false;
|
|
3619
|
-
|
|
3620
|
-
function enterScheduleMode() {
|
|
3621
|
-
if (scheduleModeActive) return;
|
|
3622
|
-
scheduleModeActive = true;
|
|
3623
|
-
var inputRow = document.getElementById("input-row");
|
|
3624
|
-
if (inputRow) inputRow.classList.add("input-rate-limited");
|
|
3625
|
-
if (inputEl) {
|
|
3626
|
-
inputEl.dataset.originalPlaceholder = inputEl.placeholder;
|
|
3627
|
-
inputEl.placeholder = "Schedule message after limit resets...";
|
|
3628
|
-
}
|
|
3629
|
-
}
|
|
3630
|
-
|
|
3631
|
-
function exitScheduleMode() {
|
|
3632
|
-
if (!scheduleModeActive) return;
|
|
3633
|
-
scheduleModeActive = false;
|
|
3634
|
-
var inputRow = document.getElementById("input-row");
|
|
3635
|
-
if (inputRow) inputRow.classList.remove("input-rate-limited");
|
|
3636
|
-
if (inputEl && inputEl.dataset.originalPlaceholder) {
|
|
3637
|
-
inputEl.placeholder = inputEl.dataset.originalPlaceholder;
|
|
3638
|
-
delete inputEl.dataset.originalPlaceholder;
|
|
3639
|
-
}
|
|
3640
|
-
}
|
|
3641
|
-
|
|
3642
3680
|
// --- Scheduled message in chat history ---
|
|
3643
3681
|
|
|
3644
3682
|
var scheduledMsgEl = null;
|
|
@@ -3647,15 +3685,15 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3647
3685
|
function addScheduledMessageBubble(text, resetsAt) {
|
|
3648
3686
|
removeScheduledMessageBubble();
|
|
3649
3687
|
var wrap = document.createElement("div");
|
|
3650
|
-
wrap.className = "scheduled-msg-wrap";
|
|
3688
|
+
wrap.className = "msg-user scheduled-msg-wrap";
|
|
3651
3689
|
wrap.id = "scheduled-msg-bubble";
|
|
3652
3690
|
|
|
3653
3691
|
var bubble = document.createElement("div");
|
|
3654
|
-
bubble.className = "scheduled-msg-bubble";
|
|
3692
|
+
bubble.className = "bubble scheduled-msg-bubble";
|
|
3655
3693
|
|
|
3656
|
-
var textEl = document.createElement("
|
|
3657
|
-
textEl.className = "scheduled-msg-text";
|
|
3694
|
+
var textEl = document.createElement("span");
|
|
3658
3695
|
textEl.textContent = text;
|
|
3696
|
+
bubble.appendChild(textEl);
|
|
3659
3697
|
|
|
3660
3698
|
var metaEl = document.createElement("div");
|
|
3661
3699
|
metaEl.className = "scheduled-msg-meta";
|
|
@@ -3672,7 +3710,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3672
3710
|
var cancelBtn = document.createElement("button");
|
|
3673
3711
|
cancelBtn.className = "scheduled-msg-cancel";
|
|
3674
3712
|
cancelBtn.title = "Cancel scheduled message";
|
|
3675
|
-
cancelBtn.
|
|
3713
|
+
cancelBtn.textContent = "\u00d7";
|
|
3676
3714
|
cancelBtn.addEventListener("click", function () {
|
|
3677
3715
|
if (ws && ws.readyState === 1) {
|
|
3678
3716
|
ws.send(JSON.stringify({ type: "cancel_scheduled_message" }));
|
|
@@ -3680,10 +3718,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3680
3718
|
});
|
|
3681
3719
|
metaEl.appendChild(cancelBtn);
|
|
3682
3720
|
|
|
3683
|
-
bubble.appendChild(textEl);
|
|
3684
|
-
bubble.appendChild(metaEl);
|
|
3685
3721
|
wrap.appendChild(bubble);
|
|
3686
|
-
|
|
3722
|
+
wrap.appendChild(metaEl);
|
|
3723
|
+
addToMessages(wrap);
|
|
3687
3724
|
scheduledMsgEl = wrap;
|
|
3688
3725
|
scrollToBottom();
|
|
3689
3726
|
|
|
@@ -3709,8 +3746,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3709
3746
|
}
|
|
3710
3747
|
updateCountdown();
|
|
3711
3748
|
scheduledCountdownTimer = setInterval(updateCountdown, 1000);
|
|
3712
|
-
|
|
3713
|
-
refreshIcons(wrap);
|
|
3714
3749
|
}
|
|
3715
3750
|
|
|
3716
3751
|
function removeScheduledMessageBubble() {
|
|
@@ -3724,6 +3759,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3724
3759
|
}
|
|
3725
3760
|
}
|
|
3726
3761
|
|
|
3762
|
+
|
|
3727
3763
|
// --- Fast Mode State ---
|
|
3728
3764
|
|
|
3729
3765
|
var fastModeIndicatorEl = null;
|
|
@@ -3958,6 +3994,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3958
3994
|
if (savedMainWs === this) return;
|
|
3959
3995
|
|
|
3960
3996
|
if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
|
|
3997
|
+
closeDmUserPicker();
|
|
3961
3998
|
setStatus("disconnected");
|
|
3962
3999
|
processing = false;
|
|
3963
4000
|
setActivity(null);
|
|
@@ -4621,10 +4658,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4621
4658
|
if (isNotifAlertEnabled() && !window._pushSubscription) showDoneNotification();
|
|
4622
4659
|
if (isNotifSoundEnabled()) playDoneSound();
|
|
4623
4660
|
}
|
|
4624
|
-
// Enter schedule mode if rate limited (regardless of exit code)
|
|
4625
|
-
if (rateLimitResetsAt && rateLimitResetsAt > Date.now()) {
|
|
4626
|
-
enterScheduleMode();
|
|
4627
|
-
}
|
|
4628
4661
|
break;
|
|
4629
4662
|
|
|
4630
4663
|
case "stderr":
|
|
@@ -4661,21 +4694,19 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4661
4694
|
|
|
4662
4695
|
case "scheduled_message_queued":
|
|
4663
4696
|
addScheduledMessageBubble(msg.text, msg.resetsAt);
|
|
4664
|
-
|
|
4697
|
+
setScheduleBtnDisabled(true);
|
|
4665
4698
|
break;
|
|
4666
4699
|
|
|
4667
4700
|
case "scheduled_message_sent":
|
|
4668
4701
|
removeScheduledMessageBubble();
|
|
4702
|
+
setScheduleBtnDisabled(false);
|
|
4669
4703
|
processing = true;
|
|
4670
4704
|
setStatus("processing");
|
|
4671
4705
|
break;
|
|
4672
4706
|
|
|
4673
4707
|
case "scheduled_message_cancelled":
|
|
4674
4708
|
removeScheduledMessageBubble();
|
|
4675
|
-
|
|
4676
|
-
if (rateLimitResetsAt && rateLimitResetsAt > Date.now()) {
|
|
4677
|
-
enterScheduleMode();
|
|
4678
|
-
}
|
|
4709
|
+
setScheduleBtnDisabled(false);
|
|
4679
4710
|
break;
|
|
4680
4711
|
|
|
4681
4712
|
case "auto_continue_scheduled":
|
|
@@ -4946,11 +4977,12 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4946
4977
|
break;
|
|
4947
4978
|
|
|
4948
4979
|
case "mate_created":
|
|
4949
|
-
handleMateCreatedInApp(msg.mate);
|
|
4980
|
+
handleMateCreatedInApp(msg.mate, msg);
|
|
4950
4981
|
break;
|
|
4951
4982
|
|
|
4952
4983
|
case "mate_deleted":
|
|
4953
4984
|
cachedMatesList = cachedMatesList.filter(function (m) { return m.id !== msg.mateId; });
|
|
4985
|
+
if (msg.availableBuiltins) cachedAvailableBuiltins = msg.availableBuiltins;
|
|
4954
4986
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
4955
4987
|
// Clean up background WS for deleted mate
|
|
4956
4988
|
var delSlug = "mate-" + msg.mateId;
|
|
@@ -4993,9 +5025,14 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4993
5025
|
|
|
4994
5026
|
case "mate_list":
|
|
4995
5027
|
cachedMatesList = msg.mates || [];
|
|
5028
|
+
cachedAvailableBuiltins = msg.availableBuiltins || [];
|
|
4996
5029
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
4997
5030
|
break;
|
|
4998
5031
|
|
|
5032
|
+
case "mate_available_builtins":
|
|
5033
|
+
// Handled via mate_list.availableBuiltins now
|
|
5034
|
+
break;
|
|
5035
|
+
|
|
4999
5036
|
case "mate_error":
|
|
5000
5037
|
showToast(msg.error || "Mate operation failed", "error");
|
|
5001
5038
|
break;
|
|
@@ -5435,9 +5472,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5435
5472
|
getMateName: function () { return dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate"; },
|
|
5436
5473
|
getMateAvatarUrl: function () { return document.body.dataset.mateAvatarUrl || ""; },
|
|
5437
5474
|
showMatePreThinking: function () { showMatePreThinking(); },
|
|
5438
|
-
isScheduleMode: function () { return scheduleModeActive; },
|
|
5439
|
-
getRateLimitResetsAt: function () { return rateLimitResetsAt; },
|
|
5440
|
-
exitScheduleMode: exitScheduleMode,
|
|
5441
5475
|
});
|
|
5442
5476
|
|
|
5443
5477
|
// --- @Mention module ---
|
|
@@ -5447,6 +5481,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5447
5481
|
inputEl: inputEl,
|
|
5448
5482
|
messagesEl: messagesEl,
|
|
5449
5483
|
matesList: function () { return cachedMatesList || []; },
|
|
5484
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
5450
5485
|
scrollToBottom: scrollToBottom,
|
|
5451
5486
|
addUserMessage: addUserMessage,
|
|
5452
5487
|
addCopyHandler: addCopyHandler,
|
|
@@ -5462,6 +5497,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5462
5497
|
scrollToBottom: scrollToBottom,
|
|
5463
5498
|
addCopyHandler: addCopyHandler,
|
|
5464
5499
|
matesList: function () { return cachedMatesList || []; },
|
|
5500
|
+
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
5465
5501
|
currentMateId: function () { return (dmTargetUser && dmTargetUser.isMate) ? dmTargetUser.id : null; },
|
|
5466
5502
|
});
|
|
5467
5503
|
|
|
@@ -830,13 +830,17 @@
|
|
|
830
830
|
border: 1px solid var(--border);
|
|
831
831
|
border-radius: 12px;
|
|
832
832
|
padding: 8px;
|
|
833
|
-
width:
|
|
833
|
+
width: 300px;
|
|
834
|
+
max-height: 70vh;
|
|
835
|
+
overflow-y: auto;
|
|
834
836
|
box-shadow: 0 8px 24px rgba(var(--shadow-rgb), 0.5);
|
|
835
837
|
z-index: 10001;
|
|
836
838
|
animation: ctxMenuAppear 0.15s ease-out;
|
|
837
839
|
display: flex;
|
|
838
840
|
flex-direction: column;
|
|
839
841
|
gap: 4px;
|
|
842
|
+
scrollbar-width: thin;
|
|
843
|
+
scrollbar-color: var(--border) transparent;
|
|
840
844
|
}
|
|
841
845
|
|
|
842
846
|
.dm-user-picker-search {
|
|
@@ -861,11 +865,27 @@
|
|
|
861
865
|
}
|
|
862
866
|
|
|
863
867
|
.dm-user-picker-list {
|
|
864
|
-
|
|
868
|
+
overflow: visible;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
.dm-user-picker-list.dm-mates-list {
|
|
872
|
+
max-height: 336px; /* ~7 items at ~48px each */
|
|
865
873
|
overflow-y: auto;
|
|
866
874
|
overflow-x: hidden;
|
|
867
875
|
scrollbar-width: thin;
|
|
868
876
|
scrollbar-color: var(--border) transparent;
|
|
877
|
+
mask-image: linear-gradient(to bottom, black 80%, transparent 100%);
|
|
878
|
+
-webkit-mask-image: linear-gradient(to bottom, black 80%, transparent 100%);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
.dm-user-picker-list.dm-mates-list.scrolled-bottom {
|
|
882
|
+
mask-image: linear-gradient(to bottom, transparent 0%, black 35%);
|
|
883
|
+
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 35%);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.dm-user-picker-list.dm-mates-list.no-overflow {
|
|
887
|
+
mask-image: none;
|
|
888
|
+
-webkit-mask-image: none;
|
|
869
889
|
}
|
|
870
890
|
|
|
871
891
|
.dm-user-picker-list::-webkit-scrollbar {
|
|
@@ -919,6 +939,39 @@
|
|
|
919
939
|
text-align: center;
|
|
920
940
|
}
|
|
921
941
|
|
|
942
|
+
.dm-picker-fav-btn,
|
|
943
|
+
.dm-picker-del-btn {
|
|
944
|
+
flex-shrink: 0;
|
|
945
|
+
border: none;
|
|
946
|
+
background: none;
|
|
947
|
+
cursor: pointer;
|
|
948
|
+
padding: 4px;
|
|
949
|
+
border-radius: 4px;
|
|
950
|
+
display: flex;
|
|
951
|
+
align-items: center;
|
|
952
|
+
opacity: 0.5;
|
|
953
|
+
transition: opacity 0.15s, color 0.15s;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
.dm-picker-fav-btn:hover,
|
|
957
|
+
.dm-picker-del-btn:hover {
|
|
958
|
+
opacity: 1;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
.dm-picker-del-btn:hover {
|
|
962
|
+
color: var(--danger, #e74c3c) !important;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.dm-picker-fav-btn svg,
|
|
966
|
+
.dm-picker-del-btn svg {
|
|
967
|
+
width: 16px;
|
|
968
|
+
height: 16px;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
.dm-picker-fav .dm-picker-fav-btn {
|
|
972
|
+
opacity: 1;
|
|
973
|
+
}
|
|
974
|
+
|
|
922
975
|
/* --- Worktree folder groups --- */
|
|
923
976
|
.icon-strip-group {
|
|
924
977
|
display: flex;
|
package/lib/public/css/input.css
CHANGED
|
@@ -340,7 +340,8 @@
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
#attach-file-btn,
|
|
343
|
-
#attach-image-btn
|
|
343
|
+
#attach-image-btn,
|
|
344
|
+
#schedule-btn {
|
|
344
345
|
width: 36px;
|
|
345
346
|
height: 36px;
|
|
346
347
|
border-radius: 50%;
|
|
@@ -356,10 +357,12 @@
|
|
|
356
357
|
}
|
|
357
358
|
|
|
358
359
|
#attach-file-btn .lucide,
|
|
359
|
-
#attach-image-btn .lucide
|
|
360
|
+
#attach-image-btn .lucide,
|
|
361
|
+
#schedule-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
|
|
360
362
|
|
|
361
363
|
#attach-file-btn:hover,
|
|
362
|
-
#attach-image-btn:hover
|
|
364
|
+
#attach-image-btn:hover,
|
|
365
|
+
#schedule-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
|
|
363
366
|
|
|
364
367
|
#send-btn {
|
|
365
368
|
flex-shrink: 0;
|
|
@@ -668,52 +671,69 @@
|
|
|
668
671
|
}
|
|
669
672
|
|
|
670
673
|
/* ==========================================================================
|
|
671
|
-
|
|
674
|
+
Message Scheduling
|
|
672
675
|
========================================================================== */
|
|
673
676
|
|
|
674
|
-
/*
|
|
675
|
-
#
|
|
676
|
-
border-color
|
|
677
|
-
|
|
677
|
+
/* Schedule button — inline expand (like STT pill) */
|
|
678
|
+
#schedule-btn {
|
|
679
|
+
transition: width 0.2s ease, border-radius 0.2s ease, background 0.15s, color 0.15s, padding 0.2s ease;
|
|
680
|
+
overflow: hidden;
|
|
681
|
+
white-space: nowrap;
|
|
682
|
+
gap: 6px;
|
|
683
|
+
position: relative;
|
|
678
684
|
}
|
|
679
685
|
|
|
680
|
-
#
|
|
681
|
-
|
|
682
|
-
|
|
686
|
+
#schedule-btn.schedule-expanded {
|
|
687
|
+
width: auto;
|
|
688
|
+
padding: 0 10px 0 8px;
|
|
689
|
+
border-radius: 18px;
|
|
683
690
|
}
|
|
684
691
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
692
|
+
#schedule-btn.schedule-active {
|
|
693
|
+
color: var(--accent);
|
|
694
|
+
background: var(--accent-bg, rgba(99,102,241,0.15));
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
.schedule-inline-input {
|
|
698
|
+
width: 48px;
|
|
699
|
+
padding: 2px 4px;
|
|
700
|
+
border: 1px solid var(--border);
|
|
701
|
+
border-radius: 6px;
|
|
702
|
+
background: var(--bg);
|
|
703
|
+
color: var(--text);
|
|
704
|
+
font-size: 12px;
|
|
705
|
+
text-align: center;
|
|
706
|
+
outline: none;
|
|
707
|
+
}
|
|
708
|
+
.schedule-inline-input:focus {
|
|
709
|
+
border-color: var(--accent);
|
|
690
710
|
}
|
|
691
711
|
|
|
692
|
-
.
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
background: color-mix(in srgb, var(--warning, #d97706) 8%, var(--bg-alt));
|
|
697
|
-
border: 1px dashed color-mix(in srgb, var(--warning, #d97706) 40%, transparent);
|
|
712
|
+
.schedule-delay-label {
|
|
713
|
+
font-size: 12px;
|
|
714
|
+
font-weight: 600;
|
|
715
|
+
color: inherit;
|
|
698
716
|
}
|
|
699
717
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
white-space: pre-wrap;
|
|
705
|
-
word-break: break-word;
|
|
718
|
+
/* Scheduled message bubble: accent-tinted user bubble */
|
|
719
|
+
.scheduled-msg-wrap .bubble {
|
|
720
|
+
background: color-mix(in srgb, var(--accent) 18%, var(--user-bubble, var(--bg-alt)));
|
|
721
|
+
border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
|
|
706
722
|
}
|
|
707
723
|
|
|
724
|
+
.scheduled-msg-wrap .msg-user-rewind-btn,
|
|
725
|
+
.scheduled-msg-wrap .msg-actions { display: none !important; }
|
|
726
|
+
|
|
708
727
|
.scheduled-msg-meta {
|
|
709
728
|
display: flex;
|
|
710
729
|
align-items: center;
|
|
711
730
|
gap: 6px;
|
|
712
|
-
|
|
731
|
+
padding-right: 4px;
|
|
713
732
|
font-size: 12px;
|
|
714
|
-
color: var(--
|
|
733
|
+
color: var(--accent);
|
|
715
734
|
}
|
|
716
735
|
|
|
736
|
+
.scheduled-msg-icon svg,
|
|
717
737
|
.scheduled-msg-icon .lucide {
|
|
718
738
|
width: 14px;
|
|
719
739
|
height: 14px;
|
package/lib/public/index.html
CHANGED
|
@@ -398,6 +398,7 @@
|
|
|
398
398
|
<button id="attach-file-btn" type="button" aria-label="Attach file" title="Attach file"><i data-lucide="paperclip"></i></button>
|
|
399
399
|
<button id="attach-image-btn" type="button" aria-label="Attach image" title="Attach image"><i data-lucide="image"></i></button>
|
|
400
400
|
<button id="stt-btn" type="button" aria-label="Voice input" title="Voice input"><i data-lucide="mic"></i></button>
|
|
401
|
+
<button id="schedule-btn" type="button" aria-label="Schedule message" title="Schedule message"><i data-lucide="clock"></i></button>
|
|
401
402
|
</div>
|
|
402
403
|
<div id="input-bottom-right">
|
|
403
404
|
<div id="config-chip-wrap" class="hidden">
|
|
Binary file
|
|
Binary file
|
|
Binary file
|