clay-server 2.22.3-beta.1 → 2.23.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/daemon.js +2 -1
- package/lib/mates.js +202 -18
- package/lib/project.js +311 -14
- package/lib/public/app.js +185 -351
- package/lib/public/css/debate.css +263 -0
- package/lib/public/modules/admin.js +2 -2
- package/lib/public/modules/debate.js +289 -0
- package/lib/public/modules/sidebar.js +3 -0
- package/lib/server.js +24 -2
- package/package.json +1 -1
package/lib/public/app.js
CHANGED
|
@@ -31,7 +31,7 @@ import { initMateWizard, openMateWizard, closeMateWizard, handleMateCreated } fr
|
|
|
31
31
|
import { initCommandPalette, handlePaletteSessionSwitch, setPaletteVersion } from './modules/command-palette.js';
|
|
32
32
|
import { initLongPress } from './modules/longpress.js';
|
|
33
33
|
import { initMention, handleMentionStart, handleMentionStream, handleMentionDone, handleMentionError, handleMentionActivity, renderMentionUser, renderMentionResponse } from './modules/mention.js';
|
|
34
|
-
import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn, handleDebateActivity, handleDebateStream, handleDebateTurnDone, handleDebateCommentQueued, handleDebateCommentInjected, handleDebateEnded, handleDebateError, renderDebateStarted, renderDebateTurnDone, renderDebateEnded, renderDebateCommentInjected, renderDebateUserResume, openDebateModal, closeDebateModal } from './modules/debate.js';
|
|
34
|
+
import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn, handleDebateActivity, handleDebateStream, handleDebateTurnDone, handleDebateCommentQueued, handleDebateCommentInjected, handleDebateEnded, handleDebateError, renderDebateStarted, renderDebateTurnDone, renderDebateEnded, renderDebateCommentInjected, renderDebateUserResume, openDebateModal, closeDebateModal, openQuickDebateModal, handleDebateBriefReady, renderDebateBriefReady } from './modules/debate.js';
|
|
35
35
|
|
|
36
36
|
// --- Base path for multi-project routing ---
|
|
37
37
|
var slugMatch = location.pathname.match(/^\/p\/([a-z0-9_-]+)/);
|
|
@@ -65,9 +65,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
65
65
|
|
|
66
66
|
// --- DM Mode ---
|
|
67
67
|
var dmMode = false;
|
|
68
|
-
var pendingMateDmRestore = false; // suppress regular history while restoring mate DM
|
|
69
68
|
var dmKey = null;
|
|
70
69
|
var dmTargetUser = null;
|
|
70
|
+
var dmMessageCache = []; // cached DM messages for quick debate context
|
|
71
71
|
var dmUnread = {}; // { otherUserId: count }
|
|
72
72
|
var cachedAllUsers = [];
|
|
73
73
|
var cachedOnlineIds = [];
|
|
@@ -77,10 +77,10 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
77
77
|
var cachedMatesList = []; // Cached list of mates for user strip
|
|
78
78
|
var cachedAvailableBuiltins = []; // Deleted built-in mates available for re-add
|
|
79
79
|
|
|
80
|
-
// --- Mate
|
|
81
|
-
var mateWs = null;
|
|
80
|
+
// --- Mate project switching ---
|
|
82
81
|
var mateProjectSlug = null;
|
|
83
|
-
var
|
|
82
|
+
var savedMainSlug = null; // main project slug saved during mate DM
|
|
83
|
+
var returningFromMateDm = false; // suppress restore_mate_dm after intentional exit
|
|
84
84
|
|
|
85
85
|
// --- Home Hub ---
|
|
86
86
|
var homeHub = $("home-hub");
|
|
@@ -574,7 +574,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
574
574
|
console.log("[DEBUG enterDmMode] key=" + key, "isMate=" + (targetUser && targetUser.isMate), "messages=" + (messages ? messages.length : 0));
|
|
575
575
|
// Clean up previous DM/mate state before entering new one
|
|
576
576
|
if (dmMode) {
|
|
577
|
-
disconnectMateWs();
|
|
578
577
|
hideMateSidebar();
|
|
579
578
|
hideKnowledge();
|
|
580
579
|
// Reset dm-header-bar
|
|
@@ -645,11 +644,12 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
645
644
|
var resizeHandle = document.getElementById("sidebar-resize-handle");
|
|
646
645
|
if (resizeHandle) resizeHandle.classList.add("dm-mode");
|
|
647
646
|
if (isMate && targetUser.projectSlug) {
|
|
648
|
-
// Mate DM:
|
|
649
|
-
// Main column stays visible (regular project chat UI), sidebar swaps to mate sidebar
|
|
647
|
+
// Mate DM: switch to mate's project (same as project switching)
|
|
650
648
|
showMateSidebar(targetUser.id, targetUser);
|
|
651
|
-
|
|
652
|
-
//
|
|
649
|
+
connectMateProject(targetUser.projectSlug);
|
|
650
|
+
// Close file viewer and terminal panel, hide terminal button (not relevant for mate)
|
|
651
|
+
closeFileViewer();
|
|
652
|
+
closeTerminal();
|
|
653
653
|
var termBtn = document.getElementById("terminal-toggle-btn");
|
|
654
654
|
if (termBtn) termBtn.style.display = "none";
|
|
655
655
|
// Apply mate color to chat title bar and panels
|
|
@@ -705,6 +705,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
705
705
|
if (userIsland && !isMate) userIsland.classList.add("dm-hidden");
|
|
706
706
|
|
|
707
707
|
// Render DM messages
|
|
708
|
+
dmMessageCache = messages ? messages.slice() : [];
|
|
708
709
|
messagesEl.innerHTML = "";
|
|
709
710
|
if (messages && messages.length > 0) {
|
|
710
711
|
for (var i = 0; i < messages.length; i++) {
|
|
@@ -744,17 +745,13 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
744
745
|
}
|
|
745
746
|
}
|
|
746
747
|
|
|
747
|
-
function exitDmMode() {
|
|
748
|
+
function exitDmMode(skipProjectSwitch) {
|
|
748
749
|
if (!dmMode) return;
|
|
750
|
+
var wasMate = dmTargetUser && dmTargetUser.isMate;
|
|
749
751
|
dmMode = false;
|
|
750
|
-
pendingMateDmRestore = false;
|
|
751
752
|
dmKey = null;
|
|
752
753
|
dmTargetUser = null;
|
|
753
754
|
setCurrentDmUser(null);
|
|
754
|
-
// Notify server that mate DM is closed
|
|
755
|
-
if (ws && ws.readyState === 1) {
|
|
756
|
-
try { ws.send(JSON.stringify({ type: "set_mate_dm", mateId: null })); } catch(e) {}
|
|
757
|
-
}
|
|
758
755
|
|
|
759
756
|
var mainCol = document.getElementById("main-column");
|
|
760
757
|
if (mainCol) mainCol.classList.remove("dm-mode");
|
|
@@ -766,15 +763,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
766
763
|
hideKnowledge();
|
|
767
764
|
hideMemory();
|
|
768
765
|
if (isSchedulerOpen()) closeScheduler();
|
|
769
|
-
disconnectMateWs();
|
|
770
766
|
// Restore terminal button
|
|
771
767
|
var termBtn = document.getElementById("terminal-toggle-btn");
|
|
772
768
|
if (termBtn) termBtn.style.display = "";
|
|
773
|
-
// Re-request session list and notes from main project to refresh state
|
|
774
|
-
if (ws && ws.readyState === 1) {
|
|
775
|
-
ws.send(JSON.stringify({ type: "switch_session", id: activeSessionId }));
|
|
776
|
-
ws.send(JSON.stringify({ type: "note_list_request" }));
|
|
777
|
-
}
|
|
778
769
|
|
|
779
770
|
// Reset DM header
|
|
780
771
|
var dmHeaderBar = document.getElementById("dm-header-bar");
|
|
@@ -807,8 +798,26 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
807
798
|
var userIsland = document.getElementById("user-island");
|
|
808
799
|
if (userIsland) userIsland.classList.remove("dm-hidden");
|
|
809
800
|
|
|
810
|
-
// Restore project UI
|
|
811
801
|
if (inputEl) inputEl.placeholder = "";
|
|
802
|
+
|
|
803
|
+
// Switch back to main project (same as project switching)
|
|
804
|
+
if (wasMate && !skipProjectSwitch) {
|
|
805
|
+
disconnectMateProject();
|
|
806
|
+
} else if (wasMate && skipProjectSwitch) {
|
|
807
|
+
// Just clean up mate state, caller will handle project switch
|
|
808
|
+
returningFromMateDm = true;
|
|
809
|
+
mateProjectSlug = null;
|
|
810
|
+
savedMainSlug = null;
|
|
811
|
+
showDebateSticky("hide", null);
|
|
812
|
+
var debateFloat = document.getElementById("debate-info-float");
|
|
813
|
+
if (debateFloat) { debateFloat.classList.add("hidden"); debateFloat.innerHTML = ""; }
|
|
814
|
+
} else {
|
|
815
|
+
// Human DM: just re-request state from main project
|
|
816
|
+
if (ws && ws.readyState === 1) {
|
|
817
|
+
ws.send(JSON.stringify({ type: "switch_session", id: activeSessionId }));
|
|
818
|
+
ws.send(JSON.stringify({ type: "note_list_request" }));
|
|
819
|
+
}
|
|
820
|
+
}
|
|
812
821
|
renderProjectList();
|
|
813
822
|
}
|
|
814
823
|
|
|
@@ -933,307 +942,64 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
933
942
|
"Seed Data:\n" + parts.join("\n");
|
|
934
943
|
}
|
|
935
944
|
|
|
936
|
-
// --- Mate
|
|
937
|
-
var
|
|
938
|
-
var backgroundMateWs = {}; // { slug: WebSocket } - kept alive after exiting mate DM
|
|
945
|
+
// --- Mate icon IO blink ---
|
|
946
|
+
var bgMateIoTimers = {};
|
|
939
947
|
|
|
940
|
-
function
|
|
941
|
-
|
|
942
|
-
var
|
|
943
|
-
try { msg = JSON.parse(ev.data); } catch (e) { return; }
|
|
944
|
-
// IO blink on mate icon strip dot (same as background handler)
|
|
948
|
+
function updateMateIconStatus(msg) {
|
|
949
|
+
if (!mateProjectSlug) return;
|
|
950
|
+
var slug = mateProjectSlug;
|
|
945
951
|
if (msg.type === "content" || msg.type === "tool" || msg.type === "tool_use" || msg.type === "thinking") {
|
|
946
|
-
var
|
|
947
|
-
if (
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
clearTimeout(bgMateIoTimers[slug]);
|
|
952
|
-
bgMateIoTimers[slug] = setTimeout(function () {
|
|
953
|
-
ioDot.classList.remove("io");
|
|
954
|
-
}, 80);
|
|
955
|
-
}
|
|
952
|
+
var ioDot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
953
|
+
if (ioDot) {
|
|
954
|
+
ioDot.classList.add("io");
|
|
955
|
+
clearTimeout(bgMateIoTimers[slug]);
|
|
956
|
+
bgMateIoTimers[slug] = setTimeout(function () { ioDot.classList.remove("io"); }, 80);
|
|
956
957
|
}
|
|
957
958
|
}
|
|
958
|
-
// Update processing status on mate icon (same as background handler)
|
|
959
959
|
if (msg.type === "status" && msg.status === "processing") {
|
|
960
|
-
var
|
|
961
|
-
if (
|
|
962
|
-
var dot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
963
|
-
if (dot) { dot.classList.add("processing"); }
|
|
964
|
-
}
|
|
965
|
-
// Show session processing dot
|
|
960
|
+
var dot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
961
|
+
if (dot) dot.classList.add("processing");
|
|
966
962
|
var mateSessionDot = document.querySelector(".mate-session-item.active .session-processing");
|
|
967
963
|
if (mateSessionDot) mateSessionDot.style.display = "";
|
|
968
964
|
}
|
|
969
965
|
if (msg.type === "done") {
|
|
970
|
-
var
|
|
971
|
-
if (
|
|
972
|
-
var dot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
973
|
-
if (dot) { dot.classList.remove("processing"); }
|
|
974
|
-
}
|
|
975
|
-
// Hide session processing dot
|
|
966
|
+
var dot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
967
|
+
if (dot) dot.classList.remove("processing");
|
|
976
968
|
var mateSessionDot = document.querySelector(".mate-session-item.active .session-processing");
|
|
977
969
|
if (mateSessionDot) mateSessionDot.style.display = "none";
|
|
978
970
|
}
|
|
979
|
-
// Handle skill_installed in mate DM context (for skill install modal)
|
|
980
|
-
if (msg.type === "skill_installed") {
|
|
981
|
-
handleSkillInstalled(msg);
|
|
982
|
-
if (msg.success) knownInstalledSkills[msg.skill] = true;
|
|
983
|
-
handleSkillInstallWs(msg);
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
// Intercept session_list for mate sidebar
|
|
987
|
-
if (msg.type === "init" && msg.sessions) {
|
|
988
|
-
renderMateSessionList(msg.sessions);
|
|
989
|
-
handlePaletteSessionSwitch();
|
|
990
|
-
// Override title bar with mate name (not session/project title)
|
|
991
|
-
if (dmTargetUser && dmTargetUser.isMate) {
|
|
992
|
-
var mateDN = dmTargetUser.displayName || "New Mate";
|
|
993
|
-
if (headerTitleEl) headerTitleEl.textContent = mateDN;
|
|
994
|
-
var tbPN = document.getElementById("title-bar-project-name");
|
|
995
|
-
if (tbPN) tbPN.textContent = mateDN;
|
|
996
|
-
updatePageTitle();
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
if (msg.type === "session_list") {
|
|
1000
|
-
renderMateSessionList(msg.sessions || []);
|
|
1001
|
-
}
|
|
1002
|
-
// Intercept search results for mate sessions
|
|
1003
|
-
if (msg.type === "search_results") {
|
|
1004
|
-
handleMateSearchResults(msg);
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
// Intercept knowledge messages
|
|
1008
|
-
if (msg.type === "knowledge_list") {
|
|
1009
|
-
renderKnowledgeList(msg.files);
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
if (msg.type === "knowledge_content") {
|
|
1013
|
-
handleKnowledgeContent(msg);
|
|
1014
|
-
return;
|
|
1015
|
-
}
|
|
1016
|
-
if (msg.type === "knowledge_saved" || msg.type === "knowledge_deleted" || msg.type === "knowledge_promoted" || msg.type === "knowledge_depromoted") {
|
|
1017
|
-
return; // list update follows separately
|
|
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
|
-
}
|
|
1026
|
-
// On done: scan DOM for [[MATE_READY: name]], update name, strip marker
|
|
1027
|
-
if (msg.type === "done" && dmTargetUser && dmTargetUser.isMate) {
|
|
1028
|
-
// Ensure last message is fully visible after rendering settles
|
|
1029
|
-
setTimeout(function () { scrollToBottom(); }, 100);
|
|
1030
|
-
setTimeout(function () { scrollToBottom(); }, 400);
|
|
1031
|
-
// Let processMessage render first, then scan DOM
|
|
1032
|
-
setTimeout(function () {
|
|
1033
|
-
var fullText = messagesEl ? messagesEl.textContent : "";
|
|
1034
|
-
var readyMatch = fullText.match(/\[\[MATE_READY:\s*(.+?)\]\]/);
|
|
1035
|
-
if (readyMatch) {
|
|
1036
|
-
var newName = readyMatch[1].trim();
|
|
1037
|
-
dmTargetUser.displayName = newName;
|
|
1038
|
-
updateMateSidebarProfile({ profile: { displayName: newName, avatarColor: dmTargetUser.avatarColor, avatarStyle: dmTargetUser.avatarStyle, avatarSeed: dmTargetUser.avatarSeed } });
|
|
1039
|
-
if (savedMainWs && savedMainWs.readyState === 1) {
|
|
1040
|
-
savedMainWs.send(JSON.stringify({
|
|
1041
|
-
type: "mate_update",
|
|
1042
|
-
mateId: dmTargetUser.id,
|
|
1043
|
-
updates: { name: newName, status: "ready", profile: { displayName: newName } },
|
|
1044
|
-
}));
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
// Strip all MATE_READY markers from visible elements
|
|
1048
|
-
var walker = document.createTreeWalker(messagesEl, NodeFilter.SHOW_TEXT, null, false);
|
|
1049
|
-
var node;
|
|
1050
|
-
while (node = walker.nextNode()) {
|
|
1051
|
-
if (node.nodeValue.indexOf("[[MATE_READY:") !== -1) {
|
|
1052
|
-
node.nodeValue = node.nodeValue.replace(/\[\[MATE_READY:\s*.+?\]\]/g, "").trim();
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
}, 100);
|
|
1056
|
-
}
|
|
1057
|
-
// Feed everything into the main message handler (renders text, tools, etc.)
|
|
1058
|
-
if (msg.type === "session_switched" || msg.type === "history_meta") {
|
|
1059
|
-
console.log("[DEBUG mateWs]", msg.type, msg.type === "session_switched" ? "id=" + msg.id + " cli=" + (msg.cliSessionId || "").substring(0, 8) : "from=" + msg.from + " total=" + msg.total);
|
|
1060
|
-
}
|
|
1061
|
-
processMessage(msg);
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
// Background handler: update mate icon status when not in DM mode
|
|
1065
|
-
var bgMateIoTimers = {};
|
|
1066
|
-
function handleBackgroundMateMsg(slug, ev) {
|
|
1067
|
-
var msg;
|
|
1068
|
-
try { msg = JSON.parse(ev.data); } catch (e) { return; }
|
|
1069
|
-
// Update processing status on mate icon
|
|
1070
|
-
if (msg.type === "status" && msg.status === "processing") {
|
|
1071
|
-
var dot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
1072
|
-
if (dot) {
|
|
1073
|
-
dot.classList.add("processing");
|
|
1074
|
-
updateCrossProjectBlink();
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
if (msg.type === "done") {
|
|
1078
|
-
var dot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
1079
|
-
if (dot) {
|
|
1080
|
-
dot.classList.remove("processing");
|
|
1081
|
-
updateCrossProjectBlink();
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
// IO blink on mate icon for streaming content (same as project IO blink)
|
|
1085
|
-
if (msg.type === "content" || msg.type === "tool" || msg.type === "tool_use" || msg.type === "thinking") {
|
|
1086
|
-
var ioDot = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"] .icon-strip-status');
|
|
1087
|
-
if (ioDot) {
|
|
1088
|
-
ioDot.classList.add("io");
|
|
1089
|
-
clearTimeout(bgMateIoTimers[slug]);
|
|
1090
|
-
bgMateIoTimers[slug] = setTimeout(function () {
|
|
1091
|
-
ioDot.classList.remove("io");
|
|
1092
|
-
}, 80);
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
// Permission requests while backgrounded: show shake on mate icon
|
|
1096
|
-
if (msg.type === "permission_request" || msg.type === "permission_request_pending") {
|
|
1097
|
-
var mateEl = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"]');
|
|
1098
|
-
if (mateEl && !mateEl.classList.contains("active")) {
|
|
1099
|
-
mateEl.classList.add("has-pending-perm");
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
if (msg.type === "permission_cancel") {
|
|
1103
|
-
var mateEl = document.querySelector('.icon-strip-mate[data-mate-slug="' + slug + '"]');
|
|
1104
|
-
if (mateEl) mateEl.classList.remove("has-pending-perm");
|
|
1105
|
-
}
|
|
1106
971
|
}
|
|
1107
972
|
|
|
1108
|
-
function
|
|
1109
|
-
disconnectMateWs();
|
|
973
|
+
function connectMateProject(slug) {
|
|
1110
974
|
mateProjectSlug = slug;
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
delete backgroundMateWs[slug];
|
|
1117
|
-
// Re-attach foreground handler
|
|
1118
|
-
mateWs.onmessage = handleMateWsMessage;
|
|
1119
|
-
mateWs.onclose = function () {
|
|
1120
|
-
if (ws === mateWs) {
|
|
1121
|
-
ws = savedMainWs;
|
|
1122
|
-
savedMainWs = null;
|
|
1123
|
-
}
|
|
1124
|
-
mateWs = null;
|
|
1125
|
-
delete backgroundMateWs[slug];
|
|
1126
|
-
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
1127
|
-
setStatus("disconnected");
|
|
1128
|
-
scheduleReconnect();
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1131
|
-
// Swap main ws
|
|
1132
|
-
savedMainWs = ws;
|
|
1133
|
-
savedActiveSessionId = activeSessionId;
|
|
1134
|
-
ws = mateWs;
|
|
1135
|
-
connected = true;
|
|
1136
|
-
// Wrap send to blink IO on outgoing traffic (if not already wrapped)
|
|
1137
|
-
if (!mateWs._ioWrapped) {
|
|
1138
|
-
var _origSend = mateWs.send.bind(mateWs);
|
|
1139
|
-
mateWs.send = function (data) { blinkIO(); return _origSend(data); };
|
|
1140
|
-
mateWs._ioWrapped = true;
|
|
1141
|
-
}
|
|
1142
|
-
// Re-request state since we were backgrounded
|
|
1143
|
-
try { mateWs.send(JSON.stringify({ type: "knowledge_list" })); } catch(e) {}
|
|
1144
|
-
// Re-switch to the active session to get fresh history replay
|
|
1145
|
-
if (mateWs._bgActiveSession) {
|
|
1146
|
-
try { mateWs.send(JSON.stringify({ type: "switch_session", id: mateWs._bgActiveSession })); } catch(e) {}
|
|
1147
|
-
}
|
|
1148
|
-
return;
|
|
1149
|
-
}
|
|
1150
|
-
// Clean up stale background WS if any
|
|
1151
|
-
if (bgWs) {
|
|
1152
|
-
bgWs.onclose = null;
|
|
1153
|
-
bgWs.onmessage = null;
|
|
1154
|
-
bgWs.close();
|
|
1155
|
-
delete backgroundMateWs[slug];
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
// Block main WS messages immediately (before mate WS connects)
|
|
1159
|
-
// so project history doesn't leak into the DM chat
|
|
1160
|
-
savedMainWs = ws;
|
|
1161
|
-
savedActiveSessionId = activeSessionId;
|
|
1162
|
-
|
|
1163
|
-
var protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
1164
|
-
mateWs = new WebSocket(protocol + "//" + location.host + "/p/" + slug + "/ws");
|
|
1165
|
-
|
|
1166
|
-
mateWs.onopen = function () {
|
|
1167
|
-
// Swap main ws to mateWs so all UI (input, model selector, etc.) routes through mate project
|
|
1168
|
-
ws = mateWs;
|
|
1169
|
-
connected = true;
|
|
1170
|
-
// Wrap send to blink IO on outgoing traffic
|
|
1171
|
-
var _origSend = mateWs.send.bind(mateWs);
|
|
1172
|
-
mateWs.send = function (data) { blinkIO(); return _origSend(data); };
|
|
1173
|
-
mateWs._ioWrapped = true;
|
|
1174
|
-
// Request knowledge list for badge immediately
|
|
1175
|
-
try { mateWs.send(JSON.stringify({ type: "knowledge_list" })); } catch(e) {}
|
|
1176
|
-
};
|
|
1177
|
-
|
|
1178
|
-
mateWs.onmessage = handleMateWsMessage;
|
|
1179
|
-
|
|
1180
|
-
mateWs.onclose = function () {
|
|
1181
|
-
if (ws === mateWs) {
|
|
1182
|
-
ws = savedMainWs;
|
|
1183
|
-
savedMainWs = null;
|
|
1184
|
-
} else if (savedMainWs && !ws) {
|
|
1185
|
-
// Mate WS failed before swap completed; restore main WS
|
|
1186
|
-
ws = savedMainWs;
|
|
1187
|
-
savedMainWs = null;
|
|
1188
|
-
}
|
|
1189
|
-
mateWs = null;
|
|
1190
|
-
delete backgroundMateWs[slug];
|
|
1191
|
-
// If main ws is also closed (server shutdown), show disconnect screen
|
|
1192
|
-
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
1193
|
-
setStatus("disconnected");
|
|
1194
|
-
scheduleReconnect();
|
|
1195
|
-
}
|
|
1196
|
-
};
|
|
975
|
+
savedMainSlug = currentSlug;
|
|
976
|
+
currentSlug = slug;
|
|
977
|
+
wsPath = "/p/" + slug + "/ws";
|
|
978
|
+
resetClientState();
|
|
979
|
+
connect();
|
|
1197
980
|
}
|
|
1198
981
|
|
|
1199
|
-
function
|
|
1200
|
-
if (mateWs) {
|
|
1201
|
-
// Restore main ws before backgrounding
|
|
1202
|
-
if (ws === mateWs && savedMainWs) {
|
|
1203
|
-
ws = savedMainWs;
|
|
1204
|
-
savedMainWs = null;
|
|
1205
|
-
}
|
|
1206
|
-
// Keep mate WS alive in background instead of closing
|
|
1207
|
-
if (mateProjectSlug && mateWs.readyState === 1) {
|
|
1208
|
-
var bgSlug = mateProjectSlug;
|
|
1209
|
-
mateWs._bgActiveSession = activeSessionId;
|
|
1210
|
-
backgroundMateWs[bgSlug] = mateWs;
|
|
1211
|
-
mateWs.onmessage = function (ev) { handleBackgroundMateMsg(bgSlug, ev); };
|
|
1212
|
-
mateWs.onclose = function () { delete backgroundMateWs[bgSlug]; };
|
|
1213
|
-
} else {
|
|
1214
|
-
mateWs.onclose = null;
|
|
1215
|
-
mateWs.close();
|
|
1216
|
-
}
|
|
1217
|
-
mateWs = null;
|
|
1218
|
-
}
|
|
1219
|
-
// Restore main project's active session ID
|
|
1220
|
-
if (savedActiveSessionId) {
|
|
1221
|
-
activeSessionId = savedActiveSessionId;
|
|
1222
|
-
savedActiveSessionId = null;
|
|
1223
|
-
}
|
|
982
|
+
function disconnectMateProject() {
|
|
1224
983
|
mateProjectSlug = null;
|
|
1225
984
|
// Hide debate sticky when leaving mate DM
|
|
1226
985
|
showDebateSticky("hide", null);
|
|
1227
986
|
// Hide debate info float
|
|
1228
987
|
var debateFloat = document.getElementById("debate-info-float");
|
|
1229
988
|
if (debateFloat) { debateFloat.classList.add("hidden"); debateFloat.innerHTML = ""; }
|
|
1230
|
-
//
|
|
1231
|
-
if (
|
|
989
|
+
// Switch back to main project
|
|
990
|
+
if (savedMainSlug) {
|
|
991
|
+
returningFromMateDm = true;
|
|
992
|
+
currentSlug = savedMainSlug;
|
|
993
|
+
basePath = "/p/" + savedMainSlug + "/";
|
|
994
|
+
wsPath = "/p/" + savedMainSlug + "/ws";
|
|
995
|
+
savedMainSlug = null;
|
|
996
|
+
resetClientState();
|
|
1232
997
|
connect();
|
|
1233
998
|
}
|
|
1234
999
|
}
|
|
1235
1000
|
|
|
1236
1001
|
function appendDmMessage(msg) {
|
|
1002
|
+
if (dmMode) dmMessageCache.push(msg);
|
|
1237
1003
|
var isMe = msg.from === myUserId;
|
|
1238
1004
|
var d = new Date(msg.ts);
|
|
1239
1005
|
var timeStr = d.getHours().toString().padStart(2, "0") + ":" + d.getMinutes().toString().padStart(2, "0");
|
|
@@ -1949,9 +1715,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
1949
1715
|
};
|
|
1950
1716
|
initSidebar(sidebarCtx);
|
|
1951
1717
|
initIconStrip(sidebarCtx);
|
|
1952
|
-
initMateSidebar(function () { return
|
|
1953
|
-
initMateKnowledge(function () { return
|
|
1954
|
-
initMateMemory(function () { return
|
|
1718
|
+
initMateSidebar(function () { return (dmMode && dmTargetUser && dmTargetUser.isMate) ? ws : null; });
|
|
1719
|
+
initMateKnowledge(function () { return (dmMode && dmTargetUser && dmTargetUser.isMate) ? ws : null; });
|
|
1720
|
+
initMateMemory(function () { return (dmMode && dmTargetUser && dmTargetUser.isMate) ? ws : null; }, { onShow: function () { hideKnowledge(); hideNotes(); } });
|
|
1955
1721
|
initMateWizard(
|
|
1956
1722
|
function (msg) { if (ws && ws.readyState === 1) ws.send(JSON.stringify(msg)); },
|
|
1957
1723
|
function (mate) { handleMateCreatedInApp(mate); }
|
|
@@ -1959,7 +1725,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
1959
1725
|
|
|
1960
1726
|
initCommandPalette({
|
|
1961
1727
|
switchProject: function (slug) { switchProject(slug); },
|
|
1962
|
-
currentSlug: function () { return
|
|
1728
|
+
currentSlug: function () { return currentSlug; },
|
|
1963
1729
|
projectList: function () { return cachedProjects || []; },
|
|
1964
1730
|
matesList: function () { return cachedMatesList || []; },
|
|
1965
1731
|
availableBuiltins: function () { return cachedAvailableBuiltins || []; },
|
|
@@ -3874,7 +3640,8 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3874
3640
|
function switchProject(slug) {
|
|
3875
3641
|
if (!slug) return;
|
|
3876
3642
|
var wasDm = dmMode;
|
|
3877
|
-
|
|
3643
|
+
var wasMate = dmMode && dmTargetUser && dmTargetUser.isMate;
|
|
3644
|
+
if (dmMode) exitDmMode(/* skipProjectSwitch */ wasMate);
|
|
3878
3645
|
if (homeHubVisible) {
|
|
3879
3646
|
hideHomeHub();
|
|
3880
3647
|
if (slug === currentSlug) return;
|
|
@@ -3930,9 +3697,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3930
3697
|
ws = new WebSocket(protocol + "//" + location.host + wsPath);
|
|
3931
3698
|
|
|
3932
3699
|
|
|
3933
|
-
// If not connected within 3s, force retry
|
|
3700
|
+
// If not connected within 3s, force retry
|
|
3934
3701
|
connectTimeoutId = setTimeout(function () {
|
|
3935
|
-
if (!connected
|
|
3702
|
+
if (!connected) {
|
|
3936
3703
|
ws.onclose = null;
|
|
3937
3704
|
ws.onerror = null;
|
|
3938
3705
|
ws.close();
|
|
@@ -3989,14 +3756,25 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
3989
3756
|
ws.send(JSON.stringify({ type: "mate_list" }));
|
|
3990
3757
|
} catch(e) {}
|
|
3991
3758
|
|
|
3759
|
+
// If connecting to a mate project, request knowledge list for badge
|
|
3760
|
+
if (mateProjectSlug) {
|
|
3761
|
+
try { ws.send(JSON.stringify({ type: "knowledge_list" })); } catch(e) {}
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3992
3764
|
// Session restore is now server-driven (user-presence.json).
|
|
3993
3765
|
// Mate DM restore is also server-driven via "restore_mate_dm" message.
|
|
3766
|
+
// Safety: clear returningFromMateDm after initial messages settle
|
|
3767
|
+
// (handles case where we connect to a non-main project that won't send restore_mate_dm)
|
|
3768
|
+
if (returningFromMateDm) {
|
|
3769
|
+
setTimeout(function () {
|
|
3770
|
+
if (returningFromMateDm) {
|
|
3771
|
+
returningFromMateDm = false;
|
|
3772
|
+
}
|
|
3773
|
+
}, 2000);
|
|
3774
|
+
}
|
|
3994
3775
|
};
|
|
3995
3776
|
|
|
3996
3777
|
ws.onclose = function (e) {
|
|
3997
|
-
// If this WS is stashed while in mate DM, ignore close events
|
|
3998
|
-
if (savedMainWs === this) return;
|
|
3999
|
-
|
|
4000
3778
|
if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
|
|
4001
3779
|
closeDmUserPicker();
|
|
4002
3780
|
setStatus("disconnected");
|
|
@@ -4022,10 +3800,7 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4022
3800
|
scheduleReconnect();
|
|
4023
3801
|
};
|
|
4024
3802
|
|
|
4025
|
-
ws.onerror = function () {
|
|
4026
|
-
// If this WS is stashed while in mate DM, ignore error events
|
|
4027
|
-
if (savedMainWs === this) return;
|
|
4028
|
-
};
|
|
3803
|
+
ws.onerror = function () {};
|
|
4029
3804
|
|
|
4030
3805
|
function showUpdateAvailable(msg) {
|
|
4031
3806
|
var updatePillWrap = $("update-pill-wrap");
|
|
@@ -4071,18 +3846,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4071
3846
|
|
|
4072
3847
|
ws.onmessage = function (event) {
|
|
4073
3848
|
// If this WS is stashed while in mate DM, only allow skill_installed through
|
|
4074
|
-
if (savedMainWs === this) {
|
|
4075
|
-
try {
|
|
4076
|
-
var stashedMsg = JSON.parse(event.data);
|
|
4077
|
-
if (stashedMsg.type === "skill_installed") {
|
|
4078
|
-
handleSkillInstalled(stashedMsg);
|
|
4079
|
-
if (stashedMsg.success) knownInstalledSkills[stashedMsg.skill] = true;
|
|
4080
|
-
handleSkillInstallWs(stashedMsg);
|
|
4081
|
-
}
|
|
4082
|
-
} catch (e) {}
|
|
4083
|
-
return;
|
|
4084
|
-
}
|
|
4085
|
-
|
|
4086
3849
|
// Backup: if we're receiving messages, we're connected
|
|
4087
3850
|
if (!connected) {
|
|
4088
3851
|
setStatus("connected");
|
|
@@ -4098,19 +3861,77 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4098
3861
|
}
|
|
4099
3862
|
|
|
4100
3863
|
function processMessage(msg) {
|
|
3864
|
+
var isMateDm = dmMode && dmTargetUser && dmTargetUser.isMate;
|
|
3865
|
+
|
|
4101
3866
|
// DEBUG: trace session/history loading
|
|
4102
3867
|
if (msg.type === "session_switched" || msg.type === "history_meta" || msg.type === "history_done" || msg.type === "mention_user" || msg.type === "mention_response") {
|
|
4103
|
-
console.log("[DEBUG msg]", msg.type, msg.type === "session_switched" ? "id=" + msg.id + " cli=" + (msg.cliSessionId || "").substring(0, 8) : "", msg.type === "history_meta" ? "from=" + msg.from + " total=" + msg.total : "", msg.type === "mention_user" ? "mate=" + msg.mateName : "", "dmMode=" + dmMode
|
|
3868
|
+
console.log("[DEBUG msg]", msg.type, msg.type === "session_switched" ? "id=" + msg.id + " cli=" + (msg.cliSessionId || "").substring(0, 8) : "", msg.type === "history_meta" ? "from=" + msg.from + " total=" + msg.total : "", msg.type === "mention_user" ? "mate=" + msg.mateName : "", "dmMode=" + dmMode);
|
|
4104
3869
|
}
|
|
4105
3870
|
|
|
4106
|
-
//
|
|
4107
|
-
if (
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
3871
|
+
// Mate DM: update mate icon status indicators
|
|
3872
|
+
if (isMateDm) updateMateIconStatus(msg);
|
|
3873
|
+
|
|
3874
|
+
// Mate DM: intercept mate-specific messages
|
|
3875
|
+
if (isMateDm) {
|
|
3876
|
+
if (msg.type === "session_list") {
|
|
3877
|
+
renderMateSessionList(msg.sessions || []);
|
|
3878
|
+
// Also override title bar with mate name
|
|
3879
|
+
var _mdn = (dmTargetUser.displayName || "New Mate");
|
|
3880
|
+
if (headerTitleEl) headerTitleEl.textContent = _mdn;
|
|
3881
|
+
var _tbpn = document.getElementById("title-bar-project-name");
|
|
3882
|
+
if (_tbpn) _tbpn.textContent = _mdn;
|
|
3883
|
+
updatePageTitle();
|
|
3884
|
+
// Still let normal session_list handler run below
|
|
3885
|
+
}
|
|
3886
|
+
if (msg.type === "search_results") {
|
|
3887
|
+
handleMateSearchResults(msg);
|
|
3888
|
+
return;
|
|
3889
|
+
}
|
|
3890
|
+
if (msg.type === "knowledge_list") {
|
|
3891
|
+
renderKnowledgeList(msg.files);
|
|
3892
|
+
return;
|
|
3893
|
+
}
|
|
3894
|
+
if (msg.type === "knowledge_content") {
|
|
3895
|
+
handleKnowledgeContent(msg);
|
|
3896
|
+
return;
|
|
3897
|
+
}
|
|
3898
|
+
if (msg.type === "knowledge_saved" || msg.type === "knowledge_deleted" || msg.type === "knowledge_promoted" || msg.type === "knowledge_depromoted") {
|
|
3899
|
+
return;
|
|
3900
|
+
}
|
|
3901
|
+
if (msg.type === "memory_list") {
|
|
3902
|
+
renderMemoryList(msg.entries, msg.summary);
|
|
3903
|
+
return;
|
|
3904
|
+
}
|
|
3905
|
+
if (msg.type === "memory_deleted") {
|
|
3906
|
+
return;
|
|
3907
|
+
}
|
|
3908
|
+
// On done: scan DOM for [[MATE_READY: name]], update name, strip marker
|
|
3909
|
+
if (msg.type === "done") {
|
|
3910
|
+
setTimeout(function () { scrollToBottom(); }, 100);
|
|
3911
|
+
setTimeout(function () { scrollToBottom(); }, 400);
|
|
3912
|
+
setTimeout(function () {
|
|
3913
|
+
var fullText = messagesEl ? messagesEl.textContent : "";
|
|
3914
|
+
var readyMatch = fullText.match(/\[\[MATE_READY:\s*(.+?)\]\]/);
|
|
3915
|
+
if (readyMatch) {
|
|
3916
|
+
var newName = readyMatch[1].trim();
|
|
3917
|
+
dmTargetUser.displayName = newName;
|
|
3918
|
+
updateMateSidebarProfile({ profile: { displayName: newName, avatarColor: dmTargetUser.avatarColor, avatarStyle: dmTargetUser.avatarStyle, avatarSeed: dmTargetUser.avatarSeed } });
|
|
3919
|
+
if (ws && ws.readyState === 1) {
|
|
3920
|
+
ws.send(JSON.stringify({
|
|
3921
|
+
type: "mate_update",
|
|
3922
|
+
mateId: dmTargetUser.id,
|
|
3923
|
+
updates: { name: newName, status: "ready", profile: { displayName: newName } },
|
|
3924
|
+
}));
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
var walker = document.createTreeWalker(messagesEl, NodeFilter.SHOW_TEXT, null, false);
|
|
3928
|
+
var node;
|
|
3929
|
+
while (node = walker.nextNode()) {
|
|
3930
|
+
if (node.nodeValue.indexOf("[[MATE_READY:") !== -1) {
|
|
3931
|
+
node.nodeValue = node.nodeValue.replace(/\[\[MATE_READY:\s*.+?\]\]/g, "").trim();
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
}, 100);
|
|
4114
3935
|
}
|
|
4115
3936
|
}
|
|
4116
3937
|
|
|
@@ -4167,18 +3988,22 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4167
3988
|
break;
|
|
4168
3989
|
|
|
4169
3990
|
case "restore_mate_dm":
|
|
4170
|
-
if (msg.mateId) {
|
|
3991
|
+
if (msg.mateId && !returningFromMateDm) {
|
|
4171
3992
|
// Server-driven mate DM restore on reconnect
|
|
4172
3993
|
if (dmMode) {
|
|
4173
3994
|
dmMode = false;
|
|
4174
|
-
savedMainWs = null;
|
|
4175
|
-
mateWs = null;
|
|
4176
3995
|
document.body.classList.remove("mate-dm-active");
|
|
4177
3996
|
}
|
|
4178
|
-
pendingMateDmRestore = true;
|
|
4179
3997
|
messagesEl.innerHTML = "";
|
|
4180
3998
|
openDm(msg.mateId);
|
|
4181
3999
|
}
|
|
4000
|
+
// Clear the flag and notify server that mate DM is closed
|
|
4001
|
+
if (returningFromMateDm) {
|
|
4002
|
+
returningFromMateDm = false;
|
|
4003
|
+
if (ws && ws.readyState === 1) {
|
|
4004
|
+
try { ws.send(JSON.stringify({ type: "set_mate_dm", mateId: null })); } catch(e) {}
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4182
4007
|
break;
|
|
4183
4008
|
|
|
4184
4009
|
case "info":
|
|
@@ -4372,6 +4197,9 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4372
4197
|
break;
|
|
4373
4198
|
|
|
4374
4199
|
case "session_list":
|
|
4200
|
+
if (isMateDm) {
|
|
4201
|
+
renderMateSessionList(msg.sessions || []);
|
|
4202
|
+
}
|
|
4375
4203
|
renderSessionList(msg.sessions || []);
|
|
4376
4204
|
handlePaletteSessionSwitch();
|
|
4377
4205
|
break;
|
|
@@ -4931,7 +4759,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4931
4759
|
|
|
4932
4760
|
// --- DM ---
|
|
4933
4761
|
case "dm_history":
|
|
4934
|
-
pendingMateDmRestore = false; // DM data arrived, resume normal processing
|
|
4935
4762
|
// Attach projectSlug to targetUser for mate DMs
|
|
4936
4763
|
if (msg.projectSlug && msg.targetUser) {
|
|
4937
4764
|
msg.targetUser.projectSlug = msg.projectSlug;
|
|
@@ -4941,12 +4768,11 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
4941
4768
|
if (pendingMateInterview && msg.targetUser && msg.targetUser.isMate && msg.projectSlug) {
|
|
4942
4769
|
var interviewMate = pendingMateInterview;
|
|
4943
4770
|
pendingMateInterview = null;
|
|
4944
|
-
// Wait for
|
|
4771
|
+
// Wait for mate project WS to connect, then send interview prompt
|
|
4945
4772
|
var checkMateReady = setInterval(function () {
|
|
4946
|
-
if (ws && ws ===
|
|
4773
|
+
if (ws && ws.readyState === 1 && mateProjectSlug) {
|
|
4947
4774
|
clearInterval(checkMateReady);
|
|
4948
4775
|
var interviewText = buildMateInterviewPrompt(interviewMate);
|
|
4949
|
-
// Send through normal input flow (ws is now mateWs)
|
|
4950
4776
|
ws.send(JSON.stringify({ type: "message", text: interviewText }));
|
|
4951
4777
|
}
|
|
4952
4778
|
}, 100);
|
|
@@ -5008,13 +4834,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5008
4834
|
cachedMatesList = cachedMatesList.filter(function (m) { return m.id !== msg.mateId; });
|
|
5009
4835
|
if (msg.availableBuiltins) cachedAvailableBuiltins = msg.availableBuiltins;
|
|
5010
4836
|
renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers, cachedMatesList);
|
|
5011
|
-
// Clean up background WS for deleted mate
|
|
5012
|
-
var delSlug = "mate-" + msg.mateId;
|
|
5013
|
-
if (backgroundMateWs[delSlug]) {
|
|
5014
|
-
backgroundMateWs[delSlug].onclose = null;
|
|
5015
|
-
backgroundMateWs[delSlug].close();
|
|
5016
|
-
delete backgroundMateWs[delSlug];
|
|
5017
|
-
}
|
|
5018
4837
|
// If currently in DM with this mate, exit DM mode
|
|
5019
4838
|
if (dmMode && dmTargetUser && dmTargetUser.id === msg.mateId) {
|
|
5020
4839
|
exitDmMode();
|
|
@@ -5099,6 +4918,14 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5099
4918
|
showDebateSticky("preparing", msg);
|
|
5100
4919
|
break;
|
|
5101
4920
|
|
|
4921
|
+
case "debate_brief_ready":
|
|
4922
|
+
if (replayingHistory) {
|
|
4923
|
+
renderDebateBriefReady(msg);
|
|
4924
|
+
} else {
|
|
4925
|
+
handleDebateBriefReady(msg);
|
|
4926
|
+
}
|
|
4927
|
+
break;
|
|
4928
|
+
|
|
5102
4929
|
case "debate_started":
|
|
5103
4930
|
showDebateSticky("live", msg);
|
|
5104
4931
|
if (replayingHistory) {
|
|
@@ -5449,8 +5276,6 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
5449
5276
|
|
|
5450
5277
|
function scheduleReconnect() {
|
|
5451
5278
|
if (reconnectTimer) return;
|
|
5452
|
-
// Don't reconnect main WS while in mate DM
|
|
5453
|
-
if (savedMainWs) return;
|
|
5454
5279
|
reconnectTimer = setTimeout(function () {
|
|
5455
5280
|
reconnectTimer = null;
|
|
5456
5281
|
// Check if auth is still valid before reconnecting
|
|
@@ -6291,9 +6116,18 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
6291
6116
|
var debateBtn = document.getElementById("mate-debate-btn");
|
|
6292
6117
|
if (debateBtn) {
|
|
6293
6118
|
debateBtn.addEventListener("click", function () {
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6119
|
+
if (dmMode && dmTargetUser && dmTargetUser.isMate) {
|
|
6120
|
+
// Quick debate: moderator is the current DM mate, uses conversation context
|
|
6121
|
+
// Build messages with isMate flag for context extraction
|
|
6122
|
+
var contextMessages = dmMessageCache.map(function (m) {
|
|
6123
|
+
return { text: m.text, isMate: m.from !== myUserId };
|
|
6124
|
+
});
|
|
6125
|
+
openQuickDebateModal(contextMessages);
|
|
6126
|
+
} else {
|
|
6127
|
+
requireClayDebateSetup(function () {
|
|
6128
|
+
openDebateModal();
|
|
6129
|
+
});
|
|
6130
|
+
}
|
|
6297
6131
|
});
|
|
6298
6132
|
}
|
|
6299
6133
|
|