@icen.ai/ui 0.8.1 → 0.9.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 (141) hide show
  1. package/AGENTS.md +49 -6
  2. package/README.md +12 -9
  3. package/dist/behaviors/ai-branch.d.mts +19 -0
  4. package/dist/behaviors/ai-branch.mjs +217 -0
  5. package/dist/behaviors/ai-chat.d.mts +8 -6
  6. package/dist/behaviors/ai-chat.mjs +68 -8
  7. package/dist/behaviors/ai-composer.mjs +108 -20
  8. package/dist/behaviors/ai-feedback.d.mts +26 -0
  9. package/dist/behaviors/ai-feedback.mjs +303 -0
  10. package/dist/behaviors/ai-panel.d.mts +15 -1
  11. package/dist/behaviors/ai-panel.mjs +26 -0
  12. package/dist/behaviors/ai-threads.d.mts +38 -0
  13. package/dist/behaviors/ai-threads.mjs +319 -0
  14. package/dist/behaviors/ai-tool.mjs +5 -0
  15. package/dist/behaviors/ai-tools.mjs +5 -0
  16. package/dist/behaviors/charts.d.mts +103 -1
  17. package/dist/behaviors/charts.mjs +795 -0
  18. package/dist/behaviors/events.d.mts +193 -0
  19. package/dist/behaviors/kb-access.d.mts +34 -0
  20. package/dist/behaviors/kb-access.mjs +569 -0
  21. package/dist/behaviors/kb-acl.d.mts +50 -0
  22. package/dist/behaviors/kb-acl.mjs +405 -0
  23. package/dist/behaviors/kb-answer.d.mts +38 -0
  24. package/dist/behaviors/kb-answer.mjs +2055 -0
  25. package/dist/behaviors/kb-audit.d.mts +23 -0
  26. package/dist/behaviors/kb-audit.mjs +375 -0
  27. package/dist/behaviors/kb-canvas.d.mts +44 -0
  28. package/dist/behaviors/kb-canvas.mjs +589 -0
  29. package/dist/behaviors/kb-chain.d.mts +15 -0
  30. package/dist/behaviors/kb-chain.mjs +270 -0
  31. package/dist/behaviors/kb-checkpoint.d.mts +16 -0
  32. package/dist/behaviors/kb-checkpoint.mjs +342 -0
  33. package/dist/behaviors/kb-chunks.d.mts +31 -0
  34. package/dist/behaviors/kb-chunks.mjs +475 -0
  35. package/dist/behaviors/kb-citation.d.mts +38 -0
  36. package/dist/behaviors/kb-citation.mjs +677 -0
  37. package/dist/behaviors/kb-clarify.d.mts +20 -0
  38. package/dist/behaviors/kb-clarify.mjs +248 -0
  39. package/dist/behaviors/kb-conflict.d.mts +22 -0
  40. package/dist/behaviors/kb-conflict.mjs +284 -0
  41. package/dist/behaviors/kb-connector.d.mts +17 -0
  42. package/dist/behaviors/kb-connector.mjs +375 -0
  43. package/dist/behaviors/kb-core.d.mts +529 -0
  44. package/dist/behaviors/kb-core.mjs +890 -0
  45. package/dist/behaviors/kb-eval.d.mts +22 -0
  46. package/dist/behaviors/kb-eval.mjs +408 -0
  47. package/dist/behaviors/kb-explain.d.mts +11 -0
  48. package/dist/behaviors/kb-explain.mjs +243 -0
  49. package/dist/behaviors/kb-filter.d.mts +31 -0
  50. package/dist/behaviors/kb-filter.mjs +587 -0
  51. package/dist/behaviors/kb-gap.d.mts +27 -0
  52. package/dist/behaviors/kb-gap.mjs +273 -0
  53. package/dist/behaviors/kb-hittest.d.mts +34 -0
  54. package/dist/behaviors/kb-hittest.mjs +409 -0
  55. package/dist/behaviors/kb-metadata.d.mts +29 -0
  56. package/dist/behaviors/kb-metadata.mjs +326 -0
  57. package/dist/behaviors/kb-passage.d.mts +41 -0
  58. package/dist/behaviors/kb-passage.mjs +529 -0
  59. package/dist/behaviors/kb-pipeline.d.mts +18 -0
  60. package/dist/behaviors/kb-pipeline.mjs +381 -0
  61. package/dist/behaviors/kb-qa.d.mts +26 -0
  62. package/dist/behaviors/kb-qa.mjs +332 -0
  63. package/dist/behaviors/kb-rerank.d.mts +20 -0
  64. package/dist/behaviors/kb-rerank.mjs +315 -0
  65. package/dist/behaviors/kb-retrieval.d.mts +49 -0
  66. package/dist/behaviors/kb-retrieval.mjs +746 -0
  67. package/dist/behaviors/kb-review.d.mts +44 -0
  68. package/dist/behaviors/kb-review.mjs +451 -0
  69. package/dist/behaviors/kb-sandbox.d.mts +33 -0
  70. package/dist/behaviors/kb-sandbox.mjs +325 -0
  71. package/dist/behaviors/kb-segment.d.mts +32 -0
  72. package/dist/behaviors/kb-segment.mjs +499 -0
  73. package/dist/behaviors/kb-sources.d.mts +27 -0
  74. package/dist/behaviors/kb-sources.mjs +373 -0
  75. package/dist/behaviors/kb-sql.d.mts +43 -0
  76. package/dist/behaviors/kb-sql.mjs +948 -0
  77. package/dist/behaviors/kb-trace.d.mts +16 -0
  78. package/dist/behaviors/kb-trace.mjs +414 -0
  79. package/dist/behaviors/kb-visibility.d.mts +44 -0
  80. package/dist/behaviors/kb-visibility.mjs +403 -0
  81. package/dist/behaviors/kb-who-can.d.mts +32 -0
  82. package/dist/behaviors/kb-who-can.mjs +379 -0
  83. package/dist/components/ai-branch.mjs +3 -0
  84. package/dist/components/ai-chat.css +295 -0
  85. package/dist/components/ai-feedback.mjs +3 -0
  86. package/dist/components/ai-panel.css +217 -0
  87. package/dist/components/ai-threads.mjs +3 -0
  88. package/dist/components/chart-graph.css +57 -0
  89. package/dist/components/chart-graph.mjs +4 -0
  90. package/dist/components/chart-map.mjs +3 -0
  91. package/dist/components/chart-scatter.mjs +1 -1
  92. package/dist/components/charts.css +32 -0
  93. package/dist/components/charts.mjs +1 -0
  94. package/dist/components/kb-access.mjs +4 -0
  95. package/dist/components/kb-acl.mjs +4 -0
  96. package/dist/components/kb-agent.css +481 -0
  97. package/dist/components/kb-answer.mjs +4 -0
  98. package/dist/components/kb-audit.mjs +4 -0
  99. package/dist/components/kb-canvas.mjs +4 -0
  100. package/dist/components/kb-chain.mjs +4 -0
  101. package/dist/components/kb-checkpoint.mjs +4 -0
  102. package/dist/components/kb-chunks.mjs +4 -0
  103. package/dist/components/kb-citation.mjs +4 -0
  104. package/dist/components/kb-clarify.mjs +4 -0
  105. package/dist/components/kb-conflict.mjs +4 -0
  106. package/dist/components/kb-connector.mjs +4 -0
  107. package/dist/components/kb-data.css +649 -0
  108. package/dist/components/kb-eval.mjs +4 -0
  109. package/dist/components/kb-explain.mjs +4 -0
  110. package/dist/components/kb-filter.mjs +4 -0
  111. package/dist/components/kb-gap.mjs +4 -0
  112. package/dist/components/kb-ground.css +566 -0
  113. package/dist/components/kb-hittest.mjs +4 -0
  114. package/dist/components/kb-ingest.css +898 -0
  115. package/dist/components/kb-metadata.mjs +4 -0
  116. package/dist/components/kb-ops.css +548 -0
  117. package/dist/components/kb-passage.mjs +4 -0
  118. package/dist/components/kb-perm.css +444 -0
  119. package/dist/components/kb-pipeline.mjs +4 -0
  120. package/dist/components/kb-qa.mjs +4 -0
  121. package/dist/components/kb-rerank.mjs +4 -0
  122. package/dist/components/kb-retrieval.mjs +4 -0
  123. package/dist/components/kb-review.mjs +4 -0
  124. package/dist/components/kb-sandbox.mjs +4 -0
  125. package/dist/components/kb-search.css +940 -0
  126. package/dist/components/kb-segment.mjs +4 -0
  127. package/dist/components/kb-sources.mjs +4 -0
  128. package/dist/components/kb-sql.mjs +4 -0
  129. package/dist/components/kb-trace.mjs +4 -0
  130. package/dist/components/kb-visibility.mjs +4 -0
  131. package/dist/components/kb-who-can.mjs +4 -0
  132. package/dist/components/kb.css +252 -0
  133. package/dist/components/kb.mjs +9 -0
  134. package/dist/index.d.mts +37 -2
  135. package/dist/index.mjs +8555 -205
  136. package/dist/registry.json +325 -3
  137. package/dist/ui.css +5451 -45
  138. package/docs/research/2026-10-03-ai-kb-components.md +392 -0
  139. package/docs/research/2026-10-03-kb-permissions.md +992 -0
  140. package/docs/spec/kb-family.md +443 -0
  141. package/package.json +2 -2
