@icen.ai/ui 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/AGENTS.md +138 -80
  2. package/README.md +66 -91
  3. package/dist/base.css +208 -179
  4. package/dist/behaviors/accordion.mjs +8 -8
  5. package/dist/behaviors/ai-branch.d.mts +1 -1
  6. package/dist/behaviors/ai-branch.mjs +1010 -94
  7. package/dist/behaviors/ai-chat.d.mts +7 -7
  8. package/dist/behaviors/ai-chat.mjs +1071 -161
  9. package/dist/behaviors/ai-composer.d.mts +44 -12
  10. package/dist/behaviors/ai-composer.mjs +1997 -524
  11. package/dist/behaviors/ai-core.d.mts +1 -1
  12. package/dist/behaviors/ai-core.mjs +1016 -107
  13. package/dist/behaviors/ai-diff.mjs +1019 -127
  14. package/dist/behaviors/ai-feedback.d.mts +1 -1
  15. package/dist/behaviors/ai-feedback.mjs +1035 -126
  16. package/dist/behaviors/ai-panel.d.mts +8 -8
  17. package/dist/behaviors/ai-panel.mjs +1284 -266
  18. package/dist/behaviors/ai-provider.mjs +1003 -101
  19. package/dist/behaviors/ai-threads.d.mts +1 -1
  20. package/dist/behaviors/ai-threads.mjs +1068 -154
  21. package/dist/behaviors/ai-tool.d.mts +2 -2
  22. package/dist/behaviors/ai-tool.mjs +2037 -396
  23. package/dist/behaviors/ai-tools.d.mts +89 -16
  24. package/dist/behaviors/ai-tools.mjs +4448 -372
  25. package/dist/behaviors/autocomplete.d.mts +53 -0
  26. package/dist/behaviors/autocomplete.mjs +1600 -0
  27. package/dist/behaviors/back-top.d.mts +1 -1
  28. package/dist/behaviors/back-top.mjs +951 -14
  29. package/dist/behaviors/carousel.d.mts +1 -1
  30. package/dist/behaviors/carousel.mjs +906 -11
  31. package/dist/behaviors/cascader.d.mts +48 -0
  32. package/dist/behaviors/cascader.mjs +1853 -0
  33. package/dist/behaviors/charts.d.mts +72 -8
  34. package/dist/behaviors/charts.mjs +1901 -256
  35. package/dist/behaviors/code-block.d.mts +36 -0
  36. package/dist/behaviors/code-block.mjs +1611 -0
  37. package/dist/behaviors/command-palette.d.mts +9 -6
  38. package/dist/behaviors/command-palette.mjs +161 -59
  39. package/dist/behaviors/context-menu.d.mts +9 -8
  40. package/dist/behaviors/context-menu.mjs +1112 -44
  41. package/dist/behaviors/controls.d.mts +13 -13
  42. package/dist/behaviors/controls.mjs +989 -130
  43. package/dist/behaviors/copy.d.mts +21 -2
  44. package/dist/behaviors/copy.mjs +1206 -42
  45. package/dist/behaviors/datatable.d.mts +53 -3
  46. package/dist/behaviors/datatable.mjs +1963 -207
  47. package/dist/behaviors/date-picker.d.mts +0 -1
  48. package/dist/behaviors/date-picker.mjs +1340 -293
  49. package/dist/behaviors/design.d.mts +54 -0
  50. package/dist/behaviors/design.mjs +109 -0
  51. package/dist/behaviors/dropdown.d.mts +5 -6
  52. package/dist/behaviors/dropdown.mjs +262 -110
  53. package/dist/behaviors/events.d.mts +120 -3
  54. package/dist/behaviors/events.mjs +47 -2
  55. package/dist/behaviors/feedback.d.mts +30 -0
  56. package/dist/behaviors/feedback.mjs +296 -0
  57. package/dist/behaviors/focus.d.mts +8 -0
  58. package/dist/behaviors/focus.mjs +24 -0
  59. package/dist/behaviors/form-validate.d.mts +102 -0
  60. package/dist/behaviors/form-validate.mjs +6091 -0
  61. package/dist/behaviors/i18n.d.mts +789 -0
  62. package/dist/behaviors/i18n.mjs +1711 -0
  63. package/dist/behaviors/icons.d.mts +93 -0
  64. package/dist/behaviors/icons.mjs +113 -0
  65. package/dist/behaviors/input.d.mts +9 -1
  66. package/dist/behaviors/input.mjs +1056 -60
  67. package/dist/behaviors/kb-access.d.mts +1 -1
  68. package/dist/behaviors/kb-access.mjs +2129 -239
  69. package/dist/behaviors/kb-acl.d.mts +6 -6
  70. package/dist/behaviors/kb-acl.mjs +1119 -179
  71. package/dist/behaviors/kb-answer.mjs +2070 -418
  72. package/dist/behaviors/kb-audit.d.mts +1 -1
  73. package/dist/behaviors/kb-audit.mjs +1076 -154
  74. package/dist/behaviors/kb-canvas.mjs +1100 -177
  75. package/dist/behaviors/kb-chain.mjs +1022 -100
  76. package/dist/behaviors/kb-checkpoint.d.mts +1 -1
  77. package/dist/behaviors/kb-checkpoint.mjs +1319 -169
  78. package/dist/behaviors/kb-chunks.mjs +1152 -213
  79. package/dist/behaviors/kb-citation.d.mts +1 -1
  80. package/dist/behaviors/kb-citation.mjs +1201 -179
  81. package/dist/behaviors/kb-clarify.mjs +1058 -130
  82. package/dist/behaviors/kb-conflict.mjs +1041 -119
  83. package/dist/behaviors/kb-connector.mjs +1104 -176
  84. package/dist/behaviors/kb-core.d.mts +6 -1
  85. package/dist/behaviors/kb-core.mjs +1077 -162
  86. package/dist/behaviors/kb-eval.mjs +1971 -144
  87. package/dist/behaviors/kb-explain.d.mts +1 -1
  88. package/dist/behaviors/kb-explain.mjs +1024 -102
  89. package/dist/behaviors/kb-filter.mjs +2008 -178
  90. package/dist/behaviors/kb-gap.d.mts +1 -1
  91. package/dist/behaviors/kb-gap.mjs +1043 -121
  92. package/dist/behaviors/kb-hittest.d.mts +1 -1
  93. package/dist/behaviors/kb-hittest.mjs +1093 -150
  94. package/dist/behaviors/kb-metadata.mjs +1052 -130
  95. package/dist/behaviors/kb-passage.d.mts +2 -2
  96. package/dist/behaviors/kb-passage.mjs +1101 -161
  97. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  98. package/dist/behaviors/kb-pipeline.mjs +1082 -162
  99. package/dist/behaviors/kb-qa.mjs +1088 -160
  100. package/dist/behaviors/kb-rerank.mjs +1047 -114
  101. package/dist/behaviors/kb-retrieval.mjs +2063 -224
  102. package/dist/behaviors/kb-review.mjs +1990 -159
  103. package/dist/behaviors/kb-sandbox.d.mts +1 -1
  104. package/dist/behaviors/kb-sandbox.mjs +1026 -104
  105. package/dist/behaviors/kb-segment.mjs +1111 -179
  106. package/dist/behaviors/kb-select.d.mts +24 -0
  107. package/dist/behaviors/kb-select.mjs +1989 -0
  108. package/dist/behaviors/kb-sources.d.mts +1 -1
  109. package/dist/behaviors/kb-sources.mjs +1084 -170
  110. package/dist/behaviors/kb-sql.d.mts +1 -1
  111. package/dist/behaviors/kb-sql.mjs +1143 -226
  112. package/dist/behaviors/kb-trace.d.mts +1 -1
  113. package/dist/behaviors/kb-trace.mjs +1042 -128
  114. package/dist/behaviors/kb-visibility.mjs +1086 -158
  115. package/dist/behaviors/kb-who-can.mjs +1974 -137
  116. package/dist/behaviors/mentions.d.mts +93 -0
  117. package/dist/behaviors/mentions.mjs +2152 -0
  118. package/dist/behaviors/modal.d.mts +4 -3
  119. package/dist/behaviors/modal.mjs +1055 -33
  120. package/dist/behaviors/nav.d.mts +1 -1
  121. package/dist/behaviors/nav.mjs +6 -6
  122. package/dist/behaviors/notification.d.mts +16 -8
  123. package/dist/behaviors/notification.mjs +1615 -265
  124. package/dist/behaviors/panel.d.mts +4 -0
  125. package/dist/behaviors/panel.mjs +994 -0
  126. package/dist/behaviors/popover.d.mts +28 -5
  127. package/dist/behaviors/popover.mjs +225 -24
  128. package/dist/behaviors/select.d.mts +5 -2
  129. package/dist/behaviors/select.mjs +1410 -117
  130. package/dist/behaviors/sidebar.d.mts +1 -1
  131. package/dist/behaviors/sidebar.mjs +13 -13
  132. package/dist/behaviors/slider.d.mts +1 -1
  133. package/dist/behaviors/slider.mjs +9 -9
  134. package/dist/behaviors/split-pane.d.mts +1 -1
  135. package/dist/behaviors/split-pane.mjs +7 -7
  136. package/dist/behaviors/suggestions.d.mts +27 -0
  137. package/dist/behaviors/suggestions.mjs +1089 -0
  138. package/dist/behaviors/svg-parse.d.mts +14 -0
  139. package/dist/behaviors/svg-parse.mjs +37 -0
  140. package/dist/behaviors/tabs.d.mts +2 -2
  141. package/dist/behaviors/tabs.mjs +25 -25
  142. package/dist/behaviors/tag-input.d.mts +23 -5
  143. package/dist/behaviors/tag-input.mjs +1359 -104
  144. package/dist/behaviors/theme-switcher.d.mts +24 -0
  145. package/dist/behaviors/theme-switcher.mjs +1981 -0
  146. package/dist/behaviors/theme.d.mts +15 -8
  147. package/dist/behaviors/theme.mjs +390 -28
  148. package/dist/behaviors/toast.d.mts +24 -25
  149. package/dist/behaviors/toast.mjs +1266 -88
  150. package/dist/behaviors/tooltip.d.mts +4 -0
  151. package/dist/behaviors/tooltip.mjs +378 -0
  152. package/dist/behaviors/tree-select.d.mts +69 -0
  153. package/dist/behaviors/tree-select.mjs +1907 -0
  154. package/dist/behaviors/tree.d.mts +1 -1
  155. package/dist/behaviors/tree.mjs +15 -15
  156. package/dist/behaviors/upload.d.mts +3 -2
  157. package/dist/behaviors/upload.mjs +1076 -66
  158. package/dist/cli.mjs +5 -6
  159. package/dist/components/ai-chat.css +666 -573
  160. package/dist/components/ai-diff.css +153 -132
  161. package/dist/components/ai-panel.css +351 -343
  162. package/dist/components/ai-tool.css +393 -238
  163. package/dist/components/autocomplete.css +61 -0
  164. package/dist/components/autocomplete.mjs +3 -0
  165. package/dist/components/back-top.css +34 -31
  166. package/dist/components/badge.css +44 -41
  167. package/dist/components/breadcrumb.css +67 -46
  168. package/dist/components/btn.css +80 -74
  169. package/dist/components/card.css +117 -106
  170. package/dist/components/cascader.css +311 -0
  171. package/dist/components/cascader.mjs +3 -0
  172. package/dist/components/chart-area.css +8 -2
  173. package/dist/components/chart-bar.css +95 -33
  174. package/dist/components/chart-gauge.css +14 -11
  175. package/dist/components/chart-graph.css +20 -17
  176. package/dist/components/chart-heatmap.css +96 -90
  177. package/dist/components/chart-line.css +8 -3
  178. package/dist/components/chart-pie.css +9 -6
  179. package/dist/components/chart-radar.css +8 -5
  180. package/dist/components/chart-scatter.css +9 -6
  181. package/dist/components/chart-sparkline.css +5 -2
  182. package/dist/components/chart-stack.css +14 -11
  183. package/dist/components/charts.css +164 -73
  184. package/dist/components/code-block.css +418 -0
  185. package/dist/components/code-block.mjs +4 -0
  186. package/dist/components/command-palette.css +138 -117
  187. package/dist/components/content.css +257 -251
  188. package/dist/components/copy.css +72 -44
  189. package/dist/components/datatable.css +423 -181
  190. package/dist/components/date-picker.css +135 -104
  191. package/dist/components/empty.css +68 -65
  192. package/dist/components/feedback.css +201 -183
  193. package/dist/components/form-validate.css +120 -0
  194. package/dist/components/form-validate.mjs +3 -0
  195. package/dist/components/form.css +150 -127
  196. package/dist/components/icon.css +102 -0
  197. package/dist/components/icon.mjs +3 -0
  198. package/dist/components/input.css +159 -104
  199. package/dist/components/kb-agent.css +188 -173
  200. package/dist/components/kb-data.css +257 -253
  201. package/dist/components/kb-ground.css +197 -185
  202. package/dist/components/kb-ingest.css +334 -350
  203. package/dist/components/kb-ops.css +265 -259
  204. package/dist/components/kb-perm.css +260 -271
  205. package/dist/components/kb-search.css +317 -360
  206. package/dist/components/kb.css +120 -109
  207. package/dist/components/layout.css +85 -82
  208. package/dist/components/material-chinese.css +73 -0
  209. package/dist/components/material-soviet.css +76 -0
  210. package/dist/components/material.css +275 -0
  211. package/dist/components/media.css +220 -166
  212. package/dist/components/mentions.css +189 -0
  213. package/dist/components/mentions.mjs +3 -0
  214. package/dist/components/menu.css +113 -105
  215. package/dist/components/modal.css +107 -112
  216. package/dist/components/nav.css +118 -115
  217. package/dist/components/notification.css +238 -174
  218. package/dist/components/pagination.css +56 -53
  219. package/dist/components/panel.css +66 -63
  220. package/dist/components/panel.mjs +1 -0
  221. package/dist/components/pill.css +81 -71
  222. package/dist/components/popover.css +67 -53
  223. package/dist/components/scroll-area.css +113 -110
  224. package/dist/components/segmented.css +146 -143
  225. package/dist/components/select.css +206 -186
  226. package/dist/components/sidebar.css +137 -127
  227. package/dist/components/slider.css +117 -114
  228. package/dist/components/split-pane.css +112 -109
  229. package/dist/components/stat.css +112 -106
  230. package/dist/components/steps.css +109 -103
  231. package/dist/components/switch.css +138 -134
  232. package/dist/components/table.css +131 -107
  233. package/dist/components/tabs.css +114 -108
  234. package/dist/components/tag-input.css +48 -133
  235. package/dist/components/tag.css +81 -71
  236. package/dist/components/theme-switcher.css +105 -0
  237. package/dist/components/theme-switcher.mjs +3 -0
  238. package/dist/components/toast.css +100 -86
  239. package/dist/components/toolbar.css +45 -42
  240. package/dist/components/tooltip.css +102 -43
  241. package/dist/components/tooltip.mjs +1 -0
  242. package/dist/components/tree-select.css +416 -0
  243. package/dist/components/tree-select.mjs +3 -0
  244. package/dist/components/upload.css +135 -92
  245. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  246. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  247. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  248. package/dist/fonts/OFL.txt +96 -0
  249. package/dist/fonts/README.md +14 -0
  250. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  251. package/dist/index.d.mts +28 -14
  252. package/dist/index.mjs +20705 -9601
  253. package/dist/react.d.mts +91 -0
  254. package/dist/react.mjs +8208 -0
  255. package/dist/registry.json +130 -13
  256. package/dist/tokens/chinese.css +44 -0
  257. package/dist/tokens/colors.css +365 -1222
  258. package/dist/tokens/design.css +109 -0
  259. package/dist/tokens/dtcg.json +11198 -0
  260. package/dist/tokens/figma.variables.json +7017 -0
  261. package/dist/tokens/icon-masks.css +78 -0
  262. package/dist/tokens/pixel.css +50 -0
  263. package/dist/tokens/soviet.css +44 -0
  264. package/dist/tokens/style-profiles.css +36 -547
  265. package/dist/tokens/themes.json +308 -0
  266. package/dist/tokens/tokens-studio.json +6728 -0
  267. package/dist/tokens/typography.css +21 -18
  268. package/dist/tokens.css +1555 -1801
  269. package/dist/ui.css +11975 -9831
  270. package/dist/vue.d.mts +344 -0
  271. package/dist/vue.mjs +7781 -0
  272. package/docs/spec/ai-input-experience.md +75 -0
  273. package/docs/spec/ai-native.md +238 -147
  274. package/docs/spec/design-philosophy.md +189 -0
  275. package/docs/spec/design-primitives.md +196 -0
  276. package/docs/spec/kb-family.md +147 -115
  277. package/package.json +43 -8
  278. package/dist/retro-effects.css +0 -255
  279. package/dist/tokens/retro-effects.css +0 -255
  280. package/docs/research/2026-10-03-ai-kb-components.md +0 -392
  281. package/docs/research/2026-10-03-kb-permissions.md +0 -992
