@kitn.ai/ui 0.27.0 → 0.28.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 (266) hide show
  1. package/README.md +10 -2
  2. package/dist/{Icon-BnFKqqtY.js → Icon-DObhsRtm.js} +1 -1
  3. package/dist/{action-icons-CBskfBMz.js → action-icons-CcgNN2oT.js} +1 -1
  4. package/dist/arrow-down-CjRU3JgV.js +1 -0
  5. package/dist/arrow-left-Bnpb1UEW.js +1 -0
  6. package/dist/{artifact-CvXEm1lS.js → artifact-Bwt7OgcR.js} +1 -1
  7. package/dist/{attachments-C43ZegEq.js → attachments-Qr4kg-2b.js} +1 -1
  8. package/dist/{audio-visualizer-B-79y1Tj.js → audio-visualizer-DToYdfSc.js} +1 -1
  9. package/dist/{badge-BpUbq8c0.js → badge-CdEu_jn2.js} +1 -1
  10. package/dist/{bell-sn17Ip9v.js → bell-DQAAOpDz.js} +1 -1
  11. package/dist/{button-BH6rN0U-.js → button-DkuOnGLy.js} +1 -1
  12. package/dist/{card-renderer-Cb1gQmth.js → card-renderer-Jx70m6_l.js} +1 -1
  13. package/dist/{card-routing-DifQgS7n.js → card-routing-0YidER_3.js} +1 -1
  14. package/dist/check-njkVdZu2.js +1 -0
  15. package/dist/{checkbox-Dc9Yov_B.js → checkbox-D7iRB3nL.js} +1 -1
  16. package/dist/{checkbox-group-B1kDLLYk.js → checkbox-group-B2_rpoPM.js} +1 -1
  17. package/dist/chevron-down-B72s6PXR.js +1 -0
  18. package/dist/chevron-right-BatuHzUm.js +1 -0
  19. package/dist/{choice-card-BT3c1S8g.js → choice-card-m0BYqqOK.js} +1 -1
  20. package/dist/circle-check-B62pODB3.js +1 -0
  21. package/dist/{circle-x-wobWkoSx.js → circle-x-BPG0iPst.js} +1 -1
  22. package/dist/circle-zx0ByzY9.js +1 -0
  23. package/dist/code-block-ClMLKb7C.js +1 -0
  24. package/dist/{collapsible-CPJbf6FM.js → collapsible-B4DlWicL.js} +1 -1
  25. package/dist/components/chat-thread.d.ts +89 -1
  26. package/dist/components/conversation-item.d.ts +16 -0
  27. package/dist/components/conversation-panel.d.ts +29 -0
  28. package/dist/components/home-panel.d.ts +34 -0
  29. package/dist/components/widget-tab-bar.d.ts +16 -0
  30. package/dist/{composer-CjngLzal.js → composer-sQ0HcvyG.js} +3 -3
  31. package/dist/{confirm-card-DCx_A4bU.js → confirm-card-rQWDQsnC.js} +1 -1
  32. package/dist/construct-cli.es.js +182 -14
  33. package/dist/{context-BY8V-Nlp.js → context-0kg4ZX1J.js} +1 -1
  34. package/dist/controllable-CnGpMF6r.js +1 -0
  35. package/dist/conversation-item-BxwQLaFJ.js +1 -0
  36. package/dist/conversation-list-BCfGN1JU.js +1 -0
  37. package/dist/{copy-B6DO4PqB.js → copy-n9u9rqpi.js} +1 -1
  38. package/dist/{create-tween-CnMHviKB.js → create-tween-C-q-JCM-.js} +1 -1
  39. package/dist/{create-tween-D1aiGZZh.js → create-tween-CRrJXxBd.js} +1 -1
  40. package/dist/{create-tween-BPzaefTp.js → create-tween-DZ3RRDHD.js} +1 -1
  41. package/dist/{create-tween-DUSQUKpr.js → create-tween-uPkArjIG.js} +1 -1
  42. package/dist/custom-elements.json +51 -2
  43. package/dist/{default-input-CucQEOqH.js → default-input-CaMrJkgH.js} +1 -1
  44. package/dist/define-By-uL588.js +1 -0
  45. package/dist/define.js +2 -2
  46. package/dist/define.server.js +2 -2
  47. package/dist/{disclosure-CbLtajUQ.js → disclosure-WUImBbDv.js} +1 -1
  48. package/dist/{dropdown-BwhViJFd.js → dropdown-wZVeJOMd.js} +1 -1
  49. package/dist/elements/agent-card.js +1 -1
  50. package/dist/elements/artifact.js +1 -1
  51. package/dist/elements/attachments.js +1 -1
  52. package/dist/elements/audio-visualizer.js +1 -1
  53. package/dist/elements/avatar.js +1 -1
  54. package/dist/elements/badge.js +1 -1
  55. package/dist/elements/button.js +1 -1
  56. package/dist/elements/card.js +1 -1
  57. package/dist/elements/cards.js +1 -1
  58. package/dist/elements/chain-of-thought.js +1 -1
  59. package/dist/elements/chat-scope-picker.js +1 -1
  60. package/dist/elements/chat-workspace.js +1 -1
  61. package/dist/elements/chat.js +1 -1
  62. package/dist/elements/checkbox-group.js +1 -1
  63. package/dist/elements/checkbox.js +1 -1
  64. package/dist/elements/checkpoint.js +1 -1
  65. package/dist/elements/choice.js +1 -1
  66. package/dist/elements/coachmark.js +1 -1
  67. package/dist/elements/code-block.js +1 -1
  68. package/dist/elements/command.js +1 -1
  69. package/dist/elements/compare.js +1 -1
  70. package/dist/elements/composer.js +1 -1
  71. package/dist/elements/confirm-card.js +1 -1
  72. package/dist/elements/context-meter.js +1 -1
  73. package/dist/elements/conversation-item.js +1 -1
  74. package/dist/elements/conversation-list.js +1 -1
  75. package/dist/elements/dialog.js +1 -1
  76. package/dist/elements/dock.js +3 -3
  77. package/dist/elements/dropdown.js +1 -1
  78. package/dist/elements/editable-label.js +1 -1
  79. package/dist/elements/embed.js +1 -1
  80. package/dist/elements/empty.js +1 -1
  81. package/dist/elements/feedback-bar.js +1 -1
  82. package/dist/elements/file-tree.js +1 -1
  83. package/dist/elements/file-upload.js +1 -1
  84. package/dist/elements/form.js +1 -1
  85. package/dist/elements/hover-card.js +1 -1
  86. package/dist/elements/icon.js +1 -1
  87. package/dist/elements/image.js +1 -1
  88. package/dist/elements/input.js +1 -1
  89. package/dist/elements/kbd.js +1 -1
  90. package/dist/elements/link-preview.js +1 -1
  91. package/dist/elements/loader.js +1 -1
  92. package/dist/elements/markdown.js +1 -1
  93. package/dist/elements/menu.js +1 -1
  94. package/dist/elements/message-skills.js +1 -1
  95. package/dist/elements/message.js +1 -1
  96. package/dist/elements/model-switcher.js +1 -1
  97. package/dist/elements/nav.js +1 -1
  98. package/dist/elements/notice.js +1 -1
  99. package/dist/elements/pane-grid.js +1 -1
  100. package/dist/elements/pane-group.js +1 -1
  101. package/dist/elements/pane.js +1 -1
  102. package/dist/elements/popover.js +1 -1
  103. package/dist/elements/progress-bar.js +1 -1
  104. package/dist/elements/prompt-dock.js +1 -1
  105. package/dist/elements/prompt-input.js +1 -1
  106. package/dist/elements/prompt-suggestions.js +1 -1
  107. package/dist/elements/radio-group.js +1 -1
  108. package/dist/elements/reasoning.js +1 -1
  109. package/dist/elements/remote.js +1 -1
  110. package/dist/elements/resizable.js +1 -1
  111. package/dist/elements/response-stream.js +1 -1
  112. package/dist/elements/screen.js +1 -1
  113. package/dist/elements/scroll-area.js +1 -1
  114. package/dist/elements/scroll-button.js +1 -1
  115. package/dist/elements/search.js +1 -1
  116. package/dist/elements/segmented.js +1 -1
  117. package/dist/elements/select.js +1 -1
  118. package/dist/elements/separator.js +1 -1
  119. package/dist/elements/setting-item.js +1 -1
  120. package/dist/elements/settings-group.js +1 -1
  121. package/dist/elements/skeleton.js +1 -1
  122. package/dist/elements/slider.js +1 -1
  123. package/dist/elements/source.js +1 -1
  124. package/dist/elements/status.js +1 -1
  125. package/dist/elements/switch.js +1 -1
  126. package/dist/elements/tabs.js +1 -1
  127. package/dist/elements/tasks.js +1 -1
  128. package/dist/elements/text-shimmer.js +1 -1
  129. package/dist/elements/thinking-bar.js +1 -1
  130. package/dist/elements/thread.js +1 -1
  131. package/dist/elements/toast.js +1 -1
  132. package/dist/elements/tool.js +1 -1
  133. package/dist/elements/tooltip.js +1 -1
  134. package/dist/elements/voice-input.js +1 -1
  135. package/dist/elements/voice-output.js +1 -1
  136. package/dist/elements.d.ts +20 -4
  137. package/dist/{ellipsis-DFr4Vqr3.js → ellipsis-CbOpJnU3.js} +1 -1
  138. package/dist/{embed-5s_vU4J0.js → embed-CrfjkbUG.js} +1 -1
  139. package/dist/{external-link-u9d85ORQ.js → external-link-ByXAwBBQ.js} +1 -1
  140. package/dist/{file-text-CX7_x42o.js → file-text-DMib2qwt.js} +1 -1
  141. package/dist/{file-tree-D3kBjXI5.js → file-tree-CJqM2aP7.js} +1 -1
  142. package/dist/{folder-V-YdIL8f.js → folder-_BAb929C.js} +1 -1
  143. package/dist/{form-BRNUMCN2.js → form-DSZgZQZk.js} +1 -1
  144. package/dist/{hover-card-DaeiYrTA.js → hover-card-BQbul9eq.js} +1 -1
  145. package/dist/{icon-BpixdZNq.js → icon-CdcfRhYI.js} +1 -1
  146. package/dist/index.d.ts +3 -1
  147. package/dist/index.js +2842 -2703
  148. package/dist/index.server.js +2820 -2681
  149. package/dist/{info-8mFsIjS3.js → info-DsFjGuI_.js} +1 -1
  150. package/dist/{input-d1Yuu-hz.js → input-DKbmkMos.js} +1 -1
  151. package/dist/kai.es.js +1 -1
  152. package/dist/{kbd-961zMPFB.js → kbd-PvdGhX4s.js} +1 -1
  153. package/dist/{link-preview-DIIbV2Sd.js → link-preview-DbM1866N.js} +1 -1
  154. package/dist/{link-DlZZBGaR.js → link-zF8PzWfF.js} +1 -1
  155. package/dist/{loader-YQszHFaW.js → loader-BM4CEz4G.js} +1 -1
  156. package/dist/{markdown-CVk1MPsj.js → markdown-LMvmAyBk.js} +7 -7
  157. package/dist/mcp.es.js +78 -4
  158. package/dist/{message-CwKVEdZg.js → message-BSsgvHvf.js} +1 -1
  159. package/dist/{message-DS8lzHc1.js → message-BYZECyek.js} +1 -1
  160. package/dist/message-circle-DruwObfX.js +1 -0
  161. package/dist/message-square-BG6q6mlm.js +1 -0
  162. package/dist/{minimize-2-UEZmP2QT.js → minimize-2-BQRoBV1V.js} +1 -1
  163. package/dist/{model-switcher-Kk1jEQ5t.js → model-switcher-CMpCOYcB.js} +1 -1
  164. package/dist/{overlay-C1od6LOz.js → overlay-Cb-MkyDa.js} +1 -1
  165. package/dist/{panel-right-ryET0yyn.js → panel-right-i8warFxT.js} +1 -1
  166. package/dist/{paperclip-BDNoZFJP.js → paperclip-ByY3UVO6.js} +1 -1
  167. package/dist/play-BvKKq3fX.js +1 -0
  168. package/dist/primitives/conversation-store.d.ts +54 -0
  169. package/dist/{progress-bar-BvYX0aoy.js → progress-bar-jVAHvMUf.js} +1 -1
  170. package/dist/{prompt-suggestion-BRFu2lcu.js → prompt-suggestion-CD-qtNgC.js} +1 -1
  171. package/dist/{radio-DcL23cNJ.js → radio-BsoBMhkF.js} +1 -1
  172. package/dist/react/index.d.ts +393 -0
  173. package/dist/react.js +20 -20
  174. package/dist/{reasoning-Cackq4Rh.js → reasoning-4kBPtlTx.js} +1 -1
  175. package/dist/register-impl-B1hLkrI8.js +424 -0
  176. package/dist/{resizable-Cp9HUYih.js → resizable-uPmY9VY-.js} +1 -1
  177. package/dist/{rotate-ccw-0DLRDHH5.js → rotate-ccw-B2xn93py.js} +1 -1
  178. package/dist/{rotate-cw-DOB9IGcU.js → rotate-cw-CMVLoCyH.js} +1 -1
  179. package/dist/{scroll-area-emVmWP4K.js → scroll-area-BqLUo8ZZ.js} +1 -1
  180. package/dist/{scroll-button-CeP_gv1x.js → scroll-button-DslXiJyL.js} +1 -1
  181. package/dist/{select-CWmu00tS.js → select-2cLRtPGT.js} +1 -1
  182. package/dist/{separator-CE6vly6z.js → separator-BWQtNJcM.js} +1 -1
  183. package/dist/{settings-CE-78SvZ.js → settings-BBR63jLg.js} +1 -1
  184. package/dist/{settings-group-ZFWNxFQR.js → settings-group-B2ciy-Iw.js} +1 -1
  185. package/dist/{skeleton-BebdP4mf.js → skeleton-CkHI-HgC.js} +1 -1
  186. package/dist/{slider-BAKRYUlz.js → slider-DDR9U-i0.js} +1 -1
  187. package/dist/{solid-BE5ui6sy.js → solid-BzCFdL25.js} +7720 -7058
  188. package/dist/{solid-DFhsce3O.js → solid-DruVOXnf.js} +5864 -5283
  189. package/dist/solid.d.ts +6 -2
  190. package/dist/solid.js +217 -210
  191. package/dist/solid.server.js +217 -210
  192. package/dist/{source-B0FlguSx.js → source-GEnFF528.js} +1 -1
  193. package/dist/{star-CBMZvLuN.js → star-CilHq8GP.js} +1 -1
  194. package/dist/store-Ciyk6eZG.js +1 -0
  195. package/dist/{switch-CViARZCy.js → switch-KkeQIbuH.js} +1 -1
  196. package/dist/{tasks-card-MjCcOhR_.js → tasks-card-BrN4bggJ.js} +1 -1
  197. package/dist/{text-shimmer-DKlwRF2G.js → text-shimmer-Dcj1MHuq.js} +1 -1
  198. package/dist/{textarea-3ay2Me2-.js → textarea-Dpvbngbg.js} +1 -1
  199. package/dist/theme.tokens.css +28 -0
  200. package/dist/{thumbs-up-DQcu2HMO.js → thumbs-up-CsT9Wzb9.js} +1 -1
  201. package/dist/{toast-store-C6yKOhbk.js → toast-store-tgK6MuMv.js} +1 -1
  202. package/dist/{tool-BCYNlfKy.js → tool-DzUjIBT8.js} +1 -1
  203. package/dist/{tooltip-05zI4hjs.js → tooltip-Bkkg_4t0.js} +1 -1
  204. package/dist/{trash-2-BR1RxGky.js → trash-2-jBKxjGGQ.js} +1 -1
  205. package/dist/{triangle-alert-DHohDOCy.js → triangle-alert-DlQ68ppf.js} +1 -1
  206. package/dist/types.d.ts +48 -3
  207. package/dist/ui/dock.d.ts +29 -0
  208. package/dist/{upload-BbGW6A_u.js → upload-TcAHXv9W.js} +1 -1
  209. package/dist/{url-scheme-policy-DHpoTJwB.js → url-scheme-policy-DR5DgvkM.js} +1 -1
  210. package/dist/{use-card-resolution-CJW4grFa.js → use-card-resolution-DaZqAdWf.js} +1 -1
  211. package/dist/{variant-aurora-xiMPty8f.js → variant-aurora-BhLuYxJR.js} +1 -1
  212. package/dist/{variant-aurora-BUOVgPOB.js → variant-aurora-CNmfHhcx.js} +2 -2
  213. package/dist/{variant-aurora-CUsUJvFI.js → variant-aurora-D6GsdTPA.js} +2 -2
  214. package/dist/{variant-aurora-CW2i4bfr.js → variant-aurora-DbW_OWL2.js} +1 -1
  215. package/dist/{variant-custom-D91HjAKz.js → variant-custom-BRvaNHSi.js} +1 -1
  216. package/dist/{variant-custom-BQtOnmeO.js → variant-custom-BvYHR62b.js} +1 -1
  217. package/dist/{variant-custom-CAnzzppW.js → variant-custom-DMTrEO5w.js} +2 -2
  218. package/dist/{variant-custom-CAm9L-E5.js → variant-custom-DV2x254s.js} +2 -2
  219. package/dist/{variant-wave-Ca1Ls4_y.js → variant-wave-BNMGrDfj.js} +2 -2
  220. package/dist/{variant-wave-uY5crU_K.js → variant-wave-BpDd8t3Z.js} +1 -1
  221. package/dist/{variant-wave-CxX39DKd.js → variant-wave-CyBueXj9.js} +2 -2
  222. package/dist/{variant-wave-DYyzIIZv.js → variant-wave-sp-qwsdI.js} +1 -1
  223. package/dist/x-Z5UntkIJ.js +1 -0
  224. package/frameworks/react/index.tsx +14 -4
  225. package/llms-full.txt +7 -2
  226. package/package.json +1 -1
  227. package/src/agent-tooling/README.md +192 -0
  228. package/src/agent-tooling/catalog/invariants.ts +2 -2
  229. package/src/agent-tooling/construct/cli.ts +16 -0
  230. package/src/agent-tooling/construct/codegen.ts +309 -27
  231. package/src/agent-tooling/construct/construct.v1.schema.json +69 -0
  232. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +11 -2
  233. package/src/agent-tooling/construct/schema.ts +81 -0
  234. package/src/components/chat-thread.tsx +532 -36
  235. package/src/components/conversation-item.tsx +23 -0
  236. package/src/components/conversation-panel.tsx +118 -0
  237. package/src/components/home-panel.tsx +159 -0
  238. package/src/components/widget-tab-bar.tsx +73 -0
  239. package/src/elements/chat.tsx +94 -2
  240. package/src/elements/compiled.css +1 -1
  241. package/src/elements/element-meta.json +49 -6
  242. package/src/elements/element-nonscalar.json +2 -0
  243. package/src/elements/element-types.d.ts +20 -4
  244. package/src/index.ts +3 -1
  245. package/src/primitives/conversation-store.ts +248 -0
  246. package/src/solid.ts +10 -2
  247. package/src/types.ts +45 -3
  248. package/src/ui/dock.tsx +47 -1
  249. package/theme.css +28 -0
  250. package/dist/arrow-down-Br0qtpsz.js +0 -1
  251. package/dist/arrow-left-Dj7xgE12.js +0 -1
  252. package/dist/check-DPeeMUYx.js +0 -1
  253. package/dist/chevron-down-CHSWk7ZT.js +0 -1
  254. package/dist/chevron-right-B7l_fMgx.js +0 -1
  255. package/dist/circle-Bb0yOpqM.js +0 -1
  256. package/dist/circle-check-BGZpCiz7.js +0 -1
  257. package/dist/code-block-CUQ5mtv0.js +0 -1
  258. package/dist/controllable-D43BKmtX.js +0 -1
  259. package/dist/conversation-list-D4lLU_yS.js +0 -1
  260. package/dist/define-CGGX-7Vg.js +0 -1
  261. package/dist/message-circle-Xf8Q-vZp.js +0 -1
  262. package/dist/message-square-Cxnwgkns.js +0 -1
  263. package/dist/play-OFIvYXUQ.js +0 -1
  264. package/dist/register-impl-C7rENvPK.js +0 -424
  265. package/dist/store-7eoadydQ.js +0 -1
  266. package/dist/x-C5m1JFgi.js +0 -1
