clay-server 2.27.0-beta.8 → 2.27.0

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.
Files changed (72) hide show
  1. package/README.md +10 -0
  2. package/lib/daemon-projects.js +164 -0
  3. package/lib/daemon.js +13 -126
  4. package/lib/mates-identity.js +132 -0
  5. package/lib/mates-knowledge.js +113 -0
  6. package/lib/mates-prompts.js +398 -0
  7. package/lib/mates.js +40 -599
  8. package/lib/project-connection.js +2 -0
  9. package/lib/project-debate.js +19 -12
  10. package/lib/project-http.js +4 -2
  11. package/lib/project-loop.js +110 -48
  12. package/lib/project-mate-interaction.js +4 -0
  13. package/lib/project-notifications.js +210 -0
  14. package/lib/project-sessions.js +5 -2
  15. package/lib/project-user-message.js +2 -1
  16. package/lib/project.js +26 -2
  17. package/lib/public/app.js +1193 -8521
  18. package/lib/public/css/command-palette.css +14 -0
  19. package/lib/public/css/loop.css +301 -0
  20. package/lib/public/css/notifications-center.css +190 -0
  21. package/lib/public/css/rewind.css +6 -0
  22. package/lib/public/index.html +89 -35
  23. package/lib/public/modules/app-connection.js +160 -0
  24. package/lib/public/modules/app-cursors.js +473 -0
  25. package/lib/public/modules/app-debate-ui.js +389 -0
  26. package/lib/public/modules/app-dm.js +627 -0
  27. package/lib/public/modules/app-favicon.js +212 -0
  28. package/lib/public/modules/app-header.js +229 -0
  29. package/lib/public/modules/app-home-hub.js +600 -0
  30. package/lib/public/modules/app-loop-ui.js +589 -0
  31. package/lib/public/modules/app-loop-wizard.js +439 -0
  32. package/lib/public/modules/app-messages.js +1560 -0
  33. package/lib/public/modules/app-misc.js +299 -0
  34. package/lib/public/modules/app-notifications.js +372 -0
  35. package/lib/public/modules/app-panels.js +888 -0
  36. package/lib/public/modules/app-projects.js +798 -0
  37. package/lib/public/modules/app-rate-limit.js +451 -0
  38. package/lib/public/modules/app-rendering.js +597 -0
  39. package/lib/public/modules/app-skills-install.js +234 -0
  40. package/lib/public/modules/command-palette.js +27 -4
  41. package/lib/public/modules/input.js +31 -20
  42. package/lib/public/modules/scheduler-config.js +1532 -0
  43. package/lib/public/modules/scheduler-history.js +79 -0
  44. package/lib/public/modules/scheduler.js +33 -1554
  45. package/lib/public/modules/session-search.js +13 -1
  46. package/lib/public/modules/sidebar-mates.js +812 -0
  47. package/lib/public/modules/sidebar-mobile.js +1269 -0
  48. package/lib/public/modules/sidebar-projects.js +1449 -0
  49. package/lib/public/modules/sidebar-sessions.js +986 -0
  50. package/lib/public/modules/sidebar.js +232 -4591
  51. package/lib/public/modules/store.js +27 -0
  52. package/lib/public/modules/ws-ref.js +7 -0
  53. package/lib/public/style.css +1 -0
  54. package/lib/sdk-bridge.js +96 -717
  55. package/lib/sdk-message-processor.js +587 -0
  56. package/lib/sdk-message-queue.js +42 -0
  57. package/lib/sdk-skill-discovery.js +131 -0
  58. package/lib/server-admin.js +712 -0
  59. package/lib/server-auth.js +737 -0
  60. package/lib/server-dm.js +221 -0
  61. package/lib/server-mates.js +281 -0
  62. package/lib/server-palette.js +110 -0
  63. package/lib/server-settings.js +479 -0
  64. package/lib/server-skills.js +280 -0
  65. package/lib/server.js +246 -2755
  66. package/lib/sessions.js +11 -4
  67. package/lib/users-auth.js +146 -0
  68. package/lib/users-permissions.js +118 -0
  69. package/lib/users-preferences.js +210 -0
  70. package/lib/users.js +48 -398
  71. package/lib/ws-schema.js +498 -0
  72. package/package.json +1 -1
