openclacky 1.5.19 → 1.5.21

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -0
  3. data/README.md +19 -1
  4. data/README_CN.md +1 -1
  5. data/README_JA.md +1 -1
  6. data/lib/clacky/agent/chunk_index.rb +8 -1
  7. data/lib/clacky/agent/feedback.rb +30 -0
  8. data/lib/clacky/agent/history_navigation.rb +17 -3
  9. data/lib/clacky/agent/hook_manager.rb +6 -1
  10. data/lib/clacky/agent/llm_caller.rb +17 -3
  11. data/lib/clacky/agent/message_compressor_helper.rb +36 -2
  12. data/lib/clacky/agent/session_serializer.rb +45 -4
  13. data/lib/clacky/agent.rb +135 -55
  14. data/lib/clacky/agent_config.rb +82 -4
  15. data/lib/clacky/billing/platform_billing.rb +10 -5
  16. data/lib/clacky/brand_config.rb +1 -1
  17. data/lib/clacky/cli.rb +5 -4
  18. data/lib/clacky/client.rb +12 -5
  19. data/lib/clacky/deepseek_web_tools.rb +156 -0
  20. data/lib/clacky/default_extensions/ext-studio/api/handler.rb +8 -0
  21. data/lib/clacky/default_extensions/ext-studio/panels/studio/view.js +97 -20
  22. data/lib/clacky/default_extensions/time_machine/panels/time_machine/view.js +1 -0
  23. data/lib/clacky/default_skills/onboard/SKILL.md +1 -1
  24. data/lib/clacky/extension/loader.rb +5 -3
  25. data/lib/clacky/locales/en.rb +5 -5
  26. data/lib/clacky/locales/zh.rb +5 -5
  27. data/lib/clacky/message_format/anthropic.rb +20 -0
  28. data/lib/clacky/message_format/open_ai.rb +31 -14
  29. data/lib/clacky/message_history.rb +45 -4
  30. data/lib/clacky/platform_http_client.rb +6 -2
  31. data/lib/clacky/providers.rb +38 -138
  32. data/lib/clacky/search_config.rb +47 -13
  33. data/lib/clacky/server/browser_manager.rb +35 -5
  34. data/lib/clacky/server/channel/channel_manager.rb +6 -6
  35. data/lib/clacky/server/discover.rb +5 -4
  36. data/lib/clacky/server/http_server.rb +285 -53
  37. data/lib/clacky/server/model_prices.rb +10 -5
  38. data/lib/clacky/server/pid_files.rb +25 -0
  39. data/lib/clacky/server/server_master.rb +9 -3
  40. data/lib/clacky/server/session_registry.rb +37 -7
  41. data/lib/clacky/server/web_ui_controller.rb +72 -0
  42. data/lib/clacky/session_manager.rb +28 -6
  43. data/lib/clacky/skill.rb +1 -1
  44. data/lib/clacky/tools/ask_user.rb +4 -1
  45. data/lib/clacky/tools/base.rb +3 -2
  46. data/lib/clacky/tools/browser.rb +18 -2
  47. data/lib/clacky/tools/file_reader.rb +1 -1
  48. data/lib/clacky/tools/terminal/session_manager.rb +19 -1
  49. data/lib/clacky/tools/terminal.rb +65 -23
  50. data/lib/clacky/tools/trash_manager.rb +5 -3
  51. data/lib/clacky/tools/web_fetch.rb +81 -22
  52. data/lib/clacky/tools/web_search.rb +45 -4
  53. data/lib/clacky/ui2/ui_controller.rb +1 -1
  54. data/lib/clacky/ui_interface.rb +4 -3
  55. data/lib/clacky/utils/file_processor.rb +51 -0
  56. data/lib/clacky/utils/model_pricing.rb +242 -39
  57. data/lib/clacky/version.rb +1 -1
  58. data/lib/clacky/web/app.css +1158 -249
  59. data/lib/clacky/web/app.js +82 -13
  60. data/lib/clacky/web/components/chat-navigator.js +8 -1
  61. data/lib/clacky/web/components/code-editor.js +6 -2
  62. data/lib/clacky/web/components/mentions.js +2 -13
  63. data/lib/clacky/web/components/model-picker.js +92 -97
  64. data/lib/clacky/web/components/onboard.js +13 -10
  65. data/lib/clacky/web/components/sidebar.js +6 -2
  66. data/lib/clacky/web/features/archive/store.js +196 -0
  67. data/lib/clacky/web/features/archive/view.js +409 -0
  68. data/lib/clacky/web/features/backup/view.js +17 -7
  69. data/lib/clacky/web/features/billing/view.js +84 -10
  70. data/lib/clacky/web/features/channels/view.js +75 -29
  71. data/lib/clacky/web/features/new-session/store.js +3 -3
  72. data/lib/clacky/web/features/new-session/view.js +1 -0
  73. data/lib/clacky/web/features/trash/store.js +14 -11
  74. data/lib/clacky/web/features/trash/view.js +66 -13
  75. data/lib/clacky/web/features/workspace/view.js +421 -16
  76. data/lib/clacky/web/i18n.js +242 -70
  77. data/lib/clacky/web/index.html +270 -117
  78. data/lib/clacky/web/projects.js +56 -1
  79. data/lib/clacky/web/sessions.js +609 -267
  80. data/lib/clacky/web/settings.js +186 -32
  81. data/lib/clacky/web/ws-dispatcher.js +33 -21
  82. data/lib/clacky.rb +4 -2
  83. metadata +6 -1
