openclacky 1.0.0 → 1.0.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/README.md +87 -53
  4. data/lib/clacky/agent/cost_tracker.rb +19 -2
  5. data/lib/clacky/agent/llm_caller.rb +218 -0
  6. data/lib/clacky/agent/message_compressor_helper.rb +32 -2
  7. data/lib/clacky/agent.rb +54 -22
  8. data/lib/clacky/client.rb +44 -5
  9. data/lib/clacky/default_parsers/pdf_parser.rb +58 -17
  10. data/lib/clacky/default_parsers/pdf_parser_ocr.py +103 -0
  11. data/lib/clacky/default_parsers/pdf_parser_plumber.py +62 -0
  12. data/lib/clacky/default_skills/deploy/SKILL.md +201 -77
  13. data/lib/clacky/default_skills/new/SKILL.md +3 -114
  14. data/lib/clacky/default_skills/onboard/SKILL.md +349 -133
  15. data/lib/clacky/default_skills/onboard/scripts/import_external_skills.rb +371 -0
  16. data/lib/clacky/default_skills/onboard/scripts/install_builtin_skills.rb +175 -0
  17. data/lib/clacky/default_skills/skill-add/scripts/install_from_zip.rb +59 -26
  18. data/lib/clacky/message_format/anthropic.rb +72 -8
  19. data/lib/clacky/message_format/bedrock.rb +6 -3
  20. data/lib/clacky/providers.rb +146 -3
  21. data/lib/clacky/server/channel/adapters/feishu/adapter.rb +14 -0
  22. data/lib/clacky/server/channel/adapters/feishu/bot.rb +10 -0
  23. data/lib/clacky/server/channel/adapters/feishu/message_parser.rb +1 -0
  24. data/lib/clacky/server/channel/channel_manager.rb +12 -4
  25. data/lib/clacky/server/channel/channel_ui_controller.rb +8 -2
  26. data/lib/clacky/server/http_server.rb +746 -13
  27. data/lib/clacky/server/session_registry.rb +55 -24
  28. data/lib/clacky/skill.rb +10 -9
  29. data/lib/clacky/skill_loader.rb +23 -11
  30. data/lib/clacky/tools/file_reader.rb +232 -127
  31. data/lib/clacky/tools/security.rb +42 -64
  32. data/lib/clacky/tools/terminal/persistent_session.rb +15 -4
  33. data/lib/clacky/tools/terminal/safe_rm.sh +106 -0
  34. data/lib/clacky/tools/terminal/session_manager.rb +8 -3
  35. data/lib/clacky/tools/terminal.rb +263 -16
  36. data/lib/clacky/ui2/layout_manager.rb +8 -1
  37. data/lib/clacky/ui2/output_buffer.rb +83 -23
  38. data/lib/clacky/ui2/ui_controller.rb +74 -7
  39. data/lib/clacky/utils/file_processor.rb +14 -40
  40. data/lib/clacky/utils/model_pricing.rb +215 -0
  41. data/lib/clacky/utils/parser_manager.rb +70 -6
  42. data/lib/clacky/utils/string_matcher.rb +23 -1
  43. data/lib/clacky/version.rb +1 -1
  44. data/lib/clacky/web/app.css +673 -9
  45. data/lib/clacky/web/app.js +40 -1608
  46. data/lib/clacky/web/i18n.js +209 -0
  47. data/lib/clacky/web/index.html +166 -2
  48. data/lib/clacky/web/onboard.js +77 -1
  49. data/lib/clacky/web/profile.js +442 -0
  50. data/lib/clacky/web/sessions.js +1034 -2
  51. data/lib/clacky/web/settings.js +127 -6
  52. data/lib/clacky/web/sidebar.js +39 -0
  53. data/lib/clacky/web/skills.js +460 -0
  54. data/lib/clacky/web/trash.js +343 -0
  55. data/lib/clacky/web/ws-dispatcher.js +255 -0
  56. data/lib/clacky.rb +5 -3
  57. metadata +16 -17
  58. data/lib/clacky/clacky_auth_client.rb +0 -152
  59. data/lib/clacky/clacky_cloud_config.rb +0 -123
  60. data/lib/clacky/cloud_project_client.rb +0 -169
  61. data/lib/clacky/default_skills/deploy/scripts/rails_deploy.rb +0 -1377
  62. data/lib/clacky/default_skills/deploy/tools/check_health.rb +0 -116
  63. data/lib/clacky/default_skills/deploy/tools/create_database_service.rb +0 -341
  64. data/lib/clacky/default_skills/deploy/tools/execute_deployment.rb +0 -99
  65. data/lib/clacky/default_skills/deploy/tools/fetch_runtime_logs.rb +0 -77
  66. data/lib/clacky/default_skills/deploy/tools/list_services.rb +0 -67
  67. data/lib/clacky/default_skills/deploy/tools/report_deploy_status.rb +0 -67
  68. data/lib/clacky/default_skills/deploy/tools/set_deploy_variables.rb +0 -189
  69. data/lib/clacky/default_skills/new/scripts/cloud_project_init.sh +0 -74
  70. data/lib/clacky/deploy_api_client.rb +0 -484
