dsh-claude-style 0.13.2 → 0.14.0-dev.12

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 (93) hide show
  1. package/CHANGELOG.md +182 -0
  2. package/LICENSE +0 -5
  3. package/README.en.md +1 -1
  4. package/README.md +2 -2
  5. package/THIRD_PARTY_NOTICES.md +282 -6
  6. package/docs/FEATURES.en.md +13 -14
  7. package/docs/FEATURES.md +13 -14
  8. package/docs/SETTINGS.en.md +21 -12
  9. package/docs/SETTINGS.md +21 -12
  10. package/docs/STYLE.md +151 -12
  11. package/lib/assets/1952ecd55916.js.br +0 -0
  12. package/lib/assets/3b91bf51db72.js.br +0 -0
  13. package/lib/assets/4ec527e58330.js.br +0 -0
  14. package/lib/assets/7323c8c86470.js.br +0 -0
  15. package/lib/assets/755d09170f37.js.br +0 -0
  16. package/lib/assets/c02a70a798bc.js.br +0 -0
  17. package/lib/assets/d8df7a57fbe3.js.br +0 -0
  18. package/lib/assets/manifest.json +28 -28
  19. package/lib/client.js +11 -8
  20. package/lib/host/brand.js +136 -0
  21. package/lib/host/http.js +74 -0
  22. package/lib/host/peakrate.js +7 -0
  23. package/lib/host/routes.js +26 -88
  24. package/lib/host/search.js +8 -1
  25. package/lib/host/settings.js +5 -0
  26. package/lib/model-descriptions.json +195 -43
  27. package/package.json +12 -4
  28. package/docs/decisions/D11-private-routes.md +0 -26
  29. package/docs/decisions/D12-fail-fast.md +0 -36
  30. package/docs/decisions/D14-account-surface.md +0 -26
  31. package/docs/decisions/D15-hdsl-contract.md +0 -24
  32. package/docs/decisions/D16-popover-baseline.md +0 -23
  33. package/docs/decisions/D17-permission-presets.md +0 -26
  34. package/docs/decisions/D19-host-contracts.md +0 -27
  35. package/docs/decisions/D20-sliding-pill.md +0 -26
  36. package/docs/decisions/D21-archived-list.md +0 -24
  37. package/docs/decisions/D22-search-panel.md +0 -30
  38. package/docs/decisions/D24-mascot.md +0 -32
  39. package/docs/decisions/D25-ban-screen-titlebar.md +0 -24
  40. package/docs/decisions/D26-motion-preference.md +0 -23
  41. package/docs/decisions/D27-context-stats.md +0 -35
  42. package/docs/decisions/D28-desktop-band.md +0 -23
  43. package/docs/decisions/D29-feature-switches.md +0 -24
  44. package/docs/decisions/D3-host-selectors.md +0 -28
  45. package/docs/decisions/D30-palette-and-typeface.md +0 -25
  46. package/docs/decisions/D31-windows-titlebar.md +0 -24
  47. package/docs/decisions/D32-chat-interactions.md +0 -33
  48. package/docs/decisions/D33-stylesheet-ownership.md +0 -26
  49. package/docs/decisions/D34-turn-navigator.md +0 -29
  50. package/docs/decisions/D35-selection-scope.md +0 -23
  51. package/docs/decisions/D36-modules-and-bundling.md +0 -35
  52. package/docs/decisions/D38-assets.md +0 -28
  53. package/docs/decisions/D39-on-demand-loading.md +0 -33
  54. package/docs/decisions/D4-composer-gate.md +0 -22
  55. package/docs/decisions/D40-observation-bus.md +0 -36
  56. package/docs/decisions/D41-scroll-owner.md +0 -40
  57. package/docs/decisions/D42-feature-manifest.md +0 -28
  58. package/docs/decisions/D43-overlay-and-upstream.md +0 -27
  59. package/docs/decisions/D44-contract-module.md +0 -36
  60. package/docs/decisions/D45-testing.md +0 -30
  61. package/docs/decisions/D46-monorepo.md +0 -31
  62. package/docs/decisions/D47-build-output.md +0 -30
  63. package/docs/decisions/D48-documentation.md +0 -28
  64. package/docs/decisions/D49-visual-yield.md +0 -30
  65. package/docs/decisions/D5-model-copy.md +0 -29
  66. package/docs/decisions/D50-brand.md +0 -24
  67. package/docs/decisions/D51-css-toolchain.md +0 -34
  68. package/docs/decisions/D52-header-band.md +0 -31
  69. package/docs/decisions/D53-usage-merge.md +0 -33
  70. package/docs/decisions/D54-peakrate-meter.md +0 -33
  71. package/docs/decisions/D58-redraw-retired.md +0 -29
  72. package/docs/decisions/D60-settings-transport.md +0 -31
  73. package/docs/decisions/D61-wallpaper-under-one-mask.md +0 -28
  74. package/docs/decisions/D62-file-row-merge.md +0 -28
  75. package/docs/decisions/D63-turn-status-retired.md +0 -29
  76. package/docs/decisions/D7-one-package.md +0 -23
  77. package/docs/decisions/D9-style-performance.md +0 -25
  78. package/docs/decisions/README.md +0 -86
  79. package/lib/assets/2c01384360ac.js.map.br +0 -0
  80. package/lib/assets/31253ed42440.js.br +0 -0
  81. package/lib/assets/5063c46824b6.js.br +0 -0
  82. package/lib/assets/55a6154f87b5.js.map.br +0 -0
  83. package/lib/assets/5e05b29d5005.js.br +0 -0
  84. package/lib/assets/668d06ca781b.js.map.br +0 -0
  85. package/lib/assets/930546669455.js.map.br +0 -0
  86. package/lib/assets/968fcbfc3e22.js.br +0 -0
  87. package/lib/assets/abf0547f08a4.js.br +0 -0
  88. package/lib/assets/ac9b0e625837.js.map.br +0 -0
  89. package/lib/assets/ad2905345a69.js.br +0 -0
  90. package/lib/assets/ba68f60ecc71.js.map.br +0 -0
  91. package/lib/assets/c52e41b4842b.js.map.br +0 -0
  92. package/lib/assets/e1291f79b7c9.js.br +0 -0
  93. package/lib/client.js.map +0 -7
