clay-server 2.29.4 → 2.29.5-beta.1

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/project.js CHANGED
@@ -872,6 +872,12 @@ function createProjectContext(opts) {
872
872
 
873
873
  // --- WS disconnection handler (delegated to project-connection.js) ---
874
874
  function handleDisconnection(ws) {
875
+ // Clean up extension WS reference if this was the extension client
876
+ if (browserState._extensionWs === ws) {
877
+ browserState._extensionWs = null;
878
+ browserState._extensionId = null;
879
+ if (_mcp) _mcp.handleExtensionDisconnect();
880
+ }
875
881
  _connection.handleDisconnection(ws);
876
882
  }
877
883
 
package/lib/public/app.js CHANGED
@@ -54,7 +54,7 @@ import { initRateLimit, handleRateLimitEvent as _rlHandleRateLimitEvent, updateR
54
54
  import { initCursors, handleRemoteCursorMove as _curHandleRemoteCursorMove, handleRemoteCursorLeave as _curHandleRemoteCursorLeave, handleRemoteSelection as _curHandleRemoteSelection, clearRemoteCursors as _curClearRemoteCursors, initCursorToggle } from './modules/app-cursors.js';
55
55
  import { initFavicon, updateFavicon as _favUpdateFavicon, setSendBtnMode as _favSetSendBtnMode, blinkIO as _favBlinkIO, blinkSessionDot as _favBlinkSessionDot, updateCrossProjectBlink as _favUpdateCrossProjectBlink, startUrgentBlink as _favStartUrgentBlink, stopUrgentBlink as _favStopUrgentBlink, setActivity as _favSetActivity, drawFaviconAnimFrame as _favDrawFaviconAnimFrame } from './modules/app-favicon.js';
56
56
  import { initHeader, closeSessionInfoPopover as _hdrCloseSessionInfoPopover, updateHistorySentinel as _hdrUpdateHistorySentinel, requestMoreHistory as _hdrRequestMoreHistory, prependOlderHistory as _hdrPrependOlderHistory } from './modules/app-header.js';
57
- import { initMisc, showImageModal as _miscShowImageModal, closeImageModal as _miscCloseImageModal, showPasteModal as _miscShowPasteModal, closePasteModal as _miscClosePasteModal, showConfirm as _miscShowConfirm, hideConfirm as _miscHideConfirm, showForceChangePinOverlay as _miscShowForceChangePinOverlay, sendExtensionCommand as _miscSendExtensionCommand, handleExtensionResult as _miscHandleExtensionResult } from './modules/app-misc.js';
57
+ import { initMisc, flushPendingExtMessages, showImageModal as _miscShowImageModal, closeImageModal as _miscCloseImageModal, showPasteModal as _miscShowPasteModal, closePasteModal as _miscClosePasteModal, showConfirm as _miscShowConfirm, hideConfirm as _miscHideConfirm, showForceChangePinOverlay as _miscShowForceChangePinOverlay, sendExtensionCommand as _miscSendExtensionCommand, handleExtensionResult as _miscHandleExtensionResult } from './modules/app-misc.js';
58
58
  import { initSkillInstall, requireSkills as _siRequireSkills, requireClayMateInterview as _siRequireClayMateInterview, handleSkillInstallWs as _siHandleSkillInstallWs } from './modules/app-skills-install.js';
59
59
  import { initDebateUi, showDebateConcludeConfirm as _debShowDebateConcludeConfirm, exitDebateConcludeMode as _debExitDebateConcludeMode, handleDebateConcludeSend as _debHandleDebateConcludeSend, showDebateEndedMode as _debShowDebateEndedMode, exitDebateEndedMode as _debExitDebateEndedMode, showDebateUserFloor as _debShowDebateUserFloor, exitDebateFloorMode as _debExitDebateFloorMode, handleDebateFloorSend as _debHandleDebateFloorSend, renderDebateUserFloorDone as _debRenderDebateUserFloorDone, showDebateSticky as _debShowDebateSticky, showDebateBottomBar as _debShowDebateBottomBar, removeDebateBottomBar as _debRemoveDebateBottomBar, sendDebateStickyComment as _debSendDebateStickyComment, updateDebateRound as _debUpdateDebateRound } from './modules/app-debate-ui.js';
60
60
  import { initLoopUi, updateLoopInputVisibility as _loopUpdateLoopInputVisibility, updateLoopButton as _loopUpdateLoopButton, showLoopBanner as _loopShowLoopBanner, updateLoopBanner as _loopUpdateLoopBanner, updateRalphBars as _loopUpdateRalphBars, showRalphCraftingBar as _loopShowRalphCraftingBar, showRalphApprovalBar as _loopShowRalphApprovalBar, updateRalphApprovalStatus as _loopUpdateRalphApprovalStatus, openRalphPreviewModal as _loopOpenRalphPreviewModal, showExecModal as _loopShowExecModal, closeExecModal as _loopCloseExecModal, updateExecModalStatus as _loopUpdateExecModalStatus } from './modules/app-loop-ui.js';
@@ -1337,6 +1337,9 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1337
1337
  setActivity: setActivity,
1338
1338
  processMessage: processMessage,
1339
1339
  onConnected: function () {
1340
+ // Flush any extension messages that arrived before WS was ready
1341
+ flushPendingExtMessages();
1342
+
1340
1343
  // Reset terminal xterm instances (server will send fresh term_list)
1341
1344
  resetTerminals();
1342
1345
 
@@ -11,6 +11,29 @@ import { setExtensionConnected } from './mcp-ui.js';
11
11
  var confirmCallback = null;
12
12
  var _extRequestCallbacks = {};
13
13
 
14
+ // Queue for extension messages that arrived before WS was ready
15
+ var _pendingExtMessages = [];
16
+
17
+ function sendOrQueue(msgObj) {
18
+ var ws = getWs();
19
+ if (ws && ws.readyState === 1) {
20
+ ws.send(JSON.stringify(msgObj));
21
+ } else {
22
+ _pendingExtMessages.push(msgObj);
23
+ }
24
+ }
25
+
26
+ export function flushPendingExtMessages() {
27
+ if (_pendingExtMessages.length === 0) return;
28
+ var ws = getWs();
29
+ if (!ws || ws.readyState !== 1) return;
30
+ var queued = _pendingExtMessages.slice();
31
+ _pendingExtMessages = [];
32
+ for (var i = 0; i < queued.length; i++) {
33
+ ws.send(JSON.stringify(queued[i]));
34
+ }
35
+ }
36
+
14
37
  export function initMisc() {
15
38
  // --- Confirm modal listeners ---
16
39
  var confirmModal = document.getElementById("confirm-modal");
@@ -98,14 +121,11 @@ export function initMisc() {
98
121
  if (msg.type === "clay_ext_tab_list") {
99
122
  setExtensionConnected(true);
100
123
  updateBrowserTabList(msg.tabs);
101
- // Also inform server about tab list
102
- var ws = getWs();
103
- if (ws && ws.readyState === 1) {
104
- ws.send(JSON.stringify({
105
- type: "browser_tab_list",
106
- tabs: msg.tabs
107
- }));
108
- }
124
+ // Also inform server about tab list (queue if WS not ready yet)
125
+ sendOrQueue({
126
+ type: "browser_tab_list",
127
+ tabs: msg.tabs
128
+ });
109
129
  }
110
130
  if (msg.type === "clay_ext_result") {
111
131
  handleExtensionResult(msg.requestId, msg.result);
@@ -114,19 +134,17 @@ export function initMisc() {
114
134
  setExtensionConnected(false);
115
135
  }
116
136
 
117
- // MCP bridge: extension reports available MCP servers
137
+ // MCP bridge: extension reports available MCP servers (queue if WS not ready yet)
118
138
  if (msg.type === "mcp_servers_available") {
119
- var ws2 = getWs();
120
- if (ws2 && ws2.readyState === 1) {
121
- ws2.send(JSON.stringify({
122
- type: "mcp_servers_available",
123
- servers: msg.servers,
124
- hostConnected: msg.hostConnected
125
- }));
126
- }
139
+ sendOrQueue({
140
+ type: "mcp_servers_available",
141
+ servers: msg.servers,
142
+ hostConnected: msg.hostConnected
143
+ });
127
144
  }
128
145
 
129
- // MCP bridge: tool result from extension
146
+ // MCP bridge: tool result from extension (tool results should not be queued,
147
+ // if WS is down the call already timed out server-side)
130
148
  if (msg.type === "mcp_tool_result") {
131
149
  var ws3 = getWs();
132
150
  if (ws3 && ws3.readyState === 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.29.4",
3
+ "version": "2.29.5-beta.1",
4
4
  "description": "Self-hosted Claude Code in your browser. Multi-session, multi-user, push notifications.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",