clay-server 5.2.0-beta.3 → 5.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/builtin-mates.js +2 -2
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/knowledge-file-store.js +7 -1
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mates.js +14 -3
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +91 -0
- package/lib/mcp-source-context.js +42 -0
- package/lib/mcp-source-discovery.js +169 -0
- package/lib/mcp-source-plugins.js +68 -0
- package/lib/mcp-source-restrictions.js +47 -0
- package/lib/mcp-tool-policy.js +34 -0
- package/lib/project-ask-user.js +6 -4
- package/lib/project-debate.js +1 -0
- package/lib/project-mate-interaction.js +8 -0
- package/lib/project-mcp.js +54 -16
- package/lib/project-session-document.js +8 -3
- package/lib/project-session-github.js +16 -7
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +7 -3
- package/lib/project-sessions.js +6 -2
- package/lib/project-shared-browser.js +56 -12
- package/lib/project.js +49 -34
- package/lib/public/app.js +5 -0
- package/lib/public/appearance-bootstrap.js +14 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/session-github.css +43 -1
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/index.html +10 -4
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/app-message-router.js +4 -0
- package/lib/public/modules/app-messages.js +13 -2
- package/lib/public/modules/app-rendering.js +1 -1
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +10 -1
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-log-links.js +1 -1
- package/lib/public/modules/command-palette.js +1 -1
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/history-replay-batch.js +5 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +6 -6
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/markdown.js +4 -0
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/pane-browser-bridge.js +20 -0
- package/lib/public/modules/profile.js +1 -238
- package/lib/public/modules/project-mate-navigation.js +99 -14
- package/lib/public/modules/search-clay-chat.js +16 -2
- package/lib/public/modules/session-github.js +23 -9
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +27 -6
- package/lib/public/modules/split-view.js +2 -0
- package/lib/public/modules/theme.js +8 -1
- package/lib/public/modules/tools.js +2 -1
- package/lib/public/style.css +1 -0
- package/lib/public/sw.js +3 -1
- package/lib/sdk-bridge.js +9 -3
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-dm.js +1 -0
- package/lib/server-home-chat-events.js +14 -4
- package/lib/server-home-chat.js +10 -2
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +6 -1
- package/lib/server-settings.js +4 -1
- package/lib/server.js +45 -12
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +3 -0
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/yoke/acp-agent-profiles.js +2 -2
- package/package.json +5 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
|
+
import { showToast } from './utils.js';
|
|
4
|
+
import { forwardPaneBrowserLink } from './pane-browser-bridge.js';
|
|
5
|
+
|
|
6
|
+
function escape(value) { return String(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); }
|
|
7
|
+
export function browserLinkTarget(href) {
|
|
8
|
+
if (typeof href !== 'string' || !href.startsWith('browser:') || href.length > 8200) return null;
|
|
9
|
+
var raw = href.slice(8);
|
|
10
|
+
if (!/^https?:\/\//i.test(raw) || /[\u0000-\u0020]/.test(raw)) return null;
|
|
11
|
+
try {
|
|
12
|
+
var url = new URL(raw);
|
|
13
|
+
if (url.username || url.password || !['http:', 'https:'].includes(url.protocol)) return null;
|
|
14
|
+
return url.href;
|
|
15
|
+
} catch (error) { return null; }
|
|
16
|
+
}
|
|
17
|
+
export function renderBrowserLink(href, title, text) {
|
|
18
|
+
var url = browserLinkTarget(href);
|
|
19
|
+
if (!url) return null;
|
|
20
|
+
var label = String(text || '').replace(/<[^>]*>/g, '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").trim();
|
|
21
|
+
if (!label || label === href || label === url) label = new URL(url).host;
|
|
22
|
+
return '<button type="button" class="clay-browser-link clayos-record-link" data-browser-url="' + escape(url) + '" data-browser-project="' + escape(store.get('currentSlug') || '') + '" title="' + escape('Open in Clay Browser · ' + url) + '" aria-label="' + escape('Open in Clay Browser: ' + label) + '">' + iconHtml('globe') + '<span>Browser</span><small>' + escape(label) + '</small></button>';
|
|
23
|
+
}
|
|
24
|
+
export function enhanceBrowserLinks(root) {
|
|
25
|
+
if (!root || typeof document === 'undefined') return;
|
|
26
|
+
root.querySelectorAll('a[href]').forEach(function (anchor) {
|
|
27
|
+
if (anchor.closest('pre, code, button')) return;
|
|
28
|
+
var html = renderBrowserLink(anchor.getAttribute('href'), '', anchor.textContent);
|
|
29
|
+
if (html) { var template = document.createElement('template'); template.innerHTML = html; anchor.replaceWith(template.content); }
|
|
30
|
+
});
|
|
31
|
+
initBrowserLinks();
|
|
32
|
+
refreshIcons();
|
|
33
|
+
}
|
|
34
|
+
export function initBrowserLinks() {
|
|
35
|
+
if (store.get('browserLinksBound')) return;
|
|
36
|
+
store.set({ browserLinksBound: true });
|
|
37
|
+
document.addEventListener('click', function (event) {
|
|
38
|
+
var button = event.target.closest && event.target.closest('.clay-browser-link');
|
|
39
|
+
if (!button) return;
|
|
40
|
+
event.preventDefault(); event.stopPropagation();
|
|
41
|
+
var url = browserLinkTarget('browser:' + button.dataset.browserUrl);
|
|
42
|
+
if (!url) { showToast('This browser link is invalid.', 'warn'); return; }
|
|
43
|
+
if (button.dataset.browserProject && button.dataset.browserProject !== store.get('currentSlug')) { showToast('Open this link from its original project.', 'warn'); return; }
|
|
44
|
+
if (forwardPaneBrowserLink(url)) return;
|
|
45
|
+
import('./shared-browser.js').then(function (module) { module.openSharedBrowserAt(url); }).catch(function (error) { showToast(error.message || 'Could not open the browser.', 'warn'); });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -16,7 +16,7 @@ export function renderClaySessionLink(ref, text) {
|
|
|
16
16
|
var parsed = parseClaySessionReference(ref);
|
|
17
17
|
if (!parsed) return null;
|
|
18
18
|
var label = text ? String(text).trim() : "";
|
|
19
|
-
var safeLabel = escapeHtml(label);
|
|
19
|
+
var safeLabel = escapeHtml(label).replace(/"/g, """);
|
|
20
20
|
var entryAttr = parsed.entryIndex === null ? "" : ' data-session-entry-index="' + parsed.entryIndex + '"';
|
|
21
21
|
return '<button type="button" class="clayos-session-link clayos-record-link" data-session-ref="' + parsed.ref + '"' + entryAttr + ' aria-label="Open session' + (safeLabel ? " from " + safeLabel : "") + '"><span>Session</span>' + (safeLabel ? '<small>' + safeLabel + '</small>' : '') + '</button>';
|
|
22
22
|
}
|
|
@@ -205,7 +205,7 @@ export function handlePaletteHistoryPrepended() {
|
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
207
207
|
requestAnimationFrame(function () {
|
|
208
|
-
if (store.get('pendingSessionEntryNavigation') === pending)
|
|
208
|
+
if (store.get('pendingSessionEntryNavigation') === pending) handlePaletteHistoryDone();
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -58,6 +58,7 @@ function buildAvatarUrl(meta) {
|
|
|
58
58
|
return mateAvatarUrl({
|
|
59
59
|
id: meta.mateId,
|
|
60
60
|
profile: {
|
|
61
|
+
avatarCatalogId: meta.avatarCatalogId || "",
|
|
61
62
|
avatarStyle: meta.avatarStyle || "imprint",
|
|
62
63
|
avatarSeed: meta.avatarSeed || meta.mateId || "mate",
|
|
63
64
|
avatarColor: meta.avatarColor || "#5857fc",
|
|
@@ -27,7 +27,7 @@ function canCombine(previous, message) {
|
|
|
27
27
|
// can differ; the first token still supplies the message's display time.
|
|
28
28
|
var keys = Object.keys(previous).concat(Object.keys(message));
|
|
29
29
|
return keys.every(function (key) {
|
|
30
|
-
return key === 'text' || key === '_ts' || previous[key] === message[key];
|
|
30
|
+
return key === 'text' || key === '_ts' || key === '_historyIndex' || key === '_historyIndexes' || previous[key] === message[key];
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -105,6 +105,10 @@ export function receiveHistoryReplay(msg, dispatch) {
|
|
|
105
105
|
if (canCombine(previous, msg)) {
|
|
106
106
|
if (!batch.textParts) batch.textParts = [previous.text];
|
|
107
107
|
batch.textParts.push(msg.text);
|
|
108
|
+
if (Number.isSafeInteger(msg._historyIndex) && msg._historyIndex >= 0) {
|
|
109
|
+
if (!previous._historyIndexes) previous._historyIndexes = Number.isSafeInteger(previous._historyIndex) ? [previous._historyIndex] : [];
|
|
110
|
+
previous._historyIndexes.push(msg._historyIndex);
|
|
111
|
+
}
|
|
108
112
|
} else {
|
|
109
113
|
finishText(batch);
|
|
110
114
|
batch.items.push(Object.assign({}, msg));
|
|
@@ -23,6 +23,7 @@ function debateIdentity(message, prior) {
|
|
|
23
23
|
return {
|
|
24
24
|
mateId: message.speakerMateId || message.mateId || previous.mateId || null,
|
|
25
25
|
mateName: name,
|
|
26
|
+
avatarCatalogId: message.avatarCatalogId || previous.avatarCatalogId || cachedProfile.avatarCatalogId || "",
|
|
26
27
|
avatarStyle: message.avatarStyle || previous.avatarStyle || cachedProfile.avatarStyle || "imprint",
|
|
27
28
|
avatarSeed: message.avatarSeed || previous.avatarSeed || cachedProfile.avatarSeed || message.speakerMateId || message.mateId || name,
|
|
28
29
|
avatarColor: message.avatarColor || previous.avatarColor || cachedProfile.avatarColor || "",
|
|
@@ -37,6 +38,7 @@ function mateForTurn(message) {
|
|
|
37
38
|
name: identity.mateName,
|
|
38
39
|
profile: {
|
|
39
40
|
displayName: identity.mateName,
|
|
41
|
+
avatarCatalogId: identity.avatarCatalogId,
|
|
40
42
|
avatarStyle: identity.avatarStyle,
|
|
41
43
|
avatarSeed: identity.avatarSeed,
|
|
42
44
|
avatarColor: identity.avatarColor,
|
|
@@ -123,11 +123,11 @@ export function createHomeDebateProposalCard(message, respond) {
|
|
|
123
123
|
export function createHomeDebateQuestionCard(message, respond) {
|
|
124
124
|
var question = Array.isArray(message.questions) && message.questions.length ? message.questions[0] : {};
|
|
125
125
|
var card = document.createElement("section");
|
|
126
|
-
card.className = "home-debate-question";
|
|
126
|
+
card.className = "home-debate-question" + (message.flow === "mcp_import" ? " mcp-import-consent" : "");
|
|
127
127
|
card.dataset.toolId = message.toolId || "";
|
|
128
128
|
card.setAttribute("aria-busy", message.status === "submitting" ? "true" : "false");
|
|
129
|
-
var isMateCreation = message.flow === "mate_creation";
|
|
130
|
-
card.setAttribute("aria-label", (isMateCreation ? "Mate creation interview question: " : "Debate planning question: ") + (question.question || "Question"));
|
|
129
|
+
var isMateCreation = message.flow === "mate_creation", isMcpImport = message.flow === "mcp_import";
|
|
130
|
+
card.setAttribute("aria-label", (isMcpImport ? "MCP import consent: " : isMateCreation ? "Mate creation interview question: " : "Debate planning question: ") + (question.question || "Question"));
|
|
131
131
|
if (question.header) card.appendChild(textElement("div", "home-debate-question-header", question.header));
|
|
132
132
|
card.appendChild(textElement("h3", "home-debate-question-text", question.question || "Clay has a question."));
|
|
133
133
|
var form = document.createElement("div");
|
|
@@ -162,8 +162,8 @@ export function createHomeDebateQuestionCard(message, respond) {
|
|
|
162
162
|
answerControl.className = freeform ? "home-debate-question-freeform" : "home-debate-question-other";
|
|
163
163
|
answerControl.placeholder = freeform ? (isMateCreation ? "Describe what you want in your own words" : "Describe the topic in your own words") : "Type another answer";
|
|
164
164
|
answerLabel.appendChild(answerControl);
|
|
165
|
-
form.appendChild(answerLabel);
|
|
166
|
-
var submit = textElement("button", "home-debate-question-submit", message.status === "submitting" ? "Submitting…" : "Submit answer");
|
|
165
|
+
if (freeform || question.allowOther !== false) form.appendChild(answerLabel);
|
|
166
|
+
var submit = textElement("button", "home-debate-question-submit", message.status === "submitting" ? "Submitting…" : isMcpImport ? "Confirm choice" : "Submit answer");
|
|
167
167
|
submit.type = "button";
|
|
168
168
|
submit.disabled = message.status !== "pending" || !selected;
|
|
169
169
|
function submitAnswer() {
|
|
@@ -253,7 +253,7 @@ export function normalizeHomeTranscript(raw) {
|
|
|
253
253
|
export function applyHomeDebateQuestion(messages, msg) {
|
|
254
254
|
if (!msg || !msg.toolId) return messages;
|
|
255
255
|
for (var i = 0; i < messages.length; i++) if (messages[i].role === "question" && messages[i].toolId === msg.toolId) return messages;
|
|
256
|
-
return messages.concat([{ role: "question", flow: msg.type === "home_mate_creation_question" ? "mate_creation" : "debate", toolId: msg.toolId, questions: msg.questions || [], status: "pending", error: "" }]);
|
|
256
|
+
return messages.concat([{ role: "question", flow: msg.type === "home_mcp_import_question" ? "mcp_import" : msg.type === "home_mate_creation_question" ? "mate_creation" : "debate", toolId: msg.toolId, questions: msg.questions || [], status: "pending", error: "" }]);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
export function resolveHomeDebateQuestion(messages, msg) {
|
|
@@ -296,7 +296,7 @@ export function markHomeDebateQuestionSubmitting(message, opener) {
|
|
|
296
296
|
export function createHomeDebateResponder(sendMessage, getContext, onChange) {
|
|
297
297
|
return function respond(message, action, opener, answers, modelOverrides) {
|
|
298
298
|
if (!message || message.status === "submitting") return;
|
|
299
|
-
var payload = message.role === "question" ? { type: message.flow === "mate_creation" ? "home_mate_creation_question_response" : "home_debate_question_response", toolId: message.toolId, answers: answers || {} } : { type: "home_debate_proposal_response", proposalId: message.proposal.proposalId, action: action, modelOverrides: Array.isArray(modelOverrides) ? modelOverrides : [] };
|
|
299
|
+
var payload = message.role === "question" ? { type: message.flow === "mcp_import" ? "home_mcp_import_response" : message.flow === "mate_creation" ? "home_mate_creation_question_response" : "home_debate_question_response", toolId: message.toolId, answers: answers || {} } : { type: "home_debate_proposal_response", proposalId: message.proposal.proposalId, action: action, modelOverrides: Array.isArray(modelOverrides) ? modelOverrides : [] };
|
|
300
300
|
Object.assign(payload, getContext());
|
|
301
301
|
if (!sendMessage(payload)) return;
|
|
302
302
|
if (message.role === "question") markHomeDebateQuestionSubmitting(message, opener);
|
|
@@ -1,228 +1,147 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
import { mateStyleAvatarUrl, mateAvatarUrl, MATE_AVATAR_STYLES } from './avatar.js';
|
|
1
|
+
// Explicit avatar drafts in the existing owner-scoped Mate settings surface.
|
|
2
|
+
import { mateAvatarUrl, mateCatalogAvatarUrl } from './avatar.js';
|
|
4
3
|
import { showAvatarPositioner } from './profile.js';
|
|
5
4
|
import { getWs } from './ws-ref.js';
|
|
6
5
|
import { store } from './store.js';
|
|
6
|
+
import { MATE_AVATAR_COLLECTIONS } from './mate-avatar-catalog.js';
|
|
7
7
|
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function mateName(mate) {
|
|
15
|
-
var profile = mate && mate.profile ? mate.profile : {};
|
|
16
|
-
return profile.displayName || (mate && (mate.displayName || mate.name)) || 'Mate';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function mateProfile(mate) {
|
|
20
|
-
return Object.assign({}, mate && mate.profile ? mate.profile : {});
|
|
8
|
+
var timer = null;
|
|
9
|
+
function state() { return store.get('mateAvatarDraft'); }
|
|
10
|
+
function put(value) { store.set({ mateAvatarDraft: value }); }
|
|
11
|
+
function profile(mate) { return Object.assign({}, mate.profile || {}); }
|
|
12
|
+
function currentMate(mate) {
|
|
13
|
+
return (store.get('cachedMatesList') || []).find(function (item) { return item.id === mate.id; }) || mate;
|
|
21
14
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return false;
|
|
15
|
+
function ensure(mate) {
|
|
16
|
+
var s = state();
|
|
17
|
+
if (!s || s.mateId !== mate.id) {
|
|
18
|
+
s = { mateId: mate.id, selected: (mate.profile || {}).avatarCatalogId || '', dirty: false, requestId: null, error: '', saved: false, uploading: false };
|
|
19
|
+
put(s);
|
|
20
|
+
} else if (!s.dirty && !s.requestId && !s.uploading && s.selected !== ((mate.profile || {}).avatarCatalogId || '')) {
|
|
21
|
+
s = Object.assign({}, s, { selected: (mate.profile || {}).avatarCatalogId || '' }); put(s);
|
|
30
22
|
}
|
|
31
|
-
|
|
32
|
-
statusByMate[mate.id] = { kind: 'pending', text: message || 'Saving avatar…' };
|
|
33
|
-
ws.send(JSON.stringify({ type: 'mate_update', mateId: mate.id, updates: { profile: profile } }));
|
|
34
|
-
rerender();
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function appendStatus(body, mate) {
|
|
39
|
-
var state = statusByMate[mate.id];
|
|
40
|
-
var status = document.createElement('div');
|
|
41
|
-
status.className = 'home-mate-avatar-status' + (state ? ' is-' + state.kind : '');
|
|
42
|
-
status.setAttribute('aria-live', 'polite');
|
|
43
|
-
status.textContent = state ? state.text : '';
|
|
44
|
-
body.appendChild(status);
|
|
23
|
+
return s;
|
|
45
24
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
button.setAttribute('aria-label', label + ' avatar');
|
|
52
|
-
button.setAttribute('aria-pressed', selected ? 'true' : 'false');
|
|
53
|
-
button.title = label;
|
|
54
|
-
var image = document.createElement('img');
|
|
55
|
-
image.src = src;
|
|
56
|
-
image.alt = '';
|
|
57
|
-
image.draggable = false;
|
|
58
|
-
var text = document.createElement('span');
|
|
59
|
-
text.textContent = label;
|
|
60
|
-
button.appendChild(image);
|
|
61
|
-
button.appendChild(text);
|
|
62
|
-
return button;
|
|
25
|
+
function button(label, id, action) {
|
|
26
|
+
var b = document.createElement('button');
|
|
27
|
+
b.type = 'button'; b.textContent = label; b.id = id;
|
|
28
|
+
b.addEventListener('click', action);
|
|
29
|
+
return b;
|
|
63
30
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
profile.avatarCustom = '';
|
|
70
|
-
sendProfile(mate, profile, rerender);
|
|
31
|
+
function closePicker(render) {
|
|
32
|
+
clearHomeMateAvatarEditor();
|
|
33
|
+
store.set({ mateSettingsAvatarOpen: false }); render();
|
|
34
|
+
var opener = document.getElementById('mate-profile-avatar');
|
|
35
|
+
if (opener) opener.focus();
|
|
71
36
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}).then(function (response) {
|
|
84
|
-
return response.json().then(function (data) {
|
|
85
|
-
if (!response.ok || !data.ok || !data.avatar) throw new Error(data.error || 'Upload failed');
|
|
86
|
-
return data.avatar;
|
|
87
|
-
});
|
|
88
|
-
}).then(function (avatar) {
|
|
89
|
-
if (token !== activeToken) return;
|
|
90
|
-
var profile = mateProfile(mate);
|
|
91
|
-
profile.avatarCustom = avatar;
|
|
92
|
-
draftByMate[mate.id] = profile;
|
|
93
|
-
statusByMate[mate.id] = { kind: 'saved', text: 'Image saved.' };
|
|
94
|
-
var mates = store.get('cachedMatesList') || [];
|
|
95
|
-
store.set({ cachedMatesList: mates.map(function (item) {
|
|
96
|
-
return item && item.id === mate.id ? Object.assign({}, item, { profile: profile }) : item;
|
|
97
|
-
}) });
|
|
98
|
-
var ws = getWs();
|
|
99
|
-
if (ws && ws.readyState === 1) {
|
|
100
|
-
ws.send(JSON.stringify({ type: 'mate_update', mateId: mate.id, updates: { profile: profile } }));
|
|
101
|
-
}
|
|
102
|
-
rerender();
|
|
103
|
-
}).catch(function (error) {
|
|
104
|
-
if (token !== activeToken) return;
|
|
105
|
-
statusByMate[mate.id] = { kind: 'error', text: error && error.message ? error.message : 'Could not upload this image.' };
|
|
106
|
-
rerender();
|
|
107
|
-
});
|
|
37
|
+
function save(mate, render) {
|
|
38
|
+
var s = state(); var ws = getWs();
|
|
39
|
+
if (!s || s.requestId || !s.dirty) return;
|
|
40
|
+
if (!ws || ws.readyState !== 1) { put(Object.assign({}, s, { error: 'Clay is offline. Your choice was not saved.' })); render(); return; }
|
|
41
|
+
var requestId = 'mate-avatar-' + Date.now() + '-' + Math.random().toString(36).slice(2);
|
|
42
|
+
var p = profile(currentMate(mate)); p.avatarCatalogId = s.selected; p.avatarCustom = '';
|
|
43
|
+
put(Object.assign({}, s, { requestId: requestId, error: '', saved: false })); render();
|
|
44
|
+
try { ws.send(JSON.stringify({ type: 'mate_update', mateId: mate.id, requestId: requestId, updates: { profile: p } })); }
|
|
45
|
+
catch (error) { failHomeMateAvatar(mate.id, 'Could not send your choice. Try again.', requestId); render(); return; }
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
timer = setTimeout(function () { if (failHomeMateAvatar(mate.id, 'No response received. Your choice is retained; try again.', requestId)) render(); }, 15000);
|
|
108
48
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
var
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
49
|
+
function upload(mate, input, render) {
|
|
50
|
+
var file = input.files && input.files[0]; if (!file) return;
|
|
51
|
+
var image = new Image(); var url = URL.createObjectURL(file); var originalState = state();
|
|
52
|
+
image.onerror = function () {
|
|
53
|
+
URL.revokeObjectURL(url);
|
|
54
|
+
if (state() === originalState) { put(Object.assign({}, originalState, { error: 'Could not read this image.' })); render(); }
|
|
55
|
+
};
|
|
116
56
|
image.onload = function () {
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
57
|
+
if (state() !== originalState) { URL.revokeObjectURL(url); return; }
|
|
58
|
+
showAvatarPositioner(image, url, function (blob) {
|
|
59
|
+
URL.revokeObjectURL(url);
|
|
60
|
+
if (state() !== originalState) return;
|
|
61
|
+
var uploadingState = Object.assign({}, originalState, { uploading: true, error: '' }); put(uploadingState); render();
|
|
62
|
+
blob.arrayBuffer().then(function (buffer) {
|
|
63
|
+
return fetch('/api/mate-avatar/' + encodeURIComponent(mate.id), { method: 'POST', headers: { 'Content-Type': 'application/octet-stream' }, body: new Uint8Array(buffer) });
|
|
64
|
+
}).then(function (response) {
|
|
65
|
+
return response.json().then(function (data) { if (!response.ok || !data.ok || !data.avatar) throw new Error(data.error || 'Upload failed.'); return data.avatar; });
|
|
66
|
+
}).then(function (avatar) {
|
|
67
|
+
if (state() !== uploadingState) return;
|
|
68
|
+
var p = profile(currentMate(mate)); p.avatarCustom = avatar;
|
|
69
|
+
store.set({ cachedMatesList: (store.get('cachedMatesList') || []).map(function (item) { return item.id === mate.id ? Object.assign({}, item, { profile: p }) : item; }) });
|
|
70
|
+
put(Object.assign({}, uploadingState, { uploading: false, dirty: false, saved: true }));
|
|
71
|
+
// The HTTP upload is persisted; the update also refreshes other owner tabs.
|
|
72
|
+
var ws = getWs();
|
|
73
|
+
if (ws && ws.readyState === 1) {
|
|
74
|
+
try { ws.send(JSON.stringify({ type: 'mate_update', mateId: mate.id, updates: { profile: p } })); }
|
|
75
|
+
catch (error) { /* The acknowledged upload remains saved. */ }
|
|
76
|
+
}
|
|
77
|
+
render();
|
|
78
|
+
}).catch(function (error) {
|
|
79
|
+
if (state() !== uploadingState) return;
|
|
80
|
+
put(Object.assign({}, uploadingState, { uploading: false, error: error.message || 'Could not upload this image.' })); render();
|
|
81
|
+
});
|
|
124
82
|
});
|
|
125
83
|
};
|
|
126
|
-
image.
|
|
127
|
-
URL.revokeObjectURL(objectUrl);
|
|
128
|
-
if (token !== activeToken) return;
|
|
129
|
-
statusByMate[mate.id] = { kind: 'error', text: 'Could not read this image.' };
|
|
130
|
-
rerender();
|
|
131
|
-
};
|
|
132
|
-
image.src = objectUrl;
|
|
84
|
+
image.src = url;
|
|
133
85
|
}
|
|
134
|
-
|
|
135
|
-
export function renderHomeMateAvatarEditor(body, mate, rerender) {
|
|
86
|
+
export function renderHomeMateAvatarEditor(body, mate, render, onCancel) {
|
|
136
87
|
if (!mate) return;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
choice.addEventListener('click', function () { selectStyle(mate, entry.id, seed, rerender); });
|
|
173
|
-
choices.appendChild(choice);
|
|
174
|
-
})(MATE_AVATAR_STYLES[i]);
|
|
175
|
-
}
|
|
176
|
-
section.appendChild(choices);
|
|
177
|
-
var actions = document.createElement('div');
|
|
178
|
-
actions.className = 'home-mate-avatar-actions';
|
|
179
|
-
var shuffle = document.createElement('button');
|
|
180
|
-
shuffle.type = 'button';
|
|
181
|
-
shuffle.textContent = 'Shuffle selected style';
|
|
182
|
-
shuffle.disabled = style === 'imprint' || style === 'initial' || !!profile.avatarCustom;
|
|
183
|
-
shuffle.addEventListener('click', function () {
|
|
184
|
-
selectStyle(mate, style, Math.random().toString(36).substring(2, 10), rerender);
|
|
88
|
+
var s = ensure(mate); var p = profile(mate); var busy = !!s.requestId || s.uploading;
|
|
89
|
+
var section = document.createElement('section'); section.className = 'home-mate-avatar-editor';
|
|
90
|
+
var preview = document.createElement('div'); preview.className = 'home-mate-avatar-selection';
|
|
91
|
+
var image = document.createElement('img'); image.className = 'home-mate-avatar-preview';
|
|
92
|
+
image.src = s.dirty ? mateCatalogAvatarUrl(s.selected) : mateAvatarUrl(mate, 52); image.alt = 'Avatar preview';
|
|
93
|
+
var caption = document.createElement('p'); caption.textContent = s.dirty ? 'Preview' : 'Current avatar';
|
|
94
|
+
preview.appendChild(image); preview.appendChild(caption); section.appendChild(preview);
|
|
95
|
+
if (!p.avatarLocked) {
|
|
96
|
+
MATE_AVATAR_COLLECTIONS.forEach(function (collection) {
|
|
97
|
+
var family = collection.id;
|
|
98
|
+
var heading = document.createElement('h4'); heading.textContent = collection.name;
|
|
99
|
+
heading.id = 'mate-avatar-family-' + family; section.appendChild(heading);
|
|
100
|
+
var grid = document.createElement('div'); grid.className = 'home-mate-avatar-choices';
|
|
101
|
+
grid.setAttribute('role', 'group'); grid.setAttribute('aria-labelledby', heading.id);
|
|
102
|
+
collection.avatars.forEach(function (entry) {
|
|
103
|
+
var id = entry.id;
|
|
104
|
+
var choice = button(id, 'mate-avatar-' + id, function () {
|
|
105
|
+
put(Object.assign({}, state(), { selected: id, dirty: id !== (currentMate(mate).profile || {}).avatarCatalogId || !!(currentMate(mate).profile || {}).avatarCustom, error: '', saved: false }));
|
|
106
|
+
render(); var target = document.getElementById('mate-avatar-' + id); if (target) target.focus({ preventScroll: true });
|
|
107
|
+
});
|
|
108
|
+
choice.textContent = ''; choice.className = 'home-mate-avatar-choice'; choice.disabled = busy;
|
|
109
|
+
choice.setAttribute('aria-label', entry.name + ' avatar'); choice.title = entry.name; choice.setAttribute('aria-pressed', String(s.selected === id && (s.dirty || !p.avatarCustom)));
|
|
110
|
+
var img = document.createElement('img'); img.src = mateCatalogAvatarUrl(id); img.alt = ''; img.draggable = false;
|
|
111
|
+
choice.appendChild(img);
|
|
112
|
+
choice.addEventListener('keydown', function (event) {
|
|
113
|
+
var buttons = Array.from(grid.querySelectorAll('button')); var index = buttons.indexOf(choice);
|
|
114
|
+
var columns = getComputedStyle(grid).gridTemplateColumns.split(' ').length;
|
|
115
|
+
var offset = { ArrowRight: 1, ArrowLeft: -1, ArrowDown: columns, ArrowUp: -columns }[event.key];
|
|
116
|
+
if (offset !== undefined || event.key === 'Home' || event.key === 'End') {
|
|
117
|
+
event.preventDefault(); var next = event.key === 'Home' ? 0 : event.key === 'End' ? 47 : Math.max(0, Math.min(47, index + offset)); buttons[next].focus();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
grid.appendChild(choice);
|
|
121
|
+
});
|
|
122
|
+
section.appendChild(grid);
|
|
185
123
|
});
|
|
186
|
-
var
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
input.type = 'file';
|
|
191
|
-
input.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
input.tabIndex = -1;
|
|
195
|
-
input.setAttribute('aria-hidden', 'true');
|
|
196
|
-
input.addEventListener('change', function () { openUpload(mate, input, rerender); });
|
|
197
|
-
upload.addEventListener('click', function () { input.click(); });
|
|
198
|
-
actions.appendChild(shuffle);
|
|
199
|
-
actions.appendChild(upload);
|
|
200
|
-
actions.appendChild(input);
|
|
201
|
-
section.appendChild(actions);
|
|
124
|
+
var actions = document.createElement('div'); actions.className = 'home-mate-avatar-actions';
|
|
125
|
+
var cancel = button('Cancel', 'mate-avatar-cancel', function () { if (onCancel) onCancel(); else closePicker(render); }); cancel.disabled = busy;
|
|
126
|
+
var saveButton = button('Save avatar', 'mate-avatar-save', function () { save(mate, render); }); saveButton.disabled = busy || !s.dirty;
|
|
127
|
+
saveButton.className = 'primary';
|
|
128
|
+
var input = document.createElement('input'); input.type = 'file'; input.accept = 'image/png,image/jpeg,image/gif,image/webp'; input.hidden = true; input.tabIndex = -1;
|
|
129
|
+
input.className = 'home-mate-avatar-file-input'; input.addEventListener('change', function () { upload(mate, input, render); });
|
|
130
|
+
var uploadButton = button('Upload image', 'mate-avatar-upload', function () { input.click(); }); uploadButton.disabled = busy;
|
|
131
|
+
actions.appendChild(cancel); actions.appendChild(saveButton); actions.appendChild(uploadButton); actions.appendChild(input); section.appendChild(actions);
|
|
202
132
|
}
|
|
203
|
-
|
|
204
|
-
|
|
133
|
+
var status = document.createElement('p'); status.className = 'home-mate-avatar-status' + (s.error ? ' is-error' : '');
|
|
134
|
+
status.setAttribute('aria-live', 'polite'); status.setAttribute('role', s.error ? 'alert' : 'status'); status.textContent = s.error || (s.requestId ? 'Saving avatar…' : s.uploading ? 'Uploading image…' : s.saved ? 'Avatar saved.' : 'Choose a face, then save.');
|
|
135
|
+
(actions || section).appendChild(status); body.appendChild(section);
|
|
205
136
|
}
|
|
206
|
-
|
|
207
|
-
export function
|
|
208
|
-
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
pending = null;
|
|
212
|
-
delete draftByMate[mate.id];
|
|
213
|
-
statusByMate[mate.id] = { kind: 'saved', text: 'Avatar saved.' };
|
|
214
|
-
return true;
|
|
137
|
+
export function hasHomeMateAvatarDraft() { var s = state(); return !!s && s.dirty; }
|
|
138
|
+
export function homeMateAvatarSaving() { var s = state(); return !!s && (!!s.requestId || s.uploading); }
|
|
139
|
+
export function confirmHomeMateAvatar(mate, requestId) {
|
|
140
|
+
var s = state(); if (!mate || !s || s.mateId !== mate.id || !s.requestId || s.requestId !== requestId || (mate.profile || {}).avatarCatalogId !== s.selected) return false;
|
|
141
|
+
clearTimeout(timer); put(Object.assign({}, s, { requestId: null, dirty: false, saved: true, error: '' })); return true;
|
|
215
142
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
statusByMate[pending.mateId] = { kind: 'error', text: message || 'Could not save this avatar.' };
|
|
220
|
-
pending = null;
|
|
221
|
-
return true;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export function clearHomeMateAvatarEditor() {
|
|
225
|
-
activeToken++;
|
|
226
|
-
activeMateId = null;
|
|
227
|
-
pending = null;
|
|
143
|
+
export function failHomeMateAvatar(mateId, message, requestId) {
|
|
144
|
+
var s = state(); if (!s || !s.requestId || s.mateId !== mateId || s.requestId !== requestId) return false;
|
|
145
|
+
clearTimeout(timer); put(Object.assign({}, s, { requestId: null, error: message || 'Could not save this avatar.' })); return true;
|
|
228
146
|
}
|
|
147
|
+
export function clearHomeMateAvatarEditor() { clearTimeout(timer); put(null); }
|
|
@@ -340,24 +340,24 @@ export function handleHomeDebateTranscript(msg) {
|
|
|
340
340
|
if (!isCurrentSessionMessage(msg)) return;
|
|
341
341
|
markHomeChatActivity();
|
|
342
342
|
settleHomeDebateLaunch(msg);
|
|
343
|
-
if (msg.type === "home_debate_proposal" || msg.type === "home_debate_question" || msg.type === "home_debate_event" || msg.type === "home_mate_creation_proposal" || msg.type === "home_mate_creation_question") messages = finalizeHomeAssistant(messages, streamingText, "", Date.now());
|
|
343
|
+
if (msg.type === "home_debate_proposal" || (msg.type === "home_debate_question" || msg.type === "home_mcp_import_question") || msg.type === "home_debate_event" || msg.type === "home_mate_creation_proposal" || msg.type === "home_mate_creation_question") messages = finalizeHomeAssistant(messages, streamingText, "", Date.now());
|
|
344
344
|
if (msg.type === "home_debate_event") messages = applyHomeDebateEvent(messages, msg);
|
|
345
345
|
if (msg.type === "home_debate_proposal") messages = applyHomeDebateProposal(messages, msg);
|
|
346
346
|
if (msg.type === "home_debate_proposal_resolved") messages = resolveHomeDebateProposal(messages, msg);
|
|
347
|
-
if (msg.type === "home_debate_question") messages = applyHomeDebateQuestion(messages, msg);
|
|
348
|
-
if (msg.type === "home_debate_question_resolved") messages = resolveHomeDebateQuestion(messages, msg);
|
|
347
|
+
if ((msg.type === "home_debate_question" || msg.type === "home_mcp_import_question")) messages = applyHomeDebateQuestion(messages, msg);
|
|
348
|
+
if ((msg.type === "home_debate_question_resolved" || msg.type === "home_mcp_import_question_resolved")) messages = resolveHomeDebateQuestion(messages, msg);
|
|
349
349
|
if (msg.type === "home_mate_creation_question") messages = applyHomeDebateQuestion(messages, msg);
|
|
350
350
|
if (msg.type === "home_mate_creation_question_resolved") messages = resolveHomeDebateQuestion(messages, msg);
|
|
351
351
|
if (msg.type === "home_mate_creation_proposal") messages = applyHomeMateProposal(messages, msg);
|
|
352
352
|
if (msg.type === "home_mate_creation_proposal_resolved") messages = resolveHomeMateProposal(messages, msg);
|
|
353
353
|
if (msg.type === "home_mate_error" && /^question_/.test(msg.code || "")) messages = failHomeDebateQuestion(messages, msg);
|
|
354
|
-
if (msg.type === "home_debate_proposal" || msg.type === "home_debate_question" || msg.type === "home_debate_event" || msg.type === "home_mate_creation_proposal" || msg.type === "home_mate_creation_question") { clearHomeDebatePlanningPending(); streaming = false; streamingText = ""; }
|
|
355
|
-
if ((msg.type === "home_debate_question_resolved" || msg.type === "home_mate_creation_question_resolved") && msg.status === "expired") clearHomeDebatePlanningPending();
|
|
354
|
+
if (msg.type === "home_debate_proposal" || (msg.type === "home_debate_question" || msg.type === "home_mcp_import_question") || msg.type === "home_debate_event" || msg.type === "home_mate_creation_proposal" || msg.type === "home_mate_creation_question") { clearHomeDebatePlanningPending(); streaming = false; streamingText = ""; }
|
|
355
|
+
if (((msg.type === "home_debate_question_resolved" || msg.type === "home_mcp_import_question_resolved") || msg.type === "home_mate_creation_question_resolved") && msg.status === "expired") clearHomeDebatePlanningPending();
|
|
356
356
|
renderHomeChat();
|
|
357
357
|
if (msg.proposalId) restoreHomeDebateProposalFocus(msg.proposalId);
|
|
358
358
|
if (msg.proposalId && msg.type === "home_mate_creation_proposal_resolved") restoreHomeMateProposalFocus(msg.proposalId);
|
|
359
359
|
if (msg.toolId && msg.type === "home_mate_creation_question") restoreHomeDebateQuestionFocus(msg.toolId);
|
|
360
|
-
if (msg.toolId && msg.type === "home_debate_question_resolved") restoreHomeDebateQuestionFocus(msg.toolId);
|
|
360
|
+
if (msg.toolId && (msg.type === "home_debate_question_resolved" || msg.type === "home_mcp_import_question_resolved")) restoreHomeDebateQuestionFocus(msg.toolId);
|
|
361
361
|
if (msg.toolId && msg.type === "home_mate_error") restoreHomeDebateQuestionFocus(msg.toolId);
|
|
362
362
|
}
|
|
363
363
|
export function handleHomeMateDelta(msg) {
|