openclacky 1.4.0 → 1.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/lib/clacky/agent/llm_caller.rb +3 -3
  4. data/lib/clacky/agent/session_serializer.rb +50 -9
  5. data/lib/clacky/agent.rb +4 -5
  6. data/lib/clacky/brand_config.rb +102 -10
  7. data/lib/clacky/client.rb +22 -16
  8. data/lib/clacky/default_extensions/ext-studio/agents/ext-developer/system_prompt.md +135 -84
  9. data/lib/clacky/default_extensions/ext-studio/api/handler.rb +144 -1
  10. data/lib/clacky/default_extensions/ext-studio/ext.yml +2 -4
  11. data/lib/clacky/default_extensions/ext-studio/panels/studio/view.js +412 -173
  12. data/lib/clacky/default_extensions/ext-studio/skills/ext-develop/SKILL.md +522 -0
  13. data/lib/clacky/extension/api_extension.rb +5 -6
  14. data/lib/clacky/extension/loader.rb +16 -2
  15. data/lib/clacky/extension/packager.rb +10 -1
  16. data/lib/clacky/extension/scaffold/templates/full/api/handler.rb.erb +16 -0
  17. data/lib/clacky/mcp/http_transport.rb +1 -1
  18. data/lib/clacky/platform_http_client.rb +9 -7
  19. data/lib/clacky/providers.rb +113 -5
  20. data/lib/clacky/server/http_server.rb +131 -38
  21. data/lib/clacky/server/session_registry.rb +9 -0
  22. data/lib/clacky/tools/grep.rb +6 -1
  23. data/lib/clacky/utils/environment_detector.rb +16 -9
  24. data/lib/clacky/utils/file_processor.rb +21 -24
  25. data/lib/clacky/utils/model_pricing.rb +85 -0
  26. data/lib/clacky/version.rb +1 -1
  27. data/lib/clacky/web/app.css +441 -48
  28. data/lib/clacky/web/app.js +29 -6
  29. data/lib/clacky/web/components/onboard.js +21 -7
  30. data/lib/clacky/web/features/backup/view.js +4 -3
  31. data/lib/clacky/web/features/extensions/store.js +56 -4
  32. data/lib/clacky/web/features/extensions/view.js +54 -24
  33. data/lib/clacky/web/features/mcp/view.js +5 -2
  34. data/lib/clacky/web/features/new-session/store.js +8 -4
  35. data/lib/clacky/web/features/version/view.js +5 -1
  36. data/lib/clacky/web/features/workspace/store.js +11 -0
  37. data/lib/clacky/web/features/workspace/view.js +10 -4
  38. data/lib/clacky/web/i18n.js +58 -36
  39. data/lib/clacky/web/index.html +74 -7
  40. data/lib/clacky/web/sessions.js +72 -15
  41. data/lib/clacky/web/settings.js +22 -3
  42. data/lib/clacky/web/theme.js +27 -58
  43. data/scripts/uninstall.sh +1 -1
  44. metadata +2 -5
  45. data/lib/clacky/default_extensions/ext-studio/skills/ext-debug/SKILL.md +0 -71
  46. data/lib/clacky/default_extensions/ext-studio/skills/ext-publish/SKILL.md +0 -73
  47. data/lib/clacky/default_extensions/ext-studio/skills/ext-scaffold/SKILL.md +0 -65
  48. data/lib/clacky/default_skills/extend-openclacky/SKILL.md +0 -106
@@ -152,6 +152,163 @@
152
152
  --shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.48), 0 4px 8px rgba(0, 0, 0, 0.32);
153
153
  }
154
154
 
