openclacky 1.5.21 → 1.5.22

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -0
  3. data/lib/clacky/billing/platform_billing.rb +3 -0
  4. data/lib/clacky/default_extensions/git/panels/git/view.js +1911 -398
  5. data/lib/clacky/default_extensions/preview/panels/preview/view.js +199 -34
  6. data/lib/clacky/providers.rb +43 -17
  7. data/lib/clacky/search_config.rb +33 -11
  8. data/lib/clacky/server/git_panel.rb +360 -34
  9. data/lib/clacky/server/http_server.rb +145 -47
  10. data/lib/clacky/server/preview.rb +118 -17
  11. data/lib/clacky/server/scheduler.rb +81 -2
  12. data/lib/clacky/server/web_ui_controller.rb +35 -27
  13. data/lib/clacky/session_manager.rb +52 -5
  14. data/lib/clacky/utils/mac_app_detector.rb +8 -7
  15. data/lib/clacky/utils/model_pricing.rb +60 -2
  16. data/lib/clacky/utils/windows_app_detector.rb +3 -1
  17. data/lib/clacky/version.rb +1 -1
  18. data/lib/clacky/web/app.css +650 -96
  19. data/lib/clacky/web/app.js +59 -6
  20. data/lib/clacky/web/auth.js +1 -1
  21. data/lib/clacky/web/components/composer.js +107 -8
  22. data/lib/clacky/web/components/image-zoom.js +165 -0
  23. data/lib/clacky/web/components/model-picker.js +6 -4
  24. data/lib/clacky/web/components/notify.js +2 -2
  25. data/lib/clacky/web/core/aside.js +60 -3
  26. data/lib/clacky/web/features/billing/view.js +2 -2
  27. data/lib/clacky/web/features/channels/view.js +5 -2
  28. data/lib/clacky/web/features/extensions/view.js +2 -2
  29. data/lib/clacky/web/features/new-session/store.js +79 -2
  30. data/lib/clacky/web/features/new-session/view.js +496 -58
  31. data/lib/clacky/web/features/skills/store.js +1 -1
  32. data/lib/clacky/web/features/tasks/view.js +162 -51
  33. data/lib/clacky/web/features/workspace/store.js +13 -6
  34. data/lib/clacky/web/features/workspace/view.js +153 -163
  35. data/lib/clacky/web/i18n.js +238 -56
  36. data/lib/clacky/web/index.html +173 -157
  37. data/lib/clacky/web/projects.js +37 -4
  38. data/lib/clacky/web/sessions.js +181 -105
  39. data/lib/clacky/web/settings.js +26 -8
  40. data/lib/clacky/web/skills.js +2 -2
  41. data/lib/clacky/web/theme.js +17 -2
  42. data/lib/clacky/web/utils.js +17 -2
  43. data/lib/clacky/web/weixin-qr.html +2 -1
  44. data/lib/clacky/web/ws-dispatcher.js +8 -29
  45. metadata +2 -1
@@ -1,8 +1,12 @@
1
1
  <!DOCTYPE html>
2
- <html lang="en" id="html-root" data-font-size="medium">
2
+ <html lang="en" id="html-root" data-font-size="medium" translate="no">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <!-- The UI translates itself (i18n.js). Browser auto-translation would rewrite
7
+ strings that are already in the user's language and mangle code, paths and
8
+ line counts in the chat log. -->
9
+ <meta name="google" content="notranslate">
6
10
  <title id="page-title">{{BRAND_NAME}}</title>
7
11
  <link rel="icon" type="image/svg+xml" href="/favicon.svg">
8
12
  <link rel="apple-touch-icon" href="/apple-touch-icon-180.png">
@@ -40,7 +44,7 @@
40
44
  <header id="top-header">
41
45
  <div id="header-left">
42
46
  <span id="ext-slot-header-left" data-slot="header.left"></span>
43
- <button id="btn-toggle-sidebar" class="sidebar-toggle-btn" title="Toggle sidebar">
47
+ <button id="btn-toggle-sidebar" class="sidebar-toggle-btn" data-tooltip="Toggle sidebar" data-tooltip-pos="right" data-i18n-tooltip="tooltip.toggleSidebar">
44
48
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm">
45
49
  <rect width="18" height="18" x="3" y="3" rx="2"/>
46
50
  <path d="M9 3v18"/>
@@ -64,14 +68,14 @@
64
68
  <div id="header-right">
65
69
  <span id="ext-slot-header-right" data-slot="header.right"></span>
66
70
 
67
- <button id="header-cmdbar" type="button" title="Search sessions" data-i18n-title="header.cmdbar.placeholder">
71
+ <button id="header-cmdbar" type="button" data-tooltip="Search sessions" data-tooltip-pos="bottom" data-i18n-tooltip="header.cmdbar.placeholder">
68
72
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm"><path d="M5.1 11.2A7 7 0 1 1 13.2 16.9"/><path d="M17 15l4 4"/><path d="M8.6 12.6 5.8 16.4h3.4L6.6 20.2"/></svg>
69
73
  <span class="cmdbar-kbd">Ctrl K</span>
70
74
  </button>
