clay-server 3.8.0-beta.1 → 3.8.0-beta.3

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.
Files changed (40) hide show
  1. package/lib/builtin-mates.js +14 -14
  2. package/lib/mates.js +2 -6
  3. package/lib/project-mate-interaction.js +7 -7
  4. package/lib/project-session-pair.js +84 -4
  5. package/lib/project-sessions.js +1 -1
  6. package/lib/project-user-mention.js +4 -4
  7. package/lib/project-worker-proposal.js +1 -1
  8. package/lib/project.js +4 -3
  9. package/lib/public/css/avatar-imprints.css +46 -0
  10. package/lib/public/css/icon-strip.css +3 -3
  11. package/lib/public/css/pane.css +1 -7
  12. package/lib/public/css/profile.css +123 -95
  13. package/lib/public/css/session-actions.css +40 -9
  14. package/lib/public/css/user-settings.css +1 -1
  15. package/lib/public/index.html +2 -2
  16. package/lib/public/modules/app-cursors.js +2 -2
  17. package/lib/public/modules/app-dm.js +1 -8
  18. package/lib/public/modules/app-messages.js +2 -2
  19. package/lib/public/modules/app-projects.js +7 -6
  20. package/lib/public/modules/app-rate-limit.js +0 -1
  21. package/lib/public/modules/app-rendering.js +0 -3
  22. package/lib/public/modules/avatar-imprint.js +134 -0
  23. package/lib/public/modules/avatar.js +25 -19
  24. package/lib/public/modules/debate.js +10 -5
  25. package/lib/public/modules/mate-sidebar.js +2 -2
  26. package/lib/public/modules/mention.js +26 -16
  27. package/lib/public/modules/profile.js +73 -190
  28. package/lib/public/modules/session-actions.js +5 -3
  29. package/lib/public/modules/sidebar-mates.js +5 -4
  30. package/lib/public/modules/sidebar-sessions.js +1 -1
  31. package/lib/public/modules/split-pair-ui.js +2 -8
  32. package/lib/public/style.css +1 -0
  33. package/lib/server-auth.js +2 -2
  34. package/lib/server-dm.js +8 -8
  35. package/lib/server-mates.js +3 -3
  36. package/lib/server-settings.js +2 -2
  37. package/lib/server.js +5 -4
  38. package/lib/session-pair-mcp-server.js +16 -1
  39. package/lib/users.js +4 -4
  40. package/package.json +1 -1
@@ -1,36 +1,42 @@
1
- // Centralized avatar URL builder and style definitions
2
- // All DiceBear avatar URLs should be constructed through this module.
1
+ // Centralized Clay Imprint URL builder for people and Mates.
2
+ import { imprintDataUrl, mateMarkDataUrl } from './avatar-imprint.js';
3
3
 
4
- export var AVATAR_STYLES = [
5
- { id: 'thumbs', name: 'Thumbs' },
6
- { id: 'bottts', name: 'Bots' },
7
- { id: 'pixel-art', name: 'Pixel' },
8
- { id: 'adventurer', name: 'Adventurer' },
9
- { id: 'micah', name: 'Micah' },
10
- { id: 'fun-emoji', name: 'Emoji' },
11
- { id: 'icons', name: 'Icons' },
12
- ];
4
+ var imprintCache = new Map();
5
+ var mateMarkCache = new Map();
13
6
 
14
- // Build a DiceBear avatar URL from style, seed, and optional size.
7
+ // Legacy style remains part of the identity hash so existing selections map
8
+ // deterministically into the new Clay Imprint system.
15
9
  export function avatarUrl(style, seed, size) {
16
- var s = encodeURIComponent(seed || 'anonymous');
17
- return 'https://api.dicebear.com/9.x/' + (style || 'thumbs') + '/svg?seed=' + s + '&size=' + (size || 64);
10
+ var cacheKey = [style || 'imprint', seed || 'anonymous', size || 64].join('|');
11
+ if (imprintCache.has(cacheKey)) return imprintCache.get(cacheKey);
12
+ var url = imprintDataUrl({ style: style || 'imprint', seed: seed || 'anonymous', size: size || 64 });
13
+ if (imprintCache.size >= 512) imprintCache.delete(imprintCache.keys().next().value);
14
+ imprintCache.set(cacheKey, url);
15
+ return url;
18
16
  }
