clay-server 2.27.0-beta.13 → 2.27.0-beta.14

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.
@@ -68,9 +68,9 @@ export function connect() {
68
68
  // Only show "restored" notification if "lost" was actually shown
69
69
  var isMobileDevice = /Mobi|Android|iPad|iPhone|iPod/.test(navigator.userAgent) ||
70
70
  (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
71
- if (wasConnected && disconnectNotifShown && !isMobileDevice && _ctx.isNotifAlertEnabled() && !document.hasFocus() && "serviceWorker" in navigator) {
71
+ if (wasConnected && disconnectNotifShown && !isMobileDevice && _ctx.isNotifAlertEnabled() && !document.hasFocus() && "serviceWorker" in navigator && Notification.permission === "granted") {
72
72
  navigator.serviceWorker.ready.then(function (reg) {
73
- reg.showNotification("Clay", {
73
+ return reg.showNotification("Clay", {
74
74
  body: "Server connection restored",
75
75
  tag: "claude-disconnect",
76
76
  });
@@ -106,9 +106,9 @@ export function connect() {
106
106
  disconnectNotifShown = true;
107
107
  var isMobileDevice = /Mobi|Android|iPad|iPhone|iPod/.test(navigator.userAgent) ||
108
108
  (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
109
- if (!isMobileDevice && _ctx.isNotifAlertEnabled() && !document.hasFocus() && "serviceWorker" in navigator) {
109
+ if (!isMobileDevice && _ctx.isNotifAlertEnabled() && !document.hasFocus() && "serviceWorker" in navigator && Notification.permission === "granted") {
110
110
  navigator.serviceWorker.ready.then(function (reg) {
111
- reg.showNotification("Clay", {
111
+ return reg.showNotification("Clay", {
112
112
  body: "Server connection lost",
113
113
  tag: "claude-disconnect",
114
114
  });
@@ -143,7 +143,7 @@ export function updateHistorySentinel() {
143
143
  export function requestMoreHistory() {
144
144
  var ws = _ctx.getWs();
145
145
  if (_ctx.loadingMore || _ctx.historyFrom <= 0 || !ws || !_ctx.connected) return;
146
- _ctx.setLoadingMore(true);
146
+ _ctx.loadingMore = true;
147
147
  var btn = _ctx.messagesEl.querySelector(".load-more-btn");
148
148
  if (btn) btn.classList.add("loading");
149
149
  ws.send(JSON.stringify({ type: "load_more_history", before: _ctx.historyFrom }));
@@ -206,8 +206,8 @@ export function prependOlderHistory(items, meta) {
206
206
  }
207
207
 
208
208
  // Update state
209
- _ctx.setHistoryFrom(meta.from);
210
- _ctx.setLoadingMore(false);
209
+ _ctx.historyFrom = meta.from;
210
+ _ctx.loadingMore = false;
211
211
 
212
212
  // Renumber data-turn attributes in DOM order
213
213
  var turnEls = _ctx.messagesEl.querySelectorAll("[data-turn]");
@@ -782,6 +782,10 @@ export function processMessage(msg) {
782
782
  _ctx.addSystemMessage(msg.text, true);
783
783
  break;
784
784
 
785
+ case "system_info":
786
+ _ctx.addSystemMessage(msg.text, false);
787
+ break;
788
+
785
789
  case "process_conflict":
786
790
  _ctx.setActivity(null);
787
791
  _ctx.addConflictMessage(msg);
@@ -618,8 +618,16 @@ export function openAddProjectModal() {
618
618
  addProjectOk.disabled = false;
619
619
  var existingBtn = addProjectModal.querySelector('.add-project-mode-btn[data-mode="existing"]');
620
620
  if (_ctx.isOsUsers) {
621
+ // Default: disable existing directory for multi-user, but allow for admins
621
622
  existingBtn.disabled = true;
622
623
  switchAddProjectMode("create");
624
+ if (_ctx.checkAdminAccess) {
625
+ _ctx.checkAdminAccess().then(function (isAdmin) {
626
+ if (isAdmin) {
627
+ existingBtn.disabled = false;
628
+ }
629
+ });
630
+ }
623
631
  } else {
624
632
  existingBtn.disabled = false;
625
633
  switchAddProjectMode("existing");
@@ -150,29 +150,39 @@ export function sendMessage() {
150
150
  }
151
151
 
152
152
  // Check for @mention: if a mate was selected, route to mention handler
153
+ // Exception: if we're in a DM with the same mate, send as regular message instead
153
154
  var mention = parseMentionFromInput(text);
154
155
  if (mention) {
155
- hideMentionMenu();
156
- if (ctx.hideSuggestionChips) ctx.hideSuggestionChips();
157
- var mentionImages = pendingImages.slice();
158
- var mentionPastes = pendingPastes.map(function (p) { return p.text; });
159
- // Prepend file paths to mention text (same pattern as regular messages)
160
- var mentionFiles = pendingFiles.slice();
161
- var mentionText = mention.text;
162
- if (mentionFiles.length > 0) {
163
- var mFilePaths = mentionFiles.map(function (f) { return "[Uploaded file: " + f.path + "]"; }).join("\n");
164
- mentionText = mentionText ? mFilePaths + "\n\n" + mentionText : mFilePaths;
156
+ var dmMateId = ctx.getDmMateId ? ctx.getDmMateId() : null;
157
+ if (dmMateId && dmMateId === mention.mateId) {
158
+ // In DM with this mate — strip mention chip and send as normal message
159
+ hideMentionMenu();
160
+ removeMentionChip();
161
+ text = mention.text;
162
+ // Fall through to normal message send below
163
+ } else {
164
+ hideMentionMenu();
165
+ if (ctx.hideSuggestionChips) ctx.hideSuggestionChips();
166
+ var mentionImages = pendingImages.slice();
167
+ var mentionPastes = pendingPastes.map(function (p) { return p.text; });
168
+ // Prepend file paths to mention text (same pattern as regular messages)
169
+ var mentionFiles = pendingFiles.slice();
170
+ var mentionText = mention.text;
171
+ if (mentionFiles.length > 0) {
172
+ var mFilePaths = mentionFiles.map(function (f) { return "[Uploaded file: " + f.path + "]"; }).join("\n");
173
+ mentionText = mentionText ? mFilePaths + "\n\n" + mentionText : mFilePaths;
174
+ }
175
+ // Render user message with mention chip (same as history replay)
176
+ renderMentionUser({ mateName: mention.mateName, text: mentionText, images: mentionImages.length > 0 ? mentionImages : null, pastes: mentionPastes.length > 0 ? mentionPastes : null });
177
+ sendMention(mention.mateId, mentionText, mentionPastes, mentionImages);
178
+ ctx.inputEl.value = "";
179
+ stickyReapplyMention();
180
+ sendInputSync();
181
+ clearPendingImages();
182
+ autoResize();
183
+ ctx.inputEl.focus();
184
+ return;
165
185
  }
166
- // Render user message with mention chip (same as history replay)
167
- renderMentionUser({ mateName: mention.mateName, text: mentionText, images: mentionImages.length > 0 ? mentionImages : null, pastes: mentionPastes.length > 0 ? mentionPastes : null });
168
- sendMention(mention.mateId, mentionText, mentionPastes, mentionImages);
169
- ctx.inputEl.value = "";
170
- stickyReapplyMention();
171
- sendInputSync();
172
- clearPendingImages();
173
- autoResize();
174
- ctx.inputEl.focus();
175
- return;
176
186
  }
177
187
 
178
188
  // Prepend file paths to text