@@ -58,6 +58,9 @@
58
58
  title="Creator / Owner" data-i18n-title="header.owner.tooltip">OWNER</button>
59
59
  </div>
60
60
  </div>
61
+ <!-- Active session title, aligned to the content column (right of the
62
+ sidebar divider). Filled by Sessions.updateChatHeader(). -->
63
+ <div id="header-session-title" hidden></div>
61
64
  <div id="header-right">
62
65
  <span id="ext-slot-header-right" data-slot="header.right"></span>
63
66
 
@@ -80,17 +83,20 @@
80
83
  <div class="cmd-palette" role="dialog" aria-modal="true" aria-label="Search sessions">
81
84
  <div class="search-panel-card">
82
85
  <!-- Input row -->
83
- <div class="search-input-row">
84
- <span class="search-icon">
85
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="20" y1="20" x2="16" y2="16"/></svg>
86
- </span>
87
- <input id="session-search-q" type="text" class="search-input"
88
- data-i18n-placeholder="sessions.search.placeholder" placeholder="Search sessions…"
89
- autocomplete="off" />
90
- <button id="btn-search-q-clear" class="btn-search-q-clear" aria-label="Clear text" hidden>
91
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
86
+ <div class="search-input-wrap">
87
+ <div class="search-input-row">
88
+ <span class="search-icon">
89
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="20" y1="20" x2="16" y2="16"/></svg>
90
+ </span>
91
+ <input id="session-search-q" type="text" class="search-input"
92
+ data-i18n-placeholder="sessions.search.placeholder" placeholder="Search sessions…"
93
+ autocomplete="off" />
94
+ <button id="btn-search-q-clear" class="btn-search-q-clear" type="button"
95
+ data-i18n="sessions.search.clear" aria-label="Clear text" hidden>Clear</button>
96
+ </div>
97
+ <button id="btn-session-search-close" class="cmd-palette-close" type="button" aria-label="Close">
98
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
92
99
  </button>
93
- <button id="btn-session-search-close" class="cmd-palette-esc" type="button" aria-label="Close">ESC</button>
94
100
  </div>
95
101
  <!-- Filter row -->
96
102
  <div class="search-filter-row">
@@ -112,7 +118,7 @@
112
118
  </div>
113
119
  <div class="search-date-wrap">
114
120
  <button id="session-search-date" class="search-date datepicker-trigger" type="button" data-value="" data-i18n="sessions.search.datePlaceholder"></button>
115
- <svg class="search-date-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M16 3v4M8 3v4M3 10h18"/></svg>
121
+ <svg class="search-date-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5.5" width="18" height="15.5" rx="2.5"/><path d="M8 2.75v3.5M16 2.75v3.5M3 10h18"/></svg>
116
122
  </div>
117
123
  <button id="btn-search-clear-all" class="btn-search-clear-all" aria-label="Clear filters" hidden>
118
124
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
@@ -305,15 +311,17 @@
305
311
  Kept as a hidden placeholder so any legacy CSS selector that
306
312
  targets this id still resolves harmlessly. -->
307
313
  </div>
308
- <div id="trash-sidebar-item" class="task-item task-item-summary">
314
+ <!-- Data management: one page holding the archive / recycle bin /
315
+ backup tabs. One rail entry keeps Billing on screen. -->
316
+ <div id="data-management-sidebar-item" class="task-item task-item-summary">
309
317
  <div class="task-row">
310
318
  <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="task-icon">
311
- <rect x="2" y="3" width="20" height="5" rx="1"/>
312
- <path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/>
313
- <path d="M10 12h4"/>
319
+ <ellipse cx="12" cy="5" rx="9" ry="3"/>
320
+ <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>
321
+ <path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"/>
314
322
  </svg>
315
323
  <div class="task-info">
316
- <span class="task-name" id="trash-sidebar-label" data-i18n="sidebar.trash">File Recall</span>
324
+ <span class="task-name" id="data-management-label" data-i18n="sidebar.dataManagement">Data</span>
317
325
  </div>
318
326
  </div>
319
327
  </div>