@@ -78,6 +78,9 @@
78
78
  --shadow-md: 0 4px 12px rgba(15, 18, 28, 0.08), 0 2px 4px rgba(15, 18, 28, 0.04);
79
79
  --shadow-lg: 0 12px 28px rgba(15, 18, 28, 0.12), 0 4px 8px rgba(15, 18, 28, 0.06);
80
80
 
81
+ /* Layout — shared dimensions */
82
+ --footer-height: 56px;
83
+
81
84
  /* Transitions — unified timing */
82
85
  --transition-fast: 120ms ease;
83
86
  --transition-base: 160ms ease;
@@ -2079,7 +2082,6 @@ body {
2079
2082
  padding: 4px 14px;
2080
2083
  background: var(--color-bg-primary);
2081
2084
  border-top: 1px solid var(--color-border-secondary);
2082
- border-bottom: 1px solid var(--color-border-secondary);
2083
2085
  font-size: 11px;
2084
2086
  color: var(--color-text-secondary);
2085
2087
  font-family: var(--font-mono, monospace);
@@ -2437,6 +2439,9 @@ body {
2437
2439
  border-top: 1px solid var(--color-border-primary);
2438
2440
  background: var(--color-bg-secondary);
2439
2441
  flex-shrink: 0;
2442
+ min-height: var(--footer-height);
2443
+ display: flex;
2444
+ flex-direction: column;
2440
2445
  }
2441
2446
 
2442
2447
  /* Hide top border when skill autocomplete is visible */
@@ -2762,9 +2767,11 @@ body {
2762
2767
 
2763
2768
  /* ── Input bar ───────────────────────────────────────────────────────────── */
2764
2769
  #input-bar {
2765
- padding: 13.5px 16px;
2770
+ margin-top: auto;
2771
+ margin-bottom: auto;
2772
+ padding: 0 16px;
2766
2773
  display: flex;
2767
- gap: 8px;
2774
+ gap: 6px;
2768
2775
  align-items: center;
2769
2776
  background: var(--color-bg-secondary);
2770
2777
  }
@@ -2775,7 +2782,9 @@ body {
2775
2782
  background: transparent;
2776
2783
  color: var(--color-text-secondary);
2777
2784
  cursor: pointer;
2778
- padding: 6px;
2785
+ width: 28px;
2786
+ height: 28px;
2787
+ padding: 0;
2779
2788
  line-height: 1;
2780
2789
  flex-shrink: 0;
2781
2790
  display: flex;
@@ -2789,17 +2798,21 @@ body {
2789
2798
  background: transparent;
2790
2799
  color: var(--color-text-secondary);
2791
2800
  cursor: pointer;
2792
- padding: 4px 7px;
2801
+ width: 28px;
2802
+ height: 28px;
2803
+ padding: 0;
2793
2804
  line-height: 1;
2794
2805
  flex-shrink: 0;
2795
2806
  display: flex;
2796
2807
  align-items: center;
2797
2808
  justify-content: center;
2798
2809
  border-radius: 6px;
2799
- font-size: 15px;
2800
2810
  font-weight: 600;
2801
2811
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
2802
2812
  }
2813
+ #btn-slash span {
2814
+ font-size: 18px;
2815
+ }
2803
2816
  #btn-slash:hover { color: var(--color-accent-primary); background: var(--color-border-secondary); }
2804
2817
  #btn-slash.active { color: var(--color-accent-primary); }
2805
2818
  #user-input {
@@ -2822,24 +2835,32 @@ body {
2822
2835
  #btn-send, #btn-interrupt {
2823
2836
  border: none;
2824
2837
  border-radius: 6px;
2825
- padding: 8px 16px;
2838
+ padding: 0 16px;
2839
+ height: 32px;
2826
2840
  font-size: 13px;
2827
2841
  cursor: pointer;
2828
2842
  white-space: nowrap;
2829
2843
  flex-shrink: 0;
2844
+ display: flex;
2845
+ align-items: center;
2846
+ justify-content: center;
2830
2847
  }
2831
2848
  #btn-send { background: var(--color-button-primary); color: #fff; }
2832
2849
  #btn-send:hover { background: var(--color-button-primary-hover); }
2833
2850
  [data-theme="dark"] #btn-send { background: #2563eb; }
2834
2851
  [data-theme="dark"] #btn-send:hover { background: #1d4ed8; }
2835
2852
  #btn-send:disabled { background: var(--color-border-primary); color: var(--color-text-secondary); cursor: not-allowed; }
2836
- #btn-interrupt { background: var(--color-error); color: #fff; font-size: 16px; line-height: 1; padding: 8px 16px; }
2853
+ #btn-interrupt { background: var(--color-error); color: #fff; }
2854
+ #btn-interrupt::after { content: ''; display: block; width: 10px; height: 10px; background: #fff; border-radius: 2px; }
2837
2855
  #btn-interrupt:hover{ background: var(--color-error); opacity: 0.85; }
2838
2856
 
2839
2857
  /* ── Sidebar footer ──────────────────────────────────────────────────────── */
2840
2858
  #sidebar-footer {
2841
2859
  border-top: 1px solid var(--color-border-primary);
2842
- padding: 14px 8px;
2860
+ min-height: var(--footer-height);
2861
+ display: flex;
2862
+ align-items: center;
2863
+ padding: 0 8px;
2843
2864
  flex-shrink: 0;
2844
2865
  }