71
- <button id="header-print-receipt" class="theme-toggle-btn" data-i18n-title="billing.share.btn" title="Print receipt">
75
+ <button id="header-print-receipt" class="theme-toggle-btn" data-tooltip="Print receipt" data-tooltip-pos="bottom" data-i18n-tooltip="billing.share.btn">
72
76
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm"><path d="M6 9V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v5"/><path d="M6 18H5a3 3 0 0 1-3-3v-3a3 3 0 0 1 3-3h14a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3h-1"/><rect x="6" y="14" width="12" height="8" rx="2"/></svg>
73
77
  </button>
74
- <button id="notify-toggle-header" class="theme-toggle-btn" data-i18n-title="notify.tooltip.off" title="Task alerts"></button>
78
+ <button id="notify-toggle-header" class="theme-toggle-btn" data-tooltip="Task alerts" data-tooltip-pos="left" data-i18n-tooltip="notify.tooltip.off"></button>
75
79
 
76
80
  </div>
77
81
  </header>
@@ -157,7 +161,7 @@
157
161
  </span>
158
162
  <div class="sidebar-divider-actions">
159
163
  <div class="btn-split-wrap">
160
- <button id="btn-new-session-inline" class="btn-split-main" title="New Session">
164
+ <button id="btn-new-session-inline" class="btn-split-main" title="New Session" data-i18n-title="tooltip.newSession">
161
165
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
162
166
  <path d="M12 3c4.97 0 9 3.58 9 8s-4.03 8-9 8c-1.2 0-2.35-.2-3.4-.58L4 20l1.2-3.6C3.84 15 3 13.1 3 11c0-4.42 4.03-8 9-8z"/>
163
167
  <path d="M12 8v6"/>
@@ -186,7 +190,7 @@
186
190
 
187
191
  <!-- Folded group sub-view header (hidden by default; title filled by Sessions) -->
188
192
  <div id="group-view-header" class="sidebar-divider" style="display:none">
189
- <button id="btn-group-back" class="btn-icon-sm" title="Back" aria-label="Back to session list">
193
+ <button id="btn-group-back" class="btn-icon-sm" title="Back" data-i18n-title="tooltip.back" aria-label="Back to session list">
190
194
  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
191
195
  <path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
192
196
  </svg>
@@ -210,12 +214,12 @@
210
214
  </svg>
211
215
  </span>
212
216
  <div class="sidebar-divider-actions">
213
- <button id="btn-projects-organize" class="btn-icon-sm" title="Organize" aria-label="Organize projects">
217
+ <button id="btn-projects-organize" class="btn-icon-sm" title="Organize" data-i18n-title="tooltip.organize" aria-label="Organize projects">
214
218
  <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
215
219
  <circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/>
216
220
  </svg>
217
221
  </button>
218
- <button id="btn-new-project" class="btn-icon-sm" title="New Project" aria-label="New project">
222
+ <button id="btn-new-project" class="btn-icon-sm" title="New Project" data-i18n-title="tooltip.newProject" aria-label="New project">
219
223
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
220
224
  <line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
221
225
  </svg>
@@ -348,7 +352,7 @@
348
352
  <div id="sidebar-footer">
349
353
  <span id="ext-slot-sidebar-footer" data-slot="sidebar.footer"></span>
350
354
  <div class="sidebar-nav-row">
351
- <button id="btn-settings" class="sidebar-nav-btn" title="Settings">
355
+ <button id="btn-settings" class="sidebar-nav-btn" title="Settings" data-i18n-title="tooltip.settings">
352
356
  <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
353
357
  <circle cx="12" cy="12" r="3"/>
354
358
  <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
@@ -422,13 +426,16 @@
422
426
  <div id="ns-input-bar" class="new-session-input-bar">
423
427
  <input type="file" id="ns-file-input" accept="*/*" multiple style="display:none">
424
428
  <button id="ns-btn-attach" type="button" class="new-session-composer-btn"
425
- title="Attach file (image, pdf, docx, md, tar.gz…) — drag & drop / Ctrl+V also work">
429
+ data-tooltip="Attach file (image, pdf, docx, md, tar.gz…) — drag &amp; drop / Ctrl+V also work"
430
+ data-tooltip-pos="top" data-i18n-tooltip="tooltip.attach">
426
431
  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
427
432
  <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66L9.41 17.41a2 2 0 0 1-2.83-2.83l8.49-8.48"/>
428
433
  </svg>
429
434
  </button>
430
- <button id="ns-btn-slash" type="button" class="new-session-composer-btn" title="Insert skill command (/)">
431
- <span>/</span>
435
+ <button id="ns-btn-slash" type="button" class="new-session-composer-btn" data-tooltip="Insert skill command (/)" data-tooltip-pos="top" data-i18n-tooltip="tooltip.slash">
436
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
437
+ <path d="M16 3l-8 18"/>
438
+ </svg>
432
439
  </button>
433
440
  <div id="new-session-input"
434
441
  class="new-session-textarea"
@@ -437,7 +444,7 @@
437
444
  aria-multiline="true"
438
445
  data-i18n-placeholder="chat.input.placeholder"
439
446
  data-placeholder="Message… (Enter to send, Shift+Enter for newline)"></div>
440
- <button id="new-session-send" class="new-session-send" type="button" title="Send message" disabled>
447
+ <button id="new-session-send" class="new-session-send" type="button" title="Send message" data-i18n-title="chat.btn.sendTitle" disabled>
441
448
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
442
449
  </button>
443
450
  </div><!-- /.new-session-input-bar -->
@@ -456,7 +463,7 @@
456
463
  <div class="task-page-header">