155
+ /* ── Dim theme (mid-dark, softer than pure dark) ─────────────────────────
156
+ Design stance: desaturated dark grey, less eye strain than near-black.
157
+ Accent is the same run-time variable — not touched here. */
158
+ [data-theme="dim"] {
159
+ --color-bg-primary: #21262d; /* sidebar / shell — deep slate */
160
+ --color-bg-secondary: #2b3038; /* main content — slightly lighter */
161
+ --color-bg-tertiary: #2b3038;
162
+ --color-bg-hover: #333b44;
163
+ --color-bg-input: #2b3038;
164
+ --color-bg-card: #2b3038;
165
+ --color-bg-overlay: rgba(0, 0, 0, 0.52);
166
+
167
+ --color-border-primary: #363d47;
168
+ --color-border-secondary: #2e353f;
169
+ --color-border-strong: #4a5260;
170
+
171
+ --color-text-primary: #cdd9e5;
172
+ --color-text-secondary: #8b98a8;
173
+ --color-text-tertiary: #5d6875;
174
+ --color-text-muted: #4a535e;
175
+ --color-text-inverse: #ffffff;
176
+ --live: #3ed47e;
177
+
178
+ --color-accent-primary: #818cf8;
179
+ --color-accent-hover: #6366f1;
180
+ --color-accent-soft: color-mix(in srgb, var(--color-accent-primary) 14%, transparent);
181
+
182
+ --color-success: #34d399;
183
+ --color-success-bg: #0d2a22;
184
+ --color-success-border: #1a4033;
185
+
186
+ --color-error: #f87171;
187
+ --color-error-bg: #2d1818;
188
+ --color-error-border: #4d2020;
189
+
190
+ --color-warning: #fbbf24;
191
+ --color-warning-bg: #2d1f00;
192
+ --color-warning-border: #4d3200;
193
+
194
+ --color-info: #38bdf8;
195
+ --color-secondary: #34d399;
196
+ --color-accent-alt: #fbbf24;
197
+
198
+ --color-button-primary: var(--color-accent-primary);
199
+ --color-button-primary-hover: var(--color-accent-hover);
200
+ --color-button-primary-text: #ffffff;
201
+
202
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.28);
203
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.30), 0 1px 2px rgba(0, 0, 0, 0.22);
204
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35), 0 2px 4px rgba(0, 0, 0, 0.20);
205
+ --shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.44), 0 4px 8px rgba(0, 0, 0, 0.28);
206
+ }
207
+
208
+ /* ── Warm theme (warm off-white, sepia feel) ─────────────────────────────
209
+ Design stance: warm paper tones, easier on eyes than cold white. */
210
+ [data-theme="warm"] {
211
+ --color-bg-primary: #f5f0e8; /* warm parchment */
212
+ --color-bg-secondary: #fdf8f0; /* warmer white */
213
+ --color-bg-tertiary: #fdf8f0;
214
+ --color-bg-hover: #ece5d8;
215
+ --color-bg-input: #fdf8f0;
216
+ --color-bg-card: #fdf8f0;
217
+ --color-bg-overlay: rgba(30, 20, 10, 0.40);
218
+
219
+ --color-border-primary: #e0d6c4;
220
+ --color-border-secondary: #ede6d6;
221
+ --color-border-strong: #c8bba8;
222
+
223
+ --color-text-primary: #2c2416;
224
+ --color-text-secondary: #5c4e38;
225
+ --color-text-tertiary: #8a7a62;
226
+ --color-text-muted: #a89880;
227
+ --color-text-inverse: #ffffff;
228
+ --live: #2e9e5b;
229
+
230
+ --color-accent-primary: #4f46e5;
231
+ --color-accent-hover: #4338ca;
232
+ --color-accent-soft: color-mix(in srgb, var(--color-accent-primary) 10%, transparent);
233
+
234
+ --color-success: #10b981;
235
+ --color-success-bg: #f0fdf4;
236
+ --color-success-border: #bbf7d0;
237
+
238
+ --color-error: #ef4444;
239
+ --color-error-bg: #fef2f2;
240
+ --color-error-border: #fecaca;
241
+
242
+ --color-warning: #f59e0b;
243
+ --color-warning-bg: #fffbeb;
244
+ --color-warning-border: #fcd34d;
245
+
246
+ --color-info: #0ea5e9;
247
+ --color-secondary: #10b981;
248
+ --color-accent-alt: #f59e0b;
249
+
250
+ --color-button-primary: var(--color-accent-primary);
251
+ --color-button-primary-hover: var(--color-accent-hover);
252
+ --color-button-primary-text: #ffffff;
253
+
254
+ --shadow-xs: 0 1px 2px rgba(30, 20, 10, 0.05);
255
+ --shadow-sm: 0 1px 3px rgba(30, 20, 10, 0.07), 0 1px 2px rgba(30, 20, 10, 0.05);
256
+ --shadow-md: 0 4px 12px rgba(30, 20, 10, 0.09), 0 2px 4px rgba(30, 20, 10, 0.05);
257
+ --shadow-lg: 0 12px 28px rgba(30, 20, 10, 0.13), 0 4px 8px rgba(30, 20, 10, 0.07);
258
+ }
259
+
260
+ /* ── Blue-dark theme (VS Code / Apifox style blue-grey dark) ────────────
261
+ Design stance: blue-tinted dark surfaces, familiar dev-tool aesthetic. */
262
+ [data-theme="bluedark"] {
263
+ --color-bg-primary: #1e2228; /* sidebar / shell — blue-grey dark */
264
+ --color-bg-secondary: #252b33; /* main content — slightly lighter */
265
+ --color-bg-tertiary: #252b33;
266
+ --color-bg-hover: #2e3540;
267
+ --color-bg-input: #252b33;
268
+ --color-bg-card: #252b33;
269
+ --color-bg-overlay: rgba(0, 0, 0, 0.60);
270
+
271
+ --color-border-primary: #30373f;
272
+ --color-border-secondary: #282f38;
273
+ --color-border-strong: #44515f;
274
+
275
+ --color-text-primary: #d4dbe6;
276
+ --color-text-secondary: #8b97a8;
277
+ --color-text-tertiary: #5a6678;
278
+ --color-text-muted: #44505e;
279
+ --color-text-inverse: #ffffff;
280
+ --live: #3ed47e;
281
+
282
+ --color-accent-primary: #818cf8;
283
+ --color-accent-hover: #6366f1;
284
+ --color-accent-soft: color-mix(in srgb, var(--color-accent-primary) 14%, transparent);
285
+
286
+ --color-success: #34d399;
287
+ --color-success-bg: #0d2a22;
288
+ --color-success-border: #1a4033;
289
+
290
+ --color-error: #f87171;
291
+ --color-error-bg: #2d1818;
292
+ --color-error-border: #4d2020;
293
+
294
+ --color-warning: #fbbf24;
295
+ --color-warning-bg: #2d1f00;
296
+ --color-warning-border: #4d3200;
297
+
298
+ --color-info: #38bdf8;
299
+ --color-secondary: #34d399;
300
+ --color-accent-alt: #fbbf24;
301
+
302
+ --color-button-primary: var(--color-accent-primary);
303
+ --color-button-primary-hover: var(--color-accent-hover);
304
+ --color-button-primary-text: #ffffff;
305
+
306
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.40);
307
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.42), 0 1px 2px rgba(0, 0, 0, 0.32);
308
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.48), 0 2px 4px rgba(0, 0, 0, 0.30);
309
+ --shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.60), 0 4px 8px rgba(0, 0, 0, 0.40);
310
+ }
311
+
155
312
  /* ── Font Size Presets ────────────────────────────────────────────────────
156
313
  Controlled via html[data-font-size]: small / medium / large.
157
314
  Mechanism: change root font-size, which 1rem inherits from. Every CSS
@@ -240,6 +397,33 @@ html { font-size: 16px; }
240
397
  background-size: 200% 100%;
241
398
  animation: skel-shimmer 1.8s infinite linear;
242
399
  }
400
+ [data-theme="dim"] .skel {
401
+ background: linear-gradient(90deg,
402
+ #2e343c 25%,
403
+ #3c444e 50%,
404
+ #2e343c 75%
405
+ );
406
+ background-size: 200% 100%;
407
+ animation: skel-shimmer 1.8s infinite linear;
408
+ }
409
+ [data-theme="warm"] .skel {
410
+ background: linear-gradient(90deg,
411
+ #ece5d8 25%,
412
+ #ddd5c5 50%,
413
+ #ece5d8 75%
414
+ );
415
+ background-size: 200% 100%;
416
+ animation: skel-shimmer 1.8s infinite linear;
417
+ }
418
+ [data-theme="bluedark"] .skel {
419
+ background: linear-gradient(90deg,
420
+ #272e38 25%,
421
+ #333d4a 50%,
422
+ #272e38 75%
423
+ );
424
+ background-size: 200% 100%;
425
+ animation: skel-shimmer 1.8s infinite linear;
426
+ }
243
427
  /* Generic size helpers */