2845
2866
  .sidebar-nav-btn {
@@ -3263,6 +3284,74 @@ body {
3263
3284
  font-style: italic;
3264
3285
  }
3265
3286
 
3287
+ /* Base URL combobox — mirrors model-name-combobox shape; differs only in
3288
+ showing a two-line option (label + URL) so users can distinguish
3289
+ regional/billing-plan variants under one provider. */
3290
+ .base-url-combobox {
3291
+ position: relative;
3292
+ display: flex;
3293
+ gap: 0;
3294
+ }
3295
+ .base-url-combobox .base-url-input {
3296
+ flex: 1;
3297
+ border-top-right-radius: 0;
3298
+ border-bottom-right-radius: 0;
3299
+ border-right: none;
3300
+ }
3301
+ .base-url-combobox .base-url-dropdown-btn {
3302
+ background: var(--color-bg-primary);
3303
+ border: 1px solid var(--color-border-primary);
3304
+ border-top-right-radius: 6px;
3305
+ border-bottom-right-radius: 6px;
3306
+ color: var(--color-text-secondary);
3307
+ padding: 0 8px;
3308
+ cursor: pointer;
3309
+ flex-shrink: 0;
3310
+ display: flex;
3311
+ align-items: center;
3312
+ justify-content: center;
3313
+ transition: all 0.15s ease;
3314
+ }
3315
+ .base-url-combobox .base-url-dropdown-btn:hover {
3316
+ background: var(--color-bg-hover);
3317
+ color: var(--color-text-primary);
3318
+ }
3319
+ .base-url-dropdown {
3320
+ position: absolute;
3321
+ top: calc(100% + 4px);
3322
+ left: 0;
3323
+ right: 0;
3324
+ background: var(--color-bg-secondary);
3325
+ border: 1px solid var(--color-border-primary);
3326
+ border-radius: 8px;
3327
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
3328
+ max-height: 280px;
3329
+ overflow-y: auto;
3330
+ z-index: 1000;
3331
+ }
3332
+ .base-url-dropdown-option {
3333
+ padding: 8px 12px;
3334
+ cursor: pointer;
3335
+ transition: background-color 0.15s ease;
3336
+ }
3337
+ .base-url-dropdown-option:hover {
3338
+ background: var(--color-bg-hover);
3339
+ }
3340
+ .base-url-dropdown-label {
3341
+ font-size: 13px;
3342
+ color: var(--color-text-primary);
3343
+ font-weight: 500;
3344
+ }
3345
+ .base-url-dropdown-option:hover .base-url-dropdown-label {
3346
+ color: var(--color-accent-primary);
3347
+ }
3348
+ .base-url-dropdown-url {
3349
+ font-size: 11px;
3350
+ color: var(--color-text-secondary);
3351
+ font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Courier New', monospace;
3352
+ margin-top: 2px;
3353
+ }
3354
+
3266
3355
  /* Model card footer */
3267
3356
  .model-card-footer {
3268
3357
  display: flex;
@@ -5748,6 +5837,7 @@ body.setup-mode[data-theme="dark"] {
5748
5837
  border-radius: 6px;
5749
5838
  overflow: hidden;
5750
5839
  transition: background .15s;
5840
+ width: 100%;
5751
5841
  }
5752
5842
  .sidebar-nav-row:hover {
5753
5843
  background: var(--color-bg-hover);
@@ -6086,6 +6176,394 @@ body.setup-mode[data-theme="dark"] {
6086
6176
 
6087
6177
 
6088
6178
 
6179
+ /* ── Profile / My Data Panel ───────────────────────────────────────────────
6180
+ *
6181
+ * Assistant Memory is a 3-tab read-only window:
6182
+ * 🧬 Soul – SOUL.md + "Have the assistant curate this" → /onboard scope:soul
6183
+ * 👤 User – USER.md + "Have the assistant update this" → /onboard scope:user
6184
+ * 🧠 Memories – cards with Curate + Delete (→ File Recall) → /onboard path:<abs>
6185
+ *
6186
+ * All mutations go through agent sessions; there are no inline editors.
6187
+ * All colours use design tokens from :root / [data-theme="dark"] above —
6188
+ * no hardcoded fallbacks so the panel looks correct in both light and dark.
6189
+ * ═════════════════════════════════════════════════════════════════════════ */
6190
+
6191
+ #profile-panel {
6192
+ flex: 1;
6193
+ display: flex;
6194
+ flex-direction: column;
6195
+ overflow: hidden;
6196
+ min-width: 0;
6197
+ }
6198
+
6199
+ #profile-body {
6200
+ flex: 1;
6201
+ overflow-y: auto;
6202
+ padding: 28px 36px;
6203
+ display: flex;
6204
+ flex-direction: column;
6205
+ gap: 4px;
6206
+ background: var(--color-bg-secondary);
6207
+ }
6208
+
6209
+ /* ── Tab bar ─────────────────────────────────────────────────────────── */
6210
+ .profile-tabs {
6211
+ display: flex;
6212
+ gap: 4px;
6213
+ margin: 18px 0 16px;
6214
+ border-bottom: 1px solid var(--color-border-primary);
6215
+ }
6216
+
6217
+ .profile-tab {
6218
+ padding: 10px 18px;
6219
+ border: none;
6220
+ background: transparent;
6221
+ color: var(--color-text-muted);
6222
+ font-size: 13px;
6223
+ font-weight: 500;
6224
+ cursor: pointer;
6225
+ border-bottom: 2px solid transparent;
6226
+ margin-bottom: -1px;
6227
+ transition: color 0.15s, border-color 0.15s;
6228
+ }
6229
+
6230
+ .profile-tab:hover:not(.active) {
6231
+ color: var(--color-text-primary);
6232
+ }
6233
+
6234
+ .profile-tab.active {
6235
+ color: var(--color-text-primary);
6236
+ border-bottom-color: var(--color-accent-primary);
6237
+ }
6238
+
6239
+ /* ── Tab panel ───────────────────────────────────────────────────────── */
6240
+ .profile-tab-panel {
6241
+ padding: 14px 2px 20px;
6242
+ }
6243
+
6244
+ /* ── Section heading (shared across panels) ──────────────────────────── */
6245
+ .profile-section-head {
6246
+ display: flex;
6247
+ justify-content: space-between;
6248
+ align-items: center;
6249
+ gap: 12px;
6250
+ margin-bottom: 14px;
6251
+ padding-bottom: 10px;
6252
+ border-bottom: 1px solid var(--color-border-primary);
6253
+ }
6254
+
6255
+ .profile-section-title {
6256
+ font-size: 15px;
6257
+ font-weight: 600;
6258
+ color: var(--color-text-primary);
6259
+ margin: 0;
6260
+ }
6261
+
6262
+ .profile-section-meta {
6263
+ display: flex;
6264
+ align-items: center;
6265
+ gap: 10px;
6266
+ font-size: 11px;
6267
+ color: var(--color-text-muted);
6268
+ }
6269
+
6270
+ .profile-section-hint {
6271
+ font-size: 12px;
6272
+ color: var(--color-text-muted);
6273
+ margin: 0 0 12px 0;
6274
+ }
6275
+
6276
+ .profile-path {
6277
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
6278
+ font-size: 11px;
6279
+ overflow: hidden;
6280
+ text-overflow: ellipsis;
6281
+ white-space: nowrap;
6282
+ max-width: 320px;
6283
+ }
6284
+
6285
+ .profile-status {
6286
+ font-size: 11px;
6287
+ padding: 2px 8px;
6288
+ border-radius: 10px;
6289
+ flex-shrink: 0;
6290
+ }
6291
+
6292
+ .profile-status-default {
6293
+ background: var(--color-bg-hover);
6294
+ color: var(--color-text-muted);
6295
+ }
6296
+
6297
+ .profile-status-custom {
6298
+ background: var(--color-success-bg);
6299
+ color: var(--color-success);
6300
+ }
6301
+
6302
+ .profile-empty {
6303
+ padding: 14px 0;
6304
+ text-align: center;
6305
+ color: var(--color-text-muted);
6306
+ font-size: 12px;
6307
+ font-style: italic;
6308
+ }
6309
+
6310
+ /* ── Per-tab curate footer (SOUL / USER) ─────────────────────────────── */
6311
+ .profile-pane-footer {
6312
+ margin-top: 22px;
6313
+ padding-top: 16px;
6314
+ border-top: 1px dashed var(--color-border-primary);
6315
+ display: flex;
6316
+ flex-direction: row;
6317
+ align-items: center;
6318
+ justify-content: space-between;
6319
+ gap: 16px;
6320
+ flex-wrap: wrap;
6321
+ }
6322
+
6323
+ .profile-pane-footer-hint {
6324
+ flex: 1;
6325
+ min-width: 200px;
6326
+ font-size: 12px;
6327
+ color: var(--color-text-muted);
6328
+ margin: 0;
6329
+ }
6330
+
6331
+ .btn-profile-update {
6332
+ padding: 8px 18px;
6333
+ border-radius: 8px;
6334
+ border: 1px solid transparent;
6335
+ background: var(--color-button-primary);
6336
+ color: var(--color-button-primary-text);
6337
+ font-size: 13px;
6338
+ font-weight: 500;
6339
+ cursor: pointer;
6340
+ transition: opacity 0.15s, background 0.15s;
6341
+ }
6342
+
6343
+ .btn-profile-update:hover:not(:disabled) {
6344
+ background: var(--color-button-primary-hover);
6345
+ opacity: 0.92;
6346
+ }
6347
+ .btn-profile-update:disabled {
6348
+ opacity: 0.55;
6349
+ cursor: wait;
6350
+ }
6351
+
6352
+ /* ── Minimal-Markdown rendered body ───────────────────────────────────── */
6353
+ .profile-markdown {
6354
+ font-size: 13.5px;
6355
+ line-height: 1.65;
6356
+ color: var(--color-text-primary);
6357
+ }
6358
+
6359
+ .profile-markdown h1,
6360
+ .profile-markdown h2,
6361
+ .profile-markdown h3 {
6362
+ margin: 14px 0 8px;
6363
+ font-weight: 600;
6364
+ color: var(--color-text-primary);
6365
+ }
6366
+
6367
+ .profile-markdown h1 { font-size: 18px; }
6368
+ .profile-markdown h2 { font-size: 15px; }
6369
+ .profile-markdown h3 { font-size: 13.5px; }
6370
+
6371
+ .profile-markdown p {
6372
+ margin: 8px 0;
6373
+ }
6374
+
6375
+ .profile-markdown ul,
6376
+ .profile-markdown ol {
6377
+ margin: 6px 0 10px 20px;
6378
+ padding: 0;
6379
+ }
6380
+
6381
+ .profile-markdown li {
6382
+ margin: 3px 0;
6383
+ }
6384
+
6385
+ .profile-markdown code {
6386
+ background: var(--color-bg-hover);
6387
+ padding: 1px 5px;
6388
+ border-radius: 4px;
6389
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
6390
+ font-size: 12px;
6391
+ }
6392
+
6393
+ .profile-markdown strong { font-weight: 600; }
6394
+ .profile-markdown em { font-style: italic; }
6395
+
6396
+ /* ── Memories list (cards) ───────────────────────────────────────────── */
6397
+ .memories-summary {
6398
+ font-size: 12px;
6399
+ color: var(--color-text-muted);
6400
+ }
6401
+
6402
+ .btn-memories-mini {
6403
+ padding: 4px 10px;
6404
+ border-radius: 5px;
6405
+ border: 1px solid var(--color-border-primary);
6406
+ background: transparent;
6407
+ color: var(--color-text-muted);
6408
+ font-size: 11px;
6409
+ cursor: pointer;
6410
+ transition: border-color 0.15s, color 0.15s;
6411
+ }
6412
+
6413
+ .btn-memories-mini:hover {
6414
+ border-color: var(--color-text-muted);
6415
+ color: var(--color-text-primary);
6416
+ }
6417
+
6418
+ #memories-list {
6419
+ display: flex;
6420
+ flex-direction: column;
6421
+ gap: 8px;
6422
+ }
6423
+
6424
+ .memory-card {
6425
+ display: flex;
6426
+ flex-direction: column;
6427
+ border: 1px solid var(--color-border-primary);
6428
+ border-radius: 8px;
6429
+ background: var(--color-bg-secondary);
6430
+ transition: border-color 0.15s;
6431
+ overflow: hidden;
6432
+ }
6433
+
6434
+ .memory-card:hover { border-color: var(--color-text-muted); }
6435
+
6436
+ .memory-card-head {
6437
+ display: flex;
6438
+ align-items: flex-start;
6439
+ justify-content: space-between;
6440
+ gap: 12px;
6441
+ padding: 14px 16px;
6442
+ }
6443
+
6444
+ .memory-card-info {
6445
+ flex: 1;
6446
+ min-width: 0;
6447
+ cursor: pointer;
6448
+ }
6449
+
6450
+ .memory-card-title {
6451
+ font-size: 14px;
6452
+ font-weight: 600;
6453
+ color: var(--color-text-primary);
6454
+ margin-bottom: 3px;
6455
+ overflow: hidden;
6456
+ text-overflow: ellipsis;
6457
+ white-space: nowrap;
6458
+ }
6459
+
6460
+ .memory-card-desc {
6461
+ font-size: 12px;
6462
+ color: var(--color-text-muted);
6463
+ margin-bottom: 6px;
6464
+ overflow: hidden;
6465
+ display: -webkit-box;
6466
+ -webkit-line-clamp: 2;
6467
+ -webkit-box-orient: vertical;
6468
+ }
6469
+
6470
+ .memory-card-meta {
6471
+ display: flex;
6472
+ gap: 10px;
6473
+ font-size: 11px;
6474
+ color: var(--color-text-muted);
6475
+ flex-wrap: wrap;
6476
+ }
6477
+
6478
+ .memory-filename {
6479
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
6480
+ }
6481
+
6482
+ .memory-card-actions {
6483
+ display: flex;
6484
+ align-items: flex-start;
6485
+ gap: 6px;
6486
+ flex-shrink: 0;
6487
+ }
6488
+
6489
+ /* Shared base for per-card buttons. */
6490
+ .btn-memory-curate,
6491
+ .btn-memory-delete,
6492
+ .btn-memory-expand {
6493
+ padding: 5px 10px;
6494
+ border-radius: 5px;
6495
+ border: 1px solid var(--color-border-primary);
6496
+ background: transparent;
6497
+ color: var(--color-text-primary);
6498
+ font-size: 11px;
6499
+ cursor: pointer;
6500
+ display: inline-flex;
6501
+ align-items: center;
6502
+ gap: 5px;
6503
+ transition: background 0.15s, border-color 0.15s, color 0.15s;
6504
+ }
6505
+
6506
+ .btn-memory-curate:hover {
6507
+ border-color: var(--color-text-primary);
6508
+ background: var(--color-bg-hover);
6509
+ }
6510
+
6511
+ .btn-memory-delete {
6512
+ color: var(--color-text-primary);
6513
+ }
6514
+ .btn-memory-delete:hover {
6515
+ border-color: var(--color-error);
6516
+ color: var(--color-error);
6517
+ background: var(--color-error-bg);
6518
+ }
6519
+
6520
+ .btn-memory-expand {
6521
+ min-width: 28px;
6522
+ justify-content: center;
6523
+ color: var(--color-text-muted);
6524
+ }
6525
+
6526
+ .btn-memory-expand:hover { color: var(--color-text-primary); }
6527
+ .btn-memory-expand.expanded svg { transform: rotate(180deg); }
6528
+ .btn-memory-expand svg { transition: transform 0.2s; }
6529
+
6530
+ .memory-card-body {
6531
+ padding: 4px 16px 14px 16px;
6532
+ border-top: 1px solid var(--color-border-primary);
6533
+ background: var(--color-bg-secondary);
6534
+ font-size: 13px;
6535
+ line-height: 1.6;
6536
+ color: var(--color-text-primary);
6537
+ }
6538
+
6539
+ .memory-card-body h1,
6540
+ .memory-card-body h2,
6541
+ .memory-card-body h3 {
6542
+ margin: 10px 0 6px;
6543
+ font-weight: 600;
6544
+ }
6545
+
6546
+ .memory-card-body p { margin: 6px 0; }
6547
+ .memory-card-body ul,
6548
+ .memory-card-body ol { margin: 4px 0 8px 20px; padding: 0; }
6549
+ .memory-card-body li { margin: 2px 0; }
6550
+ .memory-card-body code {
6551
+ background: var(--color-bg-hover);
6552
+ padding: 1px 5px;
6553
+ border-radius: 4px;
6554
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
6555
+ font-size: 12px;
6556
+ }
6557
+
6558
+ .memory-card-loading {
6559
+ padding: 10px 0;
6560
+ text-align: center;
6561
+ color: var(--color-text-muted);
6562
+ font-size: 12px;
6563
+ font-style: italic;
6564
+ }
6565
+
6566
+
6089
6567
  /* ── Mobile responsive (≤768px) ─────────────────────────────────────────── */
6090
6568
  @media (max-width: 768px) {
6091
6569
  /* Sidebar becomes a fixed drawer on top of content */
@@ -6373,6 +6851,16 @@ body.setup-mode[data-theme="dark"] {
6373
6851
  flex-wrap: wrap;
6374
6852
  gap: 6px;
6375
6853
  }
6854
+
6855
+ /* ── Profile / My Data page ── */
6856
+ #profile-body { padding: 16px 14px; }
6857
+ .profile-tab { padding: 9px 12px; font-size: 12px; }
6858
+ .profile-section-head { flex-wrap: wrap; }
6859
+ .profile-path { max-width: 100%; }
6860
+ .memory-card-head { flex-wrap: wrap; }
6861
+ .memory-card-actions { margin-top: 6px; flex-wrap: wrap; }
6862
+ .btn-memory-curate span,
6863
+ .btn-memory-delete span { display: none; } /* icon-only on narrow screens */
6376
6864
  }
6377
6865
 
6378
6866
 
@@ -6750,4 +7238,180 @@ body.setup-mode[data-theme="dark"] {
6750
7238
  }
6751
7239
  [data-theme="dark"] .creator-notice-warn { color: #f5c842; }
6752
7240
 
7241
+ /* ── Trash panel · Recently Deleted ────────────────────────────────── */
7242
+ .trash-summary {
7243
+ font-size: 11px;
7244
+ color: var(--color-text-muted);
7245
+ margin-right: auto;
7246
+ }
7247
+ .trash-actions {
7248
+ display: flex;
7249
+ align-items: center;
7250
+ gap: 8px;
7251
+ margin-left: auto;
7252
+ }
7253
+ .btn-trash-action {
7254
+ display: inline-flex;
7255
+ align-items: center;
7256
+ gap: 4px;
7257
+ font-size: 11px;
7258
+ padding: 4px 8px;
7259
+ border-radius: 5px;
7260
+ border: 1px solid var(--color-border-primary);
7261
+ background: var(--color-bg-secondary);
7262
+ color: var(--color-text-secondary);
7263
+ cursor: pointer;
7264
+ transition: all .15s;
7265
+ }
7266
+ .btn-trash-action:hover:not(:disabled) {
7267
+ background: var(--color-bg-hover, rgba(127,127,127,.08));
7268
+ border-color: var(--color-text-muted);
7269
+ color: var(--color-text-primary);
7270
+ }
7271
+ .btn-trash-action:disabled {
7272
+ opacity: .4;
7273
+ cursor: not-allowed;
7274
+ }
7275
+ .btn-trash-danger:hover:not(:disabled) {
7276
+ color: var(--color-error, #ef4444);
7277
+ border-color: var(--color-error, #ef4444);
7278
+ }
7279
+
7280
+ /* Trash card — standalone layout matching channel card tone */
7281
+ .trash-card {
7282
+ background: var(--color-bg-secondary);
7283
+ border: 1px solid var(--color-border-primary);
7284
+ border-radius: 10px;
7285
+ padding: 12px 16px;
7286
+ display: flex;
7287
+ align-items: center;
7288
+ gap: 12px;
7289
+ transition: border-color .15s, background .15s;
7290
+ }
7291
+ .trash-card:hover {
7292
+ border-color: var(--color-text-muted);
7293
+ }
7294
+ .trash-card-info {
7295
+ flex: 1;
7296
+ min-width: 0;
7297
+ }
7298
+ .trash-card-title {
7299
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
7300
+ font-size: 13px;
7301
+ font-weight: 600;
7302
+ color: var(--color-text-primary);
7303
+ white-space: nowrap;
7304
+ overflow: hidden;
7305
+ text-overflow: ellipsis;
7306
+ margin-bottom: 4px;
7307
+ }
7308
+ .trash-card-path {
7309
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
7310
+ font-size: 11px;
7311
+ color: var(--color-text-muted);
7312
+ white-space: nowrap;
7313
+ overflow: hidden;
7314
+ text-overflow: ellipsis;
7315
+ direction: rtl; /* keep the right side (filename) visible when truncating */
7316
+ text-align: left;
7317
+ margin-bottom: 4px;
7318
+ }
7319
+ .trash-card-meta {
7320
+ display: flex;
7321
+ align-items: center;
7322
+ gap: 12px;
7323
+ font-size: 11px;
7324
+ color: var(--color-text-muted);
7325
+ }
7326
+ .trash-card-actions {
7327
+ display: flex;
7328
+ align-items: center;
7329
+ gap: 6px;
7330
+ flex-shrink: 0;
7331
+ }
7332
+ .trash-project {
7333
+ display: inline-flex;
7334
+ align-items: center;
7335
+ gap: 4px;
7336
+ font-size: 11px;
7337
+ color: var(--color-text-muted);
7338
+ max-width: 260px;
7339
+ overflow: hidden;
7340
+ text-overflow: ellipsis;
7341
+ white-space: nowrap;
7342
+ }
7343
+ .trash-missing {
7344
+ display: inline-flex;
7345
+ align-items: center;
7346
+ gap: 3px;
7347
+ font-size: 10px;
7348
+ padding: 1px 6px;
7349
+ border-radius: 4px;
7350
+ color: var(--color-warning, #d97706);
7351
+ background: rgba(217, 119, 6, .1);
7352
+ border: 1px solid rgba(217, 119, 6, .3);
7353
+ }
7354
+
7355
+ .btn-trash-restore,
7356
+ .btn-trash-delete {
7357
+ display: inline-flex;
7358
+ align-items: center;
7359
+ gap: 4px;
7360
+ font-size: 11px;
7361
+ padding: 5px 9px;
7362
+ border-radius: 5px;
7363
+ border: 1px solid var(--color-border-primary);
7364
+ background: var(--color-bg-tertiary, var(--color-bg-primary));
7365
+ color: var(--color-text-secondary);
7366
+ cursor: pointer;
7367
+ transition: all .15s;
7368
+ }
7369
+ .btn-trash-restore:hover:not(:disabled) {
7370
+ background: var(--color-bg-hover, rgba(127,127,127,.08));
7371
+ color: var(--color-success, #10b981);
7372
+ border-color: var(--color-success, #10b981);
7373
+ }
7374
+ .btn-trash-delete {
7375
+ padding: 5px 8px;
7376
+ }
7377
+ .btn-trash-delete:hover:not(:disabled) {
7378
+ color: var(--color-error, #ef4444);
7379
+ border-color: var(--color-error, #ef4444);
7380
+ }
7381
+ .btn-trash-restore:disabled,
7382
+ .btn-trash-delete:disabled {
7383
+ opacity: .5;
7384
+ cursor: not-allowed;
7385
+ }
7386
+
7387
+ /* Trash panel — matches Channels layout for visual consistency */
7388
+ #trash-panel {
7389
+ flex: 1;
7390
+ display: flex;
7391
+ flex-direction: column;
7392
+ overflow: hidden;
7393
+ }
7394
+ #trash-body {
7395
+ flex: 1;
7396
+ overflow-y: auto;
7397
+ padding: 28px 36px;
7398
+ display: flex;
7399
+ flex-direction: column;
7400
+ gap: 20px;
7401
+ }
7402
+ .trash-toolbar {
7403
+ display: flex;
7404
+ align-items: center;
7405
+ gap: 8px;
7406
+ padding: 10px 14px;
7407
+ border: 1px solid var(--color-border-primary);
7408
+ border-radius: 10px;
7409
+ background: var(--color-bg-secondary);
7410
+ }
7411
+ #trash-list {
7412
+ display: flex;
7413
+ flex-direction: column;
7414
+ gap: 10px;
7415
+ }
7416
+
6753
7417