@@ -106,6 +106,18 @@
106
106
  "zh": "搜索",
107
107
  "en": "Search"
108
108
  },
109
+ "surfaceSwitch": {
110
+ "zh": "界面",
111
+ "en": "Interface"
112
+ },
113
+ "surfaceChat": {
114
+ "zh": "聊天",
115
+ "en": "Chat"
116
+ },
117
+ "surfaceCode": {
118
+ "zh": "代码",
119
+ "en": "Code"
120
+ },
109
121
  "searchClose": {
110
122
  "zh": "关闭",
111
123
  "en": "Close"
@@ -210,6 +222,18 @@
210
222
  "zh": "正在调用工具",
211
223
  "en": "Running tools…"
212
224
  },
225
+ "chatWaitReading": {
226
+ "zh": "正在读取 {file}",
227
+ "en": "Reading {file}"
228
+ },
229
+ "chatWaitEditing": {
230
+ "zh": "正在编辑 {file}",
231
+ "en": "Editing {file}"
232
+ },
233
+ "chatWaitWritingFile": {
234
+ "zh": "正在写入 {file}",
235
+ "en": "Writing {file}"
236
+ },
213
237
  "homeTabOverview": {
214
238
  "zh": "概览",
215
239
  "en": "Overview"
@@ -606,9 +630,9 @@
606
630
  "zh": "暂未响应",
607
631
  "en": "No response yet"
608
632
  },