@@ -1,52 +1,1007 @@
1
+ // src/behaviors/icons.ts
2
+ var ICON_PATHS = {
3
+ file: "M6 2.5h5.5L16 7v9.5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-12a2 2 0 0 1 2-2ZM11.5 2.5V7H16",
4
+ folder: "M3 5a1.5 1.5 0 0 1 1.5-1.5H8l2 2h5.5A1.5 1.5 0 0 1 17 7v8a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 3 15Z",
5
+ globe: "M17.5 10a7.5 7.5 0 1 1-15 0 7.5 7.5 0 0 1 15 0ZM2.5 10h15M10 2.5c-4 4-4 11 0 15 4-4 4-11 0-15Z",
6
+ document: "M6 2.5h5.5L16 7v9.5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-12a2 2 0 0 1 2-2ZM11.5 2.5V7H16M7 10.5h6M7 13.5h6",
7
+ agent: "M10 6V3M8 3h2M5 6h10a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2ZM1.5 10h1.5M17 10h1.5M7 10v2M13 10v2M8 14h4",
8
+ paperclip: "M14 7 8.3 12.7a1.6 1.6 0 0 1-2.3-2.3l6.3-6.3a3.2 3.2 0 0 1 4.5 4.5l-7 7a4.7 4.7 0 0 1-6.7-6.7l7-7",
9
+ stop: "M6.5 5h7A1.5 1.5 0 0 1 15 6.5v7a1.5 1.5 0 0 1-1.5 1.5h-7A1.5 1.5 0 0 1 5 13.5v-7A1.5 1.5 0 0 1 6.5 5Z",
10
+ terminal: "M5 3.5h10a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2ZM6 7l3 3-3 3M11 13h3",
11
+ branch: "M6 6v8M14 6v2a4 4 0 0 1-4 4H6M8 4a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM8 16a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM16 4a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z",
12
+ "line-numbers": "M3 5h2M3 10h2M3 15h2M8 5h9M8 10h9M8 15h9",
13
+ wrap: "M3 5h14M3 10h10a3 3 0 0 1 0 6h-3M12.5 13.5 10 16l2.5 2.5",
14
+ calendar: "M5.5 4h9A2.5 2.5 0 0 1 17 6.5v8a2.5 2.5 0 0 1-2.5 2.5h-9A2.5 2.5 0 0 1 3 14.5v-8A2.5 2.5 0 0 1 5.5 4ZM6.5 2.5v3M13.5 2.5v3M3 8h14M6.5 11h.1M10 11h.1M13.5 11h.1M6.5 14h.1M10 14h.1",
15
+ close: "M6 6l8 8M14 6l-8 8",
16
+ check: "M4.5 10.2l3.6 3.6 7.4-7.6",
17
+ "chevron-down": "M5.5 7.75 10 12.25l4.5-4.5",
18
+ "chevron-up": "M5.5 12.25 10 7.75l4.5 4.5",
19
+ "chevron-right": "M7.75 5.5 12.25 10l-4.5 4.5",
20
+ "chevron-left": "M12.25 5.5 7.75 10l4.5 4.5",
21
+ "arrow-right": "M3.5 10h13M11 4.5l5.5 5.5-5.5 5.5",
22
+ "arrow-left": "M16.5 10h-13M9 4.5 3.5 10 9 15.5",
23
+ "arrow-up": "M10 16.5v-13M4.5 9 10 3.5 15.5 9",
24
+ "arrow-down": "M10 3.5v13M4.5 11l5.5 5.5 5.5-5.5",
25
+ plus: "M10 4v12M4 10h12",
26
+ minus: "M4 10h12",
27
+ sort: "M6 15V4M3 7l3-3 3 3M14 5v11M11 13l3 3 3-3",
28
+ search: "M13.3 13.3 17 17M14.5 8.5a6 6 0 1 1-12 0 6 6 0 0 1 12 0",
29
+ sun: "M13.5 10a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0M10 1.75v1.5M10 16.75v1.5M1.75 10h1.5M16.75 10h1.5M4.17 4.17l1.06 1.06M14.77 14.77l1.06 1.06M4.17 15.83l1.06-1.06M14.77 5.23l1.06-1.06",
30
+ moon: "M17.25 11.15A7.5 7.5 0 0 1 8.85 2.75a7.5 7.5 0 1 0 8.4 8.4Z",
31
+ modern: "M6.5 3h7A3.5 3.5 0 0 1 17 6.5v7a3.5 3.5 0 0 1-3.5 3.5h-7A3.5 3.5 0 0 1 3 13.5v-7A3.5 3.5 0 0 1 6.5 3ZM7 10l3-3 3 3-3 3Z",
32
+ pixel: "M3 3h5v5H3ZM12 3h5v5h-5ZM3 12h5v5H3ZM12 12h5v5h-5Z",
33
+ chinese: "M3 8c3 0 5-2 7-5 2 3 4 5 7 5M4 8h12M6 8v8m8-8v8M3 16h14M8 16v-5h4v5",
34
+ soviet: "M3 17h14M5 17V8h4v9m0-12h6v12M7 8V5h2m2 3h2m-2 3h2m-2 3h2M10 5V3h4v2",
35
+ more: "M4 9.9v.2M10 9.9v.2M16 9.9v.2",
36
+ copy: "M7 7h8a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2V7ZM13 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2",
37
+ edit: "M11.5 4.5l4 4M4 12l9-9a1.4 1.4 0 0 1 2 0l2 2a1.4 1.4 0 0 1 0 2l-9 9-5 1Z",
38
+ link: "M8 6l2-2a4.2 4.2 0 0 1 6 6l-2 2M12 14l-2 2a4.2 4.2 0 0 1-6-6l2-2M7 13l6-6",
39
+ trash: "M3.5 5.5h13M7 5.5V3h6v2.5M5 5.5l.7 11.5h8.6L15 5.5M8 9v5M12 9v5",
40
+ spinner: "M10 3a7 7 0 1 1-7 7",
41
+ "circle-check": "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM6 10l2.7 2.7 5.3-5.4",
42
+ "circle-error": "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM7.2 7.2l5.6 5.6M12.8 7.2l-5.6 5.6",
43
+ "circle-info": "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM10 9v5M10 6.1v.15",
44
+ "triangle-alert": "M8.7 3.5a1.5 1.5 0 0 1 2.6 0l6.4 11.3a1.5 1.5 0 0 1-1.3 2.2H3.6a1.5 1.5 0 0 1-1.3-2.2ZM10 7.2v4.4M10 14v.15",
45
+ refresh: "M16.5 7.2A7 7 0 0 0 4.3 5.9L2.5 8M2.5 3.5V8H7M3.5 12.8a7 7 0 0 0 12.2 1.3l1.8-2.1M13 12h4.5v4.5",
46
+ external: "M11.5 3H17v5.5M17 3l-8 8M8 3H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3",
47
+ home: "M3.5 10.25 10 4l6.5 6.25M5.75 8.75v7a.75.75 0 0 0 .75.75h7.5a.75.75 0 0 0 .75-.75v-7",
48
+ settings: "M3.5 5.5h13M3.5 10h13M3.5 14.5h13M7 4v3M12.5 8.5v3M8 13v3",
49
+ star: "M10 2.5l2.4 5.1 5.6.4-4.2 3.7 1.3 5.5-5.1-3-5.1 3 1.3-5.5L1.8 8l5.6-.4Z",
50
+ eye: "M2.2 10s3-5.4 7.8-5.4S17.8 10 17.8 10s-3 5.4-7.8 5.4S2.2 10 2.2 10ZM10 12.4a2.4 2.4 0 1 0 0-4.8 2.4 2.4 0 0 0 0 4.8Z",
51
+ "eye-off": "M2.2 10s3-5.4 7.8-5.4S17.8 10 17.8 10s-3 5.4-7.8 5.4S2.2 10 2.2 10ZM10 12.4a2.4 2.4 0 1 0 0-4.8 2.4 2.4 0 0 0 0 4.8ZM3.5 3.5l13 13",
52
+ inbox: "M3.5 12.25h3.7l1.5 2.5h2.6l1.5-2.5h3.7M4.7 5.5l-1.2 6.75v3.25a1.5 1.5 0 0 0 1.5 1.5h10a1.5 1.5 0 0 0 1.5-1.5v-3.25L15.3 5.5a1.3 1.3 0 0 0-1.25-1H5.95a1.3 1.3 0 0 0-1.25 1Z",
53
+ bell: "M10 3.5a4.5 4.5 0 0 1 4.5 4.5c0 4.5 1.8 5.7 2.5 6.5H3c.7-.8 2.5-2 2.5-6.5A4.5 4.5 0 0 1 10 3.5ZM8.5 16.5a1.6 1.6 0 0 0 3 0",
54
+ users: "M13.8 16.5v-1.5a3.5 3.5 0 0 0-3.5-3.5H6.3a3.5 3.5 0 0 0-3.5 3.5v1.5M8.3 8.9a2.7 2.7 0 1 0 0-5.4 2.7 2.7 0 0 0 0 5.4ZM16.5 16.5v-1.3a3.3 3.3 0 0 0-2.3-3.1M12.3 3.7a2.7 2.7 0 0 1 0 5.2",
55
+ activity: "M17 10h-2.6l-2 5.8L8 4.2 6 10H3",
56
+ "trend-up": "M3.5 14.5l4.2-4.2 2.8 2.8 5.9-5.9M12.4 7.2h4.2v4.2",
57
+ "trend-down": "M3.5 5.5l4.2 4.2 2.8-2.8 5.9 5.9M12.4 12.8h4.2V8.6",
58
+ rocket: "M10 2.5c2 1.5 3.2 4 3.2 6.8 0 1.5-.3 2.9-.8 4.2H7.6c-.5-1.3-.8-2.7-.8-4.2 0-2.8 1.2-5.3 3.2-6.8ZM10 8.6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM7.6 12.5 5.6 15.4c-.9.3-1.6 1-2 2M12.4 12.5l2 2.9c.9.3 1.6 1 2 2M8.7 13.8c0 1.8.5 3.1 1.3 4.2.8-1.1 1.3-2.4 1.3-4.2",
59
+ bold: "M6.5 4h4.2a3 3 0 0 1 0 6H6.5M6.5 10h5a3 3 0 0 1 0 6H6.5M6.5 4v12",
60
+ italic: "M8.5 4.5h7M4.5 15.5h7M12.5 4.5l-5 11",
61
+ underline: "M6 4v5.5a4 4 0 0 0 8 0V4M4.5 16h11",
62
+ "align-left": "M3.5 4.5h13M3.5 10h8.5M3.5 15.5h11",
63
+ "align-center": "M3.5 4.5h13M5.75 10h8.5M4.5 15.5h11",
64
+ "align-right": "M3.5 4.5h13M8 10h8.5M5.5 15.5h11",
65
+ list: "M6.5 5h10M6.5 10h10M6.5 15h10M3.5 5h.01M3.5 10h.01M3.5 15h.01",
66
+ server: "M3 3h14a1.5 1.5 0 0 1 1.5 1.5v2A1.5 1.5 0 0 1 17 8H3a1.5 1.5 0 0 1-1.5-1.5v-2A1.5 1.5 0 0 1 3 3ZM3 12h14a1.5 1.5 0 0 1 1.5 1.5v2A1.5 1.5 0 0 1 17 17H3a1.5 1.5 0 0 1-1.5-1.5v-2A1.5 1.5 0 0 1 3 12ZM5 5.5h.01M5 14.5h.01",
67
+ sparkle: "M10 2.5l1.6 4.3 4.3 1.6-4.3 1.6L10 14.3l-1.6-4.3-4.3-1.6 4.3-1.6ZM15.5 12.5l.8 2.1 2.1.8-2.1.8-.8 2.1-.8-2.1-2.1-.8 2.1-.8Z",
68
+ play: "M6.5 4.8v10.4c0 .9 1 1.5 1.8 1l8.3-5.2a1.2 1.2 0 0 0 0-2L8.3 3.8a1.2 1.2 0 0 0-1.8 1Z",
69
+ "chart-line": "M3.5 3.5v13h13M6.5 12l2.8-2.8 2.2 2.2 4-4.4",
70
+ layers: "M10 3.2 3.6 6.5 10 9.8l6.4-3.3ZM4.5 10.4 10 13.2l5.5-2.8M4.5 13.6 10 16.4l5.5-2.8",
71
+ box: "M17 6 10 3.2 3 6v8l7 2.8 7-2.8ZM3 6l7 2.8L17 6M10 9v7.8",
72
+ filter: "M4 4.5h12l-4.4 5.1v5l-3.2-1.6V9.6Z",
73
+ columns: "M3.5 4h13v12h-13ZM8.2 4v12M12.8 4v12",
74
+ download: "M10 3.5v8M6.8 8.3 10 11.5l3.2-3.2M4 15v2.5a1.5 1.5 0 0 0 1.5 1.5h9a1.5 1.5 0 0 0 1.5-1.5V15"
75
+ };
76
+ var custom = /* @__PURE__ */ new Map();
77
+ var escape = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
78
+ function iconPath(name) {
79
+ return Object.hasOwn(ICON_PATHS, name) ? ICON_PATHS[name] : custom.get(name) ?? null;
80
+ }
81
+ function iconAttributes(o = {}) {
82
+ const size = Number.isFinite(o.size) && o.size > 0 ? o.size : 16;
83
+ return { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", width: String(size), height: String(size), fill: "none", stroke: "currentColor", "stroke-width": "1.6", "stroke-linecap": "round", "stroke-linejoin": "round", focusable: "false", class: ["icen-symbol", o.className].filter(Boolean).join(" "), ...o.label ? { role: "img", "aria-label": o.label } : { "aria-hidden": "true" } };
84
+ }
85
+ function iconHTML(name, o = {}) {
86
+ const path = iconPath(name);
87
+ if (!path) return "";
88
+ return `<svg${Object.entries(iconAttributes(o)).map(([k, v]) => ` ${k}="${escape(v)}"`).join("")}><path d="${escape(path)}"></path></svg>`;
89
+ }
90
+ function createIcon(name, o = {}) {
91
+ if (typeof document === "undefined") return null;
92
+ const path = iconPath(name);
93
+ if (!path) return null;
94
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
95
+ for (const [key, value] of Object.entries(iconAttributes(o))) svg.setAttribute(key, value);
96
+ const line = document.createElementNS(svg.namespaceURI, "path");
97
+ line.setAttribute("d", path);
98
+ svg.append(line);
99
+ return svg;
100
+ }
101
+
102
+ // src/behaviors/events.ts
103
+ function emitIcen(source, type, detail) {
104
+ return source.dispatchEvent(
105
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
106
+ );
107
+ }
108
+
109
+ // src/behaviors/i18n.ts
110
+ var ICEN_LOCALE_ZH_CN = {
111
+ /* ── aiBranch ── */
112
+ "aiBranch.nextVersion": "\u4E0B\u4E00\u7248\u672C",
113
+ "aiBranch.prevVersion": "\u4E0A\u4E00\u7248\u672C",
114
+ "aiBranch.version": "\u5206\u652F\u7248\u672C",
115
+ /* ── aiChat ── */
116
+ "aiChat.backToBottom": "\u56DE\u5230\u5E95\u90E8",
117
+ "aiChat.backToBottomCount": "\u56DE\u5230\u5E95\u90E8 \xB7 {p0} \u6761\u65B0\u6D88\u606F",
118
+ "aiChat.continue": "\u7EE7\u7EED\u751F\u6210",
119
+ "aiChat.download": "\u4E0B\u8F7D",
120
+ "aiChat.file": "\u6587\u4EF6",
121
+ "aiChat.roleSystem": "\u7CFB",
122
+ "aiChat.roleTool": "\u5DE5",
123
+ "aiChat.roleUser": "\u6211",
124
+ "aiChat.thinking": "\u601D\u8003 {p0}",
125
+ /* ── aiComposer ── */
126
+ "aiComposer.attachAgent": "\u4EE3\u7406",
127
+ "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
128
+ "aiComposer.searchLibrary": "\u641C\u7D22\u6280\u80FD\u3001\u5DE5\u5177\u3001\u6587\u4EF6\u4E0E\u547D\u4EE4",
129
+ "aiComposer.all": "\u5168\u90E8",
130
+ "aiComposer.skills": "\u6280\u80FD",
131
+ "aiComposer.tools": "\u5DE5\u5177",
132
+ "aiComposer.libraryHint": "\u4E0A\u4E0B\u6587\u968F\u6D88\u606F\u53D1\u9001 \xB7 \u547D\u4EE4\u5148\u586B\u5165\u8F93\u5165\u6846",
133
+ "aiComposer.commandHint": "\u2191 \u2193 \u6D4F\u89C8 \xB7 Enter \u6267\u884C \xB7 Esc \u8FD4\u56DE",
134
+ "aiComposer.refHint": "\u2191 \u2193 \u6D4F\u89C8 \xB7 Enter \u5F15\u7528 \xB7 Esc \u8FD4\u56DE",
135
+ "aiComposer.noLibraryMatch": "\u6CA1\u6709\u5339\u914D\u7684\u9879\u76EE\uFF0C\u8BD5\u8BD5\u5176\u4ED6\u5173\u952E\u8BCD",
136
+ "aiComposer.filesNeedAdapter": "\u9644\u4EF6\u5C1A\u672A\u63A5\u901A\u4E0A\u4F20\u3002\u8BF7\u914D\u7F6E prepareMessage \u540E\u91CD\u8BD5\uFF0C\u6587\u4EF6\u4ECD\u4FDD\u7559\u5728\u6B64\u8BF7\u6C42\u4E2D\u3002",
137
+ "aiComposer.attachDoc": "\u6587\u6863",
138
+ "aiComposer.attachFile": "\u6587\u4EF6",
139
+ "aiComposer.attachFolder": "\u6587\u4EF6\u5939",
140
+ "aiComposer.cacheInvalidHint": "\u5207\u6362\u6A21\u578B\u4F1A\u4F7F prompt \u7F13\u5B58\u5931\u6548",
141
+ "aiComposer.commands": "\u547D\u4EE4",
142
+ "aiComposer.currentTodos": "\u5F53\u524D\u5F85\u529E",
143
+ "aiComposer.done": "\u5B8C\u6210",
144
+ "aiComposer.justNow": "\u521A\u521A \xB7 {p0}",
145
+ "aiComposer.modelAria": "\u6A21\u578B {p0}\uFF08{p1}\uFF09",
146
+ "aiComposer.noCommandMatch": "\u65E0\u5339\u914D\u547D\u4EE4",
147
+ "aiComposer.noModelMatch": "\u65E0\u5339\u914D\u6A21\u578B",
148
+ "aiComposer.noRefMatch": "\u65E0\u5339\u914D\u5F15\u7528",
149
+ "aiComposer.placeholder": "\u8F93\u5165\u6D88\u606F\uFF0C/ \u547D\u4EE4 \xB7 @ \u5F15\u7528 \xB7 Enter \u53D1\u9001",
150
+ "aiComposer.refs": "\u5F15\u7528",
151
+ "aiComposer.removeAttachment": "\u79FB\u9664\u9644\u4EF6 {p0}",
152
+ "aiComposer.removeQueued": "\u79FB\u9664\u6392\u961F\u6D88\u606F {p0}",
153
+ "aiComposer.removeRef": "\u79FB\u9664\u5F15\u7528 {p0}",
154
+ "aiComposer.searchModels": "\u641C\u7D22\u6A21\u578B",
155
+ "aiComposer.selectModel": "\u9009\u62E9\u6A21\u578B",
156
+ "aiComposer.send": "\u53D1\u9001",
157
+ "aiComposer.stop": "\u505C\u6B62\u751F\u6210",
158
+ "aiComposer.stopped": "\u5DF2\u505C\u6B62",
159
+ "aiComposer.todoChip": "\u5F53\u524D\u5F85\u529E {p0}/{p1}{p2}",
160
+ "aiComposer.todoHasError": "\uFF08\u6709\u5931\u8D25\u9879\uFF09",
161
+ /* ── aiCore ── */
162
+ "aiCore.kindBrowser": "\u6D4F\u89C8",
163
+ "aiCore.kindChart": "\u56FE\u8868",
164
+ "aiCore.kindDelete": "\u5220\u9664",
165
+ "aiCore.kindEdit": "\u7F16\u8F91",
166
+ "aiCore.kindFetch": "\u8BF7\u6C42",
167
+ "aiCore.kindGlob": "\u5339\u914D",
168
+ "aiCore.kindGrep": "\u641C\u7D22",
169
+ "aiCore.kindNote": "\u7B14\u8BB0",
170
+ "aiCore.kindPlan": "\u8BA1\u5212",
171
+ "aiCore.kindRead": "\u8BFB\u53D6",
172
+ "aiCore.kindSearch": "\u68C0\u7D22",
173
+ "aiCore.kindShell": "\u547D\u4EE4",
174
+ "aiCore.kindSkill": "\u6280\u80FD",
175
+ "aiCore.kindSubagent": "\u5B50\u4EE3\u7406",
176
+ "aiCore.kindTodo": "\u5F85\u529E",
177
+ "aiCore.kindWrite": "\u5199\u5165",
178
+ "aiCore.statusApproval": "\u5F85\u786E\u8BA4",
179
+ "aiCore.statusCancelled": "\u5DF2\u53D6\u6D88",
180
+ "aiCore.statusDone": "\u5B8C\u6210",
181
+ "aiCore.statusError": "\u5931\u8D25",
182
+ "aiCore.statusPending": "\u7B49\u5F85",
183
+ "aiCore.statusRunning": "\u6267\u884C\u4E2D",
184
+ "aiCore.statusStreaming": "\u6D41\u5F0F\u4E2D",
185
+ "aiCore.todoProgress": "{p0}/{p1} \u5B8C\u6210",
186
+ /* ── aiDiff ── */
187
+ "aiDiff.accepted": "\u5DF2\u63A5\u53D7",
188
+ "aiDiff.binary": "\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u663E\u793A\u6587\u672C\u5DEE\u5F02",
189
+ "aiDiff.empty": "\u65E0\u5DEE\u5F02\u5185\u5BB9",
190
+ "aiDiff.rejected": "\u5DF2\u62D2\u7EDD",
191
+ /* ── aiFeedback ── */
192
+ "aiFeedback.helpful": "\u6709\u5E2E\u52A9",
193
+ "aiFeedback.notHelpful": "\u65E0\u5E2E\u52A9",
194
+ "aiFeedback.reasonCitationMismatch": "\u5F15\u7528\u4E0D\u7B26",
195
+ "aiFeedback.reasonOutdated": "\u5185\u5BB9\u8FC7\u65F6",
196
+ "aiFeedback.reasonUnauthorized": "\u8D8A\u6743\u4FE1\u606F",
197
+ "aiFeedback.reasonUnsourced": "\u65E0\u5F15\u7528\u4F9D\u636E",
198
+ "aiFeedback.reasonWrong": "\u7B54\u6848\u6709\u8BEF",
199
+ "aiFeedback.thanks": "\u611F\u8C22\u53CD\u9988\uFF0C\u5DF2\u5173\u8054\u5230\u8BE5\u6761\u56DE\u7B54\u7684\u8FFD\u8E2A\u8BB0\u5F55",
200
+ /* ── aiPanel ── */
201
+ "aiPanel.audit": "\u5BA1\u8BA1",
202
+ "aiPanel.cacheRead": "\u7F13\u5B58\u8BFB",
203
+ "aiPanel.cacheWrite": "\u7F13\u5B58\u5199",
204
+ "aiPanel.callsTokens": "{p0} \u6B21 \xB7 {p1} tok{p2}",
205
+ "aiPanel.clearAudit": "\u6E05\u9664\u5BA1\u8BA1",
206
+ "aiPanel.context": "\u4E0A\u4E0B\u6587",
207
+ "aiPanel.contextWindow": "\u4E0A\u4E0B\u6587\u7A97\u53E3",
208
+ "aiPanel.errorsCount": "{p0} \u5931\u8D25",
209
+ "aiPanel.files": "\u6587\u4EF6 ({p0})",
210
+ "aiPanel.itemStatus": "{p0}\uFF0C\u72B6\u6001\uFF1A{p1}",
211
+ "aiPanel.noAudit": "\u6682\u65E0\u5BA1\u8BA1\u8BB0\u5F55",
212
+ "aiPanel.noUsage": "\u6682\u65E0\u7528\u91CF",
213
+ "aiPanel.reasoning": "\u63A8\u7406",
214
+ "aiPanel.requestsCount": "{p0} \u6B21\u8BF7\u6C42",
215
+ "aiPanel.ringPercent": "\u4E0A\u4E0B\u6587\u7A97\u53E3\u5360\u7528 {p0}%\uFF0C\u70B9\u51FB\u67E5\u770B\u8BE6\u60C5",
216
+ "aiPanel.ringUsed": "\u5DF2\u7528 {p0}\uFF0C\u70B9\u51FB\u67E5\u770B\u8BE6\u60C5",
217
+ "aiPanel.taskProgress": "\u4EFB\u52A1\u8FDB\u5EA6",
218
+ "aiPanel.toolsCount": "{p0} \u5DE5\u5177",
219
+ "aiPanel.usage": "\u7528\u91CF",
220
+ "aiPanel.usageAria": "\u7528\u91CF\uFF1A{p0}",
221
+ /* ── aiProvider ── */
222
+ "aiProvider.audioUrlOnly": "\u4EC5 URL \u7684\u97F3\u9891\uFF08input_audio \u9700 base64\uFF0C\u8BF7\u5148\u53D6\u56DE\u5185\u8054\uFF09",
223
+ "aiProvider.audioUrlOnlyAnthropic": "\u4EC5 URL \u7684\u97F3\u9891\uFF08audio \u5757\u9700 base64 source\uFF09",
224
+ "aiProvider.base64File": "base64 \u6587\u4EF6\uFF08file \u90E8\u4EF6\u9700 Files API file_id\uFF0C\u8BF7\u7F6E\u4E8E url \u69FD\uFF09",
225
+ "aiProvider.corsHint": "\uFF1B\u6D4F\u89C8\u5668\u76F4\u8FDE {p0}\uFF08{p1}\uFF09\u5F88\u53EF\u80FD\u88AB CORS \u62E6\u622A\uFF0C\u5EFA\u8BAE\u7ECF\u4EE3\u7406/\u81EA\u5EFA\u7F51\u5173\u8F6C\u53D1",
226
+ "aiProvider.emptyResponse": "\u54CD\u5E94\u4E3A\u7A7A",
227
+ "aiProvider.glmLabel": "GLM\uFF08\u667A\u8C31\uFF09",
228
+ "aiProvider.invalidJson": "\u54CD\u5E94\u4E0D\u662F\u5408\u6CD5 JSON",
229
+ "aiProvider.kimiLabel": "Kimi\uFF08\u6708\u4E4B\u6697\u9762\uFF09",
230
+ "aiProvider.networkFailed": "\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25\uFF1A{p0}{p1}",
231
+ "aiProvider.nonPdfDocument": "\u975E PDF \u6587\u4EF6\u5757\uFF08document \u5757\u4E3A application/pdf\uFF0C\u6536\u5230 {p0}\uFF09",
232
+ "aiProvider.requestCancelled": "\u8BF7\u6C42\u5DF2\u53D6\u6D88",
233
+ "aiProvider.resourceRef": "[\u8D44\u6E90] {p0} ({p1})",
234
+ "aiProvider.streamError": "\u6D41\u5F0F\u54CD\u5E94\u9519\u8BEF",
235
+ "aiProvider.toolRoleNoCallId": "role 'tool' \u4E14\u7F3A toolCallId\uFF08openai \u65CF\u9700 tool_call_id\uFF09",
236
+ "aiProvider.toolRoleNoUseId": "role 'tool' \u4E14\u7F3A toolCallId\uFF08anthropic \u65CF\u6620\u5C04 tool_result \u9700 tool_use_id\uFF09",
237
+ "aiProvider.unsupported": "{p0} \u7EBF\u534F\u8BAE\u4E0D\u652F\u6301 {p1}",
238
+ "aiProvider.videoUnsupported": "video \u8F93\u5165\uFF08\u65E0\u4E3B\u6D41 chat API \u652F\u6301\uFF09",
239
+ "aiProvider.videoUnsupportedAnthropic": "video \u8F93\u5165",
240
+ /* ── aiThreads ── */
241
+ "aiThreads.actionsAria": "\u4F1A\u8BDD\u64CD\u4F5C",
242
+ "aiThreads.archived": "\u5DF2\u5F52\u6863",
243
+ /* ── aiTool ── */
244
+ "aiTool.allow": "\u5141\u8BB8",
245
+ "aiTool.reject": "\u62D2\u7EDD",
246
+ /* ── aiTools ── */
247
+ "aiTools.chart.area": "line \u591A\u7CFB\u5217\u586B\u5145\u9762\u79EF",
248
+ "aiTools.chart.data": "\u4EFB\u610F\u7EF4\u5EA6\u539F\u59CB\u8BB0\u5F55 + dims \u5B57\u6BB5\u6620\u5C04\uFF08\u81EA\u52A8\u900F\u89C6\u6210 \u7C7B\u76EE \xD7 \u7CFB\u5217\uFF09",
249
+ "aiTools.chart.dates": "\u8D21\u732E\u65E5\u5386 ISO \u65E5\u671F\uFF08\u4E0E values \u914D\u5BF9\uFF09",
250
+ "aiTools.chart.description": "\u5728\u7528\u6237\u754C\u9762\u6E32\u67D3\u4E00\u5F20\u56FE\u8868\u53EF\u89C6\u5316\u3002\u8F93\u5165\u4E00\u4EFD\u56FE\u8868\u89C4\u683C\uFF08\u7EAF JSON\uFF09\uFF1Alabels+values\uFF08\u7C7B\u76EE\u6570\u503C\uFF09\u3001series\uFF08\u591A\u7CFB\u5217\uFF09\u3001segments\uFF08\u5360\u6BD4\uFF09\u3001points\uFF08\u6563\u70B9\u6C14\u6CE1\uFF09\u3001dates\uFF08\u8D21\u732E\u65E5\u5386\uFF09\u4EFB\u7ED9\u5176\u4E00\uFF1Btype \u7F3A\u7701\u65F6\u6309\u6570\u636E\u5F62\u6001\u81EA\u52A8\u9009\u578B\uFF08\u65F6\u95F4\u5E8F\u5217\u2192\u6298\u7EBF\u3001\u5360\u6BD4\u2192\u73AF\u5F62\u3001\u65E5\u671F\u2192\u8D21\u732E\u65E5\u5386\u3001\u5750\u6807\u70B9\u2192\u6563\u70B9\uFF09\u3002\u56FE\u8868\u5E26\u4EA4\u4E92\uFF08\u60AC\u505C\u63D0\u793A/\u70B9\u51FB/\u53F3\u952E\uFF09\u4E0E\u53EF\u9690\u85CF\u56FE\u4F8B\u3002",
251
+ "aiTools.chart.dims": "data[] \u7684\u5B57\u6BB5\u6620\u5C04\uFF1A{label?, series?, value?, x?, y?}",
252
+ "aiTools.chart.format": "\u6570\u503C\u683C\u5F0F\u5316\uFF1A{notation?: compact|percent|ms, unit?}",
253
+ "aiTools.chart.labels": "\u7C7B\u76EE\u8F74\uFF08line/vbar/hbar\uFF09",
254
+ "aiTools.chart.legend": "false = \u521D\u59CB\u9690\u85CF\u56FE\u4F8B",
255
+ "aiTools.chart.lttb": "\u5927\u6570\u636E\u91CF\u964D\u91C7\u6837\uFF1Atrue=\u81EA\u52A8\u4E0A\u9650\uFF0C\u6570\u5B57=\u6700\u5927\u4FDD\u7559\u70B9\u6570\uFF08\u6E32\u67D3\u5C42\u5951\u7EA6\uFF0C\u968F\u56FE\u8868\u91CD\u5EA6\u573A\u666F\u843D\u5730\uFF09",
256
+ "aiTools.chart.marks": "\u6807\u8BB0\u5C42\uFF08\u9608\u503C\u7EBF/\u53C2\u8003\u533A\u95F4/\u5F3A\u8C03\u70B9\uFF09\uFF0C\u5143\u7D20\u4E3A\u7EAF JSON \u63CF\u8FF0\u5B50\uFF08\u6E32\u67D3\u5C42\u5951\u7EA6\uFF0C\u968F\u56FE\u8868\u91CD\u5EA6\u573A\u666F\u843D\u5730\uFF09",
257
+ "aiTools.chart.points": "\u6563\u70B9/\u6C14\u6CE1\uFF1A[{x,y,size?,label?}]",
258
+ "aiTools.chart.radarAxes": "\u96F7\u8FBE\u8F74\u540D",
259
+ "aiTools.chart.segments": "\u5360\u6BD4\u578B\uFF08donut/stack\uFF09\uFF1A[{label,value}]",
260
+ "aiTools.chart.series": "\u591A\u7CFB\u5217\uFF08line/vbar/radar\uFF09",
261
+ "aiTools.chart.stacked": "vbar \u591A\u7CFB\u5217\u5806\u53E0\uFF08\u9ED8\u8BA4\u5206\u7EC4\uFF09",
262
+ "aiTools.chart.title": "\u56FE\u8868\u6807\u9898\uFF08\u6E32\u67D3\u5728\u5934\u90E8\u884C\u5DE6\u4FA7\uFF09",
263
+ "aiTools.chart.tooltip": "false = \u5173\u95ED\u5185\u7F6E\u63D0\u793A",
264
+ "aiTools.chart.type": "\u56FE\u8868\u7C7B\u578B\uFF0C\u7F3A\u7701\u81EA\u52A8\u63A8\u65AD",
265
+ "aiTools.chart.values": "\u5355\u7CFB\u5217\u6570\u503C\uFF08\u4E0E labels \u914D\u5BF9\uFF09",
266
+ "aiTools.chart.zoom": "\u7F29\u653E\u4EA4\u4E92\uFF1A'x'=\u7C7B\u76EE\u8F74\u533A\u95F4\u7F29\u653E\uFF0C'brush'=\u5237\u9009\u7F29\u653E",
267
+ "aiTools.datatable.columns": "\u5217\u5B9A\u4E49\u6570\u7EC4\uFF1A\u6BCF\u9879 { key, title, sortable?, filterable? }\uFF08key \u5BF9\u5E94 rows \u5143\u7D20\u5B57\u6BB5\u540D\uFF09",
268
+ "aiTools.datatable.description": "\u5728\u7528\u6237\u754C\u9762\u6E32\u67D3\u4E00\u4E2A\u53EF\u641C\u7D22\u3001\u5206\u9875\u3001\u53EF\u5BFC\u51FA CSV \u7684\u6570\u636E\u8868\u683C\u3002\u8F93\u5165\u7EAF JSON\uFF1Acolumns \u4E3A\u5217\u5B9A\u4E49\uFF08key/title \u5FC5\u586B\uFF09\uFF0Crows \u4E3A\u884C\u5BF9\u8C61\u6570\u7EC4\uFF08\u5B57\u6BB5\u540D\u5BF9\u9F50\u5217 key\uFF09\u3002\u8FD4\u56DE { title, rows: \u884C\u6570 } \u6458\u8981\u3002",
269
+ "aiTools.datatable.rows": "\u884C\u6570\u636E\u6570\u7EC4\uFF1A\u6BCF\u9879\u4E3A\u4E00\u4E2A\u5BF9\u8C61\uFF0C\u5B57\u6BB5\u540D\u5BF9\u9F50 columns[].key",
270
+ "aiTools.datatable.title": "\u8868\u683C\u6807\u9898\uFF08\u6E32\u67D3\u5728\u5DE5\u5177\u680F\u5DE6\u4FA7\uFF09",
271
+ "aiTools.execFailed": "\u5DE5\u5177\u6267\u884C\u5931\u8D25\uFF1A{p0}",
272
+ "aiTools.execTimeout": "\u6267\u884C\u8D85\u65F6\uFF08{p0}ms\uFF09",
273
+ "aiTools.manifestHeader": "\u53EF\u7528 UI \u5DE5\u5177\uFF08\u8C03\u7528\u540E\u5728\u7528\u6237\u754C\u9762\u6302\u8F7D\u53EF\u89C6\u5316\u7ED3\u679C\uFF09\uFF1A",
274
+ "aiTools.missingRequired": "\u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5",
275
+ "aiTools.none": "\uFF08\u65E0\u5DF2\u6CE8\u518C\u7684 UI \u5DE5\u5177\uFF09",
276
+ "aiTools.notInEnum": "\u4E0D\u5728\u5141\u8BB8\u53D6\u503C\u5185\uFF08{p0}\uFF09",
277
+ "aiTools.numMax": "\u6570\u503C {p0} \u5927\u4E8E\u6700\u5927\u503C {p1}",
278
+ "aiTools.numMin": "\u6570\u503C {p0} \u5C0F\u4E8E\u6700\u5C0F\u503C {p1}",
279
+ "aiTools.removeMount": "\u79FB\u9664 {p0} \u6302\u8F7D",
280
+ "aiTools.strMax": "\u957F\u5EA6 {p0} \u8D85\u8FC7\u4E0A\u9650 {p1}",
281
+ "aiTools.strMin": "\u957F\u5EA6 {p0} \u5C0F\u4E8E\u4E0B\u9650 {p1}",
282
+ "aiTools.typeMismatch": "\u671F\u671B {p0}\uFF0C\u5B9E\u5F97 {p1}",
283
+ "aiTools.validationFailed": "\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF08{p0} \u9879\uFF09",
284
+ /* ── autocomplete ── */
285
+ "suggestions.loading": "\u6B63\u5728\u67E5\u627E\u5EFA\u8BAE\u2026",
286
+ "suggestions.error": "\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\u5EFA\u8BAE\uFF0C\u8BF7\u91CD\u8BD5\u3002",
287
+ "suggestions.options": "\u5EFA\u8BAE",
288
+ "suggestions.empty": "\u6CA1\u6709\u5339\u914D\u7684\u5EFA\u8BAE",
289
+ "autocomplete.empty": "\u65E0\u5339\u914D\u7ED3\u679C",
290
+ /* ── backTop ── */
291
+ "backTop.label": "\u56DE\u5230\u9876\u90E8",
292
+ /* ── carousel ── */
293
+ "carousel.item": "\u7B2C {p0} \u5F20",
294
+ "carousel.region": "\u8F6E\u64AD",
295
+ "carousel.slide": "\u5E7B\u706F\u7247",
296
+ "carousel.status": "\u7B2C {p0} / {p1} \u5F20",
297
+ /* ── charts ── */
298
+ "charts.calendarWeekdays": ["\u4E00", "", "\u4E09", "", "\u4E94", "", "\u65E5"],
299
+ "charts.few": "\u5C11",
300
+ "charts.hideLegend": "\u9690\u85CF\u56FE\u4F8B",
301
+ "charts.loading": "\u52A0\u8F7D\u4E2D",
302
+ "charts.many": "\u591A",
303
+ "charts.monthLabel": "{p0}\u6708",
304
+ "charts.noData": "\u6682\u65E0\u6570\u636E",
305
+ "charts.resetZoom": "\u91CD\u7F6E\u7F29\u653E",
306
+ "charts.sampled": "\u5DF2\u62BD\u6837 {p0}\u2192{p1} \u70B9",
307
+ "charts.type.area": "\u9762\u79EF\u56FE",
308
+ "charts.type.donut": "\u73AF\u5F62\u56FE",
309
+ "charts.type.gauge": "\u4EEA\u8868\u76D8",
310
+ "charts.type.graph": "\u77E5\u8BC6\u56FE\u8C31",
311
+ "charts.type.heatmap": "\u70ED\u529B\u56FE",
312
+ "charts.type.line": "\u6298\u7EBF\u56FE",
313
+ "charts.type.map": "\u5730\u56FE",
314
+ "charts.type.radar": "\u96F7\u8FBE\u56FE",
315
+ "charts.type.scatter": "\u6563\u70B9\u56FE",
316
+ "charts.type.sparkline": "\u8FF7\u4F60\u8D8B\u52BF",
317
+ "charts.seriesName": "\u7CFB\u5217{p0}",
318
+ "charts.showLegend": "\u663E\u793A\u56FE\u4F8B",
319
+ "charts.value": "\u6570\u503C",
320
+ /* ── themeSwitcher ── */
321
+ "themeSwitcher.appearance": "\u5916\u89C2",
322
+ "themeSwitcher.theme": "\u4E3B\u9898",
323
+ "themeSwitcher.primitive": "\u539F\u8BED",
324
+ "themeSwitcher.mode": "\u660E\u6697",
325
+ "themeSwitcher.light": "\u6D45\u8272",
326
+ "themeSwitcher.dark": "\u6DF1\u8272",
327
+ "themeSwitcher.modern": "\u73B0\u4EE3",
328
+ "themeSwitcher.dongyun": "\u4E1C\u97F5",
329
+ "themeSwitcher.jugou": "\u5DE8\u6784",
330
+ "themeSwitcher.piano": "\u94A2\u7434",
331
+ "themeSwitcher.monet": "\u83AB\u5948",
332
+ "themeSwitcher.vangogh": "\u68B5\u9AD8",
333
+ "themeSwitcher.chinese": "\u4E2D\u5F0F",
334
+ "themeSwitcher.soviet": "\u82CF\u5F0F",
335
+ "themeSwitcher.pixel": "\u50CF\u7D20",
336
+ /* ── codeBlock ── */
337
+ "codeBlock.collapse": "\u6536\u8D77",
338
+ "codeBlock.region": "\u4EE3\u7801\u5185\u5BB9",
339
+ "codeBlock.copyFailed": "\u672A\u80FD\u590D\u5236\uFF0C\u8BF7\u91CD\u8BD5\u3002",
340
+ "codeBlock.copyRetry": "\u91CD\u8BD5\u590D\u5236",
341
+ "codeBlock.copy": "\u590D\u5236",
342
+ "codeBlock.foldCollapse": "\u6298\u53E0\u4EE3\u7801",
343
+ "codeBlock.foldExpand": "\u5C55\u5F00\u4EE3\u7801",
344
+ "codeBlock.linesTotal": "\u5171 {p0} \u884C",
345
+ "codeBlock.numHide": "\u9690\u85CF\u884C\u53F7",
346
+ "codeBlock.numShow": "\u663E\u793A\u884C\u53F7",
347
+ "codeBlock.tailAria": "\u5C55\u5F00\u6216\u6536\u8D77\u4EE3\u7801",
348
+ "codeBlock.wrapOff": "\u5173\u95ED\u6362\u884C",
349
+ "codeBlock.wrapOn": "\u81EA\u52A8\u6362\u884C",
350
+ /* ── common ── */
351
+ "common.accept": "\u63A5\u53D7",
352
+ "common.add": "\u65B0\u589E",
353
+ "common.all": "\u5168\u90E8",
354
+ "common.approve": "\u6279\u51C6",
355
+ "common.cancel": "\u53D6\u6D88",
356
+ "common.actionFailed": "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u3002",
357
+ "common.close": "\u5173\u95ED",
358
+ "common.confirm": "\u786E\u8BA4",
359
+ "common.copied": "\u5DF2\u590D\u5236",
360
+ "common.copy": "\u590D\u5236",
361
+ "common.delete": "\u5220\u9664",
362
+ "common.enable": "\u542F\u7528",
363
+ "common.exportCsv": "\u5BFC\u51FA CSV",
364
+ "common.healthy": "\u6B63\u5E38",
365
+ "common.input": "\u8F93\u5165",
366
+ "common.loadingEllipsis": "\u52A0\u8F7D\u4E2D\u2026",
367
+ "common.official": "\u5B98\u65B9",
368
+ "common.output": "\u8F93\u51FA",
369
+ "common.page": "\u7B2C {p0} \u9875",
370
+ "common.reject": "\u62D2\u7EDD",
371
+ "common.remove": "\u79FB\u9664",
372
+ "common.requestAccess": "\u7533\u8BF7\u8BBF\u95EE",
373
+ "common.requestAccessFor": "\u7533\u8BF7\u8BBF\u95EE {p0}",
374
+ "common.restricted": "\u53D7\u9650",
375
+ "common.retry": "\u91CD\u8BD5",
376
+ "common.rows": "{p0} \u884C",
377
+ "common.run": "\u8FD0\u884C",
378
+ "common.steps": "{p0} \u6B65",
379
+ "common.submit": "\u63D0\u4EA4",
380
+ "common.unknown": "\u672A\u77E5",
381
+ /* ── contextMenu ── */
382
+ "contextMenu.back": "\u540E\u9000",
383
+ "contextMenu.copyPageLink": "\u590D\u5236\u9875\u9762\u94FE\u63A5",
384
+ "contextMenu.forward": "\u524D\u8FDB",
385
+ "contextMenu.refresh": "\u5237\u65B0",
386
+ /* ── copy ── */
387
+ "copy.copied": "\u5DF2\u590D\u5236",
388
+ "copy.failed": "\u672A\u80FD\u590D\u5236\uFF0C\u8BF7\u91CD\u8BD5\u3002",
389
+ "copy.denied": "clipboard API \u88AB\u62D2\uFF08{p0}\uFF09\u4E14\u56DE\u9000 execCommand \u5931\u8D25",
390
+ "copy.unavailable": "\u526A\u8D34\u677F\u4E0D\u53EF\u7528\uFF08\u65E0 clipboard API \u4E14 execCommand \u56DE\u9000\u5931\u8D25\uFF09",
391
+ "copy.unknown": "\u672A\u77E5\u9519\u8BEF",
392
+ /* ── datatable ── */
393
+ "datatable.clear": "\u6E05\u7A7A",
394
+ "datatable.collapseGroup": "\u6298\u53E0\u5206\u7EC4 {p0}",
395
+ "datatable.columnSettingsAria": "\u5217\u8BBE\u7F6E",
396
+ "datatable.countUnit": "{p0} \u6761",
397
+ "datatable.editHint": "\u7F16\u8F91\u300C{p0}\u300D\uFF1A\u53CC\u51FB\u6216\u6309 Enter",
398
+ "datatable.editHintWithValue": "{p0}\uFF08\u53CC\u51FB\u6216\u6309 Enter \u7F16\u8F91\u300C{p1}\u300D\uFF09",
399
+ "datatable.empty": "\u6682\u65E0\u6570\u636E",
400
+ "datatable.emptyValue": "\uFF08\u7A7A\uFF09",
401
+ "datatable.expandGroup": "\u5C55\u5F00\u5206\u7EC4 {p0}",
402
+ "datatable.expandRow": "\u5C55\u5F00\u884C",
403
+ "datatable.filterChipAria": "\u7B5B\u9009\u300C{p0}\u300D",
404
+ "datatable.pageSizeAria": "\u6BCF\u9875\u6761\u6570",
405
+ "datatable.paginationAria": "\u5206\u9875",
406
+ "datatable.reset": "\u91CD\u7F6E",
407
+ "datatable.resizeAria": "\u8C03\u6574\u300C{p0}\u300D\u5217\u5BBD",
408
+ "datatable.searchAria": "\u641C\u7D22\u8868\u683C",
409
+ "datatable.searchPlaceholder": "\u641C\u7D22\u2026",
410
+ "datatable.selectAll": "\u5168\u9009",
411
+ "datatable.selectRow": "\u9009\u62E9\u8BE5\u884C",
412
+ "datatable.selectedCount": "\u5DF2\u9009 {p0} \u9879",
413
+ "datatable.totalCount": "\u5171 {p0} \u6761",
414
+ "datatable.totalLabel": "\u5408\u8BA1",
415
+ /* ── datePicker ── */
416
+ "datePicker.noDates": "\u6CA1\u6709\u53EF\u9009\u65E5\u671F",
417
+ "datePicker.clear": "\u6E05\u9664",
418
+ "datePicker.nextMonth": "\u4E0B\u4E00\u6708",
419
+ "datePicker.prevMonth": "\u4E0A\u4E00\u6708",
420
+ "datePicker.selectDate": "\u9009\u62E9\u65E5\u671F",
421
+ "datePicker.today": "\u4ECA\u5929",
422
+ "datePicker.weekdays": ["\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u65E5"],
423
+ "datePicker.weekdaysSunFirst": ["\u65E5", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D"],
424
+ "datePicker.yearMonth": "{p0} \u5E74 {p1} \u6708",
425
+ /* ── formValidate ── */
426
+ "formValidate.email": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740",
427
+ "formValidate.invalid": "\u8F93\u5165\u4E0D\u5408\u6CD5",
428
+ "formValidate.matches": "\u4E24\u6B21\u8F93\u5165\u4E0D\u4E00\u81F4",
429
+ "formValidate.max": "\u4E0D\u80FD\u5927\u4E8E {max}",
430
+ "formValidate.maxlength": "\u6700\u591A\u8F93\u5165 {max} \u4E2A\u5B57\u7B26",
431
+ "formValidate.min": "\u4E0D\u80FD\u5C0F\u4E8E {min}",
432
+ "formValidate.minlength": "\u81F3\u5C11\u8F93\u5165 {min} \u4E2A\u5B57\u7B26",
433
+ "formValidate.number": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u6570\u5B57",
434
+ "formValidate.pattern": "\u8F93\u5165\u683C\u5F0F\u4E0D\u6B63\u786E",
435
+ "formValidate.required": "\u6B64\u9879\u4E3A\u5FC5\u586B\u9879",
436
+ "formValidate.selectPlaceholder": "\u8BF7\u9009\u62E9",
437
+ "formValidate.step": "\u6570\u503C\u5FC5\u987B\u662F {step} \u7684\u500D\u6570",
438
+ "formValidate.summary": "\u8868\u5355\u6709 {p0} \u9879\u5185\u5BB9\u9700\u8981\u4FEE\u6B63\uFF0C\u8BF7\u4FEE\u6539\u540E\u91CD\u65B0\u63D0\u4EA4",
439
+ "formValidate.tool.description": "\u5411\u7528\u6237\u6E32\u67D3\u4E00\u4E2A\u7ED3\u6784\u5316\u8868\u5355\u6536\u96C6\u8F93\u5165",
440
+ "formValidate.tool.fields": "\u5B57\u6BB5\u5217\u8868",
441
+ "formValidate.tool.help": "\u5B57\u6BB5\u4E0B\u65B9\u7684\u5E2E\u52A9\u6587\u6848",
442
+ "formValidate.tool.label": "\u5B57\u6BB5\u6807\u7B7E",
443
+ "formValidate.tool.max": "\u6700\u5927\u503C\uFF08number \u7528\uFF09",
444
+ "formValidate.tool.min": "\u6700\u5C0F\u503C\uFF08number \u7528\uFF09",
445
+ "formValidate.tool.name": "\u5B57\u6BB5\u540D\uFF08\u63D0\u4EA4\u503C\u7684 key\uFF09",
446
+ "formValidate.tool.options": "select \u9009\u9879\uFF08\u5B57\u7B26\u4E32\u6216 {label,value}\uFF09",
447
+ "formValidate.tool.pattern": "\u6B63\u5219\u7EA6\u675F\uFF08HTML pattern \u8BED\u6CD5\uFF0C\u6574\u4E32\u5339\u914D\uFF09",
448
+ "formValidate.tool.required": "\u662F\u5426\u5FC5\u586B",
449
+ "formValidate.tool.submitText": "\u63D0\u4EA4\u6309\u94AE\u6587\u6848\uFF0C\u9ED8\u8BA4\u300C\u63D0\u4EA4\u300D",
450
+ "formValidate.tool.title": "\u8868\u5355\u6807\u9898\uFF08\u53EF\u9009\uFF09",
451
+ "formValidate.tool.type": "\u63A7\u4EF6\u7C7B\u578B\uFF0C\u9ED8\u8BA4 text",
452
+ "formValidate.url": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u94FE\u63A5\u5730\u5740",
453
+ /* ── input ── */
454
+ "input.clearSearch": "\u6E05\u7A7A\u641C\u7D22",
455
+ "input.hidePassword": "\u9690\u85CF\u5BC6\u7801",
456
+ "input.otpPosition": "\u7B2C {p0} \u4F4D\uFF0C\u5171 {p1} \u4F4D",
457
+ "panel.expand": "\u5C55\u5F00",
458
+ "panel.collapse": "\u6298\u53E0",
459
+ "input.showPassword": "\u663E\u793A\u5BC6\u7801",
460
+ /* ── kbAccess ── */
461
+ "kbAccess.approveTip": "\u6279\u51C6\u8BE5\u8BBF\u95EE\u7533\u8BF7",
462
+ "kbAccess.approvedBadge": "\u5DF2\u6279\u51C6 \xB7 {p0}",
463
+ "kbAccess.approverNotePlaceholder": "\u7ED9\u8BF7\u6C42\u4EBA\u7684\u7559\u8A00\uFF08\u53EF\u9009\uFF09",
464
+ "kbAccess.daysLeft": "{p0} \u5929\u540E",
465
+ "kbAccess.defaultSubject": "\u8BE5\u5185\u5BB9",
466
+ "kbAccess.deniedHint": "\u672A\u901A\u8FC7\u2014\u2014\u53EF\u8C03\u6574\u7406\u7531\u540E\u91CD\u65B0\u7533\u8BF7",
467
+ "kbAccess.denyNoteLabel": "\u62D2\u7EDD\u7559\u8A00\uFF08\u53EF\u9009\uFF09",
468
+ "kbAccess.duration30d": "30 \u5929",
469
+ "kbAccess.duration7d": "7 \u5929",
470
+ "kbAccess.durationForever": "\u6C38\u4E45",
471
+ "kbAccess.durationLabel": "\u8BBF\u95EE\u65F6\u957F",
472
+ "kbAccess.expired": "\u5DF2\u5230\u671F",
473
+ "kbAccess.expiresAt": "{p0}\u5230\u671F",
474
+ "kbAccess.grantAsPrefix": "\u6279\u51C6\u4E3A{p0}",
475
+ "kbAccess.grantRoleLabel": "\u6279\u51C6\u89D2\u8272",
476
+ "kbAccess.hoursLeft": "{p0} \u5C0F\u65F6\u540E",
477
+ "kbAccess.minutesLeft": "{p0} \u5206\u949F\u540E",
478
+ "kbAccess.ownerLabel": "\u5185\u5BB9\u8D1F\u8D23\u4EBA",
479
+ "kbAccess.ownerPrefix": "\u8D1F\u8D23\u4EBA\uFF1A{p0}",
480
+ "kbAccess.reapply": "\u91CD\u65B0\u7533\u8BF7",
481
+ "kbAccess.reasonLabel": "\u7533\u8BF7\u7406\u7531",
482
+ "kbAccess.reasonPlaceholder": "\u8BF4\u660E\u4E1A\u52A1\u539F\u56E0\uFF08\u5BA1\u6279\u4EBA\u53EF\u89C1\uFF09",
483
+ "kbAccess.rejectTip": "\u62D2\u7EDD\u8BE5\u8BBF\u95EE\u7533\u8BF7",
484
+ "kbAccess.requestRenewal": "\u7533\u8BF7\u7EED\u671F",
485
+ "kbAccess.requestToPrefix": "\u8BF7\u6C42\u5C06\u53D1\u9001\u7ED9\uFF1A{p0}",
486
+ "kbAccess.restrictedContent": "\u53D7\u9650\u5185\u5BB9",
487
+ "kbAccess.restrictedHint": "\u6B64\u5185\u5BB9\u4EC5\u5BF9\u6388\u6743\u8005\u5F00\u653E",
488
+ "kbAccess.revokedHint": "\u8BBF\u95EE\u5DF2\u88AB\u6536\u56DE",
489
+ "kbAccess.roleLabel": "\u7533\u8BF7\u89D2\u8272",
490
+ "kbAccess.submitRequest": "\u63D0\u4EA4\u7533\u8BF7",
491
+ "kbAccess.switchIdentity": "\u5207\u6362\u8EAB\u4EFD",
492
+ "kbAccess.switchIdentityTip": "\u5207\u6362\u8EAB\u4EFD\u540E\u91CD\u65B0\u68C0\u67E5\u6743\u9650",
493
+ "kbAccess.unknownRequester": "\u672A\u77E5\u8BF7\u6C42\u4EBA",
494
+ "kbAccess.waitingApproval": "\u7B49\u5F85 {p0} \u5BA1\u6279",
495
+ /* ── kbAcl ── */
496
+ "kbAcl.breakHint": "\u505C\u6B62\u4ECE\u7236\u7EA7\u7EE7\u627F\uFF0C\u6539\u4E3A\u72EC\u7ACB\u7BA1\u7406\u672C\u9879\u6743\u9650",
497
+ "kbAcl.breakInheritance": "\u505C\u6B62\u7EE7\u627F",
498
+ "kbAcl.brokenNotice": "\u5DF2\u505C\u6B62\u7EE7\u627F\u2014\u2014\u672C\u9879\u6743\u9650\u72EC\u7ACB\u4E8E\u7236\u7EA7",
499
+ "kbAcl.detachedChildren": "{p0}\uFF1A{p1} \u4E2A\u5B50\u9879\u5DF2\u8131\u79BB",
500
+ "kbAcl.directAccess": "\u76F4\u63A5\u8BBF\u95EE",
501
+ "kbAcl.exception": "\u4F8B\u5916",
502
+ "kbAcl.expiredOn": "\u5DF2\u8FC7\u671F\uFF08{p0}\uFF09",
503
+ "kbAcl.expiresIn": "{p0} \u5230\u671F",
504
+ "kbAcl.grantAccess": "\u6388\u4E88\u8BBF\u95EE",
505
+ "kbAcl.inheritedFrom": "\u7EE7\u627F\u81EA {p0}",
506
+ "kbAcl.inheritedFromLabel": "\u7EE7\u627F\u81EA",
507
+ "kbAcl.linkAccess": "\u94FE\u63A5\u8BBF\u95EE",
508
+ "kbAcl.noDirect": "\u6682\u65E0\u76F4\u63A5\u6388\u6743",
509
+ "kbAcl.noLinks": "\u65E0\u94FE\u63A5",
510
+ "kbAcl.removeEntry": "\u79FB\u9664 {p0}",
511
+ "kbAcl.restoreHint": "\u6062\u590D\u7EE7\u627F\u5C06\u4E22\u5F03\u672C\u9879\u81EA\u5B9A\u4E49\u7684\u6743\u9650",
512
+ "kbAcl.restoreInheritance": "\u6062\u590D\u7EE7\u627F",
513
+ "kbAcl.rootNotice": "\u6839\u7EA7\u8D44\u6E90\u2014\u2014\u65E0\u7236\u7EA7\u7EE7\u627F",
514
+ "kbAcl.systemBadge": "\u7CFB\u7EDF\u7BA1\u7406",
515
+ "kbAcl.systemNote": "\u7CFB\u7EDF\u81EA\u52A8\uFF0C\u4E0D\u53EF\u624B\u5DE5\u79FB\u9664",
516
+ "kbAcl.unnamedResource": "\u672A\u547D\u540D\u8D44\u6E90",
517
+ "kbAcl.visibleToCount": "\u5BF9 {p0} \u4EBA\u53EF\u89C1",
518
+ /* ── kbAnswer ── */
519
+ "kbAnswer.chartBar": "\u67F1\u72B6",
520
+ "kbAnswer.chartLine": "\u6298\u7EBF",
521
+ "kbAnswer.chartPie": "\u997C\u56FE",
522
+ "kbAnswer.exportNoun": "\u5BFC\u51FA {p0}",
523
+ "kbAnswer.filtered": "\u5DF2\u6309\u4F60\u7684\u6570\u636E\u6743\u9650\u8FC7\u6EE4",
524
+ "kbAnswer.filteredDetail": "\u5DF2\u6309\u4F60\u7684\u6570\u636E\u6743\u9650\u8FC7\u6EE4\uFF1A{p0}",
525
+ "kbAnswer.followups": "\u8FFD\u95EE\u5EFA\u8BAE",
526
+ "kbAnswer.hitAssets": "\u547D\u4E2D\u8D44\u4EA7\uFF1A{p0}",
527
+ "kbAnswer.kindCurated": "\u4EBA\u5DE5\u7B56\u5C55",
528
+ "kbAnswer.kindFunction": "\u51FD\u6570",
529
+ "kbAnswer.kindParameterized": "\u53C2\u6570\u5316\u67E5\u8BE2",
530
+ "kbAnswer.maskedPrefix": "\u5DF2\u8131\u654F\u5217\uFF1A",
531
+ "kbAnswer.rerunTip": "\u53C2\u6570\u53EF\u6539\u91CD\u8DD1",
532
+ "kbAnswer.truncated": "\u5DF2\u622A\u65AD\uFF1A\u663E\u793A {p0}/{p1} \u884C{p2}",
533
+ "kbAnswer.verifiedBadge": "\u8BA4\u8BC1\u7B54\u6848",
534
+ /* ── kbAudit ── */
535
+ "kbAudit.actionDetail": "\u5904\u7F6E\uFF1A{p0} \xB7 {p1}",
536
+ "kbAudit.actionLabel": "\u5904\u7F6E",
537
+ "kbAudit.alertedNote": "\u5DF2\u5B9E\u65F6\u544A\u8B66\u5B89\u5168\u56E2\u961F",
538
+ "kbAudit.channelFilterAria": "\u5BA1\u8BA1\u901A\u9053\u8FC7\u6EE4",
539
+ "kbAudit.channelPermission": "\u6743\u9650\u53D8\u66F4",
540
+ "kbAudit.channelRead": "\u8BFB\u53D6",
541
+ "kbAudit.channelRequest": "\u7533\u8BF7",
542
+ "kbAudit.channelSystem": "\u7CFB\u7EDF",
543
+ "kbAudit.empty": "\u6682\u65E0\u5BA1\u8BA1\u4E8B\u4EF6",
544
+ "kbAudit.exportTip": "\u5BFC\u51FA\u5F53\u524D\u8FC7\u6EE4\u89C6\u56FE\u4E3A CSV",
545
+ "kbAudit.hygieneLabel": "\u6743\u9650\u5F02\u5473",
546
+ "kbAudit.noHygiene": "\u672A\u53D1\u73B0\u6743\u9650\u5F02\u5473",
547
+ /* ── kbCanvas ── */
548
+ "kbCanvas.splitterAria": "\u8C03\u6574\u753B\u5E03\u53CC\u680F\u6BD4\u4F8B",
549
+ "kbCanvas.splitterTip": "\u62D6\u62FD\u8C03\u6574\u6BD4\u4F8B\uFF08\u2190/\u2192 \u5FAE\u8C03\uFF0C\u53CC\u51FB\u590D\u4F4D\uFF09",
550
+ /* ── kbCheckpoint ── */
551
+ "kbCheckpoint.chatAuditNote": "\u8BA8\u8BBA\u5386\u53F2\u6709\u5BA1\u8BA1\u4EF7\u503C",
552
+ "kbCheckpoint.label": "\u68C0\u67E5\u70B9",
553
+ "kbCheckpoint.restore": "\u6062\u590D\u68C0\u67E5\u70B9",
554
+ "kbCheckpoint.scopeBoth": "\u5185\u5BB9\u4E0E\u5BF9\u8BDD",
555
+ "kbCheckpoint.scopeChat": "\u4EC5\u5BF9\u8BDD",
556
+ "kbCheckpoint.scopeContent": "\u4EC5\u5185\u5BB9\uFF08\u4FDD\u7559\u5BF9\u8BDD\uFF09",
557
+ "kbCheckpoint.scopeMissing": "\u8BE5\u68C0\u67E5\u70B9\u672A\u5305\u542B\u6B64\u6062\u590D\u8303\u56F4",
558
+ /* ── kbChunks ── */
559
+ "kbChunks.addKeyword": "+ \u5173\u952E\u8BCD",
560
+ "kbChunks.chunkAddKeywordAria": "chunk {p0} \u65B0\u589E\u5173\u952E\u8BCD",
561
+ "kbChunks.chunkContentAria": "chunk {p0} \u5185\u5BB9",
562
+ "kbChunks.chunkEnableAria": "chunk {p0} \u542F\u7528",
563
+ "kbChunks.deleteChunkAria": "\u5220\u9664 chunk {p0}",
564
+ "kbChunks.disableNote": "\u5173\u95ED\u540E\u4E0D\u5220\u9664\uFF0C\u4EC5\u6392\u9664\u51FA\u68C0\u7D22",
565
+ "kbChunks.edited": "\u5DF2\u7F16\u8F91",
566
+ "kbChunks.empty": "\u6682\u65E0 chunk",
567
+ "kbChunks.modeFull": "\u5168\u6587",
568
+ "kbChunks.modeLabel": "\u641C\u7D22\u6A21\u5F0F",
569
+ "kbChunks.modeVector": "\u8BED\u4E49",
570
+ "kbChunks.removeKeyword": "\u79FB\u9664\u5173\u952E\u8BCD {p0}",
571
+ "kbChunks.searchAria": "\u641C\u7D22 chunk",
572
+ "kbChunks.searchFullPlaceholder": "\u5168\u6587\u641C\u7D22 chunk\u2026",
573
+ "kbChunks.searchVectorPlaceholder": "\u8BED\u4E49\u641C\u7D22 chunk\u2026",
574
+ /* ── kbCitation ── */
575
+ "kbCitation.sourceN": "\u6765\u6E90 {p0}",
576
+ "kbCitation.unavailable": "\u6765\u6E90\u5DF2\u4E0D\u53EF\u7528",
577
+ /* ── kbClarify ── */
578
+ "kbClarify.parsedPrefix": "\u5DF2\u89E3\u6790\uFF1A",
579
+ /* ── kbConflict ── */
580
+ "kbConflict.owner": "\u8D23\u4EFB\u4EBA {p0}",
581
+ /* ── kbConnector ── */
582
+ "kbConnector.changeRate": "\u53D8\u66F4\u7387",
583
+ "kbConnector.crawlRate": "\u6293\u53D6\u7387",
584
+ "kbConnector.credentials": "\u51ED\u8BC1",
585
+ "kbConnector.credentialsExpired": "\u51ED\u8BC1\u8FC7\u671F",
586
+ "kbConnector.editSchedule": "\u7F16\u8F91\u8BA1\u5212",
587
+ "kbConnector.empty": "\u6682\u65E0\u8FDE\u63A5\u5668",
588
+ "kbConnector.failing": "\u5F02\u5E38",
589
+ "kbConnector.lastSync": "\u6700\u8FD1\u540C\u6B65 {p0}",
590
+ "kbConnector.neverSynced": "\u4ECE\u672A\u540C\u6B65",
591
+ "kbConnector.notConfigured": "\u672A\u914D\u7F6E",
592
+ "kbConnector.off": "\u5DF2\u505C\u7528",
593
+ "kbConnector.perDay": "{p0}/\u5929",
594
+ "kbConnector.reauth": "\u91CD\u65B0\u6388\u6743",
595
+ "kbConnector.stale": "\u505C\u6EDE",
596
+ "kbConnector.syncNow": "\u7ACB\u5373\u540C\u6B65",
597
+ "kbConnector.synced": "\u5DF2\u540C\u6B65",
598
+ /* ── kbCore ── */
599
+ "kbCore.accessDenied": "\u672A\u901A\u8FC7",
600
+ "kbCore.accessExpired": "\u5DF2\u8FC7\u671F",
601
+ "kbCore.accessExpiring": "\u5373\u5C06\u5230\u671F",
602
+ "kbCore.accessGranted": "\u5DF2\u5F00\u901A",
603
+ "kbCore.accessNotRequested": "\u672A\u7533\u8BF7",
604
+ "kbCore.accessPending": "\u5F85\u5BA1\u6279",
605
+ "kbCore.accessRequested": "\u5DF2\u63D0\u4EA4",
606
+ "kbCore.accessRevoked": "\u5DF2\u6536\u56DE",
607
+ "kbCore.auditApprove": "\u6279\u51C6",
608
+ "kbCore.auditBreakGlass": "\u5E94\u6025\u8BBF\u95EE",
609
+ "kbCore.auditDelegation": "\u59D4\u6D3E",
610
+ "kbCore.auditDeny": "\u62D2\u7EDD",
611
+ "kbCore.auditGrant": "\u6388\u4E88",
612
+ "kbCore.auditPermissionChange": "\u6743\u9650\u53D8\u66F4",
613
+ "kbCore.auditPreview": "\u9884\u89C8",
614
+ "kbCore.auditRead": "\u8BFB\u53D6",
615
+ "kbCore.auditRequest": "\u7533\u8BF7",
616
+ "kbCore.auditRevoke": "\u6536\u56DE",
617
+ "kbCore.auditSync": "\u6743\u9650\u540C\u6B65",
618
+ "kbCore.daysAgo": "{p0} \u5929\u524D",
619
+ "kbCore.hoursAgo": "{p0} \u5C0F\u65F6\u524D",
620
+ "kbCore.hygieneBroadGroup": "\u8FC7\u5BBD\u7EC4\u6388\u6743",
621
+ "kbCore.hygieneBrokenInheritance": "\u65AD\u7EE7\u627F",
622
+ "kbCore.hygieneOrgWideLink": "\u7EC4\u7EC7\u7EA7\u94FE\u63A5",
623
+ "kbCore.hygieneOrphanedOwner": "\u8D1F\u8D23\u4EBA\u7F3A\u4F4D",
624
+ "kbCore.hygieneOverexposed": "\u8FC7\u5EA6\u66B4\u9732",
625
+ "kbCore.hygieneSensitiveMismatch": "\u654F\u611F\u5EA6\u9519\u914D",
626
+ "kbCore.justNow": "\u521A\u521A",
627
+ "kbCore.levelComment": "\u53EF\u8BC4\u8BBA",
628
+ "kbCore.levelEdit": "\u53EF\u7F16\u8F91",
629
+ "kbCore.levelNone": "\u65E0\u6743\u9650",
630
+ "kbCore.levelOwner": "\u8D1F\u8D23\u4EBA",
631
+ "kbCore.levelView": "\u53EF\u67E5\u770B",
632
+ "kbCore.minutesAgo": "{p0} \u5206\u949F\u524D",
633
+ "kbCore.runCancelled": "\u5DF2\u53D6\u6D88",
634
+ "kbCore.runDone": "\u5DF2\u5B8C\u6210",
635
+ "kbCore.runFailed": "\u5931\u8D25",
636
+ "kbCore.runQueued": "\u6392\u961F\u4E2D",
637
+ "kbCore.runRunning": "\u8FDB\u884C\u4E2D",
638
+ "kbCore.runUnstarted": "\u672A\u5F00\u59CB",
639
+ "kbCore.stageAgent": "\u4EE3\u7406",
640
+ "kbCore.stageChunk": "\u5207\u7247",
641
+ "kbCore.stageEmbed": "\u5411\u91CF\u5316",
642
+ "kbCore.stageGeneration": "\u751F\u6210",
643
+ "kbCore.stageGuard": "\u62A4\u680F",
644
+ "kbCore.stageQuery": "\u67E5\u8BE2",
645
+ "kbCore.stageRerank": "\u91CD\u6392",
646
+ "kbCore.stageRetrieval": "\u68C0\u7D22",
647
+ "kbCore.stageTool": "\u5DE5\u5177",
648
+ "kbCore.typeApi": "\u63A5\u53E3",
649
+ "kbCore.typeCode": "\u4EE3\u7801",
650
+ "kbCore.typeDatabase": "\u6570\u636E\u5E93",
651
+ "kbCore.typeDocument": "\u6587\u6863",
652
+ "kbCore.typeEmail": "\u90AE\u4EF6",
653
+ "kbCore.typeImage": "\u56FE\u7247",
654
+ "kbCore.typeKb": "\u77E5\u8BC6\u5E93",
655
+ "kbCore.typeTable": "\u8868\u683C",
656
+ "kbCore.typeTicket": "\u5DE5\u5355",
657
+ "kbCore.typeWebpage": "\u7F51\u9875",
658
+ "kbCore.unnamedSource": "\u672A\u547D\u540D\u6765\u6E90",
659
+ "kbCore.unnamedSubject": "\u672A\u547D\u540D\u4E3B\u4F53",
660
+ "kbCore.visHidden": "\u4E0D\u53EF\u89C1",
661
+ "kbCore.visMetadataOnly": "\u4EC5\u5143\u6570\u636E",
662
+ "kbCore.visSummaryOnly": "\u4EC5\u6458\u8981",
663
+ "kbCore.visVisible": "\u53EF\u89C1",
664
+ /* ── kbEval ── */
665
+ "kbEval.avgA": "A \u5747\u5206 {p0}",
666
+ "kbEval.avgB": "B \u5747\u5206 {p0}",
667
+ "kbEval.compare": "\u5BF9\u6BD4",
668
+ "kbEval.runSelectAria": "\u9009\u62E9\u5BF9\u6BD4\u8FD0\u884C",
669
+ "kbEval.expected": "\u671F\u671B",
670
+ "kbEval.gradeImprovement": "\u63D0\u5347",
671
+ "kbEval.gradeRegression": "\u56DE\u5F52",
672
+ "kbEval.gradeTie": "\u6301\u5E73",
673
+ "kbEval.gradeTradeoff": "\u6743\u8861",
674
+ "kbEval.noData": "\u6CA1\u6709\u5BF9\u6BD4\u6570\u636E",
675
+ "kbEval.onlyRegression": "\u4EC5\u770B\u56DE\u5F52",
676
+ "kbEval.outputA": "\u8F93\u51FA A",
677
+ "kbEval.outputB": "\u8F93\u51FA B",
678
+ "kbEval.outputN": "\u8F93\u51FA {p0}",
679
+ /* ── kbExplain ── */
680
+ "kbExplain.empty": "\u6682\u65E0\u53E3\u5F84\u4FE1\u606F",
681
+ "kbExplain.groupAgg": "\u805A\u5408",
682
+ "kbExplain.groupColumn": "\u5217",
683
+ "kbExplain.groupFilter": "\u7B5B\u9009",
684
+ "kbExplain.groupTable": "\u8868",
685
+ "kbExplain.trigger": "\u8FD9\u4E2A\u6570\u5B57\u662F\u600E\u4E48\u7B97\u51FA\u6765\u7684",
686
+ "kbExplain.viewDefinition": "\u67E5\u770B\u53E3\u5F84",
687
+ /* ── kbFilter ── */
688
+ "kbFilter.addGroup": "+ \u7EC4",
689
+ "kbFilter.addRule": "+ \u89C4\u5219",
690
+ "kbFilter.and": "\u4E14",
691
+ "kbFilter.combineMode": "\u7EC4\u5408\u65B9\u5F0F {p0}",
692
+ "kbFilter.copyDsl": "\u590D\u5236 DSL",
693
+ "kbFilter.deleteGroup": "\u5220\u9664\u7EC4",
694
+ "kbFilter.deleteRule": "\u5220\u9664\u89C4\u5219",
695
+ "kbFilter.fieldLabel": "\u5B57\u6BB5",
696
+ "kbFilter.fieldPlaceholder": "\u8FC7\u6EE4\u5B57\u6BB5",
697
+ "kbFilter.noValueNeeded": "\uFF08\u65E0\u9700\u503C\uFF09",
698
+ "kbFilter.none": "\uFF08\u65E0\u8FC7\u6EE4\uFF09",
699
+ "kbFilter.opContains": "\u5305\u542B",
700
+ "kbFilter.opEq": "\u7B49\u4E8E",
701
+ "kbFilter.opExists": "\u5B58\u5728",
702
+ "kbFilter.opGt": "\u5927\u4E8E",
703
+ "kbFilter.opGte": "\u5927\u4E8E\u7B49\u4E8E",
704
+ "kbFilter.opIn": "\u5C5E\u4E8E",
705
+ "kbFilter.opLt": "\u5C0F\u4E8E",
706
+ "kbFilter.opLte": "\u5C0F\u4E8E\u7B49\u4E8E",
707
+ "kbFilter.opNe": "\u4E0D\u7B49\u4E8E",
708
+ "kbFilter.operatorLabel": "\u64CD\u4F5C\u7B26",
709
+ "kbFilter.or": "\u6216",
710
+ "kbFilter.toggleAndOr": "\u5207\u6362 AND / OR",
711
+ "kbFilter.valueAria": "\u8FC7\u6EE4\u503C",
712
+ "kbFilter.valueLabel": "\u503C",
713
+ "kbFilter.valuePlaceholder": "\u503C 1, \u503C 2\uFF08\u9017\u53F7\u5206\u9694\uFF09",
714
+ /* ── kbGap ── */
715
+ "kbGap.addSynonym": "\u52A0\u540C\u4E49\u8BCD",
716
+ "kbGap.colCount": "\u6B21\u6570",
717
+ "kbGap.colLastSeen": "\u6700\u8FD1\u51FA\u73B0",
718
+ "kbGap.colQuery": "\u67E5\u8BE2",
719
+ "kbGap.colShare": "\u5360\u6BD4",
720
+ "kbGap.createDoc": "\u5EFA\u6587\u6863",
721
+ "kbGap.empty": "\u6CA1\u6709\u672A\u547D\u4E2D\u67E5\u8BE2\u2014\u2014\u8986\u76D6\u826F\u597D",
722
+ "kbGap.title": "\u672A\u547D\u4E2D\u67E5\u8BE2\u8D8B\u52BF",
723
+ "kbGap.zeroClickHint": "\u7528\u6237\u53EF\u80FD\u5DF2\u4ECE\u5F15\u7528\u7247\u6BB5\u5F97\u5230\u7B54\u6848\uFF1B\u96F6\u70B9\u51FB\u9700\u4EBA\u5DE5\u5224\u8BFB\uFF0C\u4E0D\u76F4\u63A5\u89C6\u4E3A\u5931\u8D25",
724
+ "kbGap.zeroClickRate": "\u96F6\u70B9\u51FB\u7387",
725
+ "kbGap.zeroClickTitle": "\u96F6\u70B9\u51FB \u2260 \u5931\u8D25",
726
+ /* ── kbHittest ── */
727
+ "kbHittest.addAria": "\u65B0\u589E\u6D4B\u8BD5\u95EE\u9898",
728
+ "kbHittest.addPlaceholder": "\u65B0\u589E\u95EE\u9898\uFF0CEnter \u6DFB\u52A0",
729
+ "kbHittest.avgScore": "\u5747\u5206",
730
+ "kbHittest.deleteQuestion": "\u5220\u9664\u95EE\u9898",
731
+ "kbHittest.empty": "\u6682\u65E0\u6D4B\u8BD5\u95EE\u9898\u2014\u2014\u6DFB\u52A0\u7B2C\u4E00\u6761\uFF0C\u5F00\u59CB\u53EC\u56DE\u56DE\u5F52",
732
+ "kbHittest.expectHit": "\u671F\u671B\u547D\u4E2D\u5728\u524D\u6392\u547D\u4E2D\u4E2D",
733
+ "kbHittest.expectMiss": "\u671F\u671B\u672A\u547D\u4E2D",
734
+ "kbHittest.hitRate": "\u547D\u4E2D\u7387",
735
+ "kbHittest.noExpectation": "\u672A\u8BBE\u671F\u671B",
736
+ "kbHittest.notRun": "\u672A\u8FD0\u884C",
737
+ "kbHittest.pass": "\u901A\u8FC7",
738
+ "kbHittest.pin": "\u7F6E\u9876\u56FA\u5B9A",
739
+ "kbHittest.runAll": "\u8FD0\u884C\u5168\u90E8",
740
+ "kbHittest.sessionOnly": "\u53C2\u6570\u4EC5\u672C\u6B21\u4F1A\u8BDD\u751F\u6548",
741
+ "kbHittest.sessionOnlyHint": "\u6D4B\u8BD5\u8FD0\u884C\u7684\u68C0\u7D22\u53C2\u6570\uFF08topK/\u9608\u503C/\u91CD\u6392\uFF09\u4E0D\u843D\u5E93\uFF0C\u4EC5\u672C\u6B21\u4F1A\u8BDD\u751F\u6548",
742
+ "kbHittest.unpin": "\u53D6\u6D88\u7F6E\u9876",
743
+ /* ── kbMetadata ── */
744
+ "kbMetadata.addField": "\u65B0\u589E\u5B57\u6BB5",
745
+ "kbMetadata.builtIn": "\u5185\u7F6E",
746
+ "kbMetadata.colField": "\u5B57\u6BB5",
747
+ "kbMetadata.colType": "\u7C7B\u578B",
748
+ "kbMetadata.colValue": "\u503C",
749
+ "kbMetadata.empty": "\u6682\u65E0\u5143\u6570\u636E\u5B57\u6BB5",
750
+ "kbMetadata.nameLabel": "\u65B0\u5B57\u6BB5\u540D",
751
+ "kbMetadata.namePlaceholder": "\u5B57\u6BB5\u540D\uFF0C\u5982 department",
752
+ "kbMetadata.removeField": "\u79FB\u9664\u5B57\u6BB5 {p0}",
753
+ "kbMetadata.typeLabel": "\u65B0\u5B57\u6BB5\u7C7B\u578B",
754
+ "kbMetadata.valueOf": "{p0} \u7684\u503C",
755
+ /* ── kbPassage ── */
756
+ "kbPassage.blockRange": "\u5757 {p0}\u2013{p1}",
757
+ "kbPassage.close": "\u5173\u95ED\u539F\u6587",
758
+ "kbPassage.expandContext": "\u5C55\u5F00\u4E0A\u4E0B\u6587",
759
+ "kbPassage.locate": "\u539F\u6587\u5B9A\u4F4D",
760
+ "kbPassage.none": "\uFF08\u65E0\u539F\u6587\uFF09",
761
+ "kbPassage.pageRange": "\u7B2C {p0}\u2013{p1} \u9875",
762
+ "kbPassage.restricted": "\u5185\u5BB9\u53D7\u9650",
763
+ "kbPassage.unitByte": "\u5B57\u8282",
764
+ "kbPassage.unitChar": "\u5B57\u7B26",
765
+ /* ── kbPipeline ── */
766
+ "kbPipeline.empty": "\u6682\u65E0\u89E3\u6790\u4EFB\u52A1",
767
+ "kbPipeline.progress": "\u89E3\u6790\u8FDB\u5EA6",
768
+ "kbPipeline.rerun": "\u91CD\u8DD1",
769
+ "kbPipeline.unknownStage": "\u672A\u77E5\u9636\u6BB5",
770
+ /* ── kbQa ── */
771
+ "kbQa.colAnswer": "\u7B54\u6848",
772
+ "kbQa.colQuestion": "\u95EE\u9898",
773
+ "kbQa.csvHint": "CSV \u6A21\u677F\uFF1Aquestion,answer\uFF08\u6BCF\u884C\u4E00\u5BF9\uFF0CUTF-8\uFF09",
774
+ "kbQa.deleteRow": "\u5220\u9664\u7B2C {p0} \u884C",
775
+ "kbQa.empty": "\u6682\u65E0\u8BA4\u8BC1\u95EE\u7B54\u5BF9",
776
+ "kbQa.importCsv": "\u5BFC\u5165 CSV",
777
+ /* ── kbRerank ── */
778
+ "kbRerank.after": "\u91CD\u6392\u540E",
779
+ "kbRerank.before": "\u91CD\u6392\u524D",
780
+ "kbRerank.compareTitle": "\u91CD\u6392\u5BF9\u6BD4",
781
+ "kbRerank.down": "\u4E0B\u964D {p0} \u4F4D",
782
+ "kbRerank.dropped": "\u843D\u9009",
783
+ "kbRerank.empty": "\u4E24\u4FA7\u5747\u4E3A\u7A7A\u2014\u2014\u8FD0\u884C\u68C0\u7D22\u540E\u518D\u5BF9\u6BD4",
784
+ "kbRerank.enableCompare": "\u542F\u7528\u91CD\u6392\u5BF9\u6BD4",
785
+ "kbRerank.newIn": "\u65B0\u8FDB",
786
+ "kbRerank.unmarked": "\u672A\u6807",
787
+ "kbRerank.up": "\u4E0A\u5347 {p0} \u4F4D",
788
+ /* ── kbRetrieval ── */
789
+ "kbRetrieval.breakdown": "\u62C6\u89E3",
790
+ "kbRetrieval.copyParams": "\u590D\u5236\u53C2\u6570 JSON",
791
+ "kbRetrieval.decreaseTopK": "\u51CF\u5C11 topK",
792
+ "kbRetrieval.empty": "\u8F93\u5165\u95EE\u9898\u5E76\u8FD0\u884C\uFF0C\u547D\u4E2D\u7ED3\u679C\u5C06\u51FA\u73B0\u5728\u8FD9\u91CC",
793
+ "kbRetrieval.failOpenNotice": "fail-open\uFF1A\u5F53\u524D\u67E5\u8BE2\u672A\u643A\u5E26\u8EAB\u4EFD\u8FC7\u6EE4\uFF0C\u5C06\u8FD4\u56DE\u5168\u90E8\u5019\u9009\uFF08\u4EC5\u9650\u8C03\u8BD5\uFF09",
794
+ "kbRetrieval.hybridWeight": "\u6DF7\u5408\u6743\u91CD\uFF08\u5DE6\u8BED\u4E49\u53F3\u5173\u952E\u8BCD\uFF09",
795
+ "kbRetrieval.identityLabel": "\u68C0\u7D22\u8EAB\u4EFD",
796
+ "kbRetrieval.identityShort": "\u8EAB\u4EFD",
797
+ "kbRetrieval.increaseTopK": "\u589E\u52A0 topK",
798
+ "kbRetrieval.keywordHint": "\u5173\u952E\u8BCD\uFF1A\u5927\u5E93\u5FEB\u901F\u7CBE\u786E",
799
+ "kbRetrieval.layerLabel": "\u8FC7\u6EE4\u5C42",
800
+ "kbRetrieval.layerNone": "none\uFF1Afail-open\uFF0C\u65E0\u8EAB\u4EFD\u8FC7\u6EE4\u8FD4\u56DE\u5168\u90E8\u2014\u2014\u5371\u9669\uFF0C\u4EC5\u6F14\u793A",
801
+ "kbRetrieval.layerPost": "post-filter\uFF1A\u5206\u6570\u5DF2\u53EF\u89C2\u5BDF\u2014\u2014\u7F3A\u9677\u5C42\uFF0C\u4EC5\u6F14\u793A",
802
+ "kbRetrieval.layerPre": "pre-filter\uFF1AACL \u5728\u68C0\u7D22\u6267\u884C\u4F53\u5185\u751F\u6548\u2014\u2014\u5B89\u5168\u57FA\u7EBF",
803
+ "kbRetrieval.leakNote": "\u5206\u6BCD\u672A\u8FC7\u6EE4\u524D\u8BA1\u6570\u5C5E\u6CC4\u9732\uFF0C\u4E0D\u663E\u793A",
804
+ "kbRetrieval.modeHybrid": "\u6DF7\u5408",
805
+ "kbRetrieval.modeKeyword": "\u5173\u952E\u8BCD",
806
+ "kbRetrieval.modeLabel": "\u68C0\u7D22\u6A21\u5F0F",
807
+ "kbRetrieval.modeVector": "\u5411\u91CF",
808
+ "kbRetrieval.postFilterNotice": "post-filter\uFF1A\u5206\u6570\u5DF2\u5728\u8FC7\u6EE4\u524D\u4EA7\u751F\uFF08\u7F3A\u9677\u5C42\u6F14\u793A\uFF09",
809
+ "kbRetrieval.queryLabel": "\u68C0\u7D22\u95EE\u9898",
810
+ "kbRetrieval.queryPlaceholder": "\u68C0\u7D22\u95EE\u9898\uFF0CEnter \u8FD0\u884C",
811
+ "kbRetrieval.rerankLabel": "\u91CD\u6392",
812
+ "kbRetrieval.rerankThresholdOff": "\u9608\u503C \u5173 \xB7 \u5B58\u6D3B {p0}",
813
+ "kbRetrieval.rerankThresholdOn": "\u9608\u503C {p0} \xB7 \u5B58\u6D3B {p1}",
814
+ "kbRetrieval.running": "\u8FD0\u884C\u4E2D\u2026",
815
+ "kbRetrieval.thresholdLabel": "\u5206\u6570\u9608\u503C",
816
+ "kbRetrieval.thresholdValue": "\u9608\u503C N/A",
817
+ "kbRetrieval.vectorHint": "\u8BED\u4E49\uFF1A\u8DE8\u8BED\u8A00/\u65E0\u7CBE\u786E\u8BCD",
818
+ "kbRetrieval.vectorPercent": "\u8BED\u4E49 {p0}",
819
+ "kbRetrieval.weightValue": "\u5411\u91CF {p0}% / \u5173\u952E\u8BCD {p1}%",
820
+ /* ── kbReview ── */
821
+ "kbReview.assignee": "\u5206\u914D\u4EBA",
822
+ "kbReview.doneNext": "\u5B8C\u6210\u5E76\u4E0B\u4E00\u6761",
823
+ "kbReview.empty": "\u6CA1\u6709\u5F85\u5BA1\u67E5\u6761\u76EE",
824
+ "kbReview.emptyAssignee": "\u8BE5\u5206\u914D\u4EBA\u4E0B\u6CA1\u6709\u6761\u76EE",
825
+ "kbReview.emptyQueue": "\u961F\u5217\u4E3A\u7A7A",
826
+ "kbReview.kbCloseHint": "\u5173\u95ED\u63D0\u793A",
827
+ "kbReview.kbSelectOption": "\u9009\u62E9\u9009\u9879",
828
+ "kbReview.kbSwitchItem": "\u5207\u6362\u6761\u76EE",
829
+ "kbReview.kbToggleHint": "\u663E\u793A/\u9690\u85CF\u672C\u63D0\u793A",
830
+ "kbReview.shortcuts": "? \u5FEB\u6377\u952E",
831
+ "kbReview.typeAnswer": "\u56DE\u7B54",
832
+ "kbReview.typeMessage": "\u6D88\u606F",
833
+ "kbReview.typeTrace": "\u8F68\u8FF9",
834
+ "kbReview.unassigned": "\u672A\u5206\u914D",
835
+ /* ── kbSandbox ── */
836
+ "kbSandbox.noResolver": "\u5BBF\u4E3B\u672A\u63D0\u4F9B ui:// \u89E3\u6790\u5668",
837
+ "kbSandbox.notReady": "kb-sandbox: \u5E94\u7528\u672A\u5C31\u7EEA",
838
+ "kbSandbox.resolveFailed": "ui:// \u89E3\u6790\u5931\u8D25\uFF1A{p0}",
839
+ "kbSandbox.timeout": "kb-sandbox: \u8C03\u7528\u8D85\u65F6\uFF08{p0}ms\uFF09",
840
+ "kbSandbox.title": "MCP App \u6C99\u7BB1",
841
+ /* ── kbSegment ── */
842
+ "kbSegment.avgLength": "\u5747\u957F {p0}",
843
+ "kbSegment.childNote": "\u5B50\u5206\u6BB5\u6309\u957F\u5EA6\u81EA\u52A8\u751F\u6210",
844
+ "kbSegment.cleanBlankLines": "\u5408\u5E76\u8FDE\u7EED\u7A7A\u884C",
845
+ "kbSegment.cleanEmails": "\u53BB\u9664\u90AE\u7BB1",
846
+ "kbSegment.cleanLinks": "\u53BB\u9664\u94FE\u63A5",
847
+ "kbSegment.empty": "\u6837\u672C\u4E3A\u7A7A\uFF0C\u6682\u65E0\u53EF\u9884\u89C8\u5206\u6BB5",
848
+ "kbSegment.maxLengthLabel": "\u6700\u5927\u957F\u5EA6",
849
+ "kbSegment.maxLengthPlaceholder": "\u5206\u6BB5\u6700\u5927\u957F\u5EA6",
850
+ "kbSegment.modeAuto": "\u81EA\u52A8",
851
+ "kbSegment.modeCustom": "\u81EA\u5B9A\u4E49",
852
+ "kbSegment.modeLabel": "\u5206\u6BB5\u6A21\u5F0F",
853
+ "kbSegment.modeNote": "\u5206\u6BB5\u6A21\u5F0F\u521B\u5EFA\u540E\u4E0D\u53EF\u66F4\u6539\uFF0C\u53C2\u6570\u53EF\u968F\u65F6\u8C03\u6574",
854
+ "kbSegment.modeParentChild": "\u7236\u5B50",
855
+ "kbSegment.overlapInvalid": "\u91CD\u53E0\u9700\u5C0F\u4E8E\u6700\u5927\u957F\u5EA6",
856
+ "kbSegment.overlapLabel": "\u91CD\u53E0",
857
+ "kbSegment.overlapPlaceholder": "\u5206\u6BB5\u91CD\u53E0",
858
+ "kbSegment.previewNote": "\u5171 {p0} \u6BB5\uFF0C\u4EC5\u9884\u89C8\u524D {p1} \u6BB5",
859
+ "kbSegment.segmentsCount": "{p0} \u6BB5",
860
+ "kbSegment.separatorLabel": "\u5206\u9694\u7B26",
861
+ "kbSegment.separatorPlaceholder": "\u5206\u6BB5\u5206\u9694\u7B26",
862
+ "kbSegment.toggleTip": "\u70B9\u51FB\u5C55\u5F00/\u6536\u8D77",
863
+ /* ── kbSources ── */
864
+ "kbSources.cited": "\u88AB\u5F15 \xD7{p0}",
865
+ "kbSources.empty": "\u4E0B\u4E00\u6761\u7B54\u6848\u5F15\u7528\u7684\u6BB5\u843D\u5C06\u51FA\u73B0\u5728\u8FD9\u91CC",
866
+ /* ── kbSql ── */
867
+ "kbSql.adminOnly": "\u4EC5\u7BA1\u7406\u5458\u53EF\u89C1",
868
+ "kbSql.applyFix": "\u5E94\u7528\u4FEE\u590D\u5E76\u91CD\u8DD1",
869
+ "kbSql.confirmRerun": "\u786E\u8BA4\u5E76\u91CD\u8DD1",
870
+ "kbSql.editRerun": "\u7F16\u8F91\u91CD\u8DD1",
871
+ "kbSql.fixReady": "\u68C0\u6D4B\u5230\u4E0A\u7248\u62A5\u9519\uFF0C\u4FEE\u590D\u5EFA\u8BAE\u5DF2\u5C31\u7EEA",
872
+ "kbSql.generated": "\u751F\u6210\u7684 SQL",
873
+ /* ── kbTrace ── */
874
+ "kbTrace.empty": "\u6682\u65E0\u8C03\u7528\u94FE\u6570\u636E",
875
+ "kbTrace.hits": "\u547D\u4E2D {p0}",
876
+ /* ── kbVisibility ── */
877
+ "kbVisibility.adminOnlyNote": "\u4EE5\u4E0A\u5BF9\u7167\u4EC5\u9650 admin \u5BA1\u8BA1",
878
+ "kbVisibility.adminWarn": "admin \u5BA1\u8BA1\u89C6\u56FE\u2014\u2014\u547D\u4E2D\u5DEE\u5F02\u5BF9\u7167\u5BF9\u666E\u901A\u7528\u6237\u6784\u6210\u6CC4\u9732\uFF0C\u52FF\u5D4C\u5165\u7EC8\u7AEF\u7528\u6237\u754C\u9762",
879
+ "kbVisibility.failOpenNote": "fail-open\uFF1AKendra \u65E0\u8EAB\u4EFD\u4E0A\u4E0B\u6587\u8FD4\u56DE\u5168\u90E8\u6587\u6863\u2014\u2014\u68C0\u7D22\u5FC5\u987B\u643A\u5E26\u670D\u52A1\u7AEF\u8EAB\u4EFD",
880
+ "kbVisibility.focusColumn": "\u805A\u7126\u8EAB\u4EFD {p0} \u7684\u5217",
881
+ "kbVisibility.layerValue": "\u8FC7\u6EE4\u5C42\uFF1A{p0}",
882
+ "kbVisibility.leakageNote": "\u8BA1\u6570\u5DEE\u5F02\u5373 volume leakage\uFF1A\u5BF9\u666E\u901A\u7528\u6237\u53EA\u53EF\u7ED9\u300C\u5DF2\u6309\u6743\u9650\u8FC7\u6EE4\u300D\u6052\u5B9A\u6587\u6848\uFF0C\u7F13\u89E3\u53EA\u6709 padding \u53D6\u6574",
883
+ "kbVisibility.postFilterNote": "post-filter\uFF1AtopK \u88AB\u65E0\u6743\u7ED3\u679C\u5360\u7528\u4E14\u76F8\u4F3C\u5EA6\u5206\u6570\u53EF\u88AB\u89C2\u5BDF",
884
+ "kbVisibility.queryLabel": "\u67E5\u8BE2\uFF1A{p0}",
885
+ "kbVisibility.safeCount": "\u5B89\u5168\u8BA1\u6570 {p0}",
886
+ "kbVisibility.sourceUnavailable": "\u539F\u6587\u4E0D\u53EF\u7528",
887
+ "kbVisibility.unnamedHit": "\u672A\u547D\u540D\u547D\u4E2D",
888
+ /* ── kbWhoCan ── */
889
+ "kbWhoCan.check": "\u68C0\u67E5",
890
+ "kbWhoCan.checkIdentity": "\u68C0\u67E5\u8EAB\u4EFD",
891
+ "kbWhoCan.daysUntil": "{p0} \u5929\u540E",
892
+ "kbWhoCan.deniedBy": "\u88AB\u7B56\u7565\u62D2\u7EDD\uFF1A{p0}",
893
+ "kbWhoCan.denyVeto": "\u88AB Deny \u4E00\u7968\u5426\u51B3",
894
+ "kbWhoCan.direct": "\u76F4\u63A5",
895
+ "kbWhoCan.expiresSoon": "\u6700\u8FD1\u5230\u671F {p0}",
896
+ "kbWhoCan.hoursUntil": "{p0} \u5C0F\u65F6\u540E",
897
+ "kbWhoCan.inherit": "\u7EE7\u627F",
898
+ "kbWhoCan.link": "\u94FE\u63A5",
899
+ "kbWhoCan.noDeny": "\u65E0 Deny \u751F\u6548",
900
+ "kbWhoCan.noIdentity": "\u672A\u63D0\u4F9B\u53EF\u68C0\u67E5\u7684\u8EAB\u4EFD",
901
+ "kbWhoCan.none": "\u672A\u547D\u4E2D\u4EFB\u4F55\u6388\u6743\u2014\u2014\u9ED8\u8BA4\u62D2\u7EDD",
902
+ "kbWhoCan.recheckTip": "\u91CD\u65B0\u68C0\u67E5\u5F53\u524D\u8EAB\u4EFD\u7684\u6709\u6548\u6743\u9650",
903
+ "kbWhoCan.stackRule": "\u53E0\u52A0\u89C4\u5219\uFF1A\u591A\u6765\u6E90\u5E76\u96C6 \u2192 {p0}\uFF1B{p1}",
904
+ /* ── mentions ── */
905
+ "mentions.create": "\u521B\u5EFA\u201C{p0}\u201D",
906
+ "mentions.customBadge": "\u81EA\u5B9A\u4E49",
907
+ "mentions.loading": "\u52A0\u8F7D\u4E2D\u2026",
908
+ /* ── notification ── */
909
+ "notification.groupBusy": "\u64CD\u4F5C\u7ED3\u675F\u540E\u53EF\u4EE5\u6536\u8D77\u8FD9\u7EC4\u901A\u77E5\u3002",
910
+ "notification.groupUnread": "{count} \u6761\u540C\u7EC4\u901A\u77E5\uFF0C{unread} \u6761\u672A\u8BFB",
911
+ "notification.groupCount": "{count} \u6761\u540C\u7EC4\u901A\u77E5",
912
+ "notification.groupExpanded": "\u6536\u8D77\u8FD9\u7EC4\u901A\u77E5",
913
+ "notification.ariaLabel": "\u901A\u77E5",
914
+ "notification.viewDetails": "\u67E5\u770B\u8BE6\u60C5",
915
+ /* ── pagination ── */
916
+ "pagination.next": "\u4E0B\u4E00\u9875",
917
+ "pagination.pageSize": "{p0} \u6761/\u9875",
918
+ "pagination.prev": "\u4E0A\u4E00\u9875",
919
+ /* ── select ── */
920
+ "select.fieldLabel": "\u9009\u62E9\u9009\u9879",
921
+ "select.noMatch": "\u65E0\u5339\u914D\u9879",
922
+ "select.remove": "\u79FB\u9664 {p0}",
923
+ "select.searchPlaceholder": "\u641C\u7D22\u2026",
924
+ /* ── cascader / tree-select ── */
925
+ "cascader.placeholder": "\u8BF7\u9009\u62E9",
926
+ "cascader.noMatch": "\u65E0\u5339\u914D",
927
+ "cascader.search": "\u641C\u7D22",
928
+ "treeSelect.placeholder": "\u8BF7\u9009\u62E9",
929
+ "treeSelect.noMatch": "\u65E0\u5339\u914D",
930
+ "treeSelect.search": "\u641C\u7D22",
931
+ /* ── tagInput ── */
932
+ "tagInput.ariaLabel": "\u6807\u7B7E\u8F93\u5165\uFF0C\u5171 {p0} \u4E2A",
933
+ "tagInput.remove": "\u79FB\u9664 {p0}",
934
+ "tagInput.field": "\u6DFB\u52A0\u6807\u7B7E",
935
+ "tagInput.added": "\u5DF2\u6DFB\u52A0 {p0} \u4E2A\u6807\u7B7E\u3002",
936
+ "tagInput.removed": "\u5DF2\u79FB\u9664 {p0}\u3002",
937
+ "tagInput.duplicate": "\u5DF2\u6709\u300C{p0}\u300D\uFF0C\u53EF\u4EE5\u7F16\u8F91\u540E\u91CD\u8BD5\u3002",
938
+ "tagInput.limit": "\u6700\u591A {p0} \u4E2A\u6807\u7B7E\uFF0C\u8BF7\u5148\u79FB\u9664\u4E00\u4E2A\u3002",
939
+ /* ── upload ── */
940
+ "upload.remove": "\u79FB\u9664 {p0}",
941
+ "upload.tooBig": "\u6587\u4EF6\u8D85\u8FC7 {p0}",
942
+ "upload.tooMany": "\u6700\u591A {p0} \u4E2A\u6587\u4EF6",
943
+ "upload.typeNotAllowed": "\u6587\u4EF6\u7C7B\u578B\u4E0D\u652F\u6301"
944
+ };
945
+ var current = { ...ICEN_LOCALE_ZH_CN };
946
+ function t(key, vars) {
947
+ const raw = current[key] ?? ICEN_LOCALE_ZH_CN[key];
948
+ if (vars == null || Array.isArray(raw)) return raw;
949
+ return raw.replace(/\{(\w+)\}/g, (m, name) => name in vars ? String(vars[name]) : m);
950
+ }
951
+
952
+ // src/behaviors/svg-parse.ts
953
+ function parseSvg(source) {
954
+ if (typeof document === "undefined" || typeof DOMParser === "undefined") return null;
955
+ const trimmed = source.trimStart();
956
+ if (!trimmed.startsWith("<svg")) return null;
957
+ const src = /^<svg(?![^>]*\bxmlns[=:])/i.test(trimmed) ? trimmed.replace(/^<svg/i, '<svg xmlns="http://www.w3.org/2000/svg"') : trimmed;
958
+ let parsed;
959
+ try {
960
+ parsed = new DOMParser().parseFromString(src, "image/svg+xml");
961
+ } catch {
962
+ return null;
963
+ }
964
+ const root = parsed.documentElement;
965
+ if (!root || root.tagName.toLowerCase() !== "svg" || parsed.querySelector("parsererror")) return null;
966
+ const sanitize = (el) => {
967
+ for (const attr of Array.from(el.attributes)) {
968
+ const name = attr.name.toLowerCase();
969
+ if (name.startsWith("on")) el.removeAttribute(attr.name);
970
+ if ((name === "href" || name === "xlink:href") && attr.value.trim().toLowerCase().startsWith("javascript:")) {
971
+ el.removeAttribute(attr.name);
972
+ }
973
+ }
974
+ for (const child of Array.from(el.children)) {
975
+ const tag = child.tagName.toLowerCase();
976
+ if (tag === "script" || tag === "foreignobject") {
977
+ child.remove();
978
+ continue;
979
+ }
980
+ sanitize(child);
981
+ }
982
+ };
983
+ sanitize(root);
984
+ return document.importNode(root, true);
985
+ }
986
+
1
987
  // src/behaviors/ai-core.ts
2
- var svg = (body) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${body}</svg>`;
3
- var ICON_TERMINAL = svg('<path d="m4 17 6-6-6-6"/><path d="M12 19h8"/>');
4
- var ICON_FILE = svg(
5
- '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/>'
6
- );
7
- var ICON_FILE_PEN = svg(
8
- '<path d="M12.5 22H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8l5 5v3.5"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M19 6.5 16.5 4"/><path d="M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"/>'
9
- );
10
- var ICON_FILE_PLUS = svg(
11
- '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M9 15h6"/><path d="M12 12v6"/>'
12
- );
13
- var ICON_TRASH = svg(
14
- '<path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M10 11v6"/><path d="M14 11v6"/>'
15
- );
16
- var ICON_SEARCH = svg('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>');
17
- var ICON_FOLDER_SEARCH = svg(
18
- '<path d="M11 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4"/><circle cx="17" cy="17" r="3"/><path d="m21 21-1.9-1.9"/>'
19
- );
20
- var ICON_SCAN_SEARCH = svg(
21
- '<path d="M3 7V5a2 2 0 0 1 2-2h2"/><path d="M17 3h2a2 2 0 0 1 2 2v2"/><path d="M21 17v2a2 2 0 0 1-2 2h-2"/><path d="M7 21H5a2 2 0 0 1-2-2v-2"/><circle cx="12" cy="12" r="3"/><path d="m16 16-1.9-1.9"/>'
22
- );
23
- var ICON_GLOBE = svg(
24
- '<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>'
25
- );
26
- var ICON_DOWNLOAD = svg(
27
- '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/><path d="M12 15V3"/>'
28
- );
29
- var ICON_BLOCKS = svg(
30
- '<rect width="7" height="7" x="4" y="4" rx="1"/><rect width="7" height="7" x="13" y="4" rx="1"/><rect width="7" height="7" x="4" y="13" rx="1"/><rect width="7" height="7" x="13" y="13" rx="1"/>'
31
- );
32
- var ICON_ZAP = svg(
33
- '<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>'
34
- );
35
- var ICON_LIST = svg(
36
- '<path d="M3 12h.01"/><path d="M3 18h.01"/><path d="M3 6h.01"/><path d="M8 12h13"/><path d="M8 18h13"/><path d="M8 6h13"/>'
37
- );
38
- var ICON_LIST_CHECKS = svg(
39
- '<path d="m3 17 2 2 4-4"/><path d="m3 7 2 2 4-4"/><path d="M13 6h8"/><path d="M13 12h8"/><path d="M13 18h8"/>'
40
- );
41
- var ICON_BOT = svg(
42
- '<path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/>'
43
- );
44
- var ICON_CHART = svg(
45
- '<path d="M3 3v18h18"/><path d="M7 15l4-6 3 4 5-8"/>'
46
- );
47
- var ICON_FILE_TEXT = svg(
48
- '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>'
49
- );
988
+ var ICON_TERMINAL = iconHTML("terminal");
989
+ var ICON_FILE = iconHTML("file");
990
+ var ICON_FILE_PEN = iconHTML("edit");
991
+ var ICON_FILE_PLUS = iconHTML("plus");
992
+ var ICON_TRASH = iconHTML("trash");
993
+ var ICON_SEARCH = iconHTML("search");
994
+ var ICON_FOLDER_SEARCH = iconHTML("folder");
995
+ var ICON_SCAN_SEARCH = iconHTML("search");
996
+ var ICON_GLOBE = iconHTML("globe");
997
+ var ICON_DOWNLOAD = iconHTML("download");
998
+ var ICON_BLOCKS = iconHTML("server");
999
+ var ICON_ZAP = iconHTML("sparkle");
1000
+ var ICON_LIST = iconHTML("list");
1001
+ var ICON_LIST_CHECKS = iconHTML("list");
1002
+ var ICON_BOT = iconHTML("agent");
1003
+ var ICON_CHART = iconHTML("chart-line");
1004
+ var ICON_FILE_TEXT = iconHTML("document");
50
1005
  function isObj(v) {
51
1006
  return typeof v === "object" && v !== null;
52
1007
  }
@@ -96,86 +1051,58 @@ var sum = (fn) => {
96
1051
  return (input) => fn(input) ?? "";
97
1052
  };
98
1053
  var BUILTIN_KINDS = {
99
- shell: { label: "\u547D\u4EE4", icon: ICON_TERMINAL, tint: "accent", summarize: sum(summarizeShell) },
100
- read: { label: "\u8BFB\u53D6", icon: ICON_FILE, tint: "info", summarize: sum(summarizeRead) },
101
- edit: { label: "\u7F16\u8F91", icon: ICON_FILE_PEN, tint: "warning", summarize: sum(summarizePath) },
102
- write: { label: "\u5199\u5165", icon: ICON_FILE_PLUS, tint: "warning", summarize: sum(summarizePath) },
103
- rm: { label: "\u5220\u9664", icon: ICON_TRASH, tint: "error", summarize: sum(summarizePath) },
104
- grep: { label: "\u641C\u7D22", icon: ICON_SEARCH, tint: "info", summarize: sum(summarizeGrep) },
105
- glob: { label: "\u5339\u914D", icon: ICON_FOLDER_SEARCH, tint: "info", summarize: sum((i) => pickStr(i, ["pattern", "glob", "path"])) },
106
- browser: { label: "\u6D4F\u89C8", icon: ICON_GLOBE, tint: "accent", summarize: sum((i) => pickStr(i, ["url", "uri", "target"])) },
107
- search: { label: "\u68C0\u7D22", icon: ICON_SCAN_SEARCH, tint: "accent", summarize: sum((i) => pickStr(i, ["query", "q", "pattern"])) },
108
- fetch: { label: "\u8BF7\u6C42", icon: ICON_DOWNLOAD, tint: "info", summarize: sum((i) => pickStr(i, ["url", "uri", "endpoint"])) },
1054
+ shell: { label: t("aiCore.kindShell"), icon: ICON_TERMINAL, tint: "accent", summarize: sum(summarizeShell) },
1055
+ read: { label: t("aiCore.kindRead"), icon: ICON_FILE, tint: "info", summarize: sum(summarizeRead) },
1056
+ edit: { label: t("aiCore.kindEdit"), icon: ICON_FILE_PEN, tint: "warning", summarize: sum(summarizePath) },
1057
+ write: { label: t("aiCore.kindWrite"), icon: ICON_FILE_PLUS, tint: "warning", summarize: sum(summarizePath) },
1058
+ rm: { label: t("aiCore.kindDelete"), icon: ICON_TRASH, tint: "error", summarize: sum(summarizePath) },
1059
+ grep: { label: t("aiCore.kindGrep"), icon: ICON_SEARCH, tint: "info", summarize: sum(summarizeGrep) },
1060
+ glob: { label: t("aiCore.kindGlob"), icon: ICON_FOLDER_SEARCH, tint: "info", summarize: sum((i) => pickStr(i, ["pattern", "glob", "path"])) },
1061
+ browser: { label: t("aiCore.kindBrowser"), icon: ICON_GLOBE, tint: "accent", summarize: sum((i) => pickStr(i, ["url", "uri", "target"])) },
1062
+ search: { label: t("aiCore.kindSearch"), icon: ICON_SCAN_SEARCH, tint: "accent", summarize: sum((i) => pickStr(i, ["query", "q", "pattern"])) },
1063
+ fetch: { label: t("aiCore.kindFetch"), icon: ICON_DOWNLOAD, tint: "info", summarize: sum((i) => pickStr(i, ["url", "uri", "endpoint"])) },
109
1064
  mcp: { label: "MCP", icon: ICON_BLOCKS, tint: "muted", summarize: sum((i) => pickStr(i, ["tool", "method", "name"])) },
110
- skill: { label: "\u6280\u80FD", icon: ICON_ZAP, tint: "accent", summarize: sum((i) => pickStr(i, ["skill", "name", "command"])) },
1065
+ skill: { label: t("aiCore.kindSkill"), icon: ICON_ZAP, tint: "accent", summarize: sum((i) => pickStr(i, ["skill", "name", "command"])) },
111
1066
  todo: {
112
- label: "\u5F85\u529E",
1067
+ label: t("aiCore.kindTodo"),
113
1068
  icon: ICON_LIST,
114
1069
  tint: "info",
115
1070
  summarize: sum((input) => {
116
1071
  const items = input && typeof input === "object" && Array.isArray(input.items) ? input.items : Array.isArray(input) ? input : [];
117
1072
  const done = items.filter((it) => it?.status === "done").length;
118
- return items.length > 0 ? `${done}/${items.length} \u5B8C\u6210` : "";
1073
+ return items.length > 0 ? t("aiCore.todoProgress", { p0: done, p1: items.length }) : "";
119
1074
  })
120
1075
  },
121
- plan: { label: "\u8BA1\u5212", icon: ICON_LIST_CHECKS, tint: "info" },
122
- subagent: { label: "\u5B50\u4EE3\u7406", icon: ICON_BOT, tint: "accent", summarize: sum((i) => pickStr(i, ["task", "description", "prompt", "message", "subagent_type"])) },
123
- note: { label: "\u7B14\u8BB0", icon: ICON_FILE_TEXT, tint: "muted" },
124
- chart: { label: "\u56FE\u8868", icon: ICON_CHART, tint: "info", summarize: sum((i) => pickStr(i, ["title", "name"])) }
1076
+ plan: { label: t("aiCore.kindPlan"), icon: ICON_LIST_CHECKS, tint: "info" },
1077
+ subagent: { label: t("aiCore.kindSubagent"), icon: ICON_BOT, tint: "accent", summarize: sum((i) => pickStr(i, ["task", "description", "prompt", "message", "subagent_type"])) },
1078
+ note: { label: t("aiCore.kindNote"), icon: ICON_FILE_TEXT, tint: "muted" },
1079
+ chart: { label: t("aiCore.kindChart"), icon: ICON_CHART, tint: "info", summarize: sum((i) => pickStr(i, ["title", "name"])) }
125
1080
  };
126
1081
  var kindRegistry = new Map(Object.entries(BUILTIN_KINDS));
127
1082
  function h(tag, className, text) {
1083
+ if (typeof document === "undefined") throw new Error("h() \u4EC5\u6D4F\u89C8\u5668\u73AF\u5883\u53EF\u7528\uFF08SSR \u65F6\u7531\u8C03\u7528\u65B9\u5B88\u536B\uFF0C\u89C1\u6A21\u5757\u5934\u6CE8\u91CA\uFF09");
128
1084
  const node = document.createElement(tag);
129
1085
  if (className) node.className = className;
130
1086
  if (text != null) node.textContent = text;
131
1087
  return node;
132
1088
  }
133
- function svgIcon(svg2) {
134
- if (typeof document === "undefined" || typeof DOMParser === "undefined") return null;
135
- let parsed;
136
- try {
137
- parsed = new DOMParser().parseFromString(svg2, "image/svg+xml");
138
- } catch {
139
- return null;
140
- }
141
- const root = parsed.documentElement;
142
- if (!root || root.tagName.toLowerCase() !== "svg" || parsed.querySelector("parsererror")) {
143
- return null;
144
- }
145
- const sanitize = (el) => {
146
- for (const attr of Array.from(el.attributes)) {
147
- const name = attr.name.toLowerCase();
148
- if (name.startsWith("on")) el.removeAttribute(attr.name);
149
- if ((name === "href" || name === "xlink:href") && attr.value.trim().toLowerCase().startsWith("javascript:")) {
150
- el.removeAttribute(attr.name);
151
- }
152
- }
153
- for (const child of Array.from(el.children)) {
154
- const tag = child.tagName.toLowerCase();
155
- if (tag === "script" || tag === "foreignobject") {
156
- child.remove();
157
- continue;
158
- }
159
- sanitize(child);
160
- }
161
- };
162
- sanitize(root);
163
- return document.importNode(root, true);
1089
+ function svgIcon(svg) {
1090
+ return parseSvg(svg);
164
1091
  }
165
1092
 
166
1093
  // src/behaviors/kb-core.ts
167
1094
  var ic = (label, d) => ({ label, icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${d}</svg>` });
