clay-server 2.36.2-beta.8 → 2.37.0-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.
@@ -284,6 +284,14 @@
284
284
  color: var(--accent2);
285
285
  }
286
286
 
287
+ .activity-inline-avatar {
288
+ width: 28px;
289
+ height: 28px;
290
+ border-radius: 50%;
291
+ flex-shrink: 0;
292
+ object-fit: cover;
293
+ }
294
+
287
295
  .activity-inline .activity-icon {
288
296
  display: inline-flex;
289
297
  animation: sparkle 2s ease-in-out infinite;
@@ -5,7 +5,8 @@ import { refreshIcons } from './icons.js';
5
5
  import { store } from './store.js';
6
6
  import { getSendBtn, getStatusDot } from './dom-refs.js';
7
7
  import { onThemeChange } from './theme.js';
8
- import { getActivityEl, setActivityEl, addToMessages, scrollToBottom } from './app-rendering.js';
8
+ import { getActivityEl, setActivityEl, addToMessages, scrollToBottom, VENDOR_AVATARS } from './app-rendering.js';
9
+ import { escapeHtml } from './utils.js';
9
10
 
10
11
  // --- Module-owned state ---
11
12
  var faviconLink, faviconOrigHref, faviconCanvas, faviconCtx, faviconImg, faviconImgReady;
@@ -199,8 +200,21 @@ export function setActivity(text) {
199
200
  if (!getActivityEl()) {
200
201
  var _actEl = document.createElement("div");
201
202
  _actEl.className = "activity-inline";
202
- _actEl.innerHTML =
203
- '<div class="mate-thinking-dots"><span></span><span></span><span></span></div>';
203
+ // In channel mode (Claude Code / Codex sessions), include the vendor
204
+ // avatar so the user can see who is responding while the dots are
205
+ // animating. DM mode handles its own avatar via mate-thinking
206
+ // elements and shouldn't pick up a vendor avatar here.
207
+ var _isDm = !!(store.get('dmMode') && store.get('dmTargetUser') && store.get('dmTargetUser').isMate);
208
+ if (!_isDm) {
209
+ var _vendor = store.get('currentVendor') || 'claude';
210
+ var _avatarUrl = VENDOR_AVATARS[_vendor] || VENDOR_AVATARS.claude;
211
+ _actEl.innerHTML =
212
+ '<img class="activity-inline-avatar" src="' + escapeHtml(_avatarUrl) + '" alt="">' +
213
+ '<div class="mate-thinking-dots"><span></span><span></span><span></span></div>';
214
+ } else {
215
+ _actEl.innerHTML =
216
+ '<div class="mate-thinking-dots"><span></span><span></span><span></span></div>';
217
+ }
204
218
  setActivityEl(_actEl);
205
219
  addToMessages(_actEl);
206
220
  }
package/lib/sdk-bridge.js CHANGED
@@ -1269,10 +1269,32 @@ function createSDKBridge(opts) {
1269
1269
 
1270
1270
  var codexConfig = getCodexConfig(sm);
1271
1271
  var mergedMcpServers = mergeMcpServers(getMcpServers(), getRemoteMcpServers) || undefined;
1272
+
1273
+ // Derive an explicit session title for fresh queries so the SDK records
1274
+ // it at session creation and skips its own auto-generation. This also
1275
+ // lets us short-circuit autoGenerateTitle below for the common case.
1276
+ // Only applied to NEW sessions (no cliSessionId yet) — when resuming,
1277
+ // the SDK ignores Options.title in favor of the persisted title.
1278
+ var initialTitle = null;
1279
+ if (!session.cliSessionId && !session.titleManuallySet && !session.titleAutoGenerated) {
1280
+ if (session.title) {
1281
+ // Loop / scheduled / mate-seeded sessions arrive with a title already set.
1282
+ initialTitle = session.title;
1283
+ } else if (typeof text === "string") {
1284
+ // Derive a quick first-line snippet from the user's first message.
1285
+ // Skip if too short to be meaningful — fall back to autoGenerateTitle.
1286
+ var firstLine = text.replace(/\s+/g, " ").trim();
1287
+ if (firstLine.length >= 10) {
1288
+ initialTitle = firstLine.length > 60 ? firstLine.substring(0, 60) : firstLine;
1289
+ }
1290
+ }
1291
+ }
1292
+
1272
1293
  var queryOpts = {
1273
1294
  cwd: cwd,
1274
1295
  model: queryModel,
1275
1296
  effort: ls.effort || sm.currentEffort || undefined,
1297
+ title: initialTitle || undefined,
1276
1298
  toolServers: mergedMcpServers,
1277
1299
  toolServerDescriptors: extractMcpDescriptors(mergedMcpServers) || undefined,
1278
1300
  resumeSessionId: session.cliSessionId || undefined,
@@ -1305,6 +1327,18 @@ function createSDKBridge(opts) {
1305
1327
  try {
1306
1328
  handle = await sessionAdapter.createQuery(queryOpts);
1307
1329
  console.log("[sdk-bridge] createQuery returned handle, vendor=" + sessionAdapter.vendor);
1330
+ // SDK accepted the explicit title — adopt it locally so the session
1331
+ // list reflects it immediately and autoGenerateTitle skips this
1332
+ // session (titleAutoGenerated gates re-trigger).
1333
+ if (initialTitle && !session.title) {
1334
+ session.title = initialTitle;
1335
+ session.titleAutoGenerated = true;
1336
+ sm.saveSessionFile(session);
1337
+ sm.broadcastSessionList();
1338
+ } else if (initialTitle && session.title === initialTitle) {
1339
+ session.titleAutoGenerated = true;
1340
+ sm.saveSessionFile(session);
1341
+ }
1308
1342
  } catch (e) {
1309
1343
  console.error("[sdk-bridge] Failed to create query for session " + session.localId + ":", e.message || e);
1310
1344
  console.error("[sdk-bridge] cliSessionId:", session.cliSessionId, "resume:", !!session.cliSessionId);
@@ -1200,7 +1200,13 @@ function createClaudeAdapter(opts) {
1200
1200
  if (queryOpts.resumeSessionId) sdkOptions.resume = queryOpts.resumeSessionId;
1201
1201
 
1202
1202
  // Claude-specific options from adapterOptions.CLAUDE
1203
- if (co.settingSources) sdkOptions.settingSources = co.settingSources;
1203
+ // Always set settingSources explicitly. SDK 0.2.119+ defaults to
1204
+ // loading ALL sources when omitted, but Clay relies on the caller
1205
+ // declaring its scope (e.g. auto-title and mention sub-queries pass
1206
+ // ["user"] only). Falling through to the SDK default would silently
1207
+ // include project/local settings in those isolated paths.
1208
+ sdkOptions.settingSources = co.settingSources || ["user", "project", "local"];
1209
+ if (queryOpts.title) sdkOptions.title = queryOpts.title;
1204
1210
  if (co.includePartialMessages != null) sdkOptions.includePartialMessages = co.includePartialMessages;
1205
1211
  if (co.enableFileCheckpointing != null) sdkOptions.enableFileCheckpointing = co.enableFileCheckpointing;
1206
1212
  if (co.extraArgs) sdkOptions.extraArgs = co.extraArgs;
@@ -1350,7 +1356,10 @@ function createClaudeAdapter(opts) {
1350
1356
  var queryOptions = {
1351
1357
  cwd: workerCwd,
1352
1358
  };
1353
- if (claudeOpts.settingSources) queryOptions.settingSources = claudeOpts.settingSources;
1359
+ // Always set settingSources explicitly. See in-process path comment
1360
+ // above for the SDK 0.2.119+ default-change rationale.
1361
+ queryOptions.settingSources = claudeOpts.settingSources || ["user", "project", "local"];
1362
+ if (queryOpts.title) queryOptions.title = queryOpts.title;
1354
1363
  if (claudeOpts.includePartialMessages != null) queryOptions.includePartialMessages = claudeOpts.includePartialMessages;
1355
1364
  if (claudeOpts.enableFileCheckpointing != null) queryOptions.enableFileCheckpointing = claudeOpts.enableFileCheckpointing;
1356
1365
  if (claudeOpts.extraArgs) queryOptions.extraArgs = claudeOpts.extraArgs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.36.2-beta.8",
3
+ "version": "2.37.0-beta.1",
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",
@@ -48,7 +48,7 @@
48
48
  "homepage": "https://github.com/chadbyte/clay#readme",
49
49
  "author": "Chad",
50
50
  "dependencies": {
51
- "@anthropic-ai/claude-agent-sdk": "^0.2.112",
51
+ "@anthropic-ai/claude-agent-sdk": "^0.2.132",
52
52
  "@lydell/node-pty": "^1.2.0-beta.3",
53
53
  "@openai/codex": "^0.124.0",
54
54
  "imapflow": "^1.3.1",