@@ -57,6 +57,21 @@ const ConstructSchema = z.object({
57
57
  theme: z.object({
58
58
  /** Any CSS color; becomes --kai-color-primary on the host. */
59
59
  accent: z.string().optional(),
60
+ /** Any CSS color; becomes --kai-color-unread on the host (owner
61
+ * ruling, 2026-08-26 — the unread-indicator round). Same treatment
62
+ * as `accent` in every way that matters for safety: construct-
63
+ * authored/untrusted text, carried to the emitted facade via
64
+ * `ctx.element.style.setProperty('--kai-color-unread',
65
+ * JSON.stringify(...))` — never string-interpolated into CSS
66
+ * text — so it can never break out into a new declaration or rule
67
+ * (see emitElement's doc on why `accent` uses setProperty at all).
68
+ * Unlike `accent`, this has no paired -foreground to compute: the
69
+ * three surfaces that read --color-unread (the conversation-list
70
+ * row dot, the header toggle's badge, Dock's own closed-launcher
71
+ * badge) are all small filled dots with no text sitting ON them, so
72
+ * there is nothing to contrast-pair — the value is set and used
73
+ * as-is. */
74
+ unreadColor: z.string().optional(),
60
75
  mode: z.enum(["light", "dark", "system"]).default("system")
61
76
  }).strict().optional(),
62
77
  /** Construct-wide header chrome, valid on every layout (not layout-scoped
@@ -90,6 +105,30 @@ const ConstructSchema = z.object({
90
105
  description: z.string().min(1).optional(),
91
106
  icon: z.string().min(1).optional()
92
107
  }).strict().optional(),
108
+ /** Home screen (spec 2026-08-27, H-1..H-5): Intercom-style landing view behind
109
+ * a Home/Messages tab bar. PRESENCE of `home` enables the tab chrome (H-4) —
110
+ * no `enabled` boolean, like `header`/`empty`. Every sub-key optional;
111
+ * `home: {}` still means "tabs on, defaults". Never requires another
112
+ * capability (H-3): the recent card simply renders nothing without
113
+ * `capabilities.conversations` (the CLI warns — see cli.ts). All strings are
114
+ * construct-authored/untrusted: JSON.stringify'd at every emit site; hrefs
115
+ * and URL-shaped icons through isSafeUrl in superRefine below. */
116
+ home: z.object({
117
+ greeting: z.object({ title: z.string().min(1).optional(), subtitle: z.string().min(1).optional() }).strict().optional(),
118
+ recentConversation: z.literal(true).optional(),
119
+ newConversation: z.object({ label: z.string().min(1).optional() }).strict().optional(),
120
+ links: z.array(
121
+ z.object({
122
+ label: z.string().min(1),
123
+ href: z.string().min(1).optional(),
124
+ description: z.string().min(1).optional(),
125
+ /** renderIcon name (e.g. 'book-open') or a safe URL — the icon NAME
126
+ * list is renderIcon's own vocabulary, never restated here; unknown
127
+ * names warn loudly at DEV runtime. */
128
+ icon: z.string().min(1).optional()
129
+ }).strict()
130
+ ).optional()
131
+ }).strict().optional(),
93
132
  // Capability vocabulary, widened one field at a time by later tasks.
94
133
  capabilities: z.object({
95
134
  /** Starter prompts shown on the empty thread; clicking one sends it.
@@ -143,7 +182,18 @@ const ConstructSchema = z.object({
143
182
  * Meaningless when `reasoning` is `'compact'` (no expandable
144
183
  * content exists) or `'off'` (nothing renders); rejected on both,
145
184
  * loudly, below. */
146
- reasoningOpen: z.boolean().optional()
185
+ reasoningOpen: z.boolean().optional(),
186
+ /** Turns on the prior-conversations list (C-1..C-9 of the
187
+ * conversations design). `true` only — there is no `false` form,
188
+ * matching this schema's other presence-only capability flags.
189
+ * Requires `capabilities.history.persistence` to be `local` or
190
+ * `endpoint` (superRefine below, loud): a conversation list with
191
+ * nowhere to persist conversations is not a coherent construct.
192
+ * WHAT persists (this field, plus history) stays construct
193
+ * vocabulary; HOW it persists (the ConversationStore adapter,
194
+ * localStorage vs. a fetch endpoint) is codegen's call, never
195
+ * vocabulary here (C-3 — no transport-layer vocabulary). */
196
+ conversations: z.literal(true).optional()
147
197
  }).strict().optional(),
148
198
  /** Named generative-UI card definitions the model can emit as tool calls,
149
199
  * rendered in the thread. Top-level (not a capability): a card is
@@ -253,6 +303,30 @@ const ConstructSchema = z.object({
253
303
  });
254
304
  }
255
305
  const history = construct.capabilities?.history;
306
+ if (construct.capabilities?.conversations && (!history || history.persistence === "none")) {
307
+ ctx.addIssue({
308
+ code: z.ZodIssueCode.custom,
309
+ path: ["capabilities", "conversations"],
310
+ message: '"conversations" requires capabilities.history.persistence to be "local" or "endpoint" — a conversation list needs somewhere to persist conversations'
311
+ });
312
+ }
313
+ const URL_SHAPED = /^[a-zA-Z][a-zA-Z0-9+.-]*:|^\/\//;
314
+ for (const [i, link] of (construct.home?.links ?? []).entries()) {
315
+ if (link.href && !isSafeUrl(link.href)) {
316
+ ctx.addIssue({
317
+ code: z.ZodIssueCode.custom,
318
+ path: ["home", "links", i, "href"],
319
+ message: "href must be an http(s)/mailto or relative URL — no javascript:/data: schemes"
320
+ });
321
+ }
322
+ if (link.icon && URL_SHAPED.test(link.icon) && !isSafeUrl(link.icon)) {
323
+ ctx.addIssue({
324
+ code: z.ZodIssueCode.custom,
325
+ path: ["home", "links", i, "icon"],
326
+ message: "icon must be a kit icon name or an http(s)/relative URL — no javascript:/data: schemes"
327
+ });
328
+ }
329
+ }
256
330
  if (!history) return;
257
331
  if (history.persistence === "endpoint" && !history.url) {
258
332
  ctx.addIssue({
@@ -564,11 +638,26 @@ function emitIndexHtml(c) {
564
638
  }
565
639
  function emitElement(c) {
566
640
  const accent = c.theme?.accent;
567
- if (!accent) {
641
+ const unreadColor = c.theme?.unreadColor;
642
+ if (!accent && !unreadColor) {
568
643
  const facade2 = "() => <App />";
569
644
  return `import { defineWebComponent } from '@kitn.ai/ui/define';
570
645
  import { App } from './App';
571
646
 
647
+ // The one facade. Interior stays pure Solid (no nested element registrations);
648
+ // the kit CSS is injected into the shadow root by defineWebComponent itself.
649
+ defineWebComponent('${c.name}', { theme: '${themeMode(c)}' as 'light' | 'dark' | 'auto' }, ${facade2});
650
+ `;
651
+ }
652
+ const unreadColorSetProperty = unreadColor ? `
653
+ ctx.element.style.setProperty('--kai-color-unread', ${JSON.stringify(unreadColor)});` : "";
654
+ if (!accent) {
655
+ const facade2 = `(_props, ctx) => {${unreadColorSetProperty}
656
+ return <App />;
657
+ }`;
658
+ return `import { defineWebComponent } from '@kitn.ai/ui/define';
659
+ import { App } from './App';
660
+
572
661
  // The one facade. Interior stays pure Solid (no nested element registrations);
573
662
  // the kit CSS is injected into the shadow root by defineWebComponent itself.
574
663
  defineWebComponent('${c.name}', { theme: '${themeMode(c)}' as 'light' | 'dark' | 'auto' }, ${facade2});
@@ -589,7 +678,7 @@ defineWebComponent('${c.name}', { theme: '${themeMode(c)}' as 'light' | 'dark' |
589
678
  :host { --kai-color-primary-foreground: contrast-color(var(--kai-color-primary)); }
590
679
  }`;
591
680
  const facade = `(_props, ctx) => {
592
- ctx.element.style.setProperty('--kai-color-primary', ${JSON.stringify(accent)});
681
+ ctx.element.style.setProperty('--kai-color-primary', ${JSON.stringify(accent)});${unreadColorSetProperty}
593
682
  return (
594
683
  <>
595
684
  <style>{${JSON.stringify(styleText)}}</style>
@@ -607,10 +696,11 @@ defineWebComponent('${c.name}', { theme: '${themeMode(c)}' as 'light' | 'dark' |
607
696
  }
608
697
  function emitApp(c) {
609
698
  if (c.layout === "custom") return emitCustomApp(c);
610
- return `${emitSolidJsImport(c)}import { ChatThread, createKaiChat${emitLayoutImport(c)}${emitCardComponentImport(c)}${emitEmptyComponentImport(c)}${emitHeaderCloseImport(c)} } from '@kitn.ai/ui/solid';
611
- import type { AttachmentData${emitHistoryTypeImport(c)} } from '@kitn.ai/ui/solid';
699
+ return `${emitSolidJsImport(c)}${emitConversationsSignalsImport(c)}import { ChatThread, createKaiChat${emitLayoutImport(c)}${emitCardComponentImport(c)}${emitEmptyComponentImport(c)}${emitHeaderCloseImport(c)} } from '@kitn.ai/ui/solid';
700
+ import type { AttachmentData${emitHistoryTypeImport(c)}${emitConversationsResetTypeImport(c)} } from '@kitn.ai/ui/solid';
612
701
  ${emitProviderImports(c)}
613
702
  ${emitCardsImport(c)}
703
+ ${emitConversationsImport(c)}
614
704
 
615
705
  ${emitProviderSetup(c)}
616
706
  ${emitHistorySetup(c)}
@@ -679,9 +769,26 @@ ${emitHistorySetup(c)}
679
769
  // emitDockCloseVar/emitHeaderEndContentProp's docs. No header means no
680
770
  // row for it to sit in, so that case is untouched and Dock's own built-in
681
771
  // mobile X keeps covering it.
772
+ // - conversations (Task 5): gated via ChatThread's own \`conversations\`/
773
+ // \`store\` props (kit-owned end to end — the prior-conversations list,
774
+ // list/load/save, autosave on every \`chat.messages()\` change). Requires
775
+ // capabilities.history persistence \`local\` or \`endpoint\` (schema
776
+ // superRefine, C-4) and SUBSUMES this file's hand-rolled history effect
777
+ // when on — see emitHistorySetup's own doc for the persistence-ownership
778
+ // decision: the store prop is the ONLY persistence mechanism emitted,
779
+ // never both. ChatThread never mutates \`messages\` itself, so
780
+ // \`onConversationLoad\` is ALSO wired here (\`chat.setMessages(() =>
781
+ // messages)\`) — without it, select/new/mount-restore all update
782
+ // ChatThread's own internal view/list state while the rendered thread
783
+ // never changes (see emitConversationsProps's own doc for the Task 6
784
+ // live-browser bug this fixes).
785
+ // - conversations + widget (owner follow-up): closing the widget while its
786
+ // list view is open must not leave it there for the next open — see
787
+ // widgetHasConversationsChrome/emitDockOnOpenChangeProp's docs. Wired only
788
+ // for \`widget\`, the one layout with something that closes/reopens at all.
682
789
  export function App() {
683
- ${emitDockCloseVar(c, " ")} return (
684
- ${emitLayoutOpen(c)}${emitSlots(c.slots, " ")} <ChatThread messages={chat.messages()} loading={chat.loading()} placeholder="Ask anything" onSubmit={submit} webSearch={false} voice={false}${emitHeaderProp(c)}${emitHeaderEndContentProp(c)}${emitAttachProps(c)}${emitStartersProp(c)}${emitReasoningProp(c)}${emitReasoningOpenProp(c)}${emitEmptyContentProp(c)}${emitCardTypesProp(c)} />
790
+ ${emitDockCloseVar(c, " ")}${emitChatControllerVar(c, " ")}${emitConversationsSignalsVar(c, " ")} return (
791
+ ${emitLayoutOpen(c)}${emitSlots(c.slots, " ")} <ChatThread messages={chat.messages()} loading={chat.loading()} placeholder="Ask anything" onSubmit={submit} webSearch={false} voice={false}${emitHeaderProp(c)}${emitHeaderEndContentProp(c)}${emitAttachProps(c)}${emitStartersProp(c)}${emitReasoningProp(c)}${emitReasoningOpenProp(c)}${emitEmptyContentProp(c)}${emitCardTypesProp(c)}${emitHomeProp(c)}${emitConversationsProps(c)}${emitChatControllerRefProp(c)}${emitChatThreadUnreadProps(c)} />
685
792
  ${emitLayoutClose(c)} );
686
793
  }
687
794
  `;
@@ -703,8 +810,8 @@ ${emitHistorySetup(c)}
703
810
  // layout: custom — minimal chrome, no ChatThread/Dock/PaneGroup. The bare
704
811
  // spine (Thread + PromptInput) plus the declared slots, positioned by hand so
705
812
  // YOU own the surrounding DOM. Capabilities beyond the spine (starters,
706
- // attachments, reasoning display-mode, reasoningOpen, header.title, empty)
707
- // are NOT wired here in v1 — this file is the eject artifact; add them the
813
+ // attachments, reasoning display-mode, reasoningOpen, header.title, empty,
814
+ // conversations) are NOT wired here in v1 — this file is the eject artifact; add them the
708
815
  // way ChatThread composes them (components/chat-thread.tsx in the kit's own
709
816
  // source) if this construct needs them on a custom layout.
710
817
  export function App() {
@@ -757,6 +864,40 @@ function emitEmptyComponentImport(c) {
757
864
  function widgetHasHeaderClose(c) {
758
865
  return c.layout === "widget" && !!c.header?.title;
759
866
  }
867
+ function widgetHasConversationsChrome(c) {
868
+ return c.layout === "widget" && (!!c.capabilities?.conversations || !!c.home);
869
+ }
870
+ function emitChatControllerVar(c, indent) {
871
+ return widgetHasConversationsChrome(c) ? `${indent}let chatController: ChatThreadController | undefined;
872
+ ` : "";
873
+ }
874
+ function emitChatControllerRefProp(c) {
875
+ return widgetHasConversationsChrome(c) ? " controllerRef={(api) => (chatController = api)}" : "";
876
+ }
877
+ function emitDockOnOpenChangeProp(c) {
878
+ return widgetHasConversationsChrome(c) ? " onOpenChange={(open) => { setDockOpen(open); if (!open) chatController?.closeConversationsList(); }}" : "";
879
+ }
880
+ function emitConversationsResetTypeImport(c) {
881
+ return widgetHasConversationsChrome(c) ? ", ChatThreadController" : "";
882
+ }
883
+ function emitConversationsSignalsImport(c) {
884
+ return widgetHasConversationsChrome(c) ? `import { createSignal } from 'solid-js';
885
+ ` : "";
886
+ }
887
+ function emitConversationsSignalsVar(c, indent) {
888
+ if (!widgetHasConversationsChrome(c)) return "";
889
+ const w = c.layout === "widget" ? c.widget : void 0;
890
+ const defaultOpen = w?.defaultOpen === true ? "true" : "false";
891
+ return `${indent}const [dockOpen, setDockOpen] = createSignal(${defaultOpen});
892
+ ${indent}const [anyUnread, setAnyUnread] = createSignal(false);
893
+ `;
894
+ }
895
+ function emitChatThreadUnreadProps(c) {
896
+ return widgetHasConversationsChrome(c) ? " hostOpen={dockOpen()} onUnreadChange={setAnyUnread}" : "";
897
+ }
898
+ function emitDockUnreadProp(c) {
899
+ return widgetHasConversationsChrome(c) ? " unread={anyUnread()}" : "";
900
+ }
760
901
  function emitDockCloseVar(c, indent) {
761
902
  return widgetHasHeaderClose(c) ? `${indent}let dockClose: (() => void) | undefined;
762
903
  ` : "";
@@ -792,15 +933,30 @@ function emitReasoningProp(c) {
792
933
  function emitReasoningOpenProp(c) {
793
934
  return c.capabilities?.reasoningOpen === true ? " reasoningOpen={true}" : "";
794
935
  }
936
+ function emitHomeProp(c) {
937
+ if (!c.home) return "";
938
+ return ` home={${JSON.stringify(c.home)}}`;
939
+ }
940
+ function emitConversationsProps(c) {
941
+ if (!c.capabilities?.conversations) return "";
942
+ const history = c.capabilities.history;
943
+ const storeCall = history?.persistence === "endpoint" ? `fetchStore(${JSON.stringify(history.url)}${c.userId ? `, ${JSON.stringify(c.userId)}` : ""})` : `localStorageStore('${c.name}'${c.userId ? `, ${JSON.stringify(c.userId)}` : ""})`;
944
+ return ` conversations={true} store={${storeCall}} onConversationLoad={(messages) => chat.setMessages(() => messages)}`;
945
+ }
946
+ function emitConversationsImport(c) {
947
+ if (!c.capabilities?.conversations) return "";
948
+ const name = c.capabilities.history?.persistence === "endpoint" ? "fetchStore" : "localStorageStore";
949
+ return `import { ${name} } from '@kitn.ai/ui/solid';`;
950
+ }
795
951
  function emitSolidJsImport(c) {
796
952
  const history = c.capabilities?.history;
797
- if (!history || history.persistence === "none") return "";
953
+ if (!history || history.persistence === "none" || c.layout !== "custom" && c.capabilities?.conversations) return "";
798
954
  return `import { createEffect } from 'solid-js';
799
955
  `;
800
956
  }
801
957
  function emitHistoryTypeImport(c) {
802
958
  const history = c.capabilities?.history;
803
- if (!history || history.persistence === "none") return "";
959
+ if (!history || history.persistence === "none" || c.layout !== "custom" && c.capabilities?.conversations) return "";
804
960
  return ", ChatMessage";
805
961
  }
806
962
  function emitUserIdHeaderEntry(c) {
@@ -809,6 +965,7 @@ function emitUserIdHeaderEntry(c) {
809
965
  function emitHistorySetup(c) {
810
966
  const history = c.capabilities?.history;
811
967
  if (!history || history.persistence === "none") return "";
968
+ if (c.layout !== "custom" && c.capabilities?.conversations) return "";
812
969
  if (history.persistence === "local") {
813
970
  const key = JSON.stringify(c.userId ? `kai:${c.name}:${c.userId}:thread` : `kai:${c.name}:thread`);
814
971
  return `
@@ -947,7 +1104,7 @@ async function submit(detail: { value: string; attachments: AttachmentData[] })
947
1104
  function emitLayoutImport(c) {
948
1105
  switch (c.layout) {
949
1106
  case "widget":
950
- return ", Dock";
1107
+ return `, Dock${hasLauncherIcon(c) ? ", DockLauncherImage" : ""}`;
951
1108
  case "split":
952
1109
  return ", WorkspaceShell";
953
1110
  case "fullscreen":
@@ -966,10 +1123,13 @@ function emitDockPosition(c) {
966
1123
  const w = c.layout === "widget" ? c.widget : void 0;
967
1124
  return w?.position ? ` position="${w.position}"` : "";
968
1125
  }
1126
+ function hasLauncherIcon(c) {
1127
+ return c.layout === "widget" && !!c.widget?.launcherIcon;
1128
+ }
969
1129
  function emitDockLauncher(c) {
970
1130
  const w = c.layout === "widget" ? c.widget : void 0;
971
1131
  if (!w?.launcherIcon) return "";
972
- return ` launcher={<img src={${JSON.stringify(w.launcherIcon)}} alt="" style={{ width: '24px', height: '24px', 'border-radius': '9999px' }} />}`;
1132
+ return ` launcher={<DockLauncherImage src={${JSON.stringify(w.launcherIcon)}} />}`;
973
1133
  }
974
1134
  function emitDockDefaultOpen(c) {
975
1135
  const w = c.layout === "widget" ? c.widget : void 0;
@@ -978,7 +1138,7 @@ function emitDockDefaultOpen(c) {
978
1138
  function emitLayoutOpen(c) {
979
1139
  switch (c.layout) {
980
1140
  case "widget":
981
- return ` <Dock label="${c.name}"${emitDockPosition(c)}${emitDockLauncher(c)}${emitDockDefaultOpen(c)}${emitDockHideClose(c)}${emitDockControllerRef(c)}>
1141
+ return ` <Dock label="${c.name}"${emitDockPosition(c)}${emitDockLauncher(c)}${emitDockDefaultOpen(c)}${emitDockHideClose(c)}${emitDockControllerRef(c)}${emitDockOnOpenChangeProp(c)}${emitDockUnreadProp(c)}>
982
1142
  `;
983
1143
  case "fullscreen":
984
1144
  return ` <div style={{ height: '100dvh', display: 'flex', 'flex-direction': 'column' }}>
@@ -1058,6 +1218,12 @@ const USAGE = `usage: kai <command>
1058
1218
  kai dev <construct.json> live preview with reload-on-edit (Task 5)
1059
1219
  kai compile <construct.json> [outDir] one self-registering .js (Task 6)
1060
1220
  `;
1221
+ function homeRecentConversationWarning(construct) {
1222
+ if (construct.home?.recentConversation && !construct.capabilities?.conversations) {
1223
+ return "warning: home.recentConversation is set but capabilities.conversations is not — the recent-conversation card will render nothing without it.";
1224
+ }
1225
+ return null;
1226
+ }
1061
1227
  function loadConstruct(path, io) {
1062
1228
  const abs = resolve(path);
1063
1229
  let raw;
@@ -1095,6 +1261,8 @@ async function runCli(argv, io = defaultIo) {
1095
1261
  const construct = loadConstruct(rest[0] ?? "", io);
1096
1262
  if (!construct) return 1;
1097
1263
  io.log(`valid construct: <${construct.name}> (layout: ${construct.layout}, provider: ${construct.provider.mode})`);
1264
+ const warning = homeRecentConversationWarning(construct);
1265
+ if (warning) io.log(warning);
1098
1266
  return 0;
1099
1267
  }
1100
1268
  case "eject": {
@@ -1 +1 @@
1
- import{k as o,c as n,S as a,i as s,a as d,b as f,B,G as N,t as u,d as j,m as P}from"./define-CGGX-7Vg.js";import{H as M,a as $,b as E}from"./hover-card-DaeiYrTA.js";import{c as h}from"./cn-DN5AWfiS.js";import{B as G}from"./button-BH6rN0U-.js";import{P as H}from"./progress-bar-BvYX0aoy.js";var O=u('<svg aria-label="Model context usage"height=20 role=img viewBox="0 0 24 24"width=20 style=color:currentcolor><circle cx=12 cy=12 fill=none opacity=0.25 r=10 stroke=currentColor stroke-width=2></circle><circle cx=12 cy=12 fill=none opacity=0.7 r=10 stroke=currentColor stroke-linecap=round stroke-width=2 style=transform:rotate(-90deg);transform-origin:center>'),R=u('<span class="font-medium text-muted-foreground">'),q=u('<div class="flex items-center justify-between gap-3 text-xs"><p></p><p class="font-mono text-muted-foreground"> / '),z=u("<div class=space-y-2>"),T=u("<div>"),A=u("<span class=text-muted-foreground>Total cost"),S=u("<span>"),J=u("<div><span class=text-muted-foreground>Input"),K=u("<div><span class=text-muted-foreground>Output"),L=u("<div><span class=text-muted-foreground>Reasoning"),Q=u("<div><span class=text-muted-foreground>Cache");const V=10,v=.7,b=.9;function W(e,t=v,r=b){return e>r?"danger":e>t?"warn":"ok"}const I=B();function g(){const e=N(I);if(!e)throw new Error("Context components must be used within Context");return e}const y=new Intl.NumberFormat("en-US",{notation:"compact"}),D=new Intl.NumberFormat("en-US",{maximumFractionDigits:1,style:"percent"}),_=new Intl.NumberFormat("en-US",{currency:"USD",style:"currency"});function X(e){const t=o(()=>({usedTokens:e.usedTokens,maxTokens:e.maxTokens,inputTokens:e.inputTokens,outputTokens:e.outputTokens,reasoningTokens:e.reasoningTokens,cacheTokens:e.cacheTokens,estimatedCost:e.estimatedCost,warnThreshold:e.warnThreshold??v,dangerThreshold:e.dangerThreshold??b}));return n(I.Provider,{get value(){return t()},get children(){return n(M,{openDelay:0,get children(){return e.children}})}})}function Y(){const e=g(),t=2*Math.PI*V,r=o(()=>e.usedTokens/e.maxTokens),c=o(()=>t*(1-r()));return(()=>{var i=O(),p=i.firstChild,k=p.nextSibling;return j(k,"stroke-dasharray",`${t} ${t}`),d(()=>j(k,"stroke-dashoffset",c())),i})()}function Z(e){const t=g(),r=o(()=>t.usedTokens/t.maxTokens),c=o(()=>D.format(r()));return n($,{get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return n(G,{type:"button",variant:"ghost",get class(){return e.class},get children(){return[(()=>{var i=R();return s(i,c),i})(),n(Y,{})]}})}})}})}function ee(e){return n(E,{get class(){return h("min-w-60 divide-y divide-border overflow-hidden",e.class)},get children(){return e.children}})}function te(e){const t=g(),r=o(()=>t.usedTokens/t.maxTokens),c=o(()=>D.format(r())),i=o(()=>y.format(t.usedTokens)),p=o(()=>y.format(t.maxTokens)),k=o(()=>{const l=r();return l>t.dangerThreshold?"danger":l>t.warnThreshold?"warn":"ok"}),F=o(()=>{const l=k();return l==="danger"?"error":l==="warn"?"warning":"primary"});return(()=>{var l=T();return s(l,n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return[(()=>{var m=q(),C=m.firstChild,w=C.nextSibling,U=w.firstChild;return s(C,c),s(w,i,U),s(w,p,null),m})(),(()=>{var m=z();return s(m,n(H,{get value(){return t.usedTokens},get max(){return t.maxTokens},get tone(){return F()},"aria-label":"Context usage"})),m})()]}})),d(()=>f(l,h("w-full space-y-2 p-3",e.class))),l})()}function re(e){return(()=>{var t=T();return s(t,()=>e.children),d(()=>f(t,h("w-full p-3",e.class))),t})()}function ne(e){const t=g(),r=o(()=>_.format(t.estimatedCost??0));return(()=>{var c=T();return s(c,n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return[A(),(()=>{var i=S();return s(i,r),i})()]}})),d(()=>f(c,h("flex w-full items-center justify-between gap-3 bg-muted p-3 text-xs",e.class))),c})()}function x(e){return(()=>{var t=S();return s(t,(()=>{var r=P(()=>e.tokens===void 0);return()=>r()?"\u2014":y.format(e.tokens)})()),t})()}function se(e){const t=g();return n(a,{get when(){return e.children||t.inputTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=J();return r.firstChild,s(r,n(x,{get tokens(){return t.inputTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function oe(e){const t=g();return n(a,{get when(){return e.children||t.outputTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=K();return r.firstChild,s(r,n(x,{get tokens(){return t.outputTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function ae(e){const t=g();return n(a,{get when(){return e.children||t.reasoningTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=L();return r.firstChild,s(r,n(x,{get tokens(){return t.reasoningTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function ue(e){const t=g();return n(a,{get when(){return e.children||t.cacheTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=Q();return r.firstChild,s(r,n(x,{get tokens(){return t.cacheTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}export{X as C,v as D,Z as a,ee as b,te as c,re as d,se as e,oe as f,ne as g,W as h,ae as i,ue as j,b as k};
1
+ import{k as o,c as n,S as a,i as s,a as d,b as f,G as N,H as P,t as u,d as j,m as B}from"./define-By-uL588.js";import{H,a as M,b as $}from"./hover-card-BQbul9eq.js";import{c as h}from"./cn-DN5AWfiS.js";import{B as E}from"./button-DkuOnGLy.js";import{P as G}from"./progress-bar-jVAHvMUf.js";var O=u('<svg aria-label="Model context usage"height=20 role=img viewBox="0 0 24 24"width=20 style=color:currentcolor><circle cx=12 cy=12 fill=none opacity=0.25 r=10 stroke=currentColor stroke-width=2></circle><circle cx=12 cy=12 fill=none opacity=0.7 r=10 stroke=currentColor stroke-linecap=round stroke-width=2 style=transform:rotate(-90deg);transform-origin:center>'),R=u('<span class="font-medium text-muted-foreground">'),q=u('<div class="flex items-center justify-between gap-3 text-xs"><p></p><p class="font-mono text-muted-foreground"> / '),z=u("<div class=space-y-2>"),T=u("<div>"),A=u("<span class=text-muted-foreground>Total cost"),S=u("<span>"),J=u("<div><span class=text-muted-foreground>Input"),K=u("<div><span class=text-muted-foreground>Output"),L=u("<div><span class=text-muted-foreground>Reasoning"),Q=u("<div><span class=text-muted-foreground>Cache");const V=10,v=.7,b=.9;function W(e,t=v,r=b){return e>r?"danger":e>t?"warn":"ok"}const I=N();function g(){const e=P(I);if(!e)throw new Error("Context components must be used within Context");return e}const y=new Intl.NumberFormat("en-US",{notation:"compact"}),D=new Intl.NumberFormat("en-US",{maximumFractionDigits:1,style:"percent"}),_=new Intl.NumberFormat("en-US",{currency:"USD",style:"currency"});function X(e){const t=o(()=>({usedTokens:e.usedTokens,maxTokens:e.maxTokens,inputTokens:e.inputTokens,outputTokens:e.outputTokens,reasoningTokens:e.reasoningTokens,cacheTokens:e.cacheTokens,estimatedCost:e.estimatedCost,warnThreshold:e.warnThreshold??v,dangerThreshold:e.dangerThreshold??b}));return n(I.Provider,{get value(){return t()},get children(){return n(H,{openDelay:0,get children(){return e.children}})}})}function Y(){const e=g(),t=2*Math.PI*V,r=o(()=>e.usedTokens/e.maxTokens),c=o(()=>t*(1-r()));return(()=>{var i=O(),p=i.firstChild,k=p.nextSibling;return j(k,"stroke-dasharray",`${t} ${t}`),d(()=>j(k,"stroke-dashoffset",c())),i})()}function Z(e){const t=g(),r=o(()=>t.usedTokens/t.maxTokens),c=o(()=>D.format(r()));return n(M,{get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return n(E,{type:"button",variant:"ghost",get class(){return e.class},get children(){return[(()=>{var i=R();return s(i,c),i})(),n(Y,{})]}})}})}})}function ee(e){return n($,{get class(){return h("min-w-60 divide-y divide-border overflow-hidden",e.class)},get children(){return e.children}})}function te(e){const t=g(),r=o(()=>t.usedTokens/t.maxTokens),c=o(()=>D.format(r())),i=o(()=>y.format(t.usedTokens)),p=o(()=>y.format(t.maxTokens)),k=o(()=>{const l=r();return l>t.dangerThreshold?"danger":l>t.warnThreshold?"warn":"ok"}),F=o(()=>{const l=k();return l==="danger"?"error":l==="warn"?"warning":"primary"});return(()=>{var l=T();return s(l,n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return[(()=>{var m=q(),C=m.firstChild,w=C.nextSibling,U=w.firstChild;return s(C,c),s(w,i,U),s(w,p,null),m})(),(()=>{var m=z();return s(m,n(G,{get value(){return t.usedTokens},get max(){return t.maxTokens},get tone(){return F()},"aria-label":"Context usage"})),m})()]}})),d(()=>f(l,h("w-full space-y-2 p-3",e.class))),l})()}function re(e){return(()=>{var t=T();return s(t,()=>e.children),d(()=>f(t,h("w-full p-3",e.class))),t})()}function ne(e){const t=g(),r=o(()=>_.format(t.estimatedCost??0));return(()=>{var c=T();return s(c,n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return[A(),(()=>{var i=S();return s(i,r),i})()]}})),d(()=>f(c,h("flex w-full items-center justify-between gap-3 bg-muted p-3 text-xs",e.class))),c})()}function x(e){return(()=>{var t=S();return s(t,(()=>{var r=B(()=>e.tokens===void 0);return()=>r()?"\u2014":y.format(e.tokens)})()),t})()}function se(e){const t=g();return n(a,{get when(){return e.children||t.inputTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=J();return r.firstChild,s(r,n(x,{get tokens(){return t.inputTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function oe(e){const t=g();return n(a,{get when(){return e.children||t.outputTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=K();return r.firstChild,s(r,n(x,{get tokens(){return t.outputTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function ae(e){const t=g();return n(a,{get when(){return e.children||t.reasoningTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=L();return r.firstChild,s(r,n(x,{get tokens(){return t.reasoningTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function ue(e){const t=g();return n(a,{get when(){return e.children||t.cacheTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=Q();return r.firstChild,s(r,n(x,{get tokens(){return t.cacheTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}export{X as C,v as D,Z as a,ee as b,te as c,re as d,se as e,oe as f,ne as g,W as h,ae as i,ue as j,b as k};
@@ -0,0 +1 @@
1
+ import{g as c}from"./define-By-uL588.js";function i(t,o){const[r,n]=c(o);return[()=>t()??r(),a=>n(a)]}export{i as c};
@@ -0,0 +1 @@
1
+ import{s as k,i as o,c as u,S as v,a as g,d,b as m,t as c,k as $,e as C}from"./define-By-uL588.js";import{c as l}from"./cn-DN5AWfiS.js";import{m as M}from"./message-square-BG6q6mlm.js";var S=c('<span part=leading class="flex shrink-0 items-center text-muted-foreground">'),D=c('<div part=meta class="mt-0.5 truncate text-xs text-muted-foreground">'),I=c('<span part=menu data-kai-item-menu class="ml-auto flex shrink-0 items-center">'),R=c('<div part=row><div part=body role=button data-kai-item-body class="flex min-w-0 flex-1 cursor-pointer items-center gap-2.5 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"><div class="min-w-0 flex-1"><div part=title>'),y=c('<span part=trailing class="ml-auto shrink-0 text-xs text-muted-foreground">'),j=c('<div class="flex items-center gap-2.5"><span>'),E=c("<button>"),q=c('<div class="flex items-center gap-2"><div>'),z=c("<div> messages");function N(s,t=Date.now()){if(!s)return"";const n=Date.parse(s);if(Number.isNaN(n))return"";const i=Math.max(0,Math.round((t-n)/1e3));if(i<60)return"just now";const r=Math.floor(i/60);if(r<60)return`${r}m ago`;const a=Math.floor(r/60);return a<24?`${a}h ago`:`${Math.floor(a/24)}d ago`}function B(s){if(!s.lastReadAt)return!1;const t=Date.parse(s.updatedAt),n=Date.parse(s.lastReadAt);return Number.isNaN(t)||Number.isNaN(n)?!1:t>n}function F(s){const[t]=k(s,["conversationId","active","compact","leading","meta","menu","children","hostSemantics","onActivate","class"]);return(()=>{var n=R(),i=n.firstChild,r=i.firstChild,a=r.firstChild;return i.$$keydown=e=>{t.onActivate&&(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),t.onActivate())},i.$$click=()=>{var e;return(e=t.onActivate)==null?void 0:e.call(t)},o(i,u(v,{get when(){return t.leading},get children(){var e=S();return o(e,()=>t.leading),e}}),r),o(a,()=>t.children),o(r,u(v,{get when(){return t.meta},get children(){var e=D();return o(e,()=>t.meta),e}}),null),o(n,u(v,{get when(){return t.menu},get children(){var e=I();return o(e,()=>t.menu),e}}),null),g(e=>{var f=t.hostSemantics?"presentation":"listitem",x=t.active?"":void 0,p=t.conversationId,h=l("flex w-full items-center gap-2.5 rounded-lg text-left transition-colors",t.compact?"px-2.5 py-1.5":"px-2.5 py-2",t.active?"bg-muted":"hover:bg-muted/50",t.class),b=t.active?"true":"false",w=t.onActivate?0:void 0,A=l("truncate text-sm",t.active?"font-medium text-foreground":"text-foreground/80");return f!==e.e&&d(n,"role",e.e=f),x!==e.t&&d(n,"data-active",e.t=x),p!==e.a&&d(n,"data-conversation-id",e.a=p),h!==e.o&&m(n,e.o=h),b!==e.i&&d(i,"aria-current",e.i=b),w!==e.n&&d(i,"tabindex",e.n=w),A!==e.s&&m(a,e.s=A),e},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),n})()}function U(s){const[t]=k(s,["conversation","isActive","onSelect","compact","class"]),n=$(()=>t.conversation.trailing??N(t.conversation.updatedAt??t.conversation.lastMessageAt));return(()=>{var i=E();return i.$$click=()=>t.onSelect(t.conversation.id),o(i,u(v,{get when(){return t.compact},get fallback(){return[(()=>{var r=q(),a=r.firstChild;return o(a,()=>t.conversation.title),o(r,u(v,{get when(){return n()},get children(){var e=y();return o(e,n),e}}),null),g(()=>m(a,l("min-w-0 flex-1 truncate text-sm",t.isActive?"font-medium text-foreground":"text-foreground/80"))),r})(),(()=>{var r=z(),a=r.firstChild;return o(r,()=>t.conversation.messageCount,a),g(()=>m(r,l("mt-0.5 truncate text-xs",t.isActive?"text-foreground/70":"text-muted-foreground"))),r})()]},get children(){var r=j(),a=r.firstChild;return o(r,u(M,{get class(){return l("size-3.5 shrink-0",t.isActive?"text-foreground":"text-muted-foreground")}}),a),o(a,()=>t.conversation.title),o(r,u(v,{get when(){return n()},get children(){var e=y();return o(e,n),e}}),null),g(()=>m(a,l("min-w-0 flex-1 truncate text-sm",t.isActive?"font-medium text-foreground":"text-foreground/80"))),r}})),g(r=>{var a=t.conversation.id,e=t.isActive?"true":void 0,f=l("w-full rounded-lg text-left transition-colors",t.compact?"px-2.5 py-1.5":"px-2.5 py-2",t.isActive?"bg-muted":"hover:bg-muted/50",t.class);return a!==r.e&&d(i,"data-conversation-id",r.e=a),e!==r.t&&d(i,"aria-current",r.t=e),f!==r.a&&m(i,r.a=f),r},{e:void 0,t:void 0,a:void 0}),i})()}C(["click","keydown"]);export{U as C,F as S,B as i,N as r};
@@ -0,0 +1 @@
1
+ import{c as a,q as M,s as z,g as N,k as x,o as O,i as h,S as f,u as T,a as k,F as C,m as j,b as q,t as d,d as K,e as L}from"./define-By-uL588.js";import{c as S}from"./cn-DN5AWfiS.js";import{a as P,b as R,C as U}from"./collapsible-B4DlWicL.js";import{B as I}from"./button-DkuOnGLy.js";import{B as F}from"./badge-CdEu_jn2.js";import{S as B}from"./scroll-area-BqLUo8ZZ.js";import{C as D}from"./conversation-item-BxwQLaFJ.js";import{I as H}from"./Icon-DObhsRtm.js";var G=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m14 9 3 3-3 3",key:"8010ee"}]],J=i=>a(H,M(i,{name:"PanelLeftOpen",iconNode:G})),Q=J,V=d('<div class="px-3 pb-2"><div class="flex items-center gap-2 rounded-md bg-surface-strong px-2.5 py-1.5"><svg width=13 height=13 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 class=text-muted-foreground><circle cx=11 cy=11 r=8></circle><line x1=21 y1=21 x2=16.65 y2=16.65></line></svg><input type=text placeholder="Search chats..."aria-label="Search chats"class="bg-transparent text-compact text-foreground placeholder:text-muted-foreground rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring w-full">'),W=d('<div role=list aria-label=Conversations part=items class="space-y-0.5 py-1">'),X=d('<div class="flex flex-1 flex-col items-center justify-center gap-1 p-6 text-center text-sm text-muted-foreground">No conversations match your search'),Y=d('<div class="space-y-0.5 py-1">'),Z=d('<div class="shrink-0 border-t border-border">'),_=d("<div>"),ee=d('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=3 y1=12 x2=21 y2=12></line><line x1=3 y1=6 x2=21 y2=6></line><line x1=3 y1=18 x2=21 y2=18>'),te=d('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=12 y1=5 x2=12 y2=19></line><line x1=5 y1=12 x2=19 y2=12>'),re=d('<div class="flex items-center justify-between p-3 pb-2"><div class="flex items-center gap-2"><span class="text-sm font-semibold text-foreground">Chats'),ne=d('<div class="flex flex-1 flex-col items-center justify-center gap-1 p-6 text-center text-sm text-muted-foreground">No conversations yet'),oe=d('<svg width=10 height=10 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><polyline points="6 9 12 15 18 9">'),ae=d("<span>"),ie=d('<div class="pl-2 mt-0.5 space-y-0.5">');function le(i){return a(I,{variant:"ghost",size:"icon-sm","aria-label":"Open sidebar",get class(){return S("rounded-full bg-card/80 shadow-sm backdrop-blur",i.class)},get onClick(){return i.onExpand},get children(){return a(Q,{class:"size-4"})}})}function w(i){const e=i.conversationId;return typeof e=="string"&&e?e:i.getAttribute("conversation-id")??i.id}function ce(i){var e;return((e=i.parentElement)==null?void 0:e.localName)!=="kai-conversations"}function se(i){const e=n=>{const r=i.getItems();return n.composedPath().find(c=>r.includes(c))},p=n=>{var r;return((r=n.shadowRoot)==null?void 0:r.querySelector("[data-kai-item-body]"))??n},u=n=>n.composedPath().some(r=>r instanceof Element&&(r.hasAttribute("data-kai-item-menu")||r.getAttribute("slot")==="menu")),m=(n,r,c)=>{n.getAttribute(r)!==c&&n.setAttribute(r,c)},y=n=>{const r=new Map;for(const c of n){const s=p(c);s===c&&c.localName.includes("-")||r.set(c,s)}return r},v=(n,r)=>{for(const[c,s]of y(n))m(s,"tabindex",c===r?"0":"-1")};return{sync:()=>{const n=i.getItems(),r=i.getActiveId(),c=y(n);let s;for(const[o,t]of c){const l=r!==void 0&&w(o)===r;t.hasAttribute("role")||t.setAttribute("role","button"),m(t,"aria-current",l?"true":"false");const g=o;g.active!==l&&(g.active=l),l&&(s=o)}v(n,s??c.keys().next().value)},handleClick(n){const r=e(n);!r||u(n)||i.onSelect(w(r))},handleKeyDown(n){const r=i.getItems();if(r.length===0)return;const c=e(n);if(n.key==="Enter"||n.key===" "){if(!c||u(n))return;n.preventDefault(),i.onSelect(w(c));return}let s;const o=c?r.indexOf(c):r.findIndex(t=>p(t).getAttribute("tabindex")==="0");n.key==="ArrowDown"?s=r[Math.min(o+1,r.length-1)]:n.key==="ArrowUp"?s=r[Math.max(o-1,0)]:n.key==="Home"?s=r[0]:n.key==="End"&&(s=r[r.length-1]),s&&(n.preventDefault(),v(r,s),p(s).focus())}}}function ue(i){const[e]=z(i,["groups","conversations","activeId","onSelect","onNewChat","onToggleSidebar","header","footer","empty","compact","onSearchChange","controllerRef","items","itemsKeyDown","itemsClick","class"]),[p,u]=N(""),m=x(()=>e.items!=null),y=x(()=>e.conversations.length===0);let v;const n=o=>{var t;u(o),(t=e.onSearchChange)==null||t.call(e,o)};O(()=>{var o;(o=e.controllerRef)==null||o.call(e,{focus:t=>v?.focus(t),clearSearch:()=>n("")})});const r=x(()=>{const o=p().toLowerCase();return o?e.conversations.filter(t=>t.title.toLowerCase().includes(o)):e.conversations}),c=x(()=>{const o=new Map;for(const t of r()){const l=t.groupId;o.has(l)||o.set(l,[]),o.get(l).push(t)}return o}),s=x(()=>{const o=new Set((e.groups??[]).map(t=>t.id));return r().filter(t=>t.groupId==null||!o.has(t.groupId))});return(()=>{var o=_();return h(o,a(f,{get when(){return e.header},get fallback(){return(()=>{var t=re(),l=t.firstChild,g=l.firstChild;return h(l,a(I,{variant:"ghost",size:"icon-sm","aria-label":"Toggle sidebar",get onClick(){return e.onToggleSidebar},get children(){return ee()}}),g),h(t,a(I,{variant:"ghost",size:"icon-sm","aria-label":"New chat",get onClick(){return e.onNewChat},get children(){return te()}}),null),t})()},get children(){return e.header}}),null),h(o,a(f,{get when(){return m()||!y()},get children(){var t=V(),l=t.firstChild,g=l.firstChild,b=g.nextSibling;b.$$input=E=>n(E.currentTarget.value);var A=v;return typeof A=="function"?T(A,b):v=b,k(()=>b.value=p()),t}}),null),h(o,a(f,{get when(){return m()},get children(){return a(B,{class:"flex-1 px-2",get children(){var t=W();return t.$$click=l=>{var g;return(g=e.itemsClick)==null?void 0:g.call(e,l)},t.$$keydown=l=>{var g;return(g=e.itemsKeyDown)==null?void 0:g.call(e,l)},h(t,()=>e.items),t}})}}),null),h(o,a(f,{get when(){return j(()=>!m())()&&!y()},get fallback(){return a(f,{get when(){return!m()},get children(){return a(f,{get when(){return e.empty},get fallback(){return ne()},get children(){return e.empty}})}})},get children(){return[a(f,{get when(){return r().length===0},get children(){return X()}}),a(f,{get when(){return r().length>0},get children(){return a(B,{class:"flex-1 px-2",get children(){return[a(C,{get each(){return e.groups},children:t=>{const l=x(()=>c().get(t.id)??[]);return a(f,{get when(){return l().length>0},get children(){return a($,{get name(){return t.name},get count(){return l().length},get conversations(){return l()},get activeId(){return e.activeId},get onSelect(){return e.onSelect},get compact(){return e.compact}})}})}}),a(f,{get when(){return s().length>0},get children(){return a(f,{get when(){return e.compact},get fallback(){return a($,{name:"Ungrouped",get count(){return s().length},get conversations(){return s()},get activeId(){return e.activeId},get onSelect(){return e.onSelect}})},get children(){var t=Y();return h(t,a(C,{get each(){return s()},children:l=>a(D,{conversation:l,get isActive(){return l.id===e.activeId},get onSelect(){return e.onSelect},compact:!0})})),t}})}})]}})}})]}}),null),h(o,a(f,{get when(){return e.footer},get children(){var t=Z();return h(t,()=>e.footer),t}}),null),k(()=>q(o,S("flex flex-col h-full bg-sidebar",e.class))),o})()}function $(i){const[e,p]=N(!0);return a(U,{get open(){return e()},onOpenChange:p,get children(){return[a(P,{class:"flex items-center gap-1.5 w-full px-1.5 py-1 rounded-md text-compact text-muted-foreground font-medium hover:bg-muted/30 transition-colors cursor-pointer mt-1.5",get children(){return[(()=>{var u=oe();return k(()=>K(u,"class",S("transition-transform",!e()&&"-rotate-90"))),u})(),(()=>{var u=ae();return h(u,()=>i.name),u})(),a(F,{variant:"count",class:"ml-auto text-caption",get children(){return i.count}})]}}),a(R,{get children(){var u=ie();return h(u,a(C,{get each(){return i.conversations},children:m=>a(D,{conversation:m,get isActive(){return m.id===i.activeId},get onSelect(){return i.onSelect},get compact(){return i.compact}})})),u}})]}})}L(["input","keydown","click"]);export{ue as C,le as a,se as c,ce as i,w as r};
@@ -1 +1 @@
1
- import{I as a}from"./Icon-BnFKqqtY.js";import{c as o,q as c}from"./define-CGGX-7Vg.js";var e=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],t=r=>o(a,c(r,{name:"Copy",iconNode:e})),i=t;export{i as c};
1
+ import{I as a}from"./Icon-DObhsRtm.js";import{c as o,q as c}from"./define-By-uL588.js";var e=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],t=r=>o(a,c(r,{name:"Copy",iconNode:e})),i=t;export{i as c};
@@ -1,6 +1,6 @@
1
1
  import { ssr as Le, ssrAttribute as we, escape as ye } from "solid-js/web";
2
2
  import { createMemo as U, onCleanup as G, createEffect as ue, untrack as ve, createSignal as le } from "solid-js";
3
- import { c as Re } from "./solid-DFhsce3O.js";
3
+ import { c as Re } from "./solid-DruVOXnf.js";
4
4
  var _e = ['<canvas part="canvas"', "></canvas>"];
5
5
  const Ce = "#1FD5F9";
6
6
  function Ie(e) {
@@ -1,6 +1,6 @@
1
1
  import { effect as Le, className as ye, template as we, use as Re } from "solid-js/web";
2
2
  import { createMemo as U, onCleanup as z, createEffect as ue, untrack as ve, createSignal as le } from "solid-js";
3
- import { c as _e } from "./solid-BE5ui6sy.js";
3
+ import { c as _e } from "./solid-BzCFdL25.js";
4
4
  var Ce = /* @__PURE__ */ we("<canvas part=canvas>");
5
5
  const Ie = "#1FD5F9";
6
6
  function Te(e) {
@@ -1,4 +1,4 @@
1
- import{t as ye,u as Le,c as Re,f as Ie}from"./register-impl-C7rENvPK.js";import{c as N,o as j,h as ce,u as fe,d as _e,i as ue}from"./kai.es.js";var Pe=ye("<canvas part=canvas>");const me="#1FD5F9";function ve(e){const n=e.trim().match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!n)return ve(me);const[,o,i,l]=n;return[parseInt(o,16)/255,parseInt(i,16)/255,parseInt(l,16)/255]}const Ce={"1f":"float","1i":"int","1fv":"float","2f":"vec2","3f":"vec3","3fv":"vec3","4f":"vec4","4fv":"vec4",Matrix2fv:"mat2",Matrix3fv:"mat3",Matrix4fv:"mat4"},Te={"1fv":1,"3fv":3,"4fv":4,Matrix2fv:4,Matrix3fv:9,Matrix4fv:16};function ke(e){const n=Te[e.type];if(!n||!Array.isArray(e.value))return;const o=e.value.length/n;return o>1&&Number.isInteger(o)?o:void 0}function he(e){return e.arraySize??ke(e)}const Oe=["uniform float iTime;","uniform vec2 iResolution;","uniform vec4 iMouse;","uniform int iFrame;","uniform vec4 iDate;"].join(`
1
+ import{t as ye,u as Le,c as Re,f as Ie}from"./register-impl-B1hLkrI8.js";import{c as N,o as j,h as ce,u as fe,d as _e,i as ue}from"./kai.es.js";var Pe=ye("<canvas part=canvas>");const me="#1FD5F9";function ve(e){const n=e.trim().match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!n)return ve(me);const[,o,i,l]=n;return[parseInt(o,16)/255,parseInt(i,16)/255,parseInt(l,16)/255]}const Ce={"1f":"float","1i":"int","1fv":"float","2f":"vec2","3f":"vec3","3fv":"vec3","4f":"vec4","4fv":"vec4",Matrix2fv:"mat2",Matrix3fv:"mat3",Matrix4fv:"mat4"},Te={"1fv":1,"3fv":3,"4fv":4,Matrix2fv:4,Matrix3fv:9,Matrix4fv:16};function ke(e){const n=Te[e.type];if(!n||!Array.isArray(e.value))return;const o=e.value.length/n;return o>1&&Number.isInteger(o)?o:void 0}function he(e){return e.arraySize??ke(e)}const Oe=["uniform float iTime;","uniform vec2 iResolution;","uniform vec4 iMouse;","uniform int iFrame;","uniform vec4 iDate;"].join(`
2
2
  `),De=`
3
3
  attribute vec3 aVertexPosition;
4
4
  void main() { gl_Position = vec4(aVertexPosition, 1.0); }
@@ -1,4 +1,4 @@
1
- import{k as N,h as U,j as ce,z as fe,a as ye,b as Le,t as Re,u as Ie,g as ue}from"./define-CGGX-7Vg.js";import{c as _e}from"./cn-DN5AWfiS.js";var Pe=Re("<canvas part=canvas>");const me="#1FD5F9";function ve(e){const n=e.trim().match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!n)return ve(me);const[,o,a,l]=n;return[parseInt(o,16)/255,parseInt(a,16)/255,parseInt(l,16)/255]}const ke={"1f":"float","1i":"int","1fv":"float","2f":"vec2","3f":"vec3","3fv":"vec3","4f":"vec4","4fv":"vec4",Matrix2fv:"mat2",Matrix3fv:"mat3",Matrix4fv:"mat4"},Ce={"1fv":1,"3fv":3,"4fv":4,Matrix2fv:4,Matrix3fv:9,Matrix4fv:16};function Te(e){const n=Ce[e.type];if(!n||!Array.isArray(e.value))return;const o=e.value.length/n;return o>1&&Number.isInteger(o)?o:void 0}function he(e){return e.arraySize??Te(e)}const Oe=["uniform float iTime;","uniform vec2 iResolution;","uniform vec4 iMouse;","uniform int iFrame;","uniform vec4 iDate;"].join(`
1
+ import{k as N,h as U,j as ce,z as fe,a as ye,b as Le,t as Re,u as Ie,g as ue}from"./define-By-uL588.js";import{c as _e}from"./cn-DN5AWfiS.js";var Pe=Re("<canvas part=canvas>");const me="#1FD5F9";function ve(e){const n=e.trim().match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!n)return ve(me);const[,o,a,l]=n;return[parseInt(o,16)/255,parseInt(a,16)/255,parseInt(l,16)/255]}const ke={"1f":"float","1i":"int","1fv":"float","2f":"vec2","3f":"vec3","3fv":"vec3","4f":"vec4","4fv":"vec4",Matrix2fv:"mat2",Matrix3fv:"mat3",Matrix4fv:"mat4"},Ce={"1fv":1,"3fv":3,"4fv":4,Matrix2fv:4,Matrix3fv:9,Matrix4fv:16};function Te(e){const n=Ce[e.type];if(!n||!Array.isArray(e.value))return;const o=e.value.length/n;return o>1&&Number.isInteger(o)?o:void 0}function he(e){return e.arraySize??Te(e)}const Oe=["uniform float iTime;","uniform vec2 iResolution;","uniform vec4 iMouse;","uniform int iFrame;","uniform vec4 iDate;"].join(`
2
2
  `),De=`
3
3
  attribute vec3 aVertexPosition;
4
4
  void main() { gl_Position = vec4(aVertexPosition, 1.0); }
@@ -1761,7 +1761,7 @@
1761
1761
  "kind": "field",
1762
1762
  "name": "policy",
1763
1763
  "type": {
1764
- "text": "undefined | { onSubmit?: undefined | ((cardId: string, data: unknown) => void); onAction?: undefined | ((cardId: string, action: string, payload?: unknown) => void); onSendPrompt?: undefined | ((text: string, opts: { mode: \"compose\" | \"send\"; context?: unknown; }) => void); onOpen?: undefined | ((url: string, target: \"tab\" | \"artifact\") => void); onState?: undefined | ((cardId: string, patch: unknown) => void); onDismiss?: undefined | ((cardId: string) => void); onReopen?: undefined | ((cardId: string) => void); onError?: undefined | ((cardId: string, message: string) => void); maxSendPromptMode?: undefined | \"compose\" | \"send\" }"
1764
+ "text": "undefined | { onSubmit?: undefined | ((cardId: string, data: unknown) => void); onAction?: undefined | ((cardId: string, action: string, payload?: unknown) => void); onSendPrompt?: undefined | ((text: string, opts: { mode: \"compose\" | \"send\"; context?: unknown }) => void); onOpen?: undefined | ((url: string, target: \"tab\" | \"artifact\") => void); onState?: undefined | ((cardId: string, patch: unknown) => void); onDismiss?: undefined | ((cardId: string) => void); onReopen?: undefined | ((cardId: string) => void); onError?: undefined | ((cardId: string, message: string) => void); maxSendPromptMode?: undefined | \"compose\" | \"send\" }"
1765
1765
  },
1766
1766
  "description": "Optional CardPolicy handling child events. Property: `el.policy`.",
1767
1767
  "privacy": "public"
@@ -2320,6 +2320,33 @@
2320
2320
  "description": "JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `cardTypes`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `\"type\"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one.",
2321
2321
  "privacy": "public"
2322
2322
  },
2323
+ {
2324
+ "kind": "field",
2325
+ "name": "conversations",
2326
+ "type": {
2327
+ "text": "undefined | false | true"
2328
+ },
2329
+ "description": "Turns on the prior-conversations list (a list-toggle button in the header, plus a second list view sharing the panel, C-1). Attribute- settable like every other boolean flag on this element: `<kai-chat conversations>`. Requires `store`. A row select, \"new conversation,\" or the visitor's mount-time auto-restore all deliver their messages the same way: listen for `kai-conversation-load` and set `el.messages` from `event.detail.messages` (a fresh array): this element does not update `messages` for you. Set with no `store`, the underlying `ChatThread` decides loudly (one console.error) and stays visually off; this facade always supplies its own internal load handler (the `kai-conversation-load` dispatch below), so the second ChatThread guard, missing `onConversationLoad`, never trips here, even for a consumer who never listens for the event. Default false.",
2330
+ "privacy": "public"
2331
+ },
2332
+ {
2333
+ "kind": "field",
2334
+ "name": "store",
2335
+ "type": {
2336
+ "text": "undefined | { list: () => Promise<{ id: string; title: string; groupId?: undefined | string; scope?: undefined | { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt?: undefined | string; updatedAt: string; trailing?: undefined | string; lastReadAt?: undefined | string }[]>; load: (id: string) => Promise<{ id: string; role: \"user\" | \"assistant\"; parts: ({ type: \"text\"; text: string; raw?: undefined | { source: string; payload: unknown } } | { type: \"reasoning\"; text: string; label?: undefined | string; index?: undefined | number; streamId?: undefined | string; signature?: undefined | string; raw?: undefined | { source: string; payload: unknown } } | { type: \"tool\"; tool: { type: string; kind?: undefined | \"command\" | \"file-change\" | \"search\" | \"fetch\" | \"mcp\" | \"image\" | \"generic\"; state: \"input-streaming\" | \"input-available\" | \"output-available\" | \"output-error\"; input?: undefined | Record<string, unknown>; rawInput?: undefined | string; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string; raw?: undefined | { source: string; payload: unknown } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"card\"; envelope: { type: string; id: string; data: unknown; title?: undefined | string; resolution?: undefined | { kind: \"action\"; action: string; payload?: unknown; at?: undefined | string } | { kind: \"submit\"; data: unknown; at?: undefined | string } | { kind: \"dismissed\"; at?: undefined | string } | { kind: \"expired\"; reason?: undefined | string; at?: undefined | string } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"source\"; source: { id?: undefined | string; url?: undefined | string; title?: undefined | string; snippet?: undefined | string; index?: undefined | number }; raw?: undefined | { source: string; payload: unknown } } | { type: \"file\"; attachment: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }; raw?: undefined | { source: string; payload: unknown } })[]; actions?: undefined | (\"copy\" | \"like\" | \"dislike\" | \"regenerate\" | \"edit\" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | \"like\" | \"dislike\" }[]>; save: (id: string, messages: { id: string; role: \"user\" | \"assistant\"; parts: ({ type: \"text\"; text: string; raw?: undefined | { source: string; payload: unknown } } | { type: \"reasoning\"; text: string; label?: undefined | string; index?: undefined | number; streamId?: undefined | string; signature?: undefined | string; raw?: undefined | { source: string; payload: unknown } } | { type: \"tool\"; tool: { type: string; kind?: undefined | \"command\" | \"file-change\" | \"search\" | \"fetch\" | \"mcp\" | \"image\" | \"generic\"; state: \"input-streaming\" | \"input-available\" | \"output-available\" | \"output-error\"; input?: undefined | Record<string, unknown>; rawInput?: undefined | string; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string; raw?: undefined | { source: string; payload: unknown } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"card\"; envelope: { type: string; id: string; data: unknown; title?: undefined | string; resolution?: undefined | { kind: \"action\"; action: string; payload?: unknown; at?: undefined | string } | { kind: \"submit\"; data: unknown; at?: undefined | string } | { kind: \"dismissed\"; at?: undefined | string } | { kind: \"expired\"; reason?: undefined | string; at?: undefined | string } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"source\"; source: { id?: undefined | string; url?: undefined | string; title?: undefined | string; snippet?: undefined | string; index?: undefined | number }; raw?: undefined | { source: string; payload: unknown } } | { type: \"file\"; attachment: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }; raw?: undefined | { source: string; payload: unknown } })[]; actions?: undefined | (\"copy\" | \"like\" | \"dislike\" | \"regenerate\" | \"edit\" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | \"like\" | \"dislike\" }[]) => Promise<void>; markRead?: undefined | ((id: string) => Promise<void>) }"
2337
+ },
2338
+ "description": "The adapter this thread persists conversations through: an object of three functions (`list`/`load`/`save`; `ConversationStore`, exported from `@kitn.ai/ui`'s `primitives/conversation-store`). A JS PROPERTY ONLY: `el.store = myAdapter`. It can never be an attribute, since a function-bearing object has no HTML string form, the same reasoning that keeps `messages`/`cardSchemas` property-only (the kai- contract: array/object props are JS properties, never attributes). Two built-ins ship: `localStorageStore(name, userId?)` and `fetchStore(url, userId?)`.",
2339
+ "privacy": "public"
2340
+ },
2341
+ {
2342
+ "kind": "field",
2343
+ "name": "home",
2344
+ "type": {
2345
+ "text": "undefined | { greeting?: undefined | { title?: undefined | string; subtitle?: undefined | string }; recentConversation?: undefined | false | true; newConversation?: undefined | { label?: undefined | string }; links?: undefined | { label: string; href?: undefined | string; description?: undefined | string; icon?: undefined | string }[] }"
2346
+ },
2347
+ "description": "Turns on the widget home screen (Intercom-pattern): the panel boots into a `home` view, with a greeting, most-recent-conversation card, a \"new conversation\" CTA, and host-defined links, plus a Home/Messages tab bar for switching back to the thread. An OBJECT, so it is a JS property only: `el.home = { greeting: { title: 'Hey' }, links: [...] }`, never an attribute (the kai- contract: array/object props are JS properties). A `links` entry with no `href` fires `kai-home-link` with that entry when tapped, rather than navigating; one WITH `href` opens it directly (only when the URL passes the kit's own scheme allowlist). Omit for the no-home widget (chat view only, unchanged).",
2348
+ "privacy": "public"
2349
+ },
2323
2350
  {
2324
2351
  "kind": "method",
2325
2352
  "name": "focus",
@@ -2594,6 +2621,14 @@
2594
2621
  "text": "undefined | string"
2595
2622
  },
2596
2623
  "description": "Which attachment media types the user may stage, in HTML `accept` syntax: `<kai-chat accept=\"image/*,application/pdf\">`. A plain string, so unlike `messages` it DOES work as an attribute. Omitted means no filter. MEDIA TYPES ONLY -- exact (`image/png`) or subtype wildcard (`text/*`). HTML allows a file extension here and this does not: `accept=\".py\"` THROWS with the entry named, rather than silently resolving to a picker that accepts nothing. It can only NARROW what the kit can already encode: `accept=\"image/*\"` resolves to the four image formats both APIs take, not to every image type the OS offers. Pass the SAME string to `toOpenAIMessages(msgs, { accept })` and the picker and the wire cannot disagree -- both resolve it through `resolveMediaPolicy` against one declaration. That declaration is readable as `encodableMediaTypes()` from `@kitn.ai/ui/wire`, if you would rather build your own picker than use this prop."
2624
+ },
2625
+ {
2626
+ "name": "conversations",
2627
+ "fieldName": "conversations",
2628
+ "type": {
2629
+ "text": "undefined | false | true"
2630
+ },
2631
+ "description": "Turns on the prior-conversations list (a list-toggle button in the header, plus a second list view sharing the panel, C-1). Attribute- settable like every other boolean flag on this element: `<kai-chat conversations>`. Requires `store`. A row select, \"new conversation,\" or the visitor's mount-time auto-restore all deliver their messages the same way: listen for `kai-conversation-load` and set `el.messages` from `event.detail.messages` (a fresh array): this element does not update `messages` for you. Set with no `store`, the underlying `ChatThread` decides loudly (one console.error) and stays visually off; this facade always supplies its own internal load handler (the `kai-conversation-load` dispatch below), so the second ChatThread guard, missing `onConversationLoad`, never trips here, even for a consumer who never listens for the event. Default false."
2597
2632
  }
2598
2633
  ],
