clay-server 2.5.0

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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +281 -0
  3. package/bin/cli.js +2385 -0
  4. package/lib/cli-sessions.js +270 -0
  5. package/lib/config.js +237 -0
  6. package/lib/daemon.js +489 -0
  7. package/lib/ipc.js +112 -0
  8. package/lib/notes.js +120 -0
  9. package/lib/pages.js +664 -0
  10. package/lib/project.js +1433 -0
  11. package/lib/public/app.js +2795 -0
  12. package/lib/public/apple-touch-icon-dark.png +0 -0
  13. package/lib/public/apple-touch-icon.png +0 -0
  14. package/lib/public/css/base.css +264 -0
  15. package/lib/public/css/diff.css +128 -0
  16. package/lib/public/css/filebrowser.css +1114 -0
  17. package/lib/public/css/highlight.css +144 -0
  18. package/lib/public/css/icon-strip.css +296 -0
  19. package/lib/public/css/input.css +573 -0
  20. package/lib/public/css/menus.css +856 -0
  21. package/lib/public/css/messages.css +1445 -0
  22. package/lib/public/css/mobile-nav.css +354 -0
  23. package/lib/public/css/overlays.css +697 -0
  24. package/lib/public/css/rewind.css +505 -0
  25. package/lib/public/css/server-settings.css +761 -0
  26. package/lib/public/css/sidebar.css +936 -0
  27. package/lib/public/css/sticky-notes.css +358 -0
  28. package/lib/public/css/title-bar.css +314 -0
  29. package/lib/public/favicon-dark.svg +1 -0
  30. package/lib/public/favicon.svg +1 -0
  31. package/lib/public/icon-192-dark.png +0 -0
  32. package/lib/public/icon-192.png +0 -0
  33. package/lib/public/icon-512-dark.png +0 -0
  34. package/lib/public/icon-512.png +0 -0
  35. package/lib/public/icon-mono.svg +1 -0
  36. package/lib/public/index.html +762 -0
  37. package/lib/public/manifest.json +27 -0
  38. package/lib/public/modules/diff.js +398 -0
  39. package/lib/public/modules/events.js +21 -0
  40. package/lib/public/modules/filebrowser.js +1411 -0
  41. package/lib/public/modules/fileicons.js +172 -0
  42. package/lib/public/modules/icons.js +54 -0
  43. package/lib/public/modules/input.js +584 -0
  44. package/lib/public/modules/markdown.js +356 -0
  45. package/lib/public/modules/notifications.js +649 -0
  46. package/lib/public/modules/qrcode.js +70 -0
  47. package/lib/public/modules/rewind.js +345 -0
  48. package/lib/public/modules/server-settings.js +510 -0
  49. package/lib/public/modules/sidebar.js +1083 -0
  50. package/lib/public/modules/state.js +3 -0
  51. package/lib/public/modules/sticky-notes.js +688 -0
  52. package/lib/public/modules/terminal.js +697 -0
  53. package/lib/public/modules/theme.js +738 -0
  54. package/lib/public/modules/tools.js +1608 -0
  55. package/lib/public/modules/utils.js +56 -0
  56. package/lib/public/style.css +15 -0
  57. package/lib/public/sw.js +75 -0
  58. package/lib/push.js +124 -0
  59. package/lib/sdk-bridge.js +989 -0
  60. package/lib/server.js +582 -0
  61. package/lib/sessions.js +424 -0
  62. package/lib/terminal-manager.js +187 -0
  63. package/lib/terminal.js +24 -0
  64. package/lib/themes/ayu-light.json +9 -0
  65. package/lib/themes/catppuccin-latte.json +9 -0
  66. package/lib/themes/catppuccin-mocha.json +9 -0
  67. package/lib/themes/clay-light.json +10 -0
  68. package/lib/themes/clay.json +10 -0
  69. package/lib/themes/dracula.json +9 -0
  70. package/lib/themes/everforest-light.json +9 -0
  71. package/lib/themes/everforest.json +9 -0
  72. package/lib/themes/github-light.json +9 -0
  73. package/lib/themes/gruvbox-dark.json +9 -0
  74. package/lib/themes/gruvbox-light.json +9 -0
  75. package/lib/themes/monokai.json +9 -0
  76. package/lib/themes/nord-light.json +9 -0
  77. package/lib/themes/nord.json +9 -0
  78. package/lib/themes/one-dark.json +9 -0
  79. package/lib/themes/one-light.json +9 -0
  80. package/lib/themes/rose-pine-dawn.json +9 -0
  81. package/lib/themes/rose-pine.json +9 -0
  82. package/lib/themes/solarized-dark.json +9 -0
  83. package/lib/themes/solarized-light.json +9 -0
  84. package/lib/themes/tokyo-night-light.json +9 -0
  85. package/lib/themes/tokyo-night.json +9 -0
  86. package/lib/updater.js +97 -0
  87. package/package.json +47 -0
