clay-server 2.18.0-beta.6 → 2.18.0-beta.8
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/public/app.js +228 -2
- package/lib/sdk-bridge.js +2 -2
- package/package.json +1 -1
package/lib/public/app.js
CHANGED
|
@@ -29,6 +29,7 @@ import { initMateWizard, openMateWizard, closeMateWizard, handleMateCreated } fr
|
|
|
29
29
|
import { initCommandPalette, handlePaletteSessionSwitch, setPaletteVersion } from './modules/command-palette.js';
|
|
30
30
|
import { initLongPress } from './modules/longpress.js';
|
|
31
31
|
import { initMention, handleMentionStart, handleMentionStream, handleMentionDone, handleMentionError, handleMentionActivity, renderMentionUser, renderMentionResponse } from './modules/mention.js';
|
|
32
|
+
import { initDebate, handleDebateStarted, handleDebateTurn, handleDebateActivity, handleDebateStream, handleDebateTurnDone, handleDebateCommentQueued, handleDebateCommentInjected, handleDebateEnded, handleDebateError, renderDebateStarted, renderDebateTurnDone, renderDebateEnded, renderDebateCommentInjected, openDebateModal, closeDebateModal } from './modules/debate.js';
|
|
32
33
|
|
|
33
34
|
// --- Base path for multi-project routing ---
|
|
34
35
|
var slugMatch = location.pathname.match(/^\/p\/([a-z0-9_-]+)/);
|
|
@@ -62,6 +63,7 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
62
63
|
|
|
63
64
|
// --- DM Mode ---
|
|
64
65
|
var dmMode = false;
|
|
66
|
+
var pendingMateDmRestore = false; // suppress regular history while restoring mate DM
|
|
65
67
|
var dmKey = null;
|
|
66
68
|
var dmTargetUser = null;
|
|
67
69
|
var dmUnread = {}; // { otherUserId: count }
|
|
@@ -741,6 +743,7 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
741
743
|
function exitDmMode() {
|
|
742
744
|
if (!dmMode) return;
|
|
743
745
|
dmMode = false;
|
|
746
|
+
pendingMateDmRestore = false;
|
|
744
747
|
dmKey = null;
|
|
745
748
|
dmTargetUser = null;
|
|
746
749
|
setCurrentDmUser(null);
|
|
@@ -3682,10 +3685,19 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
3682
3685
|
ws.send(JSON.stringify({ type: "mate_list" }));
|
|
3683
3686
|
} catch(e) {}
|
|
3684
3687
|
|
|
3685
|
-
// Restore mate DM after hard refresh
|
|
3688
|
+
// Restore mate DM after hard refresh or server restart
|
|
3686
3689
|
try {
|
|
3687
3690
|
var savedMateDm = localStorage.getItem("clay_active_mate_dm");
|
|
3688
|
-
if (savedMateDm
|
|
3691
|
+
if (savedMateDm) {
|
|
3692
|
+
// If dmMode is stale (server restarted while in mate DM), clean up first
|
|
3693
|
+
if (dmMode) {
|
|
3694
|
+
dmMode = false;
|
|
3695
|
+
savedMainWs = null;
|
|
3696
|
+
mateWs = null;
|
|
3697
|
+
document.body.classList.remove("mate-dm-active");
|
|
3698
|
+
}
|
|
3699
|
+
pendingMateDmRestore = true;
|
|
3700
|
+
messagesEl.innerHTML = ""; // prevent regular history flash
|
|
3689
3701
|
openDm(savedMateDm);
|
|
3690
3702
|
}
|
|
3691
3703
|
} catch(e) {}
|
|
@@ -3743,6 +3755,15 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
3743
3755
|
}
|
|
3744
3756
|
|
|
3745
3757
|
function processMessage(msg) {
|
|
3758
|
+
// Suppress regular project messages while restoring mate DM
|
|
3759
|
+
if (pendingMateDmRestore) {
|
|
3760
|
+
if (msg.type === "dm_history" || msg.type === "dm_list" || msg.type === "mate_list" || msg.type === "mate_created" || msg.type === "info") {
|
|
3761
|
+
// Let these through
|
|
3762
|
+
} else {
|
|
3763
|
+
return; // skip regular session messages
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
|
|
3746
3767
|
switch (msg.type) {
|
|
3747
3768
|
case "history_meta":
|
|
3748
3769
|
historyFrom = msg.from;
|
|
@@ -4507,6 +4528,7 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
4507
4528
|
|
|
4508
4529
|
// --- DM ---
|
|
4509
4530
|
case "dm_history":
|
|
4531
|
+
pendingMateDmRestore = false; // DM data arrived, resume normal processing
|
|
4510
4532
|
// Attach projectSlug to targetUser for mate DMs
|
|
4511
4533
|
if (msg.projectSlug && msg.targetUser) {
|
|
4512
4534
|
msg.targetUser.projectSlug = msg.projectSlug;
|
|
@@ -4662,6 +4684,51 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
4662
4684
|
renderMentionResponse(msg);
|
|
4663
4685
|
break;
|
|
4664
4686
|
|
|
4687
|
+
// --- Debate ---
|
|
4688
|
+
case "debate_preparing":
|
|
4689
|
+
showDebateSticky("preparing", msg);
|
|
4690
|
+
break;
|
|
4691
|
+
|
|
4692
|
+
case "debate_started":
|
|
4693
|
+
showDebateSticky("live", msg);
|
|
4694
|
+
handleDebateStarted(msg);
|
|
4695
|
+
break;
|
|
4696
|
+
|
|
4697
|
+
case "debate_turn":
|
|
4698
|
+
handleDebateTurn(msg);
|
|
4699
|
+
if (msg.round) updateDebateRound(msg.round);
|
|
4700
|
+
break;
|
|
4701
|
+
|
|
4702
|
+
case "debate_activity":
|
|
4703
|
+
handleDebateActivity(msg);
|
|
4704
|
+
break;
|
|
4705
|
+
|
|
4706
|
+
case "debate_stream":
|
|
4707
|
+
handleDebateStream(msg);
|
|
4708
|
+
break;
|
|
4709
|
+
|
|
4710
|
+
case "debate_turn_done":
|
|
4711
|
+
handleDebateTurnDone(msg);
|
|
4712
|
+
break;
|
|
4713
|
+
|
|
4714
|
+
case "debate_comment_queued":
|
|
4715
|
+
handleDebateCommentQueued(msg);
|
|
4716
|
+
break;
|
|
4717
|
+
|
|
4718
|
+
case "debate_comment_injected":
|
|
4719
|
+
handleDebateCommentInjected(msg);
|
|
4720
|
+
break;
|
|
4721
|
+
|
|
4722
|
+
case "debate_ended":
|
|
4723
|
+
showDebateSticky("ended", msg);
|
|
4724
|
+
handleDebateEnded(msg);
|
|
4725
|
+
break;
|
|
4726
|
+
|
|
4727
|
+
case "debate_error":
|
|
4728
|
+
handleDebateError(msg);
|
|
4729
|
+
if (msg.error) showToast("Debate: " + msg.error, "error");
|
|
4730
|
+
break;
|
|
4731
|
+
|
|
4665
4732
|
case "daemon_config":
|
|
4666
4733
|
updateDaemonConfig(msg.config);
|
|
4667
4734
|
break;
|
|
@@ -4994,6 +5061,16 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
4994
5061
|
addCopyHandler: addCopyHandler,
|
|
4995
5062
|
});
|
|
4996
5063
|
|
|
5064
|
+
// --- Debate module ---
|
|
5065
|
+
initDebate({
|
|
5066
|
+
get ws() { return ws; },
|
|
5067
|
+
messagesEl: messagesEl,
|
|
5068
|
+
scrollToBottom: scrollToBottom,
|
|
5069
|
+
addCopyHandler: addCopyHandler,
|
|
5070
|
+
matesList: function () { return cachedMatesList || []; },
|
|
5071
|
+
currentMateId: function () { return (dmTargetUser && dmTargetUser.isMate) ? dmTargetUser.id : null; },
|
|
5072
|
+
});
|
|
5073
|
+
|
|
4997
5074
|
// --- STT module (voice input via Web Speech API) ---
|
|
4998
5075
|
initSTT({
|
|
4999
5076
|
inputEl: inputEl,
|
|
@@ -5485,6 +5562,13 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
5485
5562
|
updateLoopBanner(loopIteration, loopMaxIterations, "running");
|
|
5486
5563
|
}
|
|
5487
5564
|
}
|
|
5565
|
+
|
|
5566
|
+
// Restore debate sticky on session switch
|
|
5567
|
+
if (debateStickyState && debateStickyState.phase) {
|
|
5568
|
+
showDebateSticky(debateStickyState.phase, debateStickyState.msg);
|
|
5569
|
+
} else {
|
|
5570
|
+
showDebateSticky("hide", null);
|
|
5571
|
+
}
|
|
5488
5572
|
}
|
|
5489
5573
|
|
|
5490
5574
|
// --- Skill install dialog (generic) ---
|
|
@@ -5713,6 +5797,24 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
5713
5797
|
}, cb);
|
|
5714
5798
|
}
|
|
5715
5799
|
|
|
5800
|
+
function requireClayDebateSetup(cb) {
|
|
5801
|
+
requireSkills({
|
|
5802
|
+
title: "Skill Installation Required",
|
|
5803
|
+
reason: "The Debate Setup skill is required to start a debate.",
|
|
5804
|
+
skills: [{ name: "clay-debate-setup", url: "https://github.com/chadbyte/clay-debate-setup", scope: "global" }]
|
|
5805
|
+
}, cb);
|
|
5806
|
+
}
|
|
5807
|
+
|
|
5808
|
+
// Debate button in mate sidebar
|
|
5809
|
+
var debateBtn = document.getElementById("mate-debate-btn");
|
|
5810
|
+
if (debateBtn) {
|
|
5811
|
+
debateBtn.addEventListener("click", function () {
|
|
5812
|
+
requireClayDebateSetup(function () {
|
|
5813
|
+
openDebateModal();
|
|
5814
|
+
});
|
|
5815
|
+
});
|
|
5816
|
+
}
|
|
5817
|
+
|
|
5716
5818
|
// --- Ralph Wizard ---
|
|
5717
5819
|
|
|
5718
5820
|
var wizardMode = "draft"; // "draft" or "own"
|
|
@@ -6160,6 +6262,130 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
6160
6262
|
}
|
|
6161
6263
|
}
|
|
6162
6264
|
|
|
6265
|
+
// --- Debate Sticky Banner ---
|
|
6266
|
+
var debateStickyState = null;
|
|
6267
|
+
var debateHandRaiseOpen = false;
|
|
6268
|
+
|
|
6269
|
+
function showDebateSticky(phase, msg) {
|
|
6270
|
+
if (phase === "ended" || phase === "hide") {
|
|
6271
|
+
debateStickyState = null;
|
|
6272
|
+
} else {
|
|
6273
|
+
debateStickyState = { phase: phase, msg: msg };
|
|
6274
|
+
}
|
|
6275
|
+
var stickyEl = document.getElementById("debate-sticky");
|
|
6276
|
+
if (!stickyEl) return;
|
|
6277
|
+
|
|
6278
|
+
if (phase === "ended" || phase === "hide") {
|
|
6279
|
+
stickyEl.classList.add("hidden");
|
|
6280
|
+
stickyEl.innerHTML = "";
|
|
6281
|
+
debateHandRaiseOpen = false;
|
|
6282
|
+
return;
|
|
6283
|
+
}
|
|
6284
|
+
|
|
6285
|
+
var topic = (msg && msg.topic) || "Debate";
|
|
6286
|
+
var truncTopic = topic.length > 30 ? topic.slice(0, 30) + "\u2026" : topic;
|
|
6287
|
+
|
|
6288
|
+
if (phase === "preparing") {
|
|
6289
|
+
stickyEl.innerHTML =
|
|
6290
|
+
'<div class="debate-sticky-inner">' +
|
|
6291
|
+
'<div class="debate-sticky-header">' +
|
|
6292
|
+
'<span class="debate-sticky-icon">' + iconHtml("mic") + '</span>' +
|
|
6293
|
+
'<span class="debate-sticky-label">' + escapeHtml(truncTopic) + '</span>' +
|
|
6294
|
+
'<span class="debate-sticky-status" id="debate-sticky-status">Setting up\u2026</span>' +
|
|
6295
|
+
'<button class="debate-sticky-action debate-sticky-cancel" title="Cancel debate">' + iconHtml("x") + '</button>' +
|
|
6296
|
+
'</div>' +
|
|
6297
|
+
'</div>';
|
|
6298
|
+
stickyEl.classList.remove("hidden");
|
|
6299
|
+
stickyEl.className = "debate-sticky preparing";
|
|
6300
|
+
refreshIcons();
|
|
6301
|
+
|
|
6302
|
+
stickyEl.querySelector(".debate-sticky-cancel").addEventListener("click", function (e) {
|
|
6303
|
+
e.stopPropagation();
|
|
6304
|
+
if (ws && ws.readyState === 1) {
|
|
6305
|
+
ws.send(JSON.stringify({ type: "debate_stop" }));
|
|
6306
|
+
}
|
|
6307
|
+
stickyEl.classList.add("hidden");
|
|
6308
|
+
stickyEl.innerHTML = "";
|
|
6309
|
+
});
|
|
6310
|
+
} else if (phase === "live") {
|
|
6311
|
+
stickyEl.innerHTML =
|
|
6312
|
+
'<div class="debate-sticky-inner">' +
|
|
6313
|
+
'<div class="debate-sticky-header">' +
|
|
6314
|
+
'<span class="debate-sticky-icon">' + iconHtml("mic") + '</span>' +
|
|
6315
|
+
'<span class="debate-sticky-label">' + escapeHtml(truncTopic) + '</span>' +
|
|
6316
|
+
'<span class="debate-sticky-status" id="debate-sticky-status">Live</span>' +
|
|
6317
|
+
'<span class="debate-sticky-round" id="debate-sticky-round">R1</span>' +
|
|
6318
|
+
'<button class="debate-sticky-action debate-sticky-hand" title="Raise hand">' + iconHtml("hand") + '</button>' +
|
|
6319
|
+
'<button class="debate-sticky-action debate-sticky-stop" title="Stop debate">' + iconHtml("square") + '</button>' +
|
|
6320
|
+
'</div>' +
|
|
6321
|
+
'<div class="debate-sticky-hand-input hidden" id="debate-sticky-hand-input">' +
|
|
6322
|
+
'<textarea id="debate-sticky-comment" rows="1" placeholder="Your comment\u2026"></textarea>' +
|
|
6323
|
+
'<button class="debate-sticky-send" id="debate-sticky-send">Send</button>' +
|
|
6324
|
+
'<button class="debate-sticky-send-cancel" id="debate-sticky-send-cancel">Cancel</button>' +
|
|
6325
|
+
'</div>' +
|
|
6326
|
+
'</div>';
|
|
6327
|
+
stickyEl.classList.remove("hidden");
|
|
6328
|
+
stickyEl.className = "debate-sticky live";
|
|
6329
|
+
refreshIcons();
|
|
6330
|
+
debateHandRaiseOpen = false;
|
|
6331
|
+
|
|
6332
|
+
stickyEl.querySelector(".debate-sticky-hand").addEventListener("click", function (e) {
|
|
6333
|
+
e.stopPropagation();
|
|
6334
|
+
toggleDebateHandRaise();
|
|
6335
|
+
});
|
|
6336
|
+
|
|
6337
|
+
stickyEl.querySelector(".debate-sticky-stop").addEventListener("click", function (e) {
|
|
6338
|
+
e.stopPropagation();
|
|
6339
|
+
if (ws && ws.readyState === 1) {
|
|
6340
|
+
ws.send(JSON.stringify({ type: "debate_stop" }));
|
|
6341
|
+
}
|
|
6342
|
+
});
|
|
6343
|
+
|
|
6344
|
+
var sendBtn = document.getElementById("debate-sticky-send");
|
|
6345
|
+
var cancelBtn = document.getElementById("debate-sticky-send-cancel");
|
|
6346
|
+
var commentInput = document.getElementById("debate-sticky-comment");
|
|
6347
|
+
|
|
6348
|
+
if (sendBtn) sendBtn.addEventListener("click", function () { sendDebateStickyComment(); });
|
|
6349
|
+
if (cancelBtn) cancelBtn.addEventListener("click", function () { toggleDebateHandRaise(false); });
|
|
6350
|
+
if (commentInput) {
|
|
6351
|
+
commentInput.addEventListener("keydown", function (e) {
|
|
6352
|
+
if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); sendDebateStickyComment(); }
|
|
6353
|
+
if (e.key === "Escape") { toggleDebateHandRaise(false); }
|
|
6354
|
+
});
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
}
|
|
6358
|
+
|
|
6359
|
+
function toggleDebateHandRaise(forceState) {
|
|
6360
|
+
var inputWrap = document.getElementById("debate-sticky-hand-input");
|
|
6361
|
+
var commentInput = document.getElementById("debate-sticky-comment");
|
|
6362
|
+
if (!inputWrap) return;
|
|
6363
|
+
var show = typeof forceState === "boolean" ? forceState : !debateHandRaiseOpen;
|
|
6364
|
+
debateHandRaiseOpen = show;
|
|
6365
|
+
if (show) {
|
|
6366
|
+
inputWrap.classList.remove("hidden");
|
|
6367
|
+
if (commentInput) { commentInput.value = ""; commentInput.focus(); }
|
|
6368
|
+
} else {
|
|
6369
|
+
inputWrap.classList.add("hidden");
|
|
6370
|
+
}
|
|
6371
|
+
}
|
|
6372
|
+
|
|
6373
|
+
function sendDebateStickyComment() {
|
|
6374
|
+
var commentInput = document.getElementById("debate-sticky-comment");
|
|
6375
|
+
if (!commentInput) return;
|
|
6376
|
+
var text = commentInput.value.trim();
|
|
6377
|
+
if (!text) return;
|
|
6378
|
+
if (ws && ws.readyState === 1) {
|
|
6379
|
+
ws.send(JSON.stringify({ type: "debate_comment", text: text }));
|
|
6380
|
+
}
|
|
6381
|
+
toggleDebateHandRaise(false);
|
|
6382
|
+
}
|
|
6383
|
+
|
|
6384
|
+
function updateDebateRound(round) {
|
|
6385
|
+
var roundEl = document.getElementById("debate-sticky-round");
|
|
6386
|
+
if (roundEl) roundEl.textContent = "R" + round;
|
|
6387
|
+
}
|
|
6388
|
+
|
|
6163
6389
|
// --- Ralph Preview Modal ---
|
|
6164
6390
|
function openRalphPreviewModal() {
|
|
6165
6391
|
var modal = document.getElementById("ralph-preview-modal");
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -1118,7 +1118,7 @@ function createSDKBridge(opts) {
|
|
|
1118
1118
|
|
|
1119
1119
|
// Mate sessions (DM): auto-approve read-only tools
|
|
1120
1120
|
if (isMate || mateDisplayName) {
|
|
1121
|
-
var mateReadTools = { Read: true, Glob: true, Grep: true };
|
|
1121
|
+
var mateReadTools = { Read: true, Glob: true, Grep: true, WebFetch: true, WebSearch: true };
|
|
1122
1122
|
if (mateReadTools[toolName]) {
|
|
1123
1123
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1124
1124
|
}
|
|
@@ -1775,7 +1775,7 @@ function createSDKBridge(opts) {
|
|
|
1775
1775
|
includePartialMessages: true,
|
|
1776
1776
|
abortController: abortController,
|
|
1777
1777
|
canUseTool: opts.canUseTool || function (toolName, input) {
|
|
1778
|
-
var allowed = { Read: true, Glob: true, Grep: true };
|
|
1778
|
+
var allowed = { Read: true, Glob: true, Grep: true, WebFetch: true };
|
|
1779
1779
|
if (allowed[toolName]) {
|
|
1780
1780
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1781
1781
|
}
|