168
1095
  var BUILTIN_SOURCE_TYPES = {
169
- doc: ic("\u6587\u6863", '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/>'),
170
- web: ic("\u7F51\u9875", '<circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20z"/>'),
171
- wiki: ic("\u77E5\u8BC6\u5E93", '<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>'),
172
- sheet: ic("\u8868\u683C", '<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M3 15h18M9 3v18M15 3v18"/>'),
173
- db: ic("\u6570\u636E\u5E93", '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.7 4 3 9 3s9-1.3 9-3V5"/><path d="M3 12c0 1.7 4 3 9 3s9-1.3 9-3"/>'),
174
- ticket: ic("\u5DE5\u5355", '<path d="M3 9V7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2a2 2 0 0 0 0 6v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2a2 2 0 0 0 0-6z"/><path d="M13 5v14"/>'),
175
- code: ic("\u4EE3\u7801", '<path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/>'),
176
- api: ic("\u63A5\u53E3", '<path d="M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/>'),
177
- image: ic("\u56FE\u7247", '<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-4.6-4.6a2 2 0 0 0-2.8 0L3 21"/>'),
178
- mail: ic("\u90AE\u4EF6", '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 7L2 7"/>')
1096
+ doc: ic(t("kbCore.typeDocument"), '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/>'),
1097
+ web: ic(t("kbCore.typeWebpage"), '<circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20z"/>'),
1098
+ wiki: ic(t("kbCore.typeKb"), '<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>'),
1099
+ sheet: ic(t("kbCore.typeTable"), '<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M3 15h18M9 3v18M15 3v18"/>'),
1100
+ db: ic(t("kbCore.typeDatabase"), '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.7 4 3 9 3s9-1.3 9-3V5"/><path d="M3 12c0 1.7 4 3 9 3s9-1.3 9-3"/>'),
1101
+ ticket: ic(t("kbCore.typeTicket"), '<path d="M3 9V7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2a2 2 0 0 0 0 6v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2a2 2 0 0 0 0-6z"/><path d="M13 5v14"/>'),
1102
+ code: ic(t("kbCore.typeCode"), '<path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/>'),
1103
+ api: ic(t("kbCore.typeApi"), '<path d="M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/>'),
1104
+ image: ic(t("kbCore.typeImage"), '<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-4.6-4.6a2 2 0 0 0-2.8 0L3 21"/>'),
1105
+ mail: ic(t("kbCore.typeEmail"), '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 7L2 7"/>')
179
1106
  };