457
464
  <h2 class="task-page-title page-title" data-i18n="tasks.title">Scheduled Tasks</h2>
458
465
  <p class="task-page-subtitle" data-i18n="tasks.subtitle">Manage and schedule automated tasks for your assistant</p>
459
- <button id="btn-create-task" class="btn-create-task" title="Create a new task">
466
+ <button id="btn-create-task" class="btn-create-task" title="Create a new task" data-i18n-title="tooltip.createTask">
460
467
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm">
461
468
  <path d="M5 12h14"/>
462
469
  <path d="M12 5v14"/>
@@ -495,6 +502,8 @@
495
502
  </div>
496
503
  <!-- Composer slot: agent-scoped controls above the session info bar. -->
497
504
  <div id="ext-slot-session-composer" class="session-composer" data-slot="session.composer"></div>
505
+ <!-- Pending input queue — messages waiting for the current task to finish -->
506
+ <div id="input-queue" aria-live="polite" hidden></div>
498
507
  <!-- Session info bar — mirrors CLI bottom status bar -->
499
508
  <div id="session-info-bar" style="display:none">
500
509
  <!-- Order: status | id | dir | model | reasoning | mode | todo | signal | cost -->
@@ -506,20 +515,20 @@
506
515
  <div id="sib-actions-dropdown" class="clacky-popover sib-actions-dropdown" style="display:none" role="menu"></div>
507
516
  </span>
508
517
  <span class="sib-sep sib-sep-after-id">│</span>
509
- <span id="sib-dir" data-i18n-title="sib.dir.tooltip" title="Click to change directory"><span id="sib-dir-text"></span><span class="sib-caret" aria-hidden="true"><svg viewBox="0 0 16 16" width="9" height="9" aria-hidden="true"><path d="M4 6.5L8 10.5L12 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></span>
518
+ <span id="sib-dir" data-tooltip="Click to change directory" data-i18n-tooltip="sib.dir.tooltip"><span id="sib-dir-text"></span><span class="sib-caret" aria-hidden="true"><svg viewBox="0 0 16 16" width="9" height="9" aria-hidden="true"><path d="M4 6.5L8 10.5L12 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></span>
510
519
  <span class="sib-sep sib-sep-after-dir">│</span>
511
520
  <span id="sib-model-wrap">
512
- <span id="sib-model" class="sib-model-clickable" title="Click to switch model"></span>
521
+ <span id="sib-model" class="sib-model-clickable" data-tooltip="Click to switch model" data-i18n-tooltip="sib.model.tooltip"></span>
513
522
  <div id="sib-model-dropdown" class="clacky-popover sib-model-dropdown" style="display:none"></div>
514
523
  <div id="sib-submodel-panel" class="clacky-popover sib-submodel-panel" style="display:none"></div>
515
524
  </span>
516
525
  <span class="sib-sep sib-sep-after-model">│</span>
517
526
  <span id="sib-reasoning-wrap">
518
- <span id="sib-reasoning" class="sib-reasoning-clickable" data-i18n-title="sib.reasoning.tooltip" title="Click to change reasoning effort"><span class="sib-pill-label" data-i18n="sib.reasoning.label">Reasoning</span><span id="sib-reasoning-text"></span><span class="sib-caret" aria-hidden="true"><svg viewBox="0 0 16 16" width="9" height="9" aria-hidden="true"><path d="M4 6.5L8 10.5L12 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></span>
527
+ <span id="sib-reasoning" class="sib-reasoning-clickable" data-tooltip="Click to change reasoning effort" data-i18n-tooltip="sib.reasoning.tooltip"><span class="sib-pill-label" data-i18n="sib.reasoning.label">Reasoning</span><span id="sib-reasoning-text"></span><span class="sib-caret" aria-hidden="true"><svg viewBox="0 0 16 16" width="9" height="9" aria-hidden="true"><path d="M4 6.5L8 10.5L12 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></span>
519
528
  <div id="sib-reasoning-dropdown" class="clacky-popover sib-reasoning-dropdown" style="display:none" role="menu"></div>
520
529
  </span>
521
530
  <span id="sib-mode-wrap">
522
- <button id="sib-mode" class="sib-mode-clickable" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="sib-mode-menu" data-i18n-title="sib.mode.tooltip"><span class="sib-pill-label" data-i18n="sib.mode.pill">Mode</span><span id="sib-mode-text"></span><span class="sib-caret" aria-hidden="true"><svg viewBox="0 0 16 16" width="9" height="9" aria-hidden="true"><path d="M4 6.5L8 10.5L12 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></button>
531
+ <button id="sib-mode" class="sib-mode-clickable" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="sib-mode-menu" data-tooltip="Click to change permission mode" data-i18n-tooltip="sib.mode.tooltip"><span class="sib-pill-label" data-i18n="sib.mode.pill">Mode</span><span id="sib-mode-text"></span><span class="sib-caret" aria-hidden="true"><svg viewBox="0 0 16 16" width="9" height="9" aria-hidden="true"><path d="M4 6.5L8 10.5L12 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></button>
523
532
  <div id="sib-mode-menu" class="clacky-popover" role="menu" hidden>
524
533
  <button type="button" role="menuitemradio" data-permission-mode="confirm_all" aria-checked="true">
525
534
  <strong data-i18n="sib.mode.confirm_all">Manual</strong>
@@ -591,8 +600,6 @@
591
600
  </div>
