clay-server 3.6.0 → 3.7.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/project-http.js +51 -0
- package/lib/project-image.js +1 -1
- package/lib/project.js +3 -1
- package/lib/public/css/filebrowser.css +117 -7
- package/lib/public/css/generated-images.css +225 -0
- package/lib/public/css/input.css +2 -77
- package/lib/public/css/tui-attention.css +1 -2
- package/lib/public/index.html +3 -44
- package/lib/public/modules/app-messages.js +9 -33
- package/lib/public/modules/app-panels.js +0 -72
- package/lib/public/modules/filebrowser-context-menu.js +148 -0
- package/lib/public/modules/filebrowser.js +41 -4
- package/lib/public/modules/generated-images.js +132 -0
- package/lib/public/modules/input.js +2 -11
- package/lib/public/modules/session-tui-view.js +2 -3
- package/lib/public/modules/theme.js +4 -2
- package/lib/public/modules/tui-attention.js +5 -8
- package/lib/public/style.css +3 -2
- package/lib/sdk-bridge.js +2 -0
- package/lib/sdk-message-processor.js +57 -2
- package/lib/sessions.js +8 -6
- package/lib/yoke/adapters/codex.js +39 -0
- package/package.json +1 -1
package/lib/project-http.js
CHANGED
|
@@ -254,6 +254,57 @@ function attachHTTP(ctx) {
|
|
|
254
254
|
return true;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
// File browser: download project files
|
|
258
|
+
if (req.method === "GET" && urlPath.startsWith("/api/file/download?")) {
|
|
259
|
+
if (usersModule.isMultiUser()) {
|
|
260
|
+
var downloadUser = req._clayUser;
|
|
261
|
+
var downloadPermissions = downloadUser ? usersModule.getEffectivePermissions(downloadUser, osUsers) : null;
|
|
262
|
+
if (!downloadPermissions || !downloadPermissions.fileBrowser) {
|
|
263
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
264
|
+
res.end("File browser access is not permitted");
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
var downloadQueryIndex = urlPath.indexOf("?");
|
|
270
|
+
var downloadParams = new URLSearchParams(urlPath.substring(downloadQueryIndex));
|
|
271
|
+
var downloadPath = downloadParams.get("path");
|
|
272
|
+
if (!downloadPath) { res.writeHead(400); res.end("Missing path"); return true; }
|
|
273
|
+
var downloadFile = safePath(cwd, downloadPath);
|
|
274
|
+
if (!downloadFile && getOsUserInfoForReq(req)) {
|
|
275
|
+
downloadFile = safeAbsPath(downloadPath);
|
|
276
|
+
}
|
|
277
|
+
if (!downloadFile) { res.writeHead(403); res.end("Access denied"); return true; }
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
var downloadUserInfo = getOsUserInfoForReq(req);
|
|
281
|
+
var downloadContent;
|
|
282
|
+
if (downloadUserInfo) {
|
|
283
|
+
downloadContent = fsAsUser("read_binary", { file: downloadFile }, downloadUserInfo).buffer;
|
|
284
|
+
} else {
|
|
285
|
+
downloadContent = fs.readFileSync(downloadFile);
|
|
286
|
+
}
|
|
287
|
+
var downloadName = path.basename(downloadPath).replace(/[\x00-\x1f\x7f"\\]/g, "_") || "download";
|
|
288
|
+
var asciiDownloadName = downloadName.replace(/[^\x20-\x7e]/g, "_");
|
|
289
|
+
var encodedDownloadName = encodeURIComponent(downloadName).replace(/[!'()*]/g, function (character) {
|
|
290
|
+
return "%" + character.charCodeAt(0).toString(16).toUpperCase();
|
|
291
|
+
});
|
|
292
|
+
var contentDisposition = "attachment; filename=\"" + asciiDownloadName + "\"; filename*=UTF-8''" + encodedDownloadName;
|
|
293
|
+
res.writeHead(200, {
|
|
294
|
+
"Content-Type": "application/octet-stream",
|
|
295
|
+
"Content-Length": downloadContent.length,
|
|
296
|
+
"Content-Disposition": contentDisposition,
|
|
297
|
+
"Cache-Control": "no-store",
|
|
298
|
+
"X-Content-Type-Options": "nosniff",
|
|
299
|
+
});
|
|
300
|
+
res.end(downloadContent);
|
|
301
|
+
} catch (e) {
|
|
302
|
+
res.writeHead(404);
|
|
303
|
+
res.end("Not found");
|
|
304
|
+
}
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
|
|
257
308
|
// File browser: serve project images
|
|
258
309
|
if (req.method === "GET" && urlPath.startsWith("/api/file?")) {
|
|
259
310
|
var qIdx = urlPath.indexOf("?");
|
package/lib/project-image.js
CHANGED
|
@@ -34,7 +34,7 @@ function attachImage(ctx) {
|
|
|
34
34
|
return hydrated;
|
|
35
35
|
}
|
|
36
36
|
if (!entry.imageRefs) return entry;
|
|
37
|
-
if (entry.type !== "user_message" && entry.type !== "mention_user" && entry.type !== "user_mention") return entry;
|
|
37
|
+
if (entry.type !== "user_message" && entry.type !== "mention_user" && entry.type !== "user_mention" && entry.type !== "generated_image") return entry;
|
|
38
38
|
var images = [];
|
|
39
39
|
for (var ri = 0; ri < entry.imageRefs.length; ri++) {
|
|
40
40
|
var ref = entry.imageRefs[ri];
|
package/lib/project.js
CHANGED
|
@@ -111,6 +111,7 @@ var BINARY_EXTS = new Set([
|
|
|
111
111
|
]);
|
|
112
112
|
var IMAGE_EXTS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico"]);
|
|
113
113
|
var FS_MAX_SIZE = 512 * 1024;
|
|
114
|
+
var FS_VIEWER_MAX_SIZE = 5 * 1024 * 1024;
|
|
114
115
|
function safePath(base, requested) {
|
|
115
116
|
var resolved = path.resolve(base, requested);
|
|
116
117
|
if (resolved !== base && !resolved.startsWith(base + path.sep)) return null;
|
|
@@ -882,6 +883,7 @@ function createProjectContext(opts) {
|
|
|
882
883
|
scheduleMessage: function (session, text, resetsAt) {
|
|
883
884
|
scheduleMessage(session, text, resetsAt);
|
|
884
885
|
},
|
|
886
|
+
saveImageFile: saveImageFile,
|
|
885
887
|
getAutoContinueSetting: function (session) {
|
|
886
888
|
// Per-user setting in multi-user mode
|
|
887
889
|
if (usersModule.isMultiUser() && session && session.ownerId) {
|
|
@@ -1437,7 +1439,7 @@ function createProjectContext(opts) {
|
|
|
1437
1439
|
IGNORED_DIRS: IGNORED_DIRS,
|
|
1438
1440
|
BINARY_EXTS: BINARY_EXTS,
|
|
1439
1441
|
IMAGE_EXTS: IMAGE_EXTS,
|
|
1440
|
-
FS_MAX_SIZE:
|
|
1442
|
+
FS_MAX_SIZE: FS_VIEWER_MAX_SIZE,
|
|
1441
1443
|
});
|
|
1442
1444
|
|
|
1443
1445
|
// --- MCP bridge handler for Codex and session-bound Kiro tools ---
|
|
@@ -259,6 +259,11 @@
|
|
|
259
259
|
|
|
260
260
|
.file-tree-item:hover { background: var(--sidebar-hover); color: var(--text); }
|
|
261
261
|
.file-tree-item.active { background: var(--sidebar-active); color: var(--text); }
|
|
262
|
+
.file-tree-item.context-open {
|
|
263
|
+
background: var(--sidebar-active);
|
|
264
|
+
color: var(--text);
|
|
265
|
+
box-shadow: inset 0 0 0 1px var(--border);
|
|
266
|
+
}
|
|
262
267
|
/* Keyboard focus ring (arrow-key navigation) — separate from .active
|
|
263
268
|
so the currently-opened file stays visually marked even while the
|
|
264
269
|
user is exploring elsewhere with the arrows. */
|
|
@@ -324,6 +329,65 @@
|
|
|
324
329
|
color: var(--error);
|
|
325
330
|
}
|
|
326
331
|
|
|
332
|
+
/* --- File tree context menu --- */
|
|
333
|
+
.file-tree-context-menu {
|
|
334
|
+
position: fixed;
|
|
335
|
+
z-index: 10040;
|
|
336
|
+
min-width: 164px;
|
|
337
|
+
padding: 5px;
|
|
338
|
+
border: 1px solid var(--border);
|
|
339
|
+
border-radius: 10px;
|
|
340
|
+
background: var(--sidebar-bg);
|
|
341
|
+
box-shadow: 0 12px 34px rgba(var(--shadow-rgb), 0.34);
|
|
342
|
+
animation: file-tree-context-in 0.12s ease-out both;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.file-tree-context-item {
|
|
346
|
+
display: flex;
|
|
347
|
+
align-items: center;
|
|
348
|
+
gap: 9px;
|
|
349
|
+
width: 100%;
|
|
350
|
+
min-height: 34px;
|
|
351
|
+
padding: 7px 10px;
|
|
352
|
+
border: 0;
|
|
353
|
+
border-radius: 7px;
|
|
354
|
+
background: transparent;
|
|
355
|
+
color: var(--text-secondary);
|
|
356
|
+
font: inherit;
|
|
357
|
+
font-size: 13px;
|
|
358
|
+
text-align: left;
|
|
359
|
+
cursor: pointer;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.file-tree-context-item:hover,
|
|
363
|
+
.file-tree-context-item:focus-visible {
|
|
364
|
+
outline: none;
|
|
365
|
+
background: rgba(var(--overlay-rgb), 0.06);
|
|
366
|
+
color: var(--text);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.file-tree-context-item .lucide {
|
|
370
|
+
width: 15px;
|
|
371
|
+
height: 15px;
|
|
372
|
+
flex-shrink: 0;
|
|
373
|
+
color: var(--text-muted);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.file-tree-context-separator {
|
|
377
|
+
height: 1px;
|
|
378
|
+
margin: 4px 5px;
|
|
379
|
+
background: var(--border-subtle);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@keyframes file-tree-context-in {
|
|
383
|
+
from { opacity: 0; transform: translateY(-3px) scale(0.98); }
|
|
384
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@media (prefers-reduced-motion: reduce) {
|
|
388
|
+
.file-tree-context-menu { animation: none; }
|
|
389
|
+
}
|
|
390
|
+
|
|
327
391
|
/* --- Panel fullscreen --- */
|
|
328
392
|
@media (min-width: 1024px) {
|
|
329
393
|
#main-column:has(.panel-fullscreen:not(.hidden)) > .title-bar-content { display: none; }
|
|
@@ -1695,6 +1759,51 @@
|
|
|
1695
1759
|
padding: 0;
|
|
1696
1760
|
}
|
|
1697
1761
|
|
|
1762
|
+
.file-viewer-large-text {
|
|
1763
|
+
min-height: 100%;
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
.file-viewer-large-notice {
|
|
1767
|
+
position: sticky;
|
|
1768
|
+
top: 0;
|
|
1769
|
+
left: 0;
|
|
1770
|
+
z-index: 2;
|
|
1771
|
+
display: flex;
|
|
1772
|
+
align-items: center;
|
|
1773
|
+
gap: 7px;
|
|
1774
|
+
width: fit-content;
|
|
1775
|
+
margin: 10px 12px 0;
|
|
1776
|
+
padding: 6px 9px;
|
|
1777
|
+
color: var(--text-muted);
|
|
1778
|
+
background: color-mix(in srgb, var(--bg) 92%, var(--accent));
|
|
1779
|
+
border: 1px solid var(--border-subtle);
|
|
1780
|
+
border-radius: 7px;
|
|
1781
|
+
font-size: 12px;
|
|
1782
|
+
line-height: 1.35;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
.file-viewer-large-notice svg {
|
|
1786
|
+
width: 14px;
|
|
1787
|
+
height: 14px;
|
|
1788
|
+
flex-shrink: 0;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
.file-viewer-large-text pre {
|
|
1792
|
+
width: max-content;
|
|
1793
|
+
min-width: 100%;
|
|
1794
|
+
margin: 0;
|
|
1795
|
+
padding: 12px 14px;
|
|
1796
|
+
box-sizing: border-box;
|
|
1797
|
+
white-space: pre;
|
|
1798
|
+
tab-size: 2;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
.file-viewer-large-text code {
|
|
1802
|
+
font-family: var(--font-mono);
|
|
1803
|
+
font-size: 12px;
|
|
1804
|
+
line-height: 1.55;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1698
1807
|
.file-viewer-binary {
|
|
1699
1808
|
display: flex;
|
|
1700
1809
|
align-items: center;
|
|
@@ -1948,6 +2057,7 @@
|
|
|
1948
2057
|
min-height: 0;
|
|
1949
2058
|
overflow: hidden;
|
|
1950
2059
|
position: relative;
|
|
2060
|
+
background: #141412;
|
|
1951
2061
|
}
|
|
1952
2062
|
|
|
1953
2063
|
.terminal-tab-body {
|
|
@@ -1967,8 +2077,8 @@
|
|
|
1967
2077
|
align-items: center;
|
|
1968
2078
|
gap: 6px;
|
|
1969
2079
|
padding: 6px 8px;
|
|
1970
|
-
background:
|
|
1971
|
-
border-bottom: 1px solid
|
|
2080
|
+
background: var(--bg-alt);
|
|
2081
|
+
border-bottom: 1px solid var(--border);
|
|
1972
2082
|
flex-shrink: 0;
|
|
1973
2083
|
overflow-x: auto;
|
|
1974
2084
|
-webkit-overflow-scrolling: touch;
|
|
@@ -1984,9 +2094,9 @@
|
|
|
1984
2094
|
min-width: 40px;
|
|
1985
2095
|
padding: 0 10px;
|
|
1986
2096
|
border-radius: 6px;
|
|
1987
|
-
border: 1px solid
|
|
1988
|
-
background:
|
|
1989
|
-
color:
|
|
2097
|
+
border: 1px solid var(--border);
|
|
2098
|
+
background: var(--sidebar-active);
|
|
2099
|
+
color: var(--text-secondary);
|
|
1990
2100
|
font-family: "Roboto Mono", monospace;
|
|
1991
2101
|
font-size: 12px;
|
|
1992
2102
|
font-weight: 500;
|
|
@@ -1998,8 +2108,8 @@
|
|
|
1998
2108
|
}
|
|
1999
2109
|
|
|
2000
2110
|
.term-key:active {
|
|
2001
|
-
background:
|
|
2002
|
-
border-color:
|
|
2111
|
+
background: var(--sidebar-hover);
|
|
2112
|
+
border-color: var(--text-dimmer);
|
|
2003
2113
|
}
|
|
2004
2114
|
|
|
2005
2115
|
.term-key-toggle.active {
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
.generated-image-row {
|
|
2
|
+
width: 100%;
|
|
3
|
+
max-width: var(--content-width);
|
|
4
|
+
margin: 4px auto 16px;
|
|
5
|
+
padding: 0 20px;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.generated-image-card {
|
|
9
|
+
width: min(560px, 100%);
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
border: 1px solid var(--border);
|
|
12
|
+
border-radius: 14px;
|
|
13
|
+
background: var(--bg-alt);
|
|
14
|
+
box-shadow: 0 8px 28px rgba(var(--shadow-rgb), 0.16);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.generated-image-status {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: 7px;
|
|
21
|
+
width: min(560px, 100%);
|
|
22
|
+
min-height: 30px;
|
|
23
|
+
padding: 0 2px 7px;
|
|
24
|
+
color: var(--text-muted);
|
|
25
|
+
font-size: 12px;
|
|
26
|
+
font-weight: 500;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.generated-image-status .lucide {
|
|
30
|
+
width: 14px;
|
|
31
|
+
height: 14px;
|
|
32
|
+
color: var(--accent);
|
|
33
|
+
animation: generated-image-sparkle 2.4s ease-in-out infinite;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.generated-image-status-dots::after {
|
|
37
|
+
content: "";
|
|
38
|
+
animation: generated-image-ellipsis 1.4s steps(4, end) infinite;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.generated-image-card--pending {
|
|
42
|
+
position: relative;
|
|
43
|
+
width: min(560px, 100%);
|
|
44
|
+
aspect-ratio: 1 / 1;
|
|
45
|
+
border-color: var(--border-subtle);
|
|
46
|
+
background: var(--bg-alt);
|
|
47
|
+
box-shadow: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.generated-image-particle-field {
|
|
51
|
+
position: absolute;
|
|
52
|
+
inset: 0;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.generated-image-particle-field::before {
|
|
57
|
+
position: absolute;
|
|
58
|
+
inset: 11%;
|
|
59
|
+
content: "";
|
|
60
|
+
background-image: radial-gradient(circle, var(--text-dimmer) 1.4px, transparent 1.7px);
|
|
61
|
+
background-position: center;
|
|
62
|
+
background-size: 25px 25px;
|
|
63
|
+
opacity: 0.52;
|
|
64
|
+
-webkit-mask-image: radial-gradient(circle, #000 0%, rgba(0, 0, 0, 0.88) 38%, transparent 72%);
|
|
65
|
+
mask-image: radial-gradient(circle, #000 0%, rgba(0, 0, 0, 0.88) 38%, transparent 72%);
|
|
66
|
+
animation: generated-image-field 3.2s ease-in-out infinite;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.generated-image-particle-field::after {
|
|
70
|
+
position: absolute;
|
|
71
|
+
top: 50%;
|
|
72
|
+
left: 50%;
|
|
73
|
+
width: 36%;
|
|
74
|
+
aspect-ratio: 1 / 1;
|
|
75
|
+
border: 1px solid var(--accent-15);
|
|
76
|
+
border-radius: 50%;
|
|
77
|
+
content: "";
|
|
78
|
+
background: radial-gradient(circle, var(--accent-12), transparent 68%);
|
|
79
|
+
transform: translate(-50%, -50%);
|
|
80
|
+
animation: generated-image-pulse 3.2s ease-in-out infinite;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@keyframes generated-image-field {
|
|
84
|
+
0%, 100% { opacity: 0.28; transform: scale(0.92) rotate(-2deg); }
|
|
85
|
+
50% { opacity: 0.68; transform: scale(1.04) rotate(2deg); }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@keyframes generated-image-pulse {
|
|
89
|
+
0%, 100% { opacity: 0.2; transform: translate(-50%, -50%) scale(0.72); }
|
|
90
|
+
50% { opacity: 0.72; transform: translate(-50%, -50%) scale(1.08); }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@keyframes generated-image-sparkle {
|
|
94
|
+
0%, 100% { opacity: 0.5; transform: scale(0.86) rotate(-8deg); }
|
|
95
|
+
50% { opacity: 1; transform: scale(1.08) rotate(8deg); }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@keyframes generated-image-ellipsis {
|
|
99
|
+
0% { content: ""; }
|
|
100
|
+
25% { content: "."; }
|
|
101
|
+
50% { content: ".."; }
|
|
102
|
+
75%, 100% { content: "..."; }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@media (prefers-reduced-motion: reduce) {
|
|
106
|
+
.generated-image-status .lucide,
|
|
107
|
+
.generated-image-status-dots::after,
|
|
108
|
+
.generated-image-particle-field::before,
|
|
109
|
+
.generated-image-particle-field::after {
|
|
110
|
+
animation: none;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.generated-image-preview {
|
|
115
|
+
display: grid;
|
|
116
|
+
place-items: center;
|
|
117
|
+
min-height: 180px;
|
|
118
|
+
max-height: 680px;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
background:
|
|
121
|
+
linear-gradient(45deg, rgba(var(--overlay-rgb), 0.025) 25%, transparent 25%),
|
|
122
|
+
linear-gradient(-45deg, rgba(var(--overlay-rgb), 0.025) 25%, transparent 25%),
|
|
123
|
+
linear-gradient(45deg, transparent 75%, rgba(var(--overlay-rgb), 0.025) 75%),
|
|
124
|
+
linear-gradient(-45deg, transparent 75%, rgba(var(--overlay-rgb), 0.025) 75%);
|
|
125
|
+
background-position: 0 0, 0 8px, 8px -8px, -8px 0;
|
|
126
|
+
background-size: 16px 16px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.generated-image-preview img {
|
|
130
|
+
display: block;
|
|
131
|
+
width: 100%;
|
|
132
|
+
max-height: 680px;
|
|
133
|
+
object-fit: contain;
|
|
134
|
+
cursor: zoom-in;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.generated-image-footer {
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: space-between;
|
|
141
|
+
gap: 14px;
|
|
142
|
+
min-height: 52px;
|
|
143
|
+
padding: 9px 10px 9px 14px;
|
|
144
|
+
border-top: 1px solid var(--border-subtle);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.generated-image-meta {
|
|
148
|
+
display: flex;
|
|
149
|
+
flex: 1;
|
|
150
|
+
min-width: 0;
|
|
151
|
+
flex-direction: column;
|
|
152
|
+
gap: 2px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.generated-image-label {
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
gap: 6px;
|
|
159
|
+
color: var(--text-secondary);
|
|
160
|
+
font-size: 12px;
|
|
161
|
+
font-weight: 600;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.generated-image-label .lucide {
|
|
165
|
+
width: 13px;
|
|
166
|
+
height: 13px;
|
|
167
|
+
color: var(--accent);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.generated-image-prompt {
|
|
171
|
+
overflow: hidden;
|
|
172
|
+
color: var(--text-muted);
|
|
173
|
+
font-size: 11px;
|
|
174
|
+
line-height: 1.35;
|
|
175
|
+
text-overflow: ellipsis;
|
|
176
|
+
white-space: nowrap;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.generated-image-actions {
|
|
180
|
+
display: flex;
|
|
181
|
+
flex-shrink: 0;
|
|
182
|
+
gap: 4px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.generated-image-action {
|
|
186
|
+
display: inline-flex;
|
|
187
|
+
align-items: center;
|
|
188
|
+
gap: 5px;
|
|
189
|
+
height: 32px;
|
|
190
|
+
padding: 0 9px;
|
|
191
|
+
border: 1px solid transparent;
|
|
192
|
+
border-radius: 8px;
|
|
193
|
+
background: transparent;
|
|
194
|
+
color: var(--text-muted);
|
|
195
|
+
font: inherit;
|
|
196
|
+
font-size: 11px;
|
|
197
|
+
text-decoration: none;
|
|
198
|
+
cursor: pointer;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.generated-image-action:hover {
|
|
202
|
+
border-color: var(--border);
|
|
203
|
+
background: rgba(var(--overlay-rgb), 0.04);
|
|
204
|
+
color: var(--text);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.generated-image-action .lucide {
|
|
208
|
+
width: 14px;
|
|
209
|
+
height: 14px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@media (max-width: 560px) {
|
|
213
|
+
.generated-image-row { padding: 0 12px; }
|
|
214
|
+
.generated-image-card { border-radius: 12px; }
|
|
215
|
+
|
|
216
|
+
.generated-image-action span {
|
|
217
|
+
display: none;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.generated-image-action {
|
|
221
|
+
width: 32px;
|
|
222
|
+
justify-content: center;
|
|
223
|
+
padding: 0;
|
|
224
|
+
}
|
|
225
|
+
}
|
package/lib/public/css/input.css
CHANGED
|
@@ -762,7 +762,7 @@
|
|
|
762
762
|
color: var(--text-muted);
|
|
763
763
|
}
|
|
764
764
|
|
|
765
|
-
/* --- Bottom toolbar (attach left,
|
|
765
|
+
/* --- Bottom toolbar (attach left, session config + send right) --- */
|
|
766
766
|
#input-bottom {
|
|
767
767
|
display: flex;
|
|
768
768
|
align-items: center;
|
|
@@ -777,21 +777,7 @@
|
|
|
777
777
|
flex-shrink: 0;
|
|
778
778
|
}
|
|
779
779
|
|
|
780
|
-
/*
|
|
781
|
-
#vendor-toggle-wrap {
|
|
782
|
-
display: flex;
|
|
783
|
-
align-items: center;
|
|
784
|
-
border: 1px solid var(--border);
|
|
785
|
-
border-radius: 8px;
|
|
786
|
-
overflow: hidden;
|
|
787
|
-
height: 30px;
|
|
788
|
-
flex-shrink: 0;
|
|
789
|
-
}
|
|
790
|
-
#vendor-toggle-wrap.hidden { display: none; }
|
|
791
|
-
|
|
792
|
-
/* Compact session-vendor icon shown next to the config-chip when the
|
|
793
|
-
full vendor-toggle is hidden (because the session's vendor is already
|
|
794
|
-
committed). Visual only - not clickable. */
|
|
780
|
+
/* Compact committed-session vendor icon next to the config chip. */
|
|
795
781
|
#active-vendor-indicator {
|
|
796
782
|
display: inline-flex;
|
|
797
783
|
align-items: center;
|
|
@@ -806,73 +792,13 @@
|
|
|
806
792
|
border-radius: 4px;
|
|
807
793
|
object-fit: cover;
|
|
808
794
|
}
|
|
809
|
-
#vendor-toggle-wrap.locked {
|
|
810
|
-
border: none;
|
|
811
|
-
height: auto;
|
|
812
|
-
pointer-events: none;
|
|
813
|
-
}
|
|
814
|
-
#vendor-toggle-wrap.locked .vendor-toggle-btn:not(.active) { display: none; }
|
|
815
|
-
#vendor-toggle-wrap.locked .vendor-toggle-btn.active {
|
|
816
|
-
background: transparent;
|
|
817
|
-
padding: 0;
|
|
818
|
-
gap: 0;
|
|
819
|
-
opacity: 0.7;
|
|
820
|
-
}
|
|
821
|
-
#vendor-toggle-wrap.locked .vendor-toggle-btn.active .vendor-toggle-label { display: none; }
|
|
822
|
-
#vendor-toggle-wrap.locked .vendor-toggle-btn:first-child { border-right: none; }
|
|
823
|
-
.vendor-toggle-btn {
|
|
824
|
-
display: flex;
|
|
825
|
-
align-items: center;
|
|
826
|
-
gap: 4px;
|
|
827
|
-
padding: 0 10px;
|
|
828
|
-
height: 100%;
|
|
829
|
-
border: none;
|
|
830
|
-
background: transparent;
|
|
831
|
-
cursor: pointer;
|
|
832
|
-
font-size: 12px;
|
|
833
|
-
color: var(--text-secondary);
|
|
834
|
-
transition: background 0.15s, color 0.15s;
|
|
835
|
-
white-space: nowrap;
|
|
836
|
-
}
|
|
837
|
-
.vendor-toggle-btn:first-child { border-right: 1px solid var(--border); }
|
|
838
|
-
.vendor-toggle-btn.active {
|
|
839
|
-
background: var(--accent-12);
|
|
840
|
-
color: var(--accent);
|
|
841
|
-
font-weight: 600;
|
|
842
|
-
}
|
|
843
|
-
.vendor-toggle-btn.disabled {
|
|
844
|
-
opacity: 0.35;
|
|
845
|
-
cursor: default;
|
|
846
|
-
}
|
|
847
|
-
.vendor-toggle-btn.disabled:not(.active) { display: none; }
|
|
848
|
-
.vendor-toggle-icon {
|
|
849
|
-
width: 16px;
|
|
850
|
-
height: 16px;
|
|
851
|
-
border-radius: 4px;
|
|
852
|
-
object-fit: cover;
|
|
853
|
-
}
|
|
854
|
-
.vendor-toggle-label {
|
|
855
|
-
pointer-events: none;
|
|
856
|
-
}
|
|
857
|
-
.vendor-toggle-btn.experimental::after,
|
|
858
795
|
.vendor-experimental-badge {
|
|
859
|
-
content: "🧪";
|
|
860
796
|
font-size: 10px;
|
|
861
797
|
line-height: 1;
|
|
862
798
|
font-weight: 400;
|
|
863
799
|
filter: saturate(0.85);
|
|
864
|
-
}
|
|
865
|
-
.vendor-experimental-badge {
|
|
866
800
|
margin-left: auto;
|
|
867
801
|
}
|
|
868
|
-
@media (min-width: 901px) {
|
|
869
|
-
.vendor-toggle-btn:not(.active) .vendor-toggle-label { display: none; }
|
|
870
|
-
.vendor-toggle-btn:not(.active) { padding: 0 8px; }
|
|
871
|
-
}
|
|
872
|
-
@media (max-width: 900px) {
|
|
873
|
-
.vendor-toggle-label { display: none; }
|
|
874
|
-
.vendor-toggle-btn { padding: 0 8px; }
|
|
875
|
-
}
|
|
876
802
|
|
|
877
803
|
/* --- Attach buttons & menu --- */
|
|
878
804
|
#attach-wrap {
|
|
@@ -1290,7 +1216,6 @@
|
|
|
1290
1216
|
Attach (files/images -> path injection) and voice input stay available. */
|
|
1291
1217
|
body.tui-composer-active #schedule-btn,
|
|
1292
1218
|
body.tui-composer-active #ask-mate-btn,
|
|
1293
|
-
body.tui-composer-active #vendor-toggle-wrap,
|
|
1294
1219
|
body.tui-composer-active #active-vendor-indicator,
|
|
1295
1220
|
body.tui-composer-active #config-chip-wrap {
|
|
1296
1221
|
display: none !important;
|
|
@@ -282,7 +282,7 @@ body.tui-suspended #tui-resume-bar {
|
|
|
282
282
|
.tui-modal {
|
|
283
283
|
width: min(960px, 100%);
|
|
284
284
|
height: min(640px, 100%);
|
|
285
|
-
background:
|
|
285
|
+
background: var(--bg);
|
|
286
286
|
border-radius: 12px;
|
|
287
287
|
overflow: hidden;
|
|
288
288
|
display: flex;
|
|
@@ -683,4 +683,3 @@ body.tui-suspended #tui-resume-bar {
|
|
|
683
683
|
.wna-content { padding: 32px 20px 80px; }
|
|
684
684
|
.wna-title { font-size: 26px; }
|
|
685
685
|
}
|
|
686
|
-
|
package/lib/public/index.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
(function(){try{var k="clay-theme-vars",v=localStorage.getItem(k),r=document.documentElement;if(v){var o=JSON.parse(v),p;for(p in o)r.style.setProperty(p,o[p]);var vt=localStorage.getItem(k.replace("-vars","-variant"));if(vt==="light"){r.classList.add("light-theme");r.classList.remove("dark-theme")}else{r.classList.add("dark-theme");r.classList.remove("light-theme")}var m=document.querySelector('meta[name="theme-color"]');if(m&&o["--bg"])m.setAttribute("content",o["--bg"])}else{var sl=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;if(sl){r.classList.add("light-theme");r.classList.remove("dark-theme")}}}catch(e){}})();
|
|
31
31
|
</script>
|
|
32
32
|
<script>if(window.navigator.standalone||window.matchMedia("(display-mode:standalone)").matches){document.documentElement.classList.add("pwa-standalone")}</script>
|
|
33
|
-
<link rel="stylesheet" href="style.css?v=
|
|
33
|
+
<link rel="stylesheet" href="style.css?v=20260829-terminal-canvas1">
|
|
34
34
|
<style>
|
|
35
35
|
@media(max-width:768px){
|
|
36
36
|
/* User messages: vertical stack, avatar on top, right-aligned */
|
|
@@ -524,48 +524,6 @@
|
|
|
524
524
|
</div>
|
|
525
525
|
</div>
|
|
526
526
|
<div id="input-bottom-right">
|
|
527
|
-
<div id="vendor-toggle-wrap">
|
|
528
|
-
<button id="vendor-btn-claude" class="vendor-toggle-btn active" data-vendor="claude">
|
|
529
|
-
<img src="/claude-code-avatar.png" class="vendor-toggle-icon" alt="Claude">
|
|
530
|
-
<span class="vendor-toggle-label">Claude Code</span>
|
|
531
|
-
</button>
|
|
532
|
-
<button id="vendor-btn-codex" class="vendor-toggle-btn" data-vendor="codex">
|
|
533
|
-
<img src="/codex-avatar.png" class="vendor-toggle-icon" alt="Codex">
|
|
534
|
-
<span class="vendor-toggle-label">Codex</span>
|
|
535
|
-
</button>
|
|
536
|
-
<button id="vendor-btn-antigravity" class="vendor-toggle-btn" data-vendor="antigravity">
|
|
537
|
-
<img src="/antigravity-avatar.png" class="vendor-toggle-icon" alt="Antigravity">
|
|
538
|
-
<span class="vendor-toggle-label">Antigravity CLI</span>
|
|
539
|
-
</button>
|
|
540
|
-
<button id="vendor-btn-opencode" class="vendor-toggle-btn" data-vendor="opencode">
|
|
541
|
-
<img src="/opencode-avatar.svg" class="vendor-toggle-icon" alt="OpenCode">
|
|
542
|
-
<span class="vendor-toggle-label">OpenCode</span>
|
|
543
|
-
</button>
|
|
544
|
-
<button id="vendor-btn-kimi" class="vendor-toggle-btn" data-vendor="kimi">
|
|
545
|
-
<img src="/kimi-avatar.svg" class="vendor-toggle-icon" alt="Kimi">
|
|
546
|
-
<span class="vendor-toggle-label">Kimi Code</span>
|
|
547
|
-
</button>
|
|
548
|
-
<button id="vendor-btn-grok" class="vendor-toggle-btn" data-vendor="grok">
|
|
549
|
-
<img src="/grok-avatar.svg" class="vendor-toggle-icon" alt="Grok">
|
|
550
|
-
<span class="vendor-toggle-label">Grok Build</span>
|
|
551
|
-
</button>
|
|
552
|
-
<button id="vendor-btn-copilot" class="vendor-toggle-btn" data-vendor="copilot">
|
|
553
|
-
<img src="/copilot-avatar.svg" class="vendor-toggle-icon" alt="GitHub Copilot">
|
|
554
|
-
<span class="vendor-toggle-label">GitHub Copilot CLI</span>
|
|
555
|
-
</button>
|
|
556
|
-
<button id="vendor-btn-qwen" class="vendor-toggle-btn" data-vendor="qwen">
|
|
557
|
-
<img src="/qwen-avatar.svg" class="vendor-toggle-icon" alt="Qwen">
|
|
558
|
-
<span class="vendor-toggle-label">Qwen Code</span>
|
|
559
|
-
</button>
|
|
560
|
-
<button id="vendor-btn-junie" class="vendor-toggle-btn" data-vendor="junie">
|
|
561
|
-
<img src="/junie-avatar.svg" class="vendor-toggle-icon" alt="Junie">
|
|
562
|
-
<span class="vendor-toggle-label">Junie CLI</span>
|
|
563
|
-
</button>
|
|
564
|
-
<button id="vendor-btn-kiro" class="vendor-toggle-btn" data-vendor="kiro">
|
|
565
|
-
<img src="/kiro-avatar.svg" class="vendor-toggle-icon" alt="Kiro">
|
|
566
|
-
<span class="vendor-toggle-label">Kiro CLI</span>
|
|
567
|
-
</button>
|
|
568
|
-
</div>
|
|
569
527
|
<div id="active-vendor-indicator" class="hidden" title="Session vendor">
|
|
570
528
|
<img id="active-vendor-icon" alt="">
|
|
571
529
|
</div>
|
|
@@ -703,6 +661,7 @@
|
|
|
703
661
|
<button class="file-viewer-btn file-viewer-slide-level hidden" id="file-viewer-slide-level" title="Split slides by heading level" aria-haspopup="menu" aria-expanded="false"><span>H1</span><i data-lucide="chevron-down"></i></button>
|
|
704
662
|
<button class="file-viewer-btn hidden" id="file-viewer-history" title="Edit history"><i data-lucide="clock"></i></button>
|
|
705
663
|
<button class="file-viewer-btn" id="file-viewer-refresh" title="Refresh"><i data-lucide="refresh-cw"></i></button>
|
|
664
|
+
<button class="file-viewer-btn" id="file-viewer-download" title="Download file" aria-label="Download file"><i data-lucide="download"></i></button>
|
|
706
665
|
<button class="file-viewer-btn" id="file-viewer-copy" title="Copy contents" aria-label="Copy contents"><i data-lucide="copy"></i></button>
|
|
707
666
|
<button class="file-viewer-btn hidden" id="file-viewer-copy-formatted" title="Copy Markdown formatting" aria-label="Copy Markdown formatting"><i data-lucide="clipboard-copy"></i></button>
|
|
708
667
|
</div>
|
|
@@ -2323,7 +2282,7 @@
|
|
|
2323
2282
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"></script>
|
|
2324
2283
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0/lib/addon-web-links.min.js"></script>
|
|
2325
2284
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@0/lib/addon-webgl.min.js"></script>
|
|
2326
|
-
<script type="module" src="app.js?v=
|
|
2285
|
+
<script type="module" src="app.js?v=20260829-terminal-dark1"></script>
|
|
2327
2286
|
<div id="pwa-install-modal" class="pwa-modal hidden">
|
|
2328
2287
|
<div class="pwa-modal-backdrop"></div>
|
|
2329
2288
|
<div class="pwa-modal-card">
|