clay-server 3.7.0 → 3.8.0-beta.2
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/lib/builtin-mates.js +14 -14
- package/lib/mates.js +2 -6
- package/lib/os-users.js +17 -1
- package/lib/project-http.js +34 -1
- package/lib/project-image.js +87 -1
- package/lib/project-mate-interaction.js +7 -7
- package/lib/project-sessions.js +1 -1
- package/lib/project-user-mention.js +4 -4
- package/lib/project.js +6 -4
- package/lib/public/css/avatar-imprints.css +46 -0
- package/lib/public/css/generated-images.css +242 -0
- package/lib/public/css/icon-strip.css +3 -3
- package/lib/public/css/profile.css +123 -95
- package/lib/public/css/session-actions.css +40 -9
- package/lib/public/css/user-settings.css +1 -1
- package/lib/public/index.html +3 -3
- package/lib/public/modules/app-cursors.js +2 -2
- package/lib/public/modules/app-dm.js +1 -8
- package/lib/public/modules/app-messages.js +2 -2
- package/lib/public/modules/app-projects.js +7 -6
- package/lib/public/modules/app-rate-limit.js +0 -1
- package/lib/public/modules/app-rendering.js +0 -3
- package/lib/public/modules/avatar-imprint.js +134 -0
- package/lib/public/modules/avatar.js +25 -19
- package/lib/public/modules/debate.js +10 -5
- package/lib/public/modules/generated-images.js +211 -2
- package/lib/public/modules/mate-sidebar.js +2 -2
- package/lib/public/modules/mention.js +26 -16
- package/lib/public/modules/profile.js +73 -190
- package/lib/public/modules/session-actions.js +5 -3
- package/lib/public/modules/sidebar-mates.js +5 -4
- package/lib/public/modules/sidebar-sessions.js +1 -1
- package/lib/public/style.css +2 -1
- package/lib/server-auth.js +2 -2
- package/lib/server-dm.js +8 -8
- package/lib/server-mates.js +3 -3
- package/lib/server-settings.js +2 -2
- package/lib/server.js +5 -4
- package/lib/users.js +4 -4
- package/package.json +1 -1
package/lib/builtin-mates.js
CHANGED
|
@@ -18,8 +18,8 @@ var BUILTIN_MATES = [
|
|
|
18
18
|
key: "clay",
|
|
19
19
|
displayName: "Clay",
|
|
20
20
|
bio: "Your workspace memory. Searches every session, project, and decision you've made and answers from the receipts. The chat surface for the home screen.",
|
|
21
|
-
avatarColor: "#
|
|
22
|
-
avatarStyle: "
|
|
21
|
+
avatarColor: "#5857fc",
|
|
22
|
+
avatarStyle: "imprint",
|
|
23
23
|
avatarCustom: "/clay-studio-symbol.png", // Clay is the app — use the app symbol
|
|
24
24
|
avatarLocked: true,
|
|
25
25
|
primary: true, // code-managed, auto-updated on startup
|
|
@@ -48,8 +48,8 @@ var BUILTIN_MATES = [
|
|
|
48
48
|
key: "ally",
|
|
49
49
|
displayName: "Ally",
|
|
50
50
|
bio: "Chief of staff. Quiet, sharp, sees across every mate. Knows what Arch decided yesterday, what Buzz pitched last week, and what you said three weeks ago.",
|
|
51
|
-
avatarColor: "#
|
|
52
|
-
avatarStyle: "
|
|
51
|
+
avatarColor: "#5857fc",
|
|
52
|
+
avatarStyle: "imprint",
|
|
53
53
|
avatarCustom: "/mates/ally.png",
|
|
54
54
|
avatarLocked: true,
|
|
55
55
|
archived: true, // skip seeding for new users; demote on existing
|
|
@@ -69,8 +69,8 @@ var BUILTIN_MATES = [
|
|
|
69
69
|
key: "arch",
|
|
70
70
|
displayName: "Arch",
|
|
71
71
|
bio: "Architect. Stubborn about structure, patient about everything else. Draws boxes and arrows before anyone writes code, and is annoyingly right about which ones will break.",
|
|
72
|
-
avatarColor: "#
|
|
73
|
-
avatarStyle: "
|
|
72
|
+
avatarColor: "#5857fc",
|
|
73
|
+
avatarStyle: "imprint",
|
|
74
74
|
seedData: {
|
|
75
75
|
relationship: "colleague",
|
|
76
76
|
activity: ["planning", "reviewing"],
|
|
@@ -87,8 +87,8 @@ var BUILTIN_MATES = [
|
|
|
87
87
|
key: "rush",
|
|
88
88
|
displayName: "Rush",
|
|
89
89
|
bio: "Shipper. Impatient in the best way. Cuts your scope in half, ships it before lunch, and somehow it's better than the original plan.",
|
|
90
|
-
avatarColor: "#
|
|
91
|
-
avatarStyle: "
|
|
90
|
+
avatarColor: "#5857fc",
|
|
91
|
+
avatarStyle: "imprint",
|
|
92
92
|
seedData: {
|
|
93
93
|
relationship: "colleague",
|
|
94
94
|
activity: ["coding", "planning"],
|
|
@@ -105,8 +105,8 @@ var BUILTIN_MATES = [
|
|
|
105
105
|
key: "ward",
|
|
106
106
|
displayName: "Ward",
|
|
107
107
|
bio: "Guardian. Quietly anxious in a productive way. Reads error logs for fun and asks \"what happens when the input is null?\" before anyone else thinks of it.",
|
|
108
|
-
avatarColor: "#
|
|
109
|
-
avatarStyle: "
|
|
108
|
+
avatarColor: "#5857fc",
|
|
109
|
+
avatarStyle: "imprint",
|
|
110
110
|
seedData: {
|
|
111
111
|
relationship: "reviewer",
|
|
112
112
|
activity: ["reviewing", "testing"],
|
|
@@ -123,8 +123,8 @@ var BUILTIN_MATES = [
|
|
|
123
123
|
key: "pixel",
|
|
124
124
|
displayName: "Pixel",
|
|
125
125
|
bio: "Designer. Obsessed with the details nobody else notices. Sees the 2px misalignment, the confusing label, the flow that makes sense to the builder but not the user.",
|
|
126
|
-
avatarColor: "#
|
|
127
|
-
avatarStyle: "
|
|
126
|
+
avatarColor: "#5857fc",
|
|
127
|
+
avatarStyle: "imprint",
|
|
128
128
|
seedData: {
|
|
129
129
|
relationship: "colleague",
|
|
130
130
|
activity: ["designing", "reviewing"],
|
|
@@ -141,8 +141,8 @@ var BUILTIN_MATES = [
|
|
|
141
141
|
key: "buzz",
|
|
142
142
|
displayName: "Buzz",
|
|
143
143
|
bio: "Marketer. Competitive, trend-obsessed, always watching what others are doing. Researches your market, tracks what people search for, and turns \"we built a thing\" into a story people care about.",
|
|
144
|
-
avatarColor: "#
|
|
145
|
-
avatarStyle: "
|
|
144
|
+
avatarColor: "#5857fc",
|
|
145
|
+
avatarStyle: "imprint",
|
|
146
146
|
seedData: {
|
|
147
147
|
relationship: "colleague",
|
|
148
148
|
activity: ["writing", "marketing"],
|
package/lib/mates.js
CHANGED
|
@@ -121,10 +121,6 @@ function createMate(ctx, seedData) {
|
|
|
121
121
|
var id = generateMateId();
|
|
122
122
|
var userId = ctx ? ctx.userId : null;
|
|
123
123
|
|
|
124
|
-
// Pick a random avatar color from a pleasant palette
|
|
125
|
-
var colors = ["#6c5ce7", "#00b894", "#e17055", "#0984e3", "#fdcb6e", "#e84393", "#00cec9", "#ff7675"];
|
|
126
|
-
var colorIdx = crypto.randomBytes(1)[0] % colors.length;
|
|
127
|
-
|
|
128
124
|
var mate = {
|
|
129
125
|
id: id,
|
|
130
126
|
name: null,
|
|
@@ -134,8 +130,8 @@ function createMate(ctx, seedData) {
|
|
|
134
130
|
vendor: (seedData && seedData.vendor) || "claude",
|
|
135
131
|
profile: {
|
|
136
132
|
displayName: null,
|
|
137
|
-
avatarColor:
|
|
138
|
-
avatarStyle: "
|
|
133
|
+
avatarColor: "#5857fc",
|
|
134
|
+
avatarStyle: "imprint",
|
|
139
135
|
avatarSeed: crypto.randomBytes(4).toString("hex"),
|
|
140
136
|
},
|
|
141
137
|
bio: null,
|
package/lib/os-users.js
CHANGED
|
@@ -98,7 +98,7 @@ function resolveOsUserInfo(username) {
|
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Run a file system operation as a specific OS user via a helper subprocess.
|
|
101
|
-
* op: "list", "read", "write", "stat"
|
|
101
|
+
* op: "list", "read", "write", "read_binary", "mkdir", "copy", "stat"
|
|
102
102
|
* args: operation-specific arguments
|
|
103
103
|
* osUserInfo: { uid, gid } from resolveOsUserInfo
|
|
104
104
|
* Returns the result object or throws.
|
|
@@ -164,6 +164,22 @@ function fsAsUser(op, args, osUserInfo) {
|
|
|
164
164
|
"fs.writeFileSync(f, content, 'utf8');",
|
|
165
165
|
"process.stdout.write(JSON.stringify({ ok: true }));",
|
|
166
166
|
].join(" ");
|
|
167
|
+
} else if (op === "mkdir") {
|
|
168
|
+
script = [
|
|
169
|
+
"var fs = require('fs');",
|
|
170
|
+
"var dir = " + JSON.stringify(args.dir) + ";",
|
|
171
|
+
"fs.mkdirSync(dir, { recursive: true });",
|
|
172
|
+
"process.stdout.write(JSON.stringify({ ok: true }));",
|
|
173
|
+
].join(" ");
|
|
174
|
+
} else if (op === "copy") {
|
|
175
|
+
script = [
|
|
176
|
+
"var fs = require('fs');",
|
|
177
|
+
"var source = " + JSON.stringify(args.source) + ";",
|
|
178
|
+
"var file = " + JSON.stringify(args.file) + ";",
|
|
179
|
+
"var overwrite = " + JSON.stringify(!!args.overwrite) + ";",
|
|
180
|
+
"fs.copyFileSync(source, file, overwrite ? 0 : fs.constants.COPYFILE_EXCL);",
|
|
181
|
+
"process.stdout.write(JSON.stringify({ ok: true }));",
|
|
182
|
+
].join(" ");
|
|
167
183
|
} else {
|
|
168
184
|
throw new Error("Unknown fsAsUser operation: " + op);
|
|
169
185
|
}
|
package/lib/project-http.js
CHANGED
|
@@ -41,7 +41,7 @@ function parseJsonBody(req) {
|
|
|
41
41
|
* ctx fields:
|
|
42
42
|
* cwd, slug, project, sm, send, sendTo, imagesDir, osUsers, pushModule,
|
|
43
43
|
* safePath, safeAbsPath, getOsUserInfoForReq, sendExtensionCommandAny,
|
|
44
|
-
* _extToken, _browserTabList
|
|
44
|
+
* saveGeneratedImageToProject, _extToken, _browserTabList
|
|
45
45
|
*/
|
|
46
46
|
function attachHTTP(ctx) {
|
|
47
47
|
var cwd = ctx.cwd;
|
|
@@ -51,6 +51,7 @@ function attachHTTP(ctx) {
|
|
|
51
51
|
var gitAttribution = ctx.gitAttribution;
|
|
52
52
|
var send = ctx.send;
|
|
53
53
|
var imagesDir = ctx.imagesDir;
|
|
54
|
+
var saveGeneratedImageToProject = ctx.saveGeneratedImageToProject;
|
|
54
55
|
var osUsers = ctx.osUsers;
|
|
55
56
|
var pushModule = ctx.pushModule;
|
|
56
57
|
var safePath = ctx.safePath;
|
|
@@ -122,6 +123,38 @@ function attachHTTP(ctx) {
|
|
|
122
123
|
return true;
|
|
123
124
|
}
|
|
124
125
|
|
|
126
|
+
// Copy a generated image from Clay's session storage into the project.
|
|
127
|
+
if (req.method === "POST" && urlPath === "/api/generated-image/save") {
|
|
128
|
+
if (usersModule.isMultiUser()) {
|
|
129
|
+
var imageSaveUser = req._clayUser;
|
|
130
|
+
var imageSavePermissions = imageSaveUser ? usersModule.getEffectivePermissions(imageSaveUser, osUsers) : null;
|
|
131
|
+
if (!imageSavePermissions || !imageSavePermissions.fileBrowser) {
|
|
132
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
133
|
+
res.end('{"error":"File browser access is not permitted"}');
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
parseJsonBody(req).then(function (body) {
|
|
138
|
+
if (typeof saveGeneratedImageToProject !== "function") {
|
|
139
|
+
res.writeHead(501, { "Content-Type": "application/json" });
|
|
140
|
+
res.end('{"error":"Generated image saving is not available"}');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
var result = saveGeneratedImageToProject(
|
|
144
|
+
body.fileName,
|
|
145
|
+
body.path,
|
|
146
|
+
!!body.overwrite,
|
|
147
|
+
getOsUserInfoForReq(req)
|
|
148
|
+
);
|
|
149
|
+
res.writeHead(result.ok ? 200 : (result.status || 500), { "Content-Type": "application/json" });
|
|
150
|
+
res.end(JSON.stringify(result));
|
|
151
|
+
}).catch(function () {
|
|
152
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
153
|
+
res.end('{"error":"Invalid JSON body"}');
|
|
154
|
+
});
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
125
158
|
// File upload
|
|
126
159
|
if (req.method === "POST" && urlPath === "/api/upload") {
|
|
127
160
|
parseJsonBody(req).then(function (body) {
|
package/lib/project-image.js
CHANGED
|
@@ -12,13 +12,98 @@ var execFileSync = require("child_process").execFileSync;
|
|
|
12
12
|
function attachImage(ctx) {
|
|
13
13
|
var cwd = ctx.cwd;
|
|
14
14
|
var slug = ctx.slug;
|
|
15
|
+
var fsAsUser = ctx.fsAsUser;
|
|
15
16
|
|
|
16
17
|
// --- Chat image storage ---
|
|
17
18
|
var _imgConfig = require("./config");
|
|
18
19
|
var _imgUtils = require("./utils");
|
|
19
20
|
var _imagesBaseDir = path.join(_imgConfig.CONFIG_DIR, "images");
|
|
20
21
|
var _imagesEncodedCwd = _imgUtils.encodeCwd(cwd);
|
|
21
|
-
var imagesDir = path.join(_imagesBaseDir, _imagesEncodedCwd);
|
|
22
|
+
var imagesDir = ctx.imagesDir || path.join(_imagesBaseDir, _imagesEncodedCwd);
|
|
23
|
+
|
|
24
|
+
function isWithin(base, candidate) {
|
|
25
|
+
return candidate === base || candidate.indexOf(base + path.sep) === 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function saveGeneratedImageToProject(fileName, requestedPath, overwrite, osUserInfo) {
|
|
29
|
+
if (typeof fileName !== "string" || !/^\d+-[a-f0-9]+\.\w+$/.test(fileName)) {
|
|
30
|
+
return { ok: false, status: 400, error: "Invalid generated image" };
|
|
31
|
+
}
|
|
32
|
+
if (typeof requestedPath !== "string" || !requestedPath.trim() || requestedPath.length > 500) {
|
|
33
|
+
return { ok: false, status: 400, error: "Enter a project path" };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var sourcePath = path.join(imagesDir, fileName);
|
|
37
|
+
var sourceExt = path.extname(fileName).toLowerCase();
|
|
38
|
+
var targetPath = requestedPath.trim();
|
|
39
|
+
if (path.isAbsolute(targetPath)) {
|
|
40
|
+
return { ok: false, status: 400, error: "Use a project-relative path" };
|
|
41
|
+
}
|
|
42
|
+
var targetExt = path.extname(targetPath).toLowerCase();
|
|
43
|
+
if (targetExt !== sourceExt) {
|
|
44
|
+
return { ok: false, status: 400, error: "Keep the " + sourceExt + " file extension" };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var projectRoot;
|
|
48
|
+
var targetAbs;
|
|
49
|
+
try {
|
|
50
|
+
projectRoot = fs.realpathSync(cwd);
|
|
51
|
+
targetAbs = path.resolve(projectRoot, targetPath);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return { ok: false, status: 400, error: "Project path is not available" };
|
|
54
|
+
}
|
|
55
|
+
if (targetAbs === projectRoot || !isWithin(projectRoot, targetAbs)) {
|
|
56
|
+
return { ok: false, status: 403, error: "Path must stay inside the project" };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
var sourceReal = fs.realpathSync(sourcePath);
|
|
61
|
+
var imagesRoot = fs.realpathSync(imagesDir);
|
|
62
|
+
if (!isWithin(imagesRoot, sourceReal) || !fs.statSync(sourceReal).isFile()) {
|
|
63
|
+
return { ok: false, status: 404, error: "Generated image not found" };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
var parentDir = path.dirname(targetAbs);
|
|
67
|
+
var existingParent = parentDir;
|
|
68
|
+
while (!fs.existsSync(existingParent) && existingParent !== projectRoot) {
|
|
69
|
+
existingParent = path.dirname(existingParent);
|
|
70
|
+
}
|
|
71
|
+
var realExistingParent = fs.realpathSync(existingParent);
|
|
72
|
+
if (!isWithin(projectRoot, realExistingParent)) {
|
|
73
|
+
return { ok: false, status: 403, error: "Path must stay inside the project" };
|
|
74
|
+
}
|
|
75
|
+
if (osUserInfo && typeof fsAsUser === "function") {
|
|
76
|
+
fsAsUser("mkdir", { dir: parentDir }, osUserInfo);
|
|
77
|
+
} else {
|
|
78
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
79
|
+
}
|
|
80
|
+
var realParent = fs.realpathSync(parentDir);
|
|
81
|
+
if (!isWithin(projectRoot, realParent)) {
|
|
82
|
+
return { ok: false, status: 403, error: "Path must stay inside the project" };
|
|
83
|
+
}
|
|
84
|
+
if (fs.existsSync(targetAbs)) {
|
|
85
|
+
if (fs.lstatSync(targetAbs).isSymbolicLink()) {
|
|
86
|
+
return { ok: false, status: 403, error: "Symbolic link targets cannot be replaced" };
|
|
87
|
+
}
|
|
88
|
+
if (!overwrite) {
|
|
89
|
+
return { ok: false, status: 409, error: "A file already exists at this path" };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (osUserInfo && typeof fsAsUser === "function") {
|
|
94
|
+
fsAsUser("copy", { source: sourceReal, file: targetAbs, overwrite: !!overwrite }, osUserInfo);
|
|
95
|
+
} else {
|
|
96
|
+
fs.copyFileSync(sourceReal, targetAbs, overwrite ? 0 : fs.constants.COPYFILE_EXCL);
|
|
97
|
+
}
|
|
98
|
+
try { fs.chmodSync(targetAbs, 0o644); } catch (e2) {}
|
|
99
|
+
return { ok: true, path: path.relative(projectRoot, targetAbs).split(path.sep).join("/") };
|
|
100
|
+
} catch (e) {
|
|
101
|
+
if (e && e.code === "EEXIST") {
|
|
102
|
+
return { ok: false, status: 409, error: "A file already exists at this path" };
|
|
103
|
+
}
|
|
104
|
+
return { ok: false, status: 500, error: "Could not save the generated image" };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
22
107
|
|
|
23
108
|
// Convert imageRefs in history entries to images with URLs for the client
|
|
24
109
|
function hydrateImageRefs(entry) {
|
|
@@ -89,6 +174,7 @@ function attachImage(ctx) {
|
|
|
89
174
|
imagesDir: imagesDir,
|
|
90
175
|
hydrateImageRefs: hydrateImageRefs,
|
|
91
176
|
saveImageFile: saveImageFile,
|
|
177
|
+
saveGeneratedImageToProject: saveGeneratedImageToProject,
|
|
92
178
|
};
|
|
93
179
|
}
|
|
94
180
|
|
|
@@ -39,14 +39,14 @@ function attachMateInteraction(ctx) {
|
|
|
39
39
|
vendor: "claude",
|
|
40
40
|
name: "Claude Code",
|
|
41
41
|
avatarColor: "#cc785c",
|
|
42
|
-
avatarStyle: "
|
|
42
|
+
avatarStyle: "imprint",
|
|
43
43
|
avatarSeed: "plain-claude",
|
|
44
44
|
},
|
|
45
45
|
"plain:codex": {
|
|
46
46
|
vendor: "codex",
|
|
47
47
|
name: "Codex",
|
|
48
48
|
avatarColor: "#10a37f",
|
|
49
|
-
avatarStyle: "
|
|
49
|
+
avatarStyle: "imprint",
|
|
50
50
|
avatarSeed: "plain-codex",
|
|
51
51
|
},
|
|
52
52
|
};
|
|
@@ -554,8 +554,8 @@ function attachMateInteraction(ctx) {
|
|
|
554
554
|
}
|
|
555
555
|
|
|
556
556
|
var mateName = (mate.profile && mate.profile.displayName) || mate.name || "Mate";
|
|
557
|
-
var avatarColor = (mate.profile && mate.profile.avatarColor) || "#
|
|
558
|
-
var avatarStyle = (mate.profile && mate.profile.avatarStyle) || "
|
|
557
|
+
var avatarColor = (mate.profile && mate.profile.avatarColor) || "#5857fc";
|
|
558
|
+
var avatarStyle = (mate.profile && mate.profile.avatarStyle) || "imprint";
|
|
559
559
|
var avatarSeed = (mate.profile && mate.profile.avatarSeed) || mate.id;
|
|
560
560
|
|
|
561
561
|
// Build full mention text (include pasted content)
|
|
@@ -800,11 +800,11 @@ function attachMateInteraction(ctx) {
|
|
|
800
800
|
|
|
801
801
|
function getMateProfile(mateCtx, mateId) {
|
|
802
802
|
var mate = matesModule.getMate(mateCtx, mateId);
|
|
803
|
-
if (!mate) return { name: "Mate", avatarColor: "#
|
|
803
|
+
if (!mate) return { name: "Mate", avatarColor: "#5857fc", avatarStyle: "imprint", avatarSeed: mateId };
|
|
804
804
|
return {
|
|
805
805
|
name: (mate.profile && mate.profile.displayName) || mate.name || "Mate",
|
|
806
|
-
avatarColor: (mate.profile && mate.profile.avatarColor) || "#
|
|
807
|
-
avatarStyle: (mate.profile && mate.profile.avatarStyle) || "
|
|
806
|
+
avatarColor: (mate.profile && mate.profile.avatarColor) || "#5857fc",
|
|
807
|
+
avatarStyle: (mate.profile && mate.profile.avatarStyle) || "imprint",
|
|
808
808
|
avatarSeed: (mate.profile && mate.profile.avatarSeed) || mateId,
|
|
809
809
|
};
|
|
810
810
|
}
|
package/lib/project-sessions.js
CHANGED
|
@@ -1391,7 +1391,7 @@ function attachSessions(ctx) {
|
|
|
1391
1391
|
type: msg.type,
|
|
1392
1392
|
userId: u.id,
|
|
1393
1393
|
displayName: p.name || u.displayName || u.username,
|
|
1394
|
-
avatarStyle: p.avatarStyle || "
|
|
1394
|
+
avatarStyle: p.avatarStyle || "imprint",
|
|
1395
1395
|
avatarSeed: p.avatarSeed || u.username,
|
|
1396
1396
|
avatarCustom: p.avatarCustom || "",
|
|
1397
1397
|
};
|
|
@@ -47,9 +47,9 @@ function attachUserMention(ctx) {
|
|
|
47
47
|
var u = ws._clayUser;
|
|
48
48
|
var p = u.profile || {};
|
|
49
49
|
return {
|
|
50
|
-
style: p.avatarStyle || "
|
|
50
|
+
style: p.avatarStyle || "imprint",
|
|
51
51
|
seed: p.avatarSeed || u.username || u.id,
|
|
52
|
-
color: p.avatarColor || "#
|
|
52
|
+
color: p.avatarColor || "#5857fc",
|
|
53
53
|
custom: p.avatarCustom || "",
|
|
54
54
|
};
|
|
55
55
|
}
|
|
@@ -63,9 +63,9 @@ function attachUserMention(ctx) {
|
|
|
63
63
|
id: u.id,
|
|
64
64
|
name: p.name || u.displayName || u.username || "User",
|
|
65
65
|
username: u.username,
|
|
66
|
-
avatarStyle: p.avatarStyle || "
|
|
66
|
+
avatarStyle: p.avatarStyle || "imprint",
|
|
67
67
|
avatarSeed: p.avatarSeed || u.username,
|
|
68
|
-
avatarColor: p.avatarColor || "#
|
|
68
|
+
avatarColor: p.avatarColor || "#5857fc",
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
|
package/lib/project.js
CHANGED
|
@@ -187,7 +187,7 @@ function createProjectContext(opts) {
|
|
|
187
187
|
// Do NOT write to .claude-local/settings.json -- the SDK reads that too, causing duplicate spawns.
|
|
188
188
|
|
|
189
189
|
// --- Image engine (delegated to project-image.js) ---
|
|
190
|
-
var _image = attachImage({ cwd: cwd, slug: slug });
|
|
190
|
+
var _image = attachImage({ cwd: cwd, slug: slug, fsAsUser: fsAsUser });
|
|
191
191
|
var imagesDir = _image.imagesDir;
|
|
192
192
|
var hydrateImageRefs = _image.hydrateImageRefs;
|
|
193
193
|
var saveImageFile = _image.saveImageFile;
|
|
@@ -344,7 +344,7 @@ function createProjectContext(opts) {
|
|
|
344
344
|
id: u.id,
|
|
345
345
|
displayName: p.name || u.displayName || u.username,
|
|
346
346
|
username: u.username,
|
|
347
|
-
avatarStyle: p.avatarStyle || "
|
|
347
|
+
avatarStyle: p.avatarStyle || "imprint",
|
|
348
348
|
avatarSeed: p.avatarSeed || u.username,
|
|
349
349
|
avatarCustom: p.avatarCustom || "",
|
|
350
350
|
});
|
|
@@ -1277,8 +1277,9 @@ function createProjectContext(opts) {
|
|
|
1277
1277
|
id: u.id,
|
|
1278
1278
|
displayName: p.name || u.displayName || u.username,
|
|
1279
1279
|
username: u.username,
|
|
1280
|
-
avatarStyle: p.avatarStyle || "
|
|
1280
|
+
avatarStyle: p.avatarStyle || "imprint",
|
|
1281
1281
|
avatarSeed: p.avatarSeed || u.username,
|
|
1282
|
+
avatarColor: p.avatarColor || "#5857fc",
|
|
1282
1283
|
avatarCustom: p.avatarCustom || "",
|
|
1283
1284
|
});
|
|
1284
1285
|
}
|
|
@@ -1632,6 +1633,7 @@ function createProjectContext(opts) {
|
|
|
1632
1633
|
gitAttribution: _gitAttribution,
|
|
1633
1634
|
send: send,
|
|
1634
1635
|
imagesDir: imagesDir,
|
|
1636
|
+
saveGeneratedImageToProject: _image.saveGeneratedImageToProject,
|
|
1635
1637
|
osUsers: osUsers,
|
|
1636
1638
|
pushModule: pushModule,
|
|
1637
1639
|
safePath: safePath,
|
|
@@ -1826,7 +1828,7 @@ function createProjectContext(opts) {
|
|
|
1826
1828
|
id: u.id,
|
|
1827
1829
|
displayName: p.name || u.displayName || u.username,
|
|
1828
1830
|
username: u.username,
|
|
1829
|
-
avatarStyle: p.avatarStyle || "
|
|
1831
|
+
avatarStyle: p.avatarStyle || "imprint",
|
|
1830
1832
|
avatarSeed: p.avatarSeed || u.username,
|
|
1831
1833
|
avatarCustom: p.avatarCustom || "",
|
|
1832
1834
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* Clay Imprints use one consistent, pressed-square silhouette everywhere. */
|
|
2
|
+
.activity-inline-avatar,
|
|
3
|
+
.ask-mate-avatar,
|
|
4
|
+
.client-avatar,
|
|
5
|
+
.debate-info-avatar,
|
|
6
|
+
.debate-panel-item-avatar,
|
|
7
|
+
.debate-panelist-avatar,
|
|
8
|
+
.debate-speaker-avatar,
|
|
9
|
+
.delegated-card-avatar,
|
|
10
|
+
.dm-bubble-avatar,
|
|
11
|
+
.dm-header-avatar,
|
|
12
|
+
.dm-msg-avatar,
|
|
13
|
+
.dm-picker-mates-marquee-avatar,
|
|
14
|
+
.dm-user-picker-avatar,
|
|
15
|
+
.home-chat-avatar,
|
|
16
|
+
.home-hub-mate-avatar,
|
|
17
|
+
.icon-strip-me-avatar,
|
|
18
|
+
.icon-strip-user-avatar,
|
|
19
|
+
.input-mention-chip-avatar,
|
|
20
|
+
.mate-collapsed-avatar,
|
|
21
|
+
.mate-mobile-avatar,
|
|
22
|
+
.mate-profile-avatar,
|
|
23
|
+
.mate-sidebar-avatar,
|
|
24
|
+
.mention-avatar,
|
|
25
|
+
.mention-item-avatar,
|
|
26
|
+
.mobile-chat-chip-avatar,
|
|
27
|
+
.notif-banner-avatar,
|
|
28
|
+
.profile-avatar-custom-preview,
|
|
29
|
+
.profile-popover-avatar-img,
|
|
30
|
+
.project-switcher-avatar,
|
|
31
|
+
.remote-cursor-avatar,
|
|
32
|
+
.rewind-avatar,
|
|
33
|
+
.session-presence-avatar,
|
|
34
|
+
.sidebar-presence-avatar,
|
|
35
|
+
.us-account-avatar,
|
|
36
|
+
.us-account-avatar-img,
|
|
37
|
+
.user-island-avatar,
|
|
38
|
+
.user-island-avatar img {
|
|
39
|
+
border-radius: 26% !important;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.session-presence-avatar,
|
|
43
|
+
.sidebar-presence-avatar,
|
|
44
|
+
.client-avatar {
|
|
45
|
+
box-shadow: 0 0 0 1px rgba(var(--overlay-rgb), 0.12);
|
|
46
|
+
}
|