19
17
 
20
18
  // Build avatar URL for a user object, preferring custom avatar if set.
21
19
  export function userAvatarUrl(user, size) {
22
20
  if (user && user.avatarCustom) return user.avatarCustom;
23
- var style = (user && user.avatarStyle) || 'thumbs';
21
+ var style = (user && user.avatarStyle) || 'imprint';
24
22
  var seed = (user && (user.avatarSeed || user.username || user.id)) || 'anonymous';
25
23
  return avatarUrl(style, seed, size);
26
24
  }
27
25
 
26
+ export function mateMarkUrl(seed, size) {
27
+ var cacheKey = [seed || 'mate', size || 64].join('|');
28
+ if (mateMarkCache.has(cacheKey)) return mateMarkCache.get(cacheKey);
29
+ var url = mateMarkDataUrl({ seed: seed || 'mate', size: size || 64 });
30
+ if (mateMarkCache.size >= 256) mateMarkCache.delete(mateMarkCache.keys().next().value);
31
+ mateMarkCache.set(cacheKey, url);
32
+ return url;
33
+ }
34
+
28
35
  // Build avatar URL for a mate object, preferring custom avatar if set.
29
36
  export function mateAvatarUrl(mate, size) {
30
- if (!mate) return avatarUrl('bottts', 'mate', size);
37
+ if (!mate) return mateMarkUrl('mate', size);
31
38
  var p = mate.profile || mate;
32
39
  if (p.avatarCustom || mate.avatarCustom) return p.avatarCustom || mate.avatarCustom;
33
- var style = p.avatarStyle || mate.avatarStyle || 'bottts';
34
- var seed = p.avatarSeed || mate.avatarSeed || mate.id || 'mate';
35
- return avatarUrl(style, seed, size);
40
+ var identity = p.displayName || mate.name || mate.displayName || 'Mate';
41
+ return mateMarkUrl(identity, size);
36
42
  }
@@ -53,7 +53,15 @@ export function resetDebateState() {
53
53
  }
54
54
 
55
55
  function buildAvatarUrl(meta) {
56
- return "https://api.dicebear.com/7.x/" + (meta.avatarStyle || "bottts") + "/svg?seed=" + encodeURIComponent(meta.avatarSeed || meta.mateId || "mate");
56
+ return mateAvatarUrl({
57
+ id: meta.mateId,
58
+ profile: {
59
+ avatarStyle: meta.avatarStyle || "imprint",
60
+ avatarSeed: meta.avatarSeed || meta.mateId || "mate",
61
+ avatarColor: meta.avatarColor || "#5857fc",
62
+ avatarCustom: meta.avatarCustom || "",
63
+ },
64
+ }, 32);
57
65
  }
58
66
 
59
67
  // --- Float info panel ---