592
601
  <!-- Shown when the composer was prefilled from an external link -->
593
602
  <div id="chat-deeplink-notice" class="deeplink-notice" role="status" style="display:none"></div>
594
- <!-- Image preview strip (hidden when empty) -->
595
- <div id="input-queue" aria-live="polite" hidden></div>
596
603
  <!-- @ mention menu (Files & Folders / Past Chats) -->
597
604
  <div id="mention-autocomplete" class="mention-autocomplete" style="display:none" role="listbox" aria-label="Mention"></div>
598
605
  <!-- Composer card: the attachment strip and the input row share one frame,
@@ -602,13 +609,16 @@
602
609
  <div id="input-bar">
603
610
  <!-- Hidden file picker -->
604
611
  <input type="file" id="image-file-input" accept="*/*" multiple style="display:none">
605
- <button id="btn-attach" title="Attach file (image, pdf, docx, md, tar.gz…) — drag & drop / Ctrl+V also work">
612
+ <button id="btn-attach" data-tooltip="Attach file (image, pdf, docx, md, tar.gz…) — drag &amp; drop / Ctrl+V also work"
613
+ data-tooltip-pos="top" data-i18n-tooltip="tooltip.attach">
606
614
  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
607
615
  <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66L9.41 17.41a2 2 0 0 1-2.83-2.83l8.49-8.48"/>
608
616
  </svg>
609
617
  </button>
610
- <button id="btn-slash" title="Insert skill command (/)">
611
- <span>/</span>
618
+ <button id="btn-slash" data-tooltip="Insert skill command (/)" data-tooltip-pos="top" data-i18n-tooltip="tooltip.slash">
619
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
620
+ <path d="M16 3l-8 18"/>
621
+ </svg>
612
622
  </button>
613
623
  <div id="user-input"
614
624
  contenteditable="true"
@@ -634,8 +644,8 @@
634
644
  </button>
635
645
  </div>
636
646
  </div>
637
- <button id="btn-send" title="Send message"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg></button>
638
- <button id="btn-interrupt" style="display:none" title="Stop"><svg viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="1.5"/></svg></button>
647
+ <button id="btn-send" title="Send message" data-i18n-title="chat.btn.sendTitle"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg></button>
648
+ <button id="btn-interrupt" style="display:none" title="Stop" data-i18n-title="chat.btn.stopTitle"><svg viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="1.5"/></svg></button>
639
649
  </div>
640
650
  </div>
641
651
  </div>
@@ -651,11 +661,11 @@
651
661
  <!-- Host-owned actions docked at the right end of the tab bar (the bar
652
662
  itself is rendered by Clacky.ext inside the slot below). -->
653
663
  <div class="aside-tabbar-actions">
654
- <button id="btn-aside-fullscreen" class="session-aside-fullscreen" data-i18n-title="aside.fullscreen" title="Fullscreen">
664
+ <button id="btn-aside-fullscreen" class="session-aside-fullscreen" data-tooltip="Fullscreen preview" data-tooltip-pos="bottom">
655
665
  <svg class="icon-fs-enter" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/></svg>
656
666
  <svg class="icon-fs-exit" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3v3a2 2 0 0 1-2 2H3"/><path d="M21 8h-3a2 2 0 0 1-2-2V3"/><path d="M3 16h3a2 2 0 0 1 2 2v3"/><path d="M16 21v-3a2 2 0 0 1 2-2h3"/></svg>
657
667
  </button>
658
- <button id="btn-aside-collapse" class="session-aside-collapse" data-i18n-title="aside.collapse" title="Collapse">
668
+ <button id="btn-aside-collapse" class="session-aside-collapse" data-tooltip="Collapse panel" data-tooltip-pos="bottom">
659
669
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/><path d="m14 9 3 3-3 3"/></svg>
660
670
  </button>
661
671
  </div>
@@ -664,7 +674,7 @@
664
674
 
665
675
  <!-- Collapsed-state opener tab -->
666
676
  <div id="workspace-overlay"></div>
667
- <button id="btn-aside-open" class="session-aside-opener" data-i18n-title="aside.expand" title="Open panel" style="display:none">
677
+ <button id="btn-aside-open" class="session-aside-opener" data-tooltip="Open panel" data-tooltip-pos="left" style="display:none">
668
678
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/><path d="m10 15-3-3 3-3"/></svg>
669
679
  </button>
670
680
  </div>
@@ -677,7 +687,7 @@
677
687
  <h2 class="skills-page-title page-title" data-i18n="skills.title">Skills</h2>
678
688
  <p class="skills-page-subtitle" data-i18n="skills.subtitle">Extend your assistant's capabilities with custom skills</p>
679
689
  <div class="skill-action-btns">
680
- <button id="btn-import-skill" class="btn-import-skill" title="Import skill from ZIP or GitHub URL">
690
+ <button id="btn-import-skill" class="btn-import-skill" title="Import skill from ZIP or GitHub URL" data-i18n-title="tooltip.importSkill">
681
691
  <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm">
682
692
  <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
683
693
  <polyline points="7 10 12 15 17 10"/>
@@ -685,7 +695,7 @@
685
695
  </svg>
686
696
  <span data-i18n="skills.btn.import">Import</span>
687
697
  </button>
