clay-server 5.3.0-beta.4 → 5.3.0-beta.5
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-request-identity.js +18 -1
- package/lib/project-delegated-follow-up.js +18 -9
- package/lib/public/css/right-workbench.css +26 -3
- package/lib/public/css/shared-browser.css +21 -0
- package/lib/public/css/sticky-notes.css +3 -2
- package/lib/public/index.html +2 -2
- package/lib/public/modules/app-header.js +24 -2
- package/lib/public/modules/app-messages.js +1 -1
- package/lib/public/modules/clay-session-links.js +1 -1
- package/lib/public/modules/filebrowser.js +2 -2
- package/lib/public/modules/pane-activation.js +3 -0
- package/lib/public/modules/pane-browser-bridge.js +15 -5
- package/lib/public/modules/pane-header-runtime.js +18 -0
- package/lib/public/modules/right-workbench.js +92 -62
- package/lib/public/modules/shared-browser.js +6 -0
- package/lib/public/modules/split-pane-renderer.js +6 -8
- package/lib/public/modules/split-pane-runtime.js +23 -0
- package/lib/public/modules/split-view.js +8 -14
- package/lib/public/modules/sticky-notes.js +8 -10
- package/lib/public/modules/terminal.js +7 -2
- package/lib/public/modules/theme.js +5 -0
- package/lib/public/modules/workspace-assignment-card.js +9 -6
- package/lib/public/pane-assets/{app-ED2VCGNQ.js → app-6H5S2Y3Z.js} +1 -1
- package/lib/public/pane-assets/chunk-3QV5SDC4.js +1 -0
- package/lib/public/pane-assets/{chunk-JAEQCN5S.js → chunk-4FM3U3DW.js} +1 -1
- package/lib/public/pane-assets/{chunk-6SM2WQJX.js → chunk-7GZH3FZY.js} +1 -1
- package/lib/public/pane-assets/chunk-AGJTF5WQ.js +1 -0
- package/lib/public/pane-assets/chunk-NPKRTUNG.js +2 -0
- package/lib/public/pane-assets/{chunk-IYFILQHZ.js → chunk-VGA2Y3D2.js} +1 -1
- package/lib/public/pane-assets/{chunk-IZ2ZANEY.js → chunk-WKO3T75E.js} +89 -89
- package/lib/public/pane-assets/manifest.json +361 -359
- package/lib/public/pane-assets/{style-JVCOCG3W.css → style-TSRDU54Z.css} +1 -1
- package/lib/server.js +1 -0
- package/lib/workspace-assignment-service.js +56 -11
- package/lib/workspace-follow-up-queue.js +92 -0
- package/lib/workspace-query-mcp-server.js +1 -1
- package/package.json +1 -1
- package/lib/public/pane-assets/chunk-6D4DPE5X.js +0 -1
- package/lib/public/pane-assets/chunk-7H36SUZA.js +0 -2
- package/lib/public/pane-assets/chunk-ST2Q62ET.js +0 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { getCachedSessions } from './sidebar-sessions.js';
|
|
3
|
+
import { livePaneBinding, samePaneBinding, samePaneTarget, paneTarget } from './pane-binding.js';
|
|
4
|
+
import { VENDOR_AVATARS, VENDOR_NAMES } from './app-rendering.js';
|
|
5
|
+
import { modelEntryValue } from './model-picker.js';
|
|
6
|
+
|
|
7
|
+
export function renderPaneRuntime(paneEl, session) {
|
|
8
|
+
var runtime = paneEl.querySelector('.split-view-runtime');
|
|
9
|
+
if (!runtime) return;
|
|
10
|
+
var vendor = session && session.vendor || 'unknown', model = modelEntryValue(session && session.model);
|
|
11
|
+
var frame = paneEl.querySelector('.split-pane-frame'), controller = frame && frame.clayPane;
|
|
12
|
+
var live = controller && controller.identity(), target = session && paneTarget(store.snap(), getCachedSessions(), session.id);
|
|
13
|
+
if (session && live && live.ready && live.sessionId === session.id && !frame.dataset.requestedSessionId &&
|
|
14
|
+
samePaneTarget(target, live.binding) && livePaneBinding(frame) && typeof controller.headerRuntime === 'function') {
|
|
15
|
+
var observed = controller.headerRuntime();
|
|
16
|
+
if (observed && observed.vendor === vendor && samePaneBinding(live.binding, observed.binding)) model = modelEntryValue(observed.model) || model;
|
|
17
|
+
}
|
|
18
|
+
var label = model || (vendor === 'unknown' ? 'Model unavailable' : 'Provider default');
|
|
19
|
+
var icon = runtime.querySelector('.split-view-runtime-icon'), text = runtime.querySelector('.split-view-model');
|
|
20
|
+
if (icon) { icon.hidden = !VENDOR_AVATARS[vendor]; if (!icon.hidden) icon.src = VENDOR_AVATARS[vendor]; icon.title = VENDOR_NAMES[vendor] || vendor; icon.alt = ''; }
|
|
21
|
+
if (text) { text.textContent = label; text.title = (VENDOR_NAMES[vendor] || vendor) + ' · ' + label; }
|
|
22
|
+
runtime.setAttribute('aria-label', (VENDOR_NAMES[vendor] || vendor) + ' · ' + label);
|
|
23
|
+
}
|
|
@@ -131,21 +131,15 @@ function closePane(sessionId) {
|
|
|
131
131
|
// Called on session_list so pane headers follow renames made elsewhere
|
|
132
132
|
// (sidebar, in-pane app). Panes being renamed inline are left alone.
|
|
133
133
|
export function syncPaneTitles() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
var
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
var session = sessionById(
|
|
140
|
-
if (
|
|
141
|
-
if (titleEls[i].parentNode) titleEls[i].parentNode.title = session.title;
|
|
142
|
-
if (titleEls[i].style.display !== "none") titleEls[i].textContent = session.title;
|
|
143
|
-
}
|
|
144
|
-
var accessBtns = host.querySelectorAll(".split-pane-full-access");
|
|
145
|
-
for (var ai = 0; ai < split.panes.length && ai < accessBtns.length; ai++) {
|
|
146
|
-
updatePaneFullAccessButton(accessBtns[ai], sessionById(paneEls[ai] && Number(paneEls[ai].dataset.sessionId) || split.panes[ai].sessionId));
|
|
134
|
+
if (!host) return;
|
|
135
|
+
var panes = host.querySelectorAll('.split-pane:not(.split-pane-cached)');
|
|
136
|
+
for (var i = 0; i < panes.length; i++) {
|
|
137
|
+
var frame = panes[i].querySelector('.split-pane-frame');
|
|
138
|
+
if (frame && frame.dataset.requestedSessionId) continue;
|
|
139
|
+
var session = sessionById(Number(panes[i].dataset.sessionId));
|
|
140
|
+
if (session) updateSplitPaneMetadata(panes[i], { sessionId: session.id, slug: panes[i].dataset.projectSlug, title: session.title });
|
|
147
141
|
}
|
|
148
|
-
syncPairChrome(host,
|
|
142
|
+
syncPairChrome(host, store.get('splitPanes'));
|
|
149
143
|
}
|
|
150
144
|
|
|
151
145
|
function handlePaneMessage(event) {
|
|
@@ -104,11 +104,17 @@ function recomputeFlightGeometry() {
|
|
|
104
104
|
function syncFlightControls() {
|
|
105
105
|
var buttons = document.querySelectorAll("#sticky-notes-toggle-btn");
|
|
106
106
|
var hidden = !!store.get("notesTemporarilyHidden");
|
|
107
|
-
var
|
|
107
|
+
var count = openCount();
|
|
108
|
+
var label = hidden ? "Show sticky notes (" + count + ")" : "Hide sticky notes";
|
|
108
109
|
for (var i = 0; i < buttons.length; i++) {
|
|
109
110
|
buttons[i].setAttribute("aria-label", label);
|
|
110
111
|
buttons[i].setAttribute("aria-pressed", hidden ? "true" : "false");
|
|
111
112
|
buttons[i].title = label;
|
|
113
|
+
var badge = buttons[i].querySelector('.sticky-notes-count');
|
|
114
|
+
if (badge) {
|
|
115
|
+
badge.textContent = String(count);
|
|
116
|
+
badge.classList.toggle('hidden', !hidden || count === 0);
|
|
117
|
+
}
|
|
112
118
|
}
|
|
113
119
|
refreshIcons();
|
|
114
120
|
}
|
|
@@ -246,15 +252,7 @@ export function createNote() {
|
|
|
246
252
|
|
|
247
253
|
function updateBadge() {
|
|
248
254
|
syncToggleAvailability();
|
|
249
|
-
|
|
250
|
-
if (!badge) return;
|
|
251
|
-
var count = openCount();
|
|
252
|
-
if (count > 0) {
|
|
253
|
-
badge.textContent = count;
|
|
254
|
-
badge.classList.remove("hidden");
|
|
255
|
-
} else {
|
|
256
|
-
badge.classList.add("hidden");
|
|
257
|
-
}
|
|
255
|
+
syncFlightControls();
|
|
258
256
|
}
|
|
259
257
|
|
|
260
258
|
// --- WS message handlers ---
|
|
@@ -3,7 +3,7 @@ import { iconHtml, refreshIcons } from './icons.js';
|
|
|
3
3
|
import { closeSidebar } from './sidebar.js';
|
|
4
4
|
import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
5
5
|
import { copyToClipboard } from './utils.js';
|
|
6
|
-
import { getTerminalTheme } from './theme.js';
|
|
6
|
+
import { getTerminalTheme, getDockedTerminalTheme } from './theme.js';
|
|
7
7
|
import { getTerminalFontFamily, getTerminalFontSize, onTerminalFontChange } from './terminal-prefs.js';
|
|
8
8
|
import { createKeyToolbar } from './terminal-toolbar.js';
|
|
9
9
|
|
|
@@ -358,7 +358,7 @@ function createXtermForTab(tab) {
|
|
|
358
358
|
cursorBlink: true,
|
|
359
359
|
fontSize: getTerminalFontSize(),
|
|
360
360
|
fontFamily: getTerminalFontFamily(),
|
|
361
|
-
theme: getTerminalTheme(),
|
|
361
|
+
theme: (store.get('rightWorkbenchDockedOwners') || []).indexOf('terminal') !== -1 ? getDockedTerminalTheme() : getTerminalTheme(),
|
|
362
362
|
});
|
|
363
363
|
|
|
364
364
|
var fitAddon = null;
|
|
@@ -843,6 +843,7 @@ export function sendTerminalCommand(command) {
|
|
|
843
843
|
}
|
|
844
844
|
|
|
845
845
|
export function setTerminalTheme(xtermTheme) {
|
|
846
|
+
if ((store.get('rightWorkbenchDockedOwners') || []).indexOf('terminal') !== -1) xtermTheme = getDockedTerminalTheme();
|
|
846
847
|
for (var tab of tabs.values()) {
|
|
847
848
|
if (tab.xterm) {
|
|
848
849
|
tab.xterm.options.theme = xtermTheme;
|
|
@@ -850,6 +851,10 @@ export function setTerminalTheme(xtermTheme) {
|
|
|
850
851
|
}
|
|
851
852
|
}
|
|
852
853
|
|
|
854
|
+
store.subscribe(function (state, previous) {
|
|
855
|
+
if ((state.rightWorkbenchDockedOwners || []).includes('terminal') !== (previous.rightWorkbenchDockedOwners || []).includes('terminal')) setTerminalTheme(getTerminalTheme());
|
|
856
|
+
});
|
|
857
|
+
|
|
853
858
|
// Live font update: applies family/size to every open shell terminal
|
|
854
859
|
// and refits each (cell dimensions change with font size, so cols/rows
|
|
855
860
|
// shift too). Hooked via onTerminalFontChange below.
|
|
@@ -267,6 +267,11 @@ export function getTerminalTheme() {
|
|
|
267
267
|
return computeTerminalTheme(getTheme(DEFAULT_DARK_THEME_ID) || defaultDarkFallback);
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
export function getDockedTerminalTheme() {
|
|
271
|
+
var theme = getCurrentTheme();
|
|
272
|
+
return Object.assign({}, computeTerminalTheme(theme), { background: '#' + theme.base00 });
|
|
273
|
+
}
|
|
274
|
+
|
|
270
275
|
export function getMermaidThemeVars() {
|
|
271
276
|
return computeMermaidVars(getCurrentTheme());
|
|
272
277
|
}
|
|
@@ -11,6 +11,7 @@ function textElement(tag, className, text) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function statusLabel(status) {
|
|
14
|
+
if (status === "queued") return "Queued for Driver";
|
|
14
15
|
if (status === "starting") return "Starting";
|
|
15
16
|
if (status === "running") return "In progress";
|
|
16
17
|
if (status === "completed") return "Completed";
|
|
@@ -22,7 +23,7 @@ function statusLabel(status) {
|
|
|
22
23
|
|
|
23
24
|
function sendDecision(assignment, action, surface, context, card, opener) {
|
|
24
25
|
var ws = getWs();
|
|
25
|
-
if (!ws || ws.readyState !== 1 || !assignment || assignment.status !== "proposed") return false;
|
|
26
|
+
if (!ws || ws.readyState !== 1 || !assignment || (assignment.status !== "proposed" && !(assignment.status === "queued" && action === "cancel"))) return false;
|
|
26
27
|
pendingFocus[assignment.assignmentId] = opener || null;
|
|
27
28
|
card.setAttribute("aria-busy", "true");
|
|
28
29
|
var buttons = card.querySelectorAll("button");
|
|
@@ -79,10 +80,12 @@ export function createWorkspaceAssignmentCard(assignment, options) {
|
|
|
79
80
|
card.appendChild(header);
|
|
80
81
|
|
|
81
82
|
var targetText = followUp
|
|
82
|
-
? "
|
|
83
|
+
? "Send instructions to “" + (assignment.targetSessionTitle || "Existing session") + "” in " + (assignment.projectTitle || assignment.projectSlug || "project")
|
|
83
84
|
: "New private session in " + (assignment.projectTitle || assignment.projectSlug || "project");
|
|
84
85
|
var target = textElement("p", "workspace-assignment-target", targetText);
|
|
85
86
|
card.appendChild(target);
|
|
87
|
+
if (assignment.status === 'queued' && assignment.deliveryState === 'queued') card.appendChild(textElement('p', 'workspace-assignment-result', 'Approved. Waiting for the Driver to finish its current turn.'));
|
|
88
|
+
else if (assignment.deliveryState === 'accepted' && assignment.status === 'running') card.appendChild(textElement('p', 'workspace-assignment-result', 'Accepted by the Driver runtime. Completion is still pending.'));
|
|
86
89
|
card.appendChild(textElement("p", "workspace-assignment-task", assignment.task || ""));
|
|
87
90
|
|
|
88
91
|
if (assignment.error) {
|
|
@@ -94,17 +97,17 @@ export function createWorkspaceAssignmentCard(assignment, options) {
|
|
|
94
97
|
|
|
95
98
|
var actions = document.createElement("div");
|
|
96
99
|
actions.className = "workspace-assignment-actions";
|
|
97
|
-
if (assignment.status === "proposed") {
|
|
98
|
-
var cancel = textElement("button", "workspace-assignment-action secondary", "Cancel");
|
|
100
|
+
if (assignment.status === "proposed" || assignment.status === "queued") {
|
|
101
|
+
var cancel = textElement("button", "workspace-assignment-action secondary", assignment.status === "queued" ? "Cancel queued update" : "Cancel");
|
|
99
102
|
cancel.type = "button";
|
|
100
|
-
cancel.setAttribute("aria-label", "Cancel project assignment");
|
|
103
|
+
cancel.setAttribute("aria-label", assignment.status === "queued" ? "Cancel queued update" : "Cancel project assignment");
|
|
101
104
|
cancel.addEventListener("click", function () { sendDecision(assignment, "cancel", config.home ? "home" : "project", config.context, card, cancel); });
|
|
102
105
|
var approve = textElement("button", "workspace-assignment-action primary", "Approve");
|
|
103
106
|
approve.type = "button";
|
|
104
107
|
approve.setAttribute("aria-label", followUp ? "Approve follow-up in " + (assignment.targetSessionTitle || "the target session") : "Approve new session in " + (assignment.projectTitle || assignment.projectSlug || "the target project"));
|
|
105
108
|
approve.addEventListener("click", function () { sendDecision(assignment, "approve", config.home ? "home" : "project", config.context, card, approve); });
|
|
106
109
|
actions.appendChild(cancel);
|
|
107
|
-
actions.appendChild(approve);
|
|
110
|
+
if (assignment.status === "proposed") actions.appendChild(approve);
|
|
108
111
|
} else {
|
|
109
112
|
var resolved = textElement("span", "workspace-assignment-resolved", statusLabel(assignment.status));
|
|
110
113
|
resolved.setAttribute("role", "status");
|