clay-server 2.23.0-beta.2 → 2.23.0-beta.4
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/bin/cli.js +3 -10
- package/lib/mates.js +5 -10
- package/lib/project.js +9 -13
- package/lib/public/app.js +12 -3
- package/lib/public/index.html +1 -1
- package/lib/public/modules/profile.js +4 -1
- package/lib/server.js +0 -20
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -443,20 +443,13 @@ async function restartDaemonFromConfig() {
|
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
// Rebuild config (preserve everything except pid)
|
|
446
|
-
var newConfig = {
|
|
446
|
+
var newConfig = Object.assign({}, lastConfig, {
|
|
447
447
|
pid: null,
|
|
448
448
|
port: targetPort,
|
|
449
|
-
pinHash: lastConfig.pinHash || null,
|
|
450
|
-
tls: lastConfig.tls !== undefined ? lastConfig.tls : useHttps,
|
|
451
|
-
debug: lastConfig.debug || false,
|
|
452
|
-
keepAwake: lastConfig.keepAwake || false,
|
|
453
|
-
dangerouslySkipPermissions: lastConfig.dangerouslySkipPermissions || false,
|
|
454
|
-
osUsers: lastConfig.osUsers || false,
|
|
455
449
|
projects: (lastConfig.projects || []).filter(function (p) {
|
|
456
450
|
return fs.existsSync(p.path);
|
|
457
|
-
})
|
|
458
|
-
|
|
459
|
-
};
|
|
451
|
+
})
|
|
452
|
+
});
|
|
460
453
|
|
|
461
454
|
ensureConfigDir();
|
|
462
455
|
saveConfig(newConfig);
|
package/lib/mates.js
CHANGED
|
@@ -409,17 +409,12 @@ function enforceTeamAwareness(filePath) {
|
|
|
409
409
|
content = content.substring(0, teamIdx).trimEnd() + content.substring(endOfTeam);
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
-
// Insert before
|
|
413
|
-
var projRegPos = content.indexOf(PROJECT_REGISTRY_MARKER);
|
|
414
|
-
var sessionMemPos = content.indexOf(SESSION_MEMORY_MARKER);
|
|
415
|
-
var crisisPos = content.indexOf(crisisSafety.MARKER);
|
|
412
|
+
// Insert before the first subsequent system section (in order)
|
|
416
413
|
var insertBefore = -1;
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
insertBefore =
|
|
421
|
-
} else if (crisisPos !== -1) {
|
|
422
|
-
insertBefore = crisisPos;
|
|
414
|
+
var teamInsertCandidates = [PROJECT_REGISTRY_MARKER, SESSION_MEMORY_MARKER, STICKY_NOTES_MARKER, DEBATE_AWARENESS_MARKER, crisisSafety.MARKER];
|
|
415
|
+
for (var ti = 0; ti < teamInsertCandidates.length; ti++) {
|
|
416
|
+
var tip = content.indexOf(teamInsertCandidates[ti]);
|
|
417
|
+
if (tip !== -1) { insertBefore = tip; break; }
|
|
423
418
|
}
|
|
424
419
|
if (insertBefore !== -1) {
|
|
425
420
|
content = content.substring(0, insertBefore).trimEnd() + TEAM_SECTION + "\n\n" + content.substring(insertBefore);
|
package/lib/project.js
CHANGED
|
@@ -1367,7 +1367,7 @@ function createProjectContext(opts) {
|
|
|
1367
1367
|
if (active) {
|
|
1368
1368
|
userPresence.setPresence(slug, presenceKey, active.localId, storedPresence ? storedPresence.mateDm : null);
|
|
1369
1369
|
}
|
|
1370
|
-
if (storedPresence && storedPresence.mateDm) {
|
|
1370
|
+
if (storedPresence && storedPresence.mateDm && !isMate) {
|
|
1371
1371
|
sendTo(ws, { type: "restore_mate_dm", mateId: storedPresence.mateDm });
|
|
1372
1372
|
}
|
|
1373
1373
|
|
|
@@ -1870,8 +1870,12 @@ function createProjectContext(opts) {
|
|
|
1870
1870
|
}
|
|
1871
1871
|
|
|
1872
1872
|
if (msg.type === "set_mate_dm") {
|
|
1873
|
-
|
|
1874
|
-
|
|
1873
|
+
// Only store mateDm on non-mate projects (main project presence).
|
|
1874
|
+
// Mate projects should never hold mateDm to avoid circular restore loops.
|
|
1875
|
+
if (!isMate) {
|
|
1876
|
+
var dmPresKey = ws._clayUser ? ws._clayUser.id : "_default";
|
|
1877
|
+
userPresence.setMateDm(slug, dmPresKey, msg.mateId || null);
|
|
1878
|
+
}
|
|
1875
1879
|
return;
|
|
1876
1880
|
}
|
|
1877
1881
|
|
|
@@ -7041,11 +7045,6 @@ function createProjectContext(opts) {
|
|
|
7041
7045
|
var claudeMdPath = path.join(cwd, "CLAUDE.md");
|
|
7042
7046
|
// Enforce immediately on startup
|
|
7043
7047
|
try { matesModule.enforceTeamAwareness(claudeMdPath); } catch (e) {}
|
|
7044
|
-
try {
|
|
7045
|
-
var _projList = getProjectList();
|
|
7046
|
-
var _projData = _projList.filter(function (p) { return !p.isMate && !p.isWorktree; }).map(function (p) { return { slug: p.slug, path: p.path, title: p.title || p.project, icon: p.icon }; });
|
|
7047
|
-
matesModule.enforceProjectRegistry(claudeMdPath, _projData);
|
|
7048
|
-
} catch (e) {}
|
|
7049
7048
|
try { matesModule.enforceSessionMemory(claudeMdPath); } catch (e) {}
|
|
7050
7049
|
try { matesModule.enforceStickyNotes(claudeMdPath); } catch (e) {}
|
|
7051
7050
|
try { matesModule.enforceDebateAwareness(claudeMdPath); } catch (e) {}
|
|
@@ -7069,11 +7068,8 @@ function createProjectContext(opts) {
|
|
|
7069
7068
|
crisisDebounce = setTimeout(function () {
|
|
7070
7069
|
crisisDebounce = null;
|
|
7071
7070
|
try { matesModule.enforceTeamAwareness(claudeMdPath); } catch (e) {}
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
var _projData2 = _projList2.filter(function (p) { return !p.isMate && !p.isWorktree; }).map(function (p) { return { slug: p.slug, path: p.path, title: p.title || p.project, icon: p.icon }; });
|
|
7075
|
-
matesModule.enforceProjectRegistry(claudeMdPath, _projData2);
|
|
7076
|
-
} catch (e) {}
|
|
7071
|
+
// Note: project registry is NOT enforced in the watcher to avoid
|
|
7072
|
+
// write cascades (server.js scheduleProjectRegistryRefresh handles updates)
|
|
7077
7073
|
try { matesModule.enforceSessionMemory(claudeMdPath); } catch (e) {}
|
|
7078
7074
|
try { matesModule.enforceStickyNotes(claudeMdPath); } catch (e) {}
|
|
7079
7075
|
try { matesModule.enforceDebateAwareness(claudeMdPath); } catch (e) {}
|
package/lib/public/app.js
CHANGED
|
@@ -607,8 +607,16 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
607
607
|
dmTargetUser = targetUser;
|
|
608
608
|
|
|
609
609
|
// Notify server of active mate DM (server-side presence tracking)
|
|
610
|
-
|
|
611
|
-
|
|
610
|
+
// IMPORTANT: set_mate_dm must go to the MAIN project, not a mate project WS.
|
|
611
|
+
// When switching between mates, ws points to the current mate project,
|
|
612
|
+
// so we defer sending set_mate_dm until we reconnect to the main project's context.
|
|
613
|
+
// The server will also receive it via the mate project's onDmMessage handler,
|
|
614
|
+
// but the presence should only be stored on the main project slug.
|
|
615
|
+
if (targetUser && targetUser.isMate) {
|
|
616
|
+
// Send to the current WS only if it's the main project (not another mate)
|
|
617
|
+
if (!mateProjectSlug && ws && ws.readyState === 1) {
|
|
618
|
+
try { ws.send(JSON.stringify({ type: "set_mate_dm", mateId: targetUser.id })); } catch(e) {}
|
|
619
|
+
}
|
|
612
620
|
}
|
|
613
621
|
|
|
614
622
|
// Clear unread for this user
|
|
@@ -972,7 +980,8 @@ import { initDebate, handleDebateStarted, handleDebateResumed, handleDebateTurn,
|
|
|
972
980
|
|
|
973
981
|
function connectMateProject(slug) {
|
|
974
982
|
mateProjectSlug = slug;
|
|
975
|
-
|
|
983
|
+
// Only save the main slug on the FIRST mate switch (preserve original main project)
|
|
984
|
+
if (!savedMainSlug) savedMainSlug = currentSlug;
|
|
976
985
|
currentSlug = slug;
|
|
977
986
|
wsPath = "/p/" + slug + "/ws";
|
|
978
987
|
resetClientState();
|
package/lib/public/index.html
CHANGED
|
@@ -727,7 +727,7 @@
|
|
|
727
727
|
<div class="user-island-profile">
|
|
728
728
|
<div class="user-island-avatar"><span class="user-island-avatar-letter">?</span></div>
|
|
729
729
|
<div class="user-island-info">
|
|
730
|
-
<span class="user-island-name"
|
|
730
|
+
<span class="user-island-name"></span>
|
|
731
731
|
<span class="user-island-cta hidden">Personalize your name</span>
|
|
732
732
|
</div>
|
|
733
733
|
</div>
|
|
@@ -64,7 +64,10 @@ export function debouncedSave() {
|
|
|
64
64
|
export function applyToIsland() {
|
|
65
65
|
var avatarWrap = document.querySelector('.user-island-avatar');
|
|
66
66
|
var nameEl = document.querySelector('.user-island-name');
|
|
67
|
-
if (!avatarWrap || !nameEl)
|
|
67
|
+
if (!avatarWrap || !nameEl) {
|
|
68
|
+
requestAnimationFrame(applyToIsland);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
68
71
|
|
|
69
72
|
var displayName = profile.name || 'Awesome Clay User';
|
|
70
73
|
|
package/lib/server.js
CHANGED
|
@@ -2931,28 +2931,9 @@ function createServer(opts) {
|
|
|
2931
2931
|
});
|
|
2932
2932
|
projects.set(slug, ctx);
|
|
2933
2933
|
ctx.warmup();
|
|
2934
|
-
refreshMateProjectRegistries();
|
|
2935
2934
|
return true;
|
|
2936
2935
|
}
|
|
2937
2936
|
|
|
2938
|
-
// --- Refresh project registry on all mate CLAUDE.md files ---
|
|
2939
|
-
function refreshMateProjectRegistries() {
|
|
2940
|
-
var projList = [];
|
|
2941
|
-
projects.forEach(function (ctx) {
|
|
2942
|
-
var status = ctx.getStatus();
|
|
2943
|
-
if (!status.isMate && !status.isWorktree) {
|
|
2944
|
-
projList.push({ slug: status.slug, path: status.path, title: status.title || status.project, icon: status.icon });
|
|
2945
|
-
}
|
|
2946
|
-
});
|
|
2947
|
-
projects.forEach(function (ctx) {
|
|
2948
|
-
var status = ctx.getStatus();
|
|
2949
|
-
if (status.isMate) {
|
|
2950
|
-
var claudeMdPath = path.join(status.path, "CLAUDE.md");
|
|
2951
|
-
try { mates.enforceProjectRegistry(claudeMdPath, projList); } catch (e) {}
|
|
2952
|
-
}
|
|
2953
|
-
});
|
|
2954
|
-
}
|
|
2955
|
-
|
|
2956
2937
|
// --- DM message handler (server-level, cross-project) ---
|
|
2957
2938
|
function handleDmMessage(ws, msg) {
|
|
2958
2939
|
if (!users.isMultiUser() || !ws._clayUser) return;
|
|
@@ -3335,7 +3316,6 @@ function createServer(opts) {
|
|
|
3335
3316
|
if (!ctx) return false;
|
|
3336
3317
|
ctx.destroy();
|
|
3337
3318
|
projects.delete(slug);
|
|
3338
|
-
refreshMateProjectRegistries();
|
|
3339
3319
|
return true;
|
|
3340
3320
|
}
|
|
3341
3321
|
|