clay-server 2.47.0-beta.4 → 2.47.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.
@@ -105,7 +105,6 @@ function attachConnection(ctx) {
105
105
  }
106
106
 
107
107
  var loopState = _loop.loopState;
108
- var loopRegistry = _loop.loopRegistry;
109
108
 
110
109
  // Resume loop if server restarted mid-execution (deferred so client gets initial state first)
111
110
  if (loopState._needsResume) {
@@ -179,32 +178,13 @@ function attachConnection(ctx) {
179
178
  if (_mcp) _mcp.sendConnectionState(ws);
180
179
  if (_notifications) _notifications.sendConnectionState(ws, sendTo);
181
180
 
182
- // Session list (filtered for access control)
181
+ // Session list (filtered for access control). Uses the same mapper as
182
+ // broadcastSessionList: a hand-rolled copy here silently drifts and
183
+ // drops fields (the connect-time list was missing vendor/spawn/mode,
184
+ // so vendor badges showed Claude until the next broadcast).
183
185
  sendTo(ws, {
184
186
  type: "session_list",
185
- sessions: allSessions.map(function (s) {
186
- var loop = s.loop ? Object.assign({}, s.loop) : null;
187
- if (loop && loop.loopId && loopRegistry) {
188
- var rec = loopRegistry.getById(loop.loopId);
189
- if (rec) {
190
- if (rec.name) loop.name = rec.name;
191
- if (rec.source) loop.source = rec.source;
192
- }
193
- }
194
- return {
195
- id: s.localId,
196
- cliSessionId: s.cliSessionId || null,
197
- title: s.title || "New Session",
198
- active: s.localId === sm.activeSessionId,
199
- isProcessing: s.isProcessing,
200
- lastActivity: s.lastActivity || s.createdAt || 0,
201
- loop: loop,
202
- ownerId: s.ownerId || null,
203
- sessionVisibility: s.sessionVisibility || "shared",
204
- bookmarked: !!s.bookmarked,
205
- favoriteOrder: typeof s.favoriteOrder === "number" ? s.favoriteOrder : null,
206
- };
207
- }),
187
+ sessions: allSessions.map(function (s) { return sm.mapSessionForClient(s); }),
208
188
  });
209
189
 
210
190
  // Restore active session for this client from server-side presence
@@ -438,6 +438,22 @@
438
438
  object-fit: cover;
439
439
  }
440
440
 
441
+ /* No hover on touch: rest state stays dimmed, the active session shows color. */
442
+ .mobile-session-vendor-icon {
443
+ width: 14px;
444
+ height: 14px;
445
+ flex-shrink: 0;
446
+ border-radius: 3px;
447
+ object-fit: cover;
448
+ margin-right: 8px;
449
+ opacity: 0.5;
450
+ filter: grayscale(0.9) brightness(0.9);
451
+ }
452
+ .mobile-session-item.active .mobile-session-vendor-icon {
453
+ opacity: 1;
454
+ filter: none;
455
+ }
456
+
441
457
  /* --- Chat filter bar (horizontal scroll chips) --- */
442
458
  .mobile-chat-filter-bar {
443
459
  display: flex;
@@ -835,6 +835,25 @@
835
835
  contain: size layout;
836
836
  }
837
837
 
838
+ /* Vendor badge stays nearly monochrome at rest so a long session list does
839
+ not read as a row of logos; hover or the active session restores color. */
840
+ .session-vendor-icon {
841
+ width: 13px;
842
+ height: 13px;
843
+ border-radius: 3px;
844
+ object-fit: cover;
845
+ vertical-align: -2px;
846
+ margin-right: 5px;
847
+ opacity: 0.45;
848
+ filter: grayscale(0.9) brightness(0.9);
849
+ transition: opacity 0.15s, filter 0.15s;
850
+ }
851
+ .session-item:hover .session-vendor-icon,
852
+ .session-item.active .session-vendor-icon {
853
+ opacity: 1;
854
+ filter: none;
855
+ }
856
+
838
857
  .session-item-text {
839
858
  flex: 1;
840
859
  overflow: hidden;
@@ -383,6 +383,14 @@ function createMobileSessionItem(s) {
383
383
  var el = document.createElement("button");
384
384
  el.className = "mobile-session-item" + (s.active ? " active" : "");
385
385
 
386
+ // Vendor badge (legacy sessions without a vendor are Claude)
387
+ var mVendor = s.vendor || "claude";
388
+ var vendorIcon = document.createElement("img");
389
+ vendorIcon.className = "mobile-session-vendor-icon";
390
+ vendorIcon.src = VENDOR_AVATARS[mVendor] || VENDOR_AVATARS.claude;
391
+ vendorIcon.alt = "";
392
+ el.appendChild(vendorIcon);
393
+
386
394
  // Processing dot (left side, before title)
387
395
  if (s.isProcessing) {
388
396
  var dot = document.createElement("span");
@@ -1148,6 +1148,11 @@ function renderSessionItem(s) {
1148
1148
  var textSpan = document.createElement("span");
1149
1149
  textSpan.className = "session-item-text";
1150
1150
  var textHtml = "";
1151
+ // Which agent runtime this session ran on. Legacy sessions without a
1152
+ // recorded vendor are Claude (pre-multi-vendor era).
1153
+ var itemVendor = s.vendor || "claude";
1154
+ textHtml += '<img class="session-vendor-icon" src="' + (VENDOR_AVATARS[itemVendor] || VENDOR_AVATARS.claude) +
1155
+ '" alt="" title="' + escapeHtml(VENDOR_NAMES[itemVendor] || itemVendor) + '">';
1151
1156
  if (s.isProcessing) {
1152
1157
  textHtml += '<span class="session-processing"></span>';
1153
1158
  }
package/lib/sessions.js CHANGED
@@ -1091,6 +1091,7 @@ function createSessionManager(opts) {
1091
1091
  searchSessions: searchSessions,
1092
1092
  searchSessionContent: searchSessionContent,
1093
1093
  setResolveLoopInfo: setResolveLoopInfo,
1094
+ mapSessionForClient: mapSessionForClient,
1094
1095
  migrateSessionTitles: migrateSessionTitles,
1095
1096
  setSessionVisibility: function (localId, visibility) {
1096
1097
  var session = sessions.get(localId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.47.0-beta.4",
3
+ "version": "2.47.0-beta.5",
4
4
  "description": "Self-hosted team workspace for Claude Code and Codex. Multi-user, browser-based, with persistent AI mates.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",