clay-server 2.18.0-beta.7 → 2.18.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/public/app.js +243 -4
- package/lib/sdk-bridge.js +4 -4
- 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_-]+)/);
|
|
@@ -907,6 +908,13 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
907
908
|
var mateSessionDot = document.querySelector(".mate-session-item.active .session-processing");
|
|
908
909
|
if (mateSessionDot) mateSessionDot.style.display = "none";
|
|
909
910
|
}
|
|
911
|
+
// Handle skill_installed in mate DM context (for skill install modal)
|
|
912
|
+
if (msg.type === "skill_installed") {
|
|
913
|
+
handleSkillInstalled(msg);
|
|
914
|
+
if (msg.success) knownInstalledSkills[msg.skill] = true;
|
|
915
|
+
handleSkillInstallWs(msg);
|
|
916
|
+
}
|
|
917
|
+
|
|
910
918
|
// Intercept session_list for mate sidebar
|
|
911
919
|
if (msg.type === "init" && msg.sessions) {
|
|
912
920
|
renderMateSessionList(msg.sessions);
|
|
@@ -3684,10 +3692,25 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
3684
3692
|
ws.send(JSON.stringify({ type: "mate_list" }));
|
|
3685
3693
|
} catch(e) {}
|
|
3686
3694
|
|
|
3687
|
-
// Restore
|
|
3695
|
+
// Restore the last active session for this project (overrides server global)
|
|
3696
|
+
try {
|
|
3697
|
+
var savedSessionId = localStorage.getItem("clay_active_session_" + basePath);
|
|
3698
|
+
if (savedSessionId) {
|
|
3699
|
+
ws.send(JSON.stringify({ type: "switch_session", id: parseInt(savedSessionId, 10) }));
|
|
3700
|
+
}
|
|
3701
|
+
} catch(e) {}
|
|
3702
|
+
|
|
3703
|
+
// Restore mate DM after hard refresh or server restart
|
|
3688
3704
|
try {
|
|
3689
3705
|
var savedMateDm = localStorage.getItem("clay_active_mate_dm");
|
|
3690
|
-
if (savedMateDm
|
|
3706
|
+
if (savedMateDm) {
|
|
3707
|
+
// If dmMode is stale (server restarted while in mate DM), clean up first
|
|
3708
|
+
if (dmMode) {
|
|
3709
|
+
dmMode = false;
|
|
3710
|
+
savedMainWs = null;
|
|
3711
|
+
mateWs = null;
|
|
3712
|
+
document.body.classList.remove("mate-dm-active");
|
|
3713
|
+
}
|
|
3691
3714
|
pendingMateDmRestore = true;
|
|
3692
3715
|
messagesEl.innerHTML = ""; // prevent regular history flash
|
|
3693
3716
|
openDm(savedMateDm);
|
|
@@ -3729,8 +3752,18 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
3729
3752
|
};
|
|
3730
3753
|
|
|
3731
3754
|
ws.onmessage = function (event) {
|
|
3732
|
-
// If this WS is stashed while in mate DM,
|
|
3733
|
-
if (savedMainWs === this)
|
|
3755
|
+
// If this WS is stashed while in mate DM, only allow skill_installed through
|
|
3756
|
+
if (savedMainWs === this) {
|
|
3757
|
+
try {
|
|
3758
|
+
var stashedMsg = JSON.parse(event.data);
|
|
3759
|
+
if (stashedMsg.type === "skill_installed") {
|
|
3760
|
+
handleSkillInstalled(stashedMsg);
|
|
3761
|
+
if (stashedMsg.success) knownInstalledSkills[stashedMsg.skill] = true;
|
|
3762
|
+
handleSkillInstallWs(stashedMsg);
|
|
3763
|
+
}
|
|
3764
|
+
} catch (e) {}
|
|
3765
|
+
return;
|
|
3766
|
+
}
|
|
3734
3767
|
|
|
3735
3768
|
// Backup: if we're receiving messages, we're connected
|
|
3736
3769
|
if (!connected) {
|
|
@@ -4048,6 +4081,8 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
4048
4081
|
}
|
|
4049
4082
|
activeSessionId = msg.id;
|
|
4050
4083
|
cliSessionId = msg.cliSessionId || null;
|
|
4084
|
+
// Persist active session per project so reconnect restores it
|
|
4085
|
+
try { localStorage.setItem("clay_active_session_" + basePath, String(msg.id)); } catch(e) {}
|
|
4051
4086
|
clearRemoteCursors();
|
|
4052
4087
|
resetClientState();
|
|
4053
4088
|
updateRalphBars();
|
|
@@ -4676,6 +4711,51 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
4676
4711
|
renderMentionResponse(msg);
|
|
4677
4712
|
break;
|
|
4678
4713
|
|
|
4714
|
+
// --- Debate ---
|
|
4715
|
+
case "debate_preparing":
|
|
4716
|
+
showDebateSticky("preparing", msg);
|
|
4717
|
+
break;
|
|
4718
|
+
|
|
4719
|
+
case "debate_started":
|
|
4720
|
+
showDebateSticky("live", msg);
|
|
4721
|
+
handleDebateStarted(msg);
|
|
4722
|
+
break;
|
|
4723
|
+
|
|
4724
|
+
case "debate_turn":
|
|
4725
|
+
handleDebateTurn(msg);
|
|
4726
|
+
if (msg.round) updateDebateRound(msg.round);
|
|
4727
|
+
break;
|
|
4728
|
+
|
|
4729
|
+
case "debate_activity":
|
|
4730
|
+
handleDebateActivity(msg);
|
|
4731
|
+
break;
|
|
4732
|
+
|
|
4733
|
+
case "debate_stream":
|
|
4734
|
+
handleDebateStream(msg);
|
|
4735
|
+
break;
|
|
4736
|
+
|
|
4737
|
+
case "debate_turn_done":
|
|
4738
|
+
handleDebateTurnDone(msg);
|
|
4739
|
+
break;
|
|
4740
|
+
|
|
4741
|
+
case "debate_comment_queued":
|
|
4742
|
+
handleDebateCommentQueued(msg);
|
|
4743
|
+
break;
|
|
4744
|
+
|
|
4745
|
+
case "debate_comment_injected":
|
|
4746
|
+
handleDebateCommentInjected(msg);
|
|
4747
|
+
break;
|
|
4748
|
+
|
|
4749
|
+
case "debate_ended":
|
|
4750
|
+
showDebateSticky("ended", msg);
|
|
4751
|
+
handleDebateEnded(msg);
|
|
4752
|
+
break;
|
|
4753
|
+
|
|
4754
|
+
case "debate_error":
|
|
4755
|
+
handleDebateError(msg);
|
|
4756
|
+
if (msg.error) showToast("Debate: " + msg.error, "error");
|
|
4757
|
+
break;
|
|
4758
|
+
|
|
4679
4759
|
case "daemon_config":
|
|
4680
4760
|
updateDaemonConfig(msg.config);
|
|
4681
4761
|
break;
|
|
@@ -5008,6 +5088,16 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
5008
5088
|
addCopyHandler: addCopyHandler,
|
|
5009
5089
|
});
|
|
5010
5090
|
|
|
5091
|
+
// --- Debate module ---
|
|
5092
|
+
initDebate({
|
|
5093
|
+
get ws() { return ws; },
|
|
5094
|
+
messagesEl: messagesEl,
|
|
5095
|
+
scrollToBottom: scrollToBottom,
|
|
5096
|
+
addCopyHandler: addCopyHandler,
|
|
5097
|
+
matesList: function () { return cachedMatesList || []; },
|
|
5098
|
+
currentMateId: function () { return (dmTargetUser && dmTargetUser.isMate) ? dmTargetUser.id : null; },
|
|
5099
|
+
});
|
|
5100
|
+
|
|
5011
5101
|
// --- STT module (voice input via Web Speech API) ---
|
|
5012
5102
|
initSTT({
|
|
5013
5103
|
inputEl: inputEl,
|
|
@@ -5499,6 +5589,13 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
5499
5589
|
updateLoopBanner(loopIteration, loopMaxIterations, "running");
|
|
5500
5590
|
}
|
|
5501
5591
|
}
|
|
5592
|
+
|
|
5593
|
+
// Restore debate sticky on session switch
|
|
5594
|
+
if (debateStickyState && debateStickyState.phase) {
|
|
5595
|
+
showDebateSticky(debateStickyState.phase, debateStickyState.msg);
|
|
5596
|
+
} else {
|
|
5597
|
+
showDebateSticky("hide", null);
|
|
5598
|
+
}
|
|
5502
5599
|
}
|
|
5503
5600
|
|
|
5504
5601
|
// --- Skill install dialog (generic) ---
|
|
@@ -5727,6 +5824,24 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
5727
5824
|
}, cb);
|
|
5728
5825
|
}
|
|
5729
5826
|
|
|
5827
|
+
function requireClayDebateSetup(cb) {
|
|
5828
|
+
requireSkills({
|
|
5829
|
+
title: "Skill Installation Required",
|
|
5830
|
+
reason: "The Debate Setup skill is required to start a debate.",
|
|
5831
|
+
skills: [{ name: "clay-debate-setup", url: "https://github.com/chadbyte/clay-debate-setup", scope: "global" }]
|
|
5832
|
+
}, cb);
|
|
5833
|
+
}
|
|
5834
|
+
|
|
5835
|
+
// Debate button in mate sidebar
|
|
5836
|
+
var debateBtn = document.getElementById("mate-debate-btn");
|
|
5837
|
+
if (debateBtn) {
|
|
5838
|
+
debateBtn.addEventListener("click", function () {
|
|
5839
|
+
requireClayDebateSetup(function () {
|
|
5840
|
+
openDebateModal();
|
|
5841
|
+
});
|
|
5842
|
+
});
|
|
5843
|
+
}
|
|
5844
|
+
|
|
5730
5845
|
// --- Ralph Wizard ---
|
|
5731
5846
|
|
|
5732
5847
|
var wizardMode = "draft"; // "draft" or "own"
|
|
@@ -6174,6 +6289,130 @@ import { initMention, handleMentionStart, handleMentionStream, handleMentionDone
|
|
|
6174
6289
|
}
|
|
6175
6290
|
}
|
|
6176
6291
|
|
|
6292
|
+
// --- Debate Sticky Banner ---
|
|
6293
|
+
var debateStickyState = null;
|
|
6294
|
+
var debateHandRaiseOpen = false;
|
|
6295
|
+
|
|
6296
|
+
function showDebateSticky(phase, msg) {
|
|
6297
|
+
if (phase === "ended" || phase === "hide") {
|
|
6298
|
+
debateStickyState = null;
|
|
6299
|
+
} else {
|
|
6300
|
+
debateStickyState = { phase: phase, msg: msg };
|
|
6301
|
+
}
|
|
6302
|
+
var stickyEl = document.getElementById("debate-sticky");
|
|
6303
|
+
if (!stickyEl) return;
|
|
6304
|
+
|
|
6305
|
+
if (phase === "ended" || phase === "hide") {
|
|
6306
|
+
stickyEl.classList.add("hidden");
|
|
6307
|
+
stickyEl.innerHTML = "";
|
|
6308
|
+
debateHandRaiseOpen = false;
|
|
6309
|
+
return;
|
|
6310
|
+
}
|
|
6311
|
+
|
|
6312
|
+
var topic = (msg && msg.topic) || "Debate";
|
|
6313
|
+
var truncTopic = topic.length > 30 ? topic.slice(0, 30) + "\u2026" : topic;
|
|
6314
|
+
|
|
6315
|
+
if (phase === "preparing") {
|
|
6316
|
+
stickyEl.innerHTML =
|
|
6317
|
+
'<div class="debate-sticky-inner">' +
|
|
6318
|
+
'<div class="debate-sticky-header">' +
|
|
6319
|
+
'<span class="debate-sticky-icon">' + iconHtml("mic") + '</span>' +
|
|
6320
|
+
'<span class="debate-sticky-label">' + escapeHtml(truncTopic) + '</span>' +
|
|
6321
|
+
'<span class="debate-sticky-status" id="debate-sticky-status">Setting up\u2026</span>' +
|
|
6322
|
+
'<button class="debate-sticky-action debate-sticky-cancel" title="Cancel debate">' + iconHtml("x") + '</button>' +
|
|
6323
|
+
'</div>' +
|
|
6324
|
+
'</div>';
|
|
6325
|
+
stickyEl.classList.remove("hidden");
|
|
6326
|
+
stickyEl.className = "debate-sticky preparing";
|
|
6327
|
+
refreshIcons();
|
|
6328
|
+
|
|
6329
|
+
stickyEl.querySelector(".debate-sticky-cancel").addEventListener("click", function (e) {
|
|
6330
|
+
e.stopPropagation();
|
|
6331
|
+
if (ws && ws.readyState === 1) {
|
|
6332
|
+
ws.send(JSON.stringify({ type: "debate_stop" }));
|
|
6333
|
+
}
|
|
6334
|
+
stickyEl.classList.add("hidden");
|
|
6335
|
+
stickyEl.innerHTML = "";
|
|
6336
|
+
});
|
|
6337
|
+
} else if (phase === "live") {
|
|
6338
|
+
stickyEl.innerHTML =
|
|
6339
|
+
'<div class="debate-sticky-inner">' +
|
|
6340
|
+
'<div class="debate-sticky-header">' +
|
|
6341
|
+
'<span class="debate-sticky-icon">' + iconHtml("mic") + '</span>' +
|
|
6342
|
+
'<span class="debate-sticky-label">' + escapeHtml(truncTopic) + '</span>' +
|
|
6343
|
+
'<span class="debate-sticky-status" id="debate-sticky-status">Live</span>' +
|
|
6344
|
+
'<span class="debate-sticky-round" id="debate-sticky-round">R1</span>' +
|
|
6345
|
+
'<button class="debate-sticky-action debate-sticky-hand" title="Raise hand">' + iconHtml("hand") + '</button>' +
|
|
6346
|
+
'<button class="debate-sticky-action debate-sticky-stop" title="Stop debate">' + iconHtml("square") + '</button>' +
|
|
6347
|
+
'</div>' +
|
|
6348
|
+
'<div class="debate-sticky-hand-input hidden" id="debate-sticky-hand-input">' +
|
|
6349
|
+
'<textarea id="debate-sticky-comment" rows="1" placeholder="Your comment\u2026"></textarea>' +
|
|
6350
|
+
'<button class="debate-sticky-send" id="debate-sticky-send">Send</button>' +
|
|
6351
|
+
'<button class="debate-sticky-send-cancel" id="debate-sticky-send-cancel">Cancel</button>' +
|
|
6352
|
+
'</div>' +
|
|
6353
|
+
'</div>';
|
|
6354
|
+
stickyEl.classList.remove("hidden");
|
|
6355
|
+
stickyEl.className = "debate-sticky live";
|
|
6356
|
+
refreshIcons();
|
|
6357
|
+
debateHandRaiseOpen = false;
|
|
6358
|
+
|
|
6359
|
+
stickyEl.querySelector(".debate-sticky-hand").addEventListener("click", function (e) {
|
|
6360
|
+
e.stopPropagation();
|
|
6361
|
+
toggleDebateHandRaise();
|
|
6362
|
+
});
|
|
6363
|
+
|
|
6364
|
+
stickyEl.querySelector(".debate-sticky-stop").addEventListener("click", function (e) {
|
|
6365
|
+
e.stopPropagation();
|
|
6366
|
+
if (ws && ws.readyState === 1) {
|
|
6367
|
+
ws.send(JSON.stringify({ type: "debate_stop" }));
|
|
6368
|
+
}
|
|
6369
|
+
});
|
|
6370
|
+
|
|
6371
|
+
var sendBtn = document.getElementById("debate-sticky-send");
|
|
6372
|
+
var cancelBtn = document.getElementById("debate-sticky-send-cancel");
|
|
6373
|
+
var commentInput = document.getElementById("debate-sticky-comment");
|
|
6374
|
+
|
|
6375
|
+
if (sendBtn) sendBtn.addEventListener("click", function () { sendDebateStickyComment(); });
|
|
6376
|
+
if (cancelBtn) cancelBtn.addEventListener("click", function () { toggleDebateHandRaise(false); });
|
|
6377
|
+
if (commentInput) {
|
|
6378
|
+
commentInput.addEventListener("keydown", function (e) {
|
|
6379
|
+
if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); sendDebateStickyComment(); }
|
|
6380
|
+
if (e.key === "Escape") { toggleDebateHandRaise(false); }
|
|
6381
|
+
});
|
|
6382
|
+
}
|
|
6383
|
+
}
|
|
6384
|
+
}
|
|
6385
|
+
|
|
6386
|
+
function toggleDebateHandRaise(forceState) {
|
|
6387
|
+
var inputWrap = document.getElementById("debate-sticky-hand-input");
|
|
6388
|
+
var commentInput = document.getElementById("debate-sticky-comment");
|
|
6389
|
+
if (!inputWrap) return;
|
|
6390
|
+
var show = typeof forceState === "boolean" ? forceState : !debateHandRaiseOpen;
|
|
6391
|
+
debateHandRaiseOpen = show;
|
|
6392
|
+
if (show) {
|
|
6393
|
+
inputWrap.classList.remove("hidden");
|
|
6394
|
+
if (commentInput) { commentInput.value = ""; commentInput.focus(); }
|
|
6395
|
+
} else {
|
|
6396
|
+
inputWrap.classList.add("hidden");
|
|
6397
|
+
}
|
|
6398
|
+
}
|
|
6399
|
+
|
|
6400
|
+
function sendDebateStickyComment() {
|
|
6401
|
+
var commentInput = document.getElementById("debate-sticky-comment");
|
|
6402
|
+
if (!commentInput) return;
|
|
6403
|
+
var text = commentInput.value.trim();
|
|
6404
|
+
if (!text) return;
|
|
6405
|
+
if (ws && ws.readyState === 1) {
|
|
6406
|
+
ws.send(JSON.stringify({ type: "debate_comment", text: text }));
|
|
6407
|
+
}
|
|
6408
|
+
toggleDebateHandRaise(false);
|
|
6409
|
+
}
|
|
6410
|
+
|
|
6411
|
+
function updateDebateRound(round) {
|
|
6412
|
+
var roundEl = document.getElementById("debate-sticky-round");
|
|
6413
|
+
if (roundEl) roundEl.textContent = "R" + round;
|
|
6414
|
+
}
|
|
6415
|
+
|
|
6177
6416
|
// --- Ralph Preview Modal ---
|
|
6178
6417
|
function openRalphPreviewModal() {
|
|
6179
6418
|
var modal = document.getElementById("ralph-preview-modal");
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -1116,10 +1116,10 @@ function createSDKBridge(opts) {
|
|
|
1116
1116
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1117
1117
|
}
|
|
1118
1118
|
|
|
1119
|
-
// Mate sessions (DM): auto-approve read
|
|
1119
|
+
// Mate sessions (DM, debate, mention): auto-approve read + fetch tools
|
|
1120
1120
|
if (isMate || mateDisplayName) {
|
|
1121
|
-
var
|
|
1122
|
-
if (
|
|
1121
|
+
var mateAutoTools = { Read: true, Glob: true, Grep: true, WebFetch: true, WebSearch: true };
|
|
1122
|
+
if (mateAutoTools[toolName]) {
|
|
1123
1123
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1124
1124
|
}
|
|
1125
1125
|
}
|
|
@@ -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, WebSearch: true };
|
|
1779
1779
|
if (allowed[toolName]) {
|
|
1780
1780
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
1781
1781
|
}
|