@draht/web-ui 2026.3.2-2

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 (372) hide show
  1. package/CHANGELOG.md +276 -0
  2. package/README.md +601 -0
  3. package/dist/ChatPanel.d.ts +28 -0
  4. package/dist/ChatPanel.d.ts.map +1 -0
  5. package/dist/ChatPanel.js +193 -0
  6. package/dist/ChatPanel.js.map +1 -0
  7. package/dist/app.css +2 -0
  8. package/dist/components/AgentInterface.d.ts +39 -0
  9. package/dist/components/AgentInterface.d.ts.map +1 -0
  10. package/dist/components/AgentInterface.js +384 -0
  11. package/dist/components/AgentInterface.js.map +1 -0
  12. package/dist/components/AttachmentTile.d.ts +12 -0
  13. package/dist/components/AttachmentTile.d.ts.map +1 -0
  14. package/dist/components/AttachmentTile.js +110 -0
  15. package/dist/components/AttachmentTile.js.map +1 -0
  16. package/dist/components/ConsoleBlock.d.ts +12 -0
  17. package/dist/components/ConsoleBlock.d.ts.map +1 -0
  18. package/dist/components/ConsoleBlock.js +81 -0
  19. package/dist/components/ConsoleBlock.js.map +1 -0
  20. package/dist/components/CustomProviderCard.d.ts +17 -0
  21. package/dist/components/CustomProviderCard.d.ts.map +1 -0
  22. package/dist/components/CustomProviderCard.js +112 -0
  23. package/dist/components/CustomProviderCard.js.map +1 -0
  24. package/dist/components/ExpandableSection.d.ts +15 -0
  25. package/dist/components/ExpandableSection.d.ts.map +1 -0
  26. package/dist/components/ExpandableSection.js +61 -0
  27. package/dist/components/ExpandableSection.js.map +1 -0
  28. package/dist/components/Input.d.ts +26 -0
  29. package/dist/components/Input.d.ts.map +1 -0
  30. package/dist/components/Input.js +57 -0
  31. package/dist/components/Input.js.map +1 -0
  32. package/dist/components/MessageEditor.d.ts +44 -0
  33. package/dist/components/MessageEditor.d.ts.map +1 -0
  34. package/dist/components/MessageEditor.js +418 -0
  35. package/dist/components/MessageEditor.js.map +1 -0
  36. package/dist/components/MessageList.d.ts +14 -0
  37. package/dist/components/MessageList.d.ts.map +1 -0
  38. package/dist/components/MessageList.js +104 -0
  39. package/dist/components/MessageList.js.map +1 -0
  40. package/dist/components/Messages.d.ts +95 -0
  41. package/dist/components/Messages.d.ts.map +1 -0
  42. package/dist/components/Messages.js +363 -0
  43. package/dist/components/Messages.js.map +1 -0
  44. package/dist/components/ProviderKeyInput.d.ts +16 -0
  45. package/dist/components/ProviderKeyInput.d.ts.map +1 -0
  46. package/dist/components/ProviderKeyInput.js +168 -0
  47. package/dist/components/ProviderKeyInput.js.map +1 -0
  48. package/dist/components/SandboxedIframe.d.ts +85 -0
  49. package/dist/components/SandboxedIframe.d.ts.map +1 -0
  50. package/dist/components/SandboxedIframe.js +518 -0
  51. package/dist/components/SandboxedIframe.js.map +1 -0
  52. package/dist/components/StreamingMessageContainer.d.ts +19 -0
  53. package/dist/components/StreamingMessageContainer.d.ts.map +1 -0
  54. package/dist/components/StreamingMessageContainer.js +117 -0
  55. package/dist/components/StreamingMessageContainer.js.map +1 -0
  56. package/dist/components/ThinkingBlock.d.ts +11 -0
  57. package/dist/components/ThinkingBlock.d.ts.map +1 -0
  58. package/dist/components/ThinkingBlock.js +56 -0
  59. package/dist/components/ThinkingBlock.js.map +1 -0
  60. package/dist/components/message-renderer-registry.d.ts +12 -0
  61. package/dist/components/message-renderer-registry.d.ts.map +1 -0
  62. package/dist/components/message-renderer-registry.js +12 -0
  63. package/dist/components/message-renderer-registry.js.map +1 -0
  64. package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts +35 -0
  65. package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts.map +1 -0
  66. package/dist/components/sandbox/ArtifactsRuntimeProvider.js +192 -0
  67. package/dist/components/sandbox/ArtifactsRuntimeProvider.js.map +1 -0
  68. package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts +17 -0
  69. package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts.map +1 -0
  70. package/dist/components/sandbox/AttachmentsRuntimeProvider.js +65 -0
  71. package/dist/components/sandbox/AttachmentsRuntimeProvider.js.map +1 -0
  72. package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts +42 -0
  73. package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts.map +1 -0
  74. package/dist/components/sandbox/ConsoleRuntimeProvider.js +159 -0
  75. package/dist/components/sandbox/ConsoleRuntimeProvider.js.map +1 -0
  76. package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts +30 -0
  77. package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts.map +1 -0
  78. package/dist/components/sandbox/FileDownloadRuntimeProvider.js +95 -0
  79. package/dist/components/sandbox/FileDownloadRuntimeProvider.js.map +1 -0
  80. package/dist/components/sandbox/RuntimeMessageBridge.d.ts +19 -0
  81. package/dist/components/sandbox/RuntimeMessageBridge.d.ts.map +1 -0
  82. package/dist/components/sandbox/RuntimeMessageBridge.js +74 -0
  83. package/dist/components/sandbox/RuntimeMessageBridge.js.map +1 -0
  84. package/dist/components/sandbox/RuntimeMessageRouter.d.ts +65 -0
  85. package/dist/components/sandbox/RuntimeMessageRouter.d.ts.map +1 -0
  86. package/dist/components/sandbox/RuntimeMessageRouter.js +166 -0
  87. package/dist/components/sandbox/RuntimeMessageRouter.js.map +1 -0
  88. package/dist/components/sandbox/SandboxRuntimeProvider.d.ts +48 -0
  89. package/dist/components/sandbox/SandboxRuntimeProvider.d.ts.map +1 -0
  90. package/dist/components/sandbox/SandboxRuntimeProvider.js +2 -0
  91. package/dist/components/sandbox/SandboxRuntimeProvider.js.map +1 -0
  92. package/dist/dialogs/ApiKeyPromptDialog.d.ts +15 -0
  93. package/dist/dialogs/ApiKeyPromptDialog.d.ts.map +1 -0
  94. package/dist/dialogs/ApiKeyPromptDialog.js +77 -0
  95. package/dist/dialogs/ApiKeyPromptDialog.js.map +1 -0
  96. package/dist/dialogs/AttachmentOverlay.d.ts +32 -0
  97. package/dist/dialogs/AttachmentOverlay.d.ts.map +1 -0
  98. package/dist/dialogs/AttachmentOverlay.js +576 -0
  99. package/dist/dialogs/AttachmentOverlay.js.map +1 -0
  100. package/dist/dialogs/CustomProviderDialog.d.ts +25 -0
  101. package/dist/dialogs/CustomProviderDialog.d.ts.map +1 -0
  102. package/dist/dialogs/CustomProviderDialog.js +270 -0
  103. package/dist/dialogs/CustomProviderDialog.js.map +1 -0
  104. package/dist/dialogs/ModelSelector.d.ts +27 -0
  105. package/dist/dialogs/ModelSelector.d.ts.map +1 -0
  106. package/dist/dialogs/ModelSelector.js +320 -0
  107. package/dist/dialogs/ModelSelector.js.map +1 -0
  108. package/dist/dialogs/PersistentStorageDialog.d.ts +17 -0
  109. package/dist/dialogs/PersistentStorageDialog.d.ts.map +1 -0
  110. package/dist/dialogs/PersistentStorageDialog.js +144 -0
  111. package/dist/dialogs/PersistentStorageDialog.js.map +1 -0
  112. package/dist/dialogs/ProvidersModelsTab.d.ts +20 -0
  113. package/dist/dialogs/ProvidersModelsTab.d.ts.map +1 -0
  114. package/dist/dialogs/ProvidersModelsTab.js +188 -0
  115. package/dist/dialogs/ProvidersModelsTab.js.map +1 -0
  116. package/dist/dialogs/SessionListDialog.d.ts +19 -0
  117. package/dist/dialogs/SessionListDialog.d.ts.map +1 -0
  118. package/dist/dialogs/SessionListDialog.js +152 -0
  119. package/dist/dialogs/SessionListDialog.js.map +1 -0
  120. package/dist/dialogs/SettingsDialog.d.ts +30 -0
  121. package/dist/dialogs/SettingsDialog.d.ts.map +1 -0
  122. package/dist/dialogs/SettingsDialog.js +222 -0
  123. package/dist/dialogs/SettingsDialog.js.map +1 -0
  124. package/dist/index.d.ts +67 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +70 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/prompts/prompts.d.ts +11 -0
  129. package/dist/prompts/prompts.d.ts.map +1 -0
  130. package/dist/prompts/prompts.js +272 -0
  131. package/dist/prompts/prompts.js.map +1 -0
  132. package/dist/storage/app-storage.d.ts +33 -0
  133. package/dist/storage/app-storage.d.ts.map +1 -0
  134. package/dist/storage/app-storage.js +43 -0
  135. package/dist/storage/app-storage.js.map +1 -0
  136. package/dist/storage/backends/indexeddb-storage-backend.d.ts +27 -0
  137. package/dist/storage/backends/indexeddb-storage-backend.d.ts.map +1 -0
  138. package/dist/storage/backends/indexeddb-storage-backend.js +167 -0
  139. package/dist/storage/backends/indexeddb-storage-backend.js.map +1 -0
  140. package/dist/storage/store.d.ts +23 -0
  141. package/dist/storage/store.d.ts.map +1 -0
  142. package/dist/storage/store.js +24 -0
  143. package/dist/storage/store.js.map +1 -0
  144. package/dist/storage/stores/custom-providers-store.d.ts +25 -0
  145. package/dist/storage/stores/custom-providers-store.d.ts.map +1 -0
  146. package/dist/storage/stores/custom-providers-store.js +35 -0
  147. package/dist/storage/stores/custom-providers-store.js.map +1 -0
  148. package/dist/storage/stores/provider-keys-store.d.ts +14 -0
  149. package/dist/storage/stores/provider-keys-store.d.ts.map +1 -0
  150. package/dist/storage/stores/provider-keys-store.js +27 -0
  151. package/dist/storage/stores/provider-keys-store.js.map +1 -0
  152. package/dist/storage/stores/sessions-store.d.ts +32 -0
  153. package/dist/storage/stores/sessions-store.d.ts.map +1 -0
  154. package/dist/storage/stores/sessions-store.js +113 -0
  155. package/dist/storage/stores/sessions-store.js.map +1 -0
  156. package/dist/storage/stores/settings-store.d.ts +14 -0
  157. package/dist/storage/stores/settings-store.d.ts.map +1 -0
  158. package/dist/storage/stores/settings-store.js +28 -0
  159. package/dist/storage/stores/settings-store.js.map +1 -0
  160. package/dist/storage/types.d.ts +176 -0
  161. package/dist/storage/types.d.ts.map +1 -0
  162. package/dist/storage/types.js +2 -0
  163. package/dist/storage/types.js.map +1 -0
  164. package/dist/tools/artifacts/ArtifactElement.d.ts +9 -0
  165. package/dist/tools/artifacts/ArtifactElement.d.ts.map +1 -0
  166. package/dist/tools/artifacts/ArtifactElement.js +8 -0
  167. package/dist/tools/artifacts/ArtifactElement.js.map +1 -0
  168. package/dist/tools/artifacts/ArtifactPill.d.ts +4 -0
  169. package/dist/tools/artifacts/ArtifactPill.d.ts.map +1 -0
  170. package/dist/tools/artifacts/ArtifactPill.js +23 -0
  171. package/dist/tools/artifacts/ArtifactPill.js.map +1 -0
  172. package/dist/tools/artifacts/Console.d.ts +18 -0
  173. package/dist/tools/artifacts/Console.d.ts.map +1 -0
  174. package/dist/tools/artifacts/Console.js +92 -0
  175. package/dist/tools/artifacts/Console.js.map +1 -0
  176. package/dist/tools/artifacts/DocxArtifact.d.ts +22 -0
  177. package/dist/tools/artifacts/DocxArtifact.d.ts.map +1 -0
  178. package/dist/tools/artifacts/DocxArtifact.js +205 -0
  179. package/dist/tools/artifacts/DocxArtifact.js.map +1 -0
  180. package/dist/tools/artifacts/ExcelArtifact.d.ts +24 -0
  181. package/dist/tools/artifacts/ExcelArtifact.d.ts.map +1 -0
  182. package/dist/tools/artifacts/ExcelArtifact.js +213 -0
  183. package/dist/tools/artifacts/ExcelArtifact.js.map +1 -0
  184. package/dist/tools/artifacts/GenericArtifact.d.ts +19 -0
  185. package/dist/tools/artifacts/GenericArtifact.d.ts.map +1 -0
  186. package/dist/tools/artifacts/GenericArtifact.js +114 -0
  187. package/dist/tools/artifacts/GenericArtifact.js.map +1 -0
  188. package/dist/tools/artifacts/HtmlArtifact.d.ts +27 -0
  189. package/dist/tools/artifacts/HtmlArtifact.d.ts.map +1 -0
  190. package/dist/tools/artifacts/HtmlArtifact.js +187 -0
  191. package/dist/tools/artifacts/HtmlArtifact.js.map +1 -0
  192. package/dist/tools/artifacts/ImageArtifact.d.ts +20 -0
  193. package/dist/tools/artifacts/ImageArtifact.d.ts.map +1 -0
  194. package/dist/tools/artifacts/ImageArtifact.js +117 -0
  195. package/dist/tools/artifacts/ImageArtifact.js.map +1 -0
  196. package/dist/tools/artifacts/MarkdownArtifact.d.ts +19 -0
  197. package/dist/tools/artifacts/MarkdownArtifact.d.ts.map +1 -0
  198. package/dist/tools/artifacts/MarkdownArtifact.js +79 -0
  199. package/dist/tools/artifacts/MarkdownArtifact.js.map +1 -0
  200. package/dist/tools/artifacts/PdfArtifact.d.ts +25 -0
  201. package/dist/tools/artifacts/PdfArtifact.d.ts.map +1 -0
  202. package/dist/tools/artifacts/PdfArtifact.js +181 -0
  203. package/dist/tools/artifacts/PdfArtifact.js.map +1 -0
  204. package/dist/tools/artifacts/SvgArtifact.d.ts +18 -0
  205. package/dist/tools/artifacts/SvgArtifact.d.ts.map +1 -0
  206. package/dist/tools/artifacts/SvgArtifact.js +75 -0
  207. package/dist/tools/artifacts/SvgArtifact.js.map +1 -0
  208. package/dist/tools/artifacts/TextArtifact.d.ts +19 -0
  209. package/dist/tools/artifacts/TextArtifact.d.ts.map +1 -0
  210. package/dist/tools/artifacts/TextArtifact.js +141 -0
  211. package/dist/tools/artifacts/TextArtifact.js.map +1 -0
  212. package/dist/tools/artifacts/artifacts-tool-renderer.d.ts +11 -0
  213. package/dist/tools/artifacts/artifacts-tool-renderer.d.ts.map +1 -0
  214. package/dist/tools/artifacts/artifacts-tool-renderer.js +273 -0
  215. package/dist/tools/artifacts/artifacts-tool-renderer.js.map +1 -0
  216. package/dist/tools/artifacts/artifacts.d.ts +63 -0
  217. package/dist/tools/artifacts/artifacts.d.ts.map +1 -0
  218. package/dist/tools/artifacts/artifacts.js +664 -0
  219. package/dist/tools/artifacts/artifacts.js.map +1 -0
  220. package/dist/tools/artifacts/index.d.ts +8 -0
  221. package/dist/tools/artifacts/index.d.ts.map +1 -0
  222. package/dist/tools/artifacts/index.js +8 -0
  223. package/dist/tools/artifacts/index.js.map +1 -0
  224. package/dist/tools/extract-document.d.ts +24 -0
  225. package/dist/tools/extract-document.d.ts.map +1 -0
  226. package/dist/tools/extract-document.js +216 -0
  227. package/dist/tools/extract-document.js.map +1 -0
  228. package/dist/tools/index.d.ts +16 -0
  229. package/dist/tools/index.d.ts.map +1 -0
  230. package/dist/tools/index.js +33 -0
  231. package/dist/tools/index.js.map +1 -0
  232. package/dist/tools/javascript-repl.d.ts +44 -0
  233. package/dist/tools/javascript-repl.d.ts.map +1 -0
  234. package/dist/tools/javascript-repl.js +224 -0
  235. package/dist/tools/javascript-repl.js.map +1 -0
  236. package/dist/tools/renderer-registry.d.ts +23 -0
  237. package/dist/tools/renderer-registry.d.ts.map +1 -0
  238. package/dist/tools/renderer-registry.js +107 -0
  239. package/dist/tools/renderer-registry.js.map +1 -0
  240. package/dist/tools/renderers/BashRenderer.d.ts +10 -0
  241. package/dist/tools/renderers/BashRenderer.d.ts.map +1 -0
  242. package/dist/tools/renderers/BashRenderer.js +42 -0
  243. package/dist/tools/renderers/BashRenderer.js.map +1 -0
  244. package/dist/tools/renderers/CalculateRenderer.d.ts +10 -0
  245. package/dist/tools/renderers/CalculateRenderer.d.ts.map +1 -0
  246. package/dist/tools/renderers/CalculateRenderer.js +45 -0
  247. package/dist/tools/renderers/CalculateRenderer.js.map +1 -0
  248. package/dist/tools/renderers/DefaultRenderer.d.ts +6 -0
  249. package/dist/tools/renderers/DefaultRenderer.d.ts.map +1 -0
  250. package/dist/tools/renderers/DefaultRenderer.js +94 -0
  251. package/dist/tools/renderers/DefaultRenderer.js.map +1 -0
  252. package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts +10 -0
  253. package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts.map +1 -0
  254. package/dist/tools/renderers/GetCurrentTimeRenderer.js +72 -0
  255. package/dist/tools/renderers/GetCurrentTimeRenderer.js.map +1 -0
  256. package/dist/tools/types.d.ts +10 -0
  257. package/dist/tools/types.d.ts.map +1 -0
  258. package/dist/tools/types.js +2 -0
  259. package/dist/tools/types.js.map +1 -0
  260. package/dist/utils/attachment-utils.d.ts +19 -0
  261. package/dist/utils/attachment-utils.d.ts.map +1 -0
  262. package/dist/utils/attachment-utils.js +415 -0
  263. package/dist/utils/attachment-utils.js.map +1 -0
  264. package/dist/utils/auth-token.d.ts +3 -0
  265. package/dist/utils/auth-token.d.ts.map +1 -0
  266. package/dist/utils/auth-token.js +19 -0
  267. package/dist/utils/auth-token.js.map +1 -0
  268. package/dist/utils/format.d.ts +6 -0
  269. package/dist/utils/format.d.ts.map +1 -0
  270. package/dist/utils/format.js +47 -0
  271. package/dist/utils/format.js.map +1 -0
  272. package/dist/utils/i18n.d.ts +636 -0
  273. package/dist/utils/i18n.d.ts.map +1 -0
  274. package/dist/utils/i18n.js +418 -0
  275. package/dist/utils/i18n.js.map +1 -0
  276. package/dist/utils/model-discovery.d.ts +38 -0
  277. package/dist/utils/model-discovery.d.ts.map +1 -0
  278. package/dist/utils/model-discovery.js +243 -0
  279. package/dist/utils/model-discovery.js.map +1 -0
  280. package/dist/utils/proxy-utils.d.ts +45 -0
  281. package/dist/utils/proxy-utils.d.ts.map +1 -0
  282. package/dist/utils/proxy-utils.js +116 -0
  283. package/dist/utils/proxy-utils.js.map +1 -0
  284. package/dist/utils/test-sessions.d.ts +359 -0
  285. package/dist/utils/test-sessions.d.ts.map +1 -0
  286. package/dist/utils/test-sessions.js +2325 -0
  287. package/dist/utils/test-sessions.js.map +1 -0
  288. package/example/README.md +61 -0
  289. package/example/index.html +13 -0
  290. package/example/package.json +25 -0
  291. package/example/src/app.css +1 -0
  292. package/example/src/custom-messages.ts +99 -0
  293. package/example/src/env.d.ts +1 -0
  294. package/example/src/main.ts +421 -0
  295. package/example/tsconfig.json +23 -0
  296. package/example/vite.config.ts +6 -0
  297. package/package.json +53 -0
  298. package/scripts/count-prompt-tokens.ts +88 -0
  299. package/src/ChatPanel.ts +207 -0
  300. package/src/app.css +68 -0
  301. package/src/components/AgentInterface.ts +388 -0
  302. package/src/components/AttachmentTile.ts +107 -0
  303. package/src/components/ConsoleBlock.ts +72 -0
  304. package/src/components/CustomProviderCard.ts +100 -0
  305. package/src/components/ExpandableSection.ts +46 -0
  306. package/src/components/Input.ts +113 -0
  307. package/src/components/MessageEditor.ts +400 -0
  308. package/src/components/MessageList.ts +95 -0
  309. package/src/components/Messages.ts +383 -0
  310. package/src/components/ProviderKeyInput.ts +153 -0
  311. package/src/components/SandboxedIframe.ts +626 -0
  312. package/src/components/StreamingMessageContainer.ts +103 -0
  313. package/src/components/ThinkingBlock.ts +43 -0
  314. package/src/components/message-renderer-registry.ts +28 -0
  315. package/src/components/sandbox/ArtifactsRuntimeProvider.ts +219 -0
  316. package/src/components/sandbox/AttachmentsRuntimeProvider.ts +66 -0
  317. package/src/components/sandbox/ConsoleRuntimeProvider.ts +186 -0
  318. package/src/components/sandbox/FileDownloadRuntimeProvider.ts +110 -0
  319. package/src/components/sandbox/RuntimeMessageBridge.ts +82 -0
  320. package/src/components/sandbox/RuntimeMessageRouter.ts +216 -0
  321. package/src/components/sandbox/SandboxRuntimeProvider.ts +52 -0
  322. package/src/dialogs/ApiKeyPromptDialog.ts +75 -0
  323. package/src/dialogs/AttachmentOverlay.ts +636 -0
  324. package/src/dialogs/CustomProviderDialog.ts +274 -0
  325. package/src/dialogs/ModelSelector.ts +313 -0
  326. package/src/dialogs/PersistentStorageDialog.ts +144 -0
  327. package/src/dialogs/ProvidersModelsTab.ts +212 -0
  328. package/src/dialogs/SessionListDialog.ts +150 -0
  329. package/src/dialogs/SettingsDialog.ts +214 -0
  330. package/src/index.ts +119 -0
  331. package/src/prompts/prompts.ts +282 -0
  332. package/src/storage/app-storage.ts +60 -0
  333. package/src/storage/backends/indexeddb-storage-backend.ts +193 -0
  334. package/src/storage/store.ts +33 -0
  335. package/src/storage/stores/custom-providers-store.ts +62 -0
  336. package/src/storage/stores/provider-keys-store.ts +33 -0
  337. package/src/storage/stores/sessions-store.ts +136 -0
  338. package/src/storage/stores/settings-store.ts +34 -0
  339. package/src/storage/types.ts +206 -0
  340. package/src/tools/artifacts/ArtifactElement.ts +14 -0
  341. package/src/tools/artifacts/ArtifactPill.ts +26 -0
  342. package/src/tools/artifacts/Console.ts +93 -0
  343. package/src/tools/artifacts/DocxArtifact.ts +213 -0
  344. package/src/tools/artifacts/ExcelArtifact.ts +231 -0
  345. package/src/tools/artifacts/GenericArtifact.ts +117 -0
  346. package/src/tools/artifacts/HtmlArtifact.ts +195 -0
  347. package/src/tools/artifacts/ImageArtifact.ts +116 -0
  348. package/src/tools/artifacts/MarkdownArtifact.ts +82 -0
  349. package/src/tools/artifacts/PdfArtifact.ts +201 -0
  350. package/src/tools/artifacts/SvgArtifact.ts +78 -0
  351. package/src/tools/artifacts/TextArtifact.ts +148 -0
  352. package/src/tools/artifacts/artifacts-tool-renderer.ts +310 -0
  353. package/src/tools/artifacts/artifacts.ts +713 -0
  354. package/src/tools/artifacts/index.ts +7 -0
  355. package/src/tools/extract-document.ts +275 -0
  356. package/src/tools/index.ts +46 -0
  357. package/src/tools/javascript-repl.ts +293 -0
  358. package/src/tools/renderer-registry.ts +130 -0
  359. package/src/tools/renderers/BashRenderer.ts +52 -0
  360. package/src/tools/renderers/CalculateRenderer.ts +58 -0
  361. package/src/tools/renderers/DefaultRenderer.ts +103 -0
  362. package/src/tools/renderers/GetCurrentTimeRenderer.ts +92 -0
  363. package/src/tools/types.ts +15 -0
  364. package/src/utils/attachment-utils.ts +472 -0
  365. package/src/utils/auth-token.ts +22 -0
  366. package/src/utils/format.ts +42 -0
  367. package/src/utils/i18n.ts +653 -0
  368. package/src/utils/model-discovery.ts +277 -0
  369. package/src/utils/proxy-utils.ts +134 -0
  370. package/src/utils/test-sessions.ts +2357 -0
  371. package/tsconfig.build.json +20 -0
  372. package/tsconfig.json +7 -0