@@ -487,11 +495,9 @@
487
495
  </div>
488
496
  <!-- Composer slot: agent-scoped controls above the session info bar. -->
489
497
  <div id="ext-slot-session-composer" class="session-composer" data-slot="session.composer"></div>
490
- <!-- Live todo/task list panel (driven by todo_update WS events) -->
491
- <div id="todo-panel" class="todo-panel" style="display:none"></div>
492
498
  <!-- Session info bar — mirrors CLI bottom status bar -->
493
499
  <div id="session-info-bar" style="display:none">
494
- <!-- Order: status | id | dir | model | mode | tasks | cost -->
500
+ <!-- Order: status | id | dir | model | reasoning | mode | todo | signal | cost -->
495
501
  <!-- Pattern: element + separator-after-element (except last) -->
496
502
  <span id="sib-status"></span>
497
503
  <span class="sib-sep sib-sep-after-status">│</span>
@@ -512,7 +518,47 @@
512
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>
513
519
  <div id="sib-reasoning-dropdown" class="clacky-popover sib-reasoning-dropdown" style="display:none" role="menu"></div>
514
520
  </span>
515
- <span class="sib-sep sib-sep-after-reasoning">│</span>
521
+ <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>
523
+ <div id="sib-mode-menu" class="clacky-popover" role="menu" hidden>
524
+ <button type="button" role="menuitemradio" data-permission-mode="confirm_all" aria-checked="true">
525
+ <strong data-i18n="sib.mode.confirm_all">Manual</strong>
526
+ <small data-i18n="sib.mode.manualHelp">Confirm actions; wait for your answer.</small>
527
+ </button>
528
+ <button type="button" role="menuitemradio" data-permission-mode="auto_approve" aria-checked="false">
529
+ <strong data-i18n="sib.mode.auto_approve">Auto</strong>
530
+ <small data-i18n="sib.mode.autoHelp">Approve tools automatically; continue after the question countdown.</small>
531
+ </button>
532
+ </div>
533
+ </span>
534
+ <span class="sib-sep sib-sep-after-mode">│</span>
535
+ <span id="todo-panel" class="todo-panel">
536
+ <button id="todo-trigger" class="todo-trigger" type="button"
537
+ aria-controls="todo-popover" aria-expanded="false" disabled>
538
+ <svg class="todo-status-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
539
+ <circle cx="3" cy="4" r="1"/><path d="M6 4h7"/>
540
+ <circle cx="3" cy="8" r="1"/><path d="M6 8h7"/>
541
+ <circle cx="3" cy="12" r="1"/><path d="M6 12h7"/>
542
+ </svg>
543
+ <span class="todo-trigger-detail" aria-hidden="true">
544
+ <span id="todo-count" class="todo-count"></span>
545
+ <svg class="todo-caret" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 10l4-4 4 4"/></svg>
546
+ </span>
547
+ </button>
548
+ <div id="todo-popover" class="clacky-popover todo-popover" role="dialog" hidden>
549
+ <div class="todo-popover-header">
550
+ <div class="todo-popover-heading">
551
+ <div class="todo-popover-title" data-i18n="chat.todo.title">Tasks</div>
552
+ <div id="todo-summary" class="todo-summary"></div>
553
+ </div>
554
+ <button id="todo-close" class="todo-close" type="button" aria-label="Close task list">
555
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>
556
+ </button>
557
+ </div>
558
+ <div id="todo-list" class="todo-list" aria-live="polite"></div>
559
+ </div>
560
+ </span>
561
+ <span class="sib-sep sib-sep-after-todo">│</span>
516
562
  <!-- Latency signal: 4-bar signal + TTFT number. Hidden until the first LLM
517
563
  call completes (see updateInfoBar / Sessions.renderSignalBars). Click
518
564
  opens a mini benchmark panel (see Step 3/4 — not yet implemented). -->
@@ -523,14 +569,7 @@
523
569
  </span>
524
570
  </span>
525
571
  <span class="sib-sep sib-sep-after-signal" style="display:none">│</span>
526
- <!-- Detail fields: mode, tasks, cost -->
527
- <span class="sib-detail">
528
- <span id="sib-mode"></span>
529
- <span class="sib-sep sib-sep-after-mode">│</span>
530
- <span id="sib-tasks"></span>
531
- <span class="sib-sep sib-sep-after-tasks">│</span>
532
- <span id="sib-cost"></span>
533
- </span>
572
+ <span id="sib-cost"></span>
534
573
  </div>
535
574
 
536
575
  <!-- Composer slot: moved above the session info bar. -->
@@ -613,11 +652,11 @@
613
652
  itself is rendered by Clacky.ext inside the slot below). -->
614
653
  <div class="aside-tabbar-actions">