@@ -0,0 +1,940 @@
1
+ /*
2
+ * @icen.ai/ui — kb-search.css(检索域:kb-retrieval / kb-filter / kb-rerank / kb-hittest)
3
+ * 共享原语在 kb.css(.kb-score/.kb-hit mark/.kb-chip/.kb-num/.kb-badge/.kb-empty…),
4
+ * 本文件只做本域专属结构。DOM 契约见 docs/spec/kb-family.md §5.11–5.14 与各 behavior 头注释。
5
+ *
6
+ * 域内纪律(spec §2):
7
+ * - 参数栏 gap 8、控件高 28;行基元 28px 节奏;组内 8px、区块 12–16px
8
+ * - accent 稀缺:每个视图唯一 accent 级操作(检索「运行」/ 测试「运行全部」);其余 ghost 24px
9
+ * - 数字一律 .kb-num(mono + tabular-nums);元信息 11–11.5px faint
10
+ * - 显式禁用不隐藏(alpha 脱离混合模式 / 阈值脱离重排 / 组深度达上限 → .is-off + disabled)
11
+ * - 只用 --token-* 与 kb.css 原语;动效 ≤240ms ease-out;reduced-motion 走全局规则
12
+ */
13
+
14
+ /* ══════════════ 0. 域内共享控件基元 ══════════════ */
15
+
16
+ /* 文本输入(query / 过滤字段 / 过滤值 / 新增问题) */
17
+ .kb-retrieval-query,
18
+ .kb-hittest-input,
19
+ .kb-filter-field,
20
+ .kb-filter-value {
21
+ height: 28px;
22
+ padding: 0 10px;
23
+ font: inherit;
24
+ font-size: 12.5px;
25
+ color: var(--token-text);
26
+ background: var(--token-bg);
27
+ border: 1px solid var(--token-line-soft);
28
+ border-radius: var(--radius-sm, 6px);
29
+ transition: border-color 0.16s ease-out;
30
+ }
31
+ .kb-retrieval-query::placeholder,
32
+ .kb-hittest-input::placeholder,
33
+ .kb-filter-field::placeholder,
34
+ .kb-filter-value::placeholder {
35
+ color: var(--token-text-faint);
36
+ }
37
+ .kb-retrieval-query:focus-visible,
38
+ .kb-hittest-input:focus-visible,
39
+ .kb-filter-field:focus-visible,
40
+ .kb-filter-value:focus-visible,
41
+ .kb-filter-op:focus-visible {
42
+ outline: none;
43
+ border-color: var(--token-accent);
44
+ }
45
+ .kb-filter-field:disabled,
46
+ .kb-filter-value:disabled {
47
+ opacity: var(--icen-disabled-opacity, 0.5);
48
+ cursor: not-allowed;
49
+ }
50
+
51
+ /* 滑杆(alpha 混合权重 / 分数阈值):自实现简单拖杆,input[type=range] 样式化 */
52
+ .kb-range {
53
+ -webkit-appearance: none;
54
+ appearance: none;
55
+ width: 96px;
56
+ height: 28px;
57
+ margin: 0;
58
+ background: transparent;
59
+ accent-color: var(--token-accent);
60
+ cursor: pointer;
61
+ }
62
+ .kb-range::-webkit-slider-runnable-track {
63
+ height: 3px;
64
+ border-radius: 2px;
65
+ background: var(--token-line-soft);
66
+ }
67
+ .kb-range::-webkit-slider-thumb {
68
+ -webkit-appearance: none;
69
+ appearance: none;
70
+ width: 11px;
71
+ height: 11px;
72
+ margin-top: -4px;
73
+ border-radius: 50%;
74
+ background: var(--token-bg);
75
+ border: 1.5px solid var(--token-text-muted);
76
+ transition: border-color 0.16s ease-out;
77
+ }
78
+ .kb-range:hover:not(:disabled)::-webkit-slider-thumb {
79
+ border-color: var(--token-text);
80
+ }
81
+ .kb-range::-moz-range-track {
82
+ height: 3px;
83
+ border-radius: 2px;
84
+ background: var(--token-line-soft);
85
+ }
86
+ .kb-range::-moz-range-thumb {
87
+ width: 9px;
88
+ height: 9px;
89
+ border-radius: 50%;
90
+ background: var(--token-bg);
91
+ border: 1.5px solid var(--token-text-muted);
92
+ }
93
+ .kb-range:disabled {
94
+ opacity: 0.45;
95
+ cursor: not-allowed;
96
+ }
97
+ .kb-range:focus-visible {
98
+ outline: 2px solid var(--token-accent);
99
+ outline-offset: 2px;
100
+ }
101
+
102
+ /* 开关(重排 / 重排对比):中性色——accent 留给运行钮 */
103
+ .kb-switch {
104
+ position: relative;
105
+ flex: 0 0 auto;
106
+ width: 30px;
107
+ height: 17px;
108
+ padding: 0;
109
+ border-radius: 999px;
110
+ border: 1px solid var(--token-line-soft);
111
+ background: var(--token-bg-soft);
112
+ cursor: pointer;
113
+ transition: background-color 0.16s ease-out, border-color 0.16s ease-out;
114
+ }
115
+ .kb-switch::after {
116
+ content: '';
117
+ position: absolute;
118
+ top: 2px;
119
+ left: 2px;
120
+ width: 11px;
121
+ height: 11px;
122
+ border-radius: 50%;
123
+ background: var(--token-text-faint);
124
+ transition: transform 0.16s ease-out, background-color 0.16s ease-out;
125
+ }
126
+ .kb-switch[aria-checked='true'] {
127
+ background: color-mix(in srgb, var(--token-text) 10%, transparent);
128
+ border-color: var(--token-line);
129
+ }
130
+ .kb-switch[aria-checked='true']::after {
131
+ transform: translateX(13px);
132
+ background: var(--token-text);
133
+ }
134
+ .kb-switch:focus-visible {
135
+ outline: 2px solid var(--token-accent);
136
+ outline-offset: 2px;
137
+ }
138
+ .kb-toggle {
139
+ display: inline-flex;
140
+ align-items: center;
141
+ gap: 6px;
142
+ }
143
+ .kb-toggle-label {
144
+ font-size: 12px;
145
+ color: var(--token-text-muted);
146
+ }
147
+
148
+ /* 运行钮:本视图唯一 accent 级操作(btn-primary 语义,域内自持样式) */
149
+ .kb-run {
150
+ display: inline-flex;
151
+ align-items: center;
152
+ gap: 6px;
153
+ height: 28px;
154
+ padding: 0 14px;
155
+ font: inherit;
156
+ font-size: 12.5px;
157
+ font-weight: 600;
158
+ letter-spacing: 0.02em;
159
+ color: var(--token-on-accent);
160
+ background: var(--token-accent);
161
+ border: 1px solid var(--token-accent);
162
+ border-radius: var(--radius-sm, 6px);
163
+ cursor: pointer;
164
+ transition: background-color 0.16s ease-out, border-color 0.16s ease-out, opacity 0.16s ease-out;
165
+ }
166
+ .kb-run svg {
167
+ width: 12px;
168
+ height: 12px;
169
+ }
170
+ .kb-run:hover:not(:disabled) {
171
+ background: var(--token-accent-deep, var(--token-accent));
172
+ border-color: var(--token-accent-deep, var(--token-accent));
173
+ }
174
+ .kb-run:disabled {
175
+ opacity: var(--icen-disabled-opacity, 0.5);
176
+ cursor: not-allowed;
177
+ pointer-events: none;
178
+ }
179
+
180
+ /* ghost 操作钮(24px:filter 增删 / DSL 复制 / hittest pin 与删除 / 参数复制) */
181
+ .kb-params-copy,
182
+ .kb-filter-act,
183
+ .kb-hittest-pin,
184
+ .kb-hittest-remove {
185
+ display: inline-flex;
186
+ align-items: center;
187
+ justify-content: center;
188
+ width: 24px;
189
+ height: 24px;
190
+ padding: 0;
191
+ font: inherit;
192
+ font-size: 12.5px;
193
+ line-height: 1;
194
+ color: var(--token-text-muted);
195
+ background: transparent;
196
+ border: 1px solid transparent;
197
+ border-radius: var(--radius-sm, 6px);
198
+ cursor: pointer;
199
+ transition: color 0.16s ease-out, background-color 0.16s ease-out, border-color 0.16s ease-out;
200
+ }
201
+ .kb-params-copy:hover,
202
+ .kb-filter-act:hover:not(:disabled),
203
+ .kb-hittest-pin:hover,
204
+ .kb-hittest-remove:hover {
205
+ color: var(--token-text);
206
+ background: var(--token-bg-soft);
207
+ border-color: var(--token-line-soft);
208
+ }
209
+ .kb-filter-act:disabled {
210
+ opacity: var(--icen-disabled-opacity, 0.45);
211
+ cursor: not-allowed;
212
+ }
213
+ .kb-filter-act.is-danger:hover:not(:disabled),
214
+ .kb-hittest-remove:hover {
215
+ color: var(--token-danger, var(--token-error));
216
+ }
217
+ .kb-params-copy.is-copied,
218
+ .kb-filter-dsl-copy.is-copied {
219
+ color: var(--token-success);
220
+ }
221
+ .kb-params-copy {
222
+ width: 22px;
223
+ height: 22px;
224
+ }
225
+ .kb-params-copy svg {
226
+ width: 12px;
227
+ height: 12px;
228
+ }
229
+
230
+ /* scoreKind 微型 chip(retrieval hit / rerank 列头共用) */
231
+ .kb-chip--kind {
232
+ font-size: 10px;
233
+ padding: 1px 6px;
234
+ color: var(--token-text-faint);
235
+ }
236
+
237
+ /* ══════════════ 1. kb-retrieval 检索 playground ══════════════ */
238
+
239
+ .kb-retrieval {
240
+ display: flex;
241
+ flex-direction: column;
242
+ gap: 12px;
243
+ }
244
+
245
+ .kb-retrieval-bar {
246
+ display: flex;
247
+ flex-wrap: wrap;
248
+ align-items: center;
249
+ gap: 10px 14px;
250
+ }
251
+
252
+ .kb-retrieval-query {
253
+ flex: 1 1 200px;
254
+ min-width: 160px;
255
+ }
256
+
257
+ /* 模式 segmented(向量|关键词|混合):激活态用层级色,不与运行钮抢 accent */
258
+ .kb-modes {
259
+ display: inline-flex;
260
+ align-items: center;
261
+ gap: 2px;
262
+ box-sizing: border-box;
263
+ height: 28px;
264
+ padding: 2px;
265
+ background: var(--token-bg-soft);
266
+ border: 1px solid var(--token-line-soft);
267
+ border-radius: var(--radius-sm, 6px);
268
+ }
269
+ .kb-mode-item {
270
+ height: 22px;
271
+ padding: 0 10px;
272
+ font: inherit;
273
+ font-size: 12px;
274
+ line-height: 1;
275
+ color: var(--token-text-muted);
276
+ background: transparent;
277
+ border: none;
278
+ border-radius: 4px;
279
+ cursor: pointer;
280
+ transition: color 0.16s ease-out, background-color 0.16s ease-out;
281
+ }
282
+ .kb-mode-item:hover {
283
+ color: var(--token-text);
284
+ }
285
+ .kb-mode-item.is-active {
286
+ background: var(--token-bg);
287
+ color: var(--token-text);
288
+ font-weight: 600;
289
+ box-shadow: var(--token-shadow-inset);
290
+ }
291
+ .kb-mode-item:focus-visible {
292
+ outline: 2px solid var(--token-accent);
293
+ outline-offset: -2px;
294
+ }
295
+
296
+ /* topK 步进器 */
297
+ .kb-step {
298
+ display: inline-flex;
299
+ align-items: center;
300
+ height: 28px;
301
+ overflow: hidden;
302
+ background: var(--token-bg);
303
+ border: 1px solid var(--token-line-soft);
304
+ border-radius: var(--radius-sm, 6px);
305
+ }
306
+ .kb-step-btn {
307
+ width: 26px;
308
+ height: 100%;
309
+ font: inherit;
310
+ font-size: 13px;
311
+ color: var(--token-text-muted);
312
+ background: transparent;
313
+ border: none;
314
+ cursor: pointer;
315
+ transition: background-color 0.16s ease-out, color 0.16s ease-out;
316
+ }
317
+ .kb-step-btn:hover:not(:disabled) {
318
+ background: var(--token-bg-soft);
319
+ color: var(--token-text);
320
+ }
321
+ .kb-step-btn:disabled {
322
+ opacity: var(--icen-disabled-opacity, 0.45);
323
+ cursor: not-allowed;
324
+ }
325
+ .kb-step-value {
326
+ min-width: 26px;
327
+ text-align: center;
328
+ }
329
+
330
+ /* alpha 双端滑杆:两端语义文案(title 提示);非混合模式显式禁用不隐藏 */
331
+ .kb-alpha {
332
+ display: inline-flex;
333
+ align-items: center;
334
+ gap: 6px;
335
+ height: 28px;
336
+ }
337
+ .kb-alpha-end {
338
+ font-size: 10.5px;
339
+ color: var(--token-text-faint);
340
+ cursor: help;
341
+ white-space: nowrap;
342
+ }
343
+ .kb-alpha.is-off {
344
+ opacity: 0.55;
345
+ }
346
+
347
+ /* 阈值 + 存活计数:rerank 关闭时 N/A(显式禁用不隐藏) */
348
+ .kb-threshold {
349
+ display: inline-flex;
350
+ align-items: center;
351
+ gap: 6px;
352
+ height: 28px;
353
+ }
354
+ .kb-threshold-count {
355
+ min-width: 150px;
356
+ white-space: nowrap;
357
+ }
358
+ .kb-threshold.is-off .kb-threshold-count {
359
+ color: var(--token-text-faint);
360
+ }
361
+
362
+ .kb-retrieval-bar .kb-run {
363
+ margin-left: auto;
364
+ }
365
+
366
+ /* 检索身份选择(权限域注入的控件,spec §9.7;固定身份集——服务端 token 语义,不接受自由输入) */
367
+ .kb-retrieval-idn-group { display: inline-flex; align-items: center; gap: 6px; }
368
+ .kb-retrieval-idn {
369
+ height: 28px;
370
+ padding: 0 6px;
371
+ font: inherit;
372
+ font-size: 12.5px;
373
+ color: var(--token-text);
374
+ background: var(--token-bg);
375
+ border: 1px solid var(--token-line-soft);
376
+ border-radius: var(--radius-sm, 6px);
377
+ transition: border-color 0.16s ease-out;
378
+ }
379
+ .kb-retrieval-idn:focus-visible { outline: none; border-color: var(--token-accent); }
380
+
381
+ /* 可复制参数 JSON 行(.kb-meta mono;DSL 双表示纪律):不换行不断词,横向滚动 */
382
+ .kb-params {
383
+ display: flex;
384
+ align-items: center;
385
+ gap: 6px;
386
+ min-width: 0;
387
+ max-width: 100%;
388
+ }
389
+ .kb-params-text {
390
+ flex: 1 1 auto;
391
+ min-width: 0;
392
+ overflow-x: auto;
393
+ white-space: pre;
394
+ word-break: normal;
395
+ font-family: var(--font-mono, ui-monospace, monospace);
396
+ }
397
+
398
+ /* 命中列表:rank 列 28px 右对齐,hover 浮起 */
399
+ .kb-hits {
400
+ display: flex;
401
+ flex-direction: column;
402
+ gap: 4px;
403
+ }
404
+ .kb-hit {
405
+ display: grid;
406
+ grid-template-columns: 28px minmax(0, 1fr) auto;
407
+ gap: 10px;
408
+ padding: 8px 10px;
409
+ background: var(--token-bg-soft);
410
+ border: 1px solid transparent;
411
+ border-radius: var(--radius-md, 8px);
412
+ transition: border-color 0.16s ease-out, box-shadow 0.16s ease-out;
413
+ }
414
+ .kb-hit:hover {
415
+ border-color: var(--token-line-soft);
416
+ box-shadow: var(--token-shadow-card);
417
+ }
418
+ .kb-hit-rank {
419
+ width: 28px;
420
+ padding-top: 1px;
421
+ text-align: right;
422
+ font-size: 12px;
423
+ color: var(--token-text-faint);
424
+ }
425
+ .kb-hit-main {
426
+ display: flex;
427
+ flex-direction: column;
428
+ gap: 3px;
429
+ min-width: 0;
430
+ }
431
+ .kb-hit-title {
432
+ font-size: 13px;
433
+ font-weight: 500;
434
+ color: var(--token-text);
435
+ white-space: nowrap;
436
+ overflow: hidden;
437
+ text-overflow: ellipsis;
438
+ }
439
+ .kb-hit-snippet {
440
+ display: -webkit-box;
441
+ -webkit-box-orient: vertical;
442
+ -webkit-line-clamp: 2;
443
+ overflow: hidden;
444
+ font-size: 12.5px;
445
+ line-height: 1.65;
446
+ color: var(--token-text-muted);
447
+ }
448
+ /* 多命中分色轮转(补 kb-quote 的 data-hit 轮转到 .kb-hit mark) */
449
+ .kb-hit mark[data-hit='1'] {
450
+ background: color-mix(in srgb, var(--token-warning) 22%, transparent);
451
+ }
452
+ .kb-hit mark[data-hit='2'] {
453
+ background: color-mix(in srgb, var(--token-info, var(--token-accent)) 20%, transparent);
454
+ }
455
+ .kb-hit-meta {
456
+ display: flex;
457
+ flex-wrap: wrap;
458
+ gap: 4px;
459
+ }
460
+ .kb-hit-meta:empty {
461
+ display: none;
462
+ }
463
+ .kb-hit-side {
464
+ display: flex;
465
+ flex-direction: column;
466
+ align-items: flex-end;
467
+ gap: 4px;
468
+ }
469
+
470
+ /* 分数拆解:vectorPart/keywordPart 微型双段条(向量=accent / 关键词=info) */
471
+ .kb-score-dual {
472
+ display: inline-flex;
473
+ width: 88px;
474
+ height: 3px;
475
+ overflow: hidden;
476
+ border-radius: 2px;
477
+ background: var(--token-line-soft);
478
+ }
479
+ .kb-score-dual i {
480
+ display: block;
481
+ height: 100%;
482
+ }
483
+ .kb-score-dual .kb-score-dual-vec {
484
+ background: var(--token-accent);
485
+ opacity: 0.75;
486
+ }
487
+ .kb-score-dual .kb-score-dual-kw {
488
+ flex: 1 1 auto;
489
+ background: var(--token-info, var(--token-accent));
490
+ opacity: 0.8;
491
+ }
492
+
493
+ /* 分数条固定轨道:bar 定宽 64px、不参与 flex 伸缩,i 定量不缩——
494
+ 跨行条长与百分比严格成比例(0.488 与 0.131 肉眼可辨;retrieval 与 rerank 同规) */
495
+ .kb-retrieval .kb-score-bar,
496
+ .kb-rerank .kb-score-bar {
497
+ display: block;
498
+ flex: 0 0 64px;
499
+ width: 64px;
500
+ min-width: 0;
501
+ }
502
+ .kb-retrieval .kb-score-bar > i,
503
+ .kb-rerank .kb-score-bar > i {
504
+ display: block;
505
+ flex: 0 0 auto;
506
+ }
507
+
508
+ /* explain 折叠小字 */
509
+ .kb-hit-explain-fold {
510
+ display: flex;
511
+ flex-direction: column;
512
+ align-items: flex-end;
513
+ gap: 3px;
514
+ }
515
+ .kb-hit-explain-toggle {
516
+ padding: 0;
517
+ font: inherit;
518
+ font-size: 10.5px;
519
+ color: var(--token-text-faint);
520
+ background: transparent;
521
+ border: none;
522
+ cursor: pointer;
523
+ }
524
+ .kb-hit-explain-toggle:hover {
525
+ color: var(--token-text-muted);
526
+ text-decoration: underline;
527
+ }
528
+ .kb-hit-explain {
529
+ max-width: 320px;
530
+ font-size: 10.5px;
531
+ line-height: 1.6;
532
+ text-align: right;
533
+ white-space: normal;
534
+ word-break: break-all;
535
+ }
536
+
537
+ /* 运行态 */
538
+ .kb-retrieval.is-busy .kb-hits {
539
+ opacity: 0.6;
540
+ }
541
+ .kb-retrieval.is-busy .kb-hit {
542
+ pointer-events: none;
543
+ }
544
+
545
+ /* ══════════════ 2. kb-filter 过滤器构建器 ══════════════ */
546
+
547
+ .kb-filter {
548
+ display: flex;
549
+ flex-direction: column;
550
+ gap: 12px;
551
+ }
552
+
553
+ /* 组:嵌套组缩进 16px + 连接线(body 左缘竖线 + rule 行横线) */
554
+ .kb-filter-group {
555
+ padding: 8px;
556
+ border: 1px solid var(--token-line-soft);
557
+ border-radius: var(--radius-md, 8px);
558
+ }
559
+ .kb-filter-group .kb-filter-group {
560
+ background: var(--token-bg-soft);
561
+ }
562
+ .kb-filter-head {
563
+ display: flex;
564
+ align-items: center;
565
+ gap: 6px;
566
+ margin-bottom: 6px;
567
+ }
568
+ .kb-filter-op-toggle {
569
+ height: 24px;
570
+ padding: 0 10px;
571
+ font-family: var(--font-mono, ui-monospace, monospace);
572
+ font-size: 11px;
573
+ letter-spacing: 0.5px;
574
+ color: var(--token-text-muted);
575
+ background: var(--token-bg);
576
+ border: 1px solid var(--token-line-soft);
577
+ border-radius: var(--radius-sm, 6px);
578
+ cursor: pointer;
579
+ transition: color 0.16s ease-out, border-color 0.16s ease-out;
580
+ }
581
+ .kb-filter-op-toggle:hover {
582
+ color: var(--token-text);
583
+ border-color: var(--token-line);
584
+ }
585
+ .kb-filter-op-toggle.is-or {
586
+ font-weight: 600;
587
+ color: var(--token-text);
588
+ }
589
+ .kb-filter-head .kb-filter-act {
590
+ padding: 0 8px;
591
+ width: auto;
592
+ }
593
+
594
+ .kb-filter-body {
595
+ display: flex;
596
+ flex-direction: column;
597
+ gap: 6px;
598
+ margin-left: 16px;
599
+ padding-left: 10px;
600
+ border-left: 1px solid var(--token-line-soft);
601
+ }
602
+
603
+ .kb-filter-rule {
604
+ position: relative;
605
+ display: flex;
606
+ flex-wrap: wrap; /* 窄栏兜底:值输入挤不下时独占次行全宽,日期串不截字 */
607
+ align-items: center;
608
+ gap: 6px;
609
+ }
610
+ /* rule → 组竖线的横向连接线 */
611
+ .kb-filter-rule::before {
612
+ content: '';
613
+ position: absolute;
614
+ top: 50%;
615
+ left: -10px;
616
+ width: 10px;
617
+ height: 1px;
618
+ background: var(--token-line-soft);
619
+ }
620
+ .kb-filter-field {
621
+ width: 120px;
622
+ flex: 0 0 auto;
623
+ font-family: var(--font-mono, ui-monospace, monospace);
624
+ font-size: 12px;
625
+ }
626
+ .kb-filter-op {
627
+ height: 28px;
628
+ padding: 0 6px;
629
+ font: inherit;
630
+ font-size: 12px;
631
+ color: var(--token-text);
632
+ background: var(--token-bg);
633
+ border: 1px solid var(--token-line-soft);
634
+ border-radius: var(--radius-sm, 6px);
635
+ cursor: pointer;
636
+ }
637
+ .kb-filter-value {
638
+ flex: 1 1 120px;
639
+ min-width: 104px; /* 12px mono 下容得下整条日期串 2026-07-01,不截字 */
640
+ font-family: var(--font-mono, ui-monospace, monospace);
641
+ font-size: 12px;
642
+ }
643
+
644
+ /* DSL 镜像(Mongo JSON / OData tab 切换,mono 可复制) */
645
+ .kb-filter-dsl {
646
+ display: flex;
647
+ flex-direction: column;
648
+ gap: 5px;
649
+ padding: 6px 8px;
650
+ background: var(--token-bg-soft);
651
+ border: 1px solid var(--token-line-soft);
652
+ border-radius: var(--radius-md, 8px);
653
+ }
654
+ .kb-filter-dsl-bar {
655
+ display: flex;
656
+ align-items: center;
657
+ gap: 4px;
658
+ }
659
+ .kb-filter-dsl-tab {
660
+ height: 22px;
661
+ padding: 0 10px;
662
+ font-family: var(--font-mono, ui-monospace, monospace);
663
+ font-size: 11px;
664
+ color: var(--token-text-faint);
665
+ background: transparent;
666
+ border: 1px solid transparent;
667
+ border-radius: var(--radius-sm, 6px);
668
+ cursor: pointer;
669
+ transition: color 0.16s ease-out, background-color 0.16s ease-out, border-color 0.16s ease-out;
670
+ }
671
+ .kb-filter-dsl-tab:hover {
672
+ color: var(--token-text-muted);
673
+ }
674
+ .kb-filter-dsl-tab.is-active {
675
+ color: var(--token-text);
676
+ background: var(--token-bg);
677
+ border-color: var(--token-line-soft);
678
+ }
679
+ .kb-filter-dsl-copy {
680
+ margin-left: auto;
681
+ width: auto;
682
+ padding: 0 8px;
683
+ font-size: 11px;
684
+ }
685
+ .kb-filter-dsl-text {
686
+ display: block;
687
+ max-height: 110px;
688
+ overflow: auto;
689
+ line-height: 1.6;
690
+ /* DSL 镜像(Mongo/OData):mono + 不换行不断词,横向滚动兜底 */
691
+ white-space: pre;
692
+ word-break: normal;
693
+ font-family: var(--font-mono, ui-monospace, monospace);
694
+ }
695
+
696
+ /* ══════════════ 3. kb-rerank rerank A/B 对比 ══════════════ */
697
+
698
+ .kb-rerank {
699
+ display: flex;
700
+ flex-direction: column;
701
+ gap: 10px;
702
+ /* 窄视口兜底:网格按列 min-width 整体横向滚动,「重排后」末列不被截断 */
703
+ min-width: 0;
704
+ overflow-x: auto;
705
+ }
706
+ .kb-rerank-head {
707
+ display: flex;
708
+ align-items: center;
709
+ gap: 8px;
710
+ }
711
+ .kb-rerank-switch-label {
712
+ margin-left: auto;
713
+ }
714
+ .kb-rerank-grid {
715
+ display: grid;
716
+ grid-template-columns: minmax(200px, 1fr) 52px minmax(200px, 1fr);
717
+ min-width: 470px; /* 列最小宽合计:低于此宽走横向滚动而非压缩截断 */
718
+ column-gap: 8px;
719
+ row-gap: 2px;
720
+ align-items: stretch;
721
+ }
722
+ .kb-rerank-grid > .kb-empty {
723
+ grid-column: 1 / -1;
724
+ }
725
+ .kb-rerank-colhead {
726
+ display: flex;
727
+ align-items: center;
728
+ gap: 6px;
729
+ min-height: 26px;
730
+ padding: 0 8px;
731
+ font-size: 11.5px;
732
+ color: var(--token-text-muted);
733
+ border-bottom: 1px solid var(--token-line-soft);
734
+ }
735
+ .kb-rerank-colhead--delta {
736
+ justify-content: center;
737
+ font-family: var(--font-mono, ui-monospace, monospace);
738
+ }
739
+ /* 行容器 display:contents:三格参与网格对齐,行 hover 整排点亮 */
740
+ .kb-rerank-row {
741
+ display: contents;
742
+ }
743
+ .kb-rerank-row:hover > .kb-rerank-col {
744
+ background: var(--token-bg-soft);
745
+ }
746
+ .kb-rerank-col {
747
+ display: flex;
748
+ align-items: center;
749
+ gap: 8px;
750
+ min-height: 32px;
751
+ padding: 3px 8px;
752
+ border-radius: var(--radius-sm, 6px);
753
+ transition: background-color 0.16s ease-out;
754
+ }
755
+ .kb-rerank-col.is-missing {
756
+ opacity: 0.6;
757
+ }
758
+ .kb-rerank-rank {
759
+ flex: 0 0 auto;
760
+ width: 18px;
761
+ text-align: right;
762
+ font-size: 11.5px;
763
+ }
764
+ .kb-rerank-title {
765
+ flex: 1 1 auto;
766
+ min-width: 0;
767
+ overflow: hidden;
768
+ font-size: 12.5px;
769
+ color: var(--token-text);
770
+ white-space: nowrap;
771
+ text-overflow: ellipsis;
772
+ }
773
+ .kb-rerank-missing {
774
+ flex: 1 1 auto;
775
+ font-size: 11px;
776
+ color: var(--token-text-faint);
777
+ }
778
+ /* delta 箭头:上升绿 / 下降红 / 持平或单侧缺失 — */
779
+ .kb-rerank-delta {
780
+ display: flex;
781
+ align-items: center;
782
+ justify-content: center;
783
+ font-family: var(--font-mono, ui-monospace, monospace);
784
+ font-variant-numeric: tabular-nums;
785
+ font-size: 11.5px;
786
+ color: var(--token-text-faint);
787
+ }
788
+ .kb-rerank-delta.is-up {
789
+ font-weight: 600;
790
+ color: var(--token-success);
791
+ }
792
+ .kb-rerank-delta.is-down {
793
+ font-weight: 600;
794
+ color: var(--token-danger, var(--token-error));
795
+ }
796
+ /* 开关关闭:重排后列压淡(显式禁用不隐藏) */
797
+ .kb-rerank.is-off .kb-rerank-col--after {
798
+ opacity: 0.45;
799
+ }
800
+
801
+ /* ══════════════ 4. kb-hittest 召回测试集 ══════════════ */
802
+
803
+ .kb-hittest {
804
+ display: flex;
805
+ flex-direction: column;
806
+ gap: 12px;
807
+ }
808
+ .kb-hittest > .kb-run {
809
+ align-self: flex-start;
810
+ }
811
+
812
+ /* 统计头:命中率大数字 + 均分 + 通过 x/y + 参数快照徽标 */
813
+ .kb-hittest-stats {
814
+ display: flex;
815
+ flex-wrap: wrap;
816
+ align-items: center;
817
+ gap: 20px;
818
+ padding: 10px 12px;
819
+ background: var(--token-bg-soft);
820
+ border: 1px solid var(--token-line-soft);
821
+ border-radius: var(--radius-md, 8px);
822
+ }
823
+ .kb-hittest-stat {
824
+ display: flex;
825
+ align-items: baseline;
826
+ gap: 6px;
827
+ }
828
+ .kb-hittest-stat-label {
829
+ font-size: 10.5px;
830
+ letter-spacing: 0.3px;
831
+ color: var(--token-text-faint);
832
+ }
833
+ .kb-hittest-hitrate {
834
+ font-size: 22px;
835
+ font-weight: 600;
836
+ color: var(--token-text);
837
+ }
838
+ .kb-hittest-stats .kb-badge {
839
+ margin-left: auto;
840
+ }
841
+
842
+ /* 问题列表 */
843
+ .kb-hittest-list {
844
+ display: flex;
845
+ flex-direction: column;
846
+ gap: 4px;
847
+ }
848
+ .kb-hittest-row {
849
+ display: grid;
850
+ grid-template-columns: 24px minmax(0, 1fr) auto 28px 24px;
851
+ gap: 8px;
852
+ align-items: center;
853
+ min-height: 30px;
854
+ padding: 3px 8px;
855
+ border-radius: var(--radius-sm, 6px);
856
+ }
857
+ .kb-hittest-row:hover {
858
+ background: var(--token-bg-soft);
859
+ }
860
+ .kb-hittest-pin svg {
861
+ width: 13px;
862
+ height: 13px;
863
+ opacity: 0.55;
864
+ }
865
+ .kb-hittest-pin.is-pinned {
866
+ color: var(--token-text);
867
+ }
868
+ .kb-hittest-pin.is-pinned svg {
869
+ opacity: 1;
870
+ }
871
+ .kb-hittest-q {
872
+ overflow: hidden;
873
+ font-size: 13px;
874
+ color: var(--token-text);
875
+ white-space: nowrap;
876
+ text-overflow: ellipsis;
877
+ }
878
+ .kb-hittest-expected {
879
+ display: inline-flex;
880
+ align-items: center;
881
+ gap: 4px;
882
+ max-width: 42%;
883
+ overflow: hidden;
884
+ }
885
+ .kb-hittest-result {
886
+ width: 28px;
887
+ text-align: center;
888
+ font-weight: 600;
889
+ color: var(--token-text-faint);
890
+ }
891
+ .kb-hittest-row.is-pass .kb-hittest-result {
892
+ color: var(--token-success);
893
+ }
894
+ .kb-hittest-row.is-fail .kb-hittest-result {
895
+ color: var(--token-danger, var(--token-error));
896
+ }
897
+ .kb-hittest-remove {
898
+ opacity: 0;
899
+ }
900
+ .kb-hittest-row:hover .kb-hittest-remove,
901
+ .kb-hittest-remove:focus-visible {
902
+ opacity: 1;
903
+ }
904
+
905
+ /* 新增问题 */
906
+ .kb-hittest-add {
907
+ display: flex;
908
+ gap: 8px;
909
+ }
910
+ .kb-hittest-input {
911
+ flex: 1 1 auto;
912
+ }
913
+ .kb-hittest-add-btn {
914
+ height: 28px;
915
+ padding: 0 12px;
916
+ font: inherit;
917
+ font-size: 12.5px;
918
+ color: var(--token-text-muted);
919
+ background: var(--token-bg);
920
+ border: 1px solid var(--token-line-soft);
921
+ border-radius: var(--radius-sm, 6px);
922
+ cursor: pointer;
923
+ transition: color 0.16s ease-out, border-color 0.16s ease-out;
924
+ }
925
+ .kb-hittest-add-btn:hover {
926
+ color: var(--token-text);
927
+ border-color: var(--token-line);
928
+ }
929
+
930
+ /* ══════════════ 5. 密度档(spec §2:compact 行高收紧) ══════════════ */
931
+
932
+ [data-density='compact'] .kb-hit {
933
+ padding: 5px 8px;
934
+ }
935
+ [data-density='compact'] .kb-hittest-row {
936
+ min-height: 24px;
937
+ }
938
+ [data-density='compact'] .kb-rerank-col {
939
+ min-height: 26px;
940
+ }