@@ -943,12 +951,9 @@ function createPanelItem(mate) {
943
951
  cb.type = "checkbox";
944
952
  item.appendChild(cb);
945
953
 
946
- var avatarSrc = "https://api.dicebear.com/7.x/" +
947
- ((mate.profile && mate.profile.avatarStyle) || "bottts") +
948
- "/svg?seed=" + encodeURIComponent((mate.profile && mate.profile.avatarSeed) || mate.id);
949
954
  var avi = document.createElement("img");
950
955
  avi.className = "debate-panel-item-avatar";
951
- avi.src = avatarSrc;
956
+ avi.src = mateAvatarUrl(mate, 32);
952
957
  item.appendChild(avi);
953
958
 
954
959
  var info = document.createElement("div");
@@ -139,7 +139,7 @@ export function showMateSidebar(mateId, mateData) {
139
139
  var profile = mateData.profile || mateData || {};
140
140
  var displayName = profile.displayName || mateData.displayName || mateData.name || "Mate";
141
141
 
142
- var mateColor = profile.avatarColor || mateData.avatarColor || "#7c3aed";
142
+ var mateColor = profile.avatarColor || mateData.avatarColor || "#5857fc";
143
143
 
144
144
  var mateAvUrl = mateAvatarUrl(mateData, 32);
145
145
  if (avatarEl) avatarEl.src = mateAvUrl;
@@ -267,7 +267,7 @@ export function updateMateSidebarProfile(mateData) {
267
267
  if (!columnEl || !mateData) return;
268
268
  var profile = mateData.profile || mateData || {};
269
269
  var displayName = profile.displayName || mateData.displayName || mateData.name || "Mate";
270
- var mateColor = profile.avatarColor || mateData.avatarColor || "#7c3aed";
270
+ var mateColor = profile.avatarColor || mateData.avatarColor || "#5857fc";
271
271
 
272
272
  if (avatarEl) {
273
273
  avatarEl.src = mateAvatarUrl(mateData, 32);
@@ -112,7 +112,7 @@ function buildMentionCandidates() {
112
112
  kind: "mate",
113
113
  id: m.id,
114
114
  name: (m.profile && m.profile.displayName) || m.name || "Mate",
115
- color: (m.profile && m.profile.avatarColor) || "#6c5ce7",
115
+ color: (m.profile && m.profile.avatarColor) || "#5857fc",
116
116
  avatarSrc: mateAvatarUrl(m, 24),
117
117
  vendor: m.vendor || "claude",
118
118
  bio: m.bio || (m.profile && m.profile.bio) || "",
@@ -134,9 +134,8 @@ function buildMentionCandidates() {
134
134
  kind: "user",
135
135
  id: u.id,
136
136
  name: u.displayName || u.username || "User",
137
- color: u.avatarColor || "#7c3aed",
138
- // Build dicebear url from style+seed; matches userAvatarUrl shape.
139
- avatarSrc: "https://api.dicebear.com/7.x/" + (u.avatarStyle || "thumbs") + "/svg?seed=" + encodeURIComponent(u.avatarSeed || u.username || u.id),
137
+ color: u.avatarColor || "#5857fc",
138
+ avatarSrc: userAvatarUrl(u, 24),
140
139
  vendor: null,
141
140
  bio: u.username ? "@" + u.username : "",
142
141
  primary: false,
@@ -424,7 +423,7 @@ export function stickyReapplyMention() {
424
423
  var kind = selectedMateKind;
425
424
  var id = selectedMateId;
426
425
  var name = selectedMateName;
427
- var color = selectedMateColor || "#6c5ce7";
426
+ var color = selectedMateColor || "#5857fc";
428
427
  var avatarSrc = selectedMateAvatar || "";
429
428
  // Reset index but keep selection
430
429
  mentionAtIdx = -1;
@@ -516,7 +515,7 @@ export function handleMentionStart(msg) {
516
515
  header.className = "dm-bubble-header";
517
516
  var nameSpan = document.createElement("span");
518
517
  nameSpan.className = "dm-bubble-name";
519
- nameSpan.style.color = msg.avatarColor || "#6c5ce7";
518
+ nameSpan.style.color = msg.avatarColor || "#5857fc";
520
519
  nameSpan.textContent = msg.mateName || "Mate";
521
520
  header.appendChild(nameSpan);
522
521
 
@@ -556,7 +555,7 @@ export function handleMentionStart(msg) {
556
555
  // Project chat: mention block style
557
556
  currentMentionEl = document.createElement("div");
558
557
  currentMentionEl.className = "msg-mention";
559
- currentMentionEl.style.setProperty("--mention-color", msg.avatarColor || "#6c5ce7");
558
+ currentMentionEl.style.setProperty("--mention-color", msg.avatarColor || "#5857fc");
560
559
 
561
560
  var header = document.createElement("div");
562
561
  header.className = "mention-header";
@@ -754,15 +753,13 @@ function isDmLayout() {
754
753
 
755
754
  function getMyAvatarSrc() {
756
755
  if (document.body.dataset.myAvatarUrl) return document.body.dataset.myAvatarUrl;
757
- var myUser = null;
758
- try { myUser = JSON.parse(localStorage.getItem("clay_my_user") || "null"); } catch (e) {}
756
+ var myUser = (store.get('cachedAllUsers') || []).find(function (u) { return u.id === store.get('myUserId'); });
759
757
  return userAvatarUrl(myUser || {}, 36);
760
758
  }
761
759
 
762
760
  function getMyDisplayName() {
763
761
  if (document.body.dataset.myDisplayName) return document.body.dataset.myDisplayName;
764
- var myUser = null;
765
- try { myUser = JSON.parse(localStorage.getItem("clay_my_user") || "null"); } catch (e) {}
762
+ var myUser = (store.get('cachedAllUsers') || []).find(function (u) { return u.id === store.get('myUserId'); });
766
763
  return (myUser && (myUser.displayName || myUser.username)) || "Me";
767
764
  }
768
765
 
@@ -772,14 +769,27 @@ function timeStr() {
772
769
  }
773
770
 
774
771
  function buildMentionAvatarUrl(meta) {
775
- return "https://api.dicebear.com/7.x/" + (meta.avatarStyle || "bottts") + "/svg?seed=" + encodeURIComponent(meta.avatarSeed || meta.mateId);
772
+ return mateAvatarUrl({
773
+ id: meta.mateId,
774
+ profile: {
775
+ avatarStyle: meta.avatarStyle || "imprint",
776
+ avatarSeed: meta.avatarSeed || meta.mateId,
777
+ avatarColor: meta.avatarColor || "#5857fc",
778
+ avatarCustom: meta.avatarCustom || "",
779
+ },
780
+ }, 36);
776
781
  }
777
782
 
778
783
  function buildUserAvatarUrlFromEntry(entry, who) {
779
784
  // who = "from" | "target"
780
- var style = entry[who + "AvatarStyle"] || "thumbs";
781
785
  var seed = entry[who + "AvatarSeed"] || entry[who === "from" ? "fromName" : "targetName"] || entry[who === "from" ? "from" : "targetUserId"];
782
- return "https://api.dicebear.com/7.x/" + style + "/svg?seed=" + encodeURIComponent(seed || "user");
786
+ return userAvatarUrl({
787
+ id: entry[who === "from" ? "from" : "targetUserId"],
788
+ avatarStyle: entry[who + "AvatarStyle"] || "imprint",
789
+ avatarSeed: seed || "user",
790
+ avatarColor: entry[who + "AvatarColor"] || "#5857fc",
791
+ avatarCustom: entry[who + "AvatarCustom"] || "",
792
+ }, 36);
783
793
  }
784
794
 
785
795
  // Render a user-to-user @mention bubble (live receive AND history replay).
@@ -1021,7 +1031,7 @@ export function renderMentionResponse(entry) {
1021
1031
  header.className = "dm-bubble-header";
1022
1032
  var nameSpan = document.createElement("span");
1023
1033
  nameSpan.className = "dm-bubble-name";
1024
- nameSpan.style.color = entry.avatarColor || "#6c5ce7";
1034
+ nameSpan.style.color = entry.avatarColor || "#5857fc";
1025
1035
  nameSpan.textContent = entry.mateName || "Mate";
1026
1036
  header.appendChild(nameSpan);
1027
1037
 
@@ -1050,7 +1060,7 @@ export function renderMentionResponse(entry) {
1050
1060
  // Project chat: use mention block style
1051
1061
  var el = document.createElement("div");
1052
1062
  el.className = "msg-mention";
1053
- el.style.setProperty("--mention-color", entry.avatarColor || "#6c5ce7");
1063
+ el.style.setProperty("--mention-color", entry.avatarColor || "#5857fc");
1054
1064
 
1055
1065
  var mheader = document.createElement("div");
1056
1066
  mheader.className = "mention-header";