609
- "fileRowMergedChanges": {
610
- "zh": "同一文件的 {count} 次改动合并为这一行",
611
- "en": "{count} changes to the same file are merged into this row"
633
+ "fileRowMergedOperations": {
634
+ "zh": "同一文件的 {count} 次操作合并为这一行",
635
+ "en": "{count} calls on the same file are merged into this row"
612
636
  },
613
637
  "accountNameFallback": {
614
638
  "zh": "用户",
@@ -642,7 +666,7 @@
642
666
  },
643
667
  "brandDesc": {
644
668
  "zh": "插件提供的品牌标识和配色色系风格。",
645
- "en": "The brand mark in the sidebar and on the home page, and its colour family: warm for Claude, blue for DeepSeek. While Colours is set to Follow the host, only the mark changes."
669
+ "en": "The brand mark and its colour family: warm for Claude, blue for DeepSeek. While Colours follows the host, only the mark changes."
646
670
  },
647
671
  "collapseTitle": {
648
672
  "zh": "折叠侧栏设置区",
@@ -658,7 +682,7 @@
658
682
  },
659
683
  "autoPopoverDesc": {
660
684
  "zh": "本插件提供的哪些弹层悬停时便展开。",
661
- "en": "Which popovers open on hover. \"Account only\" keeps it to the sidebar account popover; \"All\" adds the permission, model, session-stats and home-page pickers. Off leaves every popover click-to-open."
685
+ "en": "Which popovers open on hover: the account popover alone, or also the permission, model, session-stats and home-page pickers."
662
686
  },
663
687
  "autoPopoverOff": {
664
688
  "zh": "关闭",
@@ -686,7 +710,7 @@
686
710
  },
687
711
  "homeDesc": {
688
712
  "zh": "新会话页的排版",
689
- "en": "The new-conversation page layout. Classic is the centered hero with the input card; Studio moves the greeting to the top left, pins the composer to the bottom and shows usage in between."
713
+ "en": "The new-conversation page layout. Classic centers the hero and input card; Studio pins the composer to the bottom and shows usage."
690
714
  },
691
715
  "homeClassic": {
692
716
  "zh": "经典",
@@ -718,7 +742,7 @@
718
742
  },
719
743
  "quickDesc": {
720
744
  "zh": "在一级列表展示勾选的供应商。",
721
- "en": "Picked providers follow the official service in the picker's first level, one rule between providers. A provider removed from the catalog stays in the list marked \"Removed\"; uncheck it to clear it."
745
+ "en": "Picked providers follow the official service in the picker's first level; one removed from the catalog stays marked \"Removed\" until unchecked."
722
746
  },
723
747
  "quickNone": {
724
748
  "zh": "未选择",
@@ -742,7 +766,7 @@
742
766
  },
743
767
  "usernameDesc": {
744
768
  "zh": "用户名会显示在欢迎语和账号行里。",
745
- "en": "The name shown in the new-conversation greeting and the account row. Leave empty to use the signed-in account name, then the HDSL launcher name, then the local system user."
769
+ "en": "The name shown in the greeting and the account row; empty falls back to the signed-in account, then the launcher, then the system user."
746
770
  },
747
771
  "usernamePlaceholder": {
748
772
  "zh": "自动获取",
@@ -756,13 +780,97 @@
756
780
  "zh": "Claude",
757
781
  "en": "Claude"
758
782
  },
783
+ "brandNameTitle": {
784
+ "zh": "品牌名称",
785
+ "en": "Brand name"
786
+ },
787
+ "brandNameDesc": {
788
+ "zh": "替换侧栏顶部的品牌文字;留空时显示所选品牌自己的文字标志。",
789
+ "en": "Replaces the brand text at the top of the sidebar. Leave empty to keep the chosen brand's own wordmark."
790
+ },
791
+ "brandNamePlaceholder": {
792
+ "zh": "所选品牌",
793
+ "en": "The chosen brand"
794
+ },
795
+ "brandMarkTitle": {
796
+ "zh": "标志图片",
797
+ "en": "Brand mark"
798
+ },
799
+ "brandMarkDesc": {
800
+ "zh": "替换侧栏顶部、折叠栏、新会话页与账号行兜底头像上的品牌标志。PNG、SVG 或 WebP,不超过 2 MB。",
801
+ "en": "Replaces the brand mark in the sidebar, the collapsed rail, the home page and the account row's fallback picture. PNG, SVG or WebP, up to 2 MB."
802
+ },
803
+ "brandWordmarkTitle": {
804
+ "zh": "文字标志",
805
+ "en": "Wordmark"
806
+ },
807
+ "brandWordmarkDesc": {
808
+ "zh": "替换标志旁的品牌名称,宽度按图片比例随高度换算,优先于品牌名称。PNG、SVG 或 WebP,不超过 2 MB。",
809
+ "en": "Replaces the brand name beside the mark, sized from the image's proportions, and wins over the brand name. PNG, SVG or WebP, up to 2 MB."
810
+ },
811
+ "brandImageUpload": {
812
+ "zh": "上传",
813
+ "en": "Upload"
814
+ },
815
+ "brandImageReplace": {
816
+ "zh": "更换",
817
+ "en": "Replace"
818
+ },
819
+ "brandImageRemove": {
820
+ "zh": "移除",
821
+ "en": "Remove"
822
+ },
823
+ "brandImageType": {
824
+ "zh": "只接受 PNG、SVG 或 WebP 图片。",
825
+ "en": "Only PNG, SVG or WebP images are accepted."
826
+ },
827
+ "brandImageSize": {
828
+ "zh": "图片超过 2 MB。",
829
+ "en": "The image is larger than 2 MB."
830
+ },
831
+ "brandImageFailed": {
832
+ "zh": "保存失败:{detail}",
833
+ "en": "Saving failed: {detail}"
834
+ },
835
+ "brandInkTitle": {
836
+ "zh": "图片颜色",
837
+ "en": "Image colours"
838
+ },
839
+ "brandInkDesc": {
840
+ "zh": "「原色」保留图片自己的颜色;「文字色」把图片当作形状,按所在位置的文字颜色上色,亮色暗色下都看得清。",
841
+ "en": "Original keeps the images' own colours; Text colour fills each image with the text colour where it stands, legible in light and dark."
842
+ },
843
+ "brandInkOriginal": {
844
+ "zh": "原色",
845
+ "en": "Original"
846
+ },
847
+ "brandInkText": {
848
+ "zh": "文字色",
849
+ "en": "Text colour"
850
+ },
851
+ "brandAccentTitle": {
852
+ "zh": "强调色",
853
+ "en": "Accent colour"
854
+ },
855
+ "brandAccentDesc": {
856
+ "zh": "按钮、选中标记、链接与焦点环使用的颜色;未指定时沿用所选品牌的强调色。配色选「跟随宿主」时不生效。",
857
+ "en": "The colour of buttons, selected marks, links and focus rings; unset keeps the brand's own. No effect while Colours follows the host."
858
+ },
859
+ "brandAccentUnset": {
860
+ "zh": "跟随品牌",
861
+ "en": "Brand's own"
862
+ },
863
+ "brandAccentReset": {
864
+ "zh": "恢复品牌强调色",
865
+ "en": "Use the brand's accent"
866
+ },
759
867
  "motionTitle": {
760
868
  "zh": "动画效果",
761
869
  "en": "Animation"
762
870
  },
763
871
  "motionDesc": {
764
872
  "zh": "「随系统」跟随系统的动画设置;「减弱」把动画停在代表帧;「总是」始终播放。",
765
- "en": "Follow the system keeps the system's animation setting in charge; Reduced holds animations on their still frame; Always plays them. The background-work ring turns in every setting."
873
+ "en": "Follow the system, hold animations on a still frame, or always play them; the background-work ring turns in every setting."
766
874
  },
767
875
  "motionSystem": {
768
876
  "zh": "随系统",
@@ -793,12 +901,16 @@
793
901
  "en": "All"
794
902
  },
795
903
  "banLocaleTitle": {
796
- "zh": "封号彩蛋语言",
797
- "en": "Account-hold easter egg language"
904
+ "zh": "封号彩蛋",
905
+ "en": "Account-hold easter egg"
798
906
  },
799
907
  "banLocaleDesc": {
800
- "zh": "账户保留彩蛋页(点账户弹层顶部的用户名行进入)使用的语言。",
801
- "en": "The language of the account-hold easter egg page (open it from the account row at the top of the sidebar footer popover). It does not follow the interface language."
908
+ "zh": "点账户弹层顶部的用户名行打开的彩蛋页,按这里选的语言显示;关闭后用户名行只显示名字。",
909
+ "en": "The account row in the account popover opens a replica of Claude's account-hold page, in the language chosen here; Off leaves a plain name."
910
+ },
911
+ "banLocaleOff": {
912
+ "zh": "关闭",
913
+ "en": "Off"
802
914
  },
803
915
  "banLocaleZh": {
804
916
  "zh": "中文",
@@ -828,13 +940,37 @@
828
940
  "zh": "对话",
829
941
  "en": "Conversation"
830
942
  },
943
+ "tabMotion": {
944
+ "zh": "动效",
945
+ "en": "Motion"
946
+ },
947
+ "statusMotionTitle": {
948
+ "zh": "状态行动画",
949
+ "en": "Waiting-line animation"
950
+ },
951
+ "statusMotionSweep": {
952
+ "zh": "扫光",
953
+ "en": "Highlight sweep"
954
+ },
955
+ "statusMotionWash": {
956
+ "zh": "渐变流动",
957
+ "en": "Colour wash"
958
+ },
959
+ "composerRequired": {
960
+ "zh": "「重绘对话框」为「关闭」时不生效。",
961
+ "en": "No effect while Composer restyle is Off."
962
+ },
963
+ "statsComposerRequired": {
964
+ "zh": "只在「重绘对话框」覆盖对话页时生效。",
965
+ "en": "Takes effect only while Composer restyle covers the conversation."
966
+ },
831
967
  "paletteTitle": {
832
968
  "zh": "配色",
833
969
  "en": "Colours"
834
970
  },
835
971
  "paletteDesc": {
836
972
  "zh": "允许插件修改主题配色,关闭后只保留布局和控件。",
837
- "en": "Claude uses the skin's own colours; Follow the host leaves the colours to DSH and to other theme plugins (a wallpaper plugin, say), and the skin keeps only its layout and controls."
973
+ "en": "Claude uses the skin's own colours; Follow the host leaves colours to DSH or other theme plugins and keeps only layout and controls."
838
974
  },
839
975
  "paletteClaude": {
840
976
  "zh": "开启",
@@ -850,7 +986,7 @@
850
986
  },
851
987
  "typefaceDesc": {
852
988
  "zh": "使用插件提供的字体。",
853
- "en": "Claude uses the Anthropic faces (or the lookalike Inter and Noto Serif when they are missing) and JetBrains Mono for code; Follow the host keeps the fonts DSH or another plugin sets."
989
+ "en": "Claude uses the Anthropic faces (or the Inter and Noto Serif stand-ins) with JetBrains Mono for code; Follow the host keeps the fonts DSH sets."
854
990
  },
855
991
  "typefaceClaude": {
856
992
  "zh": "开启",
@@ -866,7 +1002,7 @@
866
1002
  },
867
1003
  "mascotDesc": {
868
1004
  "zh": "站在输入框上沿的像素小伙伴。",
869
- "en": "The pixel companion on the input area's top edge, animated by what the agent is doing. Follow the brand shows the pixel crab under Claude and Deepy the whale under DeepSeek."
1005
+ "en": "The pixel companion on the input area's top edge, animated by the agent's state. Follow the brand picks the crab under Claude, Deepy under DeepSeek."
870
1006
  },
871
1007
  "mascotBrand": {
872
1008
  "zh": "自动",
@@ -905,8 +1041,8 @@
905
1041
  "en": "Redraw the permission control"
906
1042
  },
907
1043
  "permissionsDesc": {
908
- "zh": "使用插件提供的权限菜单样式。",
909
- "en": "Replace the composer's permission menu with a segmented control. Off restores the host's permission menu."
1044
+ "zh": "使用插件自己的权限控件;关闭后交还宿主的权限菜单。",
1045
+ "en": "Use the skin's own permission control; Off restores the host's permission menu."
910
1046
  },
911
1047
  "searchTitle": {
912
1048
  "zh": "侧栏搜索",
@@ -921,8 +1057,8 @@
921
1057
  "en": "Search box style"
922
1058
  },
923
1059
  "searchStyleDesc": {
924
- "zh": "选择搜索框样式",
925
- "en": "Choose the search box style"
1060
+ "zh": "搜索框放在哪里:盖过品牌、品牌行下单独一行,或只保留宿主的搜索图标。",
1061
+ "en": "Where the search box stands: over the brand, on a row of its own, or as the host's own search icon."
926
1062
  },
927
1063
  "searchStyleIcon": {
928
1064
  "zh": "图标",
@@ -949,16 +1085,16 @@
949
1085
  "en": "Float docked panels"
950
1086
  },
951
1087
  "dockCardsDesc": {
952
- "zh": "右侧栏停靠的面板画成悬浮卡片:四周留 8px、16px 圆角、1px 描边与投影;关闭后铺满整列、贴住四边,分栏时每栏铺满各自那一栏。",
953
- "en": "Draw the right sidebar's docked panels as floating cards: 8px inside the column, a 16px radius, a hairline and an elevation. Off fills the column and hugs its edges; a split gives each pane its own column."
1088
+ "zh": "把右侧栏停靠的面板画成悬浮卡片;关闭后铺满整列、贴住四边。",
1089
+ "en": "Draws the right sidebar's docked panels as floating cards; Off fills the column edge to edge."
954
1090
  },
955
1091
  "sidebarLayoutTitle": {
956
1092
  "zh": "左侧栏布局",
957
1093
  "en": "Sidebar layout"
958
1094
  },
959
1095
  "sidebarLayoutDesc": {
960
- "zh": "调整左侧栏的紧凑程度。「宽松」是现在的样子;「紧凑」缩短上侧各行到工作区之间的间隙、压低对话行的高度与行间距、收紧账号区的内边距。",
961
- "en": "Adjust how tight the sidebar is. Relaxed is how it looks now; Compact shortens the gap between the sidebar's top rows and the workspace, takes the conversation rows' height and spacing down, and trims the account area's padding."
1096
+ "zh": "调整左侧栏的紧凑程度:「紧凑」收紧行高、间距与账号区内边距。",
1097
+ "en": "How tight the sidebar is: Relaxed is the default look; Compact trims row heights, gaps and padding."
962
1098
  },
963
1099
  "sidebarLayoutRelaxed": {
964
1100
  "zh": "宽松",
@@ -974,15 +1110,15 @@
974
1110
  },
975
1111
  "turnNavDesc": {
976
1112
  "zh": "重绘对话导航区域。",
977
- "en": "Rest the pointer on the turn marks at the conversation's right edge and they open into a list of every turn, one line each with the message that started it; the wheel scrolls the list and a click jumps to that turn. Alt+↑ and Alt+↓ jump to the previous or the next turn, and the turn you land on is marked with a short line. Off restores the host's turn marks."
1113
+ "en": "Hover the turn marks at the conversation's right edge to open a list of every turn; the wheel scrolls it, a click jumps over. Alt+↑ / Alt+↓ jump between turns. Off restores the host's turn marks."
978
1114
  },
979
1115
  "chatAnimationsTitle": {
980
1116
  "zh": "聊天区动画效果",
981
1117
  "en": "Chat-area animations"
982
1118
  },
983
1119
  "chatAnimationsDesc": {
984
- "zh": "聊天区的动效:跟随、自动开合与卷帘门、新文字淡入、文件变更行、发送时的气泡动效、过程组标题上的计数,以及说明模型正在做什么的那一行。开启时播放本插件的这一套,关闭后聊天区交回宿主——宿主自己的说法也一并回来。「动画」设为「减弱」时一律停在原处。",
985
- "en": "The conversation area's motion: the follow, the automatic folding with its rolling door, the text fade, the file change rows, the send flight, the counted figures on each process group's header and the line saying what the model is doing. On plays this plugin's set; off hands the conversation back to the host, its own words included. With Animation set to Reduced it all stands still."
1120
+ "zh": "聊天区的一整套动效:跟随、折叠、文字淡入、文件变更行、发送气泡、过程计数与状态行;关闭后交回宿主。",
1121
+ "en": "The conversation area's motion set: follow, folding, text fade, file change rows, send flight, counters and the waiting line. Off hands the area back to the host."
986
1122
  },
987
1123
  "statsPositionTitle": {
988
1124
  "zh": "对话统计信息位置",
@@ -993,8 +1129,8 @@
993
1129
  "en": "Conversation statistics"
994
1130
  },
995
1131
  "statsPositionDesc": {
996
- "zh": "选择对话统计信息的展示位置。",
997
- "en": "Choose where the conversation statistics show."
1132
+ "zh": "「收进上下文」把会话数字放进上下文圆环的弹层;「独立成行」写在输入卡片下面一行,末尾是圆环。",
1133
+ "en": "Inside the context popover puts the session's figures in the ring's panel; On its own line writes them under the input card, ending in the ring."
998
1134
  },
999
1135
  "statsPositionContext": {
1000
1136
  "zh": "收进上下文",
@@ -1008,22 +1144,34 @@
1008
1144
  "zh": "光标动画",
1009
1145
  "en": "Composer caret motion"
1010
1146
  },
1011
- "caretDesc": {
1012
- "zh": "移动光标时平滑移动。",
1013
- "en": "The composer's caret is drawn by the plugin and glides between positions instead of jumping. Explicit moves glides only on an arrow key or a click, and lands instantly while typing."
1014
- },
1015
- "caretTyping": {
1016
- "zh": "总是",
1017
- "en": "Every move"
1018
- },
1019
- "caretMove": {
1020
- "zh": "减弱",
1021
- "en": "Explicit moves"
1147
+ "caretOn": {
1148
+ "zh": "开",
1149
+ "en": "On"
1022
1150
  },
1023
1151
  "caretOff": {
1024
- "zh": "关闭",
1152
+ "zh": "关",
1025
1153
  "en": "Off"
1026
1154
  },
1155
+ "caretSample": {
1156
+ "zh": "在此输入",
1157
+ "en": "Type here"
1158
+ },
1159
+ "statusDetailTitle": {
1160
+ "zh": "状态行描述",
1161
+ "en": "Waiting-line detail"
1162
+ },
1163
+ "statusDetailDesc": {
1164
+ "zh": "「简洁」只写状态行的状态;「精确」补上正在操作的文件、命令声明的描述或推理里的原句。",
1165
+ "en": "Simple names the running turn's state alone; Precise adds the file a call works on, a command's declared description or a clause from the reasoning."
1166
+ },
1167
+ "statusDetailSimple": {
1168
+ "zh": "简洁",
1169
+ "en": "Simple"
1170
+ },
1171
+ "statusDetailPrecise": {
1172
+ "zh": "精确",
1173
+ "en": "Precise"
1174
+ },
1027
1175
  "chatUxManaged": {
1028
1176
  "zh": "该选项由插件 dsh-chat-ux 管理",
1029
1177
  "en": "Managed by dsh-chat-ux"
@@ -1041,8 +1189,12 @@
1041
1189
  "en": "Header in the title bar"
1042
1190
  },
1043
1191
  "headerBandDesc": {
1044
- "zh": "桌面端把会话标题与顶栏那一行的控件抬进窗口的标题栏,放不下的一侧留在原来的行里。",
1045
- "en": "On the desktop the session title and the header's controls rise into the window's caption row, and a side without room stays in the header's own row."
1192
+ "zh": "Windows 桌面端把会话标题与顶栏那一行的控件抬进窗口的标题栏,放不下的一侧留在原来的行里。",
1193
+ "en": "On the Windows desktop the session title and the header's controls rise into the window's caption row, and a side without room stays in the header's own row."
1194
+ },
1195
+ "windowsOnlyNote": {
1196
+ "zh": "只在 Windows 桌面端的窗口里生效。",
1197
+ "en": "Takes effect in the Windows desktop window only."
1046
1198
  },
1047
1199
  "unavailable": {
1048
1200
  "zh": "ERROR : 设置存储服务异常,改动不会被保存。",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-claude-style",
3
3
  "description": "Claude Code Desktop theme for DeepSeek Harness (dsh) web GUI — visual & interaction overhaul",
4
- "version": "0.13.2",
4
+ "version": "0.14.0-dev.12",
5
5
  "type": "module",
6
6
  "main": "lib/host/index.js",
7
7
  "icon": "lib/claude-mark.svg",
@@ -15,12 +15,18 @@
15
15
  "changelog:check": "node scripts/changelog.mjs --check",
16
16
  "docs:index": "node scripts/decisions-index.mjs",
17
17
  "docs:check": "node scripts/decisions-index.mjs --check",
18
+ "docs:numbers": "node scripts/doc-numbers.mjs",
19
+ "agents": "node scripts/agents-commands.mjs",
20
+ "agents:check": "node scripts/agents-commands.mjs --check",
21
+ "decision:number": "node scripts/decision-number.mjs",
18
22
  "lint": "node scripts/lint.mjs",
19
23
  "features": "node scripts/features.mjs",
20
24
  "features:check": "node scripts/features.mjs --check",
21
- "probe": "node scripts/probe.cjs",
22
- "smoke": "node scripts/smoke.cjs",
25
+ "probe": "node packages/testing/probe.cjs",
26
+ "session": "node scripts/session.mjs",
27
+ "smoke": "node packages/testing/smoke.cjs",
23
28
  "test": "vitest run",
29
+ "verify": "node scripts/verify.mjs",
24
30
  "prepublishOnly": "npm run build"
25
31
  },
26
32
  "exports": {
@@ -43,6 +49,8 @@
43
49
  },
44
50
  "files": [
45
51
  "lib",
52
+ "!lib/**/*.map",
53
+ "!lib/assets/*.map.br",
46
54
  "locale",
47
55
  "skin.json",
48
56
  "cordis.patch.yml",
@@ -51,7 +59,6 @@
51
59
  "docs/FEATURES.en.md",
52
60
  "docs/SETTINGS.md",
53
61
  "docs/SETTINGS.en.md",
54
- "docs/decisions",
55
62
  "CHANGELOG.md",
56
63
  "README.md",
57
64
  "README.en.md",
@@ -97,6 +104,7 @@
97
104
  "ajv": "8.20.0",
98
105
  "ajv-formats": "3.0.1",
99
106
  "esbuild": "0.28.2",
107
+ "jscpd": "5.3.3",
100
108
  "playwright": "1.63.0",
101
109
  "pngjs": "^7.0.0",
102
110
  "postcss": "8.5.29",
@@ -1,26 +0,0 @@
1
- # D11. 私有路由借宿主的请求栅栏;外来字符串只以文本上屏
2
-
3
- - **状态**:已实施
4
- - **分组**:宿主边界
5
- - **关联**:D21、D22、D38
6
-
7
- ## 决定
8
-
9
- - 宿主半边的私有路由(`/username`、`/usage`、`/session-search`、`/hdsl`、`/hdsl-skin.png`、`POST /session-delete`)处理前先调 `connection.requestRejection(req)`,拒绝即回 401/403。宿主没有这个服务时,插件自带的替代只放行回环请求:连接的对端地址在本机回环口上、回环 Host、无跨站标记、Origin 与 Host 一致。四项里前三项都要成立,其中对端地址是请求方写不了的那一项,回环 Host 只是附带条件。
10
- - 公开静态资产不经栅栏,但请求里的文件名必须符合固定格式,读取只落在固定表给出名字的目录里:模型文案取自构建输出;字体的名字先查 `$DSH_HOME/dsh-claude-style/fonts/`,没有再看包内的 `lib/fonts/`;走路由的资源是构建清单(`lib/assets/manifest.json`,D38)里的哈希加扩展名。
11
- - 删除会话另加四道:只接受 POST;id 符合宿主的会话 id 格式;正在打开的会话拒绝;解析符号链接之后的目录必须留在会话根目录内。删除发生在宿主半边,浏览器只提交 id。请求体超过上限时先答 400,应答送出之后再结束这条连接。
12
- - 删除成功时宿主半边经 `workspaceRegistry.unarchiveSession` 把 id 移出归档集合;归档集合里存储目录已消失的条目同样按删除成功应答并移出,否则归档列表会一直留着这一行。会话根目录读不了是故障,答 500。
13
- - 用量汇总只读:别的插件的账本只读不写,自己的缓存放在 `$DSH_HOME/cache/dsh-claude-style/`,两个来源按日期合并(D53)。
14
- - 浏览器半边:来自设置、账号服务、系统或其他插件的字符串只用 `textContent` 或元素属性写入;图标复制节点,不重新解析标记。
15
-
16
- ## 理由
17
-
18
- - 插件路由不在宿主自己的栅栏之内;`dsh web` 绑定 `0.0.0.0` 时局域网可以直接访问,而页面能驱动执行 shell 命令的智能体。
19
-
20
- ## 代价
21
-
22
- - 路由依赖宿主的 connection 服务。浏览器同源请求带会话 cookie、桌面壳经 `forwardWebRequest` 转发到回环 Host,两种都核对过能通过。
23
-
24
- ## 重审条件
25
-
26
- - 宿主提供自带鉴权的路由注册时迁移过去,删掉本地替代。
@@ -1,36 +0,0 @@
1
- # D12. 快速失败与功能隔离
2
-
3
- - **状态**:已实施
4
- - **分组**:运行时
5
- - **关联**:D29、D38、D42
6
-
7
- ## 决定
8
-
9
- - 出错的地方直接抛出,不吞错误、不静默回退。宿主服务可能缺席时,用可选链与 `typeof` 表达「没有这个服务」,不用 try/catch;宿主服务是否存在以 `ctx.get` 的返回值判断(cordis 对缺席的服务返回 `undefined`)。可选的文件(读者放进来的字体、HDSL 头像、尚未建立的会话根目录)用 `existsSync` 或 `statSync(…, { throwIfNoEntry: false })` 判断。
10
- - 功能隔离:teardown 最先注册且幂等;每个功能单独安装,装不上的报告一次并退役;每轮刷新里每个功能单独执行,连续失败 3 轮即报告并退役。刷新机制自身装不上时整体回到宿主原样。
11
- - 退役就是运行这个功能自己的 teardown,交还它接管的宿主界面:页脚接管与输入框重绘的门控强制关闭;权限控件替换的宿主控件由它自己的标记把守、随它的 teardown 交还。每个功能的 teardown 是它的 DOM 与标记的唯一清理。
12
- - 需要隔离、但错误必须可见的地方用 `reportError`:`notifyAll` 逐个通知监听函数,观察总线逐个通知订阅、帧管线逐个运行任务(D40),某个出错就报告、其余照常;卸载时单个功能失败报告后继续;功能开关(D29)关闭某个功能时它的 teardown 抛错,同样报告,这个功能在本代内不再装回。
13
- - 浏览器半边允许的 catch,每处写明原因:
14
- - 上述隔离。
15
- - 宿主以抛错表达的预期状态:设置表单的 `set()` 拒绝不属于该配置的字段;`modelDirectories.directoryFor` 对还没建立的会话抛错,下一轮重试;`sessionQuery` 的观察(`observeSession`)与按 id 读(`readSession`)以 `SESSION_QUERY_CORRUPT_SESSION` / `SESSION_QUERY_SESSION_NOT_FOUND` 表示某个存档读不了或已被删,内容搜索与用量汇总把这一个会话记为空并记一条警告,其余会话照旧。
16
- - 文件变更行解析流式工具的原始参数:参数逐块到达,半截 JSON 是正常的中途状态,解析不了就交回宿主的输入 / 输出卡片(`features/chat-files/file-row-model.ts`)。
17
- - Promise 上表示「宿主半边没有应答」或「宿主自己会提示」的失败回调。
18
- - 宿主半边允许的 catch,每处写明原因:
19
- - `webServer.register` 以抛错拒绝已被别的插件占用的路径:逐条注册,被拒的记警告,其余照常(宿主半边的纤程失败会连带撤下浏览器半边的整个包)。
20
- - 卸载时逐个运行路由的撤销函数,单个失败记警告后继续。
21
- - 删除会话的请求体不是 JSON 时答 400;删除过程中的任何故障答 500 并带错误信息。
22
- - 宿主半边 `lib/assets/manifest.json` 读不了或不是 JSON 时答 404:那是构建没跑完的状态,记一次警告即可,不必让路由本身失败。
23
- - 成本计量插件的账本是别的插件的文件,读取与它的写入没有协调,解析不了时当作没有账本、改用本地折算。
24
- - 用量汇总自己的缓存只省工作量:读不了时记警告并整体重算覆盖,写不进时记警告、本轮结果照常返回。
25
-
26
- ## 理由
27
-
28
- - 被吞掉的错误会在别处以更难排查的方式出现;隔离只负责不让一个功能拖垮其他功能,失败本身必须留下记录。
29
-
30
- ## 代价
31
-
32
- - 功能失效时界面上没有提示,只有控制台记录;依赖同一宿主服务的功能会一起退役。
33
-
34
- ## 重审条件
35
-
36
- - 宿主提供插件级的错误上报时,把报告接过去。
@@ -1,26 +0,0 @@
1
- # D14. 账号表面:一套行模型,两个挂载点
2
-
3
- - **状态**:已实施
4
- - **分组**:功能
5
- - **关联**:D16
6
-
7
- ## 决定
8
-
9
- - 插件的行(账号头部、其他插件的页脚条目、设置行)只出现在账号弹层里,由 `features/account/surface.ts` 每轮判定挂载点。
10
- - 宿主有账号区时(桌面端),宿主的账号行就是入口(插件只打标记供样式重绘),插件把容器插到宿主账号菜单列表的首位,宿主渲染它自己的行;宿主没有账号区时(网页端),插件自建账号行与弹层。
11
- - 宿主的行不复制、不移动、不转发点击。插件的行被点击后需要收起菜单时,派发一次带 `__dshHostMenuEscape` 标记的 Escape 交给宿主菜单;皮肤的全局键盘路径见到这个标记就跳过。
12
- - 账号头部打开封号彩蛋时,全窗浮层让指针「离开」行与菜单:浮层打开期间悬停收起停止工作,退出后页脚保持进入时的样子。
13
- - 插进去的容器比宿主自己的行晚一帧到,卡片随之变高,宿主再晚一帧按新高度重新摆位。所以悬停或按下账号行时先给 `<body>` 打 `ACCOUNT_ARMED_ATTR`,卡片在这段时间不上色;`surface.ts` 看到插件的行已在列表里、且卡片的行内摆位连续两次读数相同之后才打 `ACCOUNT_READY_ATTR`,入场动画挂在这个标记上。行内没有摆位时行一到就放行;始终不静止的卡片在有限帧数后放行。
14
-
15
- ## 理由
16
-
17
- - 宿主菜单自带定位、动画、键盘遍历与关闭;插进去的行加入同一套键盘遍历,账号区不依赖宿主菜单的渲染时序与标签文字。
18
- - 淡入从卡片最终的高度与位置开始,不会先贴着底部出现再往上跳。
19
-
20
- ## 代价
21
-
22
- - 宿主菜单关闭即卸载,容器每轮重新确认并插入;卡片的显现要等插件的行到位与宿主重新摆位(约两三帧),这段时间卡片不上色。
23
-
24
- ## 重审条件
25
-
26
- - 宿主为账号菜单提供追加行的插槽时改用插槽;宿主把插件的行算进它自己的首次渲染时,去掉这段等待。
@@ -1,24 +0,0 @@
1
- # D15. HDSL 账号契约:宿主半边转发,浏览器半边只认一条回退顺序
2
-
3
- - **状态**:已实施
4
- - **分组**:功能
5
- - **关联**:D11
6
-
7
- ## 决定
8
-
9
- - 宿主半边读 harness 启动时填好的启动环境快照(`ctx.launchEnvironment`),只信 `process` 与 `user-env` 两层(项目目录的 `.env` 会随仓库被克隆);契约版本不为 `1` 时回 `{ contract: false }`。不 import harness 的启动环境包(`link:` 安装的插件解析不到它)。
10
- - `GET /dsh-claude-style/hdsl` 回账号元数据,不含头像文件路径;`GET /dsh-claude-style/hdsl-skin.png` 回贴图字节,路径只来自环境、永远不来自请求。契约在进程生命周期内不变,读一次并记住。
11
- - 浏览器半边:昵称 = 自定义昵称 → 官方账号昵称 → HDSL 昵称 → 探测昵称缓存 → 探测昵称 → `User`;头像 = 官方账号头像 → HDSL 头像 → Claude 徽标。两条回退都经 `packages/client/src/core/host.ts` 的身份存储,欢迎语与账号行只读这一处。
12
- - 启动器给的是贴图集:按启动器账号列表同样的裁法取头部(脸的 8×8 贴图块按盒子 1/18 内缩,帽子层铺满),方形绘制;画完主动请求一轮刷新。
13
-
14
- ## 理由
15
-
16
- - 契约只需读一次;两条回退收在一处,各处显示不会各自漂移;裁法与启动器一致,同一个玩家在两处长得一样。
17
-
18
- ## 代价
19
-
20
- - 桌面端的账号行由宿主渲染,HDSL 头像只作用于插件自己的表面;启动器内置的默认形象没有像素可用,回退到徽标。
21
-
22
- ## 重审条件
23
-
24
- - HDSL 契约升级版本(按指纹取图、账号 UUID)时改接新通道;宿主提供统一的「显示名 / 头像」服务时改接宿主。
@@ -1,23 +0,0 @@
1
- # D16. 弹层基准:一套外壳、一个停留时长、一次只开一张
2
-
3
- - **状态**:已实施
4
- - **分组**:功能
5
-
6
- ## 决定
7
-
8
- - 外壳:插件自建的卡片(权限、模型、推理强度、账号、快捷供应商)都带 `.dsh-claude-popover-card`,共用底色、边框、圆角、阴影、内边距、层级、开关动画与暗色配色;行、角标、勾号、状态行、主体用中性类名(`dsh-claude-popover-item` 等)。各功能的样式只写位置、宽度与展开方向。
9
- - 停留与宽限统一为 `shared/popover.ts` 的 `POPOVER_OPEN_DELAY` / `POPOVER_CLOSE_DELAY`(100ms);例外连同理由写在使用处(模型选择器两级卡片的收起宽限 150ms)。
10
- - 互斥:`registerPopover(name, close)` 登记每张弹层的关闭方式,`closeOtherPopovers(name)` 在打开前关掉其余的。一个弹层的多层卡片按一项登记;宿主的菜单由驱动它的功能登记。登记表只存关闭函数,按名字覆盖登记,热重载后新一代的函数替换旧一代。
11
- - hero 行一项登记对应两个宿主菜单,`hero-menu.ts` 自己再做一次互斥,依据是「已展开的触发器」。
12
-
13
- ## 理由
14
-
15
- - 同一个交互问题分处写必然漂移;共用外观用中性类名,改一个功能的样式不会波及别的功能。
16
-
17
- ## 代价
18
-
19
- - 登记表是模块级状态,功能卸载时必须 `unregisterPopover`。
20
-
21
- ## 重审条件
22
-
23
- - 宿主提供统一的弹层管理(全局互斥或焦点陷阱)时改接宿主。
@@ -1,26 +0,0 @@
1
- # D17. 权限档位以宿主目录为准,皮肤只做表现层
2
-
3
- - **状态**:已实施
4
- - **分组**:功能
5
-
6
- ## 决定
7
-
8
- - 段位与弹层行都按宿主的 `permissionPresets` 目录构建:目录里有的档位才画,没有的整条不出现。
9
- - `PERMISSION_SEGMENTS` 只描述格子:每格列出可绑定的档位、取第一个宿主提供的(部署自己的自动档优先于宿主内置的 Auto review),一个都绑不上就不画。
10
- - 档位名与说明来自皮肤的 `PERMISSION_PRESETS`,不认识的档位用目录自带的名字与说明,机器值永不上屏;档位声明的 `icon` 不画,列表保持纯文字。
11
- - 中文界面的档位名改读宿主 `permission.access` 文案表里的原文(「仅可查看」「工作区内修改」「完全权限」):皮肤的名称是 Claude 的英文叫法,中文界面没有对应的叫法,而宿主自己的中文名是用户已经在宿主界面上认过的。文案表没登记这个档位、或宿主没有 `locale` 服务时回到皮肤的名称,语言不是中文时也照旧用皮肤的名称。
12
- - 切换走宿主的 `/permission <preset>`。
13
-
14
- ## 理由
15
-
16
- - 目录变化时不漏档位,第三方档位(例如 auto mode 插件的 `auto-mode`)成为一等条目,接入新档位不用改皮肤代码。
17
- - 宿主改动自己的中文名时皮肤跟着变,不用把同一批词在皮肤里再写一遍。
18
-
19
- ## 代价
20
-
21
- - 档位集合变化时重建行与段位;不认识的档位以宿主给的名字出现。
22
-
23
- ## 重审条件
24
-
25
- - 宿主原生支持档位图标、且界面有了统一的档位图形语言时,再考虑画图标。
26
- - 宿主的档位目录直接给出本地化的档位名时,改读目录本身,不再读 `permission.access`。