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
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
// Cross-Mate debate archive and launcher. Conversation content remains in the
|
|
2
|
+
// owning Mate project; this panel is only an authorized index and launch pad.
|
|
3
|
+
|
|
4
|
+
import { store } from './store.js';
|
|
5
|
+
import { getWs } from './ws-ref.js';
|
|
6
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
7
|
+
import { switchProject } from './app-projects.js';
|
|
8
|
+
import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
9
|
+
import { startProjectDebatePlanning } from './project-debate-planning-workspace.js';
|
|
10
|
+
import { isMateWorkspace } from './project-mate-navigation.js';
|
|
11
|
+
|
|
12
|
+
var panel = null;
|
|
13
|
+
var requestSequence = 0;
|
|
14
|
+
var opener = null;
|
|
15
|
+
var backgroundState = [];
|
|
16
|
+
|
|
17
|
+
function narrowLayout() {
|
|
18
|
+
return typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(max-width: 1023px)').matches;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isMateDebateSurface(state) {
|
|
22
|
+
return isMateWorkspace(state) || (state.dmMode === true && state.dmTargetUser && state.dmTargetUser.isMate === true);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function setNarrowBackground(hidden) {
|
|
26
|
+
var selectors = ['#app', '#sidebar-column', '#icon-strip', '#top-bar', '#main-column > .title-bar-content', '#dm-header-bar'];
|
|
27
|
+
if (hidden) {
|
|
28
|
+
backgroundState = [];
|
|
29
|
+
for (var i = 0; i < selectors.length; i++) {
|
|
30
|
+
var element = document.querySelector(selectors[i]);
|
|
31
|
+
if (!element) continue;
|
|
32
|
+
backgroundState.push({ element: element, inert: element.inert === true, ariaHidden: element.getAttribute('aria-hidden') });
|
|
33
|
+
element.inert = true;
|
|
34
|
+
element.setAttribute('aria-hidden', 'true');
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (var j = 0; j < backgroundState.length; j++) {
|
|
39
|
+
backgroundState[j].element.inert = backgroundState[j].inert;
|
|
40
|
+
if (backgroundState[j].ariaHidden == null) backgroundState[j].element.removeAttribute('aria-hidden');
|
|
41
|
+
else backgroundState[j].element.setAttribute('aria-hidden', backgroundState[j].ariaHidden);
|
|
42
|
+
}
|
|
43
|
+
backgroundState = [];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function send(message) {
|
|
47
|
+
var ws = getWs();
|
|
48
|
+
if (!ws || ws.readyState !== 1) return false;
|
|
49
|
+
ws.send(JSON.stringify(message));
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function phaseLabel(phase) {
|
|
54
|
+
if (phase === 'live') return 'Live';
|
|
55
|
+
if (phase === 'ended') return 'Ended';
|
|
56
|
+
if (phase === 'interrupted') return 'Interrupted';
|
|
57
|
+
return 'Planning';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function dateLabel(value) {
|
|
61
|
+
if (typeof value !== 'number' || !isFinite(value) || value <= 0) return 'Date unavailable';
|
|
62
|
+
try { return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(new Date(value)); }
|
|
63
|
+
catch (error) { return new Date(value).toLocaleDateString(); }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function participantsLabel(participants) {
|
|
67
|
+
var source = Array.isArray(participants) ? participants : [];
|
|
68
|
+
var names = [];
|
|
69
|
+
for (var i = 0; i < source.length; i++) if (source[i] && source[i].name) names.push(source[i].name);
|
|
70
|
+
return names.length ? names.join(', ') : 'Panel not selected';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function ensurePanel() {
|
|
74
|
+
if (panel) return panel;
|
|
75
|
+
var host = document.getElementById('main-panels');
|
|
76
|
+
if (!host) return null;
|
|
77
|
+
panel = document.createElement('section');
|
|
78
|
+
panel.id = 'debates-workbench';
|
|
79
|
+
panel.className = 'hidden';
|
|
80
|
+
panel.setAttribute('role', 'region');
|
|
81
|
+
panel.setAttribute('aria-label', 'Debates');
|
|
82
|
+
panel.innerHTML =
|
|
83
|
+
'<header class="debates-workbench-topbar">' +
|
|
84
|
+
'<span class="debates-workbench-title">' + iconHtml('messages-square') + 'Debates</span>' +
|
|
85
|
+
'<button class="debates-workbench-new" type="button" data-debates-action="new">' + iconHtml('plus') + 'New debate</button>' +
|
|
86
|
+
'<div class="debates-workbench-actions">' +
|
|
87
|
+
'<button class="debates-workbench-icon" type="button" data-debates-action="wide" title="Widen panel" aria-label="Widen Debates panel" aria-pressed="false">' + iconHtml('chevrons-left-right') + '</button>' +
|
|
88
|
+
'<button class="debates-workbench-icon" type="button" data-debates-action="fullscreen" title="Toggle fullscreen" aria-label="Toggle Debates fullscreen" aria-pressed="false">' + iconHtml('maximize-2') + '</button>' +
|
|
89
|
+
'<button class="debates-workbench-icon" type="button" data-debates-action="close" title="Close" aria-label="Close Debates">' + iconHtml('x') + '</button>' +
|
|
90
|
+
'</div>' +
|
|
91
|
+
'</header>' +
|
|
92
|
+
'<div class="debates-workbench-filters" role="group" aria-label="Filter debates"></div>' +
|
|
93
|
+
'<form class="debates-workbench-form hidden"><label for="debates-workbench-topic">What should the debate be about?</label><textarea id="debates-workbench-topic" maxlength="1000" required placeholder="Enter a question or topic"></textarea><p class="debates-workbench-launch-status" role="alert"></p><div class="debates-workbench-form-actions"><button type="button" data-debates-action="cancel-new">Cancel</button><button type="submit">Continue in chat</button></div></form>' +
|
|
94
|
+
'<p class="debates-workbench-summary" role="status" aria-live="polite"></p>' +
|
|
95
|
+
'<div class="debates-workbench-list" role="list"></div>';
|
|
96
|
+
host.appendChild(panel);
|
|
97
|
+
panel.addEventListener('click', handleClick);
|
|
98
|
+
panel.addEventListener('keydown', handleKeydown);
|
|
99
|
+
panel.querySelector('form').addEventListener('submit', submitNewDebate);
|
|
100
|
+
refreshIcons();
|
|
101
|
+
return panel;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function ensureMateProjectDebatesButton() {
|
|
105
|
+
var button = document.getElementById('mate-project-debates-btn');
|
|
106
|
+
if (button) return button;
|
|
107
|
+
var tools = document.getElementById('session-actions');
|
|
108
|
+
if (!tools) return null;
|
|
109
|
+
button = document.createElement('button');
|
|
110
|
+
button.id = 'mate-project-debates-btn';
|
|
111
|
+
button.type = 'button';
|
|
112
|
+
button.className = 'palette-tile';
|
|
113
|
+
button.title = 'Debates';
|
|
114
|
+
button.setAttribute('aria-label', 'Debates');
|
|
115
|
+
button.innerHTML = iconHtml('messages-square') + '<span class="tool-btn-label">Debates</span>';
|
|
116
|
+
tools.appendChild(button);
|
|
117
|
+
refreshIcons(button);
|
|
118
|
+
return button;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function requestDebates() {
|
|
122
|
+
requestSequence += 1;
|
|
123
|
+
var requestId = 'debates-workbench-' + requestSequence;
|
|
124
|
+
store.set({ debatesWorkbenchStatus: 'loading', debatesWorkbenchRequestId: requestId, debatesWorkbenchError: '' });
|
|
125
|
+
if (!send({ type: 'home_debates_list', requestId: requestId })) {
|
|
126
|
+
store.set({ debatesWorkbenchStatus: 'error', debatesWorkbenchError: 'Reconnect to load your debates.' });
|
|
127
|
+
render();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
render();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function renderFilters() {
|
|
134
|
+
var filters = panel.querySelector('.debates-workbench-filters');
|
|
135
|
+
var active = store.get('debatesWorkbenchFilter') || 'all';
|
|
136
|
+
var specs = [{ key: 'all', label: 'All' }, { key: 'planning', label: 'Planning' }, { key: 'live', label: 'Live' }, { key: 'ended', label: 'Ended' }, { key: 'interrupted', label: 'Interrupted' }];
|
|
137
|
+
filters.innerHTML = '';
|
|
138
|
+
for (var i = 0; i < specs.length; i++) {
|
|
139
|
+
var button = document.createElement('button');
|
|
140
|
+
button.type = 'button';
|
|
141
|
+
button.className = 'debates-workbench-filter';
|
|
142
|
+
button.dataset.debatesFilter = specs[i].key;
|
|
143
|
+
button.setAttribute('aria-pressed', specs[i].key === active ? 'true' : 'false');
|
|
144
|
+
button.textContent = specs[i].label;
|
|
145
|
+
filters.appendChild(button);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function debateRow(debate) {
|
|
150
|
+
var row = document.createElement('button');
|
|
151
|
+
row.type = 'button';
|
|
152
|
+
row.className = 'debates-workbench-row';
|
|
153
|
+
row.dataset.projectSlug = debate.projectSlug || '';
|
|
154
|
+
row.dataset.sessionId = String(debate.localId == null ? '' : debate.localId);
|
|
155
|
+
row.setAttribute('role', 'listitem');
|
|
156
|
+
var title = document.createElement('strong');
|
|
157
|
+
title.textContent = debate.topic || debate.title || 'Debate planning';
|
|
158
|
+
var panelists = document.createElement('span');
|
|
159
|
+
panelists.className = 'debates-workbench-row-panel';
|
|
160
|
+
panelists.textContent = participantsLabel(debate.participants);
|
|
161
|
+
var meta = document.createElement('span');
|
|
162
|
+
meta.className = 'debates-workbench-row-meta';
|
|
163
|
+
var phase = document.createElement('span');
|
|
164
|
+
phase.className = 'debates-workbench-phase';
|
|
165
|
+
phase.textContent = phaseLabel(debate.phase);
|
|
166
|
+
var date = document.createElement('span');
|
|
167
|
+
date.textContent = dateLabel(debate.lastActivity);
|
|
168
|
+
meta.appendChild(phase);
|
|
169
|
+
meta.appendChild(date);
|
|
170
|
+
row.appendChild(title);
|
|
171
|
+
row.appendChild(panelists);
|
|
172
|
+
row.appendChild(meta);
|
|
173
|
+
return row;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function render() {
|
|
177
|
+
if (!panel || panel.classList.contains('hidden')) return;
|
|
178
|
+
renderFilters();
|
|
179
|
+
panel.querySelector('form').classList.toggle('hidden', !store.get('debatesWorkbenchCreating'));
|
|
180
|
+
var summary = panel.querySelector('.debates-workbench-summary');
|
|
181
|
+
var list = panel.querySelector('.debates-workbench-list');
|
|
182
|
+
var status = store.get('debatesWorkbenchStatus') || 'idle';
|
|
183
|
+
var filter = store.get('debatesWorkbenchFilter') || 'all';
|
|
184
|
+
var debates = (store.get('debatesWorkbenchItems') || []).filter(function (item) { return filter === 'all' || item.phase === filter; });
|
|
185
|
+
list.innerHTML = '';
|
|
186
|
+
if (status === 'loading' || status === 'idle') {
|
|
187
|
+
summary.textContent = 'Loading debates…';
|
|
188
|
+
list.innerHTML = '<div class="debates-workbench-empty"><strong>Gathering your debates</strong>Planning sessions and completed debates will appear here.</div>';
|
|
189
|
+
} else if (status === 'error') {
|
|
190
|
+
summary.textContent = 'Debates could not be loaded.';
|
|
191
|
+
var failure = document.createElement('div');
|
|
192
|
+
failure.className = 'debates-workbench-empty';
|
|
193
|
+
var failureTitle = document.createElement('strong');
|
|
194
|
+
failureTitle.textContent = 'Could not load debates';
|
|
195
|
+
var failureText = document.createElement('span');
|
|
196
|
+
failureText.textContent = store.get('debatesWorkbenchError') || 'Try again when the connection is available.';
|
|
197
|
+
failure.appendChild(failureTitle);
|
|
198
|
+
failure.appendChild(failureText);
|
|
199
|
+
list.appendChild(failure);
|
|
200
|
+
} else if (!debates.length) {
|
|
201
|
+
summary.textContent = filter === 'all' ? 'No debates yet' : 'No ' + filter + ' debates';
|
|
202
|
+
list.innerHTML = '<div class="debates-workbench-empty"><strong>Nothing here yet</strong>Use New debate to plan one with Clay in the main chat.</div>';
|
|
203
|
+
} else {
|
|
204
|
+
summary.textContent = debates.length + (debates.length === 1 ? ' debate' : ' debates');
|
|
205
|
+
for (var i = 0; i < debates.length; i++) list.appendChild(debateRow(debates[i]));
|
|
206
|
+
}
|
|
207
|
+
list.scrollTop = Number(store.get('debatesWorkbenchScrollTop')) || 0;
|
|
208
|
+
refreshIcons();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function handleKeydown(event) {
|
|
212
|
+
if (event.key === 'Escape') {
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
closeDebatesWorkbench(true);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (event.key !== 'Tab' || !narrowLayout()) return;
|
|
218
|
+
var controls = panel.querySelectorAll('button:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');
|
|
219
|
+
if (!controls.length) return;
|
|
220
|
+
var first = controls[0];
|
|
221
|
+
var last = controls[controls.length - 1];
|
|
222
|
+
if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }
|
|
223
|
+
else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function applyWindowState(wide, fullscreen) {
|
|
227
|
+
store.set({ debatesWorkbenchWide: !!wide, debatesWorkbenchFullscreen: !!fullscreen });
|
|
228
|
+
panel.classList.toggle('debates-workbench-wide', !!wide && !fullscreen);
|
|
229
|
+
panel.classList.toggle('panel-fullscreen', !!fullscreen);
|
|
230
|
+
panel.querySelector('[data-debates-action="wide"]').setAttribute('aria-pressed', wide ? 'true' : 'false');
|
|
231
|
+
panel.querySelector('[data-debates-action="fullscreen"]').setAttribute('aria-pressed', fullscreen ? 'true' : 'false');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function handleClick(event) {
|
|
235
|
+
var filter = event.target.closest('[data-debates-filter]');
|
|
236
|
+
if (filter) { store.set({ debatesWorkbenchFilter: filter.dataset.debatesFilter }); render(); return; }
|
|
237
|
+
var row = event.target.closest('.debates-workbench-row');
|
|
238
|
+
if (row) {
|
|
239
|
+
var localId = Number(row.dataset.sessionId);
|
|
240
|
+
if (!row.dataset.projectSlug || !Number.isSafeInteger(localId) || localId < 1) return;
|
|
241
|
+
store.set({ pendingDebateNavigation: { projectSlug: row.dataset.projectSlug, sessionId: localId } });
|
|
242
|
+
if (narrowLayout()) closeDebatesWorkbench(false);
|
|
243
|
+
switchProject(row.dataset.projectSlug);
|
|
244
|
+
flushPendingNavigation();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
var action = event.target.closest('[data-debates-action]');
|
|
248
|
+
if (!action) return;
|
|
249
|
+
if (action.dataset.debatesAction === 'close') closeDebatesWorkbench(true);
|
|
250
|
+
if (action.dataset.debatesAction === 'new') {
|
|
251
|
+
store.set({ debatesWorkbenchCreating: true }); render();
|
|
252
|
+
panel.querySelector('textarea').focus({ preventScroll: true });
|
|
253
|
+
}
|
|
254
|
+
if (action.dataset.debatesAction === 'cancel-new') { store.set({ debatesWorkbenchCreating: false }); render(); }
|
|
255
|
+
if (action.dataset.debatesAction === 'wide') applyWindowState(!store.get('debatesWorkbenchWide'), false);
|
|
256
|
+
if (action.dataset.debatesAction === 'fullscreen') applyWindowState(false, !store.get('debatesWorkbenchFullscreen'));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function submitNewDebate(event) {
|
|
260
|
+
event.preventDefault();
|
|
261
|
+
var input = panel.querySelector('textarea');
|
|
262
|
+
var topic = input.value.trim();
|
|
263
|
+
if (!topic) { input.focus(); return; }
|
|
264
|
+
var status = panel.querySelector('.debates-workbench-launch-status');
|
|
265
|
+
status.textContent = 'Opening Clay in the main chat…';
|
|
266
|
+
if (!startProjectDebatePlanning(topic)) {
|
|
267
|
+
status.textContent = store.get('projectDebatePlanningError') || 'Clay is unavailable. Refresh and try again.';
|
|
268
|
+
input.focus();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
input.value = '';
|
|
272
|
+
store.set({ debatesWorkbenchCreating: false });
|
|
273
|
+
closeDebatesWorkbench();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function flushPendingNavigation() {
|
|
277
|
+
var pending = store.get('pendingDebateNavigation');
|
|
278
|
+
var ws = getWs();
|
|
279
|
+
if (!pending || store.get('activeProjectSlug') !== pending.projectSlug || !ws || ws.readyState !== 1) return;
|
|
280
|
+
store.set({ pendingDebateNavigation: null });
|
|
281
|
+
ws.send(JSON.stringify({ type: 'switch_session', id: pending.sessionId }));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function handleDebatesWorkbenchState(msg) {
|
|
285
|
+
if (!msg || msg.type !== 'home_debates_state') return false;
|
|
286
|
+
if (!isMateDebateSurface(store.snap())) return true;
|
|
287
|
+
if (msg.requestId && msg.requestId !== store.get('debatesWorkbenchRequestId')) return true;
|
|
288
|
+
store.set({ debatesWorkbenchStatus: msg.status === 'error' || msg.error ? 'error' : 'ready', debatesWorkbenchItems: Array.isArray(msg.debates) ? msg.debates : [], debatesWorkbenchError: msg.error || '' });
|
|
289
|
+
render();
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function openDebatesWorkbench(trigger) {
|
|
294
|
+
if (!isMateDebateSurface(store.snap())) return false;
|
|
295
|
+
if (!ensurePanel()) return;
|
|
296
|
+
opener = trigger && trigger.focus ? trigger : document.activeElement;
|
|
297
|
+
claimRightWorkbench('debates');
|
|
298
|
+
panel.classList.remove('hidden');
|
|
299
|
+
var narrow = narrowLayout();
|
|
300
|
+
panel.setAttribute('role', narrow ? 'dialog' : 'region');
|
|
301
|
+
panel.setAttribute('aria-modal', narrow ? 'true' : 'false');
|
|
302
|
+
setNarrowBackground(narrow);
|
|
303
|
+
applyWindowState(store.get('debatesWorkbenchWide'), store.get('debatesWorkbenchFullscreen'));
|
|
304
|
+
requestDebates();
|
|
305
|
+
requestAnimationFrame(function () { panel.querySelector('[data-debates-action="new"]').focus({ preventScroll: true }); });
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function closeDebatesWorkbench(restoreFocus) {
|
|
309
|
+
if (panel) {
|
|
310
|
+
var list = panel.querySelector('.debates-workbench-list');
|
|
311
|
+
if (list) store.set({ debatesWorkbenchScrollTop: list.scrollTop });
|
|
312
|
+
panel.classList.add('hidden');
|
|
313
|
+
}
|
|
314
|
+
setNarrowBackground(false);
|
|
315
|
+
releaseRightWorkbench('debates');
|
|
316
|
+
if (restoreFocus && opener && opener.isConnected) opener.focus({ preventScroll: true });
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function initDebatesWorkbench() {
|
|
320
|
+
registerRightWorkbench('debates', function () { closeDebatesWorkbench(false); });
|
|
321
|
+
var buttons = [ensureMateProjectDebatesButton(), document.getElementById('debates-btn'), document.getElementById('mate-debates-btn')];
|
|
322
|
+
for (var i = 0; i < buttons.length; i++) if (buttons[i]) buttons[i].addEventListener('click', function (event) {
|
|
323
|
+
if (panel && !panel.classList.contains('hidden')) closeDebatesWorkbench(true);
|
|
324
|
+
else openDebatesWorkbench(event.currentTarget);
|
|
325
|
+
});
|
|
326
|
+
store.subscribe(function (state, previous) {
|
|
327
|
+
if (state.activeProjectSlug !== previous.activeProjectSlug || state.connected !== previous.connected) flushPendingNavigation();
|
|
328
|
+
var wasMateWorkspace = isMateDebateSurface(previous);
|
|
329
|
+
var isMate = isMateDebateSurface(state);
|
|
330
|
+
if (wasMateWorkspace && !isMate) {
|
|
331
|
+
requestSequence += 1;
|
|
332
|
+
store.set({ debatesWorkbenchRequestId: null });
|
|
333
|
+
if (panel && !panel.classList.contains('hidden')) closeDebatesWorkbench(false);
|
|
334
|
+
} else if (state.currentSlug !== previous.currentSlug && panel && !panel.classList.contains('hidden')) {
|
|
335
|
+
if (isMate) requestDebates();
|
|
336
|
+
else closeDebatesWorkbench(false);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
@@ -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
|
});
|