@icen.ai/ui 0.8.0 → 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 (228) hide show
  1. package/AGENTS.md +63 -14
  2. package/README.md +17 -9
  3. package/dist/base.css +4 -3
  4. package/dist/behaviors/accordion.d.mts +5 -2
  5. package/dist/behaviors/accordion.mjs +36 -11
  6. package/dist/behaviors/ai-branch.d.mts +19 -0
  7. package/dist/behaviors/ai-branch.mjs +217 -0
  8. package/dist/behaviors/ai-chat.d.mts +11 -7
  9. package/dist/behaviors/ai-chat.mjs +134 -51
  10. package/dist/behaviors/ai-composer.d.mts +28 -3
  11. package/dist/behaviors/ai-composer.mjs +399 -229
  12. package/dist/behaviors/ai-core.d.mts +9 -4
  13. package/dist/behaviors/ai-core.mjs +21 -8
  14. package/dist/behaviors/ai-diff.d.mts +2 -2
  15. package/dist/behaviors/ai-diff.mjs +172 -41
  16. package/dist/behaviors/ai-feedback.d.mts +26 -0
  17. package/dist/behaviors/ai-feedback.mjs +303 -0
  18. package/dist/behaviors/ai-panel.d.mts +26 -9
  19. package/dist/behaviors/ai-panel.mjs +211 -110
  20. package/dist/behaviors/ai-provider.mjs +54 -48
  21. package/dist/behaviors/ai-threads.d.mts +38 -0
  22. package/dist/behaviors/ai-threads.mjs +319 -0
  23. package/dist/behaviors/ai-tool.d.mts +12 -4
  24. package/dist/behaviors/ai-tool.mjs +316 -263
  25. package/dist/behaviors/ai-tools.d.mts +9 -6
  26. package/dist/behaviors/ai-tools.mjs +264 -155
  27. package/dist/behaviors/back-top.mjs +16 -1
  28. package/dist/behaviors/carousel.d.mts +5 -2
  29. package/dist/behaviors/carousel.mjs +53 -26
  30. package/dist/behaviors/charts.d.mts +170 -22
  31. package/dist/behaviors/charts.mjs +1016 -150
  32. package/dist/behaviors/command-palette.d.mts +40 -6
  33. package/dist/behaviors/command-palette.mjs +143 -15
  34. package/dist/behaviors/context-menu.d.mts +21 -4
  35. package/dist/behaviors/context-menu.mjs +122 -38
  36. package/dist/behaviors/controls.d.mts +59 -0
  37. package/dist/behaviors/controls.mjs +601 -0
  38. package/dist/behaviors/copy.d.mts +5 -2
  39. package/dist/behaviors/copy.mjs +37 -12
  40. package/dist/behaviors/datatable.d.mts +12 -0
  41. package/dist/behaviors/datatable.mjs +226 -43
  42. package/dist/behaviors/date-picker.d.mts +2 -2
  43. package/dist/behaviors/date-picker.mjs +171 -32
  44. package/dist/behaviors/dropdown.d.mts +6 -2
  45. package/dist/behaviors/dropdown.mjs +164 -25
  46. package/dist/behaviors/events.d.mts +523 -0
  47. package/dist/behaviors/events.mjs +208 -0
  48. package/dist/behaviors/input.mjs +25 -12
  49. package/dist/behaviors/kb-access.d.mts +34 -0
  50. package/dist/behaviors/kb-access.mjs +569 -0
  51. package/dist/behaviors/kb-acl.d.mts +50 -0
  52. package/dist/behaviors/kb-acl.mjs +405 -0
  53. package/dist/behaviors/kb-answer.d.mts +38 -0
  54. package/dist/behaviors/kb-answer.mjs +2055 -0
  55. package/dist/behaviors/kb-audit.d.mts +23 -0
  56. package/dist/behaviors/kb-audit.mjs +375 -0
  57. package/dist/behaviors/kb-canvas.d.mts +44 -0
  58. package/dist/behaviors/kb-canvas.mjs +589 -0
  59. package/dist/behaviors/kb-chain.d.mts +15 -0
  60. package/dist/behaviors/kb-chain.mjs +270 -0
  61. package/dist/behaviors/kb-checkpoint.d.mts +16 -0
  62. package/dist/behaviors/kb-checkpoint.mjs +342 -0
  63. package/dist/behaviors/kb-chunks.d.mts +31 -0
  64. package/dist/behaviors/kb-chunks.mjs +475 -0
  65. package/dist/behaviors/kb-citation.d.mts +38 -0
  66. package/dist/behaviors/kb-citation.mjs +677 -0
  67. package/dist/behaviors/kb-clarify.d.mts +20 -0
  68. package/dist/behaviors/kb-clarify.mjs +248 -0
  69. package/dist/behaviors/kb-conflict.d.mts +22 -0
  70. package/dist/behaviors/kb-conflict.mjs +284 -0
  71. package/dist/behaviors/kb-connector.d.mts +17 -0
  72. package/dist/behaviors/kb-connector.mjs +375 -0
  73. package/dist/behaviors/kb-core.d.mts +529 -0
  74. package/dist/behaviors/kb-core.mjs +890 -0
  75. package/dist/behaviors/kb-eval.d.mts +22 -0
  76. package/dist/behaviors/kb-eval.mjs +408 -0
  77. package/dist/behaviors/kb-explain.d.mts +11 -0
  78. package/dist/behaviors/kb-explain.mjs +243 -0
  79. package/dist/behaviors/kb-filter.d.mts +31 -0
  80. package/dist/behaviors/kb-filter.mjs +587 -0
  81. package/dist/behaviors/kb-gap.d.mts +27 -0
  82. package/dist/behaviors/kb-gap.mjs +273 -0
  83. package/dist/behaviors/kb-hittest.d.mts +34 -0
  84. package/dist/behaviors/kb-hittest.mjs +409 -0
  85. package/dist/behaviors/kb-metadata.d.mts +29 -0
  86. package/dist/behaviors/kb-metadata.mjs +326 -0
  87. package/dist/behaviors/kb-passage.d.mts +41 -0
  88. package/dist/behaviors/kb-passage.mjs +529 -0
  89. package/dist/behaviors/kb-pipeline.d.mts +18 -0
  90. package/dist/behaviors/kb-pipeline.mjs +381 -0
  91. package/dist/behaviors/kb-qa.d.mts +26 -0
  92. package/dist/behaviors/kb-qa.mjs +332 -0
  93. package/dist/behaviors/kb-rerank.d.mts +20 -0
  94. package/dist/behaviors/kb-rerank.mjs +315 -0
  95. package/dist/behaviors/kb-retrieval.d.mts +49 -0
  96. package/dist/behaviors/kb-retrieval.mjs +746 -0
  97. package/dist/behaviors/kb-review.d.mts +44 -0
  98. package/dist/behaviors/kb-review.mjs +451 -0
  99. package/dist/behaviors/kb-sandbox.d.mts +33 -0
  100. package/dist/behaviors/kb-sandbox.mjs +325 -0
  101. package/dist/behaviors/kb-segment.d.mts +32 -0
  102. package/dist/behaviors/kb-segment.mjs +499 -0
  103. package/dist/behaviors/kb-sources.d.mts +27 -0
  104. package/dist/behaviors/kb-sources.mjs +373 -0
  105. package/dist/behaviors/kb-sql.d.mts +43 -0
  106. package/dist/behaviors/kb-sql.mjs +948 -0
  107. package/dist/behaviors/kb-trace.d.mts +16 -0
  108. package/dist/behaviors/kb-trace.mjs +414 -0
  109. package/dist/behaviors/kb-visibility.d.mts +44 -0
  110. package/dist/behaviors/kb-visibility.mjs +403 -0
  111. package/dist/behaviors/kb-who-can.d.mts +32 -0
  112. package/dist/behaviors/kb-who-can.mjs +379 -0
  113. package/dist/behaviors/modal.d.mts +24 -5
  114. package/dist/behaviors/modal.mjs +76 -10
  115. package/dist/behaviors/nav.d.mts +1 -1
  116. package/dist/behaviors/nav.mjs +33 -7
  117. package/dist/behaviors/notification.d.mts +20 -4
  118. package/dist/behaviors/notification.mjs +53 -73
  119. package/dist/behaviors/popover.d.mts +39 -3
  120. package/dist/behaviors/popover.mjs +90 -4
  121. package/dist/behaviors/select.d.mts +4 -2
  122. package/dist/behaviors/select.mjs +161 -24
  123. package/dist/behaviors/sidebar.d.mts +5 -2
  124. package/dist/behaviors/sidebar.mjs +43 -13
  125. package/dist/behaviors/slider.d.mts +5 -2
  126. package/dist/behaviors/slider.mjs +54 -43
  127. package/dist/behaviors/split-pane.d.mts +6 -2
  128. package/dist/behaviors/split-pane.mjs +62 -21
  129. package/dist/behaviors/tabs.d.mts +3 -2
  130. package/dist/behaviors/tabs.mjs +65 -14
  131. package/dist/behaviors/tag-input.d.mts +5 -2
  132. package/dist/behaviors/tag-input.mjs +61 -21
  133. package/dist/behaviors/theme.d.mts +13 -2
  134. package/dist/behaviors/theme.mjs +48 -4
  135. package/dist/behaviors/toast.d.mts +30 -8
  136. package/dist/behaviors/toast.mjs +74 -7
  137. package/dist/behaviors/tree.d.mts +5 -2
  138. package/dist/behaviors/tree.mjs +38 -15
  139. package/dist/behaviors/upload.mjs +21 -23
  140. package/dist/cli.mjs +1 -1
  141. package/dist/components/ai-branch.mjs +3 -0
  142. package/dist/components/ai-chat.css +295 -0
  143. package/dist/components/ai-feedback.mjs +3 -0
  144. package/dist/components/ai-panel.css +218 -1
  145. package/dist/components/ai-threads.mjs +3 -0
  146. package/dist/components/ai-tool-call.mjs +1 -1
  147. package/dist/components/badge.css +1 -1
  148. package/dist/components/breadcrumb.css +0 -32
  149. package/dist/components/chart-calendar.mjs +1 -2
  150. package/dist/components/chart-graph.css +57 -0
  151. package/dist/components/chart-graph.mjs +4 -0
  152. package/dist/components/chart-map.mjs +3 -0
  153. package/dist/components/chart-pie.css +0 -6
  154. package/dist/components/chart-scatter.mjs +1 -1
  155. package/dist/components/charts.css +33 -1
  156. package/dist/components/charts.mjs +1 -0
  157. package/dist/components/content.css +3 -16
  158. package/dist/components/datatable.css +1 -1
  159. package/dist/components/date-picker.css +1 -1
  160. package/dist/components/kb-access.mjs +4 -0
  161. package/dist/components/kb-acl.mjs +4 -0
  162. package/dist/components/kb-agent.css +481 -0
  163. package/dist/components/kb-answer.mjs +4 -0
  164. package/dist/components/kb-audit.mjs +4 -0
  165. package/dist/components/kb-canvas.mjs +4 -0
  166. package/dist/components/kb-chain.mjs +4 -0
  167. package/dist/components/kb-checkpoint.mjs +4 -0
  168. package/dist/components/kb-chunks.mjs +4 -0
  169. package/dist/components/kb-citation.mjs +4 -0
  170. package/dist/components/kb-clarify.mjs +4 -0
  171. package/dist/components/kb-conflict.mjs +4 -0
  172. package/dist/components/kb-connector.mjs +4 -0
  173. package/dist/components/kb-data.css +649 -0
  174. package/dist/components/kb-eval.mjs +4 -0
  175. package/dist/components/kb-explain.mjs +4 -0
  176. package/dist/components/kb-filter.mjs +4 -0
  177. package/dist/components/kb-gap.mjs +4 -0
  178. package/dist/components/kb-ground.css +566 -0
  179. package/dist/components/kb-hittest.mjs +4 -0
  180. package/dist/components/kb-ingest.css +898 -0
  181. package/dist/components/kb-metadata.mjs +4 -0
  182. package/dist/components/kb-ops.css +548 -0
  183. package/dist/components/kb-passage.mjs +4 -0
  184. package/dist/components/kb-perm.css +444 -0
  185. package/dist/components/kb-pipeline.mjs +4 -0
  186. package/dist/components/kb-qa.mjs +4 -0
  187. package/dist/components/kb-rerank.mjs +4 -0
  188. package/dist/components/kb-retrieval.mjs +4 -0
  189. package/dist/components/kb-review.mjs +4 -0
  190. package/dist/components/kb-sandbox.mjs +4 -0
  191. package/dist/components/kb-search.css +940 -0
  192. package/dist/components/kb-segment.mjs +4 -0
  193. package/dist/components/kb-sources.mjs +4 -0
  194. package/dist/components/kb-sql.mjs +4 -0
  195. package/dist/components/kb-trace.mjs +4 -0
  196. package/dist/components/kb-visibility.mjs +4 -0
  197. package/dist/components/kb-who-can.mjs +4 -0
  198. package/dist/components/kb.css +252 -0
  199. package/dist/components/kb.mjs +9 -0
  200. package/dist/components/notification.css +2 -3
  201. package/dist/components/pagination.css +3 -1
  202. package/dist/components/pagination.mjs +1 -0
  203. package/dist/components/rating.mjs +1 -0
  204. package/dist/components/segmented.css +9 -1
  205. package/dist/components/segmented.mjs +1 -1
  206. package/dist/components/select.css +67 -4
  207. package/dist/components/steps.css +13 -3
  208. package/dist/components/steps.mjs +1 -0
  209. package/dist/components/switch.css +3 -1
  210. package/dist/components/switch.mjs +1 -0
  211. package/dist/components/table.mjs +1 -0
  212. package/dist/components/tabs.css +23 -0
  213. package/dist/components/tag-input.css +1 -6
  214. package/dist/components/upload.css +0 -15
  215. package/dist/index.d.mts +48 -11
  216. package/dist/index.mjs +13205 -3615
  217. package/dist/registry.json +366 -15
  218. package/dist/retro-effects.css +3 -16
  219. package/dist/tokens/retro-effects.css +3 -16
  220. package/dist/tokens/style-profiles.css +3 -2
  221. package/dist/tokens/typography.css +2 -0
  222. package/dist/tokens.css +5 -2
  223. package/dist/ui.css +5713 -267
  224. package/docs/research/2026-10-03-ai-kb-components.md +392 -0
  225. package/docs/research/2026-10-03-kb-permissions.md +992 -0
  226. package/docs/spec/ai-native.md +7 -4
  227. package/docs/spec/kb-family.md +443 -0
  228. package/package.json +2 -2