615
654
  <button id="btn-aside-fullscreen" class="session-aside-fullscreen" data-i18n-title="aside.fullscreen" title="Fullscreen">
616
- <svg class="icon-fs-enter" 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"><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>
617
- <svg class="icon-fs-exit" 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"><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>
655
+ <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
+ <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>
618
657
  </button>
619
658
  <button id="btn-aside-collapse" class="session-aside-collapse" data-i18n-title="aside.collapse" title="Collapse">
620
- <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"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/><path d="m14 9 3 3-3 3"/></svg>
659
+ <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>
621
660
  </button>
622
661
  </div>
623
662
  <div id="ext-slot-session-aside" class="session-aside-slot" data-slot="session.aside"></div>
@@ -818,30 +857,122 @@
818
857
  <div id="extensions-detail" class="extension-detail" style="display:none"></div>
819
858
  </div>
820
859
 
821
- <!-- ── TRASH PANEL — Recently deleted files across all projects ─── -->
822
- <div id="trash-panel" style="display:none">
823
- <div id="trash-body">
860
+ <!-- ── DATA MANAGEMENT PANEL — one page, three tabs ──────────────────
861
+ Archived sessions / recycle bin / backup used to be three top-level
862
+ panels. They now share one page: the tab bar owns the naming, each
863
+ tab keeps its own panel element so every module still owns exactly
864
+ one body to render into. ── -->
865
+ <div id="data-management-panel" style="display:none">
866
+ <!-- Title and description mirror the Assistant Memory page: the rail entry
867
+ label doubles as the page title, the tabs sit right below. -->
868
+ <div id="data-management-header">
824
869
  <div class="channels-page-header">
825
870
  <div class="channels-page-header-main">
826
- <h2 class="channels-page-title page-title" data-i18n="trash.title">File Recall</h2>
827
- <p class="channels-page-subtitle" data-i18n="trash.subtitle">Files the agent moved to trash across all projects. Recall them back to where they were, or clear the ones you don't need.</p>
871
+ <h2 class="channels-page-title page-title" data-i18n="dataManagement.title">Data</h2>
872
+ <p class="channels-page-subtitle" data-i18n="dataManagement.subtitle">Archiving only hides a session from the sidebar, recycled files can be restored to where they were, and a backup can move your whole ~/.clacky to another machine.</p>
873
+ </div>
874
+ </div>
875
+ </div>
876
+ <div id="data-management-tabs" class="page-tabs" role="tablist">
877
+ <button type="button" class="page-tab active" role="tab" aria-selected="true"
878
+ data-dm-tab="archive" id="tab-dm-archive" aria-controls="archive-panel" data-i18n="archive.title">Archived sessions</button>
879
+ <button type="button" class="page-tab" role="tab" aria-selected="false"
880
+ data-dm-tab="trash" id="tab-dm-trash" aria-controls="trash-panel" data-i18n="trash.title">Recycle Bin</button>
881
+ <button type="button" class="page-tab" role="tab" aria-selected="false"
882
+ data-dm-tab="backup" id="tab-dm-backup" aria-controls="backup-panel" data-i18n="backup.title">Data backup</button>
883
+ </div>
884
+
885
+ <!-- ── ARCHIVE PANEL — chats the user archived: off the rail, still on disk ── -->
886
+ <div id="archive-panel" class="dm-view" style="display:none">
887
+ <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>
925
+ </div>
828
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>
829
939
  </div>
830
940
 
831
- <div id="trash-tabs" class="page-tabs">
832
- <div class="trash-tabs-left">
833
- <button class="trash-tab page-tab active" data-tab="file-trash" id="tab-file-trash" data-i18n="trash.tabFile">文件回收</button>
834
- <button class="trash-tab page-tab" data-tab="session-trash" id="tab-session-trash" data-i18n="trash.tabSession">会话回收</button>
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
+
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>
835
954
  </div>
836
955
  </div>
837
956
 
838
- <p class="trash-session-hint" id="trash-session-hint" style="display:none" data-i18n="trash.sessionAutoCleanHint">The system keeps the most recent 200 sessions; older ones are moved here.</p>
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>
839
958
 
840
959
  <div class="trash-toolbar">
841
- <div class="trash-filter-bar" id="trash-filter-bar" style="display:none">
842
- <button class="trash-filter-chip active" data-filter="all" data-i18n="trash.filterAll">All</button>
843
- <button class="trash-filter-chip" data-filter="manual" data-i18n="trash.filterManual">Regular</button>
844
- <button class="trash-filter-chip" data-filter="cron" data-i18n="trash.filterCron">Scheduled</button>
960
+ <div class="trash-filter-bar" id="trash-filter-bar">
961
+ <div class="trash-filter-project-wrap">
962
+ <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"/>
965
+ </svg>
966
+ <div class="custom-select-wrapper" id="trash-filter-source">
967
+ <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>
969
+ <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
970
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
971
+ </svg>
972
+ </div>
973
+ <div class="custom-select-dropdown"></div>
974
+ </div>
975
+ </div>
845
976
  <div class="trash-filter-project-wrap" id="trash-filter-project-wrap">
