clay-server 5.1.0-beta.1 → 5.1.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/LICENSES/README.md +4 -0
- package/LICENSES/dicebear-avatars.md +16 -0
- package/lib/daemon-project-access.js +7 -1
- package/lib/daemon.js +2 -0
- package/lib/dicebear-avatar.js +62 -0
- package/lib/knowledge-db-service.js +175 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +49 -0
- package/lib/knowledge-draft-store.js +56 -0
- package/lib/knowledge-file-store.js +199 -0
- package/lib/knowledge-markdown.js +128 -0
- package/lib/mate-knowledge-mcp-server.js +29 -6
- package/lib/mate-knowledge-service.js +23 -2
- package/lib/mate-knowledge-sync.js +36 -21
- package/lib/mate-workspace-color.js +4 -0
- package/lib/mates.js +18 -0
- package/lib/project-connection.js +36 -2
- package/lib/project-debate-proposal.js +6 -0
- package/lib/project-debate-workspace.js +43 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-knowledge.js +315 -136
- package/lib/project-mate-creation-proposal.js +1 -0
- package/lib/project-sessions.js +39 -2
- package/lib/project-user-knowledge.js +60 -0
- package/lib/project.js +59 -18
- package/lib/public/app.js +73 -34
- package/lib/public/clay-studio-wordmark-bold.svg +20 -0
- package/lib/public/css/clay-workspace.css +105 -0
- package/lib/public/css/debates-workbench.css +47 -0
- package/lib/public/css/home-debate-live.css +26 -0
- package/lib/public/css/home-hub.css +3 -1
- package/lib/public/css/home-mate-model-picker.css +15 -131
- package/lib/public/css/home-mate-settings.css +168 -16
- package/lib/public/css/icon-strip.css +249 -32
- package/lib/public/css/mate-conversation.css +176 -0
- package/lib/public/css/mate-knowledge-workbench.css +118 -0
- package/lib/public/css/mate-workspace-color.css +16 -0
- package/lib/public/css/mates.css +28 -28
- package/lib/public/css/messages.css +1 -114
- package/lib/public/css/mobile-nav.css +16 -16
- package/lib/public/css/overlays.css +8 -0
- package/lib/public/css/project-logs.css +7 -0
- package/lib/public/css/project-mate-creation.css +105 -0
- package/lib/public/css/right-workbench.css +3 -3
- package/lib/public/css/session-folders.css +80 -21
- package/lib/public/css/sidebar.css +183 -107
- package/lib/public/css/title-bar.css +151 -0
- package/lib/public/css/worker-delegation.css +47 -0
- package/lib/public/css/worker-proposal.css +72 -150
- package/lib/public/css/you.css +74 -0
- package/lib/public/index.html +33 -101
- package/lib/public/modules/account-island.js +230 -0
- package/lib/public/modules/app-cursors.js +19 -43
- package/lib/public/modules/app-debate-ui.js +4 -3
- package/lib/public/modules/app-header.js +106 -0
- package/lib/public/modules/app-message-router.js +12 -3
- package/lib/public/modules/app-messages.js +34 -9
- package/lib/public/modules/app-notifications.js +4 -7
- package/lib/public/modules/app-projects.js +5 -38
- package/lib/public/modules/app-rendering.js +12 -13
- package/lib/public/modules/avatar.js +25 -9
- package/lib/public/modules/chat-render-runtime.js +16 -4
- package/lib/public/modules/command-palette.js +2 -15
- package/lib/public/modules/cursor-sharing-preference.js +3 -3
- package/lib/public/modules/debate-controls.js +299 -0
- package/lib/public/modules/debate.js +2 -0
- package/lib/public/modules/debates-workbench.js +339 -0
- package/lib/public/modules/default-ai.js +81 -65
- package/lib/public/modules/home-debate-controls.js +18 -289
- package/lib/public/modules/home-mate-avatar-editor.js +228 -0
- package/lib/public/modules/home-mate-color-picker.js +66 -0
- package/lib/public/modules/home-mate-creation.js +1 -1
- package/lib/public/modules/home-mate-instructions.js +90 -0
- package/lib/public/modules/home-mate-model-picker.js +80 -271
- package/lib/public/modules/home-mate-profile-editor.js +72 -0
- package/lib/public/modules/home-mate-settings.js +118 -125
- package/lib/public/modules/home-shell.js +3 -0
- package/lib/public/modules/home-surface-boot.js +1 -9
- package/lib/public/modules/icon-strip-tooltip.js +95 -0
- package/lib/public/modules/knowledge-db-edit-state.js +35 -0
- package/lib/public/modules/knowledge-db-workbench.js +234 -0
- package/lib/public/modules/knowledge-history-state.js +55 -0
- package/lib/public/modules/knowledge-markdown-editor.js +57 -0
- package/lib/public/modules/knowledge-preview-links.js +70 -0
- package/lib/public/modules/knowledge-workbench-shell.js +21 -0
- package/lib/public/modules/mate-knowledge-workbench-state.js +174 -0
- package/lib/public/modules/mate-knowledge-workbench.js +500 -0
- package/lib/public/modules/mate-knowledge.js +11 -3
- package/lib/public/modules/mate-management.js +54 -10
- package/lib/public/modules/mate-sidebar.js +11 -1
- package/lib/public/modules/mate-workspace-color.js +33 -0
- package/lib/public/modules/mention.js +5 -13
- package/lib/public/modules/profile.js +51 -18
- package/lib/public/modules/project-chat-identity.js +79 -0
- package/lib/public/modules/project-debate-planning-workspace.js +250 -0
- package/lib/public/modules/project-debate-workspace.js +185 -0
- package/lib/public/modules/project-header-identity.js +127 -0
- package/lib/public/modules/project-logs-render.js +9 -4
- package/lib/public/modules/project-mate-creation-workspace.js +414 -0
- package/lib/public/modules/project-mate-navigation.js +238 -0
- package/lib/public/modules/project-session-navigation.js +29 -0
- package/lib/public/modules/project-switcher.js +6 -8
- package/lib/public/modules/projects-hub-view.js +5 -6
- package/lib/public/modules/projects-hub.js +2 -6
- package/lib/public/modules/qrcode.js +27 -8
- package/lib/public/modules/search-clay-chat.js +8 -11
- package/lib/public/modules/session-activity-tooltip.js +12 -0
- package/lib/public/modules/session-create-form.js +86 -14
- package/lib/public/modules/session-create.js +50 -7
- package/lib/public/modules/session-list-visibility.js +41 -0
- package/lib/public/modules/session-presence-ui.js +4 -1
- package/lib/public/modules/session-title-marquee.js +51 -0
- package/lib/public/modules/sidebar-mates.js +3 -50
- package/lib/public/modules/sidebar-mobile.js +63 -60
- package/lib/public/modules/sidebar-projects.js +84 -97
- package/lib/public/modules/sidebar-session-folders-ui.js +2 -2
- package/lib/public/modules/sidebar-session-hierarchy.js +149 -70
- package/lib/public/modules/sidebar-sessions.js +49 -50
- package/lib/public/modules/sidebar.js +11 -13
- package/lib/public/modules/thinking-lifecycle.js +7 -6
- package/lib/public/modules/tool-palette-order.js +4 -3
- package/lib/public/modules/tool-palette.js +13 -3
- package/lib/public/modules/tools.js +22 -22
- package/lib/public/modules/worker-proposal.js +42 -8
- package/lib/public/modules/worker-runtime-picker.js +115 -0
- package/lib/public/modules/you-activity.js +121 -0
- package/lib/public/modules/you.js +251 -0
- package/lib/public/style.css +16 -8
- package/lib/public/vendor/codemirror/LICENSE +21 -0
- package/lib/public/vendor/codemirror/codemirror.css +344 -0
- package/lib/public/vendor/codemirror/codemirror.js +9884 -0
- package/lib/public/vendor/codemirror/continuelist.js +101 -0
- package/lib/public/vendor/codemirror/markdown.js +886 -0
- package/lib/public/vendor/codemirror/show-hint.css +37 -0
- package/lib/public/vendor/codemirror/show-hint.js +523 -0
- package/lib/sdk-bridge.js +15 -3
- package/lib/server-admin.js +11 -0
- package/lib/server-home-chat-events.js +1 -1
- package/lib/server-home-chat.js +25 -3
- package/lib/server-home-debate-planning.js +4 -1
- package/lib/server-home-debates.js +2 -0
- package/lib/server-home-mate-creation.js +4 -1
- package/lib/server-mate-instructions.js +44 -0
- package/lib/server-mates.js +12 -3
- package/lib/server-palette.js +1 -1
- package/lib/server-settings.js +65 -1
- package/lib/server-user-knowledge.js +119 -0
- package/lib/server.js +21 -1
- package/lib/session-visibility.js +7 -2
- package/lib/sessions.js +32 -6
- package/lib/user-knowledge-service.js +167 -0
- package/lib/users-permissions.js +7 -0
- package/lib/users-project-mate-filter-preferences.js +39 -0
- package/lib/users.js +6 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/ws-schema.js +50 -0
- package/package.json +10 -1
|
@@ -2,8 +2,6 @@ import { mateAvatarUrl } from './avatar.js';
|
|
|
2
2
|
import { escapeHtml } from './utils.js';
|
|
3
3
|
import { refreshIcons } from './icons.js';
|
|
4
4
|
import { openSearch as openSessionSearch } from './session-search.js';
|
|
5
|
-
import { showHomeHub, minimizeHomeHub } from './app-home-hub.js';
|
|
6
|
-
import { openHomeConversation } from './home-mate-chat.js';
|
|
7
5
|
import { startSearchClayChat, attachSearchClayChat, detachSearchClayChat, getSearchClayChatSummary } from './search-clay-chat.js';
|
|
8
6
|
import { getWs } from './ws-ref.js';
|
|
9
7
|
import { openProjectLog } from './project-logs.js';
|
|
@@ -110,13 +108,7 @@ export function handleClaySessionTarget(msg) {
|
|
|
110
108
|
navigateToLog(msg.target);
|
|
111
109
|
return true;
|
|
112
110
|
}
|
|
113
|
-
|
|
114
|
-
showHomeHub();
|
|
115
|
-
openHomeConversation(msg.target.mateId, msg.target.homeSessionId);
|
|
116
|
-
} else {
|
|
117
|
-
minimizeHomeHub();
|
|
118
|
-
navigateToSession({ projectSlug: msg.target.projectSlug, sessionId: msg.target.sessionId }, null);
|
|
119
|
-
}
|
|
111
|
+
navigateToSession({ projectSlug: msg.target.projectSlug, sessionId: msg.target.sessionId }, null);
|
|
120
112
|
return true;
|
|
121
113
|
}
|
|
122
114
|
|
|
@@ -166,7 +158,6 @@ export function handlePaletteSessionSwitch() {
|
|
|
166
158
|
|
|
167
159
|
function navigateToLog(target) {
|
|
168
160
|
closeCommandPalette();
|
|
169
|
-
minimizeHomeHub();
|
|
170
161
|
if (ctx.currentSlug && ctx.currentSlug() === target.projectSlug) {
|
|
171
162
|
openProjectLog(target.ref);
|
|
172
163
|
} else {
|
|
@@ -363,11 +354,7 @@ function resumeClayChat() {
|
|
|
363
354
|
function activateItem(entry) {
|
|
364
355
|
if (entry.type === "resume-clay") { resumeClayChat(); return; }
|
|
365
356
|
if (entry.type === "ask-clay") { beginClayChat(entry.query); return; }
|
|
366
|
-
if (entry.type === "mate-session")
|
|
367
|
-
closeCommandPalette();
|
|
368
|
-
showHomeHub();
|
|
369
|
-
openHomeConversation(entry.data.mateId, entry.data.sessionId);
|
|
370
|
-
} else if (entry.type === "session") navigateToSession(entry.data, entry.query);
|
|
357
|
+
if (entry.type === "mate-session" || entry.type === "session") navigateToSession(entry.data, entry.query);
|
|
371
358
|
}
|
|
372
359
|
|
|
373
360
|
function navigateToSession(item, query) {
|
|
@@ -15,18 +15,18 @@ export function handleCursorSharingMessage(msg) {
|
|
|
15
15
|
}
|
|
16
16
|
if (msg.ready !== true || msg.accountAvailable === false || typeof msg.cursorSharing !== "boolean") {
|
|
17
17
|
if (store.get("cursorSharingHydrated") && store.get("cursorSharingEnabled")) clearPresence();
|
|
18
|
-
store.set({ cursorSharingEnabled: false, cursorSharingHydrated: false, cursorSharingAccountId: null });
|
|
18
|
+
store.set({ cursorSharingEnabled: false, cursorSharingHydrated: false, cursorSharingAccountId: null, cursorSharingPending: null, cursorSharingError: msg.error || "unavailable" });
|
|
19
19
|
showToast(msg.error || "Cursor sharing is unavailable.", "warn");
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
22
|
var knownUserId = store.get("myUserId");
|
|
23
23
|
if (knownUserId && msg.accountId && knownUserId !== msg.accountId) {
|
|
24
24
|
if (store.get("cursorSharingHydrated") && store.get("cursorSharingEnabled")) clearPresence();
|
|
25
|
-
store.set({ cursorSharingEnabled: false, cursorSharingHydrated: false, cursorSharingAccountId: null });
|
|
25
|
+
store.set({ cursorSharingEnabled: false, cursorSharingHydrated: false, cursorSharingAccountId: null, cursorSharingPending: null, cursorSharingError: "account-changed" });
|
|
26
26
|
return true;
|
|
27
27
|
}
|
|
28
28
|
var wasEnabled = store.get("cursorSharingHydrated") && store.get("cursorSharingEnabled");
|
|
29
|
-
store.set({ cursorSharingEnabled: msg.cursorSharing, cursorSharingHydrated: true, cursorSharingAccountId: msg.accountId || null });
|
|
29
|
+
store.set({ cursorSharingEnabled: msg.cursorSharing, cursorSharingHydrated: true, cursorSharingAccountId: msg.accountId || null, cursorSharingPending: null, cursorSharingError: null });
|
|
30
30
|
if (wasEnabled && !msg.cursorSharing) {
|
|
31
31
|
var ws = getWs();
|
|
32
32
|
if (ws && ws.readyState === 1) {
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// Shared debate participation controls for Home and project workspaces.
|
|
2
|
+
|
|
3
|
+
function findHeader(messages) {
|
|
4
|
+
for (var i = (messages || []).length - 1; i >= 0; i--) if (messages[i] && messages[i].role === "debate_header") return messages[i];
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function findActiveTurn(messages) {
|
|
9
|
+
for (var i = (messages || []).length - 1; i >= 0; i--) {
|
|
10
|
+
if (messages[i] && messages[i].role === "debate_turn" && messages[i].status === "active") return messages[i];
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function homeDebateControlState(messages) {
|
|
16
|
+
var header = findHeader(messages);
|
|
17
|
+
if (!header || ["live", "ended", "interrupted"].indexOf(header.phase) === -1) return null;
|
|
18
|
+
var mode = header.phase === "live" ? (header.interaction || "default") : "terminal";
|
|
19
|
+
return { mode: mode, header: header, turn: findActiveTurn(messages), phase: header.phase };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function createDebateControls(options) {
|
|
23
|
+
var slotEl = null;
|
|
24
|
+
var normalComposerEl = null;
|
|
25
|
+
var modelEl = null;
|
|
26
|
+
var controlEl = null;
|
|
27
|
+
var controlMode = null;
|
|
28
|
+
var controlStateKey = null;
|
|
29
|
+
var currentState = null;
|
|
30
|
+
var currentRequestId = null;
|
|
31
|
+
var startNewDebate = null;
|
|
32
|
+
var inputEl = null;
|
|
33
|
+
var primaryEl = null;
|
|
34
|
+
var secondaryEl = null;
|
|
35
|
+
var activityEl = null;
|
|
36
|
+
var handEl = null;
|
|
37
|
+
var stopEl = null;
|
|
38
|
+
var composing = false;
|
|
39
|
+
var sizeAnimation = null;
|
|
40
|
+
|
|
41
|
+
function textElement(tag, className, text) {
|
|
42
|
+
var element = document.createElement(tag);
|
|
43
|
+
element.className = className;
|
|
44
|
+
element.textContent = text || "";
|
|
45
|
+
return element;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function ensureElements() {
|
|
49
|
+
var nextSlot = document.getElementById(options.slotId);
|
|
50
|
+
if (slotEl === nextSlot) return !!slotEl;
|
|
51
|
+
slotEl = nextSlot;
|
|
52
|
+
normalComposerEl = document.getElementById(options.composerId);
|
|
53
|
+
modelEl = options.modelId ? document.getElementById(options.modelId) : null;
|
|
54
|
+
controlEl = null;
|
|
55
|
+
controlMode = null;
|
|
56
|
+
controlStateKey = null;
|
|
57
|
+
return !!slotEl;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function clearControls() {
|
|
61
|
+
if (sizeAnimation) { sizeAnimation.cancel(); sizeAnimation = null; }
|
|
62
|
+
if (slotEl) slotEl.innerHTML = "";
|
|
63
|
+
controlEl = null;
|
|
64
|
+
controlMode = null;
|
|
65
|
+
controlStateKey = null;
|
|
66
|
+
currentState = null;
|
|
67
|
+
inputEl = null;
|
|
68
|
+
primaryEl = null;
|
|
69
|
+
secondaryEl = null;
|
|
70
|
+
activityEl = null;
|
|
71
|
+
handEl = null;
|
|
72
|
+
stopEl = null;
|
|
73
|
+
composing = false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function setSpecialMode(active) {
|
|
77
|
+
if (normalComposerEl) normalComposerEl.hidden = active;
|
|
78
|
+
if (modelEl) modelEl.hidden = active;
|
|
79
|
+
if (slotEl) slotEl.hidden = !active;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function sendControl(action, data) {
|
|
83
|
+
if (!currentState) return false;
|
|
84
|
+
return options.send(action, data || {}, currentRequestId);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function button(label, className) {
|
|
88
|
+
var element = textElement("button", className, label);
|
|
89
|
+
element.type = "button";
|
|
90
|
+
return element;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function dots() {
|
|
94
|
+
var group = document.createElement("span");
|
|
95
|
+
group.className = "home-debate-control-dots";
|
|
96
|
+
group.setAttribute("aria-hidden", "true");
|
|
97
|
+
for (var i = 0; i < 3; i++) group.appendChild(document.createElement("i"));
|
|
98
|
+
return group;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function activityLabel(state) {
|
|
102
|
+
if (state.header.stopping) return state.turn ? "Stopping after " + (state.turn.mateName || "the current speaker") + " finishes" : "Stopping debate";
|
|
103
|
+
if (!state.turn) return state.header.handRaised ? "Your hand is raised" : "Debate is live";
|
|
104
|
+
var name = state.turn.mateName || "Mate";
|
|
105
|
+
var activity = state.turn.activity || (state.turn.text ? "speaking" : "preparing");
|
|
106
|
+
return name + " is " + activity.toLowerCase();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function lockSubmission(label) {
|
|
110
|
+
if (inputEl) inputEl.disabled = true;
|
|
111
|
+
if (primaryEl) { primaryEl.disabled = true; primaryEl.textContent = label; }
|
|
112
|
+
if (secondaryEl) secondaryEl.disabled = true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function submitInput(action, response) {
|
|
116
|
+
var text = inputEl ? inputEl.value.trim() : "";
|
|
117
|
+
if (action === "user_floor" && !text) return false;
|
|
118
|
+
if (!sendControl(action, { text: text, response: response })) return false;
|
|
119
|
+
lockSubmission(action === "user_floor" ? "Sending…" : "Continuing…");
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function bindInput(submit) {
|
|
124
|
+
inputEl.addEventListener("compositionstart", function () { composing = true; });
|
|
125
|
+
inputEl.addEventListener("compositionend", function () { composing = false; });
|
|
126
|
+
inputEl.addEventListener("input", function () {
|
|
127
|
+
if (controlMode === "user_floor" && primaryEl) primaryEl.disabled = !inputEl.value.trim();
|
|
128
|
+
});
|
|
129
|
+
inputEl.addEventListener("keydown", function (event) {
|
|
130
|
+
if (event.key !== "Enter" || event.shiftKey || event.isComposing || composing || event.keyCode === 229) return;
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
submit();
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function focusInputOnce() {
|
|
137
|
+
var target = inputEl;
|
|
138
|
+
if (!target) return;
|
|
139
|
+
var focus = function () {
|
|
140
|
+
if (target === inputEl && !target.disabled && target.isConnected !== false) target.focus({ preventScroll: true });
|
|
141
|
+
};
|
|
142
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(focus);
|
|
143
|
+
else focus();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function buildDefault(state) {
|
|
147
|
+
var context = document.createElement("div");
|
|
148
|
+
context.className = "home-debate-control-context";
|
|
149
|
+
context.appendChild(dots());
|
|
150
|
+
activityEl = textElement("span", "home-debate-control-activity", activityLabel(state));
|
|
151
|
+
activityEl.setAttribute("role", "status");
|
|
152
|
+
activityEl.setAttribute("aria-live", "polite");
|
|
153
|
+
context.appendChild(activityEl);
|
|
154
|
+
controlEl.appendChild(context);
|
|
155
|
+
var actions = document.createElement("div");
|
|
156
|
+
actions.className = "home-debate-control-actions";
|
|
157
|
+
handEl = button(state.header.handRaised ? "Hand raised" : "Raise hand", "home-debate-control-secondary");
|
|
158
|
+
handEl.setAttribute("aria-pressed", state.header.handRaised ? "true" : "false");
|
|
159
|
+
handEl.disabled = state.header.handRaised === true;
|
|
160
|
+
handEl.addEventListener("click", function () {
|
|
161
|
+
if (!sendControl("hand_raise")) return;
|
|
162
|
+
handEl.disabled = true;
|
|
163
|
+
handEl.textContent = "Raising hand…";
|
|
164
|
+
});
|
|
165
|
+
stopEl = button(state.header.stopping ? "Cancel stop" : "Stop debate", state.header.stopping ? "home-debate-control-secondary" : "home-debate-control-stop");
|
|
166
|
+
stopEl.addEventListener("click", function () {
|
|
167
|
+
var cancelling = currentState && currentState.header && currentState.header.stopping === true;
|
|
168
|
+
if (!sendControl(cancelling ? "cancel_stop" : "stop")) return;
|
|
169
|
+
stopEl.disabled = true;
|
|
170
|
+
stopEl.textContent = cancelling ? "Cancelling…" : "Stopping…";
|
|
171
|
+
});
|
|
172
|
+
actions.appendChild(handEl);
|
|
173
|
+
actions.appendChild(stopEl);
|
|
174
|
+
controlEl.appendChild(actions);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function buildInputMode(state) {
|
|
178
|
+
var isFloor = state.mode === "user_floor";
|
|
179
|
+
var heading = textElement("div", "home-debate-control-heading", isFloor ? "You have the floor" : "The moderator is ready to conclude");
|
|
180
|
+
heading.id = options.slotId + "-heading";
|
|
181
|
+
controlEl.appendChild(heading);
|
|
182
|
+
inputEl = document.createElement("textarea");
|
|
183
|
+
inputEl.rows = 2;
|
|
184
|
+
inputEl.placeholder = isFloor ? "Share your thoughts with the panel" : "Add an optional direction to continue";
|
|
185
|
+
inputEl.setAttribute("aria-labelledby", heading.id);
|
|
186
|
+
controlEl.appendChild(inputEl);
|
|
187
|
+
var actions = document.createElement("div");
|
|
188
|
+
actions.className = "home-debate-control-actions";
|
|
189
|
+
if (isFloor) {
|
|
190
|
+
primaryEl = button("Send", "home-debate-control-primary");
|
|
191
|
+
primaryEl.disabled = true;
|
|
192
|
+
primaryEl.addEventListener("click", function () { submitInput("user_floor"); });
|
|
193
|
+
secondaryEl = button("Pass", "home-debate-control-secondary");
|
|
194
|
+
secondaryEl.addEventListener("click", function () {
|
|
195
|
+
if (!sendControl("user_floor", { text: "(The user passed without speaking)" })) return;
|
|
196
|
+
lockSubmission("Sending…");
|
|
197
|
+
});
|
|
198
|
+
} else {
|
|
199
|
+
primaryEl = button("Continue", "home-debate-control-primary");
|
|
200
|
+
primaryEl.addEventListener("click", function () { submitInput("conclude", "continue"); });
|
|
201
|
+
secondaryEl = button("End debate", "home-debate-control-stop");
|
|
202
|
+
secondaryEl.addEventListener("click", function () {
|
|
203
|
+
if (!sendControl("conclude", { response: "end" })) return;
|
|
204
|
+
lockSubmission("Ending…");
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
actions.appendChild(primaryEl);
|
|
208
|
+
actions.appendChild(secondaryEl);
|
|
209
|
+
controlEl.appendChild(actions);
|
|
210
|
+
bindInput(function () { submitInput(isFloor ? "user_floor" : "conclude", isFloor ? null : "continue"); });
|
|
211
|
+
focusInputOnce();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function terminalLabel(state) {
|
|
215
|
+
if (state.phase === "interrupted") return "Debate interrupted when Clay restarted";
|
|
216
|
+
if (state.header.reason === "error") return "The debate stopped after an error";
|
|
217
|
+
if (state.header.reason === "stopped" || state.header.reason === "user_stopped") return "Debate stopped";
|
|
218
|
+
return "Debate ended";
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function buildTerminal(state) {
|
|
222
|
+
var status = textElement("div", "home-debate-control-terminal-status", terminalLabel(state));
|
|
223
|
+
status.setAttribute("role", "status");
|
|
224
|
+
controlEl.appendChild(status);
|
|
225
|
+
var actions = document.createElement("div");
|
|
226
|
+
actions.className = "home-debate-control-actions";
|
|
227
|
+
primaryEl = button("Resume debate", "home-debate-control-primary");
|
|
228
|
+
primaryEl.addEventListener("click", function () {
|
|
229
|
+
if (!sendControl("resume")) return;
|
|
230
|
+
lockSubmission("Resuming…");
|
|
231
|
+
});
|
|
232
|
+
actions.appendChild(primaryEl);
|
|
233
|
+
if (typeof startNewDebate === "function") {
|
|
234
|
+
secondaryEl = button("New debate", "home-debate-control-secondary");
|
|
235
|
+
secondaryEl.addEventListener("click", function () { startNewDebate(); });
|
|
236
|
+
actions.appendChild(secondaryEl);
|
|
237
|
+
}
|
|
238
|
+
controlEl.appendChild(actions);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function buildControls(state) {
|
|
242
|
+
var previousHeight = slotEl.getBoundingClientRect ? slotEl.getBoundingClientRect().height : 0;
|
|
243
|
+
if (sizeAnimation) { sizeAnimation.cancel(); sizeAnimation = null; }
|
|
244
|
+
slotEl.innerHTML = "";
|
|
245
|
+
controlEl = document.createElement("section");
|
|
246
|
+
controlEl.className = "home-debate-control-surface home-debate-control-" + state.mode;
|
|
247
|
+
controlEl.setAttribute("role", state.mode === "default" ? "toolbar" : "region");
|
|
248
|
+
controlEl.setAttribute("aria-label", state.mode === "terminal" ? "Debate status" : "Live debate controls");
|
|
249
|
+
slotEl.appendChild(controlEl);
|
|
250
|
+
if (state.mode === "default") buildDefault(state);
|
|
251
|
+
else if (state.mode === "user_floor" || state.mode === "conclude") buildInputMode(state);
|
|
252
|
+
else buildTerminal(state);
|
|
253
|
+
if (previousHeight && slotEl.animate && !(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches)) {
|
|
254
|
+
var nextHeight = slotEl.getBoundingClientRect().height;
|
|
255
|
+
if (Math.abs(previousHeight - nextHeight) > 1) sizeAnimation = slotEl.animate([
|
|
256
|
+
{ height: previousHeight + 'px' }, { height: nextHeight + 'px' }
|
|
257
|
+
], { duration: 170, easing: 'ease-out' });
|
|
258
|
+
}
|
|
259
|
+
controlMode = state.mode;
|
|
260
|
+
controlStateKey = state.mode + ":" + state.phase + ":" + (state.header.reason || "");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function updateControls(state) {
|
|
264
|
+
if (state.mode !== "default") return;
|
|
265
|
+
var label = activityLabel(state);
|
|
266
|
+
if (activityEl && activityEl.textContent !== label) activityEl.textContent = label;
|
|
267
|
+
if (state.header.handRaised && handEl) {
|
|
268
|
+
handEl.textContent = "Hand raised";
|
|
269
|
+
handEl.disabled = true;
|
|
270
|
+
handEl.setAttribute("aria-pressed", "true");
|
|
271
|
+
}
|
|
272
|
+
if (stopEl) {
|
|
273
|
+
stopEl.disabled = false;
|
|
274
|
+
stopEl.textContent = state.header.stopping ? "Cancel stop" : "Stop debate";
|
|
275
|
+
stopEl.className = state.header.stopping ? "home-debate-control-secondary" : "home-debate-control-stop";
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function renderControls(messages, requestId, onStartNewDebate) {
|
|
280
|
+
if (!ensureElements()) return false;
|
|
281
|
+
var state = homeDebateControlState(messages);
|
|
282
|
+
if (currentRequestId !== (requestId || null)) clearControls();
|
|
283
|
+
currentRequestId = requestId || null;
|
|
284
|
+
startNewDebate = onStartNewDebate || null;
|
|
285
|
+
if (!state) {
|
|
286
|
+
setSpecialMode(false);
|
|
287
|
+
clearControls();
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
currentState = state;
|
|
291
|
+
setSpecialMode(true);
|
|
292
|
+
var nextStateKey = state.mode + ":" + state.phase + ":" + (state.header.reason || "");
|
|
293
|
+
if (!controlEl || controlMode !== state.mode || controlStateKey !== nextStateKey) buildControls(state);
|
|
294
|
+
else updateControls(state);
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return { render: renderControls };
|
|
299
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resetProjectDebateWorkspace } from './project-debate-workspace.js';
|
|
1
2
|
import { mateAvatarUrl } from './avatar.js';
|
|
2
3
|
import { renderMarkdown, highlightCodeBlocks, buildPrintHtml, getPrintCss } from './markdown.js';
|
|
3
4
|
import { escapeHtml } from './utils.js';
|
|
@@ -37,6 +38,7 @@ export function initDebate(_ctx) {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export function resetDebateState() {
|
|
41
|
+
resetProjectDebateWorkspace();
|
|
40
42
|
debateActive = false;
|
|
41
43
|
debateTopic = "";
|
|
42
44
|
debateRound = 0;
|