688
- <button id="btn-create-skill" class="btn-create-skill" title="Create a new skill with AI">
698
+ <button id="btn-create-skill" class="btn-create-skill" title="Create a new skill with AI" data-i18n-title="tooltip.createSkill">
689
699
  <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm">
690
700
  <path d="M5 12h14"/>
691
701
  <path d="M12 5v14"/>
@@ -714,7 +724,7 @@
714
724
  <span class="skills-filter-label" data-i18n="skills.filter.showSystem">Show system skills</span>
715
725
  </label>
716
726
  <!-- Refresh brand skills button (only visible in Brand Skills tab) -->
717
- <button id="btn-refresh-brand-skills" class="btn-brand-skills-refresh" title="Refresh from cloud" style="display:none">
727
+ <button id="btn-refresh-brand-skills" class="btn-brand-skills-refresh" title="Refresh from cloud" data-i18n-title="tooltip.refreshBrandSkills" style="display:none">
718
728
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon-sm">
719
729
  <path d="M21 2v6h-6"/>
720
730
  <path d="M3 12a9 9 0 0 1 15-6.7L21 8"/>
@@ -740,7 +750,7 @@
740
750
  <!-- Hidden file input for local ZIP selection -->
741
751
  <input id="skill-import-file" type="file" accept=".zip" style="display:none" />
742
752
  <!-- Browse local file button -->
743
- <button id="btn-skill-import-browse" class="btn-skill-import-browse" title="Choose local ZIP file">
753
+ <button id="btn-skill-import-browse" class="btn-skill-import-browse" title="Choose local ZIP file" data-i18n-title="tooltip.chooseZip">
744
754
  <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
745
755
  <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
746
756
  </svg>
@@ -748,7 +758,7 @@
748
758
  <button id="btn-skill-import-confirm" class="btn-skill-import-confirm">
749
759
  <span data-i18n="skills.import.install">Install</span>
750
760
  </button>
751
- <button id="btn-skill-import-cancel" class="btn-skill-import-cancel" title="Cancel">✕</button>
761
+ <button id="btn-skill-import-cancel" class="btn-skill-import-cancel" title="Cancel" data-i18n-title="modal.cancel">✕</button>
752
762
  </div>
753
763
  </div>
754
764
  <div id="skills-list"></div>
@@ -885,87 +895,22 @@
885
895
  <!-- ── ARCHIVE PANEL — chats the user archived: off the rail, still on disk ── -->
886
896
  <div id="archive-panel" class="dm-view" style="display:none">
887
897
  <div id="archive-body">
888
- <div class="trash-toolbar">
889
- <div class="archive-search-wrap">
890
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="archive-search-icon">
891
- <circle cx="11" cy="11" r="8"/>
892
- <line x1="21" y1="21" x2="16.65" y2="16.65"/>
893
- </svg>
894
- <input type="search" id="archive-search" class="archive-search-input" data-i18n-placeholder="archive.searchPlaceholder" placeholder="Search archived sessions" autocomplete="off" spellcheck="false">
895
- </div>
896
-
897
- <div class="trash-filter-project-wrap">
898
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="trash-filter-project-icon">
899
- <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
900
- </svg>
901
- <div class="custom-select-wrapper" id="archive-filter-project">
902
- <div class="custom-select-trigger custom-select-trigger--bare" tabindex="0">
903
- <span class="custom-select-value placeholder" data-i18n="archive.filterAllProjects">All projects</span>
904
- <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
905
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
906
- </svg>
907
- </div>
908
- <div class="custom-select-dropdown"></div>
909
- </div>
910
- </div>
911
-
912
- <div class="trash-filter-project-wrap">
913
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="trash-filter-project-icon">
914
- <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.83z"/>
915
- <line x1="7" y1="7" x2="7.01" y2="7"/>
916
- </svg>
917
- <div class="custom-select-wrapper" id="archive-filter-type">
918
- <div class="custom-select-trigger custom-select-trigger--bare" tabindex="0">
919
- <span class="custom-select-value placeholder" data-i18n="archive.filterAllTypes">All types</span>
920
- <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
921
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
922
- </svg>
923
- </div>
924
- <div class="custom-select-dropdown"></div>
898
+ <div class="trash-toolbar">
899
+ <div class="archive-search-wrap">
900
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="archive-search-icon">
901
+ <circle cx="11" cy="11" r="8"/>
902
+ <line x1="21" y1="21" x2="16.65" y2="16.65"/>
903
+ </svg>
904
+ <input type="search" id="archive-search" class="archive-search-input" data-i18n-placeholder="archive.searchPlaceholder" placeholder="Search archived sessions" autocomplete="off" spellcheck="false">
925
905
  </div>
926
- </div>
927
-
928
- <span class="trash-summary" id="archive-summary"></span>
929
-
930
- <button id="btn-archive-delete-all" class="btn-trash-action btn-trash-danger">
931
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
932
- <polyline points="3 6 5 6 21 6"/>
933
- <path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
934
- <path d="M10 11v6"/><path d="M14 11v6"/>
935
- <path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/>
936
- </svg>
937
- <span data-i18n="archive.deleteAll">Delete all</span>
938
- </button>
939
- </div>
940
-
941
- <div id="archive-list"></div>
942
-
943
- <button id="btn-archive-load-more" style="display:none" data-i18n="archive.loadMore">Load more</button>
944
- </div>
945
- </div>
946
906
 