244
428
  .skel-icon { width: 2rem; height: 2rem; border-radius: 50%; flex-shrink: 0; }
245
429
  .skel-title { height: 1.25rem; width: 6rem; }
@@ -266,8 +450,10 @@ body {
266
450
  display: flex;
267
451
  overflow: hidden;
268
452
  transition: background-color 0.3s ease, color 0.3s ease;
453
+ padding: 0 8px 8px;
454
+ box-sizing: border-box;
269
455
  }
270
- #app { display: flex; flex-direction: column; width: 100%; height: 100vh; height: 100dvh; }
456
+ #app { display: flex; flex-direction: column; width: 100%; height: 100%; overflow: hidden; }
271
457
 
272
458
  /* ── Offline Banner ───────────────────────────────────────────────────── */
273
459
  #offline-banner {
@@ -291,6 +477,8 @@ body {
291
477
  display: flex;
292
478
  flex: 1;
293
479
  overflow: hidden;
480
+ border: 1px solid var(--color-border-primary);
481
+ border-radius: 8px;
294
482
  }
295
483
 
296
484
  /* ── Top Header ───────────────────────────────────────────────────────── */
@@ -298,7 +486,6 @@ body {
298
486
  height: 3rem;
299
487
  min-height: 3rem;
300
488
  background: var(--color-bg-primary);
301
- border-bottom: 1px solid var(--color-border-primary);
302
489
  display: flex;
303
490
  align-items: center;
304
491
  justify-content: space-between;
@@ -662,11 +849,15 @@ body {
662
849
  }
663
850
 
664
851
  /* ── New Session button ──────────────────────────────────────────────────── */
852
+ .btn-split-wrap {
853
+ display: flex;
854
+ align-items: stretch;
855
+ }
665
856
  .btn-split-main {
666
857
  height: 1.5rem;
667
- padding: 0 0.625rem;
858
+ padding: 0 0.6rem;
668
859
  border: none;
669
- border-radius: 6px;
860
+ border-radius: 6px 0 0 6px;
670
861
  background: var(--color-accent-primary);
671
862
  color: #fff;
672
863
  font-size: 0.75rem;
@@ -674,12 +865,85 @@ body {
674
865
  white-space: nowrap;
675
866
  line-height: 1;
676
867
  cursor: pointer;
868
+ display: flex;
869
+ align-items: center;
870
+ gap: 0.3rem;
677
871
  transition: background 0.15s, box-shadow 0.15s;
678
872
  }
679
873
  .btn-split-main:hover {
680
874
  background: var(--color-button-primary-hover);
681
875
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
682
876
  }
877
+ .btn-split-arrow {
878
+ display: flex;
879
+ align-items: center;
880
+ justify-content: center;
881
+ height: 1.5rem;
882
+ width: 1.375rem;
883
+ padding: 0;
884
+ border: none;
885
+ border-left: 1px solid rgba(255,255,255,0.2);
886
+ border-radius: 0 6px 6px 0;
887
+ background: var(--color-accent-primary);
888
+ color: #fff;
889
+ cursor: pointer;
890
+ transition: background 0.15s, box-shadow 0.15s;
891
+ flex-shrink: 0;
892
+ }
893
+ .btn-split-arrow:hover {
894
+ background: var(--color-button-primary-hover);
895
+ box-shadow: 0 2px 6px rgba(0,0,0,0.15);
896
+ }
897
+ .btn-split-dropdown {
898
+ position: relative;
899
+ display: flex;
900
+ }
901
+ .btn-split-menu {
902
+ display: none;
903
+ position: absolute;
904
+ top: calc(100% + 4px);
905
+ right: 0;
906
+ min-width: 9rem;
907
+ background: var(--color-bg-elevated, var(--color-bg-secondary));
908
+ border: 1px solid var(--color-border-secondary);
909
+ border-radius: 8px;
910
+ box-shadow: 0 4px 16px rgba(0,0,0,0.12);
911
+ padding: 0.25rem;
912
+ z-index: 200;
913
+ white-space: nowrap;
914
+ }
915
+ /* Bridge the 4px gap so hover doesn't break when moving to the menu */
916
+ .btn-split-menu::before {
917
+ content: "";
918
+ position: absolute;
919
+ top: -8px;
920
+ left: 0;
921
+ right: 0;
922
+ height: 8px;
923
+ }
924
+ .btn-split-dropdown:hover .btn-split-menu {
925
+ display: block;
926
+ }
927
+ .btn-split-menu-item {
928
+ display: flex;
929
+ align-items: center;
930
+ gap: 7px;
931
+ width: 100%;
932
+ padding: 0.375rem 0.75rem;
933
+ border: none;
934
+ border-radius: 5px;
935
+ background: transparent;
936
+ color: var(--color-text-secondary);
937
+ font-size: 0.8125rem;
938
+ font-family: var(--font-sans);
939
+ text-align: left;
940
+ cursor: pointer;
941
+ transition: background 0.12s, color 0.12s;
942
+ }
943
+ .btn-split-menu-item:hover {
944
+ background: var(--color-bg-hover);
945
+ color: var(--color-text-primary);
946
+ }
683
947
 
684
948
  /* ── Session source badge ────────────────────────────────────────────────── */
685
949
  /* Design: compact neutral chips — the visual weight is carried by the
@@ -2375,7 +2639,7 @@ body {
2375
2639
  flex-shrink: 0;
2376
2640
  margin-bottom: -9px;
2377
2641
  display: flex;
2378
- padding-inline: 12px;
2642
+ padding-inline: 24px;
2379
2643
  }
2380
2644
  .session-composer > * {
2381
2645
  justify-content: flex-start !important;
@@ -2466,7 +2730,7 @@ body {
2466
2730
  Designed to be quiet and low-contrast so it guides without distracting. */
2467
2731
  .chat-empty-hint {
2468
2732
  margin: auto; /* vertical + horizontal centering inside flex column */
2469
- max-width: 26.25rem;
2733
+ max-width: 30rem;
2470
2734
  padding: 1.5rem 1rem;
2471
2735
  display: flex;
2472
2736
  flex-direction: column;
@@ -2475,47 +2739,43 @@ body {
2475
2739
  color: var(--color-text-secondary);
2476
2740
  user-select: none;
2477
2741
  pointer-events: none; /* purely decorative — don't block clicks/scroll */
2478
- opacity: 0.85;
2479
2742
  }
2480
2743
  .chat-empty-hint .chat-empty-icon {
2481
- color: var(--color-text-tertiary);
2482
- margin-bottom: 0.875rem;
2483
- opacity: 0.55;
2744
+ display: flex;
2745
+ align-items: center;
2746
+ justify-content: center;
2747
+ width: 4rem;
2748
+ height: 4rem;
2749
+ margin-bottom: 1.125rem;
2750
+ border-radius: 50%;
2751
+ color: var(--color-accent-primary);
2752
+ background: color-mix(in srgb, var(--color-accent-primary) 10%, transparent);
2484
2753
  }
2485
2754
  .chat-empty-hint .chat-empty-title {
2486
2755
  color: var(--color-text-primary);
2487
- font-size: 0.9375rem;
2488
- font-weight: 600;
2489
- margin-bottom: 0.25rem;
2756
+ font-size: 1.25rem;
2757
+ font-weight: 500;
2758
+ line-height: 1.3;
2759
+ margin-bottom: 0.5rem;
2490
2760
  }
2491
2761
  .chat-empty-hint .chat-empty-subtitle {
2492
- color: var(--color-text-secondary);
2493
- font-size: 0.8125rem;
2494
- margin-bottom: 1.125rem;
2495
- opacity: 0.85;
2762
+ color: var(--color-text-tertiary);
2763
+ font-size: 0.875rem;
2764
+ line-height: 1.5;
2496
2765
  }
2497
2766
  .chat-empty-hint .chat-empty-tips {
2498
2767
  list-style: none;
2499
2768
  padding: 0;
2500
- margin: 0;
2769
+ margin: 1.5rem 0 0;
2501
2770
  display: flex;
2502
2771
  flex-direction: column;
2503
- gap: 0.375rem;
2504
- font-size: 0.75rem;
2772
+ gap: 0.5rem;
2773
+ font-size: 0.8125rem;
2505
2774
  color: var(--color-text-tertiary);
2506
2775
  }
2507
2776
  .chat-empty-hint .chat-empty-tips li {
2508
- position: relative;
2509
- padding-left: 0.875rem;
2510
2777
  line-height: 1.5;
2511
2778
  }
2512
- .chat-empty-hint .chat-empty-tips li::before {
2513
- content: "·";
2514
- position: absolute;
2515
- left: 0.25rem;
2516
- top: -1px;
2517
- opacity: 0.6;
2518
- }
2519
2779
 
2520
2780
  /* New message notification banner */
2521
2781
  .new-message-banner {
@@ -3234,7 +3494,7 @@ body {
3234
3494
  max-height: 18rem;
3235
3495
  overflow-y: auto;
3236
3496
  }
3237
- .tool-item-status { margin-left: auto; font-size: 0.6875rem; flex-shrink: 0; }
3497
+ .tool-item-status { font-size: 0.6875rem; flex-shrink: 0; }
3238
3498
  .tool-item-status.ok { color: var(--color-success); }
3239
3499
  .tool-item-status.err { color: var(--color-error); }
3240
3500
  .tool-item-status.running { color: var(--live); animation: pulse 1.6s ease-in-out infinite; }
@@ -3481,7 +3741,7 @@ body {
3481
3741
  opacity: 0.45;
3482
3742
  }
3483
3743
  [data-theme="dark"] #sib-id {
3484
- opacity: 0.6;
3744
+ opacity: 1;
3485
3745
  }
3486
3746
  [data-theme="dark"] #sib-dir {
3487
3747
  opacity: 0.85;
@@ -3493,7 +3753,7 @@ body {
3493
3753
  }
3494
3754
 
3495
3755
  #sib-id {
3496
- opacity: 0.45; /* tier 3 — glanceable */
3756
+ opacity: 1;
3497
3757
  font-size: 0.625rem;
3498
3758
  letter-spacing: 0.03em;
3499
3759
  flex-shrink: 0;
@@ -3508,7 +3768,6 @@ body {
3508
3768
  }
3509
3769
  .sib-id-clickable {
3510
3770
  cursor: pointer;
3511
- padding: 1px 0.25rem;
3512
3771
  border-radius: 3px;
3513
3772
  transition: all 0.15s ease;
3514
3773
  }
@@ -7199,7 +7458,7 @@ body {
7199
7458
  .extension-card:hover { border-color: var(--color-text-muted); }
7200
7459
  .extension-card-main {
7201
7460
  display: flex;
7202
- align-items: stretch;
7461
+ align-items: center;
7203
7462
  gap: 0.75rem;
7204
7463
  }
7205
7464
  .extension-emoji {
@@ -7348,6 +7607,38 @@ body {
7348
7607
  letter-spacing: 0.04em;
7349
7608
  margin: 0 0 0.75rem;
7350
7609
  }
7610
+ /* Readme rendered Markdown */
7611
+ .extension-readme-body {
7612
+ font-size: 0.875rem;
7613
+ line-height: 1.7;
7614
+ color: var(--color-text-primary);
7615
+ overflow-wrap: break-word;
7616
+ }
7617
+ .extension-readme-body h1,
7618
+ .extension-readme-body h2,
7619
+ .extension-readme-body h3 { margin: 1em 0 0.4em; font-weight: 600; }
7620
+ .extension-readme-body h1 { font-size: 1.2em; }
7621
+ .extension-readme-body h2 { font-size: 1.05em; }
7622
+ .extension-readme-body h3 { font-size: 0.95em; }
7623
+ .extension-readme-body p { margin: 0 0 0.75em; }
7624
+ .extension-readme-body ul,
7625
+ .extension-readme-body ol { padding-left: 1.4em; margin: 0 0 0.75em; }
7626
+ .extension-readme-body pre {
7627
+ background: var(--color-bg-secondary);
7628
+ border-radius: 6px;
7629
+ padding: 0.75em 1em;
7630
+ overflow-x: auto;
7631
+ font-size: 0.8em;
7632
+ }
7633
+ .extension-readme-body code {
7634
+ background: var(--color-bg-secondary);
7635
+ padding: 0.1em 0.3em;
7636
+ border-radius: 3px;
7637
+ font-size: 0.85em;
7638
+ }
7639
+ .extension-readme-body pre code { background: none; padding: 0; }
7640
+ .extension-readme-body a { color: var(--color-accent); }
7641
+ .extension-readme-body img { max-width: 100%; height: auto; border-radius: 6px; display: block; margin: 8px 0; }
7351
7642
  .extension-detail-section { margin-bottom: 0.875rem; }
7352
7643
  .extension-detail-section-title {
7353
7644
  font-size: 0.6875rem;
@@ -11432,12 +11723,11 @@ body.setup-mode[data-theme="dark"] {
11432
11723
  color: var(--color-danger, #c33);
11433
11724
  }
11434
11725
  .mcp-tools-header {
11435
- font-size: 0.6875rem;
11726
+ font-size: 0.8125rem;
11436
11727
  font-weight: 600;
11437
11728
  color: var(--color-text-secondary);
11438
11729
  margin-bottom: 0.5rem;
11439
- text-transform: uppercase;
11440
- letter-spacing: 0.05em;
11730
+ letter-spacing: 0.01em;
11441
11731
  }
11442
11732
  .mcp-tool-list {
11443
11733
  list-style: none;
@@ -11449,10 +11739,9 @@ body.setup-mode[data-theme="dark"] {
11449
11739
  }
11450
11740
  .mcp-tool-item {
11451
11741
  display: flex;
11452
- align-items: baseline;
11453
- gap: 0.625rem;
11454
- font-size: 0.8125rem;
11455
- padding: 0.4375rem 0;
11742
+ flex-direction: column;
11743
+ gap: 0.3rem;
11744
+ padding: 0.625rem 0;
11456
11745
  border-bottom: 1px solid var(--color-border-primary, var(--color-border));
11457
11746
  }
11458
11747
  .mcp-tool-item:last-child {
@@ -11460,18 +11749,15 @@ body.setup-mode[data-theme="dark"] {
11460
11749
  }
11461
11750
  .mcp-tool-name {
11462
11751
  font-family: var(--font-mono);
11463
- background: var(--color-bg-elevated, var(--color-bg-secondary));
11464
- padding: 0.125rem 0.4375rem;
11465
- border-radius: 4px;
11466
- font-size: 0.75rem;
11752
+ font-size: 0.8125rem;
11753
+ font-weight: 600;
11467
11754
  color: var(--color-text-primary, var(--color-text));
11468
- flex-shrink: 0;
11469
- border: 1px solid var(--color-border-primary, var(--color-border));
11470
11755
  }
11471
11756
  .mcp-tool-desc {
11472
11757
  color: var(--color-text-secondary);
11473
- flex: 1;
11474
11758
  line-height: 1.5;
11759
+ font-size: 0.8125rem;
11760
+ opacity: 0.6;
11475
11761
  }
11476
11762
 
11477
11763
  /* ── MCP CTA banner & action buttons ─────────────────────────────────── */
@@ -11670,6 +11956,113 @@ body.setup-mode[data-theme="dark"] {
11670
11956
  .swatch-sunrise-orange { background: #F59E0B; }
11671
11957
  .swatch-rose-violet { background: #8B5CF6; }
11672
11958
  .swatch-coral-red { background: #EF4444; }
11959
+ .swatch-sky-blue { background: #38BDF8; }
11960
+ .swatch-hot-pink { background: #EC4899; }
11961
+ .swatch-warm-brown { background: #92745A; }
11962
+ .swatch-slate-gray { background: #6B7280; }
11963
+
11964
+ /* ── Background Theme Cards ─────────────────────────────────────────── */
11965
+ .settings-bg-theme-cards {
11966
+ display: flex;
11967
+ flex-wrap: wrap;
11968
+ gap: 0.75rem;
11969
+ padding: 0.25rem 0;
11970
+ }
11971
+
11972
+ .settings-bg-theme-card {
11973
+ display: flex;
11974
+ flex-direction: column;
11975
+ align-items: center;
11976
+ gap: 0.375rem;
11977
+ cursor: pointer;
11978
+ border: none;
11979
+ background: transparent;
11980
+ padding: 0;
11981
+ flex-shrink: 0;
11982
+ }
11983
+
11984
+ /* The thumbnail preview box */
11985
+ .settings-bg-theme-card .bg-card-preview {
11986
+ width: 4.5rem;
11987
+ height: 3rem;
11988
+ border-radius: 0.5rem;
11989
+ border: 2px solid var(--color-border-primary);
11990
+ position: relative;
11991
+ overflow: hidden;
11992
+ transition: border-color 0.15s, transform 0.15s;
11993
+ display: flex;
11994
+ flex-direction: row;
11995
+ }
11996
+
11997
+ .settings-bg-theme-card:hover .bg-card-preview {
11998
+ border-color: var(--color-border-strong);
11999
+ transform: translateY(-1px);
12000
+ }
12001
+
12002
+ .settings-bg-theme-card.active .bg-card-preview {
12003
+ border-color: var(--color-accent-primary);
12004
+ box-shadow: 0 0 0 2px var(--color-accent-soft);
12005
+ }
12006
+
12007
+ /* Active checkmark badge */
12008
+ .settings-bg-theme-card.active .bg-card-preview::after {
12009
+ content: "✓";
12010
+ position: absolute;
12011
+ top: 0.2rem;
12012
+ right: 0.3rem;
12013
+ font-size: 0.625rem;
12014
+ font-weight: 700;
12015
+ color: white;
12016
+ background: var(--color-accent-primary);
12017
+ border-radius: 50%;
12018
+ width: 0.875rem;
12019
+ height: 0.875rem;
12020
+ display: flex;
12021
+ align-items: center;
12022
+ justify-content: center;
12023
+ line-height: 1;
12024
+ }
12025
+
12026
+ /* Sidebar strip (left 35%) */
12027
+ .settings-bg-theme-card .bg-card-sidebar {
12028
+ width: 35%;
12029
+ height: 100%;
12030
+ border-radius: 0;
12031
+ }
12032
+
12033
+ /* Main area (right 65%) */
12034
+ .settings-bg-theme-card .bg-card-main {
12035
+ width: 65%;
12036
+ height: 100%;
12037
+ }
12038
+
12039
+ /* Per-theme colors */
12040
+ .bg-theme-light .bg-card-sidebar { background: #f5f5f3; }
12041
+ .bg-theme-light .bg-card-main { background: #ffffff; }
12042
+
12043
+ .bg-theme-dark .bg-card-sidebar { background: #101114; }
12044
+ .bg-theme-dark .bg-card-main { background: #16181d; }
12045
+
12046
+ .bg-theme-dim .bg-card-sidebar { background: #21262d; }
12047
+ .bg-theme-dim .bg-card-main { background: #2b3038; }
12048
+
12049
+ .bg-theme-warm .bg-card-sidebar { background: #f5f0e8; }
12050
+ .bg-theme-warm .bg-card-main { background: #fdf8f0; }
12051
+
12052
+ .bg-theme-black .bg-card-sidebar { background: #1e2228; }
12053
+ .bg-theme-black .bg-card-main { background: #252b33; }
12054
+
12055
+ /* Label under card */
12056
+ .settings-bg-theme-card .bg-card-label {
12057
+ font-size: 0.6875rem;
12058
+ color: var(--color-text-secondary);
12059
+ white-space: nowrap;
12060
+ }
12061
+
12062
+ .settings-bg-theme-card.active .bg-card-label {
12063
+ color: var(--color-accent-primary);
12064
+ font-weight: 600;
12065
+ }
11673
12066
 
11674
12067
  /* ── Sessions List ───────────────────────────────────────────────────── */
11675
12068
  .billing-sessions-row {
@@ -436,7 +436,34 @@ const Modal = (() => {
436
436
  });
437
437
  }
438
438
 
439
- /** Show a text input prompt dialog. Returns a Promise<string|null>. */
439
+ /**
440
+ * Like confirm(), but shows an extra opt-in checkbox (unchecked by default).
441
+ * Resolves { ok, checked } so the caller can act on both the decision and
442
+ * the checkbox state.
443
+ */
444
+ function confirmWithCheckbox(message, checkboxLabel) {
445
+ return new Promise(resolve => {
446
+ const overlay = $("modal-overlay");
447
+ $("modal-message").textContent = message;
448
+ $("modal-skip-text").textContent = checkboxLabel;
449
+ $("modal-skip-cb").checked = false;
450
+ $("modal-skip-label").style.display = "flex";
451
+ if (overlay.parentNode !== document.body || overlay.nextSibling) {
452
+ document.body.appendChild(overlay);
453
+ }
454
+ overlay.style.display = "flex";
455
+
456
+ const cleanup = (ok) => {
457
+ overlay.style.display = "none";
458
+ $("modal-skip-label").style.display = "none";
459
+ $("modal-yes").onclick = null;
460
+ $("modal-no").onclick = null;
461
+ resolve({ ok, checked: ok && $("modal-skip-cb").checked });
462
+ };
463
+ $("modal-yes").onclick = () => cleanup(true);
464
+ $("modal-no").onclick = () => cleanup(false);
465
+ });
466
+ }
440
467
  function prompt(message, defaultValue = "") {
441
468
  return new Promise(resolve => {
442
469
  const overlay = $("prompt-modal-overlay");
@@ -530,7 +557,7 @@ const Modal = (() => {
530
557
  });
531
558
  }
532
559
 
533
- return { confirm, confirmOnce, prompt, rename };
560
+ return { confirm, confirmOnce, confirmWithCheckbox, prompt, rename };
534
561
  })();
535
562
 
536
563
  Clacky.Modal = Modal;
@@ -714,10 +741,6 @@ window.mobileCloseSidebar = _mobileCloseSidebar;
714
741
 
715
742
  // ── Theme / session-scoped message panel bindings ──────────────────────────
716
743
 
717
- // Theme toggle in header
718
- if ($("theme-toggle-header")) {
719
- $("theme-toggle-header").addEventListener("click", () => Theme.toggle());
720
- }
721
744
  // btn-delete-session, #messages scroll-to-top (load history), and btn-interrupt
722
745
  // moved to sessions.js (_initMessageHistory in Sessions.init()).
723
746