846
977
  <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">
847
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"/>
@@ -872,7 +1003,7 @@
872
1003
  </svg>
873
1004
  <span data-i18n="trash.emptyOld">Empty older than 7 days</span>
874
1005
  </button>
875
- <button id="btn-trash-empty-orphans" class="btn-trash-action btn-trash-danger" data-i18n-title="trash.emptyOrphans.tooltip" title="Permanently delete entries whose original project directory no longer exists (e.g. test temp dirs)">
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)">
876
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">
877
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"/>
878
1009
  <line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
@@ -891,16 +1022,72 @@
891
1022
  </div>
892
1023
  </div>
893
1024
 
894
- <div id="trash-tab-file" class="trash-tab-content">
1025
+ <div id="trash-tab-file" class="trash-tab-content" style="display:none">
895
1026
  <div id="trash-list"></div>
896
1027
  </div>
897
1028
 
898
- <div id="trash-tab-session" class="trash-tab-content" style="display:none">
1029
+ <div id="trash-tab-session" class="trash-tab-content">
899
1030
  <div id="trash-session-list"></div>
900
1031
  </div>
901
1032
  </div>
902
1033
  </div>
903
1034
 
1035
+ <!-- ── BACKUP PANEL — auto/manual backup of ~/.clacky (moved out of Settings) ── -->
1036
+ <div id="backup-panel" class="dm-view" style="display:none">
1037
+ <div id="backup-body">
1038
+ <div id="backup-content">
1039
+
1040
+ <!-- 自动备份 -->
1041
+ <section class="settings-section" id="backup-section">
1042
+ <div class="settings-section-title">
1043
+ <span data-i18n="settings.backup.autoTitle">Auto Backup</span>
1044
+ </div>
1045
+ <p class="settings-section-desc" data-i18n="settings.backup.desc">Back up your ~/.clacky directory (config, skills, memories, tasks, sessions). Regenerable caches and logs are excluded.</p>
1046
+
1047
+ <div class="backup-auto-card">
1048
+ <div class="backup-auto-row">
1049
+ <label class="toggle-switch">
1050
+ <input type="checkbox" id="backup-auto-toggle">
1051
+ <span class="toggle-slider"></span>
1052
+ </label>
1053
+ <span class="backup-auto-label" data-i18n="settings.backup.autoLabel">Automatic backup</span>
1054
+ <span class="backup-auto-hint" data-i18n="settings.backup.autoHint">Daily at 03:00, keeps the latest 7</span>
1055
+ </div>
1056
+ <div class="backup-dest-row">
1057
+ <span class="backup-dest-label" data-i18n="settings.backup.destLabel">Backup folder</span>
1058
+ <span class="backup-dest-path" id="backup-dest-path">—</span>
1059
+ <button id="btn-backup-open-folder" class="btn-backup-action" data-i18n="settings.backup.openFolder">Open</button>
1060
+ </div>
1061
+ <div id="backup-status" class="model-test-result"></div>
1062
+ </div>
1063
+ <label class="backup-option">
1064
+ <input type="checkbox" id="backup-include-sessions">
1065
+ <span data-i18n="settings.backup.includeSessions">Include session history (larger archive)</span>
1066
+ </label>
1067
+ </section>
1068
+
1069
+ <!-- 手动备份 -->
1070
+ <section class="settings-section">
1071
+ <div class="settings-section-title">
1072
+ <span data-i18n="settings.backup.manualTitle">Manual Backup</span>
1073
+ </div>
1074
+
1075
+ <div class="backup-actions">
1076
+ <button id="btn-backup-now" class="btn-backup-action" data-i18n="settings.backup.runNow">Download backup</button>
1077
+ <label class="btn-backup-action">
1078
+ <span data-i18n="settings.backup.restoreBtn">Restore backup</span>
1079
+ <input type="file" id="input-backup-restore" accept=".tar.gz,.gz" style="display:none">
1080
+ </label>
1081
+ <span id="backup-manual-status" class="model-test-result"></span>
1082
+ </div>
1083
+ </section>
1084
+
1085
+ </div>
1086
+ </div>
1087
+ </div>
1088
+ </div>
1089
+ <!-- /data-management-panel -->
1090
+
904
1091
  <!-- ── PROFILE PANEL — "Assistant Memory": a 3-tab window into the agent's inner state.
905
1092
  All mutations happen through sessions (never in-browser editors):
906
1093
  SOUL tab → [让助理整理性格] → /onboard scope:soul
