@mariozechner/pi-web-ui 0.5.44 → 0.5.45

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 (346) hide show
  1. package/README.md +178 -99
  2. package/dist/ChatPanel.d.ts +15 -10
  3. package/dist/ChatPanel.d.ts.map +1 -1
  4. package/dist/ChatPanel.js +68 -100
  5. package/dist/ChatPanel.js.map +1 -1
  6. package/dist/{state/agent-session.d.ts → agent/agent.d.ts} +23 -19
  7. package/dist/agent/agent.d.ts.map +1 -0
  8. package/dist/{state/agent-session.js → agent/agent.js} +50 -32
  9. package/dist/agent/agent.js.map +1 -0
  10. package/dist/{state → agent}/transports/AppTransport.d.ts +1 -3
  11. package/dist/agent/transports/AppTransport.d.ts.map +1 -0
  12. package/dist/{state → agent}/transports/AppTransport.js +5 -4
  13. package/dist/{state → agent}/transports/AppTransport.js.map +1 -1
  14. package/dist/{state → agent}/transports/ProviderTransport.d.ts +1 -3
  15. package/dist/agent/transports/ProviderTransport.d.ts.map +1 -0
  16. package/dist/{state → agent}/transports/ProviderTransport.js +6 -7
  17. package/dist/agent/transports/ProviderTransport.js.map +1 -0
  18. package/dist/{state → agent}/transports/index.d.ts.map +1 -1
  19. package/dist/agent/transports/index.js.map +1 -0
  20. package/dist/{state → agent}/transports/proxy-types.d.ts.map +1 -1
  21. package/dist/agent/transports/proxy-types.js.map +1 -0
  22. package/dist/agent/transports/types.d.ts +12 -0
  23. package/dist/agent/transports/types.d.ts.map +1 -0
  24. package/dist/{state → agent}/transports/types.js.map +1 -1
  25. package/dist/{state → agent}/types.d.ts.map +1 -1
  26. package/dist/{state → agent}/types.js.map +1 -1
  27. package/dist/app.css +1 -1
  28. package/dist/components/AgentInterface.d.ts +7 -4
  29. package/dist/components/AgentInterface.d.ts.map +1 -1
  30. package/dist/components/AgentInterface.js +29 -17
  31. package/dist/components/AgentInterface.js.map +1 -1
  32. package/dist/components/ConsoleBlock.d.ts +1 -0
  33. package/dist/components/ConsoleBlock.d.ts.map +1 -1
  34. package/dist/components/ConsoleBlock.js +7 -1
  35. package/dist/components/ConsoleBlock.js.map +1 -1
  36. package/dist/components/ExpandableSection.d.ts +15 -0
  37. package/dist/components/ExpandableSection.d.ts.map +1 -0
  38. package/dist/components/ExpandableSection.js +63 -0
  39. package/dist/components/ExpandableSection.js.map +1 -0
  40. package/dist/components/MessageEditor.d.ts +8 -1
  41. package/dist/components/MessageEditor.d.ts.map +1 -1
  42. package/dist/components/MessageEditor.js +149 -6
  43. package/dist/components/MessageEditor.js.map +1 -1
  44. package/dist/components/MessageList.d.ts +3 -2
  45. package/dist/components/MessageList.d.ts.map +1 -1
  46. package/dist/components/MessageList.js +14 -1
  47. package/dist/components/MessageList.js.map +1 -1
  48. package/dist/components/Messages.d.ts +15 -6
  49. package/dist/components/Messages.d.ts.map +1 -1
  50. package/dist/components/Messages.js +17 -83
  51. package/dist/components/Messages.js.map +1 -1
  52. package/dist/components/ProviderKeyInput.d.ts.map +1 -1
  53. package/dist/components/ProviderKeyInput.js +6 -5
  54. package/dist/components/ProviderKeyInput.js.map +1 -1
  55. package/dist/components/SandboxedIframe.d.ts +29 -7
  56. package/dist/components/SandboxedIframe.d.ts.map +1 -1
  57. package/dist/components/SandboxedIframe.js +350 -282
  58. package/dist/components/SandboxedIframe.js.map +1 -1
  59. package/dist/components/message-renderer-registry.d.ts +12 -0
  60. package/dist/components/message-renderer-registry.d.ts.map +1 -0
  61. package/dist/components/message-renderer-registry.js +12 -0
  62. package/dist/components/message-renderer-registry.js.map +1 -0
  63. package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts +35 -0
  64. package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts.map +1 -0
  65. package/dist/components/sandbox/ArtifactsRuntimeProvider.js +189 -0
  66. package/dist/components/sandbox/ArtifactsRuntimeProvider.js.map +1 -0
  67. package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts +17 -0
  68. package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts.map +1 -0
  69. package/dist/components/sandbox/AttachmentsRuntimeProvider.js +64 -0
  70. package/dist/components/sandbox/AttachmentsRuntimeProvider.js.map +1 -0
  71. package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts +42 -0
  72. package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts.map +1 -0
  73. package/dist/components/sandbox/ConsoleRuntimeProvider.js +161 -0
  74. package/dist/components/sandbox/ConsoleRuntimeProvider.js.map +1 -0
  75. package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts +30 -0
  76. package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts.map +1 -0
  77. package/dist/components/sandbox/FileDownloadRuntimeProvider.js +97 -0
  78. package/dist/components/sandbox/FileDownloadRuntimeProvider.js.map +1 -0
  79. package/dist/components/sandbox/RuntimeMessageBridge.d.ts +19 -0
  80. package/dist/components/sandbox/RuntimeMessageBridge.d.ts.map +1 -0
  81. package/dist/components/sandbox/RuntimeMessageBridge.js +74 -0
  82. package/dist/components/sandbox/RuntimeMessageBridge.js.map +1 -0
  83. package/dist/components/sandbox/RuntimeMessageRouter.d.ts +65 -0
  84. package/dist/components/sandbox/RuntimeMessageRouter.d.ts.map +1 -0
  85. package/dist/components/sandbox/RuntimeMessageRouter.js +168 -0
  86. package/dist/components/sandbox/RuntimeMessageRouter.js.map +1 -0
  87. package/dist/components/sandbox/SandboxRuntimeProvider.d.ts +33 -0
  88. package/dist/components/sandbox/SandboxRuntimeProvider.d.ts.map +1 -0
  89. package/dist/components/sandbox/SandboxRuntimeProvider.js +2 -0
  90. package/dist/components/sandbox/SandboxRuntimeProvider.js.map +1 -0
  91. package/dist/dialogs/ApiKeyPromptDialog.d.ts.map +1 -1
  92. package/dist/dialogs/ApiKeyPromptDialog.js +2 -5
  93. package/dist/dialogs/ApiKeyPromptDialog.js.map +1 -1
  94. package/dist/dialogs/ModelSelector.js.map +1 -1
  95. package/dist/dialogs/PersistentStorageDialog.d.ts +17 -0
  96. package/dist/dialogs/PersistentStorageDialog.d.ts.map +1 -0
  97. package/dist/dialogs/PersistentStorageDialog.js +144 -0
  98. package/dist/dialogs/PersistentStorageDialog.js.map +1 -0
  99. package/dist/dialogs/SessionListDialog.d.ts +19 -0
  100. package/dist/dialogs/SessionListDialog.d.ts.map +1 -0
  101. package/dist/dialogs/SessionListDialog.js +152 -0
  102. package/dist/dialogs/SessionListDialog.js.map +1 -0
  103. package/dist/dialogs/SettingsDialog.d.ts.map +1 -1
  104. package/dist/dialogs/SettingsDialog.js +1 -0
  105. package/dist/dialogs/SettingsDialog.js.map +1 -1
  106. package/dist/index.d.ts +34 -16
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +32 -14
  109. package/dist/index.js.map +1 -1
  110. package/dist/prompts/prompts.d.ts +11 -0
  111. package/dist/prompts/prompts.d.ts.map +1 -0
  112. package/dist/prompts/prompts.js +272 -0
  113. package/dist/prompts/prompts.js.map +1 -0
  114. package/dist/storage/app-storage.d.ts +17 -12
  115. package/dist/storage/app-storage.d.ts.map +1 -1
  116. package/dist/storage/app-storage.js +13 -20
  117. package/dist/storage/app-storage.js.map +1 -1
  118. package/dist/storage/backends/indexeddb-storage-backend.d.ts +27 -0
  119. package/dist/storage/backends/indexeddb-storage-backend.d.ts.map +1 -0
  120. package/dist/storage/backends/indexeddb-storage-backend.js +166 -0
  121. package/dist/storage/backends/indexeddb-storage-backend.js.map +1 -0
  122. package/dist/storage/store.d.ts +23 -0
  123. package/dist/storage/store.d.ts.map +1 -0
  124. package/dist/storage/store.js +26 -0
  125. package/dist/storage/store.js.map +1 -0
  126. package/dist/storage/stores/provider-keys-store.d.ts +14 -0
  127. package/dist/storage/stores/provider-keys-store.d.ts.map +1 -0
  128. package/dist/storage/stores/provider-keys-store.js +27 -0
  129. package/dist/storage/stores/provider-keys-store.js.map +1 -0
  130. package/dist/storage/stores/sessions-store.d.ts +31 -0
  131. package/dist/storage/stores/sessions-store.d.ts.map +1 -0
  132. package/dist/storage/stores/sessions-store.js +113 -0
  133. package/dist/storage/stores/sessions-store.js.map +1 -0
  134. package/dist/storage/stores/settings-store.d.ts +14 -0
  135. package/dist/storage/stores/settings-store.d.ts.map +1 -0
  136. package/dist/storage/stores/settings-store.js +28 -0
  137. package/dist/storage/stores/settings-store.js.map +1 -0
  138. package/dist/storage/types.d.ts +156 -22
  139. package/dist/storage/types.d.ts.map +1 -1
  140. package/dist/tools/artifacts/ArtifactElement.d.ts +0 -1
  141. package/dist/tools/artifacts/ArtifactElement.d.ts.map +1 -1
  142. package/dist/tools/artifacts/ArtifactElement.js +0 -1
  143. package/dist/tools/artifacts/ArtifactElement.js.map +1 -1
  144. package/dist/tools/artifacts/ArtifactPill.d.ts +4 -0
  145. package/dist/tools/artifacts/ArtifactPill.d.ts.map +1 -0
  146. package/dist/tools/artifacts/ArtifactPill.js +22 -0
  147. package/dist/tools/artifacts/ArtifactPill.js.map +1 -0
  148. package/dist/tools/artifacts/Console.d.ts +18 -0
  149. package/dist/tools/artifacts/Console.d.ts.map +1 -0
  150. package/dist/tools/artifacts/Console.js +95 -0
  151. package/dist/tools/artifacts/Console.js.map +1 -0
  152. package/dist/tools/artifacts/DocxArtifact.d.ts +22 -0
  153. package/dist/tools/artifacts/DocxArtifact.d.ts.map +1 -0
  154. package/dist/tools/artifacts/DocxArtifact.js +208 -0
  155. package/dist/tools/artifacts/DocxArtifact.js.map +1 -0
  156. package/dist/tools/artifacts/ExcelArtifact.d.ts +24 -0
  157. package/dist/tools/artifacts/ExcelArtifact.d.ts.map +1 -0
  158. package/dist/tools/artifacts/ExcelArtifact.js +216 -0
  159. package/dist/tools/artifacts/ExcelArtifact.js.map +1 -0
  160. package/dist/tools/artifacts/GenericArtifact.d.ts +19 -0
  161. package/dist/tools/artifacts/GenericArtifact.d.ts.map +1 -0
  162. package/dist/tools/artifacts/GenericArtifact.js +117 -0
  163. package/dist/tools/artifacts/GenericArtifact.js.map +1 -0
  164. package/dist/tools/artifacts/HtmlArtifact.d.ts +8 -11
  165. package/dist/tools/artifacts/HtmlArtifact.d.ts.map +1 -1
  166. package/dist/tools/artifacts/HtmlArtifact.js +56 -88
  167. package/dist/tools/artifacts/HtmlArtifact.js.map +1 -1
  168. package/dist/tools/artifacts/ImageArtifact.d.ts +20 -0
  169. package/dist/tools/artifacts/ImageArtifact.d.ts.map +1 -0
  170. package/dist/tools/artifacts/ImageArtifact.js +120 -0
  171. package/dist/tools/artifacts/ImageArtifact.js.map +1 -0
  172. package/dist/tools/artifacts/MarkdownArtifact.d.ts +0 -1
  173. package/dist/tools/artifacts/MarkdownArtifact.d.ts.map +1 -1
  174. package/dist/tools/artifacts/MarkdownArtifact.js +0 -4
  175. package/dist/tools/artifacts/MarkdownArtifact.js.map +1 -1
  176. package/dist/tools/artifacts/PdfArtifact.d.ts +25 -0
  177. package/dist/tools/artifacts/PdfArtifact.d.ts.map +1 -0
  178. package/dist/tools/artifacts/PdfArtifact.js +184 -0
  179. package/dist/tools/artifacts/PdfArtifact.js.map +1 -0
  180. package/dist/tools/artifacts/SvgArtifact.d.ts +0 -1
  181. package/dist/tools/artifacts/SvgArtifact.d.ts.map +1 -1
  182. package/dist/tools/artifacts/SvgArtifact.js +0 -4
  183. package/dist/tools/artifacts/SvgArtifact.js.map +1 -1
  184. package/dist/tools/artifacts/TextArtifact.d.ts +0 -1
  185. package/dist/tools/artifacts/TextArtifact.d.ts.map +1 -1
  186. package/dist/tools/artifacts/TextArtifact.js +0 -4
  187. package/dist/tools/artifacts/TextArtifact.js.map +1 -1
  188. package/dist/tools/artifacts/artifacts-tool-renderer.d.ts +11 -0
  189. package/dist/tools/artifacts/artifacts-tool-renderer.d.ts.map +1 -0
  190. package/dist/tools/artifacts/artifacts-tool-renderer.js +262 -0
  191. package/dist/tools/artifacts/artifacts-tool-renderer.js.map +1 -0
  192. package/dist/tools/artifacts/artifacts.d.ts +10 -13
  193. package/dist/tools/artifacts/artifacts.d.ts.map +1 -1
  194. package/dist/tools/artifacts/artifacts.js +166 -344
  195. package/dist/tools/artifacts/artifacts.js.map +1 -1
  196. package/dist/tools/artifacts/index.d.ts +1 -0
  197. package/dist/tools/artifacts/index.d.ts.map +1 -1
  198. package/dist/tools/artifacts/index.js +1 -0
  199. package/dist/tools/artifacts/index.js.map +1 -1
  200. package/dist/tools/extract-document.d.ts +24 -0
  201. package/dist/tools/extract-document.d.ts.map +1 -0
  202. package/dist/tools/extract-document.js +193 -0
  203. package/dist/tools/extract-document.js.map +1 -0
  204. package/dist/tools/index.d.ts +9 -7
  205. package/dist/tools/index.d.ts.map +1 -1
  206. package/dist/tools/index.js +17 -13
  207. package/dist/tools/index.js.map +1 -1
  208. package/dist/tools/javascript-repl.d.ts +16 -15
  209. package/dist/tools/javascript-repl.d.ts.map +1 -1
  210. package/dist/tools/javascript-repl.js +101 -133
  211. package/dist/tools/javascript-repl.js.map +1 -1
  212. package/dist/tools/renderer-registry.d.ts +12 -0
  213. package/dist/tools/renderer-registry.d.ts.map +1 -1
  214. package/dist/tools/renderer-registry.js +78 -0
  215. package/dist/tools/renderer-registry.js.map +1 -1
  216. package/dist/tools/renderers/BashRenderer.d.ts +2 -4
  217. package/dist/tools/renderers/BashRenderer.d.ts.map +1 -1
  218. package/dist/tools/renderers/BashRenderer.js +30 -26
  219. package/dist/tools/renderers/BashRenderer.js.map +1 -1
  220. package/dist/tools/renderers/CalculateRenderer.d.ts +2 -4
  221. package/dist/tools/renderers/CalculateRenderer.d.ts.map +1 -1
  222. package/dist/tools/renderers/CalculateRenderer.js +32 -28
  223. package/dist/tools/renderers/CalculateRenderer.js.map +1 -1
  224. package/dist/tools/renderers/DefaultRenderer.d.ts +2 -4
  225. package/dist/tools/renderers/DefaultRenderer.d.ts.map +1 -1
  226. package/dist/tools/renderers/DefaultRenderer.js +78 -18
  227. package/dist/tools/renderers/DefaultRenderer.js.map +1 -1
  228. package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts +2 -4
  229. package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts.map +1 -1
  230. package/dist/tools/renderers/GetCurrentTimeRenderer.js +57 -21
  231. package/dist/tools/renderers/GetCurrentTimeRenderer.js.map +1 -1
  232. package/dist/tools/types.d.ts +5 -2
  233. package/dist/tools/types.d.ts.map +1 -1
  234. package/dist/utils/i18n.d.ts +424 -1
  235. package/dist/utils/i18n.d.ts.map +1 -1
  236. package/dist/utils/i18n.js +131 -7
  237. package/dist/utils/i18n.js.map +1 -1
  238. package/example/package.json +2 -1
  239. package/example/src/custom-messages.ts +112 -0
  240. package/example/src/main.ts +391 -38
  241. package/package.json +48 -43
  242. package/scripts/count-prompt-tokens.ts +88 -0
  243. package/src/ChatPanel.ts +93 -101
  244. package/src/{state/agent-session.ts → agent/agent.ts} +80 -55
  245. package/src/{state → agent}/transports/AppTransport.ts +6 -6
  246. package/src/{state → agent}/transports/ProviderTransport.ts +13 -7
  247. package/src/{state → agent}/transports/types.ts +8 -2
  248. package/src/components/AgentInterface.ts +32 -16
  249. package/src/components/ConsoleBlock.ts +5 -1
  250. package/src/components/ExpandableSection.ts +46 -0
  251. package/src/components/MessageEditor.ts +159 -5
  252. package/src/components/MessageList.ts +18 -3
  253. package/src/components/Messages.ts +48 -89
  254. package/src/components/ProviderKeyInput.ts +6 -5
  255. package/src/components/SandboxedIframe.ts +412 -321
  256. package/src/components/message-renderer-registry.ts +28 -0
  257. package/src/components/sandbox/ArtifactsRuntimeProvider.ts +219 -0
  258. package/src/components/sandbox/AttachmentsRuntimeProvider.ts +66 -0
  259. package/src/components/sandbox/ConsoleRuntimeProvider.ts +187 -0
  260. package/src/components/sandbox/FileDownloadRuntimeProvider.ts +110 -0
  261. package/src/components/sandbox/RuntimeMessageBridge.ts +82 -0
  262. package/src/components/sandbox/RuntimeMessageRouter.ts +216 -0
  263. package/src/components/sandbox/SandboxRuntimeProvider.ts +35 -0
  264. package/src/dialogs/ApiKeyPromptDialog.ts +2 -5
  265. package/src/dialogs/ModelSelector.ts +2 -2
  266. package/src/dialogs/PersistentStorageDialog.ts +141 -0
  267. package/src/dialogs/SessionListDialog.ts +148 -0
  268. package/src/dialogs/SettingsDialog.ts +1 -0
  269. package/src/index.ts +61 -20
  270. package/src/prompts/prompts.ts +282 -0
  271. package/src/storage/app-storage.ts +27 -24
  272. package/src/storage/backends/indexeddb-storage-backend.ts +193 -0
  273. package/src/storage/store.ts +33 -0
  274. package/src/storage/stores/provider-keys-store.ts +33 -0
  275. package/src/storage/stores/sessions-store.ts +130 -0
  276. package/src/storage/stores/settings-store.ts +34 -0
  277. package/src/storage/types.ts +182 -22
  278. package/src/tools/artifacts/ArtifactElement.ts +0 -1
  279. package/src/tools/artifacts/ArtifactPill.ts +25 -0
  280. package/src/tools/artifacts/Console.ts +93 -0
  281. package/src/tools/artifacts/DocxArtifact.ts +213 -0
  282. package/src/tools/artifacts/ExcelArtifact.ts +231 -0
  283. package/src/tools/artifacts/GenericArtifact.ts +117 -0
  284. package/src/tools/artifacts/HtmlArtifact.ts +64 -94
  285. package/src/tools/artifacts/ImageArtifact.ts +116 -0
  286. package/src/tools/artifacts/MarkdownArtifact.ts +0 -1
  287. package/src/tools/artifacts/PdfArtifact.ts +201 -0
  288. package/src/tools/artifacts/SvgArtifact.ts +0 -1
  289. package/src/tools/artifacts/TextArtifact.ts +0 -1
  290. package/src/tools/artifacts/artifacts-tool-renderer.ts +298 -0
  291. package/src/tools/artifacts/artifacts.ts +190 -366
  292. package/src/tools/artifacts/index.ts +1 -0
  293. package/src/tools/extract-document.ts +250 -0
  294. package/src/tools/index.ts +25 -14
  295. package/src/tools/javascript-repl.ts +138 -160
  296. package/src/tools/renderer-registry.ts +98 -0
  297. package/src/tools/renderers/BashRenderer.ts +33 -30
  298. package/src/tools/renderers/CalculateRenderer.ts +36 -31
  299. package/src/tools/renderers/DefaultRenderer.ts +84 -21
  300. package/src/tools/renderers/GetCurrentTimeRenderer.ts +68 -23
  301. package/src/tools/types.ts +10 -2
  302. package/src/utils/i18n.ts +203 -8
  303. package/dist/state/agent-session.d.ts.map +0 -1
  304. package/dist/state/agent-session.js.map +0 -1
  305. package/dist/state/transports/AppTransport.d.ts.map +0 -1
  306. package/dist/state/transports/ProviderTransport.d.ts.map +0 -1
  307. package/dist/state/transports/ProviderTransport.js.map +0 -1
  308. package/dist/state/transports/index.js.map +0 -1
  309. package/dist/state/transports/proxy-types.js.map +0 -1
  310. package/dist/state/transports/types.d.ts +0 -11
  311. package/dist/state/transports/types.d.ts.map +0 -1
  312. package/dist/storage/backends/chrome-storage-backend.d.ts +0 -18
  313. package/dist/storage/backends/chrome-storage-backend.d.ts.map +0 -1
  314. package/dist/storage/backends/chrome-storage-backend.js +0 -67
  315. package/dist/storage/backends/chrome-storage-backend.js.map +0 -1
  316. package/dist/storage/backends/indexeddb-backend.d.ts +0 -20
  317. package/dist/storage/backends/indexeddb-backend.d.ts.map +0 -1
  318. package/dist/storage/backends/indexeddb-backend.js +0 -89
  319. package/dist/storage/backends/indexeddb-backend.js.map +0 -1
  320. package/dist/storage/backends/local-storage-backend.d.ts +0 -18
  321. package/dist/storage/backends/local-storage-backend.d.ts.map +0 -1
  322. package/dist/storage/backends/local-storage-backend.js +0 -69
  323. package/dist/storage/backends/local-storage-backend.js.map +0 -1
  324. package/dist/storage/repositories/provider-keys-repository.d.ts +0 -34
  325. package/dist/storage/repositories/provider-keys-repository.d.ts.map +0 -1
  326. package/dist/storage/repositories/provider-keys-repository.js +0 -50
  327. package/dist/storage/repositories/provider-keys-repository.js.map +0 -1
  328. package/dist/storage/repositories/settings-repository.d.ts +0 -34
  329. package/dist/storage/repositories/settings-repository.d.ts.map +0 -1
  330. package/dist/storage/repositories/settings-repository.js +0 -46
  331. package/dist/storage/repositories/settings-repository.js.map +0 -1
  332. package/src/storage/backends/chrome-storage-backend.ts +0 -82
  333. package/src/storage/backends/indexeddb-backend.ts +0 -107
  334. package/src/storage/backends/local-storage-backend.ts +0 -74
  335. package/src/storage/repositories/provider-keys-repository.ts +0 -55
  336. package/src/storage/repositories/settings-repository.ts +0 -51
  337. /package/dist/{state → agent}/transports/index.d.ts +0 -0
  338. /package/dist/{state → agent}/transports/index.js +0 -0
  339. /package/dist/{state → agent}/transports/proxy-types.d.ts +0 -0
  340. /package/dist/{state → agent}/transports/proxy-types.js +0 -0
  341. /package/dist/{state → agent}/transports/types.js +0 -0
  342. /package/dist/{state → agent}/types.d.ts +0 -0
  343. /package/dist/{state → agent}/types.js +0 -0
  344. /package/src/{state → agent}/transports/index.ts +0 -0
  345. /package/src/{state → agent}/transports/proxy-types.ts +0 -0
  346. /package/src/{state → agent}/types.ts +0 -0