@@ -0,0 +1,573 @@
1
+ /* --- Pasted content chips (in chat bubble) --- */
2
+ .bubble-pastes {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ gap: 6px;
6
+ margin-bottom: 8px;
7
+ }
8
+
9
+ .bubble-pastes:last-child { margin-bottom: 0; }
10
+
11
+ .bubble-paste {
12
+ display: inline-flex;
13
+ align-items: center;
14
+ gap: 8px;
15
+ background: rgba(var(--overlay-rgb), 0.06);
16
+ border: 1px solid var(--border);
17
+ border-radius: 10px;
18
+ padding: 8px 12px;
19
+ cursor: pointer;
20
+ transition: border-color 0.15s, background 0.15s;
21
+ max-width: 220px;
22
+ }
23
+
24
+ .bubble-paste:hover {
25
+ border-color: var(--text-dimmer);
26
+ background: rgba(var(--overlay-rgb), 0.1);
27
+ }
28
+
29
+ .bubble-paste-preview {
30
+ font-size: 12px;
31
+ color: var(--text-muted);
32
+ overflow: hidden;
33
+ text-overflow: ellipsis;
34
+ white-space: nowrap;
35
+ flex: 1;
36
+ min-width: 0;
37
+ }
38
+
39
+ .bubble-paste-label {
40
+ font-size: 10px;
41
+ font-weight: 700;
42
+ color: var(--text-dimmer);
43
+ letter-spacing: 0.05em;
44
+ flex-shrink: 0;
45
+ }
46
+
47
+ /* --- Pasted content chips (input preview) --- */
48
+ .pasted-chip {
49
+ display: inline-flex;
50
+ align-items: center;
51
+ gap: 6px;
52
+ background: var(--bg-alt);
53
+ border: 1px solid var(--border);
54
+ border-radius: 10px;
55
+ padding: 6px 10px;
56
+ font-size: 12px;
57
+ max-width: 200px;
58
+ }
59
+
60
+ .pasted-chip-preview {
61
+ color: var(--text-muted);
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ flex: 1;
66
+ min-width: 0;
67
+ }
68
+
69
+ .pasted-chip-label {
70
+ font-size: 10px;
71
+ font-weight: 700;
72
+ color: var(--text-dimmer);
73
+ letter-spacing: 0.05em;
74
+ flex-shrink: 0;
75
+ }
76
+
77
+ .pasted-chip-remove {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ width: 16px;
82
+ height: 16px;
83
+ border-radius: 50%;
84
+ border: none;
85
+ background: transparent;
86
+ color: var(--text-muted);
87
+ cursor: pointer;
88
+ padding: 0;
89
+ flex-shrink: 0;
90
+ }
91
+
92
+ .pasted-chip-remove .lucide { width: 12px; height: 12px; }
93
+ .pasted-chip-remove:hover { color: var(--text); background: rgba(var(--overlay-rgb), 0.1); }
94
+
95
+ /* --- Paste viewer modal --- */
96
+ #paste-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
97
+ #paste-modal.hidden { display: none; }
98
+
99
+ .paste-modal-dialog {
100
+ max-width: 620px;
101
+ width: 94%;
102
+ max-height: 80vh;
103
+ display: flex;
104
+ flex-direction: column;
105
+ padding: 0;
106
+ }
107
+
108
+ .paste-modal-header {
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: space-between;
112
+ padding: 16px 20px;
113
+ border-bottom: 1px solid var(--border-subtle);
114
+ flex-shrink: 0;
115
+ }
116
+
117
+ .paste-modal-title {
118
+ font-size: 15px;
119
+ font-weight: 600;
120
+ color: var(--text);
121
+ }
122
+
123
+ .paste-modal-close {
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ background: none;
128
+ border: none;
129
+ color: var(--text-muted);
130
+ cursor: pointer;
131
+ padding: 4px;
132
+ border-radius: 6px;
133
+ transition: color 0.15s, background 0.15s;
134
+ }
135
+
136
+ .paste-modal-close:hover { color: var(--text); background: rgba(var(--overlay-rgb), 0.06); }
137
+
138
+ .paste-modal-body {
139
+ margin: 0;
140
+ padding: 16px 20px;
141
+ font-family: "Roboto Mono", monospace;
142
+ font-size: 13px;
143
+ line-height: 1.55;
144
+ color: var(--text-secondary);
145
+ white-space: pre-wrap;
146
+ word-break: break-word;
147
+ overflow-y: auto;
148
+ min-height: 0;
149
+ }
150
+
151
+ /* --- Image preview bar --- */
152
+ #image-preview-bar {
153
+ display: none;
154
+ width: 100%;
155
+ padding: 6px 4px 4px 14px;
156
+ }
157
+
158
+ #image-preview-bar.visible {
159
+ display: flex;
160
+ flex-wrap: wrap;
161
+ gap: 6px;
162
+ }
163
+
164
+ .image-preview-thumb {
165
+ position: relative;
166
+ display: inline-block;
167
+ }
168
+
169
+ .image-preview-thumb img {
170
+ width: 48px;
171
+ height: 48px;
172
+ object-fit: cover;
173
+ border-radius: 8px;
174
+ border: 1px solid var(--border-subtle);
175
+ cursor: pointer;
176
+ }
177
+
178
+ .image-preview-remove {
179
+ position: absolute;
180
+ top: -6px;
181
+ right: -6px;
182
+ width: 20px;
183
+ height: 20px;
184
+ border-radius: 50%;
185
+ border: 1px solid var(--border);
186
+ background: var(--bg);
187
+ color: var(--text-muted);
188
+ cursor: pointer;
189
+ display: flex;
190
+ align-items: center;
191
+ justify-content: center;
192
+ padding: 0;
193
+ }
194
+
195
+ .image-preview-remove .lucide { width: 12px; height: 12px; }
196
+
197
+ .image-preview-remove:hover {
198
+ background: var(--error);
199
+ color: white;
200
+ border-color: var(--error);
201
+ }
202
+
203
+ /* ==========================================================================
204
+ Input Area — Claude-style unified container
205
+ ========================================================================== */
206
+
207
+ #input-area {
208
+ flex-shrink: 0;
209
+ padding: 8px 16px calc(var(--safe-bottom) + 8px);
210
+ }
211
+
212
+ #input-wrapper {
213
+ max-width: var(--content-width);
214
+ margin: 0 auto;
215
+ position: relative;
216
+ }
217
+
218
+ #input-row {
219
+ display: flex;
220
+ flex-direction: column;
221
+ background: var(--input-bg);
222
+ border: 1px solid var(--border);
223
+ border-radius: 24px;
224
+ padding: 6px;
225
+ transition: border-color 0.2s, box-shadow 0.2s;
226
+ }
227
+
228
+ #input-row:focus-within {
229
+ border-color: var(--text-dimmer);
230
+ box-shadow: 0 0 0 1px rgba(109, 104, 96, 0.15);
231
+ }
232
+
233
+ #input {
234
+ width: 100%;
235
+ background: transparent;
236
+ border: none;
237
+ color: var(--text);
238
+ font-size: 16px;
239
+ font-family: inherit;
240
+ line-height: 1.4;
241
+ padding: 8px 10px 4px;
242
+ resize: none;
243
+ outline: none;
244
+ min-height: 24px;
245
+ max-height: 120px;
246
+ overflow-y: auto;
247
+ box-sizing: border-box;
248
+ unicode-bidi: plaintext;
249
+ text-align: start;
250
+ }
251
+
252
+ #input::placeholder {
253
+ color: var(--text-muted);
254
+ }
255
+
256
+ /* --- Bottom toolbar (attach left, model+send right) --- */
257
+ #input-bottom {
258
+ display: flex;
259
+ align-items: center;
260
+ justify-content: space-between;
261
+ }
262
+
263
+ #input-bottom-right {
264
+ display: flex;
265
+ align-items: center;
266
+ gap: 4px;
267
+ }
268
+
269
+ /* --- Attach button & menu --- */
270
+ #attach-wrap {
271
+ position: relative;
272
+ flex-shrink: 0;
273
+ }
274
+
275
+ #attach-btn {
276
+ width: 36px;
277
+ height: 36px;
278
+ border-radius: 50%;
279
+ border: none;
280
+ background: transparent;
281
+ color: var(--text-muted);
282
+ cursor: pointer;
283
+ display: flex;
284
+ align-items: center;
285
+ justify-content: center;
286
+ transition: background 0.15s, color 0.15s;
287
+ touch-action: manipulation;
288
+ }
289
+
290
+ #attach-btn .lucide { width: 20px; height: 20px; }
291
+ #attach-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
292
+
293
+ #attach-menu {
294
+ position: absolute;
295
+ bottom: calc(100% + 8px);
296
+ left: 0;
297
+ min-width: 170px;
298
+ background: var(--bg-alt);
299
+ border: 1px solid var(--border);
300
+ border-radius: 14px;
301
+ box-shadow: 0 -4px 24px rgba(var(--shadow-rgb), 0.4);
302
+ z-index: 10;
303
+ overflow: hidden;
304
+ }
305
+
306
+ #attach-menu.hidden { display: none; }
307
+
308
+ .attach-menu-item {
309
+ display: flex;
310
+ align-items: center;
311
+ gap: 10px;
312
+ width: 100%;
313
+ padding: 12px 16px;
314
+ border: none;
315
+ background: none;
316
+ color: var(--text-secondary);
317
+ font-family: inherit;
318
+ font-size: 14px;
319
+ cursor: pointer;
320
+ transition: background 0.15s, color 0.15s;
321
+ }
322
+
323
+ .attach-menu-item:not(:last-child) {
324
+ border-bottom: 1px solid var(--border-subtle);
325
+ }
326
+
327
+ .attach-menu-item:hover {
328
+ background: rgba(var(--overlay-rgb), 0.05);
329
+ color: var(--text);
330
+ }
331
+
332
+ .attach-menu-item .lucide { width: 18px; height: 18px; flex-shrink: 0; }
333
+
334
+ #send-btn {
335
+ flex-shrink: 0;
336
+ width: 36px;
337
+ height: 36px;
338
+ border-radius: 50%;
339
+ border: none;
340
+ background: var(--accent);
341
+ color: #fff;
342
+ cursor: pointer;
343
+ display: flex;
344
+ align-items: center;
345
+ justify-content: center;
346
+ transition: background 0.15s, opacity 0.15s;
347
+ touch-action: manipulation;
348
+ }
349
+
350
+ #send-btn .lucide {
351
+ width: 18px;
352
+ height: 18px;
353
+ }
354
+
355
+ #send-btn:hover:not(:disabled) {
356
+ background: var(--accent-hover);
357
+ }
358
+
359
+ #send-btn:disabled {
360
+ opacity: 0.25;
361
+ cursor: default;
362
+ }
363
+
364
+ #send-btn:active:not(:disabled) {
365
+ opacity: 0.7;
366
+ }
367
+
368
+ /* ==========================================================================
369
+ Slash Command Autocomplete
370
+ ========================================================================== */
371
+
372
+ #slash-menu {
373
+ display: none;
374
+ position: absolute;
375
+ bottom: 100%;
376
+ left: 0;
377
+ right: 0;
378
+ max-height: 240px;
379
+ overflow-y: auto;
380
+ background: var(--bg-alt);
381
+ border: 1px solid var(--border);
382
+ border-radius: 14px;
383
+ margin-bottom: 8px;
384
+ box-shadow: 0 -4px 24px rgba(var(--shadow-rgb), 0.4);
385
+ z-index: 10;
386
+ }
387
+
388
+ #slash-menu.visible { display: block; }
389
+
390
+ .slash-item {
391
+ display: flex;
392
+ align-items: center;
393
+ padding: 12px 16px;
394
+ cursor: pointer;
395
+ gap: 12px;
396
+ border-bottom: 1px solid var(--border-subtle);
397
+ }
398
+
399
+ .slash-item:last-child { border-bottom: none; }
400
+
401
+ .slash-item:hover,
402
+ .slash-item.active {
403
+ background: rgba(var(--overlay-rgb), 0.05);
404
+ }
405
+
406
+ .slash-item .slash-cmd {
407
+ color: var(--accent);
408
+ font-weight: 600;
409
+ font-size: 14px;
410
+ font-family: "Roboto Mono", monospace;
411
+ }
412
+
413
+ .slash-item .slash-desc {
414
+ color: var(--text-muted);
415
+ font-size: 13px;
416
+ }
417
+
418
+ /* ==========================================================================
419
+ Prompt Suggestion Chips
420
+ ========================================================================== */
421
+
422
+ #suggestion-chips {
423
+ display: flex;
424
+ flex-wrap: wrap;
425
+ gap: 6px;
426
+ padding: 0 0 8px;
427
+ }
428
+
429
+ #suggestion-chips.hidden { display: none; }
430
+
431
+ .suggestion-chip {
432
+ display: inline-flex;
433
+ align-items: center;
434
+ gap: 5px;
435
+ padding: 7px 14px;
436
+ border-radius: 16px;
437
+ border: 1px solid var(--border);
438
+ background: var(--bg-alt);
439
+ color: var(--text-secondary);
440
+ font-size: 13px;
441
+ font-family: inherit;
442
+ cursor: pointer;
443
+ transition: background 0.15s, border-color 0.15s, color 0.15s;
444
+ text-align: left;
445
+ max-width: 100%;
446
+ line-height: 1.3;
447
+ }
448
+
449
+ .suggestion-chip:hover {
450
+ border-color: var(--accent);
451
+ background: var(--accent-bg);
452
+ color: var(--accent);
453
+ }
454
+
455
+ .suggestion-chip .lucide {
456
+ width: 14px;
457
+ height: 14px;
458
+ flex-shrink: 0;
459
+ color: var(--accent);
460
+ }
461
+
462
+ /* ==========================================================================
463
+ Animations
464
+ ========================================================================== */
465
+
466
+ @keyframes pulse {
467
+ 0%, 100% { opacity: 1; }
468
+ 50% { opacity: 0.3; }
469
+ }
470
+
471
+ @keyframes spin {
472
+ to { transform: rotate(360deg); }
473
+ }
474
+
475
+ @keyframes sparkle {
476
+ 0%, 100% { opacity: 1; transform: scale(1); }
477
+ 50% { opacity: 0.5; transform: scale(0.85); }
478
+ }
479
+
480
+ /* ==========================================================================
481
+ Mobile Responsive
482
+ ========================================================================== */
483
+
484
+ @media (max-width: 768px) {
485
+ #main-area {
486
+ overflow: visible;
487
+ border-radius: 0;
488
+ border: none;
489
+ }
490
+
491
+ #sidebar {
492
+ position: fixed;
493
+ left: 0;
494
+ top: 0;
495
+ bottom: 0;
496
+ z-index: 1000;
497
+ transform: translateX(-100%);
498
+ transition: transform 0.25s ease;
499
+ width: 240px;
500
+ background: var(--sidebar-bg);
501
+ }
502
+
503
+ #sidebar.open {
504
+ transform: translateX(0);
505
+ }
506
+
507
+ #sidebar-overlay {
508
+ z-index: 999;
509
+ }
510
+
511
+ /* On mobile, sidebar-collapsed should not affect sidebar (hamburger controls it) */
512
+ #layout.sidebar-collapsed #sidebar {
513
+ width: 240px;
514
+ border-right: 1px solid var(--border-subtle);
515
+ }
516
+
517
+ #hamburger-btn,
518
+ #sidebar-toggle-btn,
519
+ #sidebar-expand-btn,
520
+ #layout.sidebar-collapsed #sidebar-expand-btn {
521
+ display: none;
522
+ }
523
+
524
+ /* Hide sidebar tools & title bar status icons — redundant with tab bar */
525
+ #sidebar-tools,
526
+ .title-bar-main .status {
527
+ display: none;
528
+ }
529
+
530
+ .msg-user .bubble {
531
+ max-width: 90%;
532
+ }
533
+
534
+ #input-row {
535
+ border-radius: 20px;
536
+ }
537
+
538
+ /* Offset for mobile tab bar (56px) */
539
+ #input-area {
540
+ padding-bottom: calc(var(--safe-bottom) + 56px + 8px);
541
+ }
542
+ }
543
+
544
+ /* ==========================================================================
545
+ Progressive History Loading
546
+ ========================================================================== */
547
+
548
+ .history-sentinel {
549
+ text-align: center;
550
+ padding: 16px 0 8px;
551
+ }
552
+
553
+ .load-more-btn {
554
+ background: none;
555
+ border: 1px solid var(--border-subtle);
556
+ border-radius: 8px;
557
+ color: var(--text-secondary);
558
+ padding: 6px 16px;
559
+ font-size: 12px;
560
+ font-family: inherit;
561
+ cursor: pointer;
562
+ transition: border-color 0.15s, color 0.15s;
563
+ }
564
+
565
+ .load-more-btn:hover {
566
+ border-color: var(--text-secondary);
567
+ color: var(--text-primary, var(--text));
568
+ }
569
+
570
+ .load-more-btn.loading {
571
+ pointer-events: none;
572
+ opacity: 0.5;
573
+ }