clay-server 3.8.1 → 4.0.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/lib/ask-user-mcp-server.js +5 -119
- package/lib/builtin-mates.js +6 -6
- package/lib/claude-hook-installer.js +15 -0
- package/lib/clay-history-mcp-server.js +62 -297
- package/lib/daemon.js +1 -1
- package/lib/debate-model-selection.js +119 -0
- package/lib/home-debate-tool-policy.js +164 -0
- package/lib/home-response-notifications.js +26 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-ready-creation.js +95 -0
- package/lib/mates.js +2 -0
- package/lib/notes.js +2 -1
- package/lib/project-ask-user.js +64 -0
- package/lib/project-capsule-catalog.js +101 -0
- package/lib/project-connection.js +4 -0
- package/lib/project-debate-proposal.js +133 -17
- package/lib/project-debate.js +214 -110
- package/lib/project-delegated-follow-up.js +84 -0
- package/lib/project-delegated-session.js +53 -0
- package/lib/project-filesystem.js +7 -9
- package/lib/project-knowledge.js +1 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-memory.js +14 -7
- package/lib/project-models.js +157 -32
- package/lib/project-session-notes.js +2 -2
- package/lib/project-session-pair.js +8 -8
- package/lib/project-sessions.js +66 -51
- package/lib/project-vendor-login.js +397 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +349 -102
- package/lib/public/app.js +85 -42
- package/lib/public/css/avatar-imprints.css +0 -1
- package/lib/public/css/base.css +4 -0
- package/lib/public/css/capsule-ui.css +389 -0
- package/lib/public/css/command-palette.css +306 -6
- package/lib/public/css/home-capsule-library.css +243 -0
- package/lib/public/css/home-capsule-source.css +192 -0
- package/lib/public/css/home-debate-live.css +146 -0
- package/lib/public/css/home-debate-planning.css +125 -0
- package/lib/public/css/home-debates-archive.css +281 -0
- package/lib/public/css/home-hub.css +896 -405
- package/lib/public/css/home-mate-creation.css +34 -0
- package/lib/public/css/home-mate-model-picker.css +131 -0
- package/lib/public/css/home-mate-settings.css +344 -0
- package/lib/public/css/home-session-actions.css +265 -0
- package/lib/public/css/home-sidebar.css +667 -0
- package/lib/public/css/icon-strip.css +1 -2
- package/lib/public/css/mates.css +7 -34
- package/lib/public/css/pane.css +1 -1
- package/lib/public/css/playbook.css +0 -80
- package/lib/public/css/sticky-notes.css +53 -117
- package/lib/public/css/tui-attention.css +0 -44
- package/lib/public/css/workspace-assignment.css +45 -0
- package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
- package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
- package/lib/public/index.html +93 -74
- package/lib/public/modules/app-connection.js +10 -1
- package/lib/public/modules/app-dm.js +43 -160
- package/lib/public/modules/app-home-hub.js +328 -585
- package/lib/public/modules/app-message-cards.js +242 -0
- package/lib/public/modules/app-message-router.js +84 -0
- package/lib/public/modules/app-messages.js +102 -37
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-projects.js +9 -1
- package/lib/public/modules/app-rendering.js +21 -602
- package/lib/public/modules/avatar-imprint.js +11 -8
- package/lib/public/modules/chat-bubble-renderer.js +152 -0
- package/lib/public/modules/chat-render-runtime.js +198 -0
- package/lib/public/modules/command-palette.js +225 -436
- package/lib/public/modules/dm-render.js +82 -0
- package/lib/public/modules/home-capsule-creation-intent.js +31 -0
- package/lib/public/modules/home-capsule-library.js +146 -0
- package/lib/public/modules/home-capsule-source.js +383 -0
- package/lib/public/modules/home-chat-identity.js +35 -0
- package/lib/public/modules/home-chat-scroll.js +77 -0
- package/lib/public/modules/home-chat-stream-state.js +34 -0
- package/lib/public/modules/home-composer-focus.js +25 -0
- package/lib/public/modules/home-conversations-sheet.js +179 -0
- package/lib/public/modules/home-debate-activity.js +48 -0
- package/lib/public/modules/home-debate-controls.js +295 -0
- package/lib/public/modules/home-debate-launch.js +41 -0
- package/lib/public/modules/home-debate-live.js +284 -0
- package/lib/public/modules/home-debate-models.js +73 -0
- package/lib/public/modules/home-debate-planning.js +335 -0
- package/lib/public/modules/home-debates-archive.js +279 -0
- package/lib/public/modules/home-dock-resize.js +74 -0
- package/lib/public/modules/home-dock.js +446 -0
- package/lib/public/modules/home-mate-chat.js +496 -0
- package/lib/public/modules/home-mate-creation.js +109 -0
- package/lib/public/modules/home-mate-model-picker.js +281 -0
- package/lib/public/modules/home-mate-selection.js +38 -0
- package/lib/public/modules/home-mate-settings-menu.js +131 -0
- package/lib/public/modules/home-mate-settings.js +383 -0
- package/lib/public/modules/home-session-actions.js +373 -0
- package/lib/public/modules/home-session-model-confirmation.js +13 -0
- package/lib/public/modules/home-shell.js +9 -0
- package/lib/public/modules/home-sidebar-chat-list.js +63 -0
- package/lib/public/modules/home-sidebar.js +158 -0
- package/lib/public/modules/home-sub-surface.js +19 -0
- package/lib/public/modules/home-surface-boot.js +68 -0
- package/lib/public/modules/home-surface.js +141 -0
- package/lib/public/modules/home-tools.js +271 -0
- package/lib/public/modules/markdown.js +50 -2
- package/lib/public/modules/mate-management.js +86 -0
- package/lib/public/modules/mate-wizard.js +0 -7
- package/lib/public/modules/mention.js +17 -19
- package/lib/public/modules/pane-bridge.js +9 -0
- package/lib/public/modules/profile.js +4 -5
- package/lib/public/modules/project-settings.js +34 -28
- package/lib/public/modules/project-switcher.js +11 -5
- package/lib/public/modules/project-workspace-assignment.js +23 -0
- package/lib/public/modules/search-clay-chat.js +402 -0
- package/lib/public/modules/server-settings.js +14 -12
- package/lib/public/modules/session-actions.js +1 -1
- package/lib/public/modules/sidebar-mates.js +56 -552
- package/lib/public/modules/sidebar-mobile.js +7 -64
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/split-pair-ui.js +13 -13
- package/lib/public/modules/split-view.js +7 -0
- package/lib/public/modules/sticky-notes.js +7 -6
- package/lib/public/modules/tool-input-composition.js +48 -0
- package/lib/public/modules/tool-llm-status.js +167 -0
- package/lib/public/modules/tool-renderer-advanced.js +285 -0
- package/lib/public/modules/tool-renderer-chart.js +158 -0
- package/lib/public/modules/tool-renderer-semantics.js +35 -0
- package/lib/public/modules/tool-renderer.js +464 -0
- package/lib/public/modules/tool-runtime.js +309 -0
- package/lib/public/modules/tool-ui-evaluator.js +97 -0
- package/lib/public/modules/tool-ui-tree.js +21 -0
- package/lib/public/modules/tui-attention.js +10 -0
- package/lib/public/modules/user-settings.js +16 -23
- package/lib/public/modules/vendor-login.js +287 -0
- package/lib/public/modules/worker-proposal.js +2 -2
- package/lib/public/modules/workspace-assignment-card.js +149 -0
- package/lib/public/modules/workspace-assignment-routing.js +4 -0
- package/lib/public/style.css +13 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +10 -6
- package/lib/server-home-capsule-creation.js +36 -0
- package/lib/server-home-chat-events.js +287 -0
- package/lib/server-home-chat.js +518 -0
- package/lib/server-home-clay-entry.js +65 -0
- package/lib/server-home-clay-session-links.js +26 -0
- package/lib/server-home-debate-planning.js +214 -0
- package/lib/server-home-debates.js +137 -0
- package/lib/server-home-mate-creation.js +261 -0
- package/lib/server-home-models.js +241 -0
- package/lib/server-home-preferences.js +61 -0
- package/lib/server-mates.js +37 -0
- package/lib/server-tools.js +377 -0
- package/lib/server.js +111 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +18 -3
- package/lib/tool-capsule-source.js +142 -0
- package/lib/tool-control-mcp-server.js +126 -0
- package/lib/tool-llm.js +48 -0
- package/lib/tool-storage.js +77 -0
- package/lib/tool-ui-spec-advanced.js +82 -0
- package/lib/tool-ui-spec.js +261 -0
- package/lib/tools-registry.js +286 -0
- package/lib/users-home-dock-preferences.js +77 -0
- package/lib/users-home-surface-preferences.js +99 -0
- package/lib/users-preferences.js +4 -7
- package/lib/users.js +12 -0
- package/lib/whats-new-content.js +3 -3
- package/lib/workspace-assignment-service.js +420 -0
- package/lib/workspace-query-mcp-server.js +154 -0
- package/lib/workspace-query-service.js +492 -0
- package/lib/ws-schema.js +93 -12
- package/lib/yoke/adapters/acp.js +2 -1
- package/lib/yoke/adapters/antigravity.js +2 -1
- package/lib/yoke/adapters/claude-worker.js +11 -4
- package/lib/yoke/adapters/claude.js +73 -43
- package/lib/yoke/adapters/codex.js +40 -10
- package/lib/yoke/adapters/kiro.js +2 -1
- package/lib/yoke/claude-user-input.js +38 -0
- package/lib/yoke/codex-app-server.js +20 -2
- package/lib/yoke/codex-user-input.js +64 -0
- package/lib/yoke/complete-once.js +164 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/interface.js +19 -0
- package/lib/yoke/mcp-bridge-server.js +2 -6
- package/lib/yoke/user-input.js +254 -0
- package/package.json +3 -2
- package/lib/public/css/home-chat.css +0 -380
- package/lib/public/modules/home-chat.js +0 -438
- package/lib/server-clay-home.js +0 -245
|
@@ -7,7 +7,6 @@ import { iconHtml, refreshIcons } from './icons.js';
|
|
|
7
7
|
import { parseEmojis } from './markdown.js';
|
|
8
8
|
import { getCurrentTheme, getChatLayout, setChatLayout } from './theme.js';
|
|
9
9
|
import { openCommandPalette } from './command-palette.js';
|
|
10
|
-
import { getMateSessions } from './mate-sidebar.js';
|
|
11
10
|
import { openProjectSettings } from './project-settings.js';
|
|
12
11
|
import {
|
|
13
12
|
getCachedSessions,
|
|
@@ -33,8 +32,8 @@ import { store } from './store.js';
|
|
|
33
32
|
import { getWs } from './ws-ref.js';
|
|
34
33
|
import { dismissOverlayPanels, closeSidebar } from './sidebar.js';
|
|
35
34
|
import { switchProject, getCachedProjects } from './app-projects.js';
|
|
36
|
-
import { openDm } from './app-dm.js';
|
|
37
35
|
import { showHomeHub } from './app-home-hub.js';
|
|
36
|
+
import { openHomeChat } from './home-mate-chat.js';
|
|
38
37
|
import { openTerminal } from './terminal.js';
|
|
39
38
|
import { requestKnowledgeList } from './mate-knowledge.js';
|
|
40
39
|
import { loadRootDirectory } from './filebrowser.js';
|
|
@@ -319,9 +318,9 @@ function renderSheetSessions(listEl) {
|
|
|
319
318
|
if (type === "project") {
|
|
320
319
|
renderMobileSessionsInto(sessionListEl);
|
|
321
320
|
} else if (type === "mate") {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
closeMobileSheet();
|
|
322
|
+
showHomeHub();
|
|
323
|
+
openHomeChat(mateId);
|
|
325
324
|
}
|
|
326
325
|
|
|
327
326
|
refreshIcons();
|
|
@@ -370,12 +369,8 @@ function renderSheetSessions(listEl) {
|
|
|
370
369
|
// Track that chat sheet is open
|
|
371
370
|
mobileChatSheetOpen = true;
|
|
372
371
|
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
renderSessionsForContext("mate", null, getCurrentDmUserId());
|
|
376
|
-
} else {
|
|
377
|
-
renderSessionsForContext("project", getCachedCurrentSlug(), null);
|
|
378
|
-
}
|
|
372
|
+
// Mate chips navigate away immediately, so the sheet always renders project sessions.
|
|
373
|
+
renderSessionsForContext("project", getCachedCurrentSlug(), null);
|
|
379
374
|
}
|
|
380
375
|
|
|
381
376
|
// Helper: create a mobile session item element
|
|
@@ -659,54 +654,6 @@ function createMobileLoopGroup(loopId, children, groupKey) {
|
|
|
659
654
|
return wrapper;
|
|
660
655
|
}
|
|
661
656
|
|
|
662
|
-
function renderMateMobileActions(container) {
|
|
663
|
-
var newSessionBtn = document.createElement("button");
|
|
664
|
-
newSessionBtn.className = "mobile-session-new";
|
|
665
|
-
newSessionBtn.innerHTML = '<i data-lucide="plus" style="width:16px;height:16px"></i> New session';
|
|
666
|
-
newSessionBtn.addEventListener("click", function () {
|
|
667
|
-
if (getWs() && store.get('connected')) {
|
|
668
|
-
getWs().send(JSON.stringify({ type: "new_session" }));
|
|
669
|
-
}
|
|
670
|
-
closeMobileSheet();
|
|
671
|
-
});
|
|
672
|
-
container.appendChild(newSessionBtn);
|
|
673
|
-
|
|
674
|
-
var debateBtn = document.createElement("button");
|
|
675
|
-
debateBtn.className = "mobile-session-new";
|
|
676
|
-
debateBtn.innerHTML = '<i data-lucide="mic" style="width:16px;height:16px"></i> New debate';
|
|
677
|
-
debateBtn.addEventListener("click", function () {
|
|
678
|
-
closeMobileSheet();
|
|
679
|
-
var targetBtn = document.getElementById("mate-debate-btn");
|
|
680
|
-
if (targetBtn) setTimeout(function () { targetBtn.click(); }, 250);
|
|
681
|
-
});
|
|
682
|
-
container.appendChild(debateBtn);
|
|
683
|
-
|
|
684
|
-
// Render mate session list
|
|
685
|
-
var mateSessions = getMateSessions();
|
|
686
|
-
if (mateSessions.length > 0) {
|
|
687
|
-
var sorted = mateSessions.slice().sort(function (a, b) {
|
|
688
|
-
return (b.lastActivity || 0) - (a.lastActivity || 0);
|
|
689
|
-
});
|
|
690
|
-
|
|
691
|
-
var currentGroup = "";
|
|
692
|
-
for (var i = 0; i < sorted.length; i++) {
|
|
693
|
-
var s = sorted[i];
|
|
694
|
-
var group = getDateGroup(s.lastActivity || 0);
|
|
695
|
-
if (group !== currentGroup) {
|
|
696
|
-
currentGroup = group;
|
|
697
|
-
var header = document.createElement("div");
|
|
698
|
-
header.className = "mobile-sheet-group";
|
|
699
|
-
header.textContent = group;
|
|
700
|
-
container.appendChild(header);
|
|
701
|
-
}
|
|
702
|
-
var mateItem = createMobileSessionItem(s);
|
|
703
|
-
container.appendChild(mateItem);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
refreshIcons();
|
|
708
|
-
}
|
|
709
|
-
|
|
710
657
|
// Helper: render sorted sessions into a container with date groups (with loop session grouping)
|
|
711
658
|
function renderMobileSessionsInto(container) {
|
|
712
659
|
// Mirrors the desktop sidebar's split button: one "New session" action on
|
|
@@ -902,11 +849,7 @@ export function refreshMobileChatSheet() {
|
|
|
902
849
|
|
|
903
850
|
// Re-render sessions for current context
|
|
904
851
|
sessionListEl.innerHTML = "";
|
|
905
|
-
|
|
906
|
-
renderMateMobileActions(sessionListEl);
|
|
907
|
-
} else {
|
|
908
|
-
renderMobileSessionsInto(sessionListEl);
|
|
909
|
-
}
|
|
852
|
+
renderMobileSessionsInto(sessionListEl);
|
|
910
853
|
|
|
911
854
|
refreshIcons();
|
|
912
855
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Compact online-user presence renderer for the project sidebar.
|
|
2
|
+
|
|
3
|
+
import { userAvatarUrl } from './avatar.js';
|
|
4
|
+
|
|
5
|
+
var lastSidebarPresenceIds = [];
|
|
6
|
+
|
|
7
|
+
export function renderSidebarPresence(onlineUsers) {
|
|
8
|
+
var container = document.getElementById("sidebar-presence");
|
|
9
|
+
if (!container) return;
|
|
10
|
+
if (!onlineUsers || onlineUsers.length < 2) {
|
|
11
|
+
if (lastSidebarPresenceIds.length > 0) {
|
|
12
|
+
lastSidebarPresenceIds = [];
|
|
13
|
+
container.innerHTML = "";
|
|
14
|
+
}
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
var newIds = onlineUsers.map(function (user) { return user.id; }).sort();
|
|
18
|
+
if (newIds.length === lastSidebarPresenceIds.length && newIds.every(function (id, index) { return id === lastSidebarPresenceIds[index]; })) return;
|
|
19
|
+
lastSidebarPresenceIds = newIds;
|
|
20
|
+
container.innerHTML = "";
|
|
21
|
+
var maxShow = 4;
|
|
22
|
+
for (var i = 0; i < Math.min(onlineUsers.length, maxShow); i++) {
|
|
23
|
+
var user = onlineUsers[i];
|
|
24
|
+
var image = document.createElement("img");
|
|
25
|
+
image.className = "sidebar-presence-avatar";
|
|
26
|
+
image.src = userAvatarUrl(user, 24);
|
|
27
|
+
image.alt = user.displayName;
|
|
28
|
+
image.dataset.tip = user.displayName + " (@" + user.username + ")";
|
|
29
|
+
container.appendChild(image);
|
|
30
|
+
}
|
|
31
|
+
if (onlineUsers.length > maxShow) {
|
|
32
|
+
var more = document.createElement("span");
|
|
33
|
+
more.className = "sidebar-presence-more";
|
|
34
|
+
more.textContent = "+" + (onlineUsers.length - maxShow);
|
|
35
|
+
container.appendChild(more);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -5,8 +5,8 @@ import { buildAgentVendorSelect, fillAgentModels, buildAgentEffortSelect, fillAg
|
|
|
5
5
|
import { showToast } from './utils.js';
|
|
6
6
|
|
|
7
7
|
var pairDialog = null;
|
|
8
|
-
// Set when the dialog was opened via "Add Worker" on an existing session:
|
|
9
|
-
// that session becomes the Driver and the dialog only configures the Worker.
|
|
8
|
+
// Set when the dialog was opened via "Add Split Worker" on an existing session:
|
|
9
|
+
// that session becomes the Driver and the dialog only configures the Split Worker.
|
|
10
10
|
var pendingDriver = null;
|
|
11
11
|
|
|
12
12
|
function closePairDialog() {
|
|
@@ -35,7 +35,7 @@ function roleColumn(role, description, vendorSelect, modelSelect, effortSelect,
|
|
|
35
35
|
col.className = "pair-modal-role";
|
|
36
36
|
var heading = document.createElement("div");
|
|
37
37
|
heading.className = "pair-modal-role-heading";
|
|
38
|
-
heading.innerHTML = '<span class="pair-role-dot pair-role-' + role.toLowerCase() + '"></span><div><strong>' + role + '</strong><span>' + description + '</span></div>';
|
|
38
|
+
heading.innerHTML = '<span class="pair-role-dot pair-role-' + role.toLowerCase().replace(/ /g, "-") + '"></span><div><strong>' + role + '</strong><span>' + description + '</span></div>';
|
|
39
39
|
col.appendChild(heading);
|
|
40
40
|
var vendorField = fieldLabel("Vendor", vendorSelect);
|
|
41
41
|
col.appendChild(vendorField.fragment);
|
|
@@ -82,13 +82,13 @@ export function showPairDialog(options) {
|
|
|
82
82
|
|
|
83
83
|
var title = document.createElement("div");
|
|
84
84
|
title.className = "wt-modal-title";
|
|
85
|
-
title.textContent = driverInfo ? "Add Worker" : "Pair session";
|
|
85
|
+
title.textContent = driverInfo ? "Add Split Worker" : "Pair session";
|
|
86
86
|
modal.appendChild(title);
|
|
87
87
|
var desc = document.createElement("div");
|
|
88
88
|
desc.className = "pair-modal-desc";
|
|
89
89
|
desc.textContent = driverInfo
|
|
90
|
-
? "This session becomes the Driver; a new Worker opens beside it."
|
|
91
|
-
: "One Driver plans and directs a visible Worker session.";
|
|
90
|
+
? "This session becomes the Driver; a new Split Worker opens beside it."
|
|
91
|
+
: "One Driver plans and directs a visible Split Worker session.";
|
|
92
92
|
modal.appendChild(desc);
|
|
93
93
|
|
|
94
94
|
var driverVendor = buildAgentVendorSelect(installed, installed.indexOf("claude") !== -1 ? "claude" : installed[0]);
|
|
@@ -137,7 +137,7 @@ export function showPairDialog(options) {
|
|
|
137
137
|
} else {
|
|
138
138
|
roles.appendChild(roleColumn("Driver", "Plans, delegates, and integrates", driverVendor, driverModel, driverEffort, options));
|
|
139
139
|
}
|
|
140
|
-
roles.appendChild(roleColumn("Worker", "Executes delegated tasks", workerVendor, workerModel, workerEffort, options));
|
|
140
|
+
roles.appendChild(roleColumn("Split Worker", "Executes delegated tasks", workerVendor, workerModel, workerEffort, options));
|
|
141
141
|
modal.appendChild(roles);
|
|
142
142
|
|
|
143
143
|
var actions = document.createElement("div");
|
|
@@ -149,7 +149,7 @@ export function showPairDialog(options) {
|
|
|
149
149
|
var createBtn = document.createElement("button");
|
|
150
150
|
createBtn.type = "button";
|
|
151
151
|
createBtn.className = "wt-modal-btn primary";
|
|
152
|
-
createBtn.textContent = driverInfo ? "Add Worker" : "Create pair";
|
|
152
|
+
createBtn.textContent = driverInfo ? "Add Split Worker" : "Create pair";
|
|
153
153
|
actions.appendChild(cancelBtn);
|
|
154
154
|
actions.appendChild(createBtn);
|
|
155
155
|
modal.appendChild(actions);
|
|
@@ -218,7 +218,7 @@ export function handleSplitDelegation(msg) {
|
|
|
218
218
|
if (msg.active) states[msg.groupId] = msg;
|
|
219
219
|
else delete states[msg.groupId];
|
|
220
220
|
store.set({ splitDelegations: states });
|
|
221
|
-
// Inside the
|
|
221
|
+
// Inside the Split Worker's own pane, mirror the delegation into the composer
|
|
222
222
|
// notice (the delegated user_message shows it too; this covers the end).
|
|
223
223
|
if (store.get('paneMode') && msg.to === store.get('activeSessionId')) {
|
|
224
224
|
if (msg.active) showWorkerDelegationNotice(null);
|
|
@@ -252,7 +252,7 @@ export function syncPairChrome(host, split) {
|
|
|
252
252
|
setBtn.type = "button";
|
|
253
253
|
setBtn.className = "split-pair-set-driver";
|
|
254
254
|
setBtn.textContent = "Set Driver";
|
|
255
|
-
setBtn.title = "Make this session the Driver; the other pane becomes its Worker";
|
|
255
|
+
setBtn.title = "Make this session the Driver; the other pane becomes its Split Worker";
|
|
256
256
|
setBtn.addEventListener("click", function () { sendSetPair(group.id, paneSessionId); });
|
|
257
257
|
var titleEl = header.querySelector(".split-pane-title");
|
|
258
258
|
var accessEl = header.querySelector(".split-pane-full-access");
|
|
@@ -264,11 +264,11 @@ export function syncPairChrome(host, split) {
|
|
|
264
264
|
for (var pi = 0; pi < split.panes.length && pi < headers.length; pi++) {
|
|
265
265
|
(function (sessionId, header) {
|
|
266
266
|
var isDriver = sessionId === group.pair.driverId;
|
|
267
|
-
var role = isDriver ? "Driver" : "Worker";
|
|
267
|
+
var role = isDriver ? "Driver" : "Split Worker";
|
|
268
268
|
var badge = document.createElement("span");
|
|
269
|
-
badge.className = "split-pair-role split-pair-role-" + role.toLowerCase();
|
|
269
|
+
badge.className = "split-pair-role split-pair-role-" + role.toLowerCase().replace(/ /g, "-");
|
|
270
270
|
badge.textContent = role;
|
|
271
|
-
badge.title = isDriver ? "Driver controls this Worker" : "Worker controlled by the Driver";
|
|
271
|
+
badge.title = isDriver ? "Driver controls this Split Worker" : "Split Worker controlled by the Driver";
|
|
272
272
|
var title = header.querySelector(".split-pane-title");
|
|
273
273
|
var access = header.querySelector(".split-pane-full-access");
|
|
274
274
|
header.insertBefore(badge, access ? access.nextSibling : (title ? title.nextSibling : null));
|
|
@@ -11,6 +11,7 @@ import { groupedSessionIds, findSplitGroup } from './split-group-helpers.js';
|
|
|
11
11
|
import { showConfirm } from './app-misc.js';
|
|
12
12
|
import { syncPairChrome } from './split-pair-ui.js';
|
|
13
13
|
import { presentMarkdownEdit } from './filebrowser.js';
|
|
14
|
+
import { autoStartLoginIfNeeded } from './vendor-login.js';
|
|
14
15
|
|
|
15
16
|
var host = null;
|
|
16
17
|
var nativeApp = null;
|
|
@@ -276,6 +277,12 @@ function handlePaneMessage(event) {
|
|
|
276
277
|
if (present) presentMarkdownEdit(present);
|
|
277
278
|
return;
|
|
278
279
|
}
|
|
280
|
+
// Both panes can report auth_required for their own sessions. The shell runs
|
|
281
|
+
// one login flow for the project; repeat events are no-ops there.
|
|
282
|
+
if (msg.type === "clay-pane-auth-required") {
|
|
283
|
+
if (msg.message) autoStartLoginIfNeeded(msg.message);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
279
286
|
if (msg.type !== "clay-pane-context") return;
|
|
280
287
|
var frames = host.querySelectorAll(".split-pane-frame");
|
|
281
288
|
for (var i = 0; i < frames.length; i++) {
|
|
@@ -11,7 +11,7 @@ var textTimers = {};
|
|
|
11
11
|
var colorPickerEl = null;
|
|
12
12
|
var formatToolbarEl = null;
|
|
13
13
|
|
|
14
|
-
var NOTE_COLORS = ["
|
|
14
|
+
var NOTE_COLORS = ["purple", "green", "yellow", "blue", "pink", "orange"];
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
function getContainerBounds() {
|
|
@@ -98,7 +98,8 @@ export function createNote() {
|
|
|
98
98
|
type: "note_create",
|
|
99
99
|
x: 60 + offset,
|
|
100
100
|
y: 60 + offset,
|
|
101
|
-
color: "
|
|
101
|
+
color: "purple",
|
|
102
|
+
opacity: 0.64,
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -154,7 +155,7 @@ function renderNote(data) {
|
|
|
154
155
|
el.style.width = data.w + "px";
|
|
155
156
|
el.style.height = data.h + "px";
|
|
156
157
|
el.style.zIndex = 100 + (data.zIndex || 0);
|
|
157
|
-
el.dataset.color = data.color || "
|
|
158
|
+
el.dataset.color = data.color || "purple";
|
|
158
159
|
|
|
159
160
|
if (data.minimized) el.classList.add("minimized");
|
|
160
161
|
if (data.hidden) el.classList.add("hidden");
|
|
@@ -217,7 +218,7 @@ function renderNote(data) {
|
|
|
217
218
|
opacitySlider.type = "range";
|
|
218
219
|
opacitySlider.min = "20";
|
|
219
220
|
opacitySlider.max = "100";
|
|
220
|
-
opacitySlider.value = String(Math.round((data.opacity
|
|
221
|
+
opacitySlider.value = String(Math.round((typeof data.opacity === "number" ? data.opacity : 0.64) * 100));
|
|
221
222
|
opacitySlider.className = "sticky-note-opacity-slider";
|
|
222
223
|
opacitySlider.title = "Opacity";
|
|
223
224
|
opacityWrap.appendChild(opacitySlider);
|
|
@@ -813,7 +814,7 @@ export function handleNoteUpdated(msg) {
|
|
|
813
814
|
entry.el.style.width = msg.note.w + "px";
|
|
814
815
|
entry.el.style.height = msg.note.h + "px";
|
|
815
816
|
entry.el.style.zIndex = 100 + (msg.note.zIndex || 0);
|
|
816
|
-
entry.el.dataset.color = msg.note.color || "
|
|
817
|
+
entry.el.dataset.color = msg.note.color || "purple";
|
|
817
818
|
|
|
818
819
|
// Update text only if not actively editing (check rendered or textarea focus)
|
|
819
820
|
var textarea = entry.el.querySelector(".sticky-note-text");
|
|
@@ -926,7 +927,7 @@ function renderArchiveCards() {
|
|
|
926
927
|
(function (noteData) {
|
|
927
928
|
var card = document.createElement("div");
|
|
928
929
|
card.className = "notes-archive-card" + (noteData.data.hidden ? " archived" : "");
|
|
929
|
-
card.dataset.color = noteData.data.color || "
|
|
930
|
+
card.dataset.color = noteData.data.color || "purple";
|
|
930
931
|
|
|
931
932
|
// Header with title + delete
|
|
932
933
|
var header = document.createElement("div");
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Composition-safe action binding for declarative Capsule text controls.
|
|
2
|
+
|
|
3
|
+
var inputStates = new WeakMap();
|
|
4
|
+
|
|
5
|
+
export function isToolTextInputComposing(input) {
|
|
6
|
+
var state = inputStates.get(input);
|
|
7
|
+
return !!state && state.composing;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function bindToolTextInput(input, commit, options) {
|
|
11
|
+
options = options || {};
|
|
12
|
+
var state = { composing: false, trailingValue: null };
|
|
13
|
+
inputStates.set(input, state);
|
|
14
|
+
|
|
15
|
+
function isAlive() {
|
|
16
|
+
return typeof options.isAlive !== "function" || options.isAlive(input);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
input.addEventListener("compositionstart", function () {
|
|
20
|
+
state.composing = true;
|
|
21
|
+
state.trailingValue = null;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
input.addEventListener("beforeinput", function (event) {
|
|
25
|
+
if (state.trailingValue === null && event && (event.isComposing || event.inputType === "insertCompositionText")) {
|
|
26
|
+
state.composing = true;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
input.addEventListener("compositionend", function () {
|
|
31
|
+
state.composing = false;
|
|
32
|
+
state.trailingValue = input.value;
|
|
33
|
+
if (!isAlive()) return;
|
|
34
|
+
commit(input.value);
|
|
35
|
+
if (typeof options.onCompositionEnd === "function") options.onCompositionEnd(input);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
input.addEventListener("input", function (event) {
|
|
39
|
+
if (state.composing || (event && event.isComposing)) return;
|
|
40
|
+
if (state.trailingValue !== null && input.value === state.trailingValue) {
|
|
41
|
+
state.trailingValue = null;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
state.trailingValue = null;
|
|
45
|
+
if (!isAlive()) return;
|
|
46
|
+
commit(input.value);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Compact provider/model status for LLM-enabled Capsule surfaces.
|
|
2
|
+
|
|
3
|
+
import { getWs } from './ws-ref.js';
|
|
4
|
+
|
|
5
|
+
var surfaces = [];
|
|
6
|
+
var requestCounter = 0;
|
|
7
|
+
var activeRequests = Object.create(null);
|
|
8
|
+
var states = Object.create(null);
|
|
9
|
+
var subscribers = [];
|
|
10
|
+
|
|
11
|
+
export var TOOL_LLM_ALIASES = Object.freeze(["fast", "standard", "deep"]);
|
|
12
|
+
|
|
13
|
+
function safeAlias(alias) {
|
|
14
|
+
return alias === "fast" || alias === "deep" ? alias : "standard";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isAlias(alias) {
|
|
18
|
+
return alias === "fast" || alias === "standard" || alias === "deep";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function initialToolLlmAlias(manifest) {
|
|
22
|
+
return manifest && isAlias(manifest.modelAlias) ? manifest.modelAlias : null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function toolLlmDisplayValue(modelState) {
|
|
26
|
+
var ready = modelState && modelState.status === "ready" && modelState.vendorName && modelState.modelName;
|
|
27
|
+
return ready ? modelState.vendorName + " · " + modelState.modelName : "No model configured";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function toolLlmShouldRetry(modelState) {
|
|
31
|
+
return !!modelState && modelState.status === "error";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function currentSurfaces() {
|
|
35
|
+
surfaces = surfaces.filter(function (surface) { return !!surface.root; });
|
|
36
|
+
return surfaces;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function notifyAlias(alias) {
|
|
40
|
+
var current = subscribers.slice();
|
|
41
|
+
for (var i = 0; i < current.length; i++) current[i](alias, getToolLlmConfiguration(alias));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getToolLlmConfiguration(alias) {
|
|
45
|
+
alias = safeAlias(alias);
|
|
46
|
+
return Object.assign({ status: "loading", vendorName: "", modelName: "", error: "" }, states[alias] || {});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function subscribeToolLlmConfigurations(listener) {
|
|
50
|
+
subscribers.push(listener);
|
|
51
|
+
return function () {
|
|
52
|
+
var index = subscribers.indexOf(listener);
|
|
53
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function renderSurface(surface) {
|
|
58
|
+
if (!surface.alias) {
|
|
59
|
+
surface.value.textContent = "Selected when Capsule runs";
|
|
60
|
+
surface.value.title = "The concrete model is selected when this Capsule requests an LLM capability.";
|
|
61
|
+
surface.error.classList.add("hidden");
|
|
62
|
+
surface.retry.classList.add("hidden");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
var state = states[surface.alias] || { status: "loading", vendorName: "", modelName: "", error: "" };
|
|
66
|
+
var ready = state.status === "ready" && state.vendorName && state.modelName;
|
|
67
|
+
surface.value.textContent = toolLlmDisplayValue(state);
|
|
68
|
+
surface.value.title = ready ? "Capsule " + surface.alias + " model: " + state.vendorName + " · " + state.modelName : "No configured Capsule model";
|
|
69
|
+
surface.error.textContent = state.error || "";
|
|
70
|
+
surface.error.classList.toggle("hidden", !state.error);
|
|
71
|
+
surface.retry.classList.toggle("hidden", !toolLlmShouldRetry(state));
|
|
72
|
+
surface.retry.disabled = false;
|
|
73
|
+
surface.retry.textContent = "Retry";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderAlias(alias) {
|
|
77
|
+
var current = currentSurfaces();
|
|
78
|
+
for (var i = 0; i < current.length; i++) {
|
|
79
|
+
if (current[i].alias === alias) renderSurface(current[i]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function requestToolLlmConfiguration(alias) {
|
|
84
|
+
alias = safeAlias(alias);
|
|
85
|
+
var ws = getWs();
|
|
86
|
+
if (!ws || ws.readyState !== 1) {
|
|
87
|
+
activeRequests[alias] = null;
|
|
88
|
+
states[alias] = { status: "error", vendorName: "", modelName: "", error: "Connect to Clay to check the Capsule model." };
|
|
89
|
+
renderAlias(alias);
|
|
90
|
+
notifyAlias(alias);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
requestCounter++;
|
|
94
|
+
activeRequests[alias] = "tool-llm-config-" + requestCounter;
|
|
95
|
+
states[alias] = { status: "loading", vendorName: "", modelName: "", error: "" };
|
|
96
|
+
renderAlias(alias);
|
|
97
|
+
notifyAlias(alias);
|
|
98
|
+
ws.send(JSON.stringify({ type: "tool_llm_config_get", requestId: activeRequests[alias], alias: alias }));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function requestAllToolLlmConfigurations() {
|
|
102
|
+
for (var i = 0; i < TOOL_LLM_ALIASES.length; i++) requestToolLlmConfiguration(TOOL_LLM_ALIASES[i]);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function handleToolLlmConfigState(msg) {
|
|
106
|
+
if (!isAlias(msg.alias)) return;
|
|
107
|
+
var alias = msg.alias;
|
|
108
|
+
if (msg.requestId && msg.requestId !== activeRequests[alias]) return;
|
|
109
|
+
activeRequests[alias] = null;
|
|
110
|
+
states[alias] = {
|
|
111
|
+
status: msg.status === "ready" ? "ready" : "error",
|
|
112
|
+
vendorName: msg.vendorName || msg.vendor || "",
|
|
113
|
+
modelName: msg.modelName || msg.model || "",
|
|
114
|
+
error: msg.error || "",
|
|
115
|
+
};
|
|
116
|
+
renderAlias(alias);
|
|
117
|
+
notifyAlias(alias);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function createToolLlmStatus(alias) {
|
|
121
|
+
alias = isAlias(alias) ? alias : null;
|
|
122
|
+
var root = document.createElement("section");
|
|
123
|
+
root.className = "tool-llm-status";
|
|
124
|
+
root.setAttribute("aria-label", "Capsule model status");
|
|
125
|
+
var identity = document.createElement("div");
|
|
126
|
+
identity.className = "tool-llm-identity";
|
|
127
|
+
var label = document.createElement("span");
|
|
128
|
+
label.className = "tool-llm-label";
|
|
129
|
+
label.textContent = "Model";
|
|
130
|
+
var value = document.createElement("span");
|
|
131
|
+
value.className = "tool-llm-value";
|
|
132
|
+
value.setAttribute("aria-live", "polite");
|
|
133
|
+
identity.appendChild(label);
|
|
134
|
+
identity.appendChild(value);
|
|
135
|
+
var actions = document.createElement("div");
|
|
136
|
+
actions.className = "tool-llm-actions";
|
|
137
|
+
var retry = document.createElement("button");
|
|
138
|
+
retry.type = "button";
|
|
139
|
+
retry.className = "tool-llm-action hidden";
|
|
140
|
+
retry.addEventListener("click", function () {
|
|
141
|
+
if (surface.alias) requestToolLlmConfiguration(surface.alias);
|
|
142
|
+
});
|
|
143
|
+
var error = document.createElement("p");
|
|
144
|
+
error.className = "tool-llm-error hidden";
|
|
145
|
+
actions.appendChild(retry);
|
|
146
|
+
root.appendChild(identity);
|
|
147
|
+
root.appendChild(actions);
|
|
148
|
+
root.appendChild(error);
|
|
149
|
+
var surface = { root: root, alias: alias, value: value, retry: retry, error: error };
|
|
150
|
+
surfaces.push(surface);
|
|
151
|
+
renderSurface(surface);
|
|
152
|
+
if (alias) requestToolLlmConfiguration(alias);
|
|
153
|
+
return {
|
|
154
|
+
element: root,
|
|
155
|
+
setAlias: function (nextAlias) {
|
|
156
|
+
if (!isAlias(nextAlias)) return;
|
|
157
|
+
surface.alias = nextAlias;
|
|
158
|
+
renderSurface(surface);
|
|
159
|
+
requestToolLlmConfiguration(nextAlias);
|
|
160
|
+
},
|
|
161
|
+
dispose: function () {
|
|
162
|
+
surface.root = null;
|
|
163
|
+
var index = surfaces.indexOf(surface);
|
|
164
|
+
if (index !== -1) surfaces.splice(index, 1);
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|