947
- <!-- ── TRASH PANEL — Recently deleted files across all projects ─── -->
948
- <div id="trash-panel" class="dm-view" style="display:none">
949
- <div id="trash-body">
950
- <div id="trash-tabs">
951
- <div class="segmented-control">
952
- <button class="trash-tab segmented-control__btn active" data-tab="session-trash" id="tab-session-trash" data-i18n="trash.tabSession">Sessions</button>
953
- <button class="trash-tab segmented-control__btn" data-tab="file-trash" id="tab-file-trash" data-i18n="trash.tabFile">Agent Files</button>
954
- </div>
955
- </div>
956
-
957
- <p class="trash-session-hint" id="trash-session-hint" data-i18n="trash.sessionAutoCleanHint">The system keeps the most recent 200 sessions; older ones are moved here.</p>
958
-
959
- <div class="trash-toolbar">
960
- <div class="trash-filter-bar" id="trash-filter-bar">
961
907
  <div class="trash-filter-project-wrap">
962
908
  <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="trash-filter-project-icon">
963
- <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.83z"/>
964
- <line x1="7" y1="7" x2="7.01" y2="7"/>
909
+ <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
965
910
  </svg>
966
- <div class="custom-select-wrapper" id="trash-filter-source">
911
+ <div class="custom-select-wrapper" id="archive-filter-project">
967
912
  <div class="custom-select-trigger custom-select-trigger--bare" tabindex="0">
968
- <span class="custom-select-value placeholder" data-i18n="trash.filterAllTypes">All types</span>
913
+ <span class="custom-select-value placeholder" data-i18n="archive.filterAllProjects">All projects</span>
969
914
  <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
970
915
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
971
916
  </svg>
@@ -973,13 +918,15 @@
973
918
  <div class="custom-select-dropdown"></div>
974
919
  </div>
975
920
  </div>
976
- <div class="trash-filter-project-wrap" id="trash-filter-project-wrap">
921
+
922
+ <div class="trash-filter-project-wrap">
977
923
  <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="trash-filter-project-icon">
978
- <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
924
+ <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.83z"/>
925
+ <line x1="7" y1="7" x2="7.01" y2="7"/>
979
926
  </svg>
980
- <div class="custom-select-wrapper" id="trash-filter-project">
927
+ <div class="custom-select-wrapper" id="archive-filter-type">
981
928
  <div class="custom-select-trigger custom-select-trigger--bare" tabindex="0">
982
- <span class="custom-select-value placeholder" data-i18n="trash.filterAllProjects">所有项目</span>
929
+ <span class="custom-select-value placeholder" data-i18n="archive.filterAllTypes">All types</span>
983
930
  <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
984
931
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
985
932
  </svg>
@@ -987,50 +934,118 @@
987
934
  <div class="custom-select-dropdown"></div>
988
935
  </div>
989
936
  </div>
990
- </div>
991
- <span class="trash-summary" id="trash-summary"></span>
992
- <div class="trash-actions">
993
- <button id="btn-trash-refresh" class="btn-trash-action" data-i18n-title="trash.refresh.tooltip" title="Refresh">
994
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
995
- <path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/>
996
- <path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>
997
- </svg>
998
- <span data-i18n="trash.refresh">Refresh</span>
999
- </button>
1000
- <button id="btn-trash-empty-old" class="btn-trash-action btn-trash-danger" data-i18n-title="trash.emptyOld.tooltip" title="Permanently delete files older than 7 days">
1001
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1002
- <circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>
1003
- </svg>
1004
- <span data-i18n="trash.emptyOld">Empty older than 7 days</span>
1005
- </button>
1006
- <button id="btn-trash-empty-orphans" class="btn-trash-action btn-trash-danger" style="display:none" data-i18n-title="trash.emptyOrphans.tooltip" title="Permanently delete entries whose original project directory no longer exists (e.g. test temp dirs)">
1007
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1008
- <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
1009
- <line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
1010
- </svg>
1011
- <span data-i18n="trash.emptyOrphans">Clean orphans</span>
1012
- </button>
1013
- <button id="btn-trash-empty-all" class="btn-trash-action btn-trash-danger" data-i18n-title="trash.emptyAll.tooltip" title="Permanently delete all trashed files">
937
+
938
+ <span class="trash-summary" id="archive-summary"></span>
939
+
940
+ <button id="btn-archive-delete-all" class="btn-trash-action btn-trash-danger">
1014
941
  <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1015
942
  <polyline points="3 6 5 6 21 6"/>
1016
943
  <path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
1017
944
  <path d="M10 11v6"/><path d="M14 11v6"/>
1018
945
  <path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/>
1019
946
  </svg>
1020
- <span data-i18n="trash.emptyAll">Empty all</span>
947
+ <span data-i18n="archive.deleteAll">Delete all</span>
1021
948
  </button>
1022
949
  </div>
1023
- </div>
1024
950
 
1025
- <div id="trash-tab-file" class="trash-tab-content" style="display:none">
1026
- <div id="trash-list"></div>
951
+ <div id="archive-list"></div>
952
+
953
+ <button id="btn-archive-load-more" style="display:none" data-i18n="archive.loadMore">Load more</button>
1027
954
  </div>
