@icen.ai/ui 0.10.0 → 0.11.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 (355) hide show
  1. package/AGENTS.md +79 -309
  2. package/LICENSE +21 -0
  3. package/README.md +43 -54
  4. package/dist/base.css +57 -16
  5. package/dist/behaviors/accordion.mjs +1 -1
  6. package/dist/behaviors/ai-branch.mjs +1 -0
  7. package/dist/behaviors/ai-chat.d.mts +2 -2
  8. package/dist/behaviors/ai-chat.mjs +53 -10
  9. package/dist/behaviors/ai-composer.d.mts +5 -5
  10. package/dist/behaviors/ai-composer.mjs +21 -10
  11. package/dist/behaviors/ai-core.mjs +1 -0
  12. package/dist/behaviors/ai-diff.mjs +1 -0
  13. package/dist/behaviors/ai-feedback.mjs +1 -0
  14. package/dist/behaviors/ai-panel.d.mts +2 -2
  15. package/dist/behaviors/ai-panel.mjs +1 -0
  16. package/dist/behaviors/ai-provider.d.mts +1 -1
  17. package/dist/behaviors/ai-provider.mjs +1 -0
  18. package/dist/behaviors/ai-threads.mjs +1 -0
  19. package/dist/behaviors/ai-tool.d.mts +1 -1
  20. package/dist/behaviors/ai-tool.mjs +57 -24
  21. package/dist/behaviors/ai-tools.mjs +937 -28
  22. package/dist/behaviors/autocomplete.d.mts +1 -1
  23. package/dist/behaviors/autocomplete.mjs +1 -0
  24. package/dist/behaviors/back-top.mjs +1 -0
  25. package/dist/behaviors/carousel.mjs +8 -1
  26. package/dist/behaviors/cascader.mjs +14 -0
  27. package/dist/behaviors/charts.mjs +56 -20
  28. package/dist/behaviors/code-block.mjs +9 -1
  29. package/dist/behaviors/command-palette.mjs +3 -3
  30. package/dist/behaviors/context-menu.d.mts +2 -2
  31. package/dist/behaviors/context-menu.mjs +1 -0
  32. package/dist/behaviors/controls.d.mts +8 -8
  33. package/dist/behaviors/controls.mjs +37 -6
  34. package/dist/behaviors/copy.mjs +1 -0
  35. package/dist/behaviors/datatable.d.mts +3 -3
  36. package/dist/behaviors/datatable.mjs +76 -11
  37. package/dist/behaviors/date-picker.mjs +1 -0
  38. package/dist/behaviors/events.d.mts +10 -10
  39. package/dist/behaviors/events.mjs +11 -1
  40. package/dist/behaviors/form-validate.d.mts +10 -1
  41. package/dist/behaviors/form-validate.mjs +266 -4611
  42. package/dist/behaviors/i18n.d.mts +1 -0
  43. package/dist/behaviors/i18n.mjs +2 -0
  44. package/dist/behaviors/input.mjs +3 -0
  45. package/dist/behaviors/kb-access.d.mts +2 -2
  46. package/dist/behaviors/kb-access.mjs +8 -2
  47. package/dist/behaviors/kb-acl.d.mts +2 -2
  48. package/dist/behaviors/kb-acl.mjs +1 -0
  49. package/dist/behaviors/kb-answer.d.mts +2 -2
  50. package/dist/behaviors/kb-answer.mjs +56 -23
  51. package/dist/behaviors/kb-audit.d.mts +2 -2
  52. package/dist/behaviors/kb-audit.mjs +1 -0
  53. package/dist/behaviors/kb-canvas.d.mts +3 -3
  54. package/dist/behaviors/kb-canvas.mjs +1 -0
  55. package/dist/behaviors/kb-chain.d.mts +2 -2
  56. package/dist/behaviors/kb-chain.mjs +1 -0
  57. package/dist/behaviors/kb-checkpoint.d.mts +2 -2
  58. package/dist/behaviors/kb-checkpoint.mjs +1 -0
  59. package/dist/behaviors/kb-chunks.d.mts +2 -2
  60. package/dist/behaviors/kb-chunks.mjs +1 -0
  61. package/dist/behaviors/kb-citation.d.mts +2 -2
  62. package/dist/behaviors/kb-citation.mjs +20 -6
  63. package/dist/behaviors/kb-clarify.d.mts +2 -2
  64. package/dist/behaviors/kb-clarify.mjs +1 -0
  65. package/dist/behaviors/kb-conflict.d.mts +2 -2
  66. package/dist/behaviors/kb-conflict.mjs +1 -0
  67. package/dist/behaviors/kb-connector.d.mts +2 -2
  68. package/dist/behaviors/kb-connector.mjs +1 -0
  69. package/dist/behaviors/kb-core.d.mts +1 -1
  70. package/dist/behaviors/kb-core.mjs +1 -0
  71. package/dist/behaviors/kb-eval.d.mts +2 -2
  72. package/dist/behaviors/kb-eval.mjs +8 -2
  73. package/dist/behaviors/kb-explain.d.mts +2 -2
  74. package/dist/behaviors/kb-explain.mjs +13 -2
  75. package/dist/behaviors/kb-filter.d.mts +2 -2
  76. package/dist/behaviors/kb-filter.mjs +8 -2
  77. package/dist/behaviors/kb-gap.d.mts +2 -2
  78. package/dist/behaviors/kb-gap.mjs +1 -0
  79. package/dist/behaviors/kb-hittest.d.mts +2 -2
  80. package/dist/behaviors/kb-hittest.mjs +2 -1
  81. package/dist/behaviors/kb-metadata.mjs +6 -0
  82. package/dist/behaviors/kb-passage.d.mts +2 -2
  83. package/dist/behaviors/kb-passage.mjs +1 -0
  84. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  85. package/dist/behaviors/kb-pipeline.mjs +1 -0
  86. package/dist/behaviors/kb-qa.mjs +1 -0
  87. package/dist/behaviors/kb-rerank.d.mts +2 -2
  88. package/dist/behaviors/kb-rerank.mjs +1 -0
  89. package/dist/behaviors/kb-retrieval.d.mts +2 -2
  90. package/dist/behaviors/kb-retrieval.mjs +18 -4
  91. package/dist/behaviors/kb-review.d.mts +2 -2
  92. package/dist/behaviors/kb-review.mjs +8 -2
  93. package/dist/behaviors/kb-sandbox.d.mts +2 -2
  94. package/dist/behaviors/kb-sandbox.mjs +7 -1
  95. package/dist/behaviors/kb-segment.d.mts +2 -2
  96. package/dist/behaviors/kb-segment.mjs +2 -1
  97. package/dist/behaviors/kb-select.mjs +8 -2
  98. package/dist/behaviors/kb-sources.d.mts +2 -2
  99. package/dist/behaviors/kb-sources.mjs +1 -0
  100. package/dist/behaviors/kb-sql.d.mts +2 -2
  101. package/dist/behaviors/kb-sql.mjs +1 -0
  102. package/dist/behaviors/kb-trace.d.mts +2 -2
  103. package/dist/behaviors/kb-trace.mjs +9 -3
  104. package/dist/behaviors/kb-visibility.d.mts +2 -2
  105. package/dist/behaviors/kb-visibility.mjs +1 -0
  106. package/dist/behaviors/kb-who-can.d.mts +2 -2
  107. package/dist/behaviors/kb-who-can.mjs +8 -2
  108. package/dist/behaviors/mentions.d.mts +1 -1
  109. package/dist/behaviors/mentions.mjs +1 -0
  110. package/dist/behaviors/modal.d.mts +1 -1
  111. package/dist/behaviors/modal.mjs +1 -0
  112. package/dist/behaviors/notification.d.mts +2 -2
  113. package/dist/behaviors/notification.mjs +14 -3
  114. package/dist/behaviors/panel.mjs +1 -0
  115. package/dist/behaviors/scroll-area.d.mts +17 -0
  116. package/dist/behaviors/scroll-area.mjs +59 -0
  117. package/dist/behaviors/select.mjs +8 -2
  118. package/dist/behaviors/slider.mjs +3 -3
  119. package/dist/behaviors/split-pane.mjs +2 -0
  120. package/dist/behaviors/suggestions.mjs +1 -0
  121. package/dist/behaviors/tabs.mjs +10 -0
  122. package/dist/behaviors/tag-input.mjs +1 -0
  123. package/dist/behaviors/theme-switcher.d.mts +2 -2
  124. package/dist/behaviors/theme-switcher.mjs +17 -2
  125. package/dist/behaviors/theme.mjs +16 -2
  126. package/dist/behaviors/toast.d.mts +2 -2
  127. package/dist/behaviors/toast.mjs +1 -0
  128. package/dist/behaviors/tree-select.mjs +14 -0
  129. package/dist/behaviors/tree.mjs +4 -4
  130. package/dist/behaviors/upload.mjs +1 -0
  131. package/dist/behaviors/url-safety.d.mts +8 -0
  132. package/dist/behaviors/url-safety.mjs +11 -0
  133. package/dist/components/accordion.d.mts +2 -0
  134. package/dist/components/ai-branch.d.mts +2 -0
  135. package/dist/components/ai-chat.css +40 -33
  136. package/dist/components/ai-chat.d.mts +2 -0
  137. package/dist/components/ai-composer.d.mts +2 -0
  138. package/dist/components/ai-context.d.mts +2 -0
  139. package/dist/components/ai-context.mjs +1 -0
  140. package/dist/components/ai-diff.css +6 -6
  141. package/dist/components/ai-diff.d.mts +2 -0
  142. package/dist/components/ai-feedback.d.mts +2 -0
  143. package/dist/components/ai-files.d.mts +2 -0
  144. package/dist/components/ai-message.d.mts +2 -0
  145. package/dist/components/ai-panel.css +12 -10
  146. package/dist/components/ai-reasoning.d.mts +2 -0
  147. package/dist/components/ai-subagent.d.mts +2 -0
  148. package/dist/components/ai-subagent.mjs +1 -0
  149. package/dist/components/ai-threads.d.mts +2 -0
  150. package/dist/components/ai-todo.d.mts +2 -0
  151. package/dist/components/ai-todo.mjs +1 -0
  152. package/dist/components/ai-tool-call.d.mts +2 -0
  153. package/dist/components/ai-tool-call.mjs +1 -0
  154. package/dist/components/ai-tool.css +16 -16
  155. package/dist/components/ai-usage.d.mts +2 -0
  156. package/dist/components/alert.d.mts +2 -0
  157. package/dist/components/autocomplete.css +12 -12
  158. package/dist/components/autocomplete.d.mts +2 -0
  159. package/dist/components/avatar.d.mts +2 -0
  160. package/dist/components/back-top.css +47 -16
  161. package/dist/components/back-top.d.mts +2 -0
  162. package/dist/components/badge.css +1 -1
  163. package/dist/components/badge.d.mts +2 -0
  164. package/dist/components/breadcrumb.css +26 -8
  165. package/dist/components/breadcrumb.d.mts +2 -0
  166. package/dist/components/btn.css +67 -62
  167. package/dist/components/btn.d.mts +2 -0
  168. package/dist/components/card.css +22 -22
  169. package/dist/components/card.d.mts +2 -0
  170. package/dist/components/carousel.d.mts +2 -0
  171. package/dist/components/cascader.css +56 -35
  172. package/dist/components/cascader.d.mts +2 -0
  173. package/dist/components/chart-area.css +46 -0
  174. package/dist/components/chart-area.d.mts +2 -0
  175. package/dist/components/chart-bar.css +66 -19
  176. package/dist/components/chart-bar.d.mts +2 -0
  177. package/dist/components/chart-calendar.d.mts +2 -0
  178. package/dist/components/chart-gauge.css +23 -3
  179. package/dist/components/chart-gauge.d.mts +2 -0
  180. package/dist/components/chart-graph.css +15 -3
  181. package/dist/components/chart-graph.d.mts +2 -0
  182. package/dist/components/chart-heatmap.css +117 -95
  183. package/dist/components/chart-heatmap.d.mts +2 -0
  184. package/dist/components/chart-line.css +54 -0
  185. package/dist/components/chart-line.d.mts +2 -0
  186. package/dist/components/chart-map.d.mts +2 -0
  187. package/dist/components/chart-pie.css +29 -0
  188. package/dist/components/chart-pie.d.mts +2 -0
  189. package/dist/components/chart-radar.css +50 -1
  190. package/dist/components/chart-radar.d.mts +2 -0
  191. package/dist/components/chart-scatter.css +39 -2
  192. package/dist/components/chart-scatter.d.mts +2 -0
  193. package/dist/components/chart-sparkline.css +20 -0
  194. package/dist/components/chart-sparkline.d.mts +2 -0
  195. package/dist/components/chart-stack.css +16 -5
  196. package/dist/components/chart-stack.d.mts +2 -0
  197. package/dist/components/charts.css +80 -35
  198. package/dist/components/charts.d.mts +2 -0
  199. package/dist/components/code-block.css +10 -8
  200. package/dist/components/code-block.d.mts +2 -0
  201. package/dist/components/command-palette.css +45 -38
  202. package/dist/components/command-palette.d.mts +2 -0
  203. package/dist/components/content.css +62 -57
  204. package/dist/components/context-menu.d.mts +2 -0
  205. package/dist/components/copy.css +10 -10
  206. package/dist/components/copy.d.mts +2 -0
  207. package/dist/components/datatable.css +72 -59
  208. package/dist/components/datatable.d.mts +2 -0
  209. package/dist/components/date-picker.css +26 -26
  210. package/dist/components/date-picker.d.mts +2 -0
  211. package/dist/components/desc.d.mts +2 -0
  212. package/dist/components/dropdown.d.mts +2 -0
  213. package/dist/components/empty.css +16 -16
  214. package/dist/components/empty.d.mts +2 -0
  215. package/dist/components/feedback.css +31 -29
  216. package/dist/components/form-validate.css +20 -6
  217. package/dist/components/form-validate.d.mts +2 -0
  218. package/dist/components/form.css +17 -14
  219. package/dist/components/form.d.mts +2 -0
  220. package/dist/components/icon.css +21 -10
  221. package/dist/components/icon.d.mts +2 -0
  222. package/dist/components/input.css +22 -22
  223. package/dist/components/input.d.mts +2 -0
  224. package/dist/components/kb-access.d.mts +2 -0
  225. package/dist/components/kb-acl.d.mts +2 -0
  226. package/dist/components/kb-agent.css +134 -55
  227. package/dist/components/kb-answer.d.mts +2 -0
  228. package/dist/components/kb-audit.d.mts +2 -0
  229. package/dist/components/kb-canvas.d.mts +2 -0
  230. package/dist/components/kb-chain.d.mts +2 -0
  231. package/dist/components/kb-checkpoint.d.mts +2 -0
  232. package/dist/components/kb-chunks.d.mts +2 -0
  233. package/dist/components/kb-citation.d.mts +2 -0
  234. package/dist/components/kb-clarify.d.mts +2 -0
  235. package/dist/components/kb-conflict.d.mts +2 -0
  236. package/dist/components/kb-connector.d.mts +2 -0
  237. package/dist/components/kb-data.css +192 -80
  238. package/dist/components/kb-eval.d.mts +2 -0
  239. package/dist/components/kb-explain.d.mts +2 -0
  240. package/dist/components/kb-filter.d.mts +2 -0
  241. package/dist/components/kb-gap.d.mts +2 -0
  242. package/dist/components/kb-ground.css +165 -73
  243. package/dist/components/kb-hittest.d.mts +2 -0
  244. package/dist/components/kb-ingest.css +308 -113
  245. package/dist/components/kb-metadata.d.mts +2 -0
  246. package/dist/components/kb-ops.css +189 -75
  247. package/dist/components/kb-passage.d.mts +2 -0
  248. package/dist/components/kb-perm.css +158 -87
  249. package/dist/components/kb-pipeline.d.mts +2 -0
  250. package/dist/components/kb-qa.d.mts +2 -0
  251. package/dist/components/kb-rerank.d.mts +2 -0
  252. package/dist/components/kb-retrieval.d.mts +2 -0
  253. package/dist/components/kb-review.d.mts +2 -0
  254. package/dist/components/kb-sandbox.d.mts +2 -0
  255. package/dist/components/kb-search.css +353 -116
  256. package/dist/components/kb-segment.d.mts +2 -0
  257. package/dist/components/kb-sources.d.mts +2 -0
  258. package/dist/components/kb-sql.d.mts +2 -0
  259. package/dist/components/kb-trace.d.mts +2 -0
  260. package/dist/components/kb-visibility.d.mts +2 -0
  261. package/dist/components/kb-who-can.d.mts +2 -0
  262. package/dist/components/kb.css +60 -36
  263. package/dist/components/kb.d.mts +2 -0
  264. package/dist/components/kbd.d.mts +2 -0
  265. package/dist/components/layout.css +10 -10
  266. package/dist/components/layout.d.mts +2 -0
  267. package/dist/components/list.d.mts +2 -0
  268. package/dist/components/material-chinese.css +10 -0
  269. package/dist/components/material-soviet.css +10 -0
  270. package/dist/components/material.css +61 -18
  271. package/dist/components/media-card.d.mts +2 -0
  272. package/dist/components/media.css +22 -27
  273. package/dist/components/mentions.css +18 -17
  274. package/dist/components/mentions.d.mts +2 -0
  275. package/dist/components/menu.css +32 -28
  276. package/dist/components/modal.css +30 -27
  277. package/dist/components/modal.d.mts +2 -0
  278. package/dist/components/nav.css +48 -44
  279. package/dist/components/nav.d.mts +2 -0
  280. package/dist/components/notification.css +31 -25
  281. package/dist/components/notification.d.mts +2 -0
  282. package/dist/components/pagination.css +15 -13
  283. package/dist/components/pagination.d.mts +2 -0
  284. package/dist/components/panel.css +19 -20
  285. package/dist/components/panel.d.mts +2 -0
  286. package/dist/components/pill.css +8 -7
  287. package/dist/components/pill.d.mts +2 -0
  288. package/dist/components/popover.css +32 -23
  289. package/dist/components/popover.d.mts +2 -0
  290. package/dist/components/progress.d.mts +2 -0
  291. package/dist/components/rating.d.mts +2 -0
  292. package/dist/components/result.d.mts +2 -0
  293. package/dist/components/scroll-area.css +84 -112
  294. package/dist/components/scroll-area.d.mts +2 -0
  295. package/dist/components/scroll-area.mjs +1 -0
  296. package/dist/components/segmented.css +47 -29
  297. package/dist/components/segmented.d.mts +2 -0
  298. package/dist/components/select.css +80 -41
  299. package/dist/components/select.d.mts +2 -0
  300. package/dist/components/sidebar.css +42 -38
  301. package/dist/components/sidebar.d.mts +2 -0
  302. package/dist/components/skeleton.d.mts +2 -0
  303. package/dist/components/slider.css +26 -22
  304. package/dist/components/slider.d.mts +2 -0
  305. package/dist/components/spinner.d.mts +2 -0
  306. package/dist/components/split-pane.css +16 -7
  307. package/dist/components/split-pane.d.mts +2 -0
  308. package/dist/components/stat.css +17 -16
  309. package/dist/components/stat.d.mts +2 -0
  310. package/dist/components/steps.css +26 -26
  311. package/dist/components/steps.d.mts +2 -0
  312. package/dist/components/switch.css +78 -39
  313. package/dist/components/switch.d.mts +2 -0
  314. package/dist/components/table.css +54 -32
  315. package/dist/components/table.d.mts +2 -0
  316. package/dist/components/tabs.css +53 -32
  317. package/dist/components/tabs.d.mts +2 -0
  318. package/dist/components/tag-input.css +12 -8
  319. package/dist/components/tag-input.d.mts +2 -0
  320. package/dist/components/tag.css +20 -12
  321. package/dist/components/tag.d.mts +2 -0
  322. package/dist/components/theme-switcher.css +7 -7
  323. package/dist/components/theme-switcher.d.mts +2 -0
  324. package/dist/components/timeline.d.mts +2 -0
  325. package/dist/components/toast.css +34 -30
  326. package/dist/components/toast.d.mts +2 -0
  327. package/dist/components/toolbar.css +19 -18
  328. package/dist/components/toolbar.d.mts +2 -0
  329. package/dist/components/tooltip.css +9 -8
  330. package/dist/components/tooltip.d.mts +2 -0
  331. package/dist/components/tree-select.css +63 -40
  332. package/dist/components/tree-select.d.mts +2 -0
  333. package/dist/components/tree.d.mts +2 -0
  334. package/dist/components/upload.css +9 -11
  335. package/dist/components/upload.d.mts +2 -0
  336. package/dist/index.d.mts +85 -84
  337. package/dist/index.mjs +14764 -14311
  338. package/dist/react.d.mts +18 -18
  339. package/dist/react.mjs +135 -36
  340. package/dist/registry.json +795 -64
  341. package/dist/tokens/colors.css +6 -0
  342. package/dist/tokens/design.css +130 -30
  343. package/dist/tokens/dtcg.json +6189 -1461
  344. package/dist/tokens/figma.variables.json +4107 -345
  345. package/dist/tokens/pixel.css +3 -0
  346. package/dist/tokens/scrollbars.css +40 -0
  347. package/dist/tokens/tokens-studio.json +5191 -271
  348. package/dist/tokens.css +304 -81
  349. package/dist/ui.css +4050 -2148
  350. package/dist/vue.d.mts +17 -17
  351. package/dist/vue.mjs +129 -34
  352. package/docs/spec/design-philosophy.md +5 -5
  353. package/docs/spec/design-primitives.md +10 -10
  354. package/docs/spec/scrollbars.md +46 -0
  355. package/package.json +16 -3