@@ -1006,7 +1193,6 @@
1006
1193
  <button class="settings-tab page-tab active" data-tab="models" data-i18n="settings.tabs.models">Models</button>
1007
1194
  <button class="settings-tab page-tab" data-tab="ui" data-i18n="settings.tabs.ui">UI</button>
1008
1195
  <button class="settings-tab page-tab" data-tab="general" data-i18n="settings.tabs.general">General</button>
1009
- <button class="settings-tab page-tab" data-tab="data" data-i18n="settings.tabs.data">Data</button>
1010
1196
  <!-- Extension tab slot: extensions add custom settings tabs here (button needs data-tab="<id>"). -->
1011
1197
  <span id="ext-slot-settings-tabs" data-slot="settings.tabs"></span>
1012
1198
  <button class="settings-tab page-tab" data-tab="about" data-i18n="settings.tabs.about">About</button>
@@ -1195,6 +1381,20 @@
1195
1381
  <button id="btn-browser-setup" class="btn-settings-action" data-i18n="settings.browser.btn">🌐 Configure Browser</button>
1196
1382
  </div>
1197
1383
  </div>
1384
+ <div class="settings-screenshot" id="browser-screenshot-settings" style="display:none">
1385
+ <div class="settings-screenshot-head">
1386
+ <span class="settings-screenshot-title" data-i18n="settings.browser.screenshot.title">Screenshot quality</span>
1387
+ <p class="settings-screenshot-desc" data-i18n="settings.browser.screenshot.desc">When the AI browses a web page it takes screenshots to "see" it. Higher quality looks clearer, but each screenshot takes up more of the conversation — long tasks can end up slower and more expensive.</p>
1388
+ </div>
1389
+ <div class="settings-screenshot-row">
1390
+ <span class="settings-screenshot-label" data-i18n="settings.browser.screenshot.quality">Quality</span>
1391
+ <div class="settings-segmented" id="browser-screenshot-quality">
1392
+ <button type="button" class="settings-segmented-btn" data-bytes="150000" data-i18n="settings.browser.screenshot.standard">Standard</button>
1393
+ <button type="button" class="settings-segmented-btn" data-bytes="300000" data-i18n="settings.browser.screenshot.high">High</button>
1394
+ </div>
1395
+ </div>
1396
+ <p class="settings-screenshot-hint" data-i18n="settings.browser.screenshot.qualityHint">Standard is enough for most pages and saves space. High keeps more detail on long pages.</p>
1397
+ </div>
1198
1398
  </section>
1199
1399
 
1200
1400
  <!-- Network / Proxy section -->
@@ -1222,24 +1422,24 @@
1222
1422
  <span data-i18n="settings.search.title">Web Search</span>
1223
1423
  </div>
1224
1424
  <div class="settings-network">
1225
- <p class="settings-network-desc" data-i18n="settings.search.desc">Free built-in search uses Parallel, DuckDuckGo, and Bing with no key required. Select a search provider to use a configured API instead.</p>
1425
+ <p class="settings-network-desc" data-i18n="settings.search.desc">The agent searches the web and fetches page content automatically when it needs up-to-date information — news, docs, prices, time-sensitive data.</p>
1226
1426
  <div class="settings-network-url">
1227
1427
  <label class="settings-network-url-label" for="settings-search-provider-trigger" data-i18n="settings.search.provider">Provider</label>
1228
1428
  <div class="settings-network-url-row">
1229
1429
  <div class="custom-select-wrapper" id="settings-search-provider-wrapper">
1230
1430
  <div class="custom-select-trigger" tabindex="0" id="settings-search-provider-trigger">
1231
- <span class="custom-select-value placeholder" id="settings-search-provider-value" data-i18n="settings.search.builtin">Built-in (Parallel / DuckDuckGo / Bing)</span>
1431
+ <span class="custom-select-value placeholder" id="settings-search-provider-value" data-i18n="settings.search.builtin">Free (auto-selects a working engine)</span>
1232
1432
  <svg class="custom-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1233
1433
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
1234
1434
  </svg>
1235
1435
  </div>
1236
1436
  <div class="custom-select-dropdown" id="settings-search-provider-dropdown">
1237
- <div class="custom-select-option" data-value="" data-i18n="settings.search.builtin">Built-in (Parallel / DuckDuckGo / Bing)</div>
1437
+ <div class="custom-select-option" data-value="" data-i18n="settings.search.builtin">Free (auto-selects a working engine)</div>
1438
+ <div class="custom-select-option" data-value="deepseek_web" data-i18n="settings.search.deepseek">DeepSeek (search &amp; page fetch)</div>
1238
1439
  </div>
1239
1440
  </div>
1240
1441
  <button type="button" id="btn-save-search" class="btn-settings-action" data-i18n="settings.search.save">Save</button>
1241
1442
  </div>