955
+ </div>
956
+
957
+ <!-- ── TRASH PANEL — Recently deleted files across all projects ─── -->
958
+ <div id="trash-panel" class="dm-view" style="display:none">
959
+ <div id="trash-body">
960
+ <div id="trash-tabs">
961
+ <div class="segmented-control">
962
+ <button class="trash-tab segmented-control__btn active" data-tab="session-trash" id="tab-session-trash" data-i18n="trash.tabSession">Sessions</button>
963
+ <button class="trash-tab segmented-control__btn" data-tab="file-trash" id="tab-file-trash" data-i18n="trash.tabFile">Agent Files</button>
964
+ </div>
965
+ </div>
966
+
967
+ <!-- Everything below the segmented tabs scrolls as one region: the
968
+ hint, the toolbar and the list share a single viewport so the tab
969
+ strip above stays put. -->
970
+ <div id="trash-scroll">
971
+ <p class="trash-session-hint" id="trash-session-hint" data-i18n="trash.sessionAutoCleanHint">The system keeps the most recent 200 sessions; older ones are moved here.</p>
972
+
973
+ <div class="trash-toolbar">
974
+ <div class="trash-filter-bar" id="trash-filter-bar">
975
+ <div class="trash-filter-project-wrap">
976
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="trash-filter-project-icon">
977
+ <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.83z"/>
978
+ <line x1="7" y1="7" x2="7.01" y2="7"/>
979
+ </svg>
980
+ <div class="custom-select-wrapper" id="trash-filter-source">
981
+ <div class="custom-select-trigger custom-select-trigger--bare" tabindex="0">
982
+ <span class="custom-select-value placeholder" data-i18n="trash.filterAllTypes">All types</span>
983
+ <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
984
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
985
+ </svg>
986
+ </div>
987
+ <div class="custom-select-dropdown"></div>
988
+ </div>
989
+ </div>
990
+ <div class="trash-filter-project-wrap" id="trash-filter-project-wrap">
991
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="trash-filter-project-icon">
992
+ <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
993
+ </svg>
994
+ <div class="custom-select-wrapper" id="trash-filter-project">
995
+ <div class="custom-select-trigger custom-select-trigger--bare" tabindex="0">
996
+ <span class="custom-select-value placeholder" data-i18n="trash.filterAllProjects">所有项目</span>
997
+ <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
998
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
999
+ </svg>
1000
+ </div>
1001
+ <div class="custom-select-dropdown"></div>
1002
+ </div>
1003
+ </div>
1004
+ </div>
1005
+ <span class="trash-summary" id="trash-summary"></span>
1006
+ <div class="trash-actions">
1007
+ <button id="btn-trash-refresh" class="btn-trash-action" data-i18n-title="trash.refresh.tooltip" title="Refresh">
1008
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1009
+ <path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/>
1010
+ <path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>
1011
+ </svg>
1012
+ <span data-i18n="trash.refresh">Refresh</span>
1013
+ </button>
1014
+ <button id="btn-trash-empty-old" class="btn-trash-action btn-trash-danger" data-i18n-title="trash.emptyOld.tooltip" title="Permanently delete files older than 7 days">
1015
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1016
+ <circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>
1017
+ </svg>
1018
+ <span data-i18n="trash.emptyOld">Empty older than 7 days</span>
1019
+ </button>
1020
+ <button id="btn-trash-empty-orphans" class="btn-trash-action btn-trash-danger" style="display:none" data-i18n-title="trash.emptyOrphans.tooltip" title="Permanently delete entries whose original project directory no longer exists (e.g. test temp dirs)">
1021
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1022
+ <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
1023
+ <line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
1024
+ </svg>
1025
+ <span data-i18n="trash.emptyOrphans">Clean orphans</span>
1026
+ </button>
1027
+ <button id="btn-trash-empty-all" class="btn-trash-action btn-trash-danger" data-i18n-title="trash.emptyAll.tooltip" title="Permanently delete all trashed files">
1028
+ <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1029
+ <polyline points="3 6 5 6 21 6"/>
1030
+ <path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
1031
+ <path d="M10 11v6"/><path d="M14 11v6"/>
1032
+ <path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/>
1033
+ </svg>
1034
+ <span data-i18n="trash.emptyAll">Empty all</span>
1035
+ </button>
1036
+ </div>
1037
+ </div>
1028
1038
 
1029
- <div id="trash-tab-session" class="trash-tab-content">
1030
- <div id="trash-session-list"></div>
1039
+ <div id="trash-tab-file" class="trash-tab-content" style="display:none">
1040
+ <div id="trash-list"></div>
1041
+ </div>
1042
+
1043
+ <div id="trash-tab-session" class="trash-tab-content">
1044
+ <div id="trash-session-list"></div>
1045
+ </div>
1046
+ </div>
1031
1047
  </div>
1032
1048
  </div>
1033
- </div>
1034
1049
 
1035
1050
  <!-- ── BACKUP PANEL — auto/manual backup of ~/.clacky (moved out of Settings) ── -->
1036
1051
  <div id="backup-panel" class="dm-view" style="display:none">
@@ -1339,16 +1354,16 @@
1339
1354
  <span data-i18n="settings.accentColor.title">Accent Color</span>
1340
1355
  </div>
1341
1356
  <div class="settings-accent-swatches">