@@ -1,3 +1,12 @@
1
+ // src/behaviors/url-safety.ts
2
+ function safeUrl(uri) {
3
+ const s = uri.replace(/[\t\n\r\0-\x1f\x7f]/g, "").trim().toLowerCase();
4
+ if (!s) return void 0;
5
+ if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
6
+ if (/^data:\s*text\/html/.test(s)) return void 0;
7
+ return uri;
8
+ }
9
+
1
10
  // src/behaviors/events.ts
2
11
  function emitIcen(source, type, detail) {
3
12
  return source.dispatchEvent(
@@ -21,6 +30,7 @@ var ICEN_LOCALE_ZH_CN = {
21
30
  "aiChat.roleTool": "\u5DE5",
22
31
  "aiChat.roleUser": "\u6211",
23
32
  "aiChat.thinking": "\u601D\u8003 {p0}",
33
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
34
  /* ── aiComposer ── */
25
35
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
36
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1136,9 +1146,10 @@ function renderKbExplain(el, fact) {
1136
1146
  const row = h("div", "icen-kb-explain-metric");
1137
1147
  row.appendChild(h("span", "icen-kb-explain-metric-name", m.name));
1138
1148
  if (m.ref) {
1139
- if (!/^\s*(javascript|data|vbscript)\s*:/i.test(m.ref)) {
1149
+ const href = safeUrl(m.ref);
1150
+ if (href) {
1140
1151
  const a = h("a", "icen-kb-explain-metric-ref", t("kbExplain.viewDefinition"));
1141
- a.href = m.ref;
1152
+ a.href = href;
1142
1153
  a.rel = "noopener";
1143
1154
  row.appendChild(a);
1144
1155
  }
@@ -1,5 +1,5 @@
1
- import { KbFilterNode } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbFilterNode } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** createKbFilter 配置项 */
5
5
  interface KbFilterOpts {
@@ -122,6 +122,7 @@ var ICEN_LOCALE_ZH_CN = {
122
122
  "aiChat.roleTool": "\u5DE5",
123
123
  "aiChat.roleUser": "\u6211",
124
124
  "aiChat.thinking": "\u601D\u8003 {p0}",
125
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
125
126
  /* ── aiComposer ── */
126
127
  "aiComposer.attachAgent": "\u4EE3\u7406",
127
128
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1434,8 +1435,13 @@ function setup(container) {
1434
1435
  el.__icenSelectInit = true;
1435
1436
  const trigger = triggerEl;
1436
1437
  const panel = panelEl;
1437
- const arrow = trigger.querySelector(".icen-select-chevron");
1438
- arrow?.remove();
1438
+ if (!trigger.querySelector(".icen-select-chevron")) {
1439
+ const chevron = createIcon("chevron-down", { size: 12, className: "icen-select-chevron" });
1440
+ if (chevron) {
1441
+ chevron.setAttribute("aria-hidden", "true");
1442
+ trigger.append(chevron);
1443
+ }
1444
+ }
1439
1445
  const isMultiple = container.hasAttribute("data-icen-select-multiple");
1440
1446
  const isSearchable = container.hasAttribute("data-icen-select-search");
1441
1447
  if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
@@ -1,5 +1,5 @@
1
- import { KbGapQuery } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbGapQuery } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** 趋势单点(label 如 '10-01',value 为当日未命中次数) */
5
5
  interface KbGapTrendPoint {
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbHitTestCase, KbHitStats } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbHitTestCase, KbHitStats } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** createKbHitTest 配置项 */
5
5
  interface KbHitTestOpts {
@@ -122,6 +122,7 @@ var ICEN_LOCALE_ZH_CN = {
122
122
  "aiChat.roleTool": "\u5DE5",
123
123
  "aiChat.roleUser": "\u6211",
124
124
  "aiChat.thinking": "\u601D\u8003 {p0}",
125
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
125
126
  /* ── aiComposer ── */
126
127
  "aiComposer.attachAgent": "\u4EE3\u7406",
127
128
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1204,7 +1205,7 @@ function createKbHitTest(el, opts = {}) {
1204
1205
  return stub;
1205
1206
  }
1206
1207
  const marked = el;
1207
- if (marked.__icenKbHitTest) return marked.__icenKbHitTest;
1208
+ marked.__icenKbHitTest?.destroy();
1208
1209
  const ctrl = new AbortController();
1209
1210
  const listen = (target, type, fn) => {
1210
1211
  target.addEventListener(type, fn, { signal: ctrl.signal });
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1209,6 +1210,11 @@ function initKbMetadata(root) {
1209
1210
  keyInput.setAttribute("aria-invalid", "true");
1210
1211
  return;
1211
1212
  }
1213
+ if (root2.querySelector(`.icen-kb-metadata-row[data-icen-key="${CSS.escape(key)}"]`)) {
1214
+ keyInput.setAttribute("aria-invalid", "true");
1215
+ keyInput.select();
1216
+ return;
1217
+ }
1212
1218
  keyInput.removeAttribute("aria-invalid");
1213
1219
  const active = root2.querySelector(".kb-metadata-type-item.is-active");
1214
1220
  const type = TYPES.includes(active?.dataset.icenValue ?? "") ? active?.dataset.icenValue : "string";
@@ -1,5 +1,5 @@
1
- import { KbLocation, KbCitation } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbLocation, KbCitation } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** getDocument 的返回契约:原文 + 定位 + 上下文(受限来源可只给 content 空串并依赖 citedText 回落) */
5
5
  interface KbPassageDoc {
@@ -122,6 +122,7 @@ var ICEN_LOCALE_ZH_CN = {
122
122
  "aiChat.roleTool": "\u5DE5",
123
123
  "aiChat.roleUser": "\u6211",
124
124
  "aiChat.thinking": "\u601D\u8003 {p0}",
125
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
125
126
  /* ── aiComposer ── */
126
127
  "aiComposer.attachAgent": "\u4EE3\u7406",
127
128
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbPipelineRun } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbPipelineRun } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /**
5
5
  * 渲染解析管线时间线(快照:整树重建后返回挂载容器 el)。
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbRetrievalHit } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbRetrievalHit } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** renderKbRerankCompare 输入 */
5
5
  interface KbRerankCompareOpts {
@@ -122,6 +122,7 @@ var ICEN_LOCALE_ZH_CN = {
122
122
  "aiChat.roleTool": "\u5DE5",
123
123
  "aiChat.roleUser": "\u6211",
124
124
  "aiChat.thinking": "\u601D\u8003 {p0}",
125
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
125
126
  /* ── aiComposer ── */
126
127
  "aiComposer.attachAgent": "\u4EE3\u7406",
127
128
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbRetrievalParams, KbRetrievalHit, KbRetrievalQuery, KbIdentity, KbVisibility } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbRetrievalParams, KbRetrievalHit, KbRetrievalQuery, KbIdentity, KbVisibility } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** createKbRetrieval 配置项 */
5
5
  interface KbRetrievalOpts {
@@ -122,6 +122,7 @@ var ICEN_LOCALE_ZH_CN = {
122
122
  "aiChat.roleTool": "\u5DE5",
123
123
  "aiChat.roleUser": "\u6211",
124
124
  "aiChat.thinking": "\u601D\u8003 {p0}",
125
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
125
126
  /* ── aiComposer ── */
126
127
  "aiComposer.attachAgent": "\u4EE3\u7406",
127
128
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1443,8 +1444,13 @@ function setup(container) {
1443
1444
  el.__icenSelectInit = true;
1444
1445
  const trigger = triggerEl;
1445
1446
  const panel = panelEl;
1446
- const arrow = trigger.querySelector(".icen-select-chevron");
1447
- arrow?.remove();
1447
+ if (!trigger.querySelector(".icen-select-chevron")) {
1448
+ const chevron = createIcon("chevron-down", { size: 12, className: "icen-select-chevron" });
1449
+ if (chevron) {
1450
+ chevron.setAttribute("aria-hidden", "true");
1451
+ trigger.append(chevron);
1452
+ }
1453
+ }
1448
1454
  const isMultiple = container.hasAttribute("data-icen-select-multiple");
1449
1455
  const isSearchable = container.hasAttribute("data-icen-select-search");
1450
1456
  if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
@@ -2189,6 +2195,14 @@ function createKbRetrieval(el, opts = {}) {
2189
2195
  let params = normalizeRetrievalParams(opts.params);
2190
2196
  const thresholdMax = typeof opts.thresholdMax === "number" && opts.thresholdMax > 0 ? opts.thresholdMax : 1;
2191
2197
  let hits = [];
2198
+ const scoreListMax = () => {
2199
+ let m = thresholdMax;
2200
+ for (const hit of hits) {
2201
+ const v = Math.abs(hit.score ?? 0);
2202
+ if (Number.isFinite(v) && v > m) m = v;
2203
+ }
2204
+ return m > 0 ? m : 1;
2205
+ };
2192
2206
  let busy = false;
2193
2207
  let destroyed = false;
2194
2208
  let thresholdValue = params.threshold ?? 0;
@@ -2356,7 +2370,7 @@ function createKbRetrieval(el, opts = {}) {
2356
2370
  }
2357
2371
  let alive = 0;
2358
2372
  for (const hit of hits) {
2359
- const pct = scorePercent(hit.score, hit.scoreKind, thresholdMax);
2373
+ const pct = scorePercent(hit.score, hit.scoreKind, scoreListMax());
2360
2374
  if (pct != null && pct >= t2 * 100 - 1e-9) alive++;
2361
2375
  }
2362
2376
  thresholdCount.textContent = t("kbRetrieval.rerankThresholdOn", { p0: t2.toFixed(2), p1: alive });
@@ -2372,7 +2386,7 @@ function createKbRetrieval(el, opts = {}) {
2372
2386
  }
2373
2387
  function renderScoreSide(hit, side) {
2374
2388
  const score = h("span", "icen-kb-score");
2375
- const pct = scorePercent(hit.score, hit.scoreKind, thresholdMax);
2389
+ const pct = scorePercent(hit.score, hit.scoreKind, scoreListMax());
2376
2390
  if (pct != null) {
2377
2391
  const barEl = h("span", "icen-kb-score-bar");
2378
2392
  const fill = h("i");
@@ -1,5 +1,5 @@
1
- import { KbReviewTask, KbScoreConfig } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbReviewTask, KbScoreConfig } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** onAction 回调的动作信封(与 icen:kb-review-* 事件双通道;select 无对应事件,仅回调) */
5
5
  interface KbReviewActionDetail {
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1353,8 +1354,13 @@ function setup(container) {
1353
1354
  el.__icenSelectInit = true;
1354
1355
  const trigger = triggerEl;
1355
1356
  const panel = panelEl;
1356
- const arrow = trigger.querySelector(".icen-select-chevron");
1357
- arrow?.remove();
1357
+ if (!trigger.querySelector(".icen-select-chevron")) {
1358
+ const chevron = createIcon("chevron-down", { size: 12, className: "icen-select-chevron" });
1359
+ if (chevron) {
1360
+ chevron.setAttribute("aria-hidden", "true");
1361
+ trigger.append(chevron);
1362
+ }
1363
+ }
1358
1364
  const isMultiple = container.hasAttribute("data-icen-select-multiple");
1359
1365
  const isSearchable = container.hasAttribute("data-icen-select-search");
1360
1366
  if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
@@ -1,5 +1,5 @@
1
- import { KbSandboxMessage } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbSandboxMessage } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  interface KbSandboxOptions {
5
5
  /** 通信观测双通道(与 icen:kb-sandbox-message 事件同 payload) */
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1089,6 +1090,9 @@ function isSandboxMessage(data) {
1089
1090
  function createKbSandbox(el, opts = {}) {
1090
1091
  const stub = { load: () => void 0, call: () => Promise.reject(new Error("icen-kb-sandbox: SSR")), destroy: () => void 0 };
1091
1092
  if (typeof document === "undefined" || !el) return stub;
1093
+ const host = el;
1094
+ host.__icenKbSandbox?.destroy();
1095
+ host.__icenKbSandbox = stub;
1092
1096
  const timeoutMs = typeof opts.timeoutMs === "number" && opts.timeoutMs > 0 ? opts.timeoutMs : DEFAULT_TIMEOUT_MS;
1093
1097
  const allowedOrigins = Array.isArray(opts.allowedOrigins) ? opts.allowedOrigins.filter((o) => typeof o === "string") : null;
1094
1098
  el.classList.add("icen-kb-sandbox");
@@ -1240,7 +1244,9 @@ function createKbSandbox(el, opts = {}) {
1240
1244
  delete el.dataset.icenState;
1241
1245
  el.textContent = "";
1242
1246
  };
1243
- return { load, call, destroy };
1247
+ const handle = { load, call, destroy };
1248
+ host.__icenKbSandbox = handle;
1249
+ return handle;
1244
1250
  }
1245
1251
  export {
1246
1252
  createKbSandbox
@@ -1,5 +1,5 @@
1
- import { KbSegmentConfig } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbSegmentConfig } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** createKbSegment 选项 */
5
5
  interface KbSegmentOpts {
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1316,7 +1317,7 @@ function createKbSegment(el, opts) {
1316
1317
  delimInput.value = cfg.delimiter ?? "";
1317
1318
  maxInput.value = String(cfg.maxLength);
1318
1319
  overlapInput.value = String(cfg.overlap);
1319
- modeSeg.querySelectorAll("[data-icen-kb-segment-clean]").forEach((cb) => {
1320
+ form.querySelectorAll("[data-icen-kb-segment-clean]").forEach((cb) => {
1320
1321
  cb.setAttribute("aria-checked", String(cfg.clean.includes(cb.dataset.icenKbSegmentClean)));
1321
1322
  });
1322
1323
  pcNotice.hidden = cfg.mode !== "parent-child";
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1353,8 +1354,13 @@ function setup(container) {
1353
1354
  el.__icenSelectInit = true;
1354
1355
  const trigger = triggerEl;
1355
1356
  const panel = panelEl;
1356
- const arrow = trigger.querySelector(".icen-select-chevron");
1357
- arrow?.remove();
1357
+ if (!trigger.querySelector(".icen-select-chevron")) {
1358
+ const chevron = createIcon("chevron-down", { size: 12, className: "icen-select-chevron" });
1359
+ if (chevron) {
1360
+ chevron.setAttribute("aria-hidden", "true");
1361
+ trigger.append(chevron);
1362
+ }
1363
+ }
1358
1364
  const isMultiple = container.hasAttribute("data-icen-select-multiple");
1359
1365
  const isSearchable = container.hasAttribute("data-icen-select-search");
1360
1366
  if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
@@ -1,5 +1,5 @@
1
- import { KbCitation } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbCitation } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** renderKbSources 的配置项:布局变体 / onlyCited 过滤 / 基准时钟 / 点击回调 */
5
5
  interface KbSourcesOptions {
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbSqlQuery } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbSqlQuery } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /**
5
5
  * 零依赖 SQL 着色:关键词(大小写不敏感)/ 单引号字符串 / 行注释与块注释 / 数字 /
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbSpan } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbSpan } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /**
5
5
  * 渲染 trace span 树(快照:整体替换 el 内容)。返回挂载容器 el。
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1163,12 +1164,12 @@ function depthOfSpan(span, byId, guard = 0) {
1163
1164
  const parent = byId.get(span.parentId);
1164
1165
  return parent ? depthOfSpan(parent, byId, guard + 1) + 1 : 0;
1165
1166
  }
1166
- function buildHitRow(hit, rank) {
1167
+ function buildHitRow(hit, rank, listMax) {
1167
1168
  const row = h("div", "icen-kb-trace-hit");
1168
1169
  row.append(h("span", "icen-kb-trace-hit-rank icen-kb-num", String(rank)));
1169
1170
  row.append(h("span", "icen-kb-trace-hit-title", hit.title || hit.snippet || hit.chunkId));
1170
1171
  const score = h("span", "icen-kb-score");
1171
- const pct = scorePercent(hit.score, hit.scoreKind);
1172
+ const pct = scorePercent(hit.score, hit.scoreKind, listMax);
1172
1173
  if (pct != null) {
1173
1174
  const bar = h("span", "icen-kb-score-bar");
1174
1175
  const fill = h("i");
@@ -1197,7 +1198,12 @@ function buildSpanBody(span) {
1197
1198
  if (hasHits && span.hits) {
1198
1199
  const wrap = h("div", "icen-kb-trace-hits");
1199
1200
  wrap.append(h("div", "kb-trace-hits-label icen-kb-meta", t("kbTrace.hits", { p0: span.hits.length })));
1200
- span.hits.forEach((hit, i) => wrap.append(buildHitRow(hit, i + 1)));
1201
+ let listMax = 1;
1202
+ for (const hit of span.hits) {
1203
+ const v = Math.abs(hit.score ?? 0);
1204
+ if (Number.isFinite(v) && v > listMax) listMax = v;
1205
+ }
1206
+ span.hits.forEach((hit, i) => wrap.append(buildHitRow(hit, i + 1, listMax)));
1201
1207
  body.append(wrap);
1202
1208
  }
1203
1209
  if (span.error) body.append(h("div", "icen-kb-trace-error", span.error));
@@ -1,5 +1,5 @@
1
- import { KbVisibility, KbIdentity } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbVisibility, KbIdentity } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** 对照命中的最小数据单元(标题必有;snippet=原文摘录 / summary=AI 摘要,二者权限语义不同) */
5
5
  interface KbVisibilityHit {
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { KbAclDecision, KbIdentity, KbAclEntry } from './kb-core.js';
2
- import './ai-core.js';
1
+ import { KbAclDecision, KbIdentity, KbAclEntry } from './kb-core.mjs';
2
+ import './ai-core.mjs';
3
3
 
4
4
  /** renderKbWhoCan 配置项 */
5
5
  interface KbWhoCanOpts {
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1434,8 +1435,13 @@ function setup(container) {
1434
1435
  el.__icenSelectInit = true;
1435
1436
  const trigger = triggerEl;
1436
1437
  const panel = panelEl;
1437
- const arrow = trigger.querySelector(".icen-select-chevron");
1438
- arrow?.remove();
1438
+ if (!trigger.querySelector(".icen-select-chevron")) {
1439
+ const chevron = createIcon("chevron-down", { size: 12, className: "icen-select-chevron" });
1440
+ if (chevron) {
1441
+ chevron.setAttribute("aria-hidden", "true");
1442
+ trigger.append(chevron);
1443
+ }
1444
+ }
1439
1445
  const isMultiple = container.hasAttribute("data-icen-select-multiple");
1440
1446
  const isSearchable = container.hasAttribute("data-icen-select-search");
1441
1447
  if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
@@ -1,4 +1,4 @@
1
- import { SuggestionSourceContext } from './suggestions.js';
1
+ import { SuggestionSourceContext } from './suggestions.mjs';
2
2
 
3
3
  /** Mention input with object-level mention entities. createMentions accepts a
4
4
  * host containing a native `<textarea class="icen-input">` (declarative markup
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,4 +1,4 @@
1
- export { FOCUSABLE, focusableWithin } from './focus.js';
1
+ export { FOCUSABLE, focusableWithin } from './focus.mjs';
2
2
 
3
3
  /** 焦点陷阱的可聚焦元素选择器(modal / command-palette 焦点陷阱全库共用)。 */
4
4
  /** openModal 可选项。 */
@@ -157,6 +157,7 @@ var ICEN_LOCALE_ZH_CN = {
157
157
  "aiChat.roleTool": "\u5DE5",
158
158
  "aiChat.roleUser": "\u6211",
159
159
  "aiChat.thinking": "\u601D\u8003 {p0}",
160
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
160
161
  /* ── aiComposer ── */
161
162
  "aiComposer.attachAgent": "\u4EE3\u7406",
162
163
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { FeedbackAction } from './feedback.js';
2
- import { IconName } from './icons.js';
1
+ import { FeedbackAction } from './feedback.mjs';
2
+ import { IconName } from './icons.mjs';
3
3
 
4
4
  type NotificationKind = 'success' | 'warning' | 'error' | 'info';
5
5
  interface NotificationAction {
@@ -302,6 +302,7 @@ var ICEN_LOCALE_ZH_CN = {
302
302
  "aiChat.roleTool": "\u5DE5",
303
303
  "aiChat.roleUser": "\u6211",
304
304
  "aiChat.thinking": "\u601D\u8003 {p0}",
305
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
305
306
  /* ── aiComposer ── */
306
307
  "aiComposer.attachAgent": "\u4EE3\u7406",
307
308
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1164,6 +1165,15 @@ function parseSvg(source) {
1164
1165
  return document.importNode(root, true);
1165
1166
  }
1166
1167
 
1168
+ // src/behaviors/url-safety.ts
1169
+ function safeUrl(uri) {
1170
+ const s = uri.replace(/[\t\n\r\0-\x1f\x7f]/g, "").trim().toLowerCase();
1171
+ if (!s) return void 0;
1172
+ if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
1173
+ if (/^data:\s*text\/html/.test(s)) return void 0;
1174
+ return uri;
1175
+ }
1176
+
1167
1177
  // src/behaviors/notification.ts
1168
1178
  var clocks = /* @__PURE__ */ new WeakMap();
1169
1179
  var KIND_SYMBOL = { success: "circle-check", warning: "triangle-alert", error: "circle-error", info: "circle-info" };
@@ -1378,7 +1388,7 @@ function buildIcon(record) {
1378
1388
  wrap.className = "icen-notification-icon";
1379
1389
  wrap.setAttribute("aria-hidden", "true");
1380
1390
  const { icon, avatar } = record.opts;
1381
- if (avatar) {
1391
+ if (avatar && safeUrl(avatar)) {
1382
1392
  const img = document.createElement("img");
1383
1393
  img.className = "icen-notification-avatar";
1384
1394
  img.src = avatar;
@@ -1481,12 +1491,13 @@ function buildActions(record) {
1481
1491
  }
1482
1492
  function buildLink(record) {
1483
1493
  const { link, linkLabel } = record.opts;
1484
- if (!link) return null;
1494
+ const href = link ? safeUrl(link) : void 0;
1495
+ if (!href) return null;
1485
1496
  const wrap = document.createElement("div");
1486
1497
  wrap.className = "icen-notification-link-wrap";
1487
1498
  const a = document.createElement("a");
1488
1499
  a.className = "icen-notification-link";
1489
- a.href = link;
1500
+ a.href = href;
1490
1501
  a.textContent = linkLabel ?? t("notification.viewDetails");
1491
1502
  a.addEventListener("click", (ev) => ev.stopPropagation());
1492
1503
  wrap.appendChild(a);
@@ -116,6 +116,7 @@ var ICEN_LOCALE_ZH_CN = {
116
116
  "aiChat.roleTool": "\u5DE5",
117
117
  "aiChat.roleUser": "\u6211",
118
118
  "aiChat.thinking": "\u601D\u8003 {p0}",
119
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
119
120
  /* ── aiComposer ── */
120
121
  "aiComposer.attachAgent": "\u4EE3\u7406",
121
122
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",