1242
- <div id="settings-search-status" class="model-test-result"></div>
1243
1443
  </div>
1244
1444
  <div class="settings-network-url" id="search-key-wrap" style="display:none">
1245
1445
  <label class="settings-network-url-label" for="settings-search-key" data-i18n="settings.search.key">API Key</label>
@@ -1247,15 +1447,17 @@
1247
1447
  <input type="password" id="settings-search-key" class="field-input" placeholder="tvly-..." autocomplete="off" spellcheck="false">
1248
1448
  <button type="button" id="btn-test-search" class="btn-settings-action" data-i18n="settings.search.test">Test</button>
1249
1449
  </div>
1450
+ <p class="settings-network-note" id="search-deepseek-hint" data-i18n="settings.search.deepseekHintFree" style="display:none">Leave the API Key empty to reuse your configured model key; accepts DeepSeek and OpenClacky provider keys. Per-call billing starts Nov 1, 2026 00:00 (Beijing time) at about ¥0.005 per call.</p>
1451
+ </div>
1452
+ <p class="settings-network-note" id="search-builtin-note" data-i18n="settings.search.builtinEngines">Tries Parallel → DuckDuckGo → Bing in order. No key or configuration needed.</p>
1453
+ <div id="settings-search-status" class="model-test-result"></div>
1454
+ <div class="settings-network-url-row settings-network-divider" id="custom-searcher-row">
1455
+ <span class="settings-network-note" data-i18n="settings.search.customHint">Need another search provider? Put a script in ~/.clacky/searchers/, see tavily.rb.</span>
1456
+ <button type="button" id="btn-custom-searcher" class="btn-settings-action" data-i18n="settings.search.customBtn">Build with Agent</button>
1250
1457
  </div>
1251
- <p class="settings-network-desc" data-i18n="settings.search.custom">Add your own provider by dropping a script into ~/.clacky/searchers/ — see tavily.rb for the interface.</p>
1252
1458
  </div>
1253
1459
  </section>
1254
1460
 
1255
- <!-- Backup section -->
1256
- <section class="settings-section" id="backup-section" style="display:none">
1257
- </section>
1258
-
1259
1461
  <!-- Brand & License section -->
1260
1462
  <section class="settings-section" id="brand-license-section">
1261
1463
  <div class="settings-section-title">
@@ -1292,7 +1494,10 @@
1292
1494
  </div>
1293
1495
  <div class="brand-status-row">
1294
1496
  <span class="brand-status-label" data-i18n="settings.brand.label.status">Status</span>
1295
- <span class="brand-status-value" id="brand-status-badge">—</span>
1497
+ <span class="brand-status-state">
1498
+ <span class="brand-status-value" id="brand-status-badge">—</span>
1499
+ <span class="brand-status-hint" id="brand-status-hint" style="display:none"></span>
1500
+ </span>
1296
1501
  </div>
1297
1502
  <div class="brand-status-row">
1298
1503
  <span class="brand-status-label" data-i18n="settings.brand.label.expires">Expires</span>
@@ -1330,7 +1535,7 @@
1330
1535
  <div class="qr-lightbox-backdrop" id="qr-lightbox-backdrop"></div>
1331
1536
  <div class="qr-lightbox-content">
1332
1537
  <img id="qr-lightbox-img" src="" alt="Support QR Code" class="qr-lightbox-img">
1333
- <p class="qr-lightbox-label" id="qr-lightbox-label">Tech Support</p>
1538
+ <p class="qr-lightbox-label" id="qr-lightbox-label" data-i18n="settings.brand.label.supportQr">Tech Support</p>
1334
1539
  <p class="qr-lightbox-hint" data-i18n="settings.brand.label.qrHint">Scan with your phone camera</p>
1335
1540
  <button class="qr-lightbox-close" id="qr-lightbox-close" aria-label="Close">
1336
1541
  <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"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
@@ -1364,56 +1569,6 @@
1364
1569
  </section>
1365
1570
  </div><!-- end Tab: General -->
1366
1571
 
