clay-server 5.0.2-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-file-path.js +2 -3
- package/lib/project-knowledge.js +315 -136
- package/lib/project-mate-creation-proposal.js +1 -0
- package/lib/project-request-access.js +13 -1
- 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/filebrowser.css +10 -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/filebrowser.js +28 -8
- 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/html-preview.js +19 -0
- 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
|
@@ -7,7 +7,9 @@ import { refreshIcons } from './icons.js';
|
|
|
7
7
|
|
|
8
8
|
var sequence = 0;
|
|
9
9
|
var opener = null;
|
|
10
|
+
var preferredOpener = null;
|
|
10
11
|
var popover = null;
|
|
12
|
+
var inlineTarget = null;
|
|
11
13
|
|
|
12
14
|
function nextRequestId() {
|
|
13
15
|
sequence += 1;
|
|
@@ -49,6 +51,7 @@ function close() {
|
|
|
49
51
|
|
|
50
52
|
function position() {
|
|
51
53
|
if (!popover || !opener) return;
|
|
54
|
+
if (inlineTarget) return;
|
|
52
55
|
var rect = opener.getBoundingClientRect();
|
|
53
56
|
var width = Math.min(390, Math.max(0, window.innerWidth - 24));
|
|
54
57
|
popover.style.width = width + "px";
|
|
@@ -101,6 +104,40 @@ function addFieldLabel(text, control) {
|
|
|
101
104
|
popover.appendChild(label);
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
function inlineCurrentSelection(state, draft) {
|
|
108
|
+
return state.preference || state.selection || draft || {};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function renderInlineSummary() {
|
|
112
|
+
var state = store.get("defaultAiState") || {};
|
|
113
|
+
var draft = store.get("defaultAiDraft") || {};
|
|
114
|
+
var current = inlineCurrentSelection(state, draft);
|
|
115
|
+
var vendor = current.vendor ? (VENDOR_NAMES[current.vendor] || current.vendor) : "Loading default…";
|
|
116
|
+
var model = current.model || "Model unavailable";
|
|
117
|
+
var effort = current.effort || "Provider default";
|
|
118
|
+
popover.innerHTML = '';
|
|
119
|
+
var summary = document.createElement('button');
|
|
120
|
+
summary.type = 'button';
|
|
121
|
+
summary.className = 'default-ai-summary';
|
|
122
|
+
summary.id = 'account-ai-summary';
|
|
123
|
+
summary.setAttribute('aria-label', 'Default AI: ' + vendor + ', ' + model + ', ' + effort);
|
|
124
|
+
var label = document.createElement('span');
|
|
125
|
+
label.className = 'default-ai-summary-label';
|
|
126
|
+
label.textContent = 'Default AI';
|
|
127
|
+
var value = document.createElement('span');
|
|
128
|
+
value.className = 'default-ai-summary-value';
|
|
129
|
+
value.textContent = vendor + ' · ' + model + ' · ' + effort;
|
|
130
|
+
var icon = document.createElement('i');
|
|
131
|
+
icon.setAttribute('data-lucide', 'chevron-right');
|
|
132
|
+
icon.setAttribute('aria-hidden', 'true');
|
|
133
|
+
summary.appendChild(label);
|
|
134
|
+
summary.appendChild(value);
|
|
135
|
+
summary.appendChild(icon);
|
|
136
|
+
popover.appendChild(summary);
|
|
137
|
+
summary.addEventListener('click', function () { store.set({ defaultAiInlineEditing: true }); });
|
|
138
|
+
refreshIcons();
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
function render() {
|
|
105
142
|
if (!popover) return;
|
|
106
143
|
var state = store.get("defaultAiState") || {};
|
|
@@ -109,7 +146,17 @@ function render() {
|
|
|
109
146
|
var catalog = (state.catalogs || {})[draft.vendor] || null;
|
|
110
147
|
var models = catalog && catalog.models || [];
|
|
111
148
|
|
|
112
|
-
|
|
149
|
+
if (inlineTarget && store.get("defaultAiInlineEditing") !== true) {
|
|
150
|
+
renderInlineSummary();
|
|
151
|
+
position();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (inlineTarget) {
|
|
156
|
+
popover.innerHTML = '<div class="default-ai-edit-heading"><strong>Default AI</strong><button type="button" class="default-ai-cancel" aria-label="Cancel Default AI editing">Cancel</button></div>';
|
|
157
|
+
} else {
|
|
158
|
+
popover.innerHTML = '<div class="default-ai-title">Default AI</div><div class="default-ai-copy">Used for new Clay interviews and built-in AI assistance.</div>';
|
|
159
|
+
}
|
|
113
160
|
if (state.loading && !vendors.length) {
|
|
114
161
|
addStatus("Loading available AI providers…", false);
|
|
115
162
|
position();
|
|
@@ -170,8 +217,8 @@ function render() {
|
|
|
170
217
|
var save = document.createElement("button");
|
|
171
218
|
save.type = "button";
|
|
172
219
|
save.className = "default-ai-save";
|
|
173
|
-
save.textContent = state.saving ? "
|
|
174
|
-
save.disabled = state.saving === true || vendors.indexOf(vendor.value) === -1 || !selectedModel || !selectedEffort;
|
|
220
|
+
save.textContent = state.saving ? "Applying…" : "Apply";
|
|
221
|
+
save.disabled = state.saving === true || store.get("defaultAiDraftDirty") !== true || vendors.indexOf(vendor.value) === -1 || !selectedModel || !selectedEffort;
|
|
175
222
|
save.addEventListener("click", function () {
|
|
176
223
|
var id = nextRequestId();
|
|
177
224
|
var latest = store.get("defaultAiState") || {};
|
|
@@ -181,6 +228,13 @@ function render() {
|
|
|
181
228
|
}
|
|
182
229
|
render();
|
|
183
230
|
});
|
|
231
|
+
if (inlineTarget) {
|
|
232
|
+
var cancel = popover.querySelector(".default-ai-cancel");
|
|
233
|
+
cancel.addEventListener("click", function () {
|
|
234
|
+
var canonical = inlineCurrentSelection(store.get("defaultAiState") || {}, store.get("defaultAiDraft") || {});
|
|
235
|
+
store.set({ defaultAiDraft: Object.assign({}, canonical), defaultAiDraftDirty: false, defaultAiInlineEditing: false });
|
|
236
|
+
});
|
|
237
|
+
}
|
|
184
238
|
popover.appendChild(save);
|
|
185
239
|
if (state.error) addStatus(state.error, true);
|
|
186
240
|
position();
|
|
@@ -293,71 +347,25 @@ export function handleDefaultAiMessage(msg) {
|
|
|
293
347
|
}
|
|
294
348
|
|
|
295
349
|
export function initDefaultAi() {
|
|
296
|
-
|
|
297
|
-
if (!actions || document.getElementById("default-ai-btn")) return;
|
|
298
|
-
var button = document.createElement("button");
|
|
299
|
-
button.id = "default-ai-btn";
|
|
300
|
-
button.className = "default-ai-button";
|
|
301
|
-
button.title = "Default AI";
|
|
302
|
-
button.setAttribute("aria-label", "Default AI");
|
|
303
|
-
button.setAttribute("aria-haspopup", "dialog");
|
|
304
|
-
button.setAttribute("aria-expanded", "false");
|
|
305
|
-
button.innerHTML = '<span class="default-ai-avatar"></span>';
|
|
306
|
-
var settings = document.getElementById("user-settings-btn");
|
|
307
|
-
if (settings) actions.insertBefore(button, settings);
|
|
308
|
-
else actions.appendChild(button);
|
|
309
|
-
popover = document.createElement("section");
|
|
310
|
-
popover.id = "default-ai-popover";
|
|
311
|
-
popover.className = "default-ai-popover hidden";
|
|
312
|
-
popover.setAttribute("role", "dialog");
|
|
313
|
-
popover.setAttribute("aria-label", "Default AI settings");
|
|
314
|
-
document.body.appendChild(popover);
|
|
315
|
-
button.addEventListener("click", function () {
|
|
316
|
-
if (!popover.classList.contains("hidden")) { close(); return; }
|
|
317
|
-
opener = button;
|
|
318
|
-
button.setAttribute("aria-expanded", "true");
|
|
319
|
-
popover.classList.remove("hidden");
|
|
320
|
-
requestDefaultAi();
|
|
321
|
-
render();
|
|
322
|
-
});
|
|
323
|
-
document.addEventListener("click", function (event) {
|
|
324
|
-
var path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
325
|
-
var clickedButton = path.indexOf(button) !== -1 || button.contains(event.target);
|
|
326
|
-
var clickedPopover = path.indexOf(popover) !== -1 || popover.contains(event.target);
|
|
327
|
-
if (!popover || popover.classList.contains("hidden") || clickedPopover || clickedButton) return;
|
|
328
|
-
close();
|
|
329
|
-
});
|
|
330
|
-
document.addEventListener("keydown", function (event) {
|
|
331
|
-
if (event.key !== "Escape" || !popover || popover.classList.contains("hidden")) return;
|
|
332
|
-
event.preventDefault();
|
|
333
|
-
close();
|
|
334
|
-
});
|
|
335
|
-
window.addEventListener("resize", position);
|
|
336
|
-
window.addEventListener("scroll", position, true);
|
|
337
|
-
updateBadge();
|
|
350
|
+
return;
|
|
338
351
|
}
|
|
339
352
|
|
|
340
|
-
export function openDefaultAi() {
|
|
341
|
-
|
|
342
|
-
if (button && popover && popover.classList.contains("hidden")) button.click();
|
|
353
|
+
export function openDefaultAi(openerElement) {
|
|
354
|
+
document.dispatchEvent(new CustomEvent('clay:open-account-default-ai', { detail: { opener: openerElement || null } }));
|
|
343
355
|
}
|
|
344
356
|
|
|
345
|
-
function
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
image.alt = "";
|
|
358
|
-
avatar.appendChild(image);
|
|
359
|
-
}
|
|
360
|
-
if (image.getAttribute("src") !== source) image.setAttribute("src", source);
|
|
357
|
+
export function mountDefaultAi(target) {
|
|
358
|
+
inlineTarget = target;
|
|
359
|
+
popover = target;
|
|
360
|
+
opener = target;
|
|
361
|
+
render();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export function unmountDefaultAi(target) {
|
|
365
|
+
if (inlineTarget !== target) return;
|
|
366
|
+
inlineTarget = null;
|
|
367
|
+
opener = null;
|
|
368
|
+
popover = null;
|
|
361
369
|
}
|
|
362
370
|
|
|
363
371
|
store.subscribe(function (state, previous) {
|
|
@@ -371,7 +379,15 @@ store.subscribe(function (state, previous) {
|
|
|
371
379
|
if (accountId && state.connected) requestDefaultAi();
|
|
372
380
|
return;
|
|
373
381
|
}
|
|
382
|
+
if (state.defaultAiInlineEditing !== previous.defaultAiInlineEditing) {
|
|
383
|
+
if (popover) render();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
374
386
|
if (state.defaultAiState === previous.defaultAiState) return;
|
|
375
|
-
|
|
387
|
+
if (inlineTarget && previous.defaultAiState && previous.defaultAiState.saving === true && state.defaultAiState && state.defaultAiState.saving === false && state.defaultAiDraftDirty !== true && state.defaultAiInlineEditing === true) {
|
|
388
|
+
store.set({ defaultAiInlineEditing: false });
|
|
389
|
+
render();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
376
392
|
if (popover && !popover.classList.contains("hidden")) render();
|
|
377
393
|
});
|
|
@@ -13,6 +13,7 @@ import { initFileViewerTabs, openFileViewerTab, previewFileViewerTab, updateFile
|
|
|
13
13
|
import { initFileBrowserContextMenu, downloadProjectFile } from './filebrowser-context-menu.js';
|
|
14
14
|
import { registerClayFileLinkOpener } from './clay-file-links.js';
|
|
15
15
|
import { isPlantUmlFile, renderPlantUmlPreview, cancelPlantUmlPreview } from './plantuml-preview.js';
|
|
16
|
+
import { isHtmlFile, renderHtmlPreview } from './html-preview.js';
|
|
16
17
|
|
|
17
18
|
var ctx;
|
|
18
19
|
var showDropHint = function () {};
|
|
@@ -43,7 +44,7 @@ export function initFileBrowser(_ctx) {
|
|
|
43
44
|
onFocus: function(path) {
|
|
44
45
|
claimRightWorkbench("file-viewer");
|
|
45
46
|
ctx.fileViewerEl.classList.remove("hidden");
|
|
46
|
-
if (path !== currentFilePath) requestFileContent(path);
|
|
47
|
+
if (path !== currentFilePath || (store.get("fileViewerIsHtml") && isRendered && !document.querySelector(".file-viewer-html-preview"))) requestFileContent(path);
|
|
47
48
|
},
|
|
48
49
|
onEmpty: function() { teardownFileViewer(); },
|
|
49
50
|
});
|
|
@@ -194,10 +195,14 @@ export function initFileBrowser(_ctx) {
|
|
|
194
195
|
downloadProjectFile(currentFilePath);
|
|
195
196
|
});
|
|
196
197
|
|
|
197
|
-
//
|
|
198
|
+
// File preview/source toggle
|
|
198
199
|
document.getElementById("file-viewer-render").addEventListener("click", function () {
|
|
199
|
-
if (currentContent == null || (!currentIsMarkdown && !currentIsSvg && !store.get("fileViewerIsPlantUml"))) return;
|
|
200
|
+
if (currentContent == null || (!currentIsMarkdown && !currentIsSvg && !store.get("fileViewerIsPlantUml") && !store.get("fileViewerIsHtml"))) return;
|
|
200
201
|
isRendered = !isRendered;
|
|
202
|
+
if (store.get("fileViewerIsHtml")) {
|
|
203
|
+
renderHtmlBody();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
201
206
|
if (store.get("fileViewerIsPlantUml")) {
|
|
202
207
|
renderPlantUmlBody();
|
|
203
208
|
return;
|
|
@@ -491,6 +496,8 @@ export function closeFileViewer() {
|
|
|
491
496
|
|
|
492
497
|
function teardownFileViewer() {
|
|
493
498
|
cancelPlantUmlPreview();
|
|
499
|
+
var htmlFrame = document.querySelector(".file-viewer-html-preview");
|
|
500
|
+
if (htmlFrame) htmlFrame.remove();
|
|
494
501
|
if (currentFilePath && isFollowingMarkdown(currentFilePath)) cancelMarkdownFollow();
|
|
495
502
|
sendUnwatch();
|
|
496
503
|
inlineDiffActive = false;
|
|
@@ -528,7 +535,7 @@ export function resetFileBrowser() {
|
|
|
528
535
|
isRendered = false;
|
|
529
536
|
currentIsMarkdown = false;
|
|
530
537
|
currentIsSvg = false;
|
|
531
|
-
store.set({ fileViewerIsPlantUml: false });
|
|
538
|
+
store.set({ fileViewerIsPlantUml: false, fileViewerIsHtml: false });
|
|
532
539
|
cancelPlantUmlPreview();
|
|
533
540
|
historyVisible = false;
|
|
534
541
|
currentHistoryEntries = [];
|
|
@@ -1165,7 +1172,7 @@ function showFileContent(msg, expectedRevision) {
|
|
|
1165
1172
|
currentFilePath = msg.path;
|
|
1166
1173
|
currentIsMarkdown = false;
|
|
1167
1174
|
currentIsSvg = false;
|
|
1168
|
-
store.set({ fileViewerIsPlantUml: false });
|
|
1175
|
+
store.set({ fileViewerIsPlantUml: false, fileViewerIsHtml: false });
|
|
1169
1176
|
cancelPlantUmlPreview();
|
|
1170
1177
|
if (!keepRenderState) isRendered = false;
|
|
1171
1178
|
var requestedExt = msg.path.split(".").pop().toLowerCase();
|
|
@@ -1193,19 +1200,20 @@ function showFileContent(msg, expectedRevision) {
|
|
|
1193
1200
|
lightweightPreview = (msg.size || 0) > FILE_RICH_PREVIEW_MAX_BYTES;
|
|
1194
1201
|
currentIsMarkdown = !lightweightPreview && (ext === "md" || ext === "mdx");
|
|
1195
1202
|
currentIsSvg = !lightweightPreview && ext === "svg";
|
|
1203
|
+
store.set({ fileViewerIsHtml: !lightweightPreview && isHtmlFile(msg.path) });
|
|
1196
1204
|
store.set({ fileViewerIsPlantUml: !lightweightPreview && isPlantUmlFile(msg.path) });
|
|
1197
1205
|
if (lightweightPreview) isRendered = false;
|
|
1198
1206
|
if (pendingRenderedOpen && currentIsMarkdown) isRendered = true;
|
|
1199
1207
|
|
|
1200
|
-
if (currentIsMarkdown || currentIsSvg || store.get("fileViewerIsPlantUml")) {
|
|
1208
|
+
if (currentIsMarkdown || currentIsSvg || store.get("fileViewerIsPlantUml") || store.get("fileViewerIsHtml")) {
|
|
1201
1209
|
renderBtn.classList.remove("hidden");
|
|
1202
1210
|
renderBtn.title = currentIsSvg ? "Show SVG source" : "Render markdown";
|
|
1203
|
-
copyBtn.title = store.get("fileViewerIsPlantUml") ? "Copy PlantUML source" : currentIsSvg ? "Copy SVG source" : "Copy Markdown source";
|
|
1211
|
+
copyBtn.title = store.get("fileViewerIsHtml") ? "Copy HTML source" : store.get("fileViewerIsPlantUml") ? "Copy PlantUML source" : currentIsSvg ? "Copy SVG source" : "Copy Markdown source";
|
|
1204
1212
|
} else {
|
|
1205
1213
|
copyBtn.title = "Copy contents";
|
|
1206
1214
|
}
|
|
1207
1215
|
|
|
1208
|
-
// Markdown starts as source; SVG
|
|
1216
|
+
// Markdown starts as source; HTML, SVG and diagrams start as previews.
|
|
1209
1217
|
if (lightweightPreview) {
|
|
1210
1218
|
renderLargeTextFile(bodyEl, msg.content, msg.size);
|
|
1211
1219
|
} else if (currentIsMarkdown) {
|
|
@@ -1214,6 +1222,9 @@ function showFileContent(msg, expectedRevision) {
|
|
|
1214
1222
|
? (previousContent == null ? "" : previousContent)
|
|
1215
1223
|
: null;
|
|
1216
1224
|
renderBody(transitionFrom, refreshSlideIndex);
|
|
1225
|
+
} else if (store.get("fileViewerIsHtml")) {
|
|
1226
|
+
if (!keepRenderState) isRendered = !store.get("pendingFileNavigation");
|
|
1227
|
+
renderHtmlBody();
|
|
1217
1228
|
} else if (store.get("fileViewerIsPlantUml")) {
|
|
1218
1229
|
if (!keepRenderState) isRendered = !store.get("pendingFileNavigation");
|
|
1219
1230
|
renderPlantUmlBody();
|
|
@@ -1283,6 +1294,15 @@ function showFileContent(msg, expectedRevision) {
|
|
|
1283
1294
|
}
|
|
1284
1295
|
}
|
|
1285
1296
|
|
|
1297
|
+
function renderHtmlBody() {
|
|
1298
|
+
var bodyEl = document.getElementById("file-viewer-body");
|
|
1299
|
+
var renderBtn = document.getElementById("file-viewer-render");
|
|
1300
|
+
renderBtn.classList.toggle("active", isRendered);
|
|
1301
|
+
renderBtn.title = isRendered ? "Show HTML source" : "Show HTML preview";
|
|
1302
|
+
if (isRendered) renderHtmlPreview(bodyEl, currentContent, currentFilePath);
|
|
1303
|
+
else renderCodeWithLineNumbers(bodyEl, currentContent, "html");
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1286
1306
|
function renderPlantUmlBody() {
|
|
1287
1307
|
var bodyEl = document.getElementById("file-viewer-body");
|
|
1288
1308
|
var renderBtn = document.getElementById("file-viewer-render");
|
|
@@ -1,295 +1,24 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
2
|
import { getWs } from './ws-ref.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
var composing = false;
|
|
20
|
-
|
|
21
|
-
function textElement(tag, className, text) {
|
|
22
|
-
var element = document.createElement(tag);
|
|
23
|
-
element.className = className;
|
|
24
|
-
element.textContent = text || "";
|
|
25
|
-
return element;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function findHeader(messages) {
|
|
29
|
-
for (var i = (messages || []).length - 1; i >= 0; i--) if (messages[i] && messages[i].role === "debate_header") return messages[i];
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function findActiveTurn(messages) {
|
|
34
|
-
for (var i = (messages || []).length - 1; i >= 0; i--) {
|
|
35
|
-
if (messages[i] && messages[i].role === "debate_turn" && messages[i].status === "active") return messages[i];
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function homeDebateControlState(messages) {
|
|
41
|
-
var header = findHeader(messages);
|
|
42
|
-
if (!header || ["live", "ended", "interrupted"].indexOf(header.phase) === -1) return null;
|
|
43
|
-
var mode = header.phase === "live" ? (header.interaction || "default") : "terminal";
|
|
44
|
-
return { mode: mode, header: header, turn: findActiveTurn(messages), phase: header.phase };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function ensureElements() {
|
|
48
|
-
var nextSlot = document.getElementById("home-debate-controls-slot");
|
|
49
|
-
if (slotEl === nextSlot) return !!slotEl;
|
|
50
|
-
slotEl = nextSlot;
|
|
51
|
-
normalComposerEl = document.getElementById("home-mate-chat-composer");
|
|
52
|
-
modelEl = document.getElementById("home-mate-chat-session-model");
|
|
53
|
-
controlEl = null;
|
|
54
|
-
controlMode = null;
|
|
55
|
-
controlStateKey = null;
|
|
56
|
-
return !!slotEl;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function clearControls() {
|
|
60
|
-
if (slotEl) slotEl.innerHTML = "";
|
|
61
|
-
controlEl = null;
|
|
62
|
-
controlMode = null;
|
|
63
|
-
controlStateKey = null;
|
|
64
|
-
currentState = null;
|
|
65
|
-
inputEl = null;
|
|
66
|
-
primaryEl = null;
|
|
67
|
-
secondaryEl = null;
|
|
68
|
-
activityEl = null;
|
|
69
|
-
handEl = null;
|
|
70
|
-
stopEl = null;
|
|
71
|
-
composing = false;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function setSpecialMode(active) {
|
|
75
|
-
if (normalComposerEl) normalComposerEl.hidden = active;
|
|
76
|
-
if (modelEl) modelEl.hidden = active;
|
|
77
|
-
if (slotEl) slotEl.hidden = !active;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function sendControl(action, data) {
|
|
81
|
-
var ws = getWs();
|
|
82
|
-
if (!ws || ws.readyState !== 1 || !currentState) return false;
|
|
83
|
-
ws.send(JSON.stringify({
|
|
84
|
-
type: "home_debate_control",
|
|
85
|
-
action: action,
|
|
86
|
-
mateId: store.get('homeChatMateId'),
|
|
87
|
-
sessionId: store.get('homeChatSessionId'),
|
|
88
|
-
requestId: currentRequestId,
|
|
89
|
-
text: data && data.text ? data.text : "",
|
|
90
|
-
response: data && data.response ? data.response : null,
|
|
91
|
-
}));
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function button(label, className) {
|
|
96
|
-
var element = textElement("button", className, label);
|
|
97
|
-
element.type = "button";
|
|
98
|
-
return element;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function dots() {
|
|
102
|
-
var group = document.createElement("span");
|
|
103
|
-
group.className = "home-debate-control-dots";
|
|
104
|
-
group.setAttribute("aria-hidden", "true");
|
|
105
|
-
for (var i = 0; i < 3; i++) group.appendChild(document.createElement("i"));
|
|
106
|
-
return group;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function activityLabel(state) {
|
|
110
|
-
if (state.header.stopping) return state.turn ? "Stopping after " + (state.turn.mateName || "the current speaker") + " finishes" : "Stopping debate";
|
|
111
|
-
if (!state.turn) return state.header.handRaised ? "Your hand is raised" : "Debate is live";
|
|
112
|
-
var name = state.turn.mateName || "Mate";
|
|
113
|
-
var activity = state.turn.activity || (state.turn.text ? "speaking" : "preparing");
|
|
114
|
-
return name + " is " + activity.toLowerCase();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function lockSubmission(label) {
|
|
118
|
-
if (inputEl) inputEl.disabled = true;
|
|
119
|
-
if (primaryEl) { primaryEl.disabled = true; primaryEl.textContent = label; }
|
|
120
|
-
if (secondaryEl) secondaryEl.disabled = true;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function submitInput(action, response) {
|
|
124
|
-
var text = inputEl ? inputEl.value.trim() : "";
|
|
125
|
-
if (action === "user_floor" && !text) return false;
|
|
126
|
-
if (!sendControl(action, { text: text, response: response })) return false;
|
|
127
|
-
lockSubmission(action === "user_floor" ? "Sending…" : "Continuing…");
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function bindInput(submit) {
|
|
132
|
-
inputEl.addEventListener("compositionstart", function () { composing = true; });
|
|
133
|
-
inputEl.addEventListener("compositionend", function () { composing = false; });
|
|
134
|
-
inputEl.addEventListener("input", function () {
|
|
135
|
-
if (controlMode === "user_floor" && primaryEl) primaryEl.disabled = !inputEl.value.trim();
|
|
136
|
-
});
|
|
137
|
-
inputEl.addEventListener("keydown", function (event) {
|
|
138
|
-
if (event.key !== "Enter" || event.shiftKey || event.isComposing || composing || event.keyCode === 229) return;
|
|
139
|
-
event.preventDefault();
|
|
140
|
-
submit();
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function focusInputOnce() {
|
|
145
|
-
var target = inputEl;
|
|
146
|
-
if (!target) return;
|
|
147
|
-
var focus = function () {
|
|
148
|
-
if (target === inputEl && !target.disabled && target.isConnected !== false) target.focus({ preventScroll: true });
|
|
149
|
-
};
|
|
150
|
-
if (typeof requestAnimationFrame === "function") requestAnimationFrame(focus);
|
|
151
|
-
else focus();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function buildDefault(state) {
|
|
155
|
-
var context = document.createElement("div");
|
|
156
|
-
context.className = "home-debate-control-context";
|
|
157
|
-
context.appendChild(dots());
|
|
158
|
-
activityEl = textElement("span", "home-debate-control-activity", activityLabel(state));
|
|
159
|
-
activityEl.setAttribute("role", "status");
|
|
160
|
-
activityEl.setAttribute("aria-live", "polite");
|
|
161
|
-
context.appendChild(activityEl);
|
|
162
|
-
controlEl.appendChild(context);
|
|
163
|
-
var actions = document.createElement("div");
|
|
164
|
-
actions.className = "home-debate-control-actions";
|
|
165
|
-
handEl = button(state.header.handRaised ? "Hand raised" : "Raise hand", "home-debate-control-secondary");
|
|
166
|
-
handEl.setAttribute("aria-pressed", state.header.handRaised ? "true" : "false");
|
|
167
|
-
handEl.disabled = state.header.handRaised === true;
|
|
168
|
-
handEl.addEventListener("click", function () {
|
|
169
|
-
if (!sendControl("hand_raise")) return;
|
|
170
|
-
handEl.disabled = true;
|
|
171
|
-
handEl.textContent = "Raising hand…";
|
|
172
|
-
});
|
|
173
|
-
stopEl = button(state.header.stopping ? "Cancel stop" : "Stop debate", state.header.stopping ? "home-debate-control-secondary" : "home-debate-control-stop");
|
|
174
|
-
stopEl.addEventListener("click", function () {
|
|
175
|
-
var cancelling = currentState && currentState.header && currentState.header.stopping === true;
|
|
176
|
-
if (!sendControl(cancelling ? "cancel_stop" : "stop")) return;
|
|
177
|
-
stopEl.disabled = true;
|
|
178
|
-
stopEl.textContent = cancelling ? "Cancelling…" : "Stopping…";
|
|
179
|
-
});
|
|
180
|
-
actions.appendChild(handEl);
|
|
181
|
-
actions.appendChild(stopEl);
|
|
182
|
-
controlEl.appendChild(actions);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function buildInputMode(state) {
|
|
186
|
-
var isFloor = state.mode === "user_floor";
|
|
187
|
-
var heading = textElement("div", "home-debate-control-heading", isFloor ? "You have the floor" : "The moderator is ready to conclude");
|
|
188
|
-
heading.id = "home-debate-control-heading";
|
|
189
|
-
controlEl.appendChild(heading);
|
|
190
|
-
inputEl = document.createElement("textarea");
|
|
191
|
-
inputEl.rows = 2;
|
|
192
|
-
inputEl.placeholder = isFloor ? "Share your thoughts with the panel" : "Add an optional direction to continue";
|
|
193
|
-
inputEl.setAttribute("aria-labelledby", heading.id);
|
|
194
|
-
controlEl.appendChild(inputEl);
|
|
195
|
-
var actions = document.createElement("div");
|
|
196
|
-
actions.className = "home-debate-control-actions";
|
|
197
|
-
if (isFloor) {
|
|
198
|
-
primaryEl = button("Send", "home-debate-control-primary");
|
|
199
|
-
primaryEl.disabled = true;
|
|
200
|
-
primaryEl.addEventListener("click", function () { submitInput("user_floor"); });
|
|
201
|
-
secondaryEl = button("Pass", "home-debate-control-secondary");
|
|
202
|
-
secondaryEl.addEventListener("click", function () {
|
|
203
|
-
if (!sendControl("user_floor", { text: "(The user passed without speaking)" })) return;
|
|
204
|
-
lockSubmission("Sending…");
|
|
205
|
-
});
|
|
206
|
-
} else {
|
|
207
|
-
primaryEl = button("Continue", "home-debate-control-primary");
|
|
208
|
-
primaryEl.addEventListener("click", function () { submitInput("conclude", "continue"); });
|
|
209
|
-
secondaryEl = button("End debate", "home-debate-control-stop");
|
|
210
|
-
secondaryEl.addEventListener("click", function () {
|
|
211
|
-
if (!sendControl("conclude", { response: "end" })) return;
|
|
212
|
-
lockSubmission("Ending…");
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
actions.appendChild(primaryEl);
|
|
216
|
-
actions.appendChild(secondaryEl);
|
|
217
|
-
controlEl.appendChild(actions);
|
|
218
|
-
bindInput(function () { submitInput(isFloor ? "user_floor" : "conclude", isFloor ? null : "continue"); });
|
|
219
|
-
focusInputOnce();
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function terminalLabel(state) {
|
|
223
|
-
if (state.phase === "interrupted") return "Debate interrupted when Clay restarted";
|
|
224
|
-
if (state.header.reason === "error") return "The debate stopped after an error";
|
|
225
|
-
if (state.header.reason === "stopped" || state.header.reason === "user_stopped") return "Debate stopped";
|
|
226
|
-
return "Debate ended";
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function buildTerminal(state) {
|
|
230
|
-
var status = textElement("div", "home-debate-control-terminal-status", terminalLabel(state));
|
|
231
|
-
status.setAttribute("role", "status");
|
|
232
|
-
controlEl.appendChild(status);
|
|
233
|
-
var actions = document.createElement("div");
|
|
234
|
-
actions.className = "home-debate-control-actions";
|
|
235
|
-
primaryEl = button("Resume debate", "home-debate-control-primary");
|
|
236
|
-
primaryEl.addEventListener("click", function () {
|
|
237
|
-
if (!sendControl("resume")) return;
|
|
238
|
-
lockSubmission("Resuming…");
|
|
239
|
-
});
|
|
240
|
-
actions.appendChild(primaryEl);
|
|
241
|
-
if (typeof startNewDebate === "function") {
|
|
242
|
-
secondaryEl = button("New debate", "home-debate-control-secondary");
|
|
243
|
-
secondaryEl.addEventListener("click", function () { startNewDebate(); });
|
|
244
|
-
actions.appendChild(secondaryEl);
|
|
245
|
-
}
|
|
246
|
-
controlEl.appendChild(actions);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function buildControls(state) {
|
|
250
|
-
slotEl.innerHTML = "";
|
|
251
|
-
controlEl = document.createElement("section");
|
|
252
|
-
controlEl.className = "home-debate-control-surface home-debate-control-" + state.mode;
|
|
253
|
-
controlEl.setAttribute("role", state.mode === "default" ? "toolbar" : "region");
|
|
254
|
-
controlEl.setAttribute("aria-label", state.mode === "terminal" ? "Debate status" : "Live debate controls");
|
|
255
|
-
slotEl.appendChild(controlEl);
|
|
256
|
-
if (state.mode === "default") buildDefault(state);
|
|
257
|
-
else if (state.mode === "user_floor" || state.mode === "conclude") buildInputMode(state);
|
|
258
|
-
else buildTerminal(state);
|
|
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");
|
|
3
|
+
import { createDebateControls } from './debate-controls.js';
|
|
4
|
+
export { homeDebateControlState } from './debate-controls.js';
|
|
5
|
+
|
|
6
|
+
var controls = createDebateControls({
|
|
7
|
+
slotId: "home-debate-controls-slot",
|
|
8
|
+
composerId: "home-mate-chat-composer",
|
|
9
|
+
modelId: "home-mate-chat-session-model",
|
|
10
|
+
send: function (action, data, requestId) {
|
|
11
|
+
var ws = getWs();
|
|
12
|
+
if (!ws || ws.readyState !== 1) return false;
|
|
13
|
+
ws.send(JSON.stringify({
|
|
14
|
+
type: "home_debate_control", action: action,
|
|
15
|
+
mateId: store.get('homeChatMateId'), sessionId: store.get('homeChatSessionId'),
|
|
16
|
+
requestId: requestId, text: data.text || "", response: data.response || null
|
|
17
|
+
}));
|
|
18
|
+
return true;
|
|
271
19
|
}
|
|
272
|
-
|
|
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
|
-
}
|
|
20
|
+
});
|
|
278
21
|
|
|
279
22
|
export function renderHomeDebateControls(messages, requestId, onStartNewDebate) {
|
|
280
|
-
|
|
281
|
-
var state = homeDebateControlState(messages);
|
|
282
|
-
currentRequestId = requestId || null;
|
|
283
|
-
startNewDebate = onStartNewDebate || null;
|
|
284
|
-
if (!state) {
|
|
285
|
-
setSpecialMode(false);
|
|
286
|
-
clearControls();
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
currentState = state;
|
|
290
|
-
setSpecialMode(true);
|
|
291
|
-
var nextStateKey = state.mode + ":" + state.phase + ":" + (state.header.reason || "");
|
|
292
|
-
if (!controlEl || controlMode !== state.mode || controlStateKey !== nextStateKey) buildControls(state);
|
|
293
|
-
else updateControls(state);
|
|
294
|
-
return true;
|
|
23
|
+
return controls.render(messages, requestId, onStartNewDebate);
|
|
295
24
|
}
|