@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,475 @@
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(svg3) {
134
+ if (typeof document === "undefined" || typeof DOMParser === "undefined") return null;
135
+ let parsed;
136
+ try {
137
+ parsed = new DOMParser().parseFromString(svg3, "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 normalizeChunk(raw) {
182
+ const kw = Array.isArray(raw.keywords) ? raw.keywords.map(String) : void 0;
183
+ return {
184
+ id: String(raw.id ?? ""),
185
+ documentId: String(raw.documentId ?? ""),
186
+ content: String(raw.content ?? ""),
187
+ keywords: kw && kw.length ? kw : void 0,
188
+ available: raw.available !== false,
189
+ page: typeof raw.page === "number" ? raw.page : void 0,
190
+ start: typeof raw.start === "number" ? raw.start : void 0,
191
+ end: typeof raw.end === "number" ? raw.end : void 0,
192
+ imageId: typeof raw.imageId === "string" ? raw.imageId : void 0,
193
+ meta: raw.meta && typeof raw.meta === "object" ? raw.meta : void 0,
194
+ edited: raw.edited === true
195
+ };
196
+ }
197
+
198
+ // src/behaviors/events.ts
199
+ function emitIcen(source, type, detail) {
200
+ return source.dispatchEvent(
201
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
202
+ );
203
+ }
204
+
205
+ // src/behaviors/kb-chunks.ts
206
+ var svg2 = (d) => `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${d}</svg>`;
207
+ var ICON_PLUS = svg2('<path d="M5 12h14"/><path d="M12 5v14"/>');
208
+ function icon(parent, svgStr) {
209
+ const node = svgIcon(svgStr);
210
+ if (node) parent.appendChild(node);
211
+ }
212
+ var MODE_LABELS = { text: "\u5168\u6587", vector: "\u8BED\u4E49" };
213
+ function buildSearchBar(opts) {
214
+ const bar = h("div", "kb-chunks-bar");
215
+ const mode = opts.searchMode === "vector" ? "vector" : "text";
216
+ const seg = h("div", "kb-seg kb-chunks-mode");
217
+ seg.setAttribute("role", "radiogroup");
218
+ seg.setAttribute("aria-label", "\u641C\u7D22\u6A21\u5F0F");
219
+ ["text", "vector"].forEach((m) => {
220
+ const item = h("button", `kb-seg-item kb-chunks-mode-item${m === mode ? " is-active" : ""}`);
221
+ item.type = "button";
222
+ item.setAttribute("role", "radio");
223
+ item.setAttribute("aria-checked", String(m === mode));
224
+ item.dataset.value = m;
225
+ item.textContent = MODE_LABELS[m];
226
+ seg.appendChild(item);
227
+ });
228
+ bar.appendChild(seg);
229
+ const input = h("input", "kb-input kb-chunks-search");
230
+ input.type = "search";
231
+ input.placeholder = opts.placeholder ?? (mode === "text" ? "\u5168\u6587\u641C\u7D22 chunk\u2026" : "\u8BED\u4E49\u641C\u7D22 chunk\u2026");
232
+ input.value = opts.query ?? "";
233
+ input.dataset.kbChunkSearch = "";
234
+ input.setAttribute("aria-label", "\u641C\u7D22 chunk");
235
+ bar.appendChild(input);
236
+ const add = h("button", "kb-btn kb-chunks-add");
237
+ add.type = "button";
238
+ add.dataset.kbChunkAdd = "";
239
+ icon(add, ICON_PLUS);
240
+ add.appendChild(document.createTextNode("\u65B0\u589E"));
241
+ bar.appendChild(add);
242
+ return bar;
243
+ }
244
+ function buildKeywordChip(word) {
245
+ const chip = h("span", "kb-chip kb-chunk-keyword");
246
+ chip.appendChild(document.createTextNode(word));
247
+ const x = h("button", "kb-chunk-keyword-x");
248
+ x.type = "button";
249
+ x.dataset.kbChunkKeywordRemove = "";
250
+ x.setAttribute("aria-label", `\u79FB\u9664\u5173\u952E\u8BCD ${word}`);
251
+ x.textContent = "\xD7";
252
+ chip.appendChild(x);
253
+ return chip;
254
+ }
255
+ function buildChunkRow(chunk, index) {
256
+ const row = h("div", `kb-chunk${chunk.available ? "" : " is-off"}${chunk.edited ? " is-edited" : ""}`);
257
+ row.dataset.chunkId = chunk.id;
258
+ const sw = h("label", "kb-chunk-switch");
259
+ sw.title = "\u5173\u95ED\u540E\u4E0D\u5220\u9664\uFF0C\u4EC5\u6392\u9664\u51FA\u68C0\u7D22";
260
+ const cb = document.createElement("input");
261
+ cb.type = "checkbox";
262
+ cb.checked = chunk.available;
263
+ cb.dataset.kbChunkToggle = "";
264
+ cb.setAttribute("aria-label", `chunk ${index + 1} \u542F\u7528`);
265
+ sw.appendChild(cb);
266
+ sw.appendChild(h("i", "kb-chunk-switch-track", "")).appendChild(h("i", "kb-chunk-switch-thumb"));
267
+ sw.appendChild(h("span", "kb-chunk-switch-label", "\u542F\u7528"));
268
+ row.appendChild(sw);
269
+ const main = h("div", "kb-chunk-main");
270
+ const content = h("div", "kb-chunk-content", chunk.content);
271
+ content.contentEditable = "true";
272
+ content.dataset.kbChunkContent = "";
273
+ content.dataset.original = chunk.content;
274
+ content.setAttribute("role", "textbox");
275
+ content.setAttribute("aria-multiline", "true");
276
+ content.setAttribute("aria-label", `chunk ${index + 1} \u5185\u5BB9`);
277
+ main.appendChild(content);
278
+ const kw = h("div", "kb-chunk-keywords");
279
+ kw.dataset.kbChunkKeywords = "";
280
+ (chunk.keywords ?? []).forEach((word) => kw.appendChild(buildKeywordChip(word)));
281
+ const kwInput = h("input", "kb-chunk-keyword-input");
282
+ kwInput.type = "text";
283
+ kwInput.placeholder = "+ \u5173\u952E\u8BCD";
284
+ kwInput.dataset.kbChunkKeywordInput = "";
285
+ kwInput.setAttribute("aria-label", `chunk ${index + 1} \u65B0\u589E\u5173\u952E\u8BCD`);
286
+ kw.appendChild(kwInput);
287
+ main.appendChild(kw);
288
+ const metaBits = [`#${index + 1}`];
289
+ if (typeof chunk.page === "number") metaBits.push(`\u7B2C ${chunk.page} \u9875`);
290
+ if (chunk.edited) metaBits.push("\u5DF2\u7F16\u8F91");
291
+ main.appendChild(h("div", "kb-chunk-meta kb-meta", metaBits.join(" \xB7 ")));
292
+ row.appendChild(main);
293
+ const remove = h("button", "kb-btn kb-chunk-remove");
294
+ remove.type = "button";
295
+ remove.dataset.kbChunkRemove = "";
296
+ remove.textContent = "\u5220\u9664";
297
+ remove.setAttribute("aria-label", `\u5220\u9664 chunk ${index + 1}`);
298
+ row.appendChild(remove);
299
+ return row;
300
+ }
301
+ function renderKbChunks(el, chunks, opts) {
302
+ if (typeof document === "undefined") return el;
303
+ const o = opts ?? {};
304
+ const list = (Array.isArray(chunks) ? chunks : []).map(
305
+ (c) => normalizeChunk(c)
306
+ );
307
+ el.textContent = "";
308
+ const root = h("div", "kb-chunks");
309
+ root.dataset.documentId = o.documentId ?? list[0]?.documentId ?? "";
310
+ root.appendChild(buildSearchBar(o));
311
+ const listBox = h("div", "kb-chunk-list");
312
+ if (!list.length) {
313
+ listBox.appendChild(h("div", "kb-empty", o.emptyText ?? "\u6682\u65E0 chunk"));
314
+ } else {
315
+ list.forEach((c, i) => listBox.appendChild(buildChunkRow(c, i)));
316
+ }
317
+ root.appendChild(listBox);
318
+ el.appendChild(root);
319
+ return el;
320
+ }
321
+ var searchTimers = /* @__PURE__ */ new WeakMap();
322
+ function filterRowsLocally(root, query) {
323
+ const q = query.trim().toLowerCase();
324
+ root.querySelectorAll(".kb-chunk[data-chunk-id]").forEach((row) => {
325
+ if (!q) {
326
+ row.style.removeProperty("display");
327
+ return;
328
+ }
329
+ const content = row.querySelector("[data-kb-chunk-content]")?.textContent ?? "";
330
+ const keywords = Array.from(row.querySelectorAll(".kb-chunk-keyword")).map((k) => k.firstChild?.textContent ?? "").join("\n");
331
+ const hit = `${content}
332
+ ${keywords}`.toLowerCase().includes(q);
333
+ row.style.display = hit ? "" : "none";
334
+ });
335
+ }
336
+ function currentSearchMode(root) {
337
+ const active = root.querySelector(".kb-chunks-mode-item.is-active");
338
+ return active?.dataset.value === "vector" ? "vector" : "text";
339
+ }
340
+ function markEdited(row) {
341
+ row.classList.add("is-edited");
342
+ const meta = row.querySelector(".kb-chunk-meta");
343
+ if (meta && !meta.querySelector(".kb-chunk-edited-flag")) {
344
+ meta.appendChild(document.createTextNode(" \xB7 "));
345
+ meta.appendChild(h("span", "kb-chunk-edited-flag", "\u5DF2\u7F16\u8F91"));
346
+ }
347
+ }
348
+ function emitEdit(row) {
349
+ markEdited(row);
350
+ emitIcen(row, "icen:kb-chunk-edit", { chunkId: row.dataset.chunkId ?? "" });
351
+ }
352
+ function initKbChunks(root) {
353
+ if (typeof document === "undefined") return () => void 0;
354
+ const scope = root ?? document;
355
+ const marked = scope;
356
+ if (marked.__icenKbChunksInit) return () => void 0;
357
+ marked.__icenKbChunksInit = true;
358
+ const target = scope;
359
+ const chunkRootOf = (node) => node.closest(".kb-chunks");
360
+ const rowOf = (node) => node.closest(".kb-chunk[data-chunk-id]");
361
+ const onClick = (e) => {
362
+ const t = e.target instanceof Element ? e.target : null;
363
+ if (!t) return;
364
+ const el = t instanceof HTMLElement ? t : null;
365
+ if (!el) return;
366
+ const addBtn = el.closest("[data-kb-chunk-add]");
367
+ if (addBtn) {
368
+ const wrap = chunkRootOf(addBtn);
369
+ emitIcen(addBtn, "icen:kb-chunk-add", { documentId: wrap?.dataset.documentId ?? "" });
370
+ return;
371
+ }
372
+ const rmBtn = el.closest("[data-kb-chunk-remove]");
373
+ if (rmBtn) {
374
+ const row = rowOf(rmBtn);
375
+ if (row) emitIcen(row, "icen:kb-chunk-remove", { chunkId: row.dataset.chunkId ?? "" });
376
+ return;
377
+ }
378
+ const kwX = el.closest("[data-kb-chunk-keyword-remove]");
379
+ if (kwX) {
380
+ const row = rowOf(kwX);
381
+ const chip = kwX.closest(".kb-chunk-keyword");
382
+ if (chip) chip.remove();
383
+ if (row) emitEdit(row);
384
+ return;
385
+ }
386
+ const modeItem = el.closest(".kb-chunks-mode-item");
387
+ if (modeItem) {
388
+ const seg = modeItem.closest(".kb-chunks-mode");
389
+ if (!seg || modeItem.classList.contains("is-active")) return;
390
+ seg.querySelectorAll(".kb-chunks-mode-item").forEach((it) => {
391
+ const on = it === modeItem;
392
+ it.classList.toggle("is-active", on);
393
+ it.setAttribute("aria-checked", String(on));
394
+ });
395
+ const wrap = chunkRootOf(modeItem);
396
+ const search = wrap?.querySelector("[data-kb-chunk-search]") ?? null;
397
+ const mode = currentSearchMode(wrap ?? seg);
398
+ if (search) search.placeholder = mode === "text" ? "\u5168\u6587\u641C\u7D22 chunk\u2026" : "\u8BED\u4E49\u641C\u7D22 chunk\u2026";
399
+ if (wrap) {
400
+ if (mode === "text") filterRowsLocally(wrap, search?.value ?? "");
401
+ else wrap.querySelectorAll(".kb-chunk[data-chunk-id]").forEach((r) => r.style.removeProperty("display"));
402
+ emitIcen(wrap, "icen:kb-chunk-search", { mode, query: search?.value ?? "" });
403
+ }
404
+ }
405
+ };
406
+ const onChange = (e) => {
407
+ const t = e.target;
408
+ if (!(t instanceof HTMLInputElement)) return;
409
+ if (t.hasAttribute("data-kb-chunk-toggle")) {
410
+ const row = rowOf(t);
411
+ if (!row) return;
412
+ row.classList.toggle("is-off", !t.checked);
413
+ emitIcen(row, "icen:kb-chunk-toggle", { chunkId: row.dataset.chunkId ?? "", available: t.checked });
414
+ }
415
+ };
416
+ const onKeydown = (e) => {
417
+ const ke = e;
418
+ if (ke.key !== "Enter") return;
419
+ const t = ke.target;
420
+ if (!(t instanceof HTMLInputElement)) return;
421
+ if (t.hasAttribute("data-kb-chunk-keyword-input")) {
422
+ ke.preventDefault();
423
+ const word = t.value.trim();
424
+ const row = rowOf(t);
425
+ if (!word || !row) return;
426
+ const kw = t.closest("[data-kb-chunk-keywords]");
427
+ if (kw) kw.insertBefore(buildKeywordChip(word), t);
428
+ t.value = "";
429
+ emitEdit(row);
430
+ }
431
+ };
432
+ const onFocusOut = (e) => {
433
+ const t = e.target;
434
+ if (!(t instanceof HTMLElement)) return;
435
+ if (!t.hasAttribute("data-kb-chunk-content")) return;
436
+ const row = rowOf(t);
437
+ if (!row) return;
438
+ const next = t.textContent ?? "";
439
+ if (next === (t.dataset.original ?? "")) return;
440
+ t.dataset.original = next;
441
+ emitEdit(row);
442
+ };
443
+ const onInput = (e) => {
444
+ const t = e.target;
445
+ if (!(t instanceof HTMLInputElement) || !t.hasAttribute("data-kb-chunk-search")) return;
446
+ const wrap = chunkRootOf(t);
447
+ if (!wrap) return;
448
+ const prev = searchTimers.get(t);
449
+ if (prev) clearTimeout(prev);
450
+ const timer = setTimeout(() => {
451
+ searchTimers.delete(t);
452
+ const mode = currentSearchMode(wrap);
453
+ if (mode === "text") filterRowsLocally(wrap, t.value);
454
+ emitIcen(wrap, "icen:kb-chunk-search", { mode, query: t.value });
455
+ }, 200);
456
+ searchTimers.set(t, timer);
457
+ };
458
+ target.addEventListener("click", onClick);
459
+ target.addEventListener("change", onChange);
460
+ target.addEventListener("keydown", onKeydown);
461
+ target.addEventListener("focusout", onFocusOut);
462
+ target.addEventListener("input", onInput);
463
+ return () => {
464
+ target.removeEventListener("click", onClick);
465
+ target.removeEventListener("change", onChange);
466
+ target.removeEventListener("keydown", onKeydown);
467
+ target.removeEventListener("focusout", onFocusOut);
468
+ target.removeEventListener("input", onInput);
469
+ marked.__icenKbChunksInit = false;
470
+ };
471
+ }
472
+ export {
473
+ initKbChunks,
474
+ renderKbChunks
475
+ };
@@ -0,0 +1,38 @@
1
+ import { KbCitation } from './kb-core.js';
2
+ import './ai-core.js';
3
+
4
+ /** 来源新鲜度阈值:date 距今超过 90 天视为 stale(来源列表/引用卡/冲突组共用) */
5
+ declare const KB_STALE_DAYS = 90;
6
+ /** 受限权限徽标的锁形线性图标(24 viewBox,stroke 1.5,经 svgIcon 消毒后插入) */
7
+ declare const KB_ICON_LOCK: string;
8
+ /** 判断引用是否过期(date 缺失或不可解析时返回 false —— 无证据不告警的诚实纪律) */
9
+ declare function isKbCitationStale(citation: KbCitation, now?: Date): boolean;
10
+ /** 取来源 URL 的域名(无 URL / 非法 URL 返回空串;引用卡与来源列表共用) */
11
+ declare function kbDomainOf(url: string | undefined): string;
12
+ /** 覆盖来源注册表(renderCitationText 传 sources 时自动调用;宿主也可手动喂数据) */
13
+ declare function setKbCitationSources(sources: KbCitation[]): void;
14
+ /** 读取来源注册表当前快照(调试 / 测试 / 二次渲染用) */
15
+ declare function getKbCitationSources(): KbCitation[];
16
+ /** 造一枚行内引用角标 `<button class="kb-citation" data-cite="{n}">`(有效性由渲染端对照来源数降级);SSR 无元素可造,返回 null */
17
+ declare function renderCitationMark(n: number): HTMLButtonElement | null;
18
+ /**
19
+ * 把含 [3] 的文本渲染成「文本节点 + 角标」混合流(流式安全:增量文本整体重渲该 el)。
20
+ * sources 提供时写入来源注册表(hover 卡数据源)并对超界编号渲染 .is-dead。
21
+ */
22
+ declare function renderCitationText(el: HTMLElement, text: string, sources?: KbCitation[]): HTMLElement;
23
+ /** initKbCitation 的配置项:来源表 / hover 卡数据源 / 浮卡防抖时长 */
24
+ interface KbCitationInitOptions {
25
+ /** 来源表(按编号解析角标;提供后超界编号在渲染端落 .is-dead) */
26
+ sources?: KbCitation[];
27
+ /** hover 卡数据源:入参为注册表查得(或合成)的 citation,返回增强数据;返回 null/undefined 落回注册表结果 */
28
+ getCard?: (citation: KbCitation) => KbCitation | null | undefined;
29
+ /** hover 浮卡防抖(默认 300ms) */
30
+ hoverDelay?: number;
31
+ }
32
+ /**
33
+ * 初始化引用角标交互(root 级委托;幂等 WeakSet 标记,返回销毁函数,销毁后可重新 init)。
34
+ * click → icen:kb-citation-open { citation };hover ≥300ms 且有数据 → openPopover 浮引用卡。
35
+ */
36
+ declare function initKbCitation(root?: ParentNode, opts?: KbCitationInitOptions): () => void;
37
+
38
+ export { KB_ICON_LOCK, KB_STALE_DAYS, type KbCitationInitOptions, getKbCitationSources, initKbCitation, isKbCitationStale, kbDomainOf, renderCitationMark, renderCitationText, setKbCitationSources };