180
1107
  var sourceTypeRegistry = new Map(Object.entries(BUILTIN_SOURCE_TYPES));
181
1108
  var LOWER_IS_BETTER = /* @__PURE__ */ new Set(["l2"]);
@@ -191,6 +1118,14 @@ function scorePercent(v, kind, max = 1) {
191
1118
  const pct = scoreHigherIsBetter(kind) ? v / max * 100 : (1 - v / max) * 100;
192
1119
  return Math.max(0, Math.min(100, pct));
193
1120
  }
1121
+ var RUN_LABELS = {
1122
+ unstart: t("kbCore.runUnstarted"),
1123
+ queued: t("kbCore.runQueued"),
1124
+ running: t("kbCore.runRunning"),
1125
+ cancel: t("kbCore.runCancelled"),
1126
+ done: t("kbCore.runDone"),
1127
+ fail: t("kbCore.runFailed")
1128
+ };
194
1129
  function normalizeHit(raw) {
195
1130
  const score = typeof raw.score === "number" && Number.isFinite(raw.score) ? raw.score : null;
196
1131
  return {
@@ -218,8 +1153,19 @@ function normalizeRetrievalParams(raw) {
218
1153
  threshold: typeof r.threshold === "number" ? r.threshold : null
219
1154
  };
220
1155
  }
1156
+ var SPAN_LABELS = {
1157
+ retrieval: t("kbCore.stageRetrieval"),
1158
+ generation: t("kbCore.stageGeneration"),
1159
+ rerank: t("kbCore.stageRerank"),
1160
+ embed: t("kbCore.stageEmbed"),
1161
+ tool: t("kbCore.stageTool"),
1162
+ guard: t("kbCore.stageGuard"),
1163
+ chunk: t("kbCore.stageChunk"),
1164
+ query: t("kbCore.stageQuery"),
1165
+ agent: t("kbCore.stageAgent")
1166
+ };
221
1167
  function kbVisibilityLabel(v) {
222
- return v === "hidden" ? "\u4E0D\u53EF\u89C1" : v === "metadata" ? "\u4EC5\u5143\u6570\u636E" : v === "restricted" ? "\u53D7\u9650" : v === "summary" ? "\u4EC5\u6458\u8981" : "\u53EF\u89C1";
1168
+ return v === "hidden" ? t("kbCore.visHidden") : v === "metadata" ? t("kbCore.visMetadataOnly") : v === "restricted" ? t("common.restricted") : v === "summary" ? t("kbCore.visSummaryOnly") : t("kbCore.visVisible");
223
1169
  }
224
1170
  function normalizeIdentity(raw) {
225
1171
  const r = raw;
@@ -231,18 +1177,909 @@ function normalizeIdentity(raw) {
231
1177
  };
232
1178
  }
233
1179
 
234
- // src/behaviors/events.ts
235
- function emitIcen(source, type, detail) {
236
- return source.dispatchEvent(
237
- new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
1180
+ // src/behaviors/input.ts
1181
+ var searchFields = /* @__PURE__ */ new WeakMap();
1182
+ function enhanceSearchField(input) {
1183
+ if (typeof document === "undefined" || !input.parentElement) return { refresh() {
1184
+ }, destroy() {
1185
+ } };
1186
+ const previous = searchFields.get(input);
1187
+ if (previous) return previous;
1188
+ const host = input.parentElement;
1189
+ const wasFocused = document.activeElement === input;
1190
+ const hadHostClass = host.classList.contains("icen-search-field");
1191
+ const hadInputClass = input.classList.contains("icen-search-input");
1192
+ const hadStandardClass = input.classList.contains("icen-input");
1193
+ const ownedWrap = !host.classList.contains("icen-input-wrap");
1194
+ const next = input.nextSibling;
1195
+ const wrap = ownedWrap ? document.createElement("div") : host;
1196
+ if (ownedWrap) {
1197
+ wrap.className = "icen-input-wrap icen-input-wrap--sm icen-input-wrap--search icen-control";
1198
+ host.insertBefore(wrap, input);
1199
+ wrap.append(input);
1200
+ }
1201
+ const leading = wrap.querySelector(".icen-input-leading") ? null : document.createElement("span");
1202
+ if (leading) {
1203
+ leading.className = "icen-input-leading";
1204
+ leading.append(createIcon("search"));
1205
+ wrap.prepend(leading);
1206
+ }
1207
+ host.classList.add("icen-search-field");
1208
+ input.classList.add("icen-search-input", "icen-input");
1209
+ const clear = document.createElement("button");
1210
+ clear.type = "button";
1211
+ clear.className = "icen-input-clear icen-search-clear";
1212
+ clear.append(createIcon("close"));
1213
+ wrap.append(clear);
1214
+ const ac = new AbortController();
1215
+ let disposed = false;
1216
+ const refresh = () => {
1217
+ if (disposed) return;
1218
+ clear.hidden = !input.value || input.disabled || input.readOnly;
1219
+ clear.setAttribute("aria-label", t("input.clearSearch"));
1220
+ };
1221
+ clear.addEventListener("pointerdown", (event) => event.preventDefault(), { signal: ac.signal });
1222
+ clear.addEventListener("click", () => {
1223
+ if (input.disabled || input.readOnly) return;
1224
+ input.value = "";
1225
+ input.dispatchEvent(new Event("input", { bubbles: true }));
1226
+ input.focus({ preventScroll: true });
1227
+ refresh();
1228
+ }, { signal: ac.signal });
1229
+ for (const event of ["input", "change", "focus"]) input.addEventListener(event, refresh, { signal: ac.signal });
1230
+ document.addEventListener("icen:locale-change", refresh, { signal: ac.signal });
1231
+ const observer = new MutationObserver(refresh);
1232
+ observer.observe(input, { attributes: true, attributeFilter: ["disabled", "readonly"] });
1233
+ refresh();
1234
+ if (wasFocused) input.focus({ preventScroll: true });
1235
+ const handle = { refresh, destroy() {
1236
+ if (disposed) return;
1237
+ disposed = true;
1238
+ observer.disconnect();
1239
+ ac.abort();
1240
+ clear.remove();
1241
+ leading?.remove();
1242
+ searchFields.delete(input);
1243
+ const focused = document.activeElement === input;
1244
+ if (ownedWrap) {
1245
+ host.insertBefore(input, next?.parentNode === host ? next : null);
1246
+ wrap.remove();
1247
+ }
1248
+ if (focused) input.focus({ preventScroll: true });
1249
+ if (!hadHostClass) host.classList.remove("icen-search-field");
1250
+ if (!hadInputClass) input.classList.remove("icen-search-input");
1251
+ if (!hadStandardClass) input.classList.remove("icen-input");
1252
+ } };
1253
+ searchFields.set(input, handle);
1254
+ return handle;
1255
+ }
1256
+
1257
+ // src/behaviors/popover.ts
1258
+ function revealPopoverItem(item, scrollport, opts = {}) {
1259
+ if (typeof document === "undefined") return;
1260
+ if (opts.focus) item.focus({ preventScroll: true });
1261
+ const rect = item.getBoundingClientRect(), bounds = scrollport.getBoundingClientRect();
1262
+ const style = getComputedStyle(scrollport);
1263
+ const inset = (value, extent) => {
1264
+ const amount = Number.parseFloat(value) || 0;
1265
+ return value.endsWith("%") ? amount * extent / 100 : amount;
1266
+ };
1267
+ if (opts.axis !== "inline") {
1268
+ const top = bounds.top + scrollport.clientTop + inset(style.scrollPaddingTop, scrollport.clientHeight);
1269
+ const bottom = bounds.top + scrollport.clientTop + scrollport.clientHeight - inset(style.scrollPaddingBottom, scrollport.clientHeight);
1270
+ if (rect.top < top) scrollport.scrollTop -= top - rect.top;
1271
+ else if (rect.bottom > bottom) scrollport.scrollTop += rect.bottom - bottom;
1272
+ }
1273
+ if (opts.axis === "inline" || opts.axis === "both") {
1274
+ const left = bounds.left + scrollport.clientLeft + inset(style.scrollPaddingLeft, scrollport.clientWidth);
1275
+ const right = bounds.left + scrollport.clientLeft + scrollport.clientWidth - inset(style.scrollPaddingRight, scrollport.clientWidth);
1276
+ if (rect.left < left) scrollport.scrollLeft -= left - rect.left;
1277
+ else if (rect.right > right) scrollport.scrollLeft += rect.right - right;
1278
+ }
1279
+ }
1280
+ var PANEL_SIZING_ATTRS = {
1281
+ width: "data-icen-panel-width",
1282
+ minWidth: "data-icen-panel-min",
1283
+ maxWidth: "data-icen-panel-max",
1284
+ minHeight: "data-icen-panel-min-height",
1285
+ maxHeight: "data-icen-panel-max-height"
1286
+ };
1287
+ function readPanelSizing(el) {
1288
+ const out = {};
1289
+ if (!el) return out;
1290
+ for (const key of Object.keys(PANEL_SIZING_ATTRS)) {
1291
+ const raw = el.getAttribute(PANEL_SIZING_ATTRS[key]);
1292
+ if (raw == null) continue;
1293
+ const n = Number(raw);
1294
+ if (Number.isFinite(n) && n > 0) out[key] = n;
1295
+ }
1296
+ return out;
1297
+ }
1298
+ function resolvePanelSizing(el, overrides) {
1299
+ const base = readPanelSizing(el);
1300
+ if (!overrides) return base;
1301
+ for (const key of Object.keys(overrides)) {
1302
+ const v = overrides[key];
1303
+ if (typeof v === "number" && Number.isFinite(v) && v > 0) base[key] = v;
1304
+ }
1305
+ return base;
1306
+ }
1307
+ var DEFAULT_MIN_WIDTH = 220;
1308
+ var DEFAULT_MAX_WIDTH = 420;
1309
+ var DEFAULT_MIN_HEIGHT = 120;
1310
+ var DEFAULT_MAX_HEIGHT = 420;
1311
+ function clamp(value, min, max) {
1312
+ if (max < min) return min;
1313
+ return Math.min(max, Math.max(min, value));
1314
+ }
1315
+ function chooseSide(preferredSide, availableTop, availableBottom, desiredHeight) {
1316
+ const preferredSpace = preferredSide === "top" ? availableTop : availableBottom;
1317
+ const oppositeSpace = preferredSide === "top" ? availableBottom : availableTop;
1318
+ if (preferredSpace >= desiredHeight) return preferredSide;
1319
+ if (oppositeSpace >= desiredHeight) return preferredSide === "top" ? "bottom" : "top";
1320
+ if (preferredSpace >= oppositeSpace) return preferredSide;
1321
+ return preferredSide === "top" ? "bottom" : "top";
1322
+ }
1323
+ function horizontalAnchor(anchor, width, align) {
1324
+ if (align === "center") return anchor.left + anchor.width / 2 - width / 2;
1325
+ if (align === "end") return anchor.right - width;
1326
+ return anchor.left;
1327
+ }
1328
+ function computePopoverLayout(anchor, viewport, opts = {}) {
1329
+ const margin = opts.margin ?? 12;
1330
+ const offset = opts.offset ?? 8;
1331
+ const preferredSide = opts.side ?? "top";
1332
+ const align = opts.align ?? "start";
1333
+ if (preferredSide === "left" || preferredSide === "right") {
1334
+ const minWidth2 = Math.max(1, opts.minWidth ?? DEFAULT_MIN_WIDTH);
1335
+ const availableLeft = Math.max(0, anchor.left - margin - offset);
1336
+ const availableRight = Math.max(0, viewport.width - anchor.right - margin - offset);
1337
+ const side2 = (preferredSide === "left" ? availableLeft : availableRight) >= minWidth2 ? preferredSide : preferredSide === "left" ? "right" : "left";
1338
+ const maxWidth2 = Math.min(
1339
+ Math.max(opts.maxWidth ?? DEFAULT_MAX_WIDTH, minWidth2),
1340
+ side2 === "left" ? availableLeft : availableRight
1341
+ );
1342
+ const width2 = minWidth2;
1343
+ const left2 = clamp(
1344
+ side2 === "left" ? anchor.left - offset - width2 : anchor.right + offset,
1345
+ margin,
1346
+ viewport.width - margin - width2
1347
+ );
1348
+ const availableHeight2 = Math.max(80, viewport.height - margin * 2);
1349
+ const maxHeight2 = Math.min(opts.maxHeight ?? DEFAULT_MAX_HEIGHT, availableHeight2);
1350
+ const desired = clamp(opts.contentHeightHint ?? Math.min(anchor.height, maxHeight2), 40, maxHeight2);
1351
+ const anchorTop = align === "center" ? anchor.top + anchor.height / 2 - desired / 2 : align === "end" ? anchor.bottom - desired : anchor.top;
1352
+ const top2 = clamp(anchorTop, margin, viewport.height - margin - desired);
1353
+ return { side: side2, left: left2, top: top2, width: width2, maxHeight: maxHeight2 };
1354
+ }
1355
+ const availableWidth = Math.max(80, viewport.width - margin * 2);
1356
+ const requestedMinWidth = Math.max(1, opts.minWidth ?? DEFAULT_MIN_WIDTH);
1357
+ const requestedMaxWidth = Math.max(requestedMinWidth, opts.maxWidth ?? DEFAULT_MAX_WIDTH);
1358
+ const maxWidth = Math.min(requestedMaxWidth, availableWidth);
1359
+ const minWidth = Math.min(requestedMinWidth, maxWidth);
1360
+ const availableTop = Math.max(0, anchor.top - margin - offset);
1361
+ const availableBottom = Math.max(0, viewport.height - anchor.bottom - margin - offset);
1362
+ const availableHeight = Math.max(80, viewport.height - margin * 2);
1363
+ const minHeight = Math.min(Math.max(80, opts.minHeight ?? DEFAULT_MIN_HEIGHT), availableHeight);
1364
+ const requestedMaxHeight = Math.max(minHeight, opts.maxHeight ?? DEFAULT_MAX_HEIGHT);
1365
+ const fallbackHeight = Math.min(260, requestedMaxHeight);
1366
+ const contentHeight = opts.contentHeightHint != null && opts.contentHeightHint > 0 ? opts.contentHeightHint : fallbackHeight;
1367
+ const desiredHeight = clamp(contentHeight, minHeight, Math.min(requestedMaxHeight, availableHeight));
1368
+ const side = chooseSide(preferredSide, availableTop, availableBottom, desiredHeight);
1369
+ const sideSpace = side === "top" ? availableTop : availableBottom;
1370
+ const maxHeight = Math.min(
1371
+ requestedMaxHeight,
1372
+ Math.max(80, sideSpace || Math.max(availableTop, availableBottom)),
1373
+ availableHeight
238
1374
  );
1375
+ const positionedHeight = clamp(desiredHeight, 40, maxHeight);
1376
+ const width = align === "stretch" ? clamp(anchor.width, minWidth, maxWidth) : maxWidth;
1377
+ const left = clamp(horizontalAnchor(anchor, width, align), margin, viewport.width - margin - width);
1378
+ const desiredTop = side === "top" ? anchor.top - offset - positionedHeight : anchor.bottom + offset;
1379
+ const top = clamp(desiredTop, margin, viewport.height - margin - positionedHeight);
1380
+ return { side, left, top, width, maxHeight };
1381
+ }
1382
+
1383
+ // src/behaviors/select.ts
1384
+ var selectSequence = 0;
1385
+ var instances = /* @__PURE__ */ new Map();
1386
+ var openSelect = null;
1387
+ var globalBound = false;
1388
+ var PANEL_OFFSET = 4;
1389
+ var PANEL_MAX_HEIGHT = 240;
1390
+ function onGlobalPointerDown(ev) {
1391
+ const cur = openSelect;
1392
+ if (!cur) return;
1393
+ const t2 = ev.target;
1394
+ if (!(t2 instanceof Node)) return;
1395
+ if (cur.container.contains(t2) || cur.panel.contains(t2)) return;
1396
+ cur.close();
1397
+ }
1398
+ function onGlobalKeyDown(ev) {
1399
+ if (ev.key !== "Escape" || ev.isComposing) return;
1400
+ const cur = openSelect;
1401
+ if (!cur) return;
1402
+ cur.close();
1403
+ cur.trigger.focus();
1404
+ }
1405
+ function onWindowChange() {
1406
+ const cur = openSelect;
1407
+ if (!cur) return;
1408
+ if (!cur.trigger.isConnected) {
1409
+ cur.close();
1410
+ return;
1411
+ }
1412
+ cur.reposition();
1413
+ }
1414
+ function bindGlobalListeners() {
1415
+ if (globalBound) return;
1416
+ globalBound = true;
1417
+ document.addEventListener("pointerdown", onGlobalPointerDown);
1418
+ document.addEventListener("keydown", onGlobalKeyDown);
1419
+ }
1420
+ function bindOpenListeners() {
1421
+ window.addEventListener("scroll", onWindowChange, true);
1422
+ window.addEventListener("resize", onWindowChange);
1423
+ }
1424
+ function unbindOpenListeners() {
1425
+ window.removeEventListener("scroll", onWindowChange, true);
1426
+ window.removeEventListener("resize", onWindowChange);
1427
+ }
1428
+ function setup(container) {
1429
+ const el = container;
1430
+ const existing = instances.get(container);
1431
+ if (existing) return existing.dispose;
1432
+ const ac = new AbortController();
1433
+ const on = (t2, ev, fn) => {
1434
+ const listener = (evt) => fn(evt);
1435
+ t2.addEventListener(ev, listener, { signal: ac.signal });
1436
+ };
1437
+ const triggerEl = container.querySelector(".icen-select-trigger");
1438
+ const panelEl = container.querySelector(".icen-select-panel");
1439
+ const valueEl = container.querySelector(".icen-select-value");
1440
+ const hiddenInput = container.querySelector("input[data-icen-select-value], icen-input[data-icen-select-value]");
1441
+ if (!triggerEl || !panelEl) return () => {
1442
+ };
1443
+ el.__icenSelectInit = true;
1444
+ const trigger = triggerEl;
1445
+ const panel = panelEl;
1446
+ const arrow = trigger.querySelector(".icen-select-chevron");
1447
+ arrow?.remove();
1448
+ const isMultiple = container.hasAttribute("data-icen-select-multiple");
1449
+ const isSearchable = container.hasAttribute("data-icen-select-search");
1450
+ if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
1451
+ const maxSelect = Number(container.getAttribute("data-icen-select-max")) || 0;
1452
+ const panelSizing = resolvePanelSizing(container);
1453
+ function resolvedPanelWidth(triggerWidth) {
1454
+ let w = triggerWidth;
1455
+ if (panelSizing.minWidth != null) w = Math.max(w, panelSizing.minWidth);
1456
+ if (panelSizing.maxWidth != null) w = Math.min(w, panelSizing.maxWidth);
1457
+ if (panelSizing.width != null) w = panelSizing.width;
1458
+ return w;
1459
+ }
1460
+ const placeholder = container.getAttribute("data-icen-select-placeholder") ?? (valueEl?.classList.contains("is-empty") ? valueEl?.textContent ?? "" : "");
1461
+ if (isMultiple) panel.setAttribute("data-icen-select-multiple", "");
1462
+ let searchInput = null;
1463
+ let focusIdx = -1;
1464
+ if (isSearchable && !panel.querySelector(".icen-select-search-input")) {
1465
+ const searchWrap = document.createElement("div");
1466
+ searchWrap.className = "icen-select-search";
1467
+ const input = document.createElement("input");
1468
+ input.className = "icen-select-search-input";
1469
+ input.type = "search";
1470
+ input.placeholder = t("select.searchPlaceholder");
1471
+ searchWrap.appendChild(input);
1472
+ panel.insertBefore(searchWrap, panel.firstChild);
1473
+ }
1474
+ searchInput = panel.querySelector(".icen-select-search-input");
1475
+ const searchField = searchInput ? enhanceSearchField(searchInput) : null;
1476
+ ac.signal.addEventListener("abort", () => searchField?.destroy(), { once: true });
1477
+ let list = panel.querySelector("[data-icen-select-options]");
1478
+ if (!list) {
1479
+ list = document.createElement("div");
1480
+ list.className = "icen-select-options";
1481
+ list.setAttribute("data-icen-select-options", "");
1482
+ for (const child of Array.from(panel.children)) {
1483
+ if (!child.matches(".icen-select-search,.icen-select-empty")) list.append(child);
1484
+ }
1485
+ panel.append(list);
1486
+ }
1487
+ const optionsList = list;
1488
+ const allOptions = () => Array.from(panel.querySelectorAll(".icen-select-option"));
1489
+ if (!allOptions().some((option) => option.classList.contains("is-selected"))) {
1490
+ const requested = (container.getAttribute("data-icen-value") ?? hiddenInput?.value ?? "").split(",").filter(Boolean);
1491
+ let matched = false;
1492
+ allOptions().forEach((option) => {
1493
+ const selected = requested.includes(option.getAttribute("data-icen-value") ?? "") && (isMultiple || !matched);
1494
+ if (selected) {
1495
+ option.classList.add("is-selected");
1496
+ matched = true;
1497
+ }
1498
+ });
1499
+ }
1500
+ const originalDisabled = /* @__PURE__ */ new WeakSet();
1501
+ const knownOptions = /* @__PURE__ */ new WeakSet();
1502
+ panel.id ||= `icen-select-list-${++selectSequence}`;
1503
+ optionsList.id ||= `${panel.id}-options`;
1504
+ if (panel.getAttribute("role") === "listbox") panel.removeAttribute("role");
1505
+ optionsList.setAttribute("role", "listbox");
1506
+ optionsList.setAttribute("aria-label", trigger.getAttribute("aria-label") ?? (placeholder || t("select.fieldLabel")));
1507
+ if (isMultiple) optionsList.setAttribute("aria-multiselectable", "true");
1508
+ trigger.setAttribute("aria-controls", optionsList.id);
1509
+ trigger.setAttribute("aria-haspopup", "listbox");
1510
+ searchInput?.setAttribute("aria-label", t("select.searchPlaceholder"));
1511
+ if (searchInput) {
1512
+ searchInput.setAttribute("role", "combobox");
1513
+ searchInput.setAttribute("aria-autocomplete", "list");
1514
+ searchInput.setAttribute("aria-controls", optionsList.id);
1515
+ searchInput.setAttribute("aria-expanded", "false");
1516
+ }
1517
+ function prepareOptions() {
1518
+ const atLimit = isMultiple && maxSelect > 0 && getSelectedValues().length >= maxSelect;
1519
+ allOptions().forEach((option) => {
1520
+ if (!option.hasAttribute("type")) option.type = "button";
1521
+ if (!knownOptions.has(option)) {
1522
+ knownOptions.add(option);
1523
+ if (!option.hasAttribute("data-icen-select-limit-disabled") && option.matches('.is-disabled,[aria-disabled="true"]')) originalDisabled.add(option);
1524
+ }
1525
+ option.id ||= `${optionsList.id}-option-${++selectSequence}`;
1526
+ const limited = atLimit && !option.classList.contains("is-selected");
1527
+ const authored = originalDisabled.has(option) || option.disabled || option.hasAttribute("data-icen-disabled");
1528
+ option.toggleAttribute("data-icen-select-limit-disabled", limited && !authored);
1529
+ option.classList.toggle("is-disabled", authored || limited);
1530
+ });
1531
+ panel.querySelectorAll(".icen-select-group").forEach((group) => {
1532
+ group.setAttribute("role", "group");
1533
+ const heading = group.querySelector(".icen-select-group-label");
1534
+ if (heading && !group.hasAttribute("aria-label") && !group.hasAttribute("aria-labelledby")) {
1535
+ heading.id ||= `${optionsList.id}-group-${++selectSequence}`;
1536
+ group.setAttribute("aria-labelledby", heading.id);
1537
+ }
1538
+ });
1539
+ }
1540
+ function syncOptionAria() {
1541
+ prepareOptions();
1542
+ allOptions().forEach((option) => {
1543
+ if (originalDisabled.has(option)) option.classList.add("is-disabled");
1544
+ option.setAttribute("role", "option");
1545
+ option.setAttribute("aria-selected", String(option.classList.contains("is-selected")));
1546
+ option.setAttribute("aria-disabled", String(option.classList.contains("is-disabled")));
1547
+ option.tabIndex = -1;
1548
+ });
1549
+ }
1550
+ syncOptionAria();
1551
+ const visibleOptions = () => allOptions().filter((o) => !o.hidden);
1552
+ const isOpen = () => !panel.hidden;
1553
+ function setFocus(idx, moveDomFocus = false) {
1554
+ const opts = visibleOptions();
1555
+ focusIdx = Math.max(-1, Math.min(idx, opts.length - 1));
1556
+ opts.forEach((o, i) => o.classList.toggle("is-focused", i === focusIdx));
1557
+ const cur = focusIdx >= 0 ? opts[focusIdx] : void 0;
1558
+ if (cur && searchInput) searchInput.setAttribute("aria-activedescendant", cur.id);
1559
+ else searchInput?.removeAttribute("aria-activedescendant");
1560
+ if (cur) revealPopoverItem(cur, panel, { focus: moveDomFocus });
1561
+ }
1562
+ function firstEnabled() {
1563
+ return visibleOptions().findIndex((o) => !o.classList.contains("is-disabled"));
1564
+ }
1565
+ function lastEnabled() {
1566
+ const opts = visibleOptions();
1567
+ for (let i = opts.length - 1; i >= 0; i--) if (!opts[i].classList.contains("is-disabled")) return i;
1568
+ return -1;
1569
+ }
1570
+ function leaveByTab() {
1571
+ closePanel();
1572
+ trigger.focus({ preventScroll: true });
1573
+ }
1574
+ function moveFocus(delta) {
1575
+ const opts = visibleOptions();
1576
+ if (opts.length === 0) return;
1577
+ if (!opts.some((option) => !option.classList.contains("is-disabled"))) {
1578
+ setFocus(-1);
1579
+ return;
1580
+ }
1581
+ let n = focusIdx < 0 && delta < 0 ? 0 : focusIdx;
1582
+ for (let guard = 0; guard < opts.length; guard++) {
1583
+ n = (n + delta + opts.length) % opts.length;
1584
+ const opt = opts[n];
1585
+ if (opt && !opt.classList.contains("is-disabled")) break;
1586
+ }
1587
+ setFocus(n, document.activeElement !== searchInput);
1588
+ }
1589
+ let emptyEl = panel.querySelector(".icen-select-empty");
1590
+ if (!emptyEl) {
1591
+ emptyEl = document.createElement("div");
1592
+ emptyEl.className = "icen-select-empty";
1593
+ emptyEl.textContent = t("select.noMatch");
1594
+ emptyEl.hidden = true;
1595
+ panel.appendChild(emptyEl);
1596
+ }
1597
+ function updateEmptyState() {
1598
+ const hasVisible = visibleOptions().length > 0;
1599
+ if (emptyEl) emptyEl.hidden = hasVisible;
1600
+ optionsList.hidden = !hasVisible;
1601
+ }
1602
+ emptyEl.setAttribute("role", "status");
1603
+ function filterOptions(query) {
1604
+ searchField?.refresh();
1605
+ const q = query.trim().toLowerCase();
1606
+ const groups = Array.from(panel.querySelectorAll(".icen-select-group"));
1607
+ for (const opt of allOptions()) {
1608
+ const text = (opt.textContent ?? "").toLowerCase();
1609
+ const kw = (opt.getAttribute("data-icen-keywords") ?? "").toLowerCase();
1610
+ opt.hidden = q !== "" && !text.includes(q) && !kw.includes(q);
1611
+ }
1612
+ for (const g of groups) {
1613
+ const hasVisible = Array.from(g.querySelectorAll(".icen-select-option")).some((o) => !o.hidden);
1614
+ g.hidden = !hasVisible;
1615
+ }
1616
+ updateEmptyState();
1617
+ setFocus(isOpen() ? firstEnabled() : -1);
1618
+ }
1619
+ if (searchInput) {
1620
+ on(searchInput, "input", (event) => {
1621
+ if (!event.isComposing) filterOptions(searchInput.value);
1622
+ });
1623
+ on(searchInput, "compositionend", () => filterOptions(searchInput.value));
1624
+ on(searchInput, "keydown", (ev) => {
1625
+ if (ev.isComposing || ev.keyCode === 229) return;
1626
+ if (ev.key === "Escape") {
1627
+ ev.preventDefault();
1628
+ ev.stopPropagation();
1629
+ if (searchInput.value) {
1630
+ searchInput.value = "";
1631
+ filterOptions("");
1632
+ } else {
1633
+ closePanel();
1634
+ trigger.focus({ preventScroll: true });
1635
+ }
1636
+ } else if (ev.key === "ArrowDown" || ev.key === "ArrowUp") {
1637
+ ev.preventDefault();
1638
+ moveFocus(ev.key === "ArrowDown" ? 1 : -1);
1639
+ } else if (ev.key === "Enter") {
1640
+ ev.preventDefault();
1641
+ const option = visibleOptions()[focusIdx];
1642
+ if (option) choose(option);
1643
+ } else if (ev.key === "Tab" && (ev.shiftKey || panel.querySelector(".icen-search-clear")?.hidden !== false)) leaveByTab();
1644
+ });
1645
+ }
1646
+ function positionPanel() {
1647
+ const rect = trigger.getBoundingClientRect();
1648
+ const panelWidth = resolvedPanelWidth(rect.width);
1649
+ const layout = computePopoverLayout(
1650
+ rect,
1651
+ { width: window.innerWidth, height: window.innerHeight },
1652
+ {
1653
+ side: "bottom",
1654
+ align: "stretch",
1655
+ offset: PANEL_OFFSET,
1656
+ minWidth: panelWidth,
1657
+ maxWidth: panelWidth,
1658
+ maxHeight: panelSizing.maxHeight ?? PANEL_MAX_HEIGHT,
1659
+ contentHeightHint: panel.scrollHeight
1660
+ }
1661
+ );
1662
+ panel.style.left = `${layout.left + window.scrollX}px`;
1663
+ panel.style.top = `${layout.top + window.scrollY}px`;
1664
+ panel.style.minWidth = `${layout.width}px`;
1665
+ panel.style.width = `${layout.width}px`;
1666
+ panel.style.maxHeight = `${layout.maxHeight}px`;
1667
+ panel.dataset.icenSide = layout.side;
1668
+ }
1669
+ function openPanel(edge) {
1670
+ if (isOpen() || trigger.disabled || container.matches('[data-icen-disabled],[aria-disabled="true"]')) return;
1671
+ openSelect?.close();
1672
+ if (panel.parentElement !== document.body) document.body.appendChild(panel);
1673
+ panel.hidden = false;
1674
+ container.classList.add("is-open");
1675
+ trigger.setAttribute("aria-expanded", "true");
1676
+ syncOptionAria();
1677
+ searchInput?.setAttribute("aria-expanded", "true");
1678
+ positionPanel();
1679
+ openSelect = { container, trigger, panel, close: closePanel, reposition: positionPanel };
1680
+ bindOpenListeners();
1681
+ if (searchInput) {
1682
+ searchInput.value = "";
1683
+ filterOptions("");
1684
+ searchInput.focus({ preventScroll: true });
1685
+ } else {
1686
+ const opts = visibleOptions();
1687
+ const sel = opts.findIndex((o) => o.classList.contains("is-selected") && !o.classList.contains("is-disabled"));
1688
+ setFocus(edge === "last" ? lastEnabled() : edge === "first" ? firstEnabled() : sel >= 0 ? sel : firstEnabled(), true);
1689
+ }
1690
+ }
1691
+ function closePanel() {
1692
+ if (!isOpen()) return;
1693
+ panel.hidden = true;
1694
+ container.classList.remove("is-open");
1695
+ trigger.setAttribute("aria-expanded", "false");
1696
+ searchInput?.setAttribute("aria-expanded", "false");
1697
+ setFocus(-1);
1698
+ if (openSelect?.panel === panel) openSelect = null;
1699
+ unbindOpenListeners();
1700
+ }
1701
+ function getSelectedValues() {
1702
+ return allOptions().filter((o) => o.classList.contains("is-selected")).map((o) => o.getAttribute("data-icen-value") ?? "");
1703
+ }
1704
+ let chipsClickBound = false;
1705
+ function updateMultiTrigger() {
1706
+ if (!valueEl) return;
1707
+ const selected = allOptions().filter((o) => o.classList.contains("is-selected"));
1708
+ let chipsEl = container.querySelector(".icen-select-chips");
1709
+ if (selected.length === 0) {
1710
+ valueEl.textContent = placeholder;
1711
+ valueEl.classList.add("is-empty");
1712
+ valueEl.hidden = false;
1713
+ if (chipsEl) {
1714
+ chipsEl.hidden = true;
1715
+ chipsEl.replaceChildren();
1716
+ }
1717
+ container.removeAttribute("data-icen-value");
1718
+ } else {
1719
+ valueEl.classList.remove("is-empty");
1720
+ valueEl.hidden = true;
1721
+ if (!chipsEl) {
1722
+ chipsEl = document.createElement("span");
1723
+ chipsEl.className = "icen-select-chips";
1724
+ trigger.insertAdjacentElement("afterend", chipsEl);
1725
+ }
1726
+ if (trigger.contains(chipsEl)) trigger.insertAdjacentElement("afterend", chipsEl);
1727
+ if (!chipsClickBound) {
1728
+ chipsClickBound = true;
1729
+ const chips = chipsEl;
1730
+ on(chips, "click", (event) => {
1731
+ const target = event.target instanceof Element ? event.target.closest(".icen-select-chip-x") : null;
1732
+ if (!target) {
1733
+ trigger.click();
1734
+ return;
1735
+ }
1736
+ if (target.disabled) return;
1737
+ event.preventDefault();
1738
+ event.stopPropagation();
1739
+ const buttons = Array.from(chips.querySelectorAll(".icen-select-chip-x"));
1740
+ const index = buttons.indexOf(target);
1741
+ const option = allOptions().find((option2) => option2.getAttribute("data-icen-value") === target.dataset.icenValue);
1742
+ if (!option) return;
1743
+ option.classList.remove("is-selected");
1744
+ updateMultiTrigger();
1745
+ syncHiddenInput();
1746
+ const remaining = chips.querySelectorAll(".icen-select-chip-x");
1747
+ (remaining[Math.min(index, remaining.length - 1)] ?? trigger).focus({ preventScroll: true });
1748
+ });
1749
+ }
1750
+ chipsEl.hidden = false;
1751
+ chipsEl.textContent = "";
1752
+ const maxLabel = Number(container.getAttribute("data-icen-select-max-label")) || 3;
1753
+ const shown = selected.slice(0, maxLabel);
1754
+ const rest = selected.length - shown.length;
1755
+ for (const o of shown) {
1756
+ const label = o.textContent ?? "";
1757
+ const chip = document.createElement("span");
1758
+ chip.className = "icen-select-chip";
1759
+ const lb = document.createElement("span");
1760
+ lb.textContent = label;
1761
+ chip.appendChild(lb);
1762
+ const x = document.createElement("button");
1763
+ x.type = "button";
1764
+ x.className = "icen-select-chip-x";
1765
+ x.dataset.icenValue = o.getAttribute("data-icen-value") ?? "";
1766
+ x.disabled = trigger.disabled || container.hasAttribute("data-icen-disabled") || container.getAttribute("aria-disabled") === "true";
1767
+ x.setAttribute("aria-label", t("select.remove", { p0: label }));
1768
+ x.append(createIcon("close", { size: 12 }));
1769
+ chip.appendChild(x);
1770
+ chipsEl.appendChild(chip);
1771
+ }
1772
+ if (rest > 0) {
1773
+ const more = document.createElement("span");
1774
+ more.className = "icen-select-chip icen-select-chip--more";
1775
+ more.textContent = `+${rest}`;
1776
+ chipsEl.appendChild(more);
1777
+ }
1778
+ container.setAttribute("data-icen-value", getSelectedValues().join(","));
1779
+ }
1780
+ if (clearBtn) clearBtn.hidden = selected.length === 0;
1781
+ syncOptionAria();
1782
+ }
1783
+ function syncHiddenInput() {
1784
+ syncOptionAria();
1785
+ const values = getSelectedValues();
1786
+ const label = allOptions().filter((o) => o.classList.contains("is-selected")).map((o) => (o.textContent ?? "").trim()).join(", ");
1787
+ if (hiddenInput) hiddenInput.value = isMultiple ? values.join(",") : values[0] ?? "";
1788
+ emitIcen(container, "icen:select-change", { value: values[0] ?? "", values, label });
1789
+ hiddenInput?.dispatchEvent(new Event("change", { bubbles: true }));
1790
+ }
1791
+ function choose(opt) {
1792
+ if (opt.classList.contains("is-disabled")) return;
1793
+ if (isMultiple) {
1794
+ opt.classList.toggle("is-selected");
1795
+ container.setAttribute(
1796
+ "data-icen-value",
1797
+ getSelectedValues().join(",")
1798
+ );
1799
+ updateMultiTrigger();
1800
+ syncHiddenInput();
1801
+ if (searchInput) searchInput.focus();
1802
+ else opt.focus();
1803
+ } else {
1804
+ allOptions().forEach((o) => o.classList.toggle("is-selected", o === opt));
1805
+ if (valueEl) {
1806
+ valueEl.textContent = opt.textContent ?? "";
1807
+ valueEl.classList.remove("is-empty");
1808
+ }
1809
+ const v = opt.getAttribute("data-icen-value") ?? "";
1810
+ container.setAttribute("data-icen-value", v);
1811
+ syncHiddenInput();
1812
+ closePanel();
1813
+ trigger.focus();
1814
+ }
1815
+ }
1816
+ const clearBtn = container.querySelector(".icen-select-clear");
1817
+ if (!trigger.hasAttribute("type")) trigger.type = "button";
1818
+ if (clearBtn instanceof HTMLButtonElement && !clearBtn.hasAttribute("type")) clearBtn.type = "button";
1819
+ if (clearBtn) {
1820
+ clearBtn.replaceChildren(createIcon("close"));
1821
+ clearBtn.classList.add("icen-icon-action");
1822
+ clearBtn.setAttribute("data-icen-reveal", "");
1823
+ }
1824
+ if (clearBtn && isMultiple) {
1825
+ on(clearBtn, "click", (ev) => {
1826
+ ev.stopPropagation();
1827
+ allOptions().forEach((o) => o.classList.remove("is-selected"));
1828
+ updateMultiTrigger();
1829
+ syncHiddenInput();
1830
+ trigger.focus({ preventScroll: true });
1831
+ });
1832
+ on(clearBtn, "pointerdown", (ev) => ev.stopPropagation());
1833
+ }
1834
+ on(trigger, "click", () => isOpen() ? closePanel() : openPanel());
1835
+ let typed = "";
1836
+ let typedAt = 0;
1837
+ function handleListKey(ev) {
1838
+ if (ev.isComposing || ev.keyCode === 229) return;
1839
+ if (!isOpen()) {
1840
+ if (["ArrowDown", "ArrowUp", "Enter", " ", "Home", "End"].includes(ev.key)) {
1841
+ ev.preventDefault();
1842
+ openPanel(ev.key === "End" || ev.key === "ArrowUp" ? "last" : ev.key === "Home" ? "first" : void 0);
1843
+ return;
1844
+ }
1845
+ }
1846
+ switch (ev.key) {
1847
+ case "ArrowDown":
1848
+ ev.preventDefault();
1849
+ moveFocus(1);
1850
+ break;
1851
+ case "ArrowUp":
1852
+ ev.preventDefault();
1853
+ moveFocus(-1);
1854
+ break;
1855
+ case "Home":
1856
+ ev.preventDefault();
1857
+ setFocus(firstEnabled(), true);
1858
+ break;
1859
+ case "End":
1860
+ ev.preventDefault();
1861
+ setFocus(lastEnabled(), true);
1862
+ break;
1863
+ case "Enter":
1864
+ case " ": {
1865
+ ev.preventDefault();
1866
+ const opt = visibleOptions()[focusIdx];
1867
+ if (opt) choose(opt);
1868
+ break;
1869
+ }
1870
+ case "Escape":
1871
+ ev.preventDefault();
1872
+ closePanel();
1873
+ trigger.focus({ preventScroll: true });
1874
+ break;
1875
+ case "Tab":
1876
+ if (isOpen()) leaveByTab();
1877
+ break;
1878
+ default: {
1879
+ if (isSearchable || ev.ctrlKey || ev.metaKey || ev.altKey || ev.key.length !== 1) return;
1880
+ ev.preventDefault();
1881
+ if (!isOpen()) openPanel();
1882
+ if (!isOpen()) return;
1883
+ const now = Date.now();
1884
+ typed = now - typedAt < 600 ? typed + ev.key : ev.key;
1885
+ typedAt = now;
1886
+ let query = typed.toLocaleLowerCase();
1887
+ if ([...query].every((character) => character === query[0])) {
1888
+ query = query[0];
1889
+ typed = query;
1890
+ }
1891
+ const opts = visibleOptions();
1892
+ const start = query.length === 1 ? focusIdx + 1 : Math.max(0, focusIdx);
1893
+ for (let step = 0; step < opts.length; step++) {
1894
+ const index = (start + step + opts.length) % opts.length;
1895
+ const option = opts[index];
1896
+ if (!option.classList.contains("is-disabled") && (option.textContent ?? "").trim().toLocaleLowerCase().startsWith(query)) {
1897
+ setFocus(index, true);
1898
+ break;
1899
+ }
1900
+ }
1901
+ }
1902
+ }
1903
+ }
1904
+ on(trigger, "keydown", handleListKey);
1905
+ on(panel, "click", (ev) => {
1906
+ const t2 = ev.target;
1907
+ if (!(t2 instanceof Element)) return;
1908
+ const opt = t2.closest(".icen-select-option");
1909
+ if (opt instanceof HTMLButtonElement && panel.contains(opt)) choose(opt);
1910
+ });
1911
+ on(panel, "keydown", (event) => {
1912
+ if (event.target === searchInput) return;
1913
+ if (event.target instanceof Element && event.target.closest(".icen-search-clear")) {
1914
+ if (event.key === "Tab" && !event.shiftKey) leaveByTab();
1915
+ return;
1916
+ }
1917
+ handleListKey(event);
1918
+ });
1919
+ on(panel, "mouseover", (ev) => {
1920
+ const t2 = ev.target;
1921
+ if (!(t2 instanceof Element)) return;
1922
+ const opt = t2.closest(".icen-select-option");
1923
+ if (!opt || opt.hidden) return;
1924
+ const idx = visibleOptions().indexOf(opt);
1925
+ if (idx >= 0 && !opt.classList.contains("is-disabled")) setFocus(idx);
1926
+ });
1927
+ function refresh() {
1928
+ for (const child of Array.from(panel.children)) {
1929
+ if (child.matches(".icen-select-option,.icen-select-group")) optionsList.append(child);
1930
+ }
1931
+ const focusedRemove = container.querySelector(".icen-select-chip-x:focus")?.dataset.icenValue;
1932
+ syncOptionAria();
1933
+ if (isMultiple) updateMultiTrigger();
1934
+ else {
1935
+ const selected = allOptions().find((option) => option.classList.contains("is-selected"));
1936
+ if (valueEl) {
1937
+ valueEl.textContent = selected?.textContent ?? (placeholder || t("select.fieldLabel"));
1938
+ valueEl.classList.toggle("is-empty", !selected);
1939
+ }
1940
+ if (selected) container.setAttribute("data-icen-value", selected.getAttribute("data-icen-value") ?? "");
1941
+ else container.removeAttribute("data-icen-value");
1942
+ }
1943
+ if (hiddenInput) hiddenInput.value = isMultiple ? getSelectedValues().join(",") : getSelectedValues()[0] ?? "";
1944
+ if (searchInput) filterOptions(searchInput.value);
1945
+ else updateEmptyState();
1946
+ if (focusedRemove != null) {
1947
+ const next = Array.from(container.querySelectorAll(".icen-select-chip-x")).find((button) => button.dataset.icenValue === focusedRemove);
1948
+ (next ?? trigger).focus({ preventScroll: true });
1949
+ }
1950
+ if (isOpen()) positionPanel();
1951
+ }
1952
+ refresh();
1953
+ let disposed = false;
1954
+ let refreshPending = false;
1955
+ const observer = new MutationObserver(() => {
1956
+ if (refreshPending) return;
1957
+ refreshPending = true;
1958
+ queueMicrotask(() => {
1959
+ refreshPending = false;
1960
+ if (!disposed) refresh();
1961
+ });
1962
+ });
1963
+ observer.observe(panel, { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: ["disabled", "data-icen-disabled", "data-icen-value", "data-icen-keywords"] });
1964
+ const dispose = () => {
1965
+ if (disposed) return;
1966
+ disposed = true;
1967
+ observer.disconnect();
1968
+ if (openSelect?.panel === panel) closePanel();
1969
+ if (panel.parentElement === document.body) container.appendChild(panel);
1970
+ ac.abort();
1971
+ allOptions().forEach((option) => {
1972
+ option.removeAttribute("data-icen-select-limit-disabled");
1973
+ option.classList.toggle("is-disabled", originalDisabled.has(option));
1974
+ if (!originalDisabled.has(option)) option.removeAttribute("aria-disabled");
1975
+ });
1976
+ el.__icenSelectInit = false;
1977
+ instances.delete(container);
1978
+ activeSetups.delete(dispose);
1979
+ if (!activeSetups.size && globalBound) {
1980
+ document.removeEventListener("pointerdown", onGlobalPointerDown);
1981
+ document.removeEventListener("keydown", onGlobalKeyDown);
1982
+ globalBound = false;
1983
+ }
1984
+ };
1985
+ instances.set(container, { dispose, refresh, wasConnected: container.isConnected });
1986
+ return dispose;
1987
+ }
1988
+ var activeSetups = /* @__PURE__ */ new Set();
1989
+ function initSelect(root) {
1990
+ if (typeof document === "undefined") return () => {
1991
+ };
1992
+ const scope = root ?? document;
1993
+ for (const [container, instance] of instances) {
1994
+ if (container.isConnected) instance.wasConnected = true;
1995
+ else if (instance.wasConnected) instance.dispose();
1996
+ }
1997
+ const containers = [];
1998
+ if (scope instanceof Element && scope.matches("[data-icen-select]")) containers.push(scope);
1999
+ containers.push(...Array.from(scope.querySelectorAll("[data-icen-select]")));
2000
+ const disposers = [];
2001
+ for (const c of containers) {
2002
+ const dispose = setup(c);
2003
+ if (!instances.has(c)) continue;
2004
+ activeSetups.add(dispose);
2005
+ disposers.push(dispose);
2006
+ }
2007
+ if (disposers.length) bindGlobalListeners();
2008
+ return () => {
2009
+ for (const d of disposers) {
2010
+ d();
2011
+ activeSetups.delete(d);
2012
+ }
2013
+ if (activeSetups.size === 0 && globalBound) {
2014
+ document.removeEventListener("pointerdown", onGlobalPointerDown);
2015
+ document.removeEventListener("keydown", onGlobalKeyDown);
2016
+ globalBound = false;
2017
+ }
2018
+ };
2019
+ }
2020
+ function refreshSelect(root) {
2021
+ if (typeof document === "undefined") return;
2022
+ const scope = root ?? document;
2023
+ for (const [container, instance] of instances) {
2024
+ if (scope === container || scope instanceof Node && scope.contains(container)) instance.refresh();
2025
+ }
2026
+ }
2027
+
2028
+ // src/behaviors/kb-select.ts
2029
+ function kbSelect(cfg) {
2030
+ if (typeof document === "undefined") {
2031
+ return { el: null, getValue: () => "", setValue: () => void 0, setDisabled: () => void 0 };
2032
+ }
2033
+ const initial = cfg.options.some((o) => o.value === (cfg.value ?? "")) ? cfg.value : "";
2034
+ const labelOf = (v) => cfg.options.find((o) => o.value === v)?.label ?? "";
2035
+ const box = h("div", `icen-select${cfg.cls ? ` ${cfg.cls}` : ""}`);
2036
+ box.setAttribute("data-icen-select", "");
2037
+ box.setAttribute("data-icen-panel-min", String(cfg.panelMin ?? 96));
2038
+ if (cfg.panelWidth != null) box.setAttribute("data-icen-panel-width", String(cfg.panelWidth));
2039
+ const trigger = h("button", `icen-select-trigger icen-pressable icen-focus-ring${cfg.sm ? " icen-select-trigger--sm" : ""}`);
2040
+ trigger.type = "button";
2041
+ trigger.setAttribute("aria-haspopup", "listbox");
2042
+ trigger.setAttribute("aria-expanded", "false");
2043
+ if (cfg.ariaLabel) trigger.setAttribute("aria-label", cfg.ariaLabel);
2044
+ trigger.appendChild(h("span", `icen-select-value${initial ? "" : " is-empty"}`, labelOf(initial)));
2045
+ const panel = h("div", "icen-select-panel");
2046
+ panel.hidden = true;
2047
+ for (const o of cfg.options) {
2048
+ const opt = h("button", "icen-select-option", o.label);
2049
+ opt.type = "button";
2050
+ opt.setAttribute("data-icen-value", o.value);
2051
+ panel.appendChild(opt);
2052
+ }
2053
+ const hidden = document.createElement("input");
2054
+ hidden.type = "hidden";
2055
+ hidden.setAttribute("data-icen-select-value", "");
2056
+ hidden.value = initial;
2057
+ box.append(trigger, panel, hidden);
2058
+ initSelect(box);
2059
+ if (cfg.onChange) box.addEventListener("icen:select-change", (ev) => cfg.onChange(ev.detail.value));
2060
+ return {
2061
+ el: box,
2062
+ getValue: () => hidden.value,
2063
+ setValue(value) {
2064
+ const v = cfg.options.some((o) => o.value === value) ? value : "";
2065
+ for (const opt of Array.from(box.querySelectorAll(".icen-select-option"))) {
2066
+ opt.classList.toggle("is-selected", opt.getAttribute("data-icen-value") === v);
2067
+ }
2068
+ refreshSelect(box);
2069
+ },
2070
+ setDisabled(disabled) {
2071
+ trigger.disabled = disabled;
2072
+ if (disabled) box.setAttribute("aria-disabled", "true");
2073
+ else box.removeAttribute("aria-disabled");
2074
+ }
2075
+ };
239
2076
  }
240
2077
 
241
2078
  // src/behaviors/kb-retrieval.ts
242
2079
  var MODES = [
243
- ["vector", "\u5411\u91CF"],
244
- ["keyword", "\u5173\u952E\u8BCD"],
245
- ["hybrid", "\u6DF7\u5408"]
2080
+ ["vector", t("kbRetrieval.modeVector")],
2081
+ ["keyword", t("kbRetrieval.modeKeyword")],
2082
+ ["hybrid", t("kbRetrieval.modeHybrid")]
246
2083
  ];
247
2084
  var TOP_K_MIN = 1;
248
2085
  var TOP_K_MAX = 50;
@@ -252,9 +2089,9 @@ var ICON_COPY = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
252
2089
  var LAYER_ORDER = ["pre", "post", "none"];
253
2090
  var LAYER_LABEL = { pre: "pre \u2713", post: "post \u26A0", none: "none \u2715" };
254
2091
  var LAYER_TITLE = {
255
- pre: "pre-filter\uFF1AACL \u5728\u68C0\u7D22\u6267\u884C\u4F53\u5185\u751F\u6548\u2014\u2014\u5B89\u5168\u57FA\u7EBF",
256
- post: "post-filter\uFF1A\u5206\u6570\u5DF2\u53EF\u89C2\u5BDF\u2014\u2014\u7F3A\u9677\u5C42\uFF0C\u4EC5\u6F14\u793A",
257
- none: "none\uFF1Afail-open\uFF0C\u65E0\u8EAB\u4EFD\u8FC7\u6EE4\u8FD4\u56DE\u5168\u90E8\u2014\u2014\u5371\u9669\uFF0C\u4EC5\u6F14\u793A"
2092
+ pre: t("kbRetrieval.layerPre"),
2093
+ post: t("kbRetrieval.layerPost"),
2094
+ none: t("kbRetrieval.layerNone")
258
2095
  };
259
2096
  var stubHandle = () => ({
260
2097
  getParams: () => normalizeRetrievalParams(),
@@ -279,11 +2116,11 @@ function tokenizeQuery(query) {
279
2116
  const seen = /* @__PURE__ */ new Set();
280
2117
  const out = [];
281
2118
  for (const raw of query.trim().split(/\s+/)) {
282
- const t = raw.trim();
283
- if (!t || seen.has(t)) continue;
284
- if (t.length < 2 && !/[\u4e00-\u9fff]/.test(t)) continue;
285
- seen.add(t);
286
- out.push(t);
2119
+ const t2 = raw.trim();
2120
+ if (!t2 || seen.has(t2)) continue;
2121
+ if (t2.length < 2 && !/[\u4e00-\u9fff]/.test(t2)) continue;
2122
+ seen.add(t2);
2123
+ out.push(t2);
287
2124
  if (out.length >= HIGHLIGHT_TERM_LIMIT) break;
288
2125
  }
289
2126
  return out;
@@ -309,7 +2146,7 @@ function highlightTerms(text, terms) {
309
2146
  }
310
2147
  if (m.index > last) next.push(document.createTextNode(seg.slice(last, m.index)));
311
2148
  const mark = document.createElement("mark");
312
- mark.dataset.hit = String(ti % 3);
2149
+ mark.dataset.icenHit = String(ti % 3);
313
2150
  mark.textContent = m[0];
314
2151
  next.push(mark);
315
2152
  last = m.index + m[0].length;
@@ -359,115 +2196,117 @@ function createKbRetrieval(el, opts = {}) {
359
2196
  let layer = opts.layer === "post" || opts.layer === "none" ? opts.layer : "pre";
360
2197
  const idnList = (Array.isArray(opts.identities) ? opts.identities : []).map(normalizeIdentity).filter((i) => i.user || i.label);
361
2198
  const adminAcl = opts.admin === true && typeof opts.aclOf === "function" ? opts.aclOf : null;
362
- el.classList.add("kb-retrieval");
363
- el.dataset.kbRetrieval = "";
2199
+ el.classList.add("icen-kb-retrieval");
2200
+ el.dataset.icenKbRetrieval = "";
364
2201
  el.textContent = "";
365
- const bar = h("div", "kb-retrieval-bar");
366
- const queryInput = h("input", "kb-retrieval-query");
2202
+ const bar = h("div", "icen-kb-retrieval-bar");
2203
+ const queryInput = h("input", "icen-kb-retrieval-query");
367
2204
  queryInput.type = "text";
368
- queryInput.placeholder = "\u68C0\u7D22\u95EE\u9898\uFF0CEnter \u8FD0\u884C";
369
- queryInput.setAttribute("aria-label", "\u68C0\u7D22\u95EE\u9898");
370
- const modes = h("div", "kb-modes");
2205
+ queryInput.placeholder = t("kbRetrieval.queryPlaceholder");
2206
+ queryInput.setAttribute("aria-label", t("kbRetrieval.queryLabel"));
2207
+ const modes = h("div", "icen-kb-modes");
371
2208
  modes.role = "radiogroup";
372
- modes.setAttribute("aria-label", "\u68C0\u7D22\u6A21\u5F0F");
2209
+ modes.setAttribute("aria-label", t("kbRetrieval.modeLabel"));
373
2210
  const modeButtons = /* @__PURE__ */ new Map();
374
2211
  for (const [mode, label] of MODES) {
375
- const btn = h("button", "kb-mode-item", label);
2212
+ const btn = h("button", "icen-kb-mode-item", label);
376
2213
  btn.type = "button";
377
- btn.dataset.mode = mode;
2214
+ btn.dataset.icenMode = mode;
378
2215
  btn.role = "radio";
379
2216
  modes.appendChild(btn);
380
2217
  modeButtons.set(mode, btn);
381
2218
  }
382
- const topKDown = h("button", "kb-step-btn", "\u2212");
2219
+ const topKDown = h("button", "icen-kb-step-btn");
2220
+ topKDown.append(createIcon("minus"));
383
2221
  topKDown.type = "button";
384
- topKDown.dataset.step = "-1";
385
- topKDown.setAttribute("aria-label", "\u51CF\u5C11 topK");
386
- const topKValue = h("span", "kb-step-value kb-num");
387
- const topKUp = h("button", "kb-step-btn", "+");
2222
+ topKDown.dataset.icenStep = "-1";
2223
+ topKDown.setAttribute("aria-label", t("kbRetrieval.decreaseTopK"));
2224
+ const topKValue = h("span", "icen-kb-step-value icen-kb-num");
2225
+ const topKUp = h("button", "icen-kb-step-btn");
2226
+ topKUp.append(createIcon("plus"));
388
2227
  topKUp.type = "button";
389
- topKUp.dataset.step = "1";
390
- topKUp.setAttribute("aria-label", "\u589E\u52A0 topK");
391
- const step = h("div", "kb-step");
2228
+ topKUp.dataset.icenStep = "1";
2229
+ topKUp.setAttribute("aria-label", t("kbRetrieval.increaseTopK"));
2230
+ const step = h("div", "icen-kb-step");
392
2231
  step.append(topKDown, topKValue, topKUp);
393
- const stepLabel = h("span", "kb-step-label kb-meta", "topK");
2232
+ const stepLabel = h("span", "kb-step-label icen-kb-meta", "topK");
394
2233
  step.setAttribute("aria-label", "topK");
395
- const alphaEndL = h("span", "kb-alpha-end", "\u8BED\u4E49");
396
- alphaEndL.title = "\u8BED\u4E49\uFF1A\u8DE8\u8BED\u8A00/\u65E0\u7CBE\u786E\u8BCD";
397
- const alphaRange = h("input", "kb-range kb-alpha-range");
2234
+ const alphaEndL = h("span", "icen-kb-alpha-end", t("kbRetrieval.modeVector"));
2235
+ alphaEndL.title = t("kbRetrieval.vectorHint");
2236
+ const alphaRange = h("input", "icen-kb-range kb-alpha-range");
398
2237
  alphaRange.type = "range";
399
2238
  alphaRange.min = "0";
400
2239
  alphaRange.max = "1";
401
2240
  alphaRange.step = "0.05";
402
- alphaRange.setAttribute("aria-label", "\u6DF7\u5408\u6743\u91CD\uFF08\u5DE6\u8BED\u4E49\u53F3\u5173\u952E\u8BCD\uFF09");
403
- const alphaEndR = h("span", "kb-alpha-end", "\u5173\u952E\u8BCD");
404
- alphaEndR.title = "\u5173\u952E\u8BCD\uFF1A\u5927\u5E93\u5FEB\u901F\u7CBE\u786E";
405
- const alpha = h("div", "kb-alpha");
2241
+ alphaRange.setAttribute("aria-label", t("kbRetrieval.hybridWeight"));
2242
+ const alphaEndR = h("span", "icen-kb-alpha-end", t("kbRetrieval.modeKeyword"));
2243
+ alphaEndR.title = t("kbRetrieval.keywordHint");
2244
+ const alpha = h("div", "icen-kb-alpha");
406
2245
  alpha.append(alphaEndL, alphaRange, alphaEndR);
407
- const rerankSwitch = h("button", "kb-switch");
2246
+ const rerankSwitch = h("button", "icen-kb-switch");
408
2247
  rerankSwitch.type = "button";
409
2248
  rerankSwitch.role = "switch";
410
- rerankSwitch.setAttribute("aria-label", "\u91CD\u6392");
411
- const rerankText = h("span", "kb-toggle-label", "\u91CD\u6392");
412
- const rerankToggle = h("span", "kb-toggle");
2249
+ rerankSwitch.setAttribute("aria-label", t("kbRetrieval.rerankLabel"));
2250
+ const rerankText = h("span", "icen-kb-toggle-label", t("kbRetrieval.rerankLabel"));
2251
+ const rerankToggle = h("span", "icen-kb-toggle");
413
2252
  rerankToggle.append(rerankSwitch, rerankText);
414
- const thresholdRange = h("input", "kb-range kb-threshold-range");
2253
+ const thresholdRange = h("input", "icen-kb-range kb-threshold-range");
415
2254
  thresholdRange.type = "range";
416
2255
  thresholdRange.min = "0";
417
2256
  thresholdRange.max = "1";
418
2257
  thresholdRange.step = "0.05";
419
- thresholdRange.setAttribute("aria-label", "\u5206\u6570\u9608\u503C");
420
- const thresholdCount = h("span", "kb-threshold-count kb-meta");
421
- const threshold = h("div", "kb-threshold");
2258
+ thresholdRange.setAttribute("aria-label", t("kbRetrieval.thresholdLabel"));
2259
+ const thresholdCount = h("span", "icen-kb-threshold-count icen-kb-meta");
2260
+ const threshold = h("div", "icen-kb-threshold");
422
2261
  threshold.append(thresholdRange, thresholdCount);
423
- const runBtn = h("button", "kb-run", "\u8FD0\u884C");
2262
+ const runBtn = h("button", "icen-kb-run", t("common.run"));
424
2263
  runBtn.type = "button";
425
2264
  const runIcon = svgIcon(ICON_RUN);
426
2265
  if (runIcon) runBtn.prepend(runIcon);
427
2266
  let idnSelect = null;
428
2267
  let idnGroup = null;
429
2268
  if (idnList.length) {
430
- idnSelect = h("select", "kb-retrieval-idn");
431
- idnSelect.setAttribute("aria-label", "\u68C0\u7D22\u8EAB\u4EFD");
432
- for (const idn of idnList) {
433
- const opt = h("option", void 0, idn.label ?? idn.user);
434
- opt.value = idn.user;
435
- idnSelect.appendChild(opt);
436
- }
437
- idnGroup = h("span", "kb-retrieval-idn-group");
438
- idnGroup.append(h("span", "kb-meta", "\u8EAB\u4EFD"), idnSelect);
2269
+ idnSelect = kbSelect({
2270
+ cls: "icen-kb-retrieval-idn",
2271
+ sm: true,
2272
+ options: idnList.map((idn) => ({ value: idn.user, label: idn.label ?? idn.user })),
2273
+ value: idnList[0]?.user,
2274
+ ariaLabel: t("kbRetrieval.identityLabel")
2275
+ });
2276
+ idnGroup = h("span", "icen-kb-retrieval-idn-group");
2277
+ idnGroup.append(h("span", "icen-kb-meta", t("kbRetrieval.identityShort")), idnSelect.el);
439
2278
  }
440
- const layerChip = h("button", "kb-chip kb-layer-chip");
2279
+ const layerChip = h("button", "icen-kb-chip icen-kb-layer-chip");
441
2280
  layerChip.type = "button";
442
- layerChip.setAttribute("aria-label", "\u8FC7\u6EE4\u5C42");
2281
+ layerChip.setAttribute("aria-label", t("kbRetrieval.layerLabel"));
443
2282
  const paintLayer = () => {
444
- layerChip.dataset.layer = layer;
2283
+ layerChip.dataset.icenLayer = layer;
445
2284
  layerChip.textContent = LAYER_LABEL[layer];
446
2285
  layerChip.title = LAYER_TITLE[layer];
447
2286
  };
448
2287
  paintLayer();
449
- const adminBadge = adminAcl ? h("span", "kb-badge kb-badge--admin", "admin") : null;
2288
+ const adminBadge = adminAcl ? h("span", "icen-kb-badge icen-kb-badge--admin", "admin") : null;
450
2289
  bar.append(queryInput, modes, stepLabel, step, alpha, rerankToggle, threshold);
451
2290
  if (idnGroup) bar.appendChild(idnGroup);
452
2291
  bar.append(runBtn, layerChip);
453
2292
  if (adminBadge) bar.appendChild(adminBadge);
454
- const paramsText = h("code", "kb-params-text kb-meta");
455
- const paramsCopy = h("button", "kb-params-copy");
2293
+ const paramsText = h("code", "icen-kb-params-text icen-kb-meta");
2294
+ const paramsCopy = h("button", "icen-kb-params-copy");
456
2295
  paramsCopy.type = "button";
457
- paramsCopy.title = "\u590D\u5236\u53C2\u6570 JSON";
458
- paramsCopy.setAttribute("aria-label", "\u590D\u5236\u53C2\u6570 JSON");
2296
+ paramsCopy.title = t("kbRetrieval.copyParams");
2297
+ paramsCopy.setAttribute("aria-label", t("kbRetrieval.copyParams"));
459
2298
  const copyIcon = svgIcon(ICON_COPY);
460
2299
  if (copyIcon) paramsCopy.appendChild(copyIcon);
461
- const paramsRow = h("div", "kb-params");
2300
+ const paramsRow = h("div", "icen-kb-params");
462
2301
  paramsRow.append(paramsCopy, paramsText);
463
- const layerNotice = h("div", "kb-notice");
2302
+ const layerNotice = h("div", "icen-kb-notice");
464
2303
  layerNotice.hidden = true;
465
2304
  const paintLayerNotice = () => {
466
2305
  if (layer === "none") {
467
- layerNotice.textContent = "fail-open\uFF1A\u5F53\u524D\u67E5\u8BE2\u672A\u643A\u5E26\u8EAB\u4EFD\u8FC7\u6EE4\uFF0C\u5C06\u8FD4\u56DE\u5168\u90E8\u5019\u9009\uFF08\u4EC5\u9650\u8C03\u8BD5\uFF09";
2306
+ layerNotice.textContent = t("kbRetrieval.failOpenNotice");
468
2307
  layerNotice.hidden = false;
469
2308
  } else if (layer === "post") {
470
- layerNotice.textContent = "post-filter\uFF1A\u5206\u6570\u5DF2\u5728\u8FC7\u6EE4\u524D\u4EA7\u751F\uFF08\u7F3A\u9677\u5C42\u6F14\u793A\uFF09";
2309
+ layerNotice.textContent = t("kbRetrieval.postFilterNotice");
471
2310
  layerNotice.hidden = false;
472
2311
  } else {
473
2312
  layerNotice.textContent = "";
@@ -475,7 +2314,7 @@ function createKbRetrieval(el, opts = {}) {
475
2314
  }
476
2315
  };
477
2316
  paintLayerNotice();
478
- const hitsBox = h("div", "kb-hits");
2317
+ const hitsBox = h("div", "icen-kb-hits");
479
2318
  el.append(bar, layerNotice, paramsRow, hitsBox);
480
2319
  function currentQueryText() {
481
2320
  return queryInput.value.trim();
@@ -497,7 +2336,7 @@ function createKbRetrieval(el, opts = {}) {
497
2336
  const alphaOn = params.mode === "hybrid";
498
2337
  alphaRange.disabled = !alphaOn;
499
2338
  alphaRange.value = String(params.alpha ?? 0.5);
500
- alphaEndL.textContent = `\u8BED\u4E49 ${(params.alpha ?? 0.5).toFixed(2)}`;
2339
+ alphaEndL.textContent = t("kbRetrieval.vectorPercent", { p0: (params.alpha ?? 0.5).toFixed(2) });
501
2340
  alpha.classList.toggle("is-off", !alphaOn);
502
2341
  rerankSwitch.setAttribute("aria-checked", params.rerank ? "true" : "false");
503
2342
  thresholdRange.disabled = !params.rerank;
@@ -505,22 +2344,22 @@ function createKbRetrieval(el, opts = {}) {
505
2344
  threshold.classList.toggle("is-off", !params.rerank);
506
2345
  }
507
2346
  function updateSurvival() {
508
- thresholdCount.title = "\u5206\u6BCD\u672A\u8FC7\u6EE4\u524D\u8BA1\u6570\u5C5E\u6CC4\u9732\uFF0C\u4E0D\u663E\u793A";
2347
+ thresholdCount.title = t("kbRetrieval.leakNote");
509
2348
  if (!params.rerank) {
510
- thresholdCount.textContent = "\u9608\u503C N/A";
2349
+ thresholdCount.textContent = t("kbRetrieval.thresholdValue");
511
2350
  return;
512
2351
  }
513
- const t = thresholdValue;
514
- if (!(t > 0)) {
515
- thresholdCount.textContent = `\u9608\u503C \u5173 \xB7 \u5B58\u6D3B ${hits.length}`;
2352
+ const t2 = thresholdValue;
2353
+ if (!(t2 > 0)) {
2354
+ thresholdCount.textContent = t("kbRetrieval.rerankThresholdOff", { p0: hits.length });
516
2355
  return;
517
2356
  }
518
2357
  let alive = 0;
519
2358
  for (const hit of hits) {
520
2359
  const pct = scorePercent(hit.score, hit.scoreKind, thresholdMax);
521
- if (pct != null && pct >= t * 100 - 1e-9) alive++;
2360
+ if (pct != null && pct >= t2 * 100 - 1e-9) alive++;
522
2361
  }
523
- thresholdCount.textContent = `\u9608\u503C ${t.toFixed(2)} \xB7 \u5B58\u6D3B ${alive}`;
2362
+ thresholdCount.textContent = t("kbRetrieval.rerankThresholdOn", { p0: t2.toFixed(2), p1: alive });
524
2363
  }
525
2364
  function updateParamsLine() {
526
2365
  const q = buildQueryObject();
@@ -532,72 +2371,72 @@ function createKbRetrieval(el, opts = {}) {
532
2371
  updateSurvival();
533
2372
  }
534
2373
  function renderScoreSide(hit, side) {
535
- const score = h("span", "kb-score");
2374
+ const score = h("span", "icen-kb-score");
536
2375
  const pct = scorePercent(hit.score, hit.scoreKind, thresholdMax);
537
2376
  if (pct != null) {
538
- const barEl = h("span", "kb-score-bar");
2377
+ const barEl = h("span", "icen-kb-score-bar");
539
2378
  const fill = h("i");
540
2379
  fill.style.width = `${pct.toFixed(1)}%`;
541
2380
  barEl.appendChild(fill);
542
2381
  score.appendChild(barEl);
543
2382
  }
544
- const value = h("span", "kb-score-value", formatScore(hit.score));
2383
+ const value = h("span", "icen-kb-score-value", formatScore(hit.score));
545
2384
  score.appendChild(value);
546
2385
  side.appendChild(score);
547
- const kind = h("span", "kb-chip kb-chip--kind", hit.scoreKind ?? "\u672A\u6807");
2386
+ const kind = h("span", "icen-kb-chip icen-kb-chip--kind", hit.scoreKind ?? t("kbRerank.unmarked"));
548
2387
  side.appendChild(kind);
549
2388
  if (hit.vectorPart != null && hit.keywordPart != null) {
550
- const dual = h("span", "kb-score-dual");
551
- const vec = h("i", "kb-score-dual-vec");
552
- const kw = h("i", "kb-score-dual-kw");
2389
+ const dual = h("span", "icen-kb-score-dual");
2390
+ const vec = h("i", "icen-kb-score-dual-vec");
2391
+ const kw = h("i", "icen-kb-score-dual-kw");
553
2392
  const sum2 = hit.vectorPart + hit.keywordPart;
554
2393
  const vecPct = sum2 > 0 ? hit.vectorPart / sum2 * 100 : 50;
555
2394
  vec.style.width = `${Math.max(0, Math.min(100, vecPct)).toFixed(1)}%`;
556
2395
  kw.style.flex = "1 1 auto";
557
2396
  dual.append(vec, kw);
558
- dual.title = `\u5411\u91CF ${vecPct.toFixed(0)}% / \u5173\u952E\u8BCD ${(100 - vecPct).toFixed(0)}%`;
2397
+ dual.title = t("kbRetrieval.weightValue", { p0: vecPct.toFixed(0), p1: (100 - vecPct).toFixed(0) });
559
2398
  side.appendChild(dual);
560
2399
  }
561
2400
  if (hit.explain) {
562
- const fold = h("div", "kb-hit-explain-fold");
563
- const toggle = h("button", "kb-hit-explain-toggle", "\u62C6\u89E3");
2401
+ const fold = h("div", "icen-kb-hit-explain-fold");
2402
+ const toggle = h("button", "icen-kb-hit-explain-toggle", t("kbRetrieval.breakdown"));
564
2403
  toggle.type = "button";
565
2404
  toggle.setAttribute("aria-expanded", "false");
566
- const body = h("div", "kb-hit-explain kb-meta", hit.explain);
2405
+ const body = h("div", "icen-kb-hit-explain icen-kb-meta", hit.explain);
567
2406
  body.hidden = true;
568
2407
  fold.append(toggle, body);
569
2408
  side.appendChild(fold);
570
2409
  }
571
2410
  }
572
2411
  function renderMetaChips(hit, box) {
573
- if (hit.page != null) box.appendChild(h("span", "kb-chip", `\u7B2C ${hit.page} \u9875`));
574
- if (hit.documentId) box.appendChild(h("span", "kb-chip", hit.documentId));
2412
+ if (hit.page != null) box.appendChild(h("span", "icen-kb-chip", t("common.page", { p0: hit.page })));
2413
+ if (hit.documentId) box.appendChild(h("span", "icen-kb-chip", hit.documentId));
575
2414
  if (hit.meta) {
576
2415
  for (const [k, v] of Object.entries(hit.meta).slice(0, 4)) {
577
- box.appendChild(h("span", "kb-chip", `${k}: ${String(v)}`));
2416
+ box.appendChild(h("span", "icen-kb-chip", `${k}: ${String(v)}`));
578
2417
  }
579
2418
  }
580
2419
  }
581
2420
  function renderHitRow(hit, index) {
582
- const row = h("div", "kb-hit");
583
- const rank = h("div", "kb-hit-rank kb-num", String(index + 1));
584
- const main = h("div", "kb-hit-main");
585
- const title = h("div", "kb-hit-title", hit.title ?? hit.documentId ?? hit.chunkId);
586
- const snippet = h("div", "kb-hit-snippet");
2421
+ const row = h("div", "icen-kb-hit");
2422
+ const rank = h("div", "icen-kb-hit-rank icen-kb-num", String(index + 1));
2423
+ const main = h("div", "icen-kb-hit-main");
2424
+ const title = h("div", "icen-kb-hit-title", hit.title ?? hit.documentId ?? hit.chunkId);
2425
+ const snippet = h("div", "icen-kb-hit-snippet");
587
2426
  for (const node of highlightTerms(hit.snippet ?? "", tokenizeQuery(currentQueryText()))) {
588
2427
  snippet.appendChild(node);
589
2428
  }
590
- const metaBox = h("div", "kb-hit-meta");
2429
+ const metaBox = h("div", "icen-kb-hit-meta");
591
2430
  renderMetaChips(hit, metaBox);
592
2431
  main.append(title, snippet, metaBox);
593
- const side = h("div", "kb-hit-side");
2432
+ const side = h("div", "icen-kb-hit-side");
594
2433
  renderScoreSide(hit, side);
595
- if (adminAcl) side.appendChild(h("span", "kb-chip", kbVisibilityLabel(adminAcl(hit))));
2434
+ if (adminAcl) side.appendChild(h("span", "icen-kb-chip", kbVisibilityLabel(adminAcl(hit))));
596
2435
  row.append(rank, main, side);
597
2436
  return row;
598
2437
  }
599
2438
  function renderEmpty() {
600
- const empty = h("div", "kb-empty", "\u8F93\u5165\u95EE\u9898\u5E76\u8FD0\u884C\uFF0C\u547D\u4E2D\u7ED3\u679C\u5C06\u51FA\u73B0\u5728\u8FD9\u91CC");
2439
+ const empty = h("div", "icen-kb-empty", t("kbRetrieval.empty"));
601
2440
  hitsBox.appendChild(empty);
602
2441
  }
603
2442
  function run() {
@@ -617,17 +2456,17 @@ function createKbRetrieval(el, opts = {}) {
617
2456
  }
618
2457
  });
619
2458
  listen(modes, "click", (ev) => {
620
- const btn = ev.target?.closest?.(".kb-mode-item");
2459
+ const btn = ev.target?.closest?.(".icen-kb-mode-item");
621
2460
  if (!(btn instanceof HTMLButtonElement) || btn.disabled) return;
622
- const mode = btn.dataset.mode;
2461
+ const mode = btn.dataset.icenMode;
623
2462
  if (!mode || mode === params.mode) return;
624
2463
  params = normalizeRetrievalParams({ ...params, mode });
625
2464
  refreshDerived();
626
2465
  });
627
2466
  listen(step, "click", (ev) => {
628
- const btn = ev.target?.closest?.(".kb-step-btn");
2467
+ const btn = ev.target?.closest?.(".icen-kb-step-btn");
629
2468
  if (!(btn instanceof HTMLButtonElement) || btn.disabled) return;
630
- const dir = Number(btn.dataset.step) || 0;
2469
+ const dir = Number(btn.dataset.icenStep) || 0;
631
2470
  if (!dir) return;
632
2471
  const next = Math.max(TOP_K_MIN, Math.min(TOP_K_MAX, params.topK + dir));
633
2472
  if (next === params.topK) return;
@@ -661,15 +2500,15 @@ function createKbRetrieval(el, opts = {}) {
661
2500
  });
662
2501
  if (idnSelect) {
663
2502
  const select = idnSelect;
664
- listen(select, "change", () => {
665
- const identity = idnList.find((i) => i.user === select.value);
2503
+ listen(select.el, "icen:select-change", (ev) => {
2504
+ const identity = idnList.find((i) => i.user === ev.detail.value);
666
2505
  if (identity) emitIcen(el, "icen:kb-visibility-identity", { identity });
667
2506
  });
668
2507
  }
669
2508
  listen(hitsBox, "click", (ev) => {
670
- const btn = ev.target?.closest?.(".kb-hit-explain-toggle");
2509
+ const btn = ev.target?.closest?.(".icen-kb-hit-explain-toggle");
671
2510
  if (!(btn instanceof HTMLButtonElement)) return;
672
- const body = btn.parentElement?.querySelector(".kb-hit-explain");
2511
+ const body = btn.parentElement?.querySelector(".icen-kb-hit-explain");
673
2512
  if (!body) return;
674
2513
  const open = body.hasAttribute("hidden");
675
2514
  body.toggleAttribute("hidden", !open);
@@ -680,12 +2519,12 @@ function createKbRetrieval(el, opts = {}) {
680
2519
  const ok = copyText(paramsText.textContent ?? "");
681
2520
  if (ok) {
682
2521
  paramsCopy.classList.add("is-copied");
683
- paramsCopy.title = "\u5DF2\u590D\u5236";
2522
+ paramsCopy.title = t("common.copied");
684
2523
  if (copyTimer) clearTimeout(copyTimer);
685
2524
  copyTimer = setTimeout(() => {
686
2525
  if (destroyed) return;
687
2526
  paramsCopy.classList.remove("is-copied");
688
- paramsCopy.title = "\u590D\u5236\u53C2\u6570 JSON";
2527
+ paramsCopy.title = t("kbRetrieval.copyParams");
689
2528
  }, 1200);
690
2529
  }
691
2530
  });
@@ -710,7 +2549,7 @@ function createKbRetrieval(el, opts = {}) {
710
2549
  el.classList.toggle("is-busy", busy);
711
2550
  runBtn.disabled = busy;
712
2551
  runBtn.setAttribute("aria-busy", busy ? "true" : "false");
713
- runBtn.textContent = busy ? "\u8FD0\u884C\u4E2D\u2026" : "\u8FD0\u884C";
2552
+ runBtn.textContent = busy ? t("kbRetrieval.running") : t("common.run");
714
2553
  if (!busy) {
715
2554
  const icon = svgIcon(ICON_RUN);
716
2555
  if (icon) runBtn.prepend(icon);
@@ -731,8 +2570,8 @@ function createKbRetrieval(el, opts = {}) {
731
2570
  destroyed = true;
732
2571
  ctrl.abort();
733
2572
  if (copyTimer) clearTimeout(copyTimer);
734
- el.classList.remove("kb-retrieval", "is-busy");
735
- delete el.dataset.kbRetrieval;
2573
+ el.classList.remove("icen-kb-retrieval", "is-busy");
2574
+ delete el.dataset.icenKbRetrieval;
736
2575
  el.textContent = "";
737
2576
  delete el.__icenKbRetrieval;
738
2577
  }