package/src/index.ts CHANGED
@@ -1,15 +1,33 @@
1
1
  // Main chat interface
2
- export { ChatPanel } from "./ChatPanel.js";
3
2
 
3
+ export type { AgentState, ThinkingLevel } from "./agent/agent.js";
4
+ // State management
5
+ export { Agent } from "./agent/agent.js";
6
+ // Transports
7
+ export { AppTransport } from "./agent/transports/AppTransport.js";
8
+ export { ProviderTransport } from "./agent/transports/ProviderTransport.js";
9
+ export type { ProxyAssistantMessageEvent } from "./agent/transports/proxy-types.js";
10
+ export type { AgentRunConfig, AgentTransport } from "./agent/transports/types.js";
11
+ export { ChatPanel } from "./ChatPanel.js";
4
12
  // Components
5
13
  export { AgentInterface } from "./components/AgentInterface.js";
6
14
  export { AttachmentTile } from "./components/AttachmentTile.js";
7
15
  export { ConsoleBlock } from "./components/ConsoleBlock.js";
16
+ export { ExpandableSection } from "./components/ExpandableSection.js";
8
17
  export { Input } from "./components/Input.js";
9
18
  export { MessageEditor } from "./components/MessageEditor.js";
10
19
  export { MessageList } from "./components/MessageList.js";
