clay-server 2.26.0-beta.8 → 2.26.0-beta.9
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/daemon.js +1 -1
- package/lib/project.js +20 -0
- package/lib/public/app.js +135 -42
- package/lib/public/css/input.css +74 -19
- package/lib/public/css/mates.css +39 -19
- package/lib/public/css/mention.css +7 -4
- package/lib/public/modules/input.js +3 -1
- package/lib/public/modules/mention.js +40 -2
- package/lib/public/modules/theme.js +2 -1
- package/lib/public/modules/tools.js +49 -25
- package/lib/sdk-bridge.js +12 -0
- package/package.json +1 -1
package/lib/daemon.js
CHANGED
|
@@ -807,7 +807,7 @@ var relay = createServer({
|
|
|
807
807
|
var isMateProject = slug.indexOf("mate-") === 0;
|
|
808
808
|
return {
|
|
809
809
|
slug: slug,
|
|
810
|
-
visibility: isMateProject ? "private" : (config.projects[i].visibility || "public"),
|
|
810
|
+
visibility: isMateProject ? "private" : (config.projects[i].visibility || (config.osUsers ? "private" : "public")),
|
|
811
811
|
allowedUsers: config.projects[i].allowedUsers || [],
|
|
812
812
|
ownerId: config.projects[i].ownerId || null,
|
|
813
813
|
};
|
package/lib/project.js
CHANGED
|
@@ -3884,6 +3884,26 @@ function createProjectContext(opts) {
|
|
|
3884
3884
|
return;
|
|
3885
3885
|
}
|
|
3886
3886
|
|
|
3887
|
+
if (msg.type === "send_scheduled_now") {
|
|
3888
|
+
var nowSession = getSessionForWs(ws);
|
|
3889
|
+
if (!nowSession || !nowSession.scheduledMessage) return;
|
|
3890
|
+
var schedText = nowSession.scheduledMessage.text;
|
|
3891
|
+
clearTimeout(nowSession.scheduledMessage.timer);
|
|
3892
|
+
nowSession.scheduledMessage = null;
|
|
3893
|
+
console.log("[project] Scheduled message sent immediately for session " + nowSession.localId);
|
|
3894
|
+
sm.sendAndRecord(nowSession, { type: "scheduled_message_sent" });
|
|
3895
|
+
var userMsg = { type: "user_message", text: schedText };
|
|
3896
|
+
nowSession.history.push(userMsg);
|
|
3897
|
+
sm.appendToSessionFile(nowSession, userMsg);
|
|
3898
|
+
sendToSession(nowSession.localId, userMsg);
|
|
3899
|
+
nowSession.isProcessing = true;
|
|
3900
|
+
onProcessingChanged();
|
|
3901
|
+
sendToSession(nowSession.localId, { type: "status", status: "processing" });
|
|
3902
|
+
sdk.startQuery(nowSession, schedText, null, getLinuxUserForSession(nowSession));
|
|
3903
|
+
sm.broadcastSessionList();
|
|
3904
|
+
return;
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3887
3907
|
if (msg.type !== "message") return;
|
|
3888
3908
|
if (!msg.text && (!msg.images || msg.images.length === 0) && (!msg.pastes || msg.pastes.length === 0)) return;
|
|
3889
3909
|
|
package/lib/public/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { avatarUrl, userAvatarUrl, mateAvatarUrl } from './modules/avatar.js';
|
|
2
2
|
import { showToast, copyToClipboard, escapeHtml } from './modules/utils.js';
|
|
3
|
-
import { refreshIcons, iconHtml
|
|
3
|
+
import { refreshIcons, iconHtml } from './modules/icons.js';
|
|
4
4
|
import { renderMarkdown, highlightCodeBlocks, renderMermaidBlocks, closeMermaidModal, parseEmojis } from './modules/markdown.js';
|
|
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';
|
|
@@ -14,7 +14,7 @@ import { initFileBrowser, loadRootDirectory, refreshTree, handleFsList, handleFs
|
|
|
14
14
|
import { initTerminal, openTerminal, closeTerminal, resetTerminals, handleTermList, handleTermCreated, handleTermOutput, handleTermResized, handleTermExited, handleTermClosed, sendTerminalCommand } from './modules/terminal.js';
|
|
15
15
|
import { initContextSources, updateTerminalList, updateBrowserTabList, handleContextSourcesState, getActiveSources, hasActiveSources } from './modules/context-sources.js';
|
|
16
16
|
import { initStickyNotes, handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, openArchive, closeArchive, isArchiveOpen, hideNotes, showNotes, isNotesVisible } from './modules/sticky-notes.js';
|
|
17
|
-
import { initTheme, getThemeColor, getComputedVar, onThemeChange, getCurrentTheme } from './modules/theme.js';
|
|
17
|
+
import { initTheme, getThemeColor, getComputedVar, onThemeChange, getCurrentTheme, getChatLayout } from './modules/theme.js';
|
|
18
18
|
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, resetTurnMetaCost, enableMainInput, getTools, getPlanContent, setPlanContent, isPlanFilePath, getTodoTools, updateSubagentActivity, addSubagentToolEntry, markSubagentDone, updateSubagentProgress, initSubagentStop, closeToolGroup, removeToolFromGroup } from './modules/tools.js';
|
|
19
19
|
import { initServerSettings, updateSettingsStats, updateSettingsModels, updateDaemonConfig, handleSetPinResult, handleKeepAwakeChanged, handleAutoContinueChanged, handleRestartResult, handleShutdownResult, handleSharedEnv, handleSharedEnvSaved, handleGlobalClaudeMdRead, handleGlobalClaudeMdWrite } from './modules/server-settings.js';
|
|
20
20
|
import { initProjectSettings, handleInstructionsRead, handleInstructionsWrite, handleProjectEnv, handleProjectEnvSaved, isProjectSettingsOpen, handleProjectSharedEnv, handleProjectSharedEnvSaved, handleProjectOwnerChanged } from './modules/project-settings.js';
|
|
@@ -2083,12 +2083,9 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
2083
2083
|
activityEl = document.createElement("div");
|
|
2084
2084
|
activityEl.className = "activity-inline";
|
|
2085
2085
|
activityEl.innerHTML =
|
|
2086
|
-
'<
|
|
2087
|
-
'<span class="activity-text"></span>';
|
|
2086
|
+
'<div class="mate-thinking-dots"><span></span><span></span><span></span></div>';
|
|
2088
2087
|
addToMessages(activityEl);
|
|
2089
|
-
refreshIcons();
|
|
2090
2088
|
}
|
|
2091
|
-
activityEl.querySelector(".activity-text").textContent = text;
|
|
2092
2089
|
scrollToBottom();
|
|
2093
2090
|
} else {
|
|
2094
2091
|
if (activityEl) {
|
|
@@ -2098,9 +2095,14 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
2098
2095
|
}
|
|
2099
2096
|
}
|
|
2100
2097
|
|
|
2101
|
-
// ---
|
|
2098
|
+
// --- Pre-thinking (instant dots before server responds) ---
|
|
2102
2099
|
var matePreThinkingEl = null;
|
|
2103
2100
|
var matePreThinkingTimer = null;
|
|
2101
|
+
function showClaudePreThinking() {
|
|
2102
|
+
if (getChatLayout() !== "channel") return;
|
|
2103
|
+
var claudeAvatar = CLAUDE_CODE_AVATAR;
|
|
2104
|
+
doShowMatePreThinking("Claude Code", claudeAvatar);
|
|
2105
|
+
}
|
|
2104
2106
|
function showMatePreThinking() {
|
|
2105
2107
|
removeMatePreThinking();
|
|
2106
2108
|
var mateName = dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate";
|
|
@@ -2114,10 +2116,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
2114
2116
|
'<img class="dm-bubble-avatar dm-bubble-avatar-mate" src="' + escapeHtml(mateAvatar) + '" alt="" style="display:block">' +
|
|
2115
2117
|
'<div class="dm-bubble-content">' +
|
|
2116
2118
|
'<div class="dm-bubble-header"><span class="dm-bubble-name">' + escapeHtml(mateName) + '</span></div>' +
|
|
2117
|
-
'<div class="
|
|
2118
|
-
'<span class="activity-icon">' + iconHtml("sparkles") + '</span>' +
|
|
2119
|
-
'<span class="activity-text">' + randomThinkingVerb() + '...</span>' +
|
|
2120
|
-
'</div>' +
|
|
2119
|
+
'<div class="mate-thinking-dots"><span></span><span></span><span></span></div>' +
|
|
2121
2120
|
'</div>';
|
|
2122
2121
|
if (activityEl && activityEl.parentNode) {
|
|
2123
2122
|
activityEl.parentNode.insertBefore(matePreThinkingEl, activityEl);
|
|
@@ -3020,6 +3019,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
3020
3019
|
isMateDm: function () { return dmMode && dmTargetUser && dmTargetUser.isMate; },
|
|
3021
3020
|
getMateName: function () { return dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate"; },
|
|
3022
3021
|
getMateAvatarUrl: function () { return document.body.dataset.mateAvatarUrl || ""; },
|
|
3022
|
+
getClaudeAvatar: function () { return CLAUDE_CODE_AVATAR; },
|
|
3023
3023
|
getMateById: function (id) {
|
|
3024
3024
|
if (!id || !cachedMatesList) return null;
|
|
3025
3025
|
for (var i = 0; i < cachedMatesList.length; i++) {
|
|
@@ -3716,42 +3716,134 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
3716
3716
|
|
|
3717
3717
|
function addScheduledMessageBubble(text, resetsAt) {
|
|
3718
3718
|
removeScheduledMessageBubble();
|
|
3719
|
+
var isChannel = document.body.classList.contains("wide-view");
|
|
3719
3720
|
var wrap = document.createElement("div");
|
|
3720
3721
|
wrap.className = "msg-user scheduled-msg-wrap";
|
|
3721
3722
|
wrap.id = "scheduled-msg-bubble";
|
|
3722
3723
|
|
|
3723
|
-
var
|
|
3724
|
-
|
|
3724
|
+
var countdownEl;
|
|
3725
|
+
var cancelBtn;
|
|
3725
3726
|
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3727
|
+
if (isChannel) {
|
|
3728
|
+
// Channel mode: avatar + header with scheduled badge + message
|
|
3729
|
+
var _me = cachedAllUsers.find(function (u) { return u.id === myUserId; });
|
|
3730
|
+
if (!_me) { try { _me = JSON.parse(localStorage.getItem("clay_my_user") || "null"); } catch(e) {} }
|
|
3731
|
+
var _myName = document.body.dataset.myDisplayName || (_me && (_me.displayName || _me.username)) || "Me";
|
|
3729
3732
|
|
|
3730
|
-
|
|
3731
|
-
|
|
3733
|
+
var avi = document.createElement("img");
|
|
3734
|
+
avi.className = "dm-bubble-avatar dm-bubble-avatar-me";
|
|
3735
|
+
avi.src = document.body.dataset.myAvatarUrl || userAvatarUrl(_me || { id: myUserId }, 36);
|
|
3736
|
+
wrap.appendChild(avi);
|
|
3732
3737
|
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
clockIcon.innerHTML = iconHtml("clock");
|
|
3736
|
-
metaEl.appendChild(clockIcon);
|
|
3738
|
+
var content = document.createElement("div");
|
|
3739
|
+
content.className = "dm-bubble-content";
|
|
3737
3740
|
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
metaEl.appendChild(countdownEl);
|
|
3741
|
+
var header = document.createElement("div");
|
|
3742
|
+
header.className = "dm-bubble-header";
|
|
3741
3743
|
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3744
|
+
var nameSpan = document.createElement("span");
|
|
3745
|
+
nameSpan.className = "dm-bubble-name";
|
|
3746
|
+
nameSpan.textContent = _myName;
|
|
3747
|
+
header.appendChild(nameSpan);
|
|
3748
|
+
|
|
3749
|
+
var badge = document.createElement("span");
|
|
3750
|
+
badge.className = "scheduled-msg-badge";
|
|
3751
|
+
badge.innerHTML = iconHtml("clock");
|
|
3752
|
+
countdownEl = document.createElement("span");
|
|
3753
|
+
countdownEl.className = "scheduled-msg-countdown";
|
|
3754
|
+
badge.appendChild(countdownEl);
|
|
3755
|
+
header.appendChild(badge);
|
|
3756
|
+
|
|
3757
|
+
var actions = document.createElement("span");
|
|
3758
|
+
actions.className = "scheduled-msg-actions";
|
|
3759
|
+
|
|
3760
|
+
var sendNowBtn = document.createElement("button");
|
|
3761
|
+
sendNowBtn.className = "scheduled-msg-send-now";
|
|
3762
|
+
sendNowBtn.textContent = "Send now";
|
|
3763
|
+
sendNowBtn.addEventListener("click", function () {
|
|
3764
|
+
if (ws && ws.readyState === 1) {
|
|
3765
|
+
ws.send(JSON.stringify({ type: "send_scheduled_now" }));
|
|
3766
|
+
}
|
|
3767
|
+
});
|
|
3768
|
+
actions.appendChild(sendNowBtn);
|
|
3769
|
+
|
|
3770
|
+
var sep = document.createElement("span");
|
|
3771
|
+
sep.className = "scheduled-msg-sep";
|
|
3772
|
+
sep.textContent = "\u00b7";
|
|
3773
|
+
actions.appendChild(sep);
|
|
3774
|
+
|
|
3775
|
+
cancelBtn = document.createElement("button");
|
|
3776
|
+
cancelBtn.className = "scheduled-msg-cancel";
|
|
3777
|
+
cancelBtn.textContent = "Cancel";
|
|
3778
|
+
cancelBtn.addEventListener("click", function () {
|
|
3779
|
+
if (ws && ws.readyState === 1) {
|
|
3780
|
+
ws.send(JSON.stringify({ type: "cancel_scheduled_message" }));
|
|
3781
|
+
}
|
|
3782
|
+
});
|
|
3783
|
+
actions.appendChild(cancelBtn);
|
|
3784
|
+
|
|
3785
|
+
header.appendChild(actions);
|
|
3786
|
+
|
|
3787
|
+
content.appendChild(header);
|
|
3788
|
+
|
|
3789
|
+
var bubble = document.createElement("div");
|
|
3790
|
+
bubble.className = "bubble scheduled-msg-bubble";
|
|
3791
|
+
var textEl = document.createElement("span");
|
|
3792
|
+
textEl.textContent = text;
|
|
3793
|
+
bubble.appendChild(textEl);
|
|
3794
|
+
content.appendChild(bubble);
|
|
3795
|
+
|
|
3796
|
+
wrap.appendChild(content);
|
|
3797
|
+
} else {
|
|
3798
|
+
// Bubble mode: original layout
|
|
3799
|
+
var bubble = document.createElement("div");
|
|
3800
|
+
bubble.className = "bubble scheduled-msg-bubble";
|
|
3801
|
+
|
|
3802
|
+
var textEl = document.createElement("span");
|
|
3803
|
+
textEl.textContent = text;
|
|
3804
|
+
bubble.appendChild(textEl);
|
|
3805
|
+
|
|
3806
|
+
var metaEl = document.createElement("div");
|
|
3807
|
+
metaEl.className = "scheduled-msg-meta";
|
|
3808
|
+
|
|
3809
|
+
var clockIcon = document.createElement("span");
|
|
3810
|
+
clockIcon.className = "scheduled-msg-icon";
|
|
3811
|
+
clockIcon.innerHTML = iconHtml("clock");
|
|
3812
|
+
metaEl.appendChild(clockIcon);
|
|
3813
|
+
|
|
3814
|
+
countdownEl = document.createElement("span");
|
|
3815
|
+
countdownEl.className = "scheduled-msg-countdown";
|
|
3816
|
+
metaEl.appendChild(countdownEl);
|
|
3817
|
+
|
|
3818
|
+
var sendNowBtn2 = document.createElement("button");
|
|
3819
|
+
sendNowBtn2.className = "scheduled-msg-send-now";
|
|
3820
|
+
sendNowBtn2.textContent = "Send now";
|
|
3821
|
+
sendNowBtn2.addEventListener("click", function () {
|
|
3822
|
+
if (ws && ws.readyState === 1) {
|
|
3823
|
+
ws.send(JSON.stringify({ type: "send_scheduled_now" }));
|
|
3824
|
+
}
|
|
3825
|
+
});
|
|
3826
|
+
metaEl.appendChild(sendNowBtn2);
|
|
3827
|
+
|
|
3828
|
+
var sep2 = document.createElement("span");
|
|
3829
|
+
sep2.className = "scheduled-msg-sep";
|
|
3830
|
+
sep2.textContent = "\u00b7";
|
|
3831
|
+
metaEl.appendChild(sep2);
|
|
3832
|
+
|
|
3833
|
+
cancelBtn = document.createElement("button");
|
|
3834
|
+
cancelBtn.className = "scheduled-msg-cancel";
|
|
3835
|
+
cancelBtn.textContent = "Cancel";
|
|
3836
|
+
cancelBtn.addEventListener("click", function () {
|
|
3837
|
+
if (ws && ws.readyState === 1) {
|
|
3838
|
+
ws.send(JSON.stringify({ type: "cancel_scheduled_message" }));
|
|
3839
|
+
}
|
|
3840
|
+
});
|
|
3841
|
+
metaEl.appendChild(cancelBtn);
|
|
3842
|
+
|
|
3843
|
+
wrap.appendChild(bubble);
|
|
3844
|
+
wrap.appendChild(metaEl);
|
|
3845
|
+
}
|
|
3752
3846
|
|
|
3753
|
-
wrap.appendChild(bubble);
|
|
3754
|
-
wrap.appendChild(metaEl);
|
|
3755
3847
|
addToMessages(wrap);
|
|
3756
3848
|
scheduledMsgEl = wrap;
|
|
3757
3849
|
scrollToBottom();
|
|
@@ -4644,17 +4736,17 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
4644
4736
|
case "status":
|
|
4645
4737
|
if (msg.status === "processing") {
|
|
4646
4738
|
setStatus("processing");
|
|
4647
|
-
if (!(dmMode && dmTargetUser && dmTargetUser.isMate)) {
|
|
4648
|
-
setActivity(
|
|
4739
|
+
if (!(dmMode && dmTargetUser && dmTargetUser.isMate) && !matePreThinkingEl) {
|
|
4740
|
+
setActivity("thinking");
|
|
4649
4741
|
}
|
|
4650
4742
|
}
|
|
4651
4743
|
break;
|
|
4652
4744
|
|
|
4653
4745
|
case "compacting":
|
|
4654
4746
|
if (msg.active) {
|
|
4655
|
-
setActivity("
|
|
4747
|
+
setActivity("compacting");
|
|
4656
4748
|
} else if (!(dmMode && dmTargetUser && dmTargetUser.isMate)) {
|
|
4657
|
-
setActivity(
|
|
4749
|
+
setActivity("thinking");
|
|
4658
4750
|
}
|
|
4659
4751
|
break;
|
|
4660
4752
|
|
|
@@ -4670,7 +4762,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
4670
4762
|
case "thinking_stop":
|
|
4671
4763
|
stopThinking(msg.duration);
|
|
4672
4764
|
if (!(dmMode && dmTargetUser && dmTargetUser.isMate)) {
|
|
4673
|
-
setActivity(
|
|
4765
|
+
setActivity("thinking");
|
|
4674
4766
|
}
|
|
4675
4767
|
break;
|
|
4676
4768
|
|
|
@@ -5703,6 +5795,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
5703
5795
|
getMateName: function () { return dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate"; },
|
|
5704
5796
|
getMateAvatarUrl: function () { return document.body.dataset.mateAvatarUrl || ""; },
|
|
5705
5797
|
showMatePreThinking: function () { showMatePreThinking(); },
|
|
5798
|
+
showClaudePreThinking: function () { showClaudePreThinking(); },
|
|
5706
5799
|
});
|
|
5707
5800
|
|
|
5708
5801
|
// --- @Mention module ---
|
package/lib/public/css/input.css
CHANGED
|
@@ -466,15 +466,14 @@
|
|
|
466
466
|
display: flex;
|
|
467
467
|
flex-direction: column;
|
|
468
468
|
background: var(--input-bg);
|
|
469
|
-
border:
|
|
469
|
+
border: none;
|
|
470
470
|
border-radius: 8px;
|
|
471
|
-
padding:
|
|
472
|
-
transition:
|
|
471
|
+
padding: 7px;
|
|
472
|
+
transition: box-shadow 0.2s;
|
|
473
473
|
}
|
|
474
474
|
|
|
475
475
|
#input-row:focus-within {
|
|
476
|
-
|
|
477
|
-
box-shadow: 0 0 0 1px rgba(109, 104, 96, 0.15);
|
|
476
|
+
box-shadow: 0 0 0 1px var(--border);
|
|
478
477
|
}
|
|
479
478
|
|
|
480
479
|
#input {
|
|
@@ -553,7 +552,7 @@
|
|
|
553
552
|
border-radius: 10px;
|
|
554
553
|
border: 1px solid transparent;
|
|
555
554
|
background:
|
|
556
|
-
linear-gradient(var(--bg,
|
|
555
|
+
linear-gradient(var(--ask-mate-bg, var(--bg)), var(--ask-mate-bg, var(--bg))) padding-box,
|
|
557
556
|
linear-gradient(135deg, #4ecdc4 0%, #4ecdc4 25%, #556bf7, #a855f7, #f857a6, #ff6b6b) border-box;
|
|
558
557
|
color: transparent;
|
|
559
558
|
cursor: pointer;
|
|
@@ -934,27 +933,83 @@
|
|
|
934
933
|
flex: 1;
|
|
935
934
|
}
|
|
936
935
|
|
|
937
|
-
|
|
938
|
-
|
|
936
|
+
|
|
937
|
+
/* Channel mode: scheduled badge in header row */
|
|
938
|
+
.scheduled-msg-badge {
|
|
939
|
+
display: inline-flex;
|
|
939
940
|
align-items: center;
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
941
|
+
gap: 5px;
|
|
942
|
+
padding: 3px 10px;
|
|
943
|
+
border-radius: 12px;
|
|
944
|
+
font-size: 12px;
|
|
945
|
+
font-weight: 600;
|
|
946
|
+
line-height: 1;
|
|
947
|
+
color: var(--accent);
|
|
948
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
949
|
+
vertical-align: middle;
|
|
950
|
+
}
|
|
951
|
+
.scheduled-msg-badge svg,
|
|
952
|
+
.scheduled-msg-badge .lucide {
|
|
953
|
+
width: 13px;
|
|
954
|
+
height: 13px;
|
|
955
|
+
}
|
|
956
|
+
/* Scheduled message action links (shared by both modes) */
|
|
957
|
+
.scheduled-msg-actions {
|
|
958
|
+
display: inline-flex;
|
|
959
|
+
align-items: center;
|
|
960
|
+
gap: 6px;
|
|
961
|
+
margin-left: 4px;
|
|
962
|
+
}
|
|
963
|
+
.scheduled-msg-send-now {
|
|
964
|
+
padding: 0;
|
|
943
965
|
border: none;
|
|
944
|
-
border-radius: 4px;
|
|
945
966
|
background: none;
|
|
946
|
-
color: var(--
|
|
967
|
+
color: var(--accent);
|
|
968
|
+
font-size: 12px;
|
|
969
|
+
font-weight: 500;
|
|
970
|
+
font-family: inherit;
|
|
947
971
|
cursor: pointer;
|
|
972
|
+
transition: text-decoration 0.15s;
|
|
973
|
+
}
|
|
974
|
+
.scheduled-msg-send-now:hover {
|
|
975
|
+
text-decoration: underline;
|
|
976
|
+
}
|
|
977
|
+
.scheduled-msg-sep {
|
|
978
|
+
color: var(--text-dimmer);
|
|
979
|
+
font-size: 12px;
|
|
980
|
+
user-select: none;
|
|
981
|
+
}
|
|
982
|
+
.scheduled-msg-cancel {
|
|
948
983
|
padding: 0;
|
|
949
|
-
|
|
984
|
+
border: none;
|
|
985
|
+
background: none;
|
|
986
|
+
color: var(--text-dimmer);
|
|
987
|
+
font-size: 12px;
|
|
988
|
+
font-weight: 500;
|
|
989
|
+
font-family: inherit;
|
|
990
|
+
cursor: pointer;
|
|
991
|
+
transition: color 0.15s;
|
|
950
992
|
}
|
|
951
|
-
|
|
952
993
|
.scheduled-msg-cancel:hover {
|
|
953
|
-
background: rgba(var(--overlay-rgb), 0.08);
|
|
954
994
|
color: var(--error);
|
|
955
995
|
}
|
|
956
996
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
997
|
+
/* Channel mode: strip bubble box styling, render as plain text */
|
|
998
|
+
body.wide-view .scheduled-msg-wrap .bubble {
|
|
999
|
+
background: none;
|
|
1000
|
+
border: none;
|
|
1001
|
+
box-shadow: none;
|
|
1002
|
+
padding: 0;
|
|
1003
|
+
border-radius: 0;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/* Channel mode: header alignment */
|
|
1007
|
+
body.wide-view .scheduled-msg-wrap .dm-bubble-header {
|
|
1008
|
+
display: flex;
|
|
1009
|
+
align-items: center;
|
|
1010
|
+
gap: 6px;
|
|
1011
|
+
}
|
|
1012
|
+
body.wide-view .scheduled-msg-wrap .scheduled-msg-countdown {
|
|
1013
|
+
font-size: inherit;
|
|
1014
|
+
color: inherit;
|
|
960
1015
|
}
|
package/lib/public/css/mates.css
CHANGED
|
@@ -2342,7 +2342,9 @@ body.mate-dm-active .turn-meta {
|
|
|
2342
2342
|
========================================================================== */
|
|
2343
2343
|
|
|
2344
2344
|
/* --- Mate Thinking: flex layout matching msg-assistant --- */
|
|
2345
|
-
|
|
2345
|
+
/* Applies in both Mate DM and channel project chat */
|
|
2346
|
+
body.mate-dm-active .mate-thinking,
|
|
2347
|
+
body.wide-view .mate-thinking {
|
|
2346
2348
|
display: flex;
|
|
2347
2349
|
flex-direction: row;
|
|
2348
2350
|
align-items: flex-start;
|
|
@@ -2351,10 +2353,12 @@ body.mate-dm-active .mate-thinking {
|
|
|
2351
2353
|
margin: 0;
|
|
2352
2354
|
max-width: 100%;
|
|
2353
2355
|
}
|
|
2354
|
-
body.mate-dm-active .mate-thinking:hover
|
|
2356
|
+
body.mate-dm-active .mate-thinking:hover,
|
|
2357
|
+
body.wide-view .mate-thinking:hover {
|
|
2355
2358
|
background: var(--bg-alt);
|
|
2356
2359
|
}
|
|
2357
|
-
body.mate-dm-active .mate-thinking > .dm-bubble-avatar
|
|
2360
|
+
body.mate-dm-active .mate-thinking > .dm-bubble-avatar,
|
|
2361
|
+
body.wide-view .mate-thinking > .dm-bubble-avatar {
|
|
2358
2362
|
display: block;
|
|
2359
2363
|
width: 36px;
|
|
2360
2364
|
height: 36px;
|
|
@@ -2362,7 +2366,8 @@ body.mate-dm-active .mate-thinking > .dm-bubble-avatar {
|
|
|
2362
2366
|
flex-shrink: 0;
|
|
2363
2367
|
margin-top: 2px;
|
|
2364
2368
|
}
|
|
2365
|
-
body.mate-dm-active .mate-thinking > .dm-bubble-content
|
|
2369
|
+
body.mate-dm-active .mate-thinking > .dm-bubble-content,
|
|
2370
|
+
body.wide-view .mate-thinking > .dm-bubble-content {
|
|
2366
2371
|
flex: 1;
|
|
2367
2372
|
min-width: 0;
|
|
2368
2373
|
}
|
|
@@ -2373,7 +2378,8 @@ body.mate-dm-active .mate-thinking > .dm-bubble-content {
|
|
|
2373
2378
|
gap: 4px;
|
|
2374
2379
|
padding: 4px 0;
|
|
2375
2380
|
}
|
|
2376
|
-
body.mate-dm-active .mate-thinking:not(.done) .mate-thinking-row
|
|
2381
|
+
body.mate-dm-active .mate-thinking:not(.done) .mate-thinking-row,
|
|
2382
|
+
body.wide-view .mate-thinking:not(.done) .mate-thinking-row {
|
|
2377
2383
|
display: flex;
|
|
2378
2384
|
}
|
|
2379
2385
|
.mate-thinking-dots {
|
|
@@ -2400,10 +2406,16 @@ body.mate-dm-active .mate-thinking:not(.done) .mate-thinking-row {
|
|
|
2400
2406
|
}
|
|
2401
2407
|
|
|
2402
2408
|
/* When done, hide mate row (JS does this too), show compact expandable header */
|
|
2403
|
-
body.mate-dm-active .mate-thinking.done .mate-thinking-row
|
|
2409
|
+
body.mate-dm-active .mate-thinking.done .mate-thinking-row,
|
|
2410
|
+
body.wide-view .mate-thinking.done .mate-thinking-row {
|
|
2404
2411
|
display: none;
|
|
2405
2412
|
}
|
|
2406
|
-
body.mate-dm-active .mate-thinking.done .thinking-
|
|
2413
|
+
body.mate-dm-active .mate-thinking.done .mate-thinking-activity,
|
|
2414
|
+
body.wide-view .mate-thinking.done .mate-thinking-activity {
|
|
2415
|
+
display: none;
|
|
2416
|
+
}
|
|
2417
|
+
body.mate-dm-active .mate-thinking.done .thinking-header,
|
|
2418
|
+
body.wide-view .mate-thinking.done .thinking-header {
|
|
2407
2419
|
display: inline-flex !important;
|
|
2408
2420
|
font-size: 12px;
|
|
2409
2421
|
padding: 4px 10px;
|
|
@@ -2412,16 +2424,19 @@ body.mate-dm-active .mate-thinking.done .thinking-header {
|
|
|
2412
2424
|
opacity: 0.7;
|
|
2413
2425
|
transition: opacity 0.15s;
|
|
2414
2426
|
}
|
|
2415
|
-
body.mate-dm-active .mate-thinking.done .thinking-header:hover
|
|
2427
|
+
body.mate-dm-active .mate-thinking.done .thinking-header:hover,
|
|
2428
|
+
body.wide-view .mate-thinking.done .thinking-header:hover {
|
|
2416
2429
|
opacity: 1;
|
|
2417
2430
|
background: rgba(var(--overlay-rgb), 0.08);
|
|
2418
2431
|
}
|
|
2419
|
-
body.mate-dm-active .mate-thinking .thinking-content
|
|
2432
|
+
body.mate-dm-active .mate-thinking .thinking-content,
|
|
2433
|
+
body.wide-view .mate-thinking .thinking-content {
|
|
2420
2434
|
max-height: 0;
|
|
2421
2435
|
overflow: hidden;
|
|
2422
2436
|
transition: max-height 0.25s ease;
|
|
2423
2437
|
}
|
|
2424
|
-
body.mate-dm-active .mate-thinking.expanded .thinking-content
|
|
2438
|
+
body.mate-dm-active .mate-thinking.expanded .thinking-content,
|
|
2439
|
+
body.wide-view .mate-thinking.expanded .thinking-content {
|
|
2425
2440
|
max-height: 2000px;
|
|
2426
2441
|
}
|
|
2427
2442
|
|
|
@@ -2476,8 +2491,10 @@ body.mate-dm-active .mate-tool-group .tool-name {
|
|
|
2476
2491
|
color: var(--text-muted);
|
|
2477
2492
|
}
|
|
2478
2493
|
|
|
2479
|
-
/* ---
|
|
2480
|
-
|
|
2494
|
+
/* --- Conversational Permission: flex layout matching msg-assistant --- */
|
|
2495
|
+
/* Applies in both Mate DM and channel project chat */
|
|
2496
|
+
body.mate-dm-active .mate-permission,
|
|
2497
|
+
body.wide-view .mate-permission {
|
|
2481
2498
|
display: flex;
|
|
2482
2499
|
flex-direction: row;
|
|
2483
2500
|
align-items: flex-start;
|
|
@@ -2490,10 +2507,12 @@ body.mate-dm-active .mate-permission {
|
|
|
2490
2507
|
margin: 0;
|
|
2491
2508
|
max-width: 100%;
|
|
2492
2509
|
}
|
|
2493
|
-
body.mate-dm-active .mate-permission:hover
|
|
2510
|
+
body.mate-dm-active .mate-permission:hover,
|
|
2511
|
+
body.wide-view .mate-permission:hover {
|
|
2494
2512
|
background: var(--bg-alt);
|
|
2495
2513
|
}
|
|
2496
|
-
body.mate-dm-active .mate-permission > .dm-bubble-avatar
|
|
2514
|
+
body.mate-dm-active .mate-permission > .dm-bubble-avatar,
|
|
2515
|
+
body.wide-view .mate-permission > .dm-bubble-avatar {
|
|
2497
2516
|
display: block;
|
|
2498
2517
|
width: 36px;
|
|
2499
2518
|
height: 36px;
|
|
@@ -2501,7 +2520,8 @@ body.mate-dm-active .mate-permission > .dm-bubble-avatar {
|
|
|
2501
2520
|
flex-shrink: 0;
|
|
2502
2521
|
margin-top: 2px;
|
|
2503
2522
|
}
|
|
2504
|
-
body.mate-dm-active .mate-permission > .dm-bubble-content
|
|
2523
|
+
body.mate-dm-active .mate-permission > .dm-bubble-content,
|
|
2524
|
+
body.wide-view .mate-permission > .dm-bubble-content {
|
|
2505
2525
|
flex: 1;
|
|
2506
2526
|
min-width: 0;
|
|
2507
2527
|
}
|
|
@@ -2569,14 +2589,14 @@ body.mate-dm-active .mate-permission > .dm-bubble-content {
|
|
|
2569
2589
|
.mate-permission-deny {
|
|
2570
2590
|
color: var(--text-muted);
|
|
2571
2591
|
}
|
|
2572
|
-
/* Resolved state */
|
|
2573
|
-
|
|
2592
|
+
/* Resolved state (works in both Mate DM and channel project chat) */
|
|
2593
|
+
.mate-permission.resolved .mate-permission-actions {
|
|
2574
2594
|
pointer-events: none;
|
|
2575
2595
|
}
|
|
2576
|
-
|
|
2596
|
+
.mate-permission.resolved .mate-permission-reply {
|
|
2577
2597
|
display: none;
|
|
2578
2598
|
}
|
|
2579
|
-
|
|
2599
|
+
.mate-permission.resolved .permission-decision-label {
|
|
2580
2600
|
font-size: 12px;
|
|
2581
2601
|
color: var(--text-dimmer);
|
|
2582
2602
|
}
|
|
@@ -107,8 +107,8 @@
|
|
|
107
107
|
padding: 3px 6px 3px 4px;
|
|
108
108
|
margin: 0 0 4px 0;
|
|
109
109
|
border-radius: 6px;
|
|
110
|
-
background: color-mix(in srgb, var(--chip-color, #6c5ce7)
|
|
111
|
-
border: 1px solid color-mix(in srgb, var(--chip-color, #6c5ce7)
|
|
110
|
+
background: color-mix(in srgb, var(--chip-color, #6c5ce7) 15%, var(--bg-alt));
|
|
111
|
+
border: 1px solid color-mix(in srgb, var(--chip-color, #6c5ce7) 30%, var(--border));
|
|
112
112
|
cursor: default;
|
|
113
113
|
flex-shrink: 0;
|
|
114
114
|
width: fit-content;
|
|
@@ -131,19 +131,22 @@
|
|
|
131
131
|
font-size: 13px;
|
|
132
132
|
font-weight: 600;
|
|
133
133
|
white-space: nowrap;
|
|
134
|
+
line-height: 18px;
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
.input-mention-chip-remove {
|
|
137
138
|
background: none;
|
|
138
139
|
border: none;
|
|
139
|
-
padding: 0
|
|
140
|
+
padding: 0;
|
|
140
141
|
margin: 0;
|
|
141
142
|
cursor: pointer;
|
|
142
143
|
font-size: 15px;
|
|
143
|
-
line-height:
|
|
144
|
+
line-height: 18px;
|
|
144
145
|
color: var(--text-dimmer);
|
|
145
146
|
opacity: 0.6;
|
|
146
147
|
transition: opacity 0.1s;
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: center;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
.input-mention-chip-remove:hover {
|
|
@@ -193,9 +193,11 @@ export function sendMessage() {
|
|
|
193
193
|
}
|
|
194
194
|
ctx.ws.send(JSON.stringify(payload));
|
|
195
195
|
|
|
196
|
-
//
|
|
196
|
+
// Show pre-thinking dots before server responds
|
|
197
197
|
if (ctx.isMateDm && ctx.isMateDm()) {
|
|
198
198
|
ctx.showMatePreThinking();
|
|
199
|
+
} else if (ctx.showClaudePreThinking) {
|
|
200
|
+
ctx.showClaudePreThinking();
|
|
199
201
|
}
|
|
200
202
|
|
|
201
203
|
ctx.inputEl.value = "";
|
|
@@ -176,13 +176,42 @@ function selectMentionItem(idx) {
|
|
|
176
176
|
hideMentionMenu();
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
function ensureChipContrast(hex) {
|
|
180
|
+
if (!hex || hex.charAt(0) !== "#") return hex;
|
|
181
|
+
var r = parseInt(hex.substring(1, 3), 16);
|
|
182
|
+
var g = parseInt(hex.substring(3, 5), 16);
|
|
183
|
+
var b = parseInt(hex.substring(5, 7), 16);
|
|
184
|
+
// Relative luminance (sRGB)
|
|
185
|
+
var lum = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
186
|
+
var isDark = document.documentElement.classList.contains("dark") ||
|
|
187
|
+
document.body.classList.contains("dark-mode");
|
|
188
|
+
if (isDark) {
|
|
189
|
+
// Dark mode: lighten if too dark
|
|
190
|
+
return lum < 0.4 ? color_mix_lighten(r, g, b, 0.35) : hex;
|
|
191
|
+
}
|
|
192
|
+
// Light mode: darken if too bright
|
|
193
|
+
return lum > 0.55 ? color_mix_darken(r, g, b, 0.4) : hex;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function color_mix_darken(r, g, b, amount) {
|
|
197
|
+
var f = 1 - amount;
|
|
198
|
+
return "#" + [Math.round(r * f), Math.round(g * f), Math.round(b * f)]
|
|
199
|
+
.map(function (v) { return v.toString(16).padStart(2, "0"); }).join("");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function color_mix_lighten(r, g, b, amount) {
|
|
203
|
+
return "#" + [Math.round(r + (255 - r) * amount), Math.round(g + (255 - g) * amount), Math.round(b + (255 - b) * amount)]
|
|
204
|
+
.map(function (v) { return v.toString(16).padStart(2, "0"); }).join("");
|
|
205
|
+
}
|
|
206
|
+
|
|
179
207
|
function showInputMentionChip(name, color, avatarSrc) {
|
|
180
208
|
removeInputMentionChip();
|
|
209
|
+
var textColor = ensureChipContrast(color);
|
|
181
210
|
var chip = document.createElement("div");
|
|
182
211
|
chip.id = "input-mention-chip";
|
|
183
212
|
chip.innerHTML =
|
|
184
213
|
'<img class="input-mention-chip-avatar" src="' + escapeHtml(avatarSrc) + '" width="18" height="18" />' +
|
|
185
|
-
'<span class="input-mention-chip-name" style="color:' + escapeHtml(
|
|
214
|
+
'<span class="input-mention-chip-name" style="color:' + escapeHtml(textColor) + '">@' + escapeHtml(name) + '</span>' +
|
|
186
215
|
'<button class="input-mention-chip-remove" type="button" aria-label="Remove mention">×</button>';
|
|
187
216
|
chip.style.setProperty("--chip-color", color);
|
|
188
217
|
|
|
@@ -277,7 +306,16 @@ export function sendMention(mateId, text, pastes, images) {
|
|
|
277
306
|
|
|
278
307
|
// Recreate the mention block if it was lost (e.g. session switch)
|
|
279
308
|
function ensureMentionBlock() {
|
|
280
|
-
if (currentMentionEl && currentMentionEl.parentNode)
|
|
309
|
+
if (currentMentionEl && currentMentionEl.parentNode) {
|
|
310
|
+
// If other elements (e.g. permission requests) were added after the mention
|
|
311
|
+
// block, move it to the bottom to maintain chronological order.
|
|
312
|
+
var parent = currentMentionEl.parentNode;
|
|
313
|
+
if (parent.lastElementChild !== currentMentionEl) {
|
|
314
|
+
parent.appendChild(currentMentionEl);
|
|
315
|
+
if (ctx.scrollToBottom) ctx.scrollToBottom();
|
|
316
|
+
}
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
281
319
|
if (!activeMentionMeta) return;
|
|
282
320
|
// Recreate from saved meta
|
|
283
321
|
handleMentionStart(activeMentionMeta);
|
|
@@ -155,7 +155,8 @@ function computeVars(theme) {
|
|
|
155
155
|
"--code-bg": isLight ? darken(b.base00, 0.03) : darken(b.base00, 0.15),
|
|
156
156
|
"--border": b.base02,
|
|
157
157
|
"--border-subtle": mixColors(b.base00, b.base02, 0.6),
|
|
158
|
-
"--input-bg": mixColors(b.base01, b.base02, 0.5),
|
|
158
|
+
"--input-bg": isLight ? darken(b.base00, 0.04) : mixColors(b.base01, b.base02, 0.5),
|
|
159
|
+
"--ask-mate-bg": isLight ? mixColors("#ffffff", darken(b.base00, 0.04), 0.6) : mixColors(b.base00, mixColors(b.base01, b.base02, 0.5), 0.6),
|
|
159
160
|
"--user-bubble": isLight ? darken(b.base01, 0.03) : mixColors(b.base01, b.base02, 0.3),
|
|
160
161
|
"--error": b.base08,
|
|
161
162
|
"--success": b.base0B,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { escapeHtml, copyToClipboard } from './utils.js';
|
|
2
|
-
import { iconHtml, refreshIcons
|
|
2
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
3
|
import { renderMarkdown, highlightCodeBlocks, renderMermaidBlocks } from './markdown.js';
|
|
4
4
|
import { renderUnifiedDiff, renderSplitDiff, renderPatchDiff } from './diff.js';
|
|
5
5
|
import { openFile } from './filebrowser.js';
|
|
6
6
|
import { mateAvatarUrl } from './avatar.js';
|
|
7
|
+
import { getChatLayout } from './theme.js';
|
|
7
8
|
|
|
8
9
|
var ctx;
|
|
9
10
|
|
|
@@ -204,7 +205,7 @@ export function renderAskUserQuestion(toolId, input) {
|
|
|
204
205
|
|
|
205
206
|
var avi = document.createElement("img");
|
|
206
207
|
avi.className = "dm-bubble-avatar";
|
|
207
|
-
avi.src =
|
|
208
|
+
avi.src = identity.avatar;
|
|
208
209
|
container.appendChild(avi);
|
|
209
210
|
|
|
210
211
|
mateContentWrap = document.createElement("div");
|
|
@@ -213,7 +214,7 @@ export function renderAskUserQuestion(toolId, input) {
|
|
|
213
214
|
var headerEl = document.createElement("div");
|
|
214
215
|
headerEl.className = "dm-bubble-header";
|
|
215
216
|
headerEl.innerHTML =
|
|
216
|
-
'<span class="dm-bubble-name">' + escapeHtml(
|
|
217
|
+
'<span class="dm-bubble-name">' + escapeHtml(identity.name) + '</span>' +
|
|
217
218
|
'<span class="dm-bubble-time">' + String(new Date().getHours()).padStart(2, "0") + ":" + String(new Date().getMinutes()).padStart(2, "0") + '</span>';
|
|
218
219
|
mateContentWrap.appendChild(headerEl);
|
|
219
220
|
}
|
|
@@ -496,12 +497,17 @@ export function renderPermissionRequest(requestId, toolName, toolInput, decision
|
|
|
496
497
|
return;
|
|
497
498
|
}
|
|
498
499
|
|
|
499
|
-
// Mate DM:
|
|
500
|
-
if (ctx.isMateDm && ctx.isMateDm()) {
|
|
501
|
-
|
|
500
|
+
// Channel layout or Mate DM: conversational "Can I ...?" style
|
|
501
|
+
if ((ctx.isMateDm && ctx.isMateDm()) || getChatLayout() === "channel") {
|
|
502
|
+
renderConversationalPermission(requestId, toolName, toolInput, mateId);
|
|
502
503
|
return;
|
|
503
504
|
}
|
|
504
505
|
|
|
506
|
+
// Bubble layout: formal "Permission Required" dialog
|
|
507
|
+
renderFormalPermission(requestId, toolName, toolInput, decisionReason);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function renderFormalPermission(requestId, toolName, toolInput, decisionReason) {
|
|
505
511
|
var container = document.createElement("div");
|
|
506
512
|
container.className = "permission-container";
|
|
507
513
|
container.dataset.requestId = requestId;
|
|
@@ -755,18 +761,40 @@ function matePermissionInfo(toolName, toolInput) {
|
|
|
755
761
|
return { verb: verb, target: target };
|
|
756
762
|
}
|
|
757
763
|
|
|
758
|
-
function
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
764
|
+
function resolvePermissionIdentity(mateId) {
|
|
765
|
+
// Mate DM: use DM target mate info
|
|
766
|
+
if (ctx.isMateDm && ctx.isMateDm()) {
|
|
767
|
+
var name = ctx.getMateName();
|
|
768
|
+
var avatar = ctx.getMateAvatarUrl();
|
|
769
|
+
// Override if specific mateId provided (e.g. @mention)
|
|
770
|
+
if (mateId && ctx.getMateById) {
|
|
771
|
+
var mentionMate = ctx.getMateById(mateId);
|
|
772
|
+
if (mentionMate) {
|
|
773
|
+
name = (mentionMate.profile && mentionMate.profile.displayName) || mentionMate.displayName || mentionMate.name || name;
|
|
774
|
+
avatar = mateAvatarUrl(mentionMate, 36);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return { name: name, avatar: avatar };
|
|
778
|
+
}
|
|
779
|
+
// Channel with Mate mention
|
|
763
780
|
if (mateId && ctx.getMateById) {
|
|
764
|
-
var
|
|
765
|
-
if (
|
|
766
|
-
|
|
767
|
-
|
|
781
|
+
var mate = ctx.getMateById(mateId);
|
|
782
|
+
if (mate) {
|
|
783
|
+
return {
|
|
784
|
+
name: (mate.profile && mate.profile.displayName) || mate.displayName || mate.name || "Mate",
|
|
785
|
+
avatar: mateAvatarUrl(mate, 36)
|
|
786
|
+
};
|
|
768
787
|
}
|
|
769
788
|
}
|
|
789
|
+
// Project chat (Claude Code)
|
|
790
|
+
return {
|
|
791
|
+
name: "Claude Code",
|
|
792
|
+
avatar: ctx.getClaudeAvatar ? ctx.getClaudeAvatar() : ""
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
function renderConversationalPermission(requestId, toolName, toolInput, mateId) {
|
|
797
|
+
var identity = resolvePermissionIdentity(mateId);
|
|
770
798
|
var info = matePermissionInfo(toolName, toolInput);
|
|
771
799
|
var askMsg = "Can I " + info.verb + (info.target ? " " + info.target : "") + "?";
|
|
772
800
|
|
|
@@ -777,7 +805,7 @@ function renderMatePermission(requestId, toolName, toolInput, mateId) {
|
|
|
777
805
|
// Avatar (left column)
|
|
778
806
|
var avi = document.createElement("img");
|
|
779
807
|
avi.className = "dm-bubble-avatar dm-bubble-avatar-mate";
|
|
780
|
-
avi.src =
|
|
808
|
+
avi.src = identity.avatar;
|
|
781
809
|
avi.alt = "";
|
|
782
810
|
container.appendChild(avi);
|
|
783
811
|
|
|
@@ -789,7 +817,7 @@ function renderMatePermission(requestId, toolName, toolInput, mateId) {
|
|
|
789
817
|
var headerRow = document.createElement("div");
|
|
790
818
|
headerRow.className = "dm-bubble-header";
|
|
791
819
|
headerRow.innerHTML =
|
|
792
|
-
'<span class="dm-bubble-name">' + escapeHtml(
|
|
820
|
+
'<span class="dm-bubble-name">' + escapeHtml(identity.name) + '</span>' +
|
|
793
821
|
'<span class="dm-bubble-time">' + String(new Date().getHours()).padStart(2, "0") + ":" + String(new Date().getMinutes()).padStart(2, "0") + '</span>';
|
|
794
822
|
content.appendChild(headerRow);
|
|
795
823
|
|
|
@@ -1409,12 +1437,11 @@ export function startThinking() {
|
|
|
1409
1437
|
var el = thinkingGroup.el;
|
|
1410
1438
|
el.classList.remove("done");
|
|
1411
1439
|
el.querySelector(".thinking-content").textContent = "";
|
|
1412
|
-
// Mate mode: restore
|
|
1440
|
+
// Mate mode: restore dots activity row, hide thinking header
|
|
1413
1441
|
if (el.classList.contains("mate-thinking")) {
|
|
1414
1442
|
var actRow = el.querySelector(".mate-thinking-activity");
|
|
1415
1443
|
if (actRow) {
|
|
1416
1444
|
actRow.style.display = "";
|
|
1417
|
-
actRow.querySelector(".activity-text").textContent = randomThinkingVerb() + "...";
|
|
1418
1445
|
}
|
|
1419
1446
|
var header = el.querySelector(".thinking-header");
|
|
1420
1447
|
if (header) header.style.display = "none";
|
|
@@ -1423,7 +1450,7 @@ export function startThinking() {
|
|
|
1423
1450
|
refreshIcons();
|
|
1424
1451
|
ctx.scrollToBottom();
|
|
1425
1452
|
if (!el.classList.contains("mate-thinking")) {
|
|
1426
|
-
ctx.setActivity(
|
|
1453
|
+
ctx.setActivity("thinking");
|
|
1427
1454
|
}
|
|
1428
1455
|
return;
|
|
1429
1456
|
}
|
|
@@ -1439,10 +1466,7 @@ export function startThinking() {
|
|
|
1439
1466
|
'<img class="dm-bubble-avatar dm-bubble-avatar-mate" src="' + escapeHtml(mateAvatar) + '" alt="">' +
|
|
1440
1467
|
'<div class="dm-bubble-content">' +
|
|
1441
1468
|
'<div class="dm-bubble-header"><span class="dm-bubble-name">' + escapeHtml(mateName) + '</span></div>' +
|
|
1442
|
-
'<div class="
|
|
1443
|
-
'<span class="activity-icon">' + iconHtml("sparkles") + '</span>' +
|
|
1444
|
-
'<span class="activity-text">' + randomThinkingVerb() + '...</span>' +
|
|
1445
|
-
'</div>' +
|
|
1469
|
+
'<div class="mate-thinking-dots mate-thinking-activity"><span></span><span></span><span></span></div>' +
|
|
1446
1470
|
'<div class="thinking-header" style="display:none">' +
|
|
1447
1471
|
'<span class="thinking-chevron">' + iconHtml("chevron-right") + '</span>' +
|
|
1448
1472
|
'<span class="thinking-label">Thinking</span>' +
|
|
@@ -1472,7 +1496,7 @@ export function startThinking() {
|
|
|
1472
1496
|
thinkingGroup = { el: el, count: 0, totalDuration: 0 };
|
|
1473
1497
|
currentThinking = { el: el, fullText: "", startTime: Date.now() };
|
|
1474
1498
|
if (!ctx.isMateDm()) {
|
|
1475
|
-
ctx.setActivity(
|
|
1499
|
+
ctx.setActivity("thinking");
|
|
1476
1500
|
}
|
|
1477
1501
|
}
|
|
1478
1502
|
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -1515,6 +1515,18 @@ function createSDKBridge(opts) {
|
|
|
1515
1515
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1516
1516
|
}
|
|
1517
1517
|
|
|
1518
|
+
// Auto-approve safe browser MCP tools.
|
|
1519
|
+
// Only watch/unwatch: user explicitly chose which tab to share.
|
|
1520
|
+
// Everything else (screenshot, read_page, list_tabs, etc.) can expose
|
|
1521
|
+
// content from tabs the user didn't intend to share, so require approval.
|
|
1522
|
+
var safeBrowserTools = { browser_watch_tab: true, browser_unwatch_tab: true };
|
|
1523
|
+
if (toolName.indexOf("mcp__") === 0 && toolName.indexOf("__browser_") !== -1) {
|
|
1524
|
+
var mcpToolName = toolName.substring(toolName.lastIndexOf("__") + 2);
|
|
1525
|
+
if (safeBrowserTools[mcpToolName]) {
|
|
1526
|
+
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1518
1530
|
// Auto-approve safe Bash commands (read-only, non-destructive)
|
|
1519
1531
|
// Applies to ALL sessions (mates and regular projects alike).
|
|
1520
1532
|
// These are purely read-only commands that cannot modify files, install
|