1367
- <!-- ══ Tab: Data ══ -->
1368
- <div class="settings-tab-content" data-tab-content="data" style="display:none">
1369
-
1370
- <!-- 自动备份 -->
1371
- <section class="settings-section">
1372
- <div class="settings-section-title">
1373
- <span data-i18n="settings.backup.autoTitle">Auto Backup</span>
1374
- </div>
1375
- <p class="settings-section-desc" data-i18n="settings.backup.desc">Back up your ~/.clacky directory (config, skills, memories, tasks, sessions). Regenerable caches and logs are excluded.</p>
1376
-
1377
- <div class="backup-auto-card">
1378
- <div class="backup-auto-row">
1379
- <label class="toggle-switch">
1380
- <input type="checkbox" id="backup-auto-toggle">
1381
- <span class="toggle-slider"></span>
1382
- </label>
1383
- <span class="backup-auto-label" data-i18n="settings.backup.autoLabel">Automatic backup</span>
1384
- <span class="backup-auto-hint" data-i18n="settings.backup.autoHint">Daily at 03:00, keeps the latest 7</span>
1385
- </div>
1386
- <label class="backup-option backup-option-nested">
1387
- <input type="checkbox" id="backup-include-sessions">
1388
- <span data-i18n="settings.backup.includeSessions">Include session history (larger archive)</span>
1389
- </label>
1390
- <div class="backup-dest-row">
1391
- <span class="backup-dest-label" data-i18n="settings.backup.destLabel">Backup folder</span>
1392
- <span class="backup-dest-path" id="backup-dest-path">—</span>
1393
- <button id="btn-backup-open-folder" class="btn-settings-link" data-i18n="settings.backup.openFolder">Open</button>
1394
- </div>
1395
- <div id="backup-status" class="model-test-result"></div>
1396
- </div>
1397
- </section>
1398
-
1399
- <!-- 手动备份 -->
1400
- <section class="settings-section">
1401
- <div class="settings-section-title">
1402
- <span data-i18n="settings.backup.manualTitle">Manual Backup</span>
1403
- </div>
1404
-
1405
- <div class="backup-actions">
1406
- <button id="btn-backup-now" class="btn-settings-action" data-i18n="settings.backup.runNow">Download backup</button>
1407
- <label class="btn-settings-action btn-settings-action--file">
1408
- <span data-i18n="settings.backup.restoreBtn">Restore backup</span>
1409
- <input type="file" id="input-backup-restore" accept=".tar.gz,.gz" style="display:none">
1410
- </label>
1411
- <span id="backup-manual-status" class="model-test-result"></span>
1412
- </div>
1413
- </section>
1414
-
1415
- </div><!-- end Tab: Data -->
1416
-
1417
1572
  <!-- ══ Tab: About ══ -->
1418
1573
  <div class="settings-tab-content" data-tab-content="about" style="display:none">
1419
1574
  <!-- Version section -->
@@ -1633,8 +1788,8 @@
1633
1788
  </div>
1634
1789
  <p class="setup-device-card-lead" data-i18n="onboard.device.card.lead">Sign up and get $1 free credit · no subscription · pay as you go</p>
1635
1790
  <ul class="setup-device-card-points">
1636
- <li data-i18n="onboard.device.card.point1">One key for all frontier models — Claude, Gemini, DeepSeek &amp; more</li>
1637
- <li data-i18n="onboard.device.card.point2">Same pricing as official APIs, switch models instantly</li>
1791
+ <li data-i18n="onboard.device.card.point1">One key for all frontier models — Claude, GPT, DeepSeek &amp; more</li>
1792
+ <li data-i18n="onboard.device.card.point2">Up to 70% off, switch models instantly</li>
1638
1793
  </ul>
1639
1794
  <button id="setup-btn-device-login" class="setup-submit-btn setup-device-btn">
1640
1795
  <span data-i18n="onboard.device.btn">Get started free</span>
@@ -1645,11 +1800,7 @@
1645
1800
  <!-- Pending state: shown while waiting for browser approval -->
1646
1801
  <div id="setup-device-pending" style="display:none">
1647
1802
  <div class="setup-device-spinner"></div>
1648
- <p class="setup-device-pending-text" data-i18n="onboard.device.pending">Waiting for confirmation in your browser…</p>
1649
- <p class="setup-device-code">
1650
- <span data-i18n="onboard.device.code">Verification code:</span>
1651
- <strong id="setup-device-usercode">—</strong>
1652
- </p>
1803
+ <p class="setup-device-pending-text" data-i18n="onboard.device.pending">Finishing the connection in your browser…</p>
1653
1804
  <a id="setup-device-link" href="#" target="_blank" rel="noopener" class="setup-device-reopen"><span data-i18n="onboard.device.reopen">Open browser again</span><svg class="setup-btn-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14"/><path d="M13 6l6 6-6 6"/></svg></a>
1654
1805
  <button id="setup-device-cancel" class="setup-back-btn" data-i18n="onboard.device.cancel">Cancel</button>
1655
1806
  </div>
@@ -1860,6 +2011,8 @@
1860
2011
  <script src="/features/brand/view.js"></script>
1861
2012
  <script src="/features/trash/store.js"></script>
1862
2013
  <script src="/features/trash/view.js"></script>
2014
+ <script src="/features/archive/store.js"></script>
2015
+ <script src="/features/archive/view.js"></script>
1863
2016
  <script src="/features/profile/store.js"></script>
1864
2017
  <script src="/features/profile/view.js"></script>
1865
2018
  <script src="/features/version/store.js"></script>