11
20
  // Message components
21
+ export type { AppMessage, CustomMessages, UserMessageWithAttachments } from "./components/Messages.js";
12
22
  export { AssistantMessage, ToolMessage, UserMessage } from "./components/Messages.js";
23
+ // Message renderer registry
24
+ export {
25
+ getMessageRenderer,
26
+ type MessageRenderer,
27
+ type MessageRole,
28
+ registerMessageRenderer,
29
+ renderMessage,
30
+ } from "./components/message-renderer-registry.js";
13
31
  export {
14
32
  type SandboxFile,
15
33
  SandboxIframe,
@@ -17,47 +35,70 @@ export {
17
35
  type SandboxUrlProvider,
18
36
  } from "./components/SandboxedIframe.js";
19
37
  export { StreamingMessageContainer } from "./components/StreamingMessageContainer.js";
38
+ // Sandbox Runtime Providers
39
+ export { ArtifactsRuntimeProvider } from "./components/sandbox/ArtifactsRuntimeProvider.js";
40
+ export { AttachmentsRuntimeProvider } from "./components/sandbox/AttachmentsRuntimeProvider.js";
41
+ export { type ConsoleLog, ConsoleRuntimeProvider } from "./components/sandbox/ConsoleRuntimeProvider.js";
42
+ export {
43
+ type DownloadableFile,
44
+ FileDownloadRuntimeProvider,
45
+ } from "./components/sandbox/FileDownloadRuntimeProvider.js";
46
+ export { RuntimeMessageBridge } from "./components/sandbox/RuntimeMessageBridge.js";
47
+ export { RUNTIME_MESSAGE_ROUTER } from "./components/sandbox/RuntimeMessageRouter.js";
48
+ export type { SandboxRuntimeProvider } from "./components/sandbox/SandboxRuntimeProvider.js";
20
49
  export { ApiKeyPromptDialog } from "./dialogs/ApiKeyPromptDialog.js";
21
50
  export { AttachmentOverlay } from "./dialogs/AttachmentOverlay.js";
22
51
  // Dialogs
23
52
  export { ModelSelector } from "./dialogs/ModelSelector.js";
53
+ export { PersistentStorageDialog } from "./dialogs/PersistentStorageDialog.js";
54
+ export { SessionListDialog } from "./dialogs/SessionListDialog.js";
24
55
  export { ApiKeysTab, ProxyTab, SettingsDialog, SettingsTab } from "./dialogs/SettingsDialog.js";
25
- export type { AgentSessionState, ThinkingLevel } from "./state/agent-session.js";
26
- // State management
27
- export { AgentSession } from "./state/agent-session.js";
28
-
29
- // Transports
30
- export { AppTransport } from "./state/transports/AppTransport.js";
31
- export { ProviderTransport } from "./state/transports/ProviderTransport.js";
32
- export type { ProxyAssistantMessageEvent } from "./state/transports/proxy-types.js";
33
- export type { AgentRunConfig, AgentTransport } from "./state/transports/types.js";
56
+ // Prompts
57
+ export {
58
+ ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RO,
59
+ ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RW,
60
+ ATTACHMENTS_RUNTIME_DESCRIPTION,
61
+ } from "./prompts/prompts.js";
34
62
  // Storage
35
- export { AppStorage, getAppStorage, initAppStorage, setAppStorage } from "./storage/app-storage.js";
36
- export { ChromeStorageBackend } from "./storage/backends/chrome-storage-backend.js";
37
- export { IndexedDBBackend } from "./storage/backends/indexeddb-backend.js";
38
- export { LocalStorageBackend } from "./storage/backends/local-storage-backend.js";
39
- export { ProviderKeysRepository } from "./storage/repositories/provider-keys-repository.js";
40
- export { SettingsRepository } from "./storage/repositories/settings-repository.js";
41
- export type { AppStorageConfig, StorageBackend } from "./storage/types.js";
63
+ export { AppStorage, getAppStorage, setAppStorage } from "./storage/app-storage.js";
64
+ export { IndexedDBStorageBackend } from "./storage/backends/indexeddb-storage-backend.js";
65
+ export { Store } from "./storage/store.js";
66
+ export { ProviderKeysStore } from "./storage/stores/provider-keys-store.js";
67
+ export { SessionsStore } from "./storage/stores/sessions-store.js";
68
+ export { SettingsStore } from "./storage/stores/settings-store.js";
69
+ export type {
70
+ IndexConfig,
71
+ IndexedDBConfig,
72
+ SessionData,
73
+ SessionMetadata,
74
+ StorageBackend,
75
+ StorageTransaction,
76
+ StoreConfig,
77
+ } from "./storage/types.js";
42
78
  // Artifacts
43
79
  export { ArtifactElement } from "./tools/artifacts/ArtifactElement.js";
80
+ export { ArtifactPill } from "./tools/artifacts/ArtifactPill.js";
44
81
  export { type Artifact, ArtifactsPanel, type ArtifactsParams } from "./tools/artifacts/artifacts.js";
82
+ export { ArtifactsToolRenderer } from "./tools/artifacts/artifacts-tool-renderer.js";
45
83
  export { HtmlArtifact } from "./tools/artifacts/HtmlArtifact.js";
84
+ export { ImageArtifact } from "./tools/artifacts/ImageArtifact.js";
46
85
  export { MarkdownArtifact } from "./tools/artifacts/MarkdownArtifact.js";
47
86
  export { SvgArtifact } from "./tools/artifacts/SvgArtifact.js";
48
87
  export { TextArtifact } from "./tools/artifacts/TextArtifact.js";
88
+ export { createExtractDocumentTool, extractDocumentTool } from "./tools/extract-document.js";
49
89
  // Tools
50
- export { getToolRenderer, registerToolRenderer, renderToolParams, renderToolResult } from "./tools/index.js";
90
+ export { getToolRenderer, registerToolRenderer, renderTool, setShowJsonMode } from "./tools/index.js";
51
91
  export { createJavaScriptReplTool, javascriptReplTool } from "./tools/javascript-repl.js";
92
+ export { renderCollapsibleHeader, renderHeader } from "./tools/renderer-registry.js";
52
93
  export { BashRenderer } from "./tools/renderers/BashRenderer.js";
53
94
  export { CalculateRenderer } from "./tools/renderers/CalculateRenderer.js";
54
95
  // Tool renderers
55
96
  export { DefaultRenderer } from "./tools/renderers/DefaultRenderer.js";
56
97
  export { GetCurrentTimeRenderer } from "./tools/renderers/GetCurrentTimeRenderer.js";
57
- export type { ToolRenderer } from "./tools/types.js";
98
+ export type { ToolRenderer, ToolRenderResult } from "./tools/types.js";
58
99
  export type { Attachment } from "./utils/attachment-utils.js";
59
100
  // Utils
60
101
  export { loadAttachment } from "./utils/attachment-utils.js";
61
102
  export { clearAuthToken, getAuthToken } from "./utils/auth-token.js";
62
103
  export { formatCost, formatModelCost, formatTokenCount, formatUsage } from "./utils/format.js";
63
- export { i18n, setLanguage } from "./utils/i18n.js";
104
+ export { i18n, setLanguage, translations } from "./utils/i18n.js";
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Centralized tool prompts/descriptions.
3
+ * Each prompt is either a string constant or a template function.
4
+ */
5
+
6
+ // ============================================================================
7
+ // JavaScript REPL Tool
8
+ // ============================================================================
9
+
10
+ export const JAVASCRIPT_REPL_TOOL_DESCRIPTION = (runtimeProviderDescriptions: string[]) => `# JavaScript REPL
11
+
12
+ ## Purpose
13
+ Execute JavaScript code in a sandboxed browser environment with full Web APIs.
14
+
15
+ ## When to Use
16
+ - Quick calculations or data transformations
17
+ - Testing JavaScript code snippets in isolation
18
+ - Processing data with libraries (XLSX, CSV, etc.)
19
+ - Creating artifacts from data
20
+
21
+ ## Environment
22
+ - ES2023+ JavaScript (async/await, optional chaining, nullish coalescing, etc.)
23
+ - All browser APIs: DOM, Canvas, WebGL, Fetch, Web Workers, WebSockets, Crypto, etc.
24
+ - Import any npm package: await import('https://esm.run/package-name')
25
+
26
+ ## Common Libraries
27
+ - XLSX: const XLSX = await import('https://esm.run/xlsx');
28
+ - CSV: const Papa = (await import('https://esm.run/papaparse')).default;
29
+ - Chart.js: const Chart = (await import('https://esm.run/chart.js/auto')).default;
30
+ - Three.js: const THREE = await import('https://esm.run/three');
31
+
32
+ ## Persistence between tool calls
33
+ - Objects stored on global scope do not persist between calls.
34
+ - Use artifacts as a key-value JSON object store:
35
+ - Use createOrUpdateArtifact(filename, content) to persist data between calls. JSON objects are auto-stringified.
36
+ - Use listArtifacts() and getArtifact(filename) to read persisted data. JSON files are auto-parsed to objects.
37
+ - Prefer to use a single artifact throughout the session to store intermediate data (e.g. 'data.json').
38
+
39
+ ## Input
40
+ - You have access to the user's attachments via listAttachments(), readTextAttachment(id), and readBinaryAttachment(id)
41
+ - You have access to previously created artifacts via listArtifacts() and getArtifact(filename)
42
+
43
+ ## Output
44
+ - All console.log() calls are captured for you to inspect. The user does not see these logs.
45
+ - Create artifacts for file results (images, JSON, CSV, etc.) which persiste throughout the
46
+ session and are accessible to you and the user.
47
+
48
+ ## Example
49
+ const data = [10, 20, 15, 25];
50
+ const sum = data.reduce((a, b) => a + b, 0);
51
+ const avg = sum / data.length;
52
+ console.log('Sum:', sum, 'Average:', avg);
53
+
54
+ ## Important Notes
55
+ - Graphics: Use fixed dimensions (800x600), NOT window.innerWidth/Height
56
+ - Chart.js: Set options: { responsive: false, animation: false }
57
+ - Three.js: renderer.setSize(800, 600) with matching aspect ratio
58
+
59
+ ## Helper Functions (Automatically Available)
60
+
61
+ These functions are injected into the execution environment and available globally:
62
+
63
+ ${runtimeProviderDescriptions.join("\n\n")}
64
+ `;
65
+
66
+ // ============================================================================
67
+ // Artifacts Tool
68
+ // ============================================================================
69
+
70
+ export const ARTIFACTS_TOOL_DESCRIPTION = (runtimeProviderDescriptions: string[]) => `# Artifacts
71
+
72
+ Create and manage persistent files that live alongside the conversation.
73
+
74
+ ## When to Use - Artifacts Tool vs REPL
75
+
76
+ **Use artifacts tool when YOU are the author:**
77
+ - Writing research summaries, analysis, ideas, documentation
78
+ - Creating markdown notes for user to read
79
+ - Building HTML applications/visualizations that present data
80
+ - Creating HTML artifacts that render charts from programmatically generated data
81
+
82
+ **Use repl + artifact storage functions when CODE processes data:**
83
+ - Scraping workflows that extract and store data
84
+ - Processing CSV/Excel files programmatically
85
+ - Data transformation pipelines
86
+ - Binary file generation requiring libraries (PDF, DOCX)
87
+
88
+ **Pattern: REPL generates data → Artifacts tool creates HTML that visualizes it**
89
+ Example: repl scrapes products → stores products.json → you author dashboard.html that reads products.json and renders Chart.js visualizations
90
+
91
+ ## Input
92
+ - { action: "create", filename: "notes.md", content: "..." } - Create new file
93
+ - { action: "update", filename: "notes.md", old_str: "...", new_str: "..." } - Update part of file (PREFERRED)
94
+ - { action: "rewrite", filename: "notes.md", content: "..." } - Replace entire file (LAST RESORT)
95
+ - { action: "get", filename: "data.json" } - Retrieve file content
96
+ - { action: "delete", filename: "old.csv" } - Delete file
97
+ - { action: "htmlArtifactLogs", filename: "app.html" } - Get console logs from HTML artifact
98
+
99
+ ## Returns
100
+ Depends on action:
101
+ - create/update/rewrite/delete: Success status or error
102
+ - get: File content
103
+ - htmlArtifactLogs: Console logs and errors
104
+
105
+ ## Supported File Types
106
+ ✅ Text-based files you author: .md, .txt, .html, .js, .css, .json, .csv, .svg
107
+ ❌ Binary files requiring libraries (use repl): .pdf, .docx
108
+
109
+ ## Critical - Prefer Update Over Rewrite
110
+ ❌ NEVER: get entire file + rewrite to change small sections
111
+ ✅ ALWAYS: update for targeted edits (token efficient)
112
+ ✅ Ask: Can I describe the change as old_str → new_str? Use update.
113
+
114
+ ---
115
+
116
+ ## HTML Artifacts
117
+
118
+ Interactive HTML applications that can visualize data from other artifacts.
119
+
120
+ ### Data Access
121
+ - Can read artifacts created by repl and user attachments
122
+ - Use to build dashboards, visualizations, interactive tools
123
+ - See Helper Functions section below for available functions
124
+
125
+ ### Requirements
126
+ - Self-contained single file
127
+ - Import ES modules from esm.sh: <script type="module">import X from 'https://esm.sh/pkg';</script>
128
+ - Use Tailwind CDN: <script src="https://cdn.tailwindcss.com"></script>
129
+ - Can embed images from any domain: <img src="https://example.com/image.jpg">
130
+ - MUST set background color explicitly (avoid transparent)
131
+ - Inline CSS or Tailwind utility classes
132
+ - No localStorage/sessionStorage
133
+
134
+ ### Styling
135
+ - Use Tailwind utility classes for clean, functional designs
136
+ - Ensure responsive layout (iframe may be resized)
137
+ - Avoid purple gradients, AI aesthetic clichés, and emojis
138
+
139
+ ### Helper Functions (Automatically Available)
140
+
141
+ These functions are injected into HTML artifact sandbox:
142
+
143
+ ${runtimeProviderDescriptions.join("\n\n")}
144
+ `;
145
+
146
+ // ============================================================================
147
+ // Artifacts Runtime Provider
148
+ // ============================================================================
149
+
150
+ export const ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RW = `
151
+ ### Artifacts Storage
152
+
153
+ Create, read, update, and delete files in artifacts storage.
154
+
155
+ #### When to Use
156
+ - Store intermediate results between tool calls
157
+ - Save generated files (images, CSVs, processed data) for user to view and download
158
+
159
+ #### Do NOT Use For
160
+ - Content you author directly, like summaries of content you read (use artifacts tool instead)
161
+
162
+ #### Functions
163
+ - listArtifacts() - List all artifact filenames, returns Promise<string[]>
164
+ - getArtifact(filename) - Read artifact content, returns Promise<string | object>. JSON files auto-parse to objects, binary files return base64 string
165
+ - createOrUpdateArtifact(filename, content, mimeType?) - Create or update artifact, returns Promise<void>. JSON files auto-stringify objects, binary requires base64 string with mimeType
166
+ - deleteArtifact(filename) - Delete artifact, returns Promise<void>
167
+
168
+ #### Example
169
+ JSON workflow:
170
+ \`\`\`javascript
171
+ // Fetch and save
172
+ const response = await fetch('https://api.example.com/products');
173
+ const products = await response.json();
174
+ await createOrUpdateArtifact('products.json', products);
175
+
176
+ // Later: read and filter
177
+ const all = await getArtifact('products.json');
178
+ const cheap = all.filter(p => p.price < 100);
179
+ await createOrUpdateArtifact('cheap.json', cheap);
180
+ \`\`\`
181
+
182
+ Binary file (image):
183
+ \`\`\`javascript
184
+ const canvas = document.createElement('canvas');
185
+ canvas.width = 800; canvas.height = 600;
186
+ const ctx = canvas.getContext('2d');
187
+ ctx.fillStyle = 'blue';
188
+ ctx.fillRect(0, 0, 800, 600);
189
+ // Remove data:image/png;base64, prefix
190
+ const base64 = canvas.toDataURL().split(',')[1];
191
+ await createOrUpdateArtifact('chart.png', base64, 'image/png');
192
+ \`\`\`
193
+ `;
194
+
195
+ export const ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION_RO = `
196
+ ### Artifacts Storage
197
+
198
+ Read files from artifacts storage.
199
+
200
+ #### When to Use
201
+ - Read artifacts created by REPL or artifacts tool
202
+ - Access data from other HTML artifacts
203
+ - Load configuration or data files
204
+
205
+ #### Do NOT Use For
206
+ - Creating new artifacts (not available in HTML artifacts)
207
+ - Modifying artifacts (read-only access)
208
+
209
+ #### Functions
210
+ - listArtifacts() - List all artifact filenames, returns Promise<string[]>
211
+ - getArtifact(filename) - Read artifact content, returns Promise<string | object>. JSON files auto-parse to objects, binary files return base64 string
212
+
213
+ #### Example
214
+ JSON data:
215
+ \`\`\`javascript
216
+ const products = await getArtifact('products.json');
217
+ const html = products.map(p => \`<div>\${p.name}: $\${p.price}</div>\`).join('');
218
+ document.body.innerHTML = html;
219
+ \`\`\`
220
+
221
+ Binary image:
222
+ \`\`\`javascript
223
+ const base64 = await getArtifact('chart.png');
224
+ const img = document.createElement('img');
225
+ img.src = 'data:image/png;base64,' + base64;
226
+ document.body.appendChild(img);
227
+ \`\`\`
228
+ `;
229
+
230
+ // ============================================================================
231
+ // Attachments Runtime Provider
232
+ // ============================================================================
233
+
234
+ export const ATTACHMENTS_RUNTIME_DESCRIPTION = `
235
+ ### User Attachments
236
+
237
+ Read files the user uploaded to the conversation.
238
+
239
+ #### When to Use
240
+ - Process user-uploaded files (CSV, JSON, Excel, images, PDFs)
241
+
242
+ #### Functions
243
+ - listAttachments() - List all attachments, returns array of {id, fileName, mimeType, size}
244
+ - readTextAttachment(id) - Read attachment as text, returns string
245
+ - readBinaryAttachment(id) - Read attachment as binary data, returns Uint8Array
246
+
247
+ #### Example
248
+ CSV file:
249
+ \`\`\`javascript
250
+ const files = listAttachments();
251
+ const csvFile = files.find(f => f.fileName.endsWith('.csv'));
252
+ const csvData = readTextAttachment(csvFile.id);
253
+ const rows = csvData.split('\\n').map(row => row.split(','));
254
+ \`\`\`
255
+
256
+ Excel file:
257
+ \`\`\`javascript
258
+ const XLSX = await import('https://esm.run/xlsx');
259
+ const files = listAttachments();
260
+ const xlsxFile = files.find(f => f.fileName.endsWith('.xlsx'));
261
+ const bytes = readBinaryAttachment(xlsxFile.id);
262
+ const workbook = XLSX.read(bytes);
263
+ const data = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
264
+ \`\`\`
265
+ `;
266
+
267
+ // ============================================================================
268
+ // Extract Document Tool
269
+ // ============================================================================
270
+
271
+ export const EXTRACT_DOCUMENT_DESCRIPTION = `# Extract Document
272
+
273
+ Extract plain text from documents on the web (PDF, DOCX, XLSX, PPTX).
274
+
275
+ ## When to Use
276
+ User wants you to read a document at a URL.
277
+
278
+ ## Input
279
+ - { url: "https://example.com/document.pdf" } - URL to PDF, DOCX, XLSX, or PPTX
280
+
281
+ ## Returns
282
+ Structured plain text with page/sheet/slide delimiters.`;
@@ -1,23 +1,36 @@
1
- import { LocalStorageBackend } from "./backends/local-storage-backend.js";
2
- import { ProviderKeysRepository } from "./repositories/provider-keys-repository.js";
3
- import { SettingsRepository } from "./repositories/settings-repository.js";
4
- import type { AppStorageConfig } from "./types.js";
1
+ import type { ProviderKeysStore } from "./stores/provider-keys-store.js";
2
+ import type { SessionsStore } from "./stores/sessions-store.js";
3
+ import type { SettingsStore } from "./stores/settings-store.js";
4
+ import type { StorageBackend } from "./types.js";
5
5
 
6
6
  /**
7
- * High-level storage API aggregating all repositories.
8
- * Apps configure backends and use repositories through this interface.
7
+ * High-level storage API providing access to all storage operations.
8
+ * Subclasses can extend this to add domain-specific stores.
9
9
  */
10
10
  export class AppStorage {
11
- readonly settings: SettingsRepository;
12
- readonly providerKeys: ProviderKeysRepository;
11
+ readonly backend: StorageBackend;
12
+ readonly settings: SettingsStore;
13
+ readonly providerKeys: ProviderKeysStore;
14
+ readonly sessions: SessionsStore;
13
15
 
14
- constructor(config: AppStorageConfig = {}) {
15
- // Use LocalStorage with prefixes as defaults
16
- const settingsBackend = config.settings ?? new LocalStorageBackend("settings");
17
- const providerKeysBackend = config.providerKeys ?? new LocalStorageBackend("providerKeys");
16
+ constructor(
17
+ settings: SettingsStore,
18
+ providerKeys: ProviderKeysStore,
19
+ sessions: SessionsStore,
20
+ backend: StorageBackend,
21
+ ) {
22
+ this.settings = settings;
23
+ this.providerKeys = providerKeys;
24
+ this.sessions = sessions;
25
+ this.backend = backend;
26
+ }
27
+
28
+ async getQuotaInfo(): Promise<{ usage: number; quota: number; percent: number }> {
29
+ return this.backend.getQuotaInfo();
30
+ }
18
31
 
19
- this.settings = new SettingsRepository(settingsBackend);
20
- this.providerKeys = new ProviderKeysRepository(providerKeysBackend);
32
+ async requestPersistence(): Promise<boolean> {
33
+ return this.backend.requestPersistence();
21
34
  }
22
35
  }
23
36
 
@@ -41,13 +54,3 @@ export function getAppStorage(): AppStorage {
41
54
  export function setAppStorage(storage: AppStorage): void {
42
55
  globalAppStorage = storage;
43
56
  }
44
-
45
- /**
46
- * Initialize AppStorage with default configuration if not already set.
47
- */
48
- export function initAppStorage(config: AppStorageConfig = {}): AppStorage {
49
- if (!globalAppStorage) {
50
- globalAppStorage = new AppStorage(config);
51
- }
52
- return globalAppStorage;
53
- }
@@ -0,0 +1,193 @@
1
+ import type { IndexedDBConfig, StorageBackend, StorageTransaction } from "../types.js";
2
+
3
+ /**
4
+ * IndexedDB implementation of StorageBackend.
5
+ * Provides multi-store key-value storage with transactions and quota management.
6
+ */
7
+ export class IndexedDBStorageBackend implements StorageBackend {
8
+ private dbPromise: Promise<IDBDatabase> | null = null;
9
+
10
+ constructor(private config: IndexedDBConfig) {}
11
+
12
+ private async getDB(): Promise<IDBDatabase> {
13
+ if (!this.dbPromise) {
14
+ this.dbPromise = new Promise((resolve, reject) => {
15
+ const request = indexedDB.open(this.config.dbName, this.config.version);
16
+
17
+ request.onerror = () => reject(request.error);
18
+ request.onsuccess = () => resolve(request.result);
19
+
20
+ request.onupgradeneeded = (_event) => {
21
+ const db = request.result;
22
+
23
+ // Create object stores from config
24
+ for (const storeConfig of this.config.stores) {
25
+ if (!db.objectStoreNames.contains(storeConfig.name)) {
26
+ const store = db.createObjectStore(storeConfig.name, {
27
+ keyPath: storeConfig.keyPath,
28
+ autoIncrement: storeConfig.autoIncrement,
29
+ });
30
+
31
+ // Create indices
32
+ if (storeConfig.indices) {
33
+ for (const indexConfig of storeConfig.indices) {
34
+ store.createIndex(indexConfig.name, indexConfig.keyPath, {
35
+ unique: indexConfig.unique,
36
+ });
37
+ }
38
+ }
39
+ }
40
+ }
41
+ };
42
+ });
43
+ }
44
+
45
+ return this.dbPromise;
46
+ }
47
+
48
+ private promisifyRequest<T>(request: IDBRequest<T>): Promise<T> {
49
+ return new Promise((resolve, reject) => {
50
+ request.onsuccess = () => resolve(request.result);
51
+ request.onerror = () => reject(request.error);
52
+ });
53
+ }
54
+
55
+ async get<T = unknown>(storeName: string, key: string): Promise<T | null> {
56
+ const db = await this.getDB();
57
+ const tx = db.transaction(storeName, "readonly");
58
+ const store = tx.objectStore(storeName);
59
+ const result = await this.promisifyRequest(store.get(key));
60
+ return result ?? null;
61
+ }
62
+
63
+ async set<T = unknown>(storeName: string, key: string, value: T): Promise<void> {
64
+ const db = await this.getDB();
65
+ const tx = db.transaction(storeName, "readwrite");
66
+ const store = tx.objectStore(storeName);
67
+ // If store has keyPath, only pass value (in-line key)
68
+ // Otherwise pass both value and key (out-of-line key)
69
+ if (store.keyPath) {
70
+ await this.promisifyRequest(store.put(value));
71
+ } else {
72
+ await this.promisifyRequest(store.put(value, key));
73
+ }
74
+ }
75
+
76
+ async delete(storeName: string, key: string): Promise<void> {
77
+ const db = await this.getDB();
78
+ const tx = db.transaction(storeName, "readwrite");
79
+ const store = tx.objectStore(storeName);
80
+ await this.promisifyRequest(store.delete(key));
81
+ }
82
+
83
+ async keys(storeName: string, prefix?: string): Promise<string[]> {
84
+ const db = await this.getDB();
85
+ const tx = db.transaction(storeName, "readonly");
86
+ const store = tx.objectStore(storeName);
87
+
88
+ if (prefix) {
89
+ // Use IDBKeyRange for efficient prefix filtering
90
+ const range = IDBKeyRange.bound(prefix, prefix + "\uffff", false, false);
91
+ const keys = await this.promisifyRequest(store.getAllKeys(range));
92
+ return keys.map((k) => String(k));
93
+ } else {
94
+ const keys = await this.promisifyRequest(store.getAllKeys());
95
+ return keys.map((k) => String(k));
96
+ }
97
+ }
98
+
99
+ async getAllFromIndex<T = unknown>(
100
+ storeName: string,
101
+ indexName: string,
102
+ direction: "asc" | "desc" = "asc",
103
+ ): Promise<T[]> {
104
+ const db = await this.getDB();
105
+ const tx = db.transaction(storeName, "readonly");
106
+ const store = tx.objectStore(storeName);
107
+ const index = store.index(indexName);
108
+
109
+ return new Promise((resolve, reject) => {
110
+ const results: T[] = [];
111
+ const request = index.openCursor(null, direction === "desc" ? "prev" : "next");
112
+
113
+ request.onsuccess = () => {
114
+ const cursor = request.result;
115
+ if (cursor) {
116
+ results.push(cursor.value as T);
117
+ cursor.continue();
118
+ } else {
119
+ resolve(results);
120
+ }
121
+ };
122
+
123
+ request.onerror = () => reject(request.error);
124
+ });
125
+ }
126
+
127
+ async clear(storeName: string): Promise<void> {
128
+ const db = await this.getDB();
129
+ const tx = db.transaction(storeName, "readwrite");
130
+ const store = tx.objectStore(storeName);
131
+ await this.promisifyRequest(store.clear());
132
+ }
133
+
134
+ async has(storeName: string, key: string): Promise<boolean> {
135
+ const db = await this.getDB();
136
+ const tx = db.transaction(storeName, "readonly");
137
+ const store = tx.objectStore(storeName);
138
+ const result = await this.promisifyRequest(store.getKey(key));
139
+ return result !== undefined;
140
+ }
141
+
142
+ async transaction<T>(
143
+ storeNames: string[],
144
+ mode: "readonly" | "readwrite",
145
+ operation: (tx: StorageTransaction) => Promise<T>,
146
+ ): Promise<T> {
147
+ const db = await this.getDB();
148
+ const idbTx = db.transaction(storeNames, mode);
149
+
150
+ const storageTx: StorageTransaction = {
151
+ get: async <T>(storeName: string, key: string) => {
152
+ const store = idbTx.objectStore(storeName);
153
+ const result = await this.promisifyRequest(store.get(key));
154
+ return (result ?? null) as T | null;
155
+ },
156
+ set: async <T>(storeName: string, key: string, value: T) => {
157
+ const store = idbTx.objectStore(storeName);
158
+ // If store has keyPath, only pass value (in-line key)
159
+ // Otherwise pass both value and key (out-of-line key)
160
+ if (store.keyPath) {
161
+ await this.promisifyRequest(store.put(value));
162
+ } else {
163
+ await this.promisifyRequest(store.put(value, key));
164
+ }
165
+ },
166
+ delete: async (storeName: string, key: string) => {
167
+ const store = idbTx.objectStore(storeName);
168
+ await this.promisifyRequest(store.delete(key));
169
+ },
170
+ };
171
+
172
+ return operation(storageTx);
173
+ }
174
+
175
+ async getQuotaInfo(): Promise<{ usage: number; quota: number; percent: number }> {
176
+ if (navigator.storage?.estimate) {
177
+ const estimate = await navigator.storage.estimate();
178
+ return {
179
+ usage: estimate.usage || 0,
180
+ quota: estimate.quota || 0,
181
+ percent: estimate.quota ? ((estimate.usage || 0) / estimate.quota) * 100 : 0,
182
+ };
183
+ }
184
+ return { usage: 0, quota: 0, percent: 0 };
185
+ }
186
+
187
+ async requestPersistence(): Promise<boolean> {
188
+ if (navigator.storage?.persist) {
189
+ return await navigator.storage.persist();
190
+ }
191
+ return false;
192
+ }
193
+ }