1342
- <button class="settings-accent-swatch swatch-indigo" data-color="#4f46e5" title="Indigo"></button>
1343
- <button class="settings-accent-swatch swatch-aurora-blue" data-color="#3B82F6" title="Aurora Blue"></button>
1344
- <button class="settings-accent-swatch swatch-forest-green" data-color="#10B981" title="Forest Green"></button>
1345
- <button class="settings-accent-swatch swatch-sunrise-orange" data-color="#F59E0B" title="Sunrise Orange"></button>
1346
- <button class="settings-accent-swatch swatch-rose-violet" data-color="#8B5CF6" title="Rose Violet"></button>
1347
- <button class="settings-accent-swatch swatch-coral-red" data-color="#EF4444" title="Coral Red"></button>
1348
- <button class="settings-accent-swatch swatch-sky-blue" data-color="#38BDF8" title="Sky Blue"></button>
1349
- <button class="settings-accent-swatch swatch-hot-pink" data-color="#EC4899" title="Hot Pink"></button>
1350
- <button class="settings-accent-swatch swatch-warm-brown" data-color="#92745A" title="Warm Brown"></button>
1351
- <button class="settings-accent-swatch swatch-slate-gray" data-color="#6B7280" title="Slate Gray"></button>
1357
+ <button class="settings-accent-swatch swatch-indigo" data-color="#4f46e5" title="Indigo" data-i18n-title="tooltip.swatch.indigo"></button>
1358
+ <button class="settings-accent-swatch swatch-aurora-blue" data-color="#3B82F6" title="Aurora Blue" data-i18n-title="tooltip.swatch.auroraBlue"></button>
1359
+ <button class="settings-accent-swatch swatch-forest-green" data-color="#10B981" title="Forest Green" data-i18n-title="tooltip.swatch.forestGreen"></button>
1360
+ <button class="settings-accent-swatch swatch-sunrise-orange" data-color="#F59E0B" title="Sunrise Orange" data-i18n-title="tooltip.swatch.sunriseOrange"></button>
1361
+ <button class="settings-accent-swatch swatch-rose-violet" data-color="#8B5CF6" title="Rose Violet" data-i18n-title="tooltip.swatch.roseViolet"></button>
1362
+ <button class="settings-accent-swatch swatch-coral-red" data-color="#EF4444" title="Coral Red" data-i18n-title="tooltip.swatch.coralRed"></button>
1363
+ <button class="settings-accent-swatch swatch-sky-blue" data-color="#38BDF8" title="Sky Blue" data-i18n-title="tooltip.swatch.skyBlue"></button>
1364
+ <button class="settings-accent-swatch swatch-hot-pink" data-color="#EC4899" title="Hot Pink" data-i18n-title="tooltip.swatch.hotPink"></button>
1365
+ <button class="settings-accent-swatch swatch-warm-brown" data-color="#92745A" title="Warm Brown" data-i18n-title="tooltip.swatch.warmBrown"></button>
1366
+ <button class="settings-accent-swatch swatch-slate-gray" data-color="#6B7280" title="Slate Gray" data-i18n-title="tooltip.swatch.slateGray"></button>
1352
1367
  </div>
1353
1368
  </section>
1354
1369
  </div>
@@ -1520,7 +1535,7 @@
1520
1535
 
1521
1536
  <!-- Support QR code (shown when support_qr_url is available) -->
1522
1537
  <div id="brand-support-qr" class="brand-support-qr" style="display:none">
1523
- <button class="brand-support-qr-btn" id="brand-support-qr-btn" title="Click to enlarge" aria-label="View QR code larger">
1538
+ <button class="brand-support-qr-btn" id="brand-support-qr-btn" title="Click to enlarge" data-i18n-title="tooltip.enlargeQr" aria-label="View QR code larger">
1524
1539
  <img id="brand-support-qr-img" src="" alt="Support QR Code" class="brand-support-qr-img">
1525
1540
  <span class="brand-support-qr-zoom-hint">
1526
1541
  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg>
@@ -1664,7 +1679,7 @@
1664
1679
  </span>
1665
1680
  <div class="field-input-row">
1666
1681
  <input type="password" id="model-modal-apikey" class="field-input api-key-input" placeholder="sk-..." autocomplete="off">
1667
- <button class="btn-toggle-key" id="model-modal-toggle-key" type="button" title="Show/hide key">
1682
+ <button class="btn-toggle-key" id="model-modal-toggle-key" type="button" title="Show/hide key" data-i18n-title="tooltip.toggleKey">
1668
1683
  <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1669
1684
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"></path>
1670
1685
  </svg>
@@ -1880,7 +1895,7 @@
1880
1895
  </label>
1881
1896
  <div class="setup-input-row">
1882
1897
  <input id="setup-api-key" type="password" class="setup-input" data-i18n-placeholder="settings.models.placeholder.apikey" placeholder="sk-…">
1883
- <button id="setup-toggle-key" class="btn-toggle-key" title="Show/hide">
1898
+ <button id="setup-toggle-key" class="btn-toggle-key" title="Show/hide" data-i18n-title="tooltip.toggleKey">
1884
1899
  <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1885
1900
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
1886
1901
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
@@ -1963,6 +1978,7 @@
1963
1978
 
1964
1979
  <script src="/vendor/codemirror/codemirror.min.js"></script>
1965
1980
  <script src="/components/code-editor.js"></script>
1981
+ <script src="/components/image-zoom.js"></script>
1966
1982
  <script src="/vendor/marked/marked.min.js"></script>
1967
1983
  <script src="/vendor/hljs/highlight.min.js"></script>
1968
1984
  <script src="/vendor/katex/katex.min.js"></script>