@@ -0,0 +1,421 @@
1
+ import "@mariozechner/mini-lit/dist/ThemeToggle.js";
2
+ import { Agent, type AgentMessage } from "@draht/agent-core";
3
+ import { getModel } from "@draht/ai";
4
+ import {
5
+ type AgentState,
6
+ ApiKeyPromptDialog,
7
+ AppStorage,
8
+ ChatPanel,
9
+ CustomProvidersStore,
10
+ createJavaScriptReplTool,
11
+ IndexedDBStorageBackend,
12
+ // PersistentStorageDialog, // TODO: Fix - currently broken
13
+ ProviderKeysStore,
14
+ ProvidersModelsTab,
15
+ ProxyTab,
16
+ SessionListDialog,
17
+ SessionsStore,
18
+ SettingsDialog,
19
+ SettingsStore,
20
+ setAppStorage,
21
+ } from "@draht/web-ui";
22
+ import { html, render } from "lit";
23
+ import { Bell, History, Plus, Settings } from "lucide";
24
+ import "./app.css";
25
+ import { icon } from "@mariozechner/mini-lit";
26
+ import { Button } from "@mariozechner/mini-lit/dist/Button.js";
27
+ import { Input } from "@mariozechner/mini-lit/dist/Input.js";
28
+ import { createSystemNotification, customConvertToLlm, registerCustomMessageRenderers } from "./custom-messages.js";
29
+
30
+ // Register custom message renderers
31
+ registerCustomMessageRenderers();
32
+
33
+ // Create stores
34
+ const settings = new SettingsStore();
35
+ const providerKeys = new ProviderKeysStore();
36
+ const sessions = new SessionsStore();
37
+ const customProviders = new CustomProvidersStore();
38
+
39
+ // Gather configs
40
+ const configs = [
41
+ settings.getConfig(),
42
+ SessionsStore.getMetadataConfig(),
43
+ providerKeys.getConfig(),
44
+ customProviders.getConfig(),
45
+ sessions.getConfig(),
46
+ ];
47
+
48
+ // Create backend
49
+ const backend = new IndexedDBStorageBackend({
50
+ dbName: "pi-web-ui-example",
51
+ version: 2, // Incremented for custom-providers store
52
+ stores: configs,
53
+ });
54
+
55
+ // Wire backend to stores
56
+ settings.setBackend(backend);
57
+ providerKeys.setBackend(backend);
58
+ customProviders.setBackend(backend);
59
+ sessions.setBackend(backend);
60
+
61
+ // Create and set app storage
62
+ const storage = new AppStorage(settings, providerKeys, sessions, customProviders, backend);
63
+ setAppStorage(storage);
64
+
65
+ let currentSessionId: string | undefined;
66
+ let currentTitle = "";
67
+ let isEditingTitle = false;
68
+ let agent: Agent;
69
+ let chatPanel: ChatPanel;
70
+ let agentUnsubscribe: (() => void) | undefined;
71
+
72
+ const generateTitle = (messages: AgentMessage[]): string => {
73
+ const firstUserMsg = messages.find((m) => m.role === "user" || m.role === "user-with-attachments");
74
+ if (!firstUserMsg || (firstUserMsg.role !== "user" && firstUserMsg.role !== "user-with-attachments")) return "";
75
+
76
+ let text = "";
77
+ const content = firstUserMsg.content;
78
+
79
+ if (typeof content === "string") {
80
+ text = content;
81
+ } else {
82
+ const textBlocks = content.filter((c: any) => c.type === "text");
83
+ text = textBlocks.map((c: any) => c.text || "").join(" ");
84
+ }
85
+
86
+ text = text.trim();
87
+ if (!text) return "";
88
+
89
+ const sentenceEnd = text.search(/[.!?]/);
90
+ if (sentenceEnd > 0 && sentenceEnd <= 50) {
91
+ return text.substring(0, sentenceEnd + 1);
92
+ }
93
+ return text.length <= 50 ? text : `${text.substring(0, 47)}...`;
94
+ };
95
+
96
+ const shouldSaveSession = (messages: AgentMessage[]): boolean => {
97
+ const hasUserMsg = messages.some((m: any) => m.role === "user" || m.role === "user-with-attachments");
98
+ const hasAssistantMsg = messages.some((m: any) => m.role === "assistant");
99
+ return hasUserMsg && hasAssistantMsg;
100
+ };
101
+
102
+ const saveSession = async () => {
103
+ if (!storage.sessions || !currentSessionId || !agent || !currentTitle) return;
104
+
105
+ const state = agent.state;
106
+ if (!shouldSaveSession(state.messages)) return;
107
+
108
+ try {
109
+ // Create session data
110
+ const sessionData = {
111
+ id: currentSessionId,
112
+ title: currentTitle,
113
+ model: state.model!,
114
+ thinkingLevel: state.thinkingLevel,
115
+ messages: state.messages,
116
+ createdAt: new Date().toISOString(),
117
+ lastModified: new Date().toISOString(),
118
+ };
119
+
120
+ // Create session metadata
121
+ const metadata = {
122
+ id: currentSessionId,
123
+ title: currentTitle,
124
+ createdAt: sessionData.createdAt,
125
+ lastModified: sessionData.lastModified,
126
+ messageCount: state.messages.length,
127
+ usage: {
128
+ input: 0,
129
+ output: 0,
130
+ cacheRead: 0,
131
+ cacheWrite: 0,
132
+ totalTokens: 0,
133
+ cost: {
134
+ input: 0,
135
+ output: 0,
136
+ cacheRead: 0,
137
+ cacheWrite: 0,
138
+ total: 0,
139
+ },
140
+ },
141
+ modelId: state.model?.id || null,
142
+ thinkingLevel: state.thinkingLevel,
143
+ preview: generateTitle(state.messages),
144
+ };
145
+
146
+ await storage.sessions.save(sessionData, metadata);
147
+ } catch (err) {
148
+ console.error("Failed to save session:", err);
149
+ }
150
+ };
151
+
152
+ const updateUrl = (sessionId: string) => {
153
+ const url = new URL(window.location.href);
154
+ url.searchParams.set("session", sessionId);
155
+ window.history.replaceState({}, "", url);
156
+ };
157
+
158
+ const createAgent = async (initialState?: Partial<AgentState>) => {
159
+ if (agentUnsubscribe) {
160
+ agentUnsubscribe();
161
+ }
162
+
163
+ agent = new Agent({
164
+ initialState: initialState || {
165
+ systemPrompt: `You are a helpful AI assistant with access to various tools.
166
+
167
+ Available tools:
168
+ - JavaScript REPL: Execute JavaScript code in a sandboxed browser environment (can do calculations, get time, process data, create visualizations, etc.)
169
+ - Artifacts: Create interactive HTML, SVG, Markdown, and text artifacts
170
+
171
+ Feel free to use these tools when needed to provide accurate and helpful responses.`,
172
+ model: getModel("anthropic", "claude-sonnet-4-5-20250929"),
173
+ thinkingLevel: "off",
174
+ messages: [],
175
+ tools: [],
176
+ },
177
+ // Custom transformer: convert custom messages to LLM-compatible format
178
+ convertToLlm: customConvertToLlm,
179
+ });
180
+
181
+ agentUnsubscribe = agent.subscribe((event: any) => {
182
+ if (event.type === "state-update") {
183
+ const messages = event.state.messages;
184
+
185
+ // Generate title after first successful response
186
+ if (!currentTitle && shouldSaveSession(messages)) {
187
+ currentTitle = generateTitle(messages);
188
+ }
189
+
190
+ // Create session ID on first successful save
191
+ if (!currentSessionId && shouldSaveSession(messages)) {
192
+ currentSessionId = crypto.randomUUID();
193
+ updateUrl(currentSessionId);
194
+ }
195
+
196
+ // Auto-save
197
+ if (currentSessionId) {
198
+ saveSession();
199
+ }
200
+
201
+ renderApp();
202
+ }
203
+ });
204
+
205
+ await chatPanel.setAgent(agent, {
206
+ onApiKeyRequired: async (provider: string) => {
207
+ return await ApiKeyPromptDialog.prompt(provider);
208
+ },
209
+ toolsFactory: (_agent, _agentInterface, _artifactsPanel, runtimeProvidersFactory) => {
210
+ // Create javascript_repl tool with access to attachments + artifacts
211
+ const replTool = createJavaScriptReplTool();
212
+ replTool.runtimeProvidersFactory = runtimeProvidersFactory;
213
+ return [replTool];
214
+ },
215
+ });
216
+ };
217
+
218
+ const loadSession = async (sessionId: string): Promise<boolean> => {
219
+ if (!storage.sessions) return false;
220
+
221
+ const sessionData = await storage.sessions.get(sessionId);
222
+ if (!sessionData) {
223
+ console.error("Session not found:", sessionId);
224
+ return false;
225
+ }
226
+
227
+ currentSessionId = sessionId;
228
+ const metadata = await storage.sessions.getMetadata(sessionId);
229
+ currentTitle = metadata?.title || "";
230
+
231
+ await createAgent({
232
+ model: sessionData.model,
233
+ thinkingLevel: sessionData.thinkingLevel,
234
+ messages: sessionData.messages,
235
+ tools: [],
236
+ });
237
+
238
+ updateUrl(sessionId);
239
+ renderApp();
240
+ return true;
241
+ };
242
+
243
+ const newSession = () => {
244
+ const url = new URL(window.location.href);
245
+ url.search = "";
246
+ window.location.href = url.toString();
247
+ };
248
+
249
+ // ============================================================================
250
+ // RENDER
251
+ // ============================================================================
252
+ const renderApp = () => {
253
+ const app = document.getElementById("app");
254
+ if (!app) return;
255
+
256
+ const appHtml = html`
257
+ <div class="w-full h-screen flex flex-col bg-background text-foreground overflow-hidden">
258
+ <!-- Header -->
259
+ <div class="flex items-center justify-between border-b border-border shrink-0">
260
+ <div class="flex items-center gap-2 px-4 py-">
261
+ ${Button({
262
+ variant: "ghost",
263
+ size: "sm",
264
+ children: icon(History, "sm"),
265
+ onClick: () => {
266
+ SessionListDialog.open(
267
+ async (sessionId) => {
268
+ await loadSession(sessionId);
269
+ },
270
+ (deletedSessionId) => {
271
+ // Only reload if the current session was deleted
272
+ if (deletedSessionId === currentSessionId) {
273
+ newSession();
274
+ }
275
+ },
276
+ );
277
+ },
278
+ title: "Sessions",
279
+ })}
280
+ ${Button({
281
+ variant: "ghost",
282
+ size: "sm",
283
+ children: icon(Plus, "sm"),
284
+ onClick: newSession,
285
+ title: "New Session",
286
+ })}
287
+
288
+ ${
289
+ currentTitle
290
+ ? isEditingTitle
291
+ ? html`<div class="flex items-center gap-2">
292
+ ${Input({
293
+ type: "text",
294
+ value: currentTitle,
295
+ className: "text-sm w-64",
296
+ onChange: async (e: Event) => {
297
+ const newTitle = (e.target as HTMLInputElement).value.trim();
298
+ if (newTitle && newTitle !== currentTitle && storage.sessions && currentSessionId) {
299
+ await storage.sessions.updateTitle(currentSessionId, newTitle);
300
+ currentTitle = newTitle;
301
+ }
302
+ isEditingTitle = false;
303
+ renderApp();
304
+ },
305
+ onKeyDown: async (e: KeyboardEvent) => {
306
+ if (e.key === "Enter") {
307
+ const newTitle = (e.target as HTMLInputElement).value.trim();
308
+ if (newTitle && newTitle !== currentTitle && storage.sessions && currentSessionId) {
309
+ await storage.sessions.updateTitle(currentSessionId, newTitle);
310
+ currentTitle = newTitle;
311
+ }
312
+ isEditingTitle = false;
313
+ renderApp();
314
+ } else if (e.key === "Escape") {
315
+ isEditingTitle = false;
316
+ renderApp();
317
+ }
318
+ },
319
+ })}
320
+ </div>`
321
+ : html`<button
322
+ class="px-2 py-1 text-sm text-foreground hover:bg-secondary rounded transition-colors"
323
+ @click=${() => {
324
+ isEditingTitle = true;
325
+ renderApp();
326
+ requestAnimationFrame(() => {
327
+ const input = app?.querySelector('input[type="text"]') as HTMLInputElement;
328
+ if (input) {
329
+ input.focus();
330
+ input.select();
331
+ }
332
+ });
333
+ }}
334
+ title="Click to edit title"
335
+ >
336
+ ${currentTitle}
337
+ </button>`
338
+ : html`<span class="text-base font-semibold text-foreground">Pi Web UI Example</span>`
339
+ }
340
+ </div>
341
+ <div class="flex items-center gap-1 px-2">
342
+ ${Button({
343
+ variant: "ghost",
344
+ size: "sm",
345
+ children: icon(Bell, "sm"),
346
+ onClick: () => {
347
+ // Demo: Inject custom message (will appear on next agent run)
348
+ if (agent) {
349
+ agent.steer(
350
+ createSystemNotification(
351
+ "This is a custom message! It appears in the UI but is never sent to the LLM.",
352
+ ),
353
+ );
354
+ }
355
+ },
356
+ title: "Demo: Add Custom Notification",
357
+ })}
358
+ <theme-toggle></theme-toggle>
359
+ ${Button({
360
+ variant: "ghost",
361
+ size: "sm",
362
+ children: icon(Settings, "sm"),
363
+ onClick: () => SettingsDialog.open([new ProvidersModelsTab(), new ProxyTab()]),
364
+ title: "Settings",
365
+ })}
366
+ </div>
367
+ </div>
368
+
369
+ <!-- Chat Panel -->
370
+ ${chatPanel}
371
+ </div>
372
+ `;
373
+
374
+ render(appHtml, app);
375
+ };
376
+
377
+ // ============================================================================
378
+ // INIT
379
+ // ============================================================================
380
+ async function initApp() {
381
+ const app = document.getElementById("app");
382
+ if (!app) throw new Error("App container not found");
383
+
384
+ // Show loading
385
+ render(
386
+ html`
387
+ <div class="w-full h-screen flex items-center justify-center bg-background text-foreground">
388
+ <div class="text-muted-foreground">Loading...</div>
389
+ </div>
390
+ `,
391
+ app,
392
+ );
393
+
394
+ // TODO: Fix PersistentStorageDialog - currently broken
395
+ // Request persistent storage
396
+ // if (storage.sessions) {
397
+ // await PersistentStorageDialog.request();
398
+ // }
399
+
400
+ // Create ChatPanel
401
+ chatPanel = new ChatPanel();
402
+
403
+ // Check for session in URL
404
+ const urlParams = new URLSearchParams(window.location.search);
405
+ const sessionIdFromUrl = urlParams.get("session");
406
+
407
+ if (sessionIdFromUrl) {
408
+ const loaded = await loadSession(sessionIdFromUrl);
409
+ if (!loaded) {
410
+ // Session doesn't exist, redirect to new session
411
+ newSession();
412
+ return;
413
+ }
414
+ } else {
415
+ await createAgent();
416
+ }
417
+
418
+ renderApp();
419
+ }
420
+
421
+ initApp();
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "moduleResolution": "bundler",
7
+ "paths": {
8
+ "*": ["./*"],
9
+ "@draht/agent-core": ["../../agent/dist/index.d.ts"],
10
+ "@draht/ai": ["../../ai/dist/index.d.ts"],
11
+ "@draht/tui": ["../../tui/dist/index.d.ts"],
12
+ "@draht/web-ui": ["../dist/index.d.ts"]
13
+ },
14
+ "strict": true,
15
+ "skipLibCheck": true,
16
+ "esModuleInterop": true,
17
+ "allowSyntheticDefaultImports": true,
18
+ "experimentalDecorators": true,
19
+ "useDefineForClassFields": false
20
+ },
21
+ "include": ["src/**/*"],
22
+ "exclude": ["../src"]
23
+ }
@@ -0,0 +1,6 @@
1
+ import tailwindcss from "@tailwindcss/vite";
2
+ import { defineConfig } from "vite";
3
+
4
+ export default defineConfig({
5
+ plugins: [tailwindcss()],
6
+ });
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@draht/web-ui",
3
+ "version": "2026.3.2-2",
4
+ "description": "Reusable web UI components for AI chat interfaces powered by @draht/ai",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./app.css": "./dist/app.css"
11
+ },
12
+ "scripts": {
13
+ "clean": "rm -rf dist",
14
+ "build": "tsgo -p tsconfig.build.json && tailwindcss -i ./src/app.css -o ./dist/app.css --minify",
15
+ "dev": "concurrently --names \"build,example\" --prefix-colors \"cyan,green\" \"tsgo -p tsconfig.build.json --watch --preserveWatchOutput\" \"tailwindcss -i ./src/app.css -o ./dist/app.css --watch\" \"bun run dev --prefix example\"",
16
+ "dev:tsc": "concurrently --names \"build\" --prefix-colors \"cyan\" \"tsgo -p tsconfig.build.json --watch --preserveWatchOutput\" \"tailwindcss -i ./src/app.css -o ./dist/app.css --watch\"",
17
+ "check": "biome check --write --error-on-warnings . && tsgo --noEmit && cd example && biome check --write --error-on-warnings . && tsgo --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "@lmstudio/sdk": "^1.5.0",
21
+ "@draht/ai": "2026.3.1-7",
22
+ "@draht/tui": "2026.3.1-7",
23
+ "docx-preview": "^0.3.7",
24
+ "jszip": "^3.10.1",
25
+ "lucide": "^0.544.0",
26
+ "ollama": "^0.6.0",
27
+ "pdfjs-dist": "5.4.394",
28
+ "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
29
+ "@draht/agent-core": "2026.3.1-7",
30
+ "highlight.js": "^11.11.0"
31
+ },
32
+ "peerDependencies": {
33
+ "@mariozechner/mini-lit": "^0.2.0",
34
+ "lit": "^3.3.1"
35
+ },
36
+ "devDependencies": {
37
+ "@mariozechner/mini-lit": "^0.2.0",
38
+ "@tailwindcss/cli": "^4.0.0-beta.14",
39
+ "concurrently": "^9.2.1",
40
+ "typescript": "^6.0.0-beta"
41
+ },
42
+ "keywords": [
43
+ "ai",
44
+ "chat",
45
+ "ui",
46
+ "components",
47
+ "llm",
48
+ "web-components",
49
+ "mini-lit"
50
+ ],
51
+ "author": "Mario Zechner",
52
+ "license": "MIT"
53
+ }
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Count tokens in system prompts using Anthropic's token counter API
4
+ */
5
+
6
+ import * as prompts from "../src/prompts/prompts.js";
7
+
8
+ const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
9
+
10
+ if (!ANTHROPIC_API_KEY) {
11
+ console.error("Error: ANTHROPIC_API_KEY environment variable not set");
12
+ process.exit(1);
13
+ }
14
+
15
+ interface TokenCountResponse {
16
+ input_tokens: number;
17
+ }
18
+
19
+ async function countTokens(text: string): Promise<number> {
20
+ const response = await fetch("https://api.anthropic.com/v1/messages/count_tokens", {
21
+ method: "POST",
22
+ headers: {
23
+ "Content-Type": "application/json",
24
+ "x-api-key": ANTHROPIC_API_KEY,
25
+ "anthropic-version": "2023-06-01",
26
+ },
27
+ body: JSON.stringify({
28
+ model: "claude-3-5-sonnet-20241022",
29
+ messages: [
30
+ {
31
+ role: "user",
32
+ content: text,
33
+ },
34
+ ],
35
+ }),
36
+ });
37
+
38
+ if (!response.ok) {
39
+ const error = await response.text();
40
+ throw new Error(`API error: ${response.status} ${error}`);
41
+ }
42
+
43
+ const data = (await response.json()) as TokenCountResponse;
44
+ return data.input_tokens;
45
+ }
46
+
47
+ async function main() {
48
+ console.log("Counting tokens in prompts...\n");
49
+
50
+ const promptsToCount: Array<{ name: string; content: string }> = [
51
+ {
52
+ name: "ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RW",
53
+ content: prompts.ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RW,
54
+ },
55
+ {
56
+ name: "ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RO",
57
+ content: prompts.ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RO,
58
+ },
59
+ {
60
+ name: "ATTACHMENTS_RUNTIME_DESCRIPTION",
61
+ content: prompts.ATTACHMENTS_RUNTIME_DESCRIPTION,
62
+ },
63
+ {
64
+ name: "JAVASCRIPT_REPL_TOOL_DESCRIPTION (without runtime providers)",
65
+ content: prompts.JAVASCRIPT_REPL_TOOL_DESCRIPTION([]),
66
+ },
67
+ {
68
+ name: "ARTIFACTS_TOOL_DESCRIPTION (without runtime providers)",
69
+ content: prompts.ARTIFACTS_TOOL_DESCRIPTION([]),
70
+ },
71
+ ];
72
+
73
+ let total = 0;
74
+
75
+ for (const prompt of promptsToCount) {
76
+ try {
77
+ const tokens = await countTokens(prompt.content);
78
+ total += tokens;
79
+ console.log(`${prompt.name}: ${tokens.toLocaleString()} tokens`);
80
+ } catch (error) {
81
+ console.error(`Error counting tokens for ${prompt.name}:`, error);
82
+ }
83
+ }
84
+
85
+ console.log(`\nTotal: ${total.toLocaleString()} tokens`);
86
+ }
87
+
88
+ main();