@@ -0,0 +1,389 @@
1
+ // app-debate-ui.js - Debate sticky banner, floor/conclude/ended modes, bottom bar, hand raise
2
+ // Extracted from app.js (PR-32)
3
+
4
+ import { refreshIcons, iconHtml } from './icons.js';
5
+ import { store } from './store.js';
6
+ import { getWs } from './ws-ref.js';
7
+ import { scrollToBottom } from './app-rendering.js';
8
+ import { exportDebateAsPdf } from './debate.js';
9
+
10
+ // Module-internal UI var (not in store)
11
+ var debateHandRaiseOpen = false;
12
+
13
+ export function initDebateUi() {}
14
+
15
+ // --- Debate modes ---
16
+
17
+ export function showDebateConcludeConfirm(msg) {
18
+ showDebateConcludeMode();
19
+ }
20
+
21
+ function showDebateConcludeMode() {
22
+ removeDebateBottomBar();
23
+ store.setState({ debateConcludeMode: true });
24
+ var inputArea = document.getElementById("input-area");
25
+ if (inputArea) {
26
+ inputArea.classList.add("debate-floor-mode");
27
+ inputArea.style.display = "";
28
+ }
29
+ var existingBanner = document.getElementById("debate-floor-banner");
30
+ if (existingBanner) existingBanner.remove();
31
+ var banner = document.createElement("div");
32
+ banner.id = "debate-floor-banner";
33
+ banner.className = "debate-floor-banner";
34
+ banner.innerHTML = iconHtml("check-circle") + " <span>The moderator is ready to conclude</span>" +
35
+ '<button class="debate-floor-done-btn debate-floor-end-btn" id="debate-floor-end-btn">End Debate</button>';
36
+ if (inputArea && inputArea.parentNode) {
37
+ inputArea.parentNode.insertBefore(banner, inputArea);
38
+ }
39
+ refreshIcons();
40
+ var endBtn = document.getElementById("debate-floor-end-btn");
41
+ if (endBtn) {
42
+ endBtn.addEventListener("click", function () {
43
+ var ws = getWs();
44
+ if (ws && ws.readyState === 1) {
45
+ ws.send(JSON.stringify({ type: "debate_conclude_response", action: "end" }));
46
+ }
47
+ exitDebateConcludeMode();
48
+ });
49
+ }
50
+ var inputEl = document.getElementById("input");
51
+ if (inputEl) {
52
+ inputEl._origPlaceholder = inputEl._origPlaceholder || inputEl.placeholder;
53
+ inputEl.placeholder = "Add a direction to continue the debate...";
54
+ inputEl.focus();
55
+ }
56
+ scrollToBottom();
57
+ }
58
+
59
+ export function exitDebateConcludeMode() {
60
+ store.setState({ debateConcludeMode: false });
61
+ var inputArea = document.getElementById("input-area");
62
+ if (inputArea) inputArea.classList.remove("debate-floor-mode");
63
+ var banner = document.getElementById("debate-floor-banner");
64
+ if (banner) banner.remove();
65
+ var inputEl = document.getElementById("input");
66
+ if (inputEl && inputEl._origPlaceholder) {
67
+ inputEl.placeholder = inputEl._origPlaceholder;
68
+ delete inputEl._origPlaceholder;
69
+ }
70
+ }
71
+
72
+ export function handleDebateConcludeSend() {
73
+ var text = document.getElementById("input").value.trim();
74
+ var ws = getWs();
75
+ if (ws && ws.readyState === 1) {
76
+ ws.send(JSON.stringify({ type: "debate_conclude_response", action: "continue", text: text }));
77
+ }
78
+ document.getElementById("input").value = "";
79
+ exitDebateConcludeMode();
80
+ showDebateBottomBar("live");
81
+ }
82
+
83
+ export function showDebateEndedMode(msg) {
84
+ removeDebateBottomBar();
85
+ store.setState({ debateEndedMode: true });
86
+ var inputArea = document.getElementById("input-area");
87
+ if (inputArea) {
88
+ inputArea.classList.add("debate-floor-mode");
89
+ inputArea.style.display = "";
90
+ }
91
+ var existingBanner = document.getElementById("debate-floor-banner");
92
+ if (existingBanner) existingBanner.remove();
93
+ var banner = document.createElement("div");
94
+ banner.id = "debate-floor-banner";
95
+ banner.className = "debate-floor-banner";
96
+ banner.innerHTML = iconHtml("check-circle") + " <span>Debate ended</span>" +
97
+ '<button class="debate-floor-done-btn" id="debate-ended-resume-btn">Resume</button>' +
98
+ '<button class="debate-floor-done-btn" id="debate-ended-pdf-btn">' + iconHtml("download") + ' PDF</button>';
99
+ if (inputArea && inputArea.parentNode) {
100
+ inputArea.parentNode.insertBefore(banner, inputArea);
101
+ }
102
+ refreshIcons();
103
+ var resumeBtn = document.getElementById("debate-ended-resume-btn");
104
+ if (resumeBtn) {
105
+ resumeBtn.addEventListener("click", function () {
106
+ handleDebateEndedSend();
107
+ });
108
+ }
109
+ var pdfBtn = document.getElementById("debate-ended-pdf-btn");
110
+ if (pdfBtn) {
111
+ pdfBtn.addEventListener("click", function () {
112
+ pdfBtn.disabled = true;
113
+ exportDebateAsPdf().then(function () { pdfBtn.disabled = false; }).catch(function () { pdfBtn.disabled = false; });
114
+ });
115
+ }
116
+ var inputEl2 = document.getElementById("input");
117
+ if (inputEl2) {
118
+ inputEl2._origPlaceholder = inputEl2._origPlaceholder || inputEl2.placeholder;
119
+ inputEl2.placeholder = "Continue with a new direction...";
120
+ }
121
+ scrollToBottom();
122
+ }
123
+
124
+ export function exitDebateEndedMode() {
125
+ store.setState({ debateEndedMode: false });
126
+ var inputArea = document.getElementById("input-area");
127
+ if (inputArea) inputArea.classList.remove("debate-floor-mode");
128
+ var banner = document.getElementById("debate-floor-banner");
129
+ if (banner) banner.remove();
130
+ var inputEl2 = document.getElementById("input");
131
+ if (inputEl2 && inputEl2._origPlaceholder) {
132
+ inputEl2.placeholder = inputEl2._origPlaceholder;
133
+ delete inputEl2._origPlaceholder;
134
+ }
135
+ }
136
+
137
+ function handleDebateEndedSend() {
138
+ var text = document.getElementById("input").value.trim();
139
+ var ws = getWs();
140
+ if (ws && ws.readyState === 1) {
141
+ ws.send(JSON.stringify({ type: "debate_conclude_response", action: "continue", text: text }));
142
+ }
143
+ document.getElementById("input").value = "";
144
+ exitDebateEndedMode();
145
+ }
146
+
147
+ export function showDebateUserFloor(msg) {
148
+ removeDebateBottomBar();
149
+ store.setState({ debateFloorMode: true });
150
+ var inputArea = document.getElementById("input-area");
151
+ if (inputArea) {
152
+ inputArea.classList.add("debate-floor-mode");
153
+ inputArea.style.display = "";
154
+ }
155
+ var existingBanner = document.getElementById("debate-floor-banner");
156
+ if (existingBanner) existingBanner.remove();
157
+ var banner = document.createElement("div");
158
+ banner.id = "debate-floor-banner";
159
+ banner.className = "debate-floor-banner";
160
+ banner.innerHTML = iconHtml("mic") + " <span>You have the floor</span>" +
161
+ '<button class="debate-floor-done-btn" id="debate-floor-done-btn">Pass</button>';
162
+ if (inputArea && inputArea.parentNode) {
163
+ inputArea.parentNode.insertBefore(banner, inputArea);
164
+ }
165
+ refreshIcons();
166
+ var doneBtn = document.getElementById("debate-floor-done-btn");
167
+ if (doneBtn) {
168
+ doneBtn.addEventListener("click", function () {
169
+ var ws = getWs();
170
+ if (ws && ws.readyState === 1) {
171
+ ws.send(JSON.stringify({ type: "debate_user_floor_response", text: "(The user passed without speaking)" }));
172
+ }
173
+ exitDebateFloorMode();
174
+ showDebateBottomBar("live");
175
+ });
176
+ }
177
+ var inputEl = document.getElementById("input");
178
+ if (inputEl) {
179
+ inputEl._origPlaceholder = inputEl.placeholder;
180
+ inputEl.placeholder = "Share your thoughts with the panel...";
181
+ inputEl.focus();
182
+ }
183
+ scrollToBottom();
184
+ }
185
+
186
+ export function exitDebateFloorMode() {
187
+ store.setState({ debateFloorMode: false });
188
+ var inputArea = document.getElementById("input-area");
189
+ if (inputArea) inputArea.classList.remove("debate-floor-mode");
190
+ var banner = document.getElementById("debate-floor-banner");
191
+ if (banner) banner.remove();
192
+ var inputEl = document.getElementById("input");
193
+ if (inputEl && inputEl._origPlaceholder) {
194
+ inputEl.placeholder = inputEl._origPlaceholder;
195
+ delete inputEl._origPlaceholder;
196
+ }
197
+ }
198
+
199
+ export function handleDebateFloorSend() {
200
+ var text = document.getElementById("input").value.trim();
201
+ if (!text) return;
202
+ var ws = getWs();
203
+ if (ws && ws.readyState === 1) {
204
+ ws.send(JSON.stringify({ type: "debate_user_floor_response", text: text }));
205
+ }
206
+ document.getElementById("input").value = "";
207
+ exitDebateFloorMode();
208
+ showDebateBottomBar("live");
209
+ }
210
+
211
+ export function renderDebateUserFloorDone(msg) {
212
+ var messagesEl = document.getElementById("messages");
213
+ if (!messagesEl) return;
214
+ var el = document.createElement("div");
215
+ el.className = "debate-user-comment";
216
+ var label = document.createElement("span");
217
+ label.className = "debate-comment-label";
218
+ label.innerHTML = iconHtml("mic") + " User:";
219
+ var textEl = document.createElement("div");
220
+ textEl.className = "debate-comment-text";
221
+ textEl.textContent = msg.text || "";
222
+ el.appendChild(label);
223
+ el.appendChild(textEl);
224
+ messagesEl.appendChild(el);
225
+ refreshIcons();
226
+ scrollToBottom();
227
+ }
228
+
229
+ // --- Debate sticky banner ---
230
+
231
+ export function showDebateSticky(phase, msg) {
232
+ if (phase === "ended" || phase === "hide") {
233
+ store.setState({ debateStickyState: null });
234
+ } else {
235
+ store.setState({ debateStickyState: { phase: phase, msg: msg } });
236
+ }
237
+
238
+ var stickyEl = document.getElementById("debate-sticky");
239
+ if (stickyEl) { stickyEl.classList.add("hidden"); stickyEl.innerHTML = ""; }
240
+
241
+ var oldBadges = document.querySelectorAll(".debate-header-badge");
242
+ for (var i = 0; i < oldBadges.length; i++) oldBadges[i].remove();
243
+
244
+ if (phase === "ended" || phase === "hide") {
245
+ debateHandRaiseOpen = false;
246
+ removeDebateBottomBar();
247
+ return;
248
+ }
249
+
250
+ if (phase === "live") {
251
+ debateHandRaiseOpen = false;
252
+ showDebateBottomBar("live");
253
+ }
254
+
255
+ var headerTitle = document.getElementById("header-title");
256
+ if (!headerTitle) return;
257
+
258
+ if (phase === "preparing") {
259
+ var badge = document.createElement("span");
260
+ badge.className = "debate-header-badge preparing";
261
+ badge.textContent = "Setting up\u2026";
262
+ headerTitle.after(badge);
263
+ } else if (phase === "live") {
264
+ var liveBadge = document.createElement("span");
265
+ liveBadge.className = "debate-header-badge live";
266
+ liveBadge.textContent = "Live";
267
+ headerTitle.after(liveBadge);
268
+
269
+ var roundBadge = document.createElement("span");
270
+ roundBadge.className = "debate-header-badge round";
271
+ roundBadge.id = "debate-header-round";
272
+ roundBadge.textContent = "R" + ((msg && msg.round) || 1);
273
+ liveBadge.after(roundBadge);
274
+ }
275
+ }
276
+
277
+ // --- Debate bottom bar ---
278
+
279
+ export function showDebateBottomBar(mode, msg) {
280
+ removeDebateBottomBar();
281
+
282
+ var inputArea = document.getElementById("input-area");
283
+ if (!inputArea || !inputArea.parentNode) return;
284
+
285
+ var bar = document.createElement("div");
286
+ bar.id = "debate-bottom-bar";
287
+ bar.className = "debate-bottom-bar";
288
+
289
+ if (mode === "live") {
290
+ bar.innerHTML =
291
+ '<div class="debate-bottom-inner">' +
292
+ '<button class="debate-bottom-hand" id="debate-bottom-hand">' + iconHtml("hand") + ' Raise hand</button>' +
293
+ '<span class="debate-bottom-waiting hidden" id="debate-bottom-waiting">' + iconHtml("loader") + ' You will get the floor after the current speaker</span>' +
294
+ '<button class="debate-bottom-stop" id="debate-bottom-stop">' + iconHtml("square") + ' Stop</button>' +
295
+ '</div>';
296
+
297
+ inputArea.parentNode.insertBefore(bar, inputArea);
298
+ inputArea.style.display = "none";
299
+ refreshIcons();
300
+
301
+ if (debateHandRaiseOpen) {
302
+ var handBtn = document.getElementById("debate-bottom-hand");
303
+ var waitingEl = document.getElementById("debate-bottom-waiting");
304
+ if (handBtn) { handBtn.classList.add("raised"); handBtn.classList.add("hidden"); }
305
+ if (waitingEl) waitingEl.classList.remove("hidden");
306
+ }
307
+
308
+ document.getElementById("debate-bottom-hand").addEventListener("click", function () {
309
+ toggleDebateHandRaise();
310
+ });
311
+ document.getElementById("debate-bottom-stop").addEventListener("click", function () {
312
+ var ws = getWs();
313
+ if (ws && ws.readyState === 1) {
314
+ ws.send(JSON.stringify({ type: "debate_stop" }));
315
+ var stopBtn = document.getElementById("debate-bottom-stop");
316
+ if (stopBtn) {
317
+ stopBtn.disabled = true;
318
+ stopBtn.innerHTML = iconHtml("loader") + " Stopping...";
319
+ refreshIcons();
320
+ }
321
+ var waitingEl2 = document.getElementById("debate-bottom-waiting");
322
+ if (waitingEl2) {
323
+ waitingEl2.textContent = "Stopping after current turn...";
324
+ waitingEl2.classList.remove("hidden");
325
+ }
326
+ }
327
+ });
328
+ }
329
+ }
330
+
331
+ export function debateAutoResize(textarea, maxRows) {
332
+ textarea.style.height = "auto";
333
+ var lineHeight = parseInt(getComputedStyle(textarea).lineHeight) || 20;
334
+ var maxHeight = lineHeight * maxRows;
335
+ var newHeight = Math.min(textarea.scrollHeight, maxHeight);
336
+ textarea.style.height = newHeight + "px";
337
+ textarea.style.overflowY = textarea.scrollHeight > maxHeight ? "auto" : "hidden";
338
+ }
339
+
340
+ export function removeDebateBottomBar() {
341
+ var existing = document.getElementById("debate-bottom-bar");
342
+ if (existing) existing.remove();
343
+ var handBar = document.getElementById("debate-hand-raise-bar");
344
+ if (handBar) handBar.remove();
345
+ debateHandRaiseOpen = false;
346
+ var _ds = store.getState();
347
+ if (_ds.debateFloorMode) exitDebateFloorMode();
348
+ if (_ds.debateConcludeMode) exitDebateConcludeMode();
349
+ if (_ds.debateEndedMode) exitDebateEndedMode();
350
+ var inputArea = document.getElementById("input-area");
351
+ if (inputArea) inputArea.style.display = "";
352
+ }
353
+
354
+ function toggleDebateHandRaise(forceState) {
355
+ var raise = typeof forceState === "boolean" ? forceState : !debateHandRaiseOpen;
356
+ debateHandRaiseOpen = raise;
357
+
358
+ var handBtn = document.getElementById("debate-bottom-hand");
359
+ var waitingEl = document.getElementById("debate-bottom-waiting");
360
+ if (raise) {
361
+ if (handBtn) { handBtn.classList.add("raised"); handBtn.classList.add("hidden"); }
362
+ if (waitingEl) waitingEl.classList.remove("hidden");
363
+ } else {
364
+ if (handBtn) { handBtn.classList.remove("raised"); handBtn.classList.remove("hidden"); }
365
+ if (waitingEl) waitingEl.classList.add("hidden");
366
+ }
367
+
368
+ var ws = getWs();
369
+ if (raise && ws && ws.readyState === 1) {
370
+ ws.send(JSON.stringify({ type: "debate_hand_raise" }));
371
+ }
372
+ }
373
+
374
+ export function sendDebateStickyComment() {
375
+ var commentInput = document.getElementById("debate-sticky-comment");
376
+ if (!commentInput) return;
377
+ var text = commentInput.value.trim();
378
+ if (!text) return;
379
+ var ws = getWs();
380
+ if (ws && ws.readyState === 1) {
381
+ ws.send(JSON.stringify({ type: "debate_comment", text: text }));
382
+ }
383
+ toggleDebateHandRaise(false);
384
+ }
385
+
386
+ export function updateDebateRound(round) {
387
+ var roundEl = document.getElementById("debate-header-round");
388
+ if (roundEl) roundEl.textContent = "R" + round;
389
+ }