@@ -0,0 +1,890 @@
1
+ // 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
+ );
50
+ function isObj(v) {
51
+ return typeof v === "object" && v !== null;
52
+ }
53
+ function pickStr(input, keys) {
54
+ if (!isObj(input)) return void 0;
55
+ for (const k of keys) {
56
+ const v = input[k];
57
+ if (typeof v === "string" && v) return v;
58
+ }
59
+ return void 0;
60
+ }
61
+ function pickNum(src, keys) {
62
+ if (!isObj(src)) return void 0;
63
+ for (const k of keys) {
64
+ const v = src[k];
65
+ if (typeof v === "number" && Number.isFinite(v)) return v;
66
+ }
67
+ return void 0;
68
+ }
69
+ function firstLine(s, max = 80) {
70
+ const line = s.split("\n", 1)[0]?.trim() ?? "";
71
+ return line.length > max ? `${line.slice(0, max)}\u2026` : line;
72
+ }
73
+ function filePathOf(input) {
74
+ return pickStr(input, ["file_path", "path", "file", "filename"]);
75
+ }
76
+ var summarizePath = (input) => filePathOf(input);
77
+ function summarizeRead(input) {
78
+ const p = filePathOf(input);
79
+ if (!p) return void 0;
80
+ const offset = pickNum(input, ["offset", "start_line"]);
81
+ if (offset == null) return p;
82
+ const limit = pickNum(input, ["limit", "end_line"]);
83
+ return limit != null ? `${p}:${offset}-${offset + limit}` : `${p}:${offset}`;
84
+ }
85
+ function summarizeShell(input) {
86
+ const cmd = typeof input === "string" ? input : pickStr(input, ["command", "cmd", "script"]);
87
+ return cmd ? firstLine(cmd) : void 0;
88
+ }
89
+ function summarizeGrep(input) {
90
+ const pattern = pickStr(input, ["pattern", "regex", "query"]);
91
+ const p = filePathOf(input);
92
+ if (pattern) return p ? `${firstLine(pattern, 40)} \xB7 ${p}` : firstLine(pattern);
93
+ return p;
94
+ }
95
+ var sum = (fn) => {
96
+ return (input) => fn(input) ?? "";
97
+ };
98
+ 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"])) },
109
+ 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"])) },
111
+ todo: {
112
+ label: "\u5F85\u529E",
113
+ icon: ICON_LIST,
114
+ tint: "info",
115
+ summarize: sum((input) => {
116
+ const items = input && typeof input === "object" && Array.isArray(input.items) ? input.items : Array.isArray(input) ? input : [];
117
+ const done = items.filter((it) => it?.status === "done").length;
118
+ return items.length > 0 ? `${done}/${items.length} \u5B8C\u6210` : "";
119
+ })
120
+ },
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"])) }
125
+ };
126
+ var kindRegistry = new Map(Object.entries(BUILTIN_KINDS));
127
+ function h(tag, className, text) {
128
+ const node = document.createElement(tag);
129
+ if (className) node.className = className;
130
+ if (text != null) node.textContent = text;
131
+ return node;
132
+ }
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);
164
+ }
165
+
166
+ // src/behaviors/kb-core.ts
167
+ 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
+ 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"/>')
179
+ };
180
+ var sourceTypeRegistry = new Map(Object.entries(BUILTIN_SOURCE_TYPES));
181
+ function registerKbSourceType(name, def) {
182
+ sourceTypeRegistry.set(name, def);
183
+ }
184
+ function unregisterKbSourceType(name) {
185
+ if (!Object.prototype.hasOwnProperty.call(BUILTIN_SOURCE_TYPES, name)) sourceTypeRegistry.delete(name);
186
+ }
187
+ function getKbSourceType(name) {
188
+ if (name) return sourceTypeRegistry.get(name) ?? BUILTIN_SOURCE_TYPES.doc;
189
+ return BUILTIN_SOURCE_TYPES.doc;
190
+ }
191
+ function listKbSourceTypes() {
192
+ return [...sourceTypeRegistry.keys()];
193
+ }
194
+ function normalizeCitation(raw) {
195
+ const r = raw;
196
+ const score = typeof r.score === "number" && Number.isFinite(r.score) ? r.score : r.score == null ? null : null;
197
+ return {
198
+ id: String(r.id ?? ""),
199
+ index: typeof r.index === "number" ? r.index : void 0,
200
+ title: String(r.title ?? "\u672A\u547D\u540D\u6765\u6E90"),
201
+ url: typeof r.url === "string" && r.url ? r.url : void 0,
202
+ kind: typeof r.kind === "string" ? r.kind : void 0,
203
+ citedText: typeof r.citedText === "string" ? r.citedText : void 0,
204
+ snippet: typeof r.snippet === "string" ? r.snippet : void 0,
205
+ date: typeof r.date === "string" ? r.date : void 0,
206
+ score: score === void 0 ? null : score,
207
+ scoreKind: r.scoreKind,
208
+ official: r.official === true,
209
+ permission: r.permission === "restricted" || r.permission === "requestable" ? r.permission : "readable",
210
+ owner: typeof r.owner === "string" ? r.owner : void 0,
211
+ loc: r.loc,
212
+ documentId: typeof r.documentId === "string" ? r.documentId : void 0,
213
+ useCount: typeof r.useCount === "number" ? r.useCount : void 0
214
+ };
215
+ }
216
+ var CITE_RE = /\[(\d{1,3})\]/g;
217
+ function parseInlineCitations(text) {
218
+ const out = [];
219
+ if (!text) return out;
220
+ let last = 0;
221
+ CITE_RE.lastIndex = 0;
222
+ let m;
223
+ while ((m = CITE_RE.exec(text)) !== null) {
224
+ if (m.index > last) out.push({ text: text.slice(last, m.index) });
225
+ out.push({ text: m[0], n: Number(m[1]) });
226
+ last = m.index + m[0].length;
227
+ }
228
+ if (last < text.length) out.push({ text: text.slice(last) });
229
+ return out;
230
+ }
231
+ function collectCitationNumbers(text) {
232
+ return parseInlineCitations(text).filter((s) => typeof s.n === "number").map((s) => s.n);
233
+ }
234
+ var KB_SCORE_KINDS = [
235
+ "cosine",
236
+ "dot",
237
+ "ip",
238
+ "l2",
239
+ "bm25",
240
+ "rrf",
241
+ "dbsf",
242
+ "rerank",
243
+ "hybrid"
244
+ ];
245
+ var LOWER_IS_BETTER = /* @__PURE__ */ new Set(["l2"]);
246
+ function scoreHigherIsBetter(kind) {
247
+ return kind != null && LOWER_IS_BETTER.has(kind) ? false : true;
248
+ }
249
+ function formatScore(v, digits = 3) {
250
+ if (v == null || !Number.isFinite(v)) return "\u2014";
251
+ return v.toFixed(digits).replace(/\.?0+$/, (s) => s.includes(".") ? "" : s);
252
+ }
253
+ function scorePercent(v, kind, max = 1) {
254
+ if (v == null || !Number.isFinite(v)) return null;
255
+ const pct = scoreHigherIsBetter(kind) ? v / max * 100 : (1 - v / max) * 100;
256
+ return Math.max(0, Math.min(100, pct));
257
+ }
258
+ function normalizeChunk(raw) {
259
+ const kw = Array.isArray(raw.keywords) ? raw.keywords.map(String) : void 0;
260
+ return {
261
+ id: String(raw.id ?? ""),
262
+ documentId: String(raw.documentId ?? ""),
263
+ content: String(raw.content ?? ""),
264
+ keywords: kw && kw.length ? kw : void 0,
265
+ available: raw.available !== false,
266
+ page: typeof raw.page === "number" ? raw.page : void 0,
267
+ start: typeof raw.start === "number" ? raw.start : void 0,
268
+ end: typeof raw.end === "number" ? raw.end : void 0,
269
+ imageId: typeof raw.imageId === "string" ? raw.imageId : void 0,
270
+ meta: raw.meta && typeof raw.meta === "object" ? raw.meta : void 0,
271
+ edited: raw.edited === true
272
+ };
273
+ }
274
+ var KB_RUN_STATUSES = ["unstart", "queued", "running", "cancel", "done", "fail"];
275
+ var RUN_LABELS = {
276
+ unstart: "\u672A\u5F00\u59CB",
277
+ queued: "\u6392\u961F\u4E2D",
278
+ running: "\u8FDB\u884C\u4E2D",
279
+ cancel: "\u5DF2\u53D6\u6D88",
280
+ done: "\u5DF2\u5B8C\u6210",
281
+ fail: "\u5931\u8D25"
282
+ };
283
+ function kbRunStatusLabel(s) {
284
+ return RUN_LABELS[s] ?? s;
285
+ }
286
+ var STEP = (raw) => ({
287
+ key: String(raw.key ?? ""),
288
+ label: String(raw.label ?? raw.key ?? ""),
289
+ status: KB_RUN_STATUSES.includes(raw.status) ? raw.status : "unstart",
290
+ detail: typeof raw.detail === "string" ? raw.detail : void 0,
291
+ elapsedMs: typeof raw.elapsedMs === "number" ? raw.elapsedMs : void 0,
292
+ count: typeof raw.count === "number" ? raw.count : void 0
293
+ });
294
+ function normalizePipelineRun(raw) {
295
+ const steps = Array.isArray(raw.steps) ? raw.steps.map((s) => STEP(s)) : [];
296
+ return {
297
+ documentId: String(raw.documentId ?? ""),
298
+ title: typeof raw.title === "string" ? raw.title : void 0,
299
+ status: KB_RUN_STATUSES.includes(raw.status) ? raw.status : "unstart",
300
+ progress: typeof raw.progress === "number" ? Math.max(0, Math.min(100, raw.progress)) : void 0,
301
+ steps,
302
+ chunkCount: typeof raw.chunkCount === "number" ? raw.chunkCount : void 0,
303
+ elapsedMs: typeof raw.elapsedMs === "number" ? raw.elapsedMs : void 0,
304
+ error: raw.error && typeof raw.error === "object" ? { stage: typeof raw.error.stage === "string" ? raw.error.stage : void 0, message: String(raw.error.message ?? "") } : void 0
305
+ };
306
+ }
307
+ function normalizeConnector(raw) {
308
+ return {
309
+ id: String(raw.id ?? ""),
310
+ name: String(raw.name ?? ""),
311
+ kind: typeof raw.kind === "string" ? raw.kind : void 0,
312
+ scope: typeof raw.scope === "string" ? raw.scope : void 0,
313
+ enabled: raw.enabled !== false,
314
+ lastSyncAt: typeof raw.lastSyncAt === "string" ? raw.lastSyncAt : void 0,
315
+ lastCrawlStatus: raw.lastCrawlStatus === "ok" || raw.lastCrawlStatus === "fail" ? raw.lastCrawlStatus : "none",
316
+ itemsSynced: typeof raw.itemsSynced === "number" ? raw.itemsSynced : void 0,
317
+ crawlRate: typeof raw.crawlRate === "number" ? raw.crawlRate : void 0,
318
+ changeRate: typeof raw.changeRate === "number" ? raw.changeRate : void 0,
319
+ credential: raw.credential === "expired" || raw.credential === "none" ? raw.credential : "ok",
320
+ schedule: typeof raw.schedule === "string" ? raw.schedule : void 0,
321
+ metrics: raw.metrics && typeof raw.metrics === "object" ? raw.metrics : void 0
322
+ };
323
+ }
324
+ function connectorHealth(c, now = /* @__PURE__ */ new Date()) {
325
+ if (!c.enabled) return "off";
326
+ if (c.lastCrawlStatus === "fail" || c.credential === "expired" || c.credential === "none") return "failing";
327
+ const last = c.lastSyncAt ? Date.parse(c.lastSyncAt) : NaN;
328
+ const staleMs = 24 * 60 * 60 * 1e3;
329
+ if (!Number.isFinite(last) || now.getTime() - last > staleMs) return "stale";
330
+ return "healthy";
331
+ }
332
+ var KB_CLEAN_OPTIONS = ["collapse-blank", "strip-url", "strip-email"];
333
+ function normalizeSegmentConfig(raw) {
334
+ const r = raw ?? {};
335
+ return {
336
+ mode: r.mode === "custom" || r.mode === "parent-child" ? r.mode : "auto",
337
+ delimiter: typeof r.delimiter === "string" && r.delimiter ? r.delimiter : r.mode === "custom" || r.mode === "parent-child" ? void 0 : "\n\n",
338
+ maxLength: typeof r.maxLength === "number" && r.maxLength > 0 ? Math.floor(r.maxLength) : 500,
339
+ overlap: typeof r.overlap === "number" && r.overlap >= 0 ? Math.floor(r.overlap) : 50,
340
+ clean: Array.isArray(r.clean) ? r.clean.filter((c) => KB_CLEAN_OPTIONS.includes(c)) : [],
341
+ locked: r.locked === true
342
+ };
343
+ }
344
+ var URL_RE = /https?:\/\/\S+/g;
345
+ var EMAIL_RE = /[\w.+-]+@[\w-]+\.[\w.]+/g;
346
+ function cleanText(text, clean) {
347
+ let out = text;
348
+ if (clean.includes("collapse-blank")) out = out.replace(/\n{3,}/g, "\n\n");
349
+ if (clean.includes("strip-url")) out = out.replace(URL_RE, "");
350
+ if (clean.includes("strip-email")) out = out.replace(EMAIL_RE, "");
351
+ return out;
352
+ }
353
+ function delimiterToRe(delim) {
354
+ const literal = delim.replace(/\\n/g, "\n").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
355
+ return new RegExp(literal, "g");
356
+ }
357
+ function segmentText(text, config) {
358
+ const cfg = normalizeSegmentConfig(config);
359
+ const cleaned = cleanText(text ?? "", cfg.clean);
360
+ if (!cleaned.trim()) return [];
361
+ const parts = [];
362
+ if (cfg.mode === "custom" || cfg.mode === "parent-child" || cfg.mode === "auto" && cfg.delimiter) {
363
+ const re = delimiterToRe(cfg.delimiter ?? "\n\n");
364
+ for (const seg of cleaned.split(re)) {
365
+ const s = seg.trim();
366
+ if (s) parts.push(s);
367
+ }
368
+ } else {
369
+ parts.push(cleaned.trim());
370
+ }
371
+ if (cfg.mode === "parent-child") return parts;
372
+ const out = [];
373
+ for (const p of parts) {
374
+ if (p.length <= cfg.maxLength) {
375
+ out.push(p);
376
+ continue;
377
+ }
378
+ const overlap = Math.min(cfg.overlap, Math.max(0, cfg.maxLength - 1));
379
+ for (let i = 0; i < p.length; i += cfg.maxLength - overlap) {
380
+ out.push(p.slice(i, i + cfg.maxLength));
381
+ if (i + cfg.maxLength >= p.length) break;
382
+ }
383
+ }
384
+ return out;
385
+ }
386
+ function segmentStats(chunks) {
387
+ const count = chunks.length;
388
+ const total = chunks.reduce((n, c) => n + c.length, 0);
389
+ return { count, avgLength: count ? Math.round(total / count) : 0, tokensEstimate: Math.round(total / 2) };
390
+ }
391
+ function normalizeHit(raw) {
392
+ const score = typeof raw.score === "number" && Number.isFinite(raw.score) ? raw.score : null;
393
+ return {
394
+ chunkId: String(raw.chunkId ?? raw.id ?? ""),
395
+ documentId: typeof raw.documentId === "string" ? raw.documentId : void 0,
396
+ title: typeof raw.title === "string" ? raw.title : void 0,
397
+ snippet: String(raw.snippet ?? raw.content ?? ""),
398
+ score,
399
+ scoreKind: raw.scoreKind,
400
+ vectorPart: typeof raw.vectorPart === "number" ? raw.vectorPart : void 0,
401
+ keywordPart: typeof raw.keywordPart === "number" ? raw.keywordPart : void 0,
402
+ explain: typeof raw.explain === "string" ? raw.explain : void 0,
403
+ page: typeof raw.page === "number" ? raw.page : void 0,
404
+ meta: raw.meta && typeof raw.meta === "object" ? raw.meta : void 0
405
+ };
406
+ }
407
+ function normalizeRetrievalParams(raw) {
408
+ const r = raw ?? {};
409
+ return {
410
+ topK: typeof r.topK === "number" && r.topK > 0 ? Math.floor(r.topK) : 5,
411
+ mode: r.mode === "vector" || r.mode === "keyword" || r.mode === "hybrid" ? r.mode : "hybrid",
412
+ alpha: typeof r.alpha === "number" ? Math.max(0, Math.min(1, r.alpha)) : 0.5,
413
+ rerank: r.rerank === true,
414
+ rerankModel: typeof r.rerankModel === "string" ? r.rerankModel : void 0,
415
+ threshold: typeof r.threshold === "number" ? r.threshold : null
416
+ };
417
+ }
418
+ var KB_FILTER_OPS = ["eq", "ne", "gt", "gte", "lt", "lte", "in", "contains", "exists"];
419
+ function normalizeFilterNode(raw) {
420
+ if (!raw || typeof raw !== "object") return null;
421
+ const r = raw;
422
+ if (r.type === "group") {
423
+ const children = Array.isArray(r.children) ? r.children.map(normalizeFilterNode).filter((c) => c !== null) : [];
424
+ return children.length ? { type: "group", op: r.op === "or" ? "or" : "and", children } : null;
425
+ }
426
+ if (r.type === "rule") {
427
+ const field = String(r.field ?? "").trim();
428
+ const op = KB_FILTER_OPS.includes(r.op) ? r.op : null;
429
+ if (!field || !op) return null;
430
+ let value;
431
+ if (Array.isArray(r.value)) value = r.value.map((v) => typeof v === "number" ? v : String(v));
432
+ else if (typeof r.value === "number" || typeof r.value === "string" || typeof r.value === "boolean") value = r.value;
433
+ return { type: "rule", field, op, value };
434
+ }
435
+ return null;
436
+ }
437
+ var MONGO_OP = {
438
+ eq: "$eq",
439
+ ne: "$ne",
440
+ gt: "$gt",
441
+ gte: "$gte",
442
+ lt: "$lt",
443
+ lte: "$lte",
444
+ in: "$in",
445
+ contains: "$regex",
446
+ exists: "$exists"
447
+ };
448
+ function filterToMongo(node) {
449
+ const n = normalizeFilterNode(node);
450
+ if (!n) return null;
451
+ if (n.type === "group") {
452
+ const key = n.op === "or" ? "$or" : "$and";
453
+ return { [key]: n.children.map((c) => filterToMongo(c) ?? {}) };
454
+ }
455
+ if (n.op === "exists") return { [n.field]: { $exists: n.value !== false } };
456
+ if (n.op === "contains") {
457
+ const v = Array.isArray(n.value) ? String(n.value[0] ?? "") : String(n.value ?? "");
458
+ return { [n.field]: { $regex: v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), $options: "i" } };
459
+ }
460
+ const mk = MONGO_OP[n.op];
461
+ if (!mk) return null;
462
+ const value = Array.isArray(n.value) ? n.value : n.value ?? "";
463
+ return { [n.field]: { [mk]: value } };
464
+ }
465
+ function odataQuote(v) {
466
+ return typeof v === "number" ? String(v) : `'${String(v).replace(/'/g, "''")}'`;
467
+ }
468
+ var ODATA_OP = {
469
+ eq: "eq",
470
+ ne: "ne",
471
+ gt: "gt",
472
+ gte: "ge",
473
+ lt: "lt",
474
+ lte: "le",
475
+ in: "in",
476
+ contains: "contains",
477
+ exists: "exists"
478
+ };
479
+ function filterToOData(node) {
480
+ const n = normalizeFilterNode(node);
481
+ if (!n) return "";
482
+ if (n.type === "group") {
483
+ const join = n.op === "or" ? " or " : " and ";
484
+ return n.children.map((c) => `(${filterToOData(c)})`).join(join);
485
+ }
486
+ if (n.op === "contains") {
487
+ const v = Array.isArray(n.value) ? String(n.value[0] ?? "") : String(n.value ?? "");
488
+ return `contains(${n.field},${odataQuote(v)})`;
489
+ }
490
+ if (n.op === "in") {
491
+ const list = Array.isArray(n.value) ? n.value : [typeof n.value === "number" ? n.value : String(n.value ?? "")];
492
+ return `${n.field} in (${list.map(odataQuote).join(",")})`;
493
+ }
494
+ if (n.op === "exists") return n.value === false ? `${n.field} eq null` : `${n.field} ne null`;
495
+ const raw = Array.isArray(n.value) ? n.value[0] : n.value;
496
+ const value = typeof raw === "number" ? raw : String(raw ?? "");
497
+ return `${n.field} ${ODATA_OP[n.op]} ${odataQuote(value)}`;
498
+ }
499
+ function rerankDelta(item) {
500
+ if (!item.before || !item.after) return null;
501
+ return item.after.rank - item.before.rank;
502
+ }
503
+ function hitTestStats(cases) {
504
+ const ran = cases.filter((c) => c.passed !== void 0);
505
+ const passed = ran.filter((c) => c.passed === true);
506
+ const scores = ran.flatMap((c) => (c.lastHits ?? []).map((h2) => h2.score)).filter((s) => typeof s === "number");
507
+ return {
508
+ total: cases.length,
509
+ passed: passed.length,
510
+ hitRate: ran.length ? passed.length / ran.length : null,
511
+ avgScore: scores.length ? scores.reduce((a, b) => a + b, 0) / scores.length : null
512
+ };
513
+ }
514
+ function normalizeSqlQuery(raw) {
515
+ return {
516
+ sql: String(raw.sql ?? ""),
517
+ dialect: typeof raw.dialect === "string" ? raw.dialect : void 0,
518
+ tables: Array.isArray(raw.tables) ? raw.tables.map(String) : void 0,
519
+ visibility: raw.visibility === "admin" ? "admin" : "all",
520
+ editable: raw.editable !== false,
521
+ prevSql: typeof raw.prevSql === "string" ? raw.prevSql : void 0,
522
+ reasoning: typeof raw.reasoning === "string" ? raw.reasoning : void 0
523
+ };
524
+ }
525
+ function normalizeQueryResult(raw) {
526
+ const columns = Array.isArray(raw.columns) ? raw.columns.map((c) => typeof c === "string" ? { name: c } : { name: String(c.name ?? ""), type: c.type }) : [];
527
+ return {
528
+ columns,
529
+ rows: Array.isArray(raw.rows) ? raw.rows.map((r) => Array.isArray(r) ? r.map((v) => typeof v === "number" || typeof v === "string" ? v : null) : []) : [],
530
+ totalRows: typeof raw.totalRows === "number" ? raw.totalRows : void 0,
531
+ truncated: raw.truncated === true,
532
+ limit: typeof raw.limit === "number" ? raw.limit : void 0,
533
+ rowCount: typeof raw.rowCount === "number" ? raw.rowCount : Array.isArray(raw.rows) ? raw.rows.length : 0,
534
+ durationMs: typeof raw.durationMs === "number" ? raw.durationMs : void 0,
535
+ exportFormats: Array.isArray(raw.exportFormats) ? raw.exportFormats.map(String) : void 0
536
+ };
537
+ }
538
+ var KB_SPAN_KINDS = [
539
+ "retrieval",
540
+ "generation",
541
+ "rerank",
542
+ "embed",
543
+ "tool",
544
+ "guard",
545
+ "chunk",
546
+ "query",
547
+ "agent"
548
+ ];
549
+ var SPAN_LABELS = {
550
+ retrieval: "\u68C0\u7D22",
551
+ generation: "\u751F\u6210",
552
+ rerank: "\u91CD\u6392",
553
+ embed: "\u5411\u91CF\u5316",
554
+ tool: "\u5DE5\u5177",
555
+ guard: "\u62A4\u680F",
556
+ chunk: "\u5207\u7247",
557
+ query: "\u67E5\u8BE2",
558
+ agent: "\u4EE3\u7406"
559
+ };
560
+ function kbSpanKindLabel(k) {
561
+ return SPAN_LABELS[k] ?? k;
562
+ }
563
+ var KB_SPAN_STATUSES = ["running", "done", "error", "cancel"];
564
+ function toSpanStatus(v) {
565
+ return v === "running" || v === "error" || v === "cancel" ? v : "done";
566
+ }
567
+ function normalizeSpans(raw) {
568
+ const spans = raw.map((r) => ({
569
+ id: String(r.id ?? ""),
570
+ parentId: typeof r.parentId === "string" ? r.parentId : void 0,
571
+ kind: KB_SPAN_KINDS.includes(r.kind) ? r.kind : "tool",
572
+ name: String(r.name ?? ""),
573
+ status: toSpanStatus(r.status),
574
+ startedAt: typeof r.startedAt === "number" || typeof r.startedAt === "string" ? r.startedAt : void 0,
575
+ elapsedMs: typeof r.elapsedMs === "number" ? r.elapsedMs : void 0,
576
+ detail: typeof r.detail === "string" ? r.detail : void 0,
577
+ usage: r.usage && typeof r.usage === "object" ? r.usage : void 0,
578
+ hits: Array.isArray(r.hits) ? r.hits.map((h2) => normalizeHit(h2)) : void 0,
579
+ error: typeof r.error === "string" ? r.error : void 0
580
+ })).filter((s) => s.id);
581
+ const byId = new Map(spans.map((s) => [s.id, s]));
582
+ return [...spans].sort((a, b) => {
583
+ const da = depthOf(a, byId, 0);
584
+ const db = depthOf(b, byId, 0);
585
+ return da === db ? indexIn(spans, a) - indexIn(spans, b) : da - db;
586
+ });
587
+ }
588
+ function depthOf(span, byId, guard) {
589
+ if (guard > 32 || !span.parentId) return 0;
590
+ const parent = byId.get(span.parentId);
591
+ return parent ? depthOf(parent, byId, guard + 1) + 1 : 0;
592
+ }
593
+ function indexIn(spans, target) {
594
+ const i = spans.findIndex((s) => s.id === target.id);
595
+ return i === -1 ? spans.length : i;
596
+ }
597
+ function evalGrade(scoreDelta, costDeltaPct, latencyDeltaPct) {
598
+ if (scoreDelta == null || Math.abs(scoreDelta) < 1e-9) {
599
+ if (scoreDelta == null) return "tie";
600
+ const worse = costDeltaPct != null && costDeltaPct > 5 || latencyDeltaPct != null && latencyDeltaPct > 15;
601
+ return worse ? "tradeoff" : "tie";
602
+ }
603
+ if (scoreDelta > 0) {
604
+ const worse = costDeltaPct != null && costDeltaPct > 5 || latencyDeltaPct != null && latencyDeltaPct > 15;
605
+ return worse ? "tradeoff" : "improvement";
606
+ }
607
+ return "regression";
608
+ }
609
+ function meanScore(scores) {
610
+ if (!scores) return null;
611
+ const vals = Object.values(scores).filter((v) => typeof v === "number");
612
+ return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
613
+ }
614
+ function deltaLabel(v, digits = 1) {
615
+ if (v == null || !Number.isFinite(v)) return "\u2014";
616
+ const s = v.toFixed(digits);
617
+ return v > 0 ? `+${s}` : s;
618
+ }
619
+ var KB_ROLES = ["viewer", "commenter", "editor", "owner"];
620
+ function kbRoleLabel(r) {
621
+ return r === "viewer" ? "\u53EF\u67E5\u770B" : r === "commenter" ? "\u53EF\u8BC4\u8BBA" : r === "editor" ? "\u53EF\u7F16\u8F91" : r === "owner" ? "\u8D1F\u8D23\u4EBA" : "\u65E0\u6743\u9650";
622
+ }
623
+ function roleAtLeast(role, floor) {
624
+ return KB_ROLES.indexOf(role) >= KB_ROLES.indexOf(floor);
625
+ }
626
+ var KB_VISIBILITIES = ["hidden", "metadata", "restricted", "summary", "full"];
627
+ function kbVisibilityLabel(v) {
628
+ return v === "hidden" ? "\u4E0D\u53EF\u89C1" : v === "metadata" ? "\u4EC5\u5143\u6570\u636E" : v === "restricted" ? "\u53D7\u9650" : v === "summary" ? "\u4EC5\u6458\u8981" : "\u53EF\u89C1";
629
+ }
630
+ function normalizeAclEntry(raw) {
631
+ const r = raw;
632
+ const s = r.subject ?? {};
633
+ const kind = s.kind === "user" || s.kind === "group" || s.kind === "org" || s.kind === "anyone" || s.kind === "link" ? s.kind : "user";
634
+ return {
635
+ subject: { kind, id: String(s.id ?? ""), label: String(s.label ?? "\u672A\u547D\u540D\u4E3B\u4F53"), note: typeof s.note === "string" ? s.note : void 0 },
636
+ role: KB_ROLES.includes(r.role) ? r.role : "viewer",
637
+ inheritedFrom: typeof r.inheritedFrom === "string" && r.inheritedFrom ? r.inheritedFrom : void 0,
638
+ expiresAt: typeof r.expiresAt === "string" && r.expiresAt ? r.expiresAt : void 0,
639
+ deny: r.deny === true,
640
+ system: r.system === true
641
+ };
642
+ }
643
+ function normalizeIdentity(raw) {
644
+ const r = raw;
645
+ return {
646
+ user: String(r.user ?? ""),
647
+ groups: Array.isArray(r.groups) ? r.groups.map(String) : [],
648
+ label: typeof r.label === "string" ? r.label : void 0,
649
+ note: typeof r.note === "string" ? r.note : void 0
650
+ };
651
+ }
652
+ function visibilityForRole(role, policy) {
653
+ if (role) return "full";
654
+ if (policy?.summaryAllowed === true) return "summary";
655
+ return policy?.discoverable === false ? "hidden" : "metadata";
656
+ }
657
+ function subjectMatches(subject, identity) {
658
+ if (subject.kind === "user") return subject.id === identity.user || subject.label === identity.user;
659
+ if (subject.kind === "group") return identity.groups.includes(subject.id) || identity.groups.includes(subject.label);
660
+ if (subject.kind === "org" || subject.kind === "anyone") return true;
661
+ return false;
662
+ }
663
+ function evaluateAcl(entries, identity, policy) {
664
+ const list = (Array.isArray(entries) ? entries : []).map((e) => normalizeAclEntry(e));
665
+ const id = normalizeIdentity(identity);
666
+ const matched = list.filter((e) => subjectMatches(e.subject, id));
667
+ const chain = matched.map((entry) => ({
668
+ entry,
669
+ via: entry.subject.kind === "link" ? "link" : entry.inheritedFrom ? "inherit" : "direct"
670
+ }));
671
+ const deny = matched.find((e) => e.deny);
672
+ if (deny) {
673
+ return { role: null, visibility: visibilityForRole(null, { ...policy, summaryAllowed: false }), chain, deniedBy: deny.subject };
674
+ }
675
+ const grants = matched.filter((e) => !e.deny);
676
+ const role = grants.reduce((acc, e) => acc && roleAtLeast(acc, e.role) ? acc : e.role, null);
677
+ const futureExpiry = grants.map((e) => Date.parse(e.expiresAt ?? "")).filter((t) => Number.isFinite(t) && t > Date.now()).sort((a, b) => a - b)[0];
678
+ return {
679
+ role,
680
+ visibility: visibilityForRole(role, policy),
681
+ chain,
682
+ expiresAt: Number.isFinite(futureExpiry) ? new Date(futureExpiry).toISOString() : void 0
683
+ };
684
+ }
685
+ var KB_ACCESS_STATES = [
686
+ "idle",
687
+ "requested",
688
+ "pending_review",
689
+ "granted",
690
+ "expiring",
691
+ "expired",
692
+ "denied",
693
+ "revoked"
694
+ ];
695
+ function kbAccessStateLabel(s) {
696
+ return {
697
+ idle: "\u672A\u7533\u8BF7",
698
+ requested: "\u5DF2\u63D0\u4EA4",
699
+ pending_review: "\u5F85\u5BA1\u6279",
700
+ granted: "\u5DF2\u5F00\u901A",
701
+ expiring: "\u5373\u5C06\u5230\u671F",
702
+ expired: "\u5DF2\u8FC7\u671F",
703
+ denied: "\u672A\u901A\u8FC7",
704
+ revoked: "\u5DF2\u6536\u56DE"
705
+ }[s] ?? s;
706
+ }
707
+ function normalizeAccessRequest(raw) {
708
+ const r = raw;
709
+ const state = KB_ACCESS_STATES.includes(r.state) ? r.state : "idle";
710
+ const str = (v) => typeof v === "string" && v ? v : void 0;
711
+ return {
712
+ id: String(r.id ?? ""),
713
+ requester: String(r.requester ?? ""),
714
+ resource: String(r.resource ?? ""),
715
+ role: KB_ROLES.includes(r.role) ? r.role : "viewer",
716
+ reason: str(r.reason),
717
+ state,
718
+ submittedAt: str(r.submittedAt) ?? (/* @__PURE__ */ new Date()).toISOString(),
719
+ approverNote: str(r.approverNote),
720
+ decidedBy: str(r.decidedBy),
721
+ decidedAt: str(r.decidedAt),
722
+ expiresAt: str(r.expiresAt)
723
+ };
724
+ }
725
+ var KB_AUDIT_ACTIONS = [
726
+ "read",
727
+ "preview",
728
+ "permission_change",
729
+ "grant",
730
+ "revoke",
731
+ "request",
732
+ "approve",
733
+ "deny",
734
+ "delegation",
735
+ "break_glass",
736
+ "sync"
737
+ ];
738
+ function kbAuditActionLabel(a) {
739
+ return {
740
+ read: "\u8BFB\u53D6",
741
+ preview: "\u9884\u89C8",
742
+ permission_change: "\u6743\u9650\u53D8\u66F4",
743
+ grant: "\u6388\u4E88",
744
+ revoke: "\u6536\u56DE",
745
+ request: "\u7533\u8BF7",
746
+ approve: "\u6279\u51C6",
747
+ deny: "\u62D2\u7EDD",
748
+ delegation: "\u59D4\u6D3E",
749
+ break_glass: "\u5E94\u6025\u8BBF\u95EE",
750
+ sync: "\u6743\u9650\u540C\u6B65"
751
+ }[a] ?? a;
752
+ }
753
+ var KB_AUDIT_CHANNELS = ["read", "permission", "request", "system"];
754
+ function auditChannelOf(a) {
755
+ if (a === "read" || a === "preview") return "read";
756
+ if (a === "permission_change" || a === "grant" || a === "revoke" || a === "delegation" || a === "sync") return "permission";
757
+ if (a === "request" || a === "approve" || a === "deny") return "request";
758
+ return "system";
759
+ }
760
+ function normalizeAuditEntry(raw) {
761
+ const r = raw;
762
+ const actor = r.actor ?? {};
763
+ const kind = actor.kind === "app" || actor.kind === "system" ? actor.kind : "human";
764
+ return {
765
+ id: String(r.id ?? ""),
766
+ at: String(r.at ?? ""),
767
+ actor: { kind, name: String(actor.name ?? "\u672A\u77E5") },
768
+ action: KB_AUDIT_ACTIONS.includes(r.action) ? r.action : "read",
769
+ resource: typeof r.resource === "string" && r.resource ? r.resource : void 0,
770
+ detail: String(r.detail ?? ""),
771
+ breakGlass: r.breakGlass === true
772
+ };
773
+ }
774
+ var KB_HYGIENE_KINDS = [
775
+ "org_wide_link",
776
+ "broad_group",
777
+ "sensitive_mismatch",
778
+ "broken_inheritance",
779
+ "orphaned_owner",
780
+ "overexposed"
781
+ ];
782
+ function kbHygieneLabel(k) {
783
+ return {
784
+ org_wide_link: "\u7EC4\u7EC7\u7EA7\u94FE\u63A5",
785
+ broad_group: "\u8FC7\u5BBD\u7EC4\u6388\u6743",
786
+ sensitive_mismatch: "\u654F\u611F\u5EA6\u9519\u914D",
787
+ broken_inheritance: "\u65AD\u7EE7\u627F",
788
+ orphaned_owner: "\u8D1F\u8D23\u4EBA\u7F3A\u4F4D",
789
+ overexposed: "\u8FC7\u5EA6\u66B4\u9732"
790
+ }[k] ?? k;
791
+ }
792
+ function normalizeHygieneIssue(raw) {
793
+ const r = raw;
794
+ const severity = r.severity === "high" || r.severity === "medium" || r.severity === "low" ? r.severity : "medium";
795
+ return {
796
+ id: String(r.id ?? ""),
797
+ kind: KB_HYGIENE_KINDS.includes(r.kind) ? r.kind : "overexposed",
798
+ resource: String(r.resource ?? ""),
799
+ metric: String(r.metric ?? ""),
800
+ hint: String(r.hint ?? ""),
801
+ severity
802
+ };
803
+ }
804
+ function formatPercent(v, digits = 1) {
805
+ if (v == null || !Number.isFinite(v)) return "\u2014";
806
+ return `${(v * 100).toFixed(digits)}%`;
807
+ }
808
+ function formatCount(n) {
809
+ if (n == null || !Number.isFinite(n)) return "\u2014";
810
+ if (Math.abs(n) >= 1e4) return `${(n / 1e3).toFixed(1)}k`;
811
+ return n.toLocaleString("en-US");
812
+ }
813
+ function relativeTime(input, now = /* @__PURE__ */ new Date()) {
814
+ const t = input instanceof Date ? input.getTime() : typeof input === "number" ? input : Date.parse(input);
815
+ if (!Number.isFinite(t)) return typeof input === "string" ? input : "\u2014";
816
+ const diff = now.getTime() - t;
817
+ const MIN = 6e4, HOUR = 36e5, DAY = 864e5;
818
+ if (diff < MIN) return "\u521A\u521A";
819
+ if (diff < HOUR) return `${Math.floor(diff / MIN)} \u5206\u949F\u524D`;
820
+ if (diff < DAY) return `${Math.floor(diff / HOUR)} \u5C0F\u65F6\u524D`;
821
+ if (diff < 30 * DAY) return `${Math.floor(diff / DAY)} \u5929\u524D`;
822
+ const d = new Date(t);
823
+ const ymd = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
824
+ return ymd;
825
+ }
826
+ export {
827
+ KB_ACCESS_STATES,
828
+ KB_AUDIT_ACTIONS,
829
+ KB_AUDIT_CHANNELS,
830
+ KB_CLEAN_OPTIONS,
831
+ KB_FILTER_OPS,
832
+ KB_HYGIENE_KINDS,
833
+ KB_ROLES,
834
+ KB_RUN_STATUSES,
835
+ KB_SCORE_KINDS,
836
+ KB_SPAN_KINDS,
837
+ KB_SPAN_STATUSES,
838
+ KB_VISIBILITIES,
839
+ auditChannelOf,
840
+ collectCitationNumbers,
841
+ connectorHealth,
842
+ deltaLabel,
843
+ evalGrade,
844
+ evaluateAcl,
845
+ filterToMongo,
846
+ filterToOData,
847
+ formatCount,
848
+ formatPercent,
849
+ formatScore,
850
+ getKbSourceType,
851
+ h,
852
+ hitTestStats,
853
+ kbAccessStateLabel,
854
+ kbAuditActionLabel,
855
+ kbHygieneLabel,
856
+ kbRoleLabel,
857
+ kbRunStatusLabel,
858
+ kbSpanKindLabel,
859
+ kbVisibilityLabel,
860
+ listKbSourceTypes,
861
+ meanScore,
862
+ normalizeAccessRequest,
863
+ normalizeAclEntry,
864
+ normalizeAuditEntry,
865
+ normalizeChunk,
866
+ normalizeCitation,
867
+ normalizeConnector,
868
+ normalizeFilterNode,
869
+ normalizeHit,
870
+ normalizeHygieneIssue,
871
+ normalizeIdentity,
872
+ normalizePipelineRun,
873
+ normalizeQueryResult,
874
+ normalizeRetrievalParams,
875
+ normalizeSegmentConfig,
876
+ normalizeSpans,
877
+ normalizeSqlQuery,
878
+ parseInlineCitations,
879
+ registerKbSourceType,
880
+ relativeTime,
881
+ rerankDelta,
882
+ roleAtLeast,
883
+ scoreHigherIsBetter,
884
+ scorePercent,
885
+ segmentStats,
886
+ segmentText,
887
+ svgIcon,
888
+ unregisterKbSourceType,
889
+ visibilityForRole
890
+ };