2599
2634
  "events": [
@@ -2611,6 +2646,20 @@
2611
2646
  },
2612
2647
  "description": "One or more picked files were refused because `accept` excluded them. The element renders NO message of its own: it reports the facts (name, media type, whether the kit could have sent it) and what the user should see is the application's call. Only ever fires when `accept` is set."
2613
2648
  },
2649
+ {
2650
+ "name": "kai-conversation-load",
2651
+ "type": {
2652
+ "text": "CustomEvent<{ id: string | undefined; messages: { id: string; role: \"user\" | \"assistant\"; parts: ({ type: \"text\"; text: string; raw?: undefined | { source: string; payload: unknown } } | { type: \"reasoning\"; text: string; label?: undefined | string; index?: undefined | number; streamId?: undefined | string; signature?: undefined | string; raw?: undefined | { source: string; payload: unknown } } | { type: \"tool\"; tool: { type: string; kind?: undefined | \"command\" | \"file-change\" | \"search\" | \"fetch\" | \"mcp\" | \"image\" | \"generic\"; state: \"input-streaming\" | \"input-available\" | \"output-available\" | \"output-error\"; input?: undefined | Record<string, unknown>; rawInput?: undefined | string; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string; raw?: undefined | { source: string; payload: unknown } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"card\"; envelope: { type: string; id: string; data: unknown; title?: undefined | string; resolution?: undefined | { kind: \"action\"; action: string; payload?: unknown; at?: undefined | string } | { kind: \"submit\"; data: unknown; at?: undefined | string } | { kind: \"dismissed\"; at?: undefined | string } | { kind: \"expired\"; reason?: undefined | string; at?: undefined | string } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"source\"; source: { id?: undefined | string; url?: undefined | string; title?: undefined | string; snippet?: undefined | string; index?: undefined | number }; raw?: undefined | { source: string; payload: unknown } } | { type: \"file\"; attachment: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }; raw?: undefined | { source: string; payload: unknown } })[]; actions?: undefined | (\"copy\" | \"like\" | \"dislike\" | \"regenerate\" | \"edit\" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | \"like\" | \"dislike\" }[] }>"
2653
+ },
2654
+ "description": "A conversation's history loaded: a row tap in the list, \"new conversation,\" or the visitor's own mount-time auto-restore of their most recent thread (only fires when `conversations` is on and a `store` is set). `detail.id` is that conversation's id, `undefined` for the \"new conversation\" case (no id exists until the first message mints one, C-6). Set `el.messages = event.detail.messages` (already a fresh array) to actually render it, since this element does not do that for you; `messages` stays your own state like everywhere else on this element."
2655
+ },
2656
+ {
2657
+ "name": "kai-home-link",
2658
+ "type": {
2659
+ "text": "CustomEvent<{ entry: { label: string; href?: undefined | string; description?: undefined | string; icon?: undefined | string } }>"
2660
+ },
2661
+ "description": "A `home.links` entry with no `href` was activated (tapped/clicked/Enter). Meaningful only when `home` is set."
2662
+ },
2614
2663
  {
2615
2664
  "name": "kai-message-action",
2616
2665
  "type": {
@@ -4748,7 +4797,7 @@
4748
4797
  "kind": "field",
4749
4798
  "name": "conversations",
4750
4799
  "type": {
4751
- "text": "undefined | { id: string; title: string; groupId?: undefined | string; scope?: undefined | { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt?: undefined | string; updatedAt: string; trailing?: undefined | string }[]"
4800
+ "text": "undefined | { id: string; title: string; groupId?: undefined | string; scope?: undefined | { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt?: undefined | string; updatedAt: string; trailing?: undefined | string; lastReadAt?: undefined | string }[]"
4752
4801
  },
4753
4802
  "description": "Every conversation the list renders, flat. Each one is filed under the group whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId` matching no entry in `groups`, falls into a trailing \"Ungrouped\" section, so nothing you pass in is ever dropped. There is no recency bucketing. Set as a JS property. Omit to supply them as `<kai-conversation>` light-DOM children instead, or for the empty state. A search query that matches nothing shows a visible \"No conversations match your search\" state, distinct from the zero-conversations empty state. Slotted `<kai-conversation-item>` children switch the list into item mode instead: your own rows win and this array is not rendered.",
4754
4803
  "privacy": "public"