llms-py 3.0.0__py3-none-any.whl → 3.0.0b2__py3-none-any.whl

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 (195) hide show
  1. llms/__pycache__/main.cpython-314.pyc +0 -0
  2. llms/index.html +37 -26
  3. llms/llms.json +21 -70
  4. llms/main.py +731 -1426
  5. llms/providers.json +1 -1
  6. llms/{extensions/analytics/ui/index.mjs → ui/Analytics.mjs} +238 -154
  7. llms/ui/App.mjs +63 -133
  8. llms/ui/Avatar.mjs +86 -0
  9. llms/ui/Brand.mjs +52 -0
  10. llms/ui/ChatPrompt.mjs +597 -0
  11. llms/ui/Main.mjs +862 -0
  12. llms/ui/OAuthSignIn.mjs +61 -0
  13. llms/ui/ProviderIcon.mjs +36 -0
  14. llms/ui/ProviderStatus.mjs +104 -0
  15. llms/{extensions/app/ui → ui}/Recents.mjs +57 -82
  16. llms/ui/{modules/chat/SettingsDialog.mjs → SettingsDialog.mjs} +9 -9
  17. llms/{extensions/app/ui/index.mjs → ui/Sidebar.mjs} +57 -122
  18. llms/ui/SignIn.mjs +65 -0
  19. llms/ui/Welcome.mjs +8 -0
  20. llms/ui/ai.mjs +13 -117
  21. llms/ui/app.css +49 -1776
  22. llms/ui/index.mjs +171 -87
  23. llms/ui/lib/charts.mjs +13 -9
  24. llms/ui/lib/servicestack-vue.mjs +3 -3
  25. llms/ui/lib/vue.min.mjs +9 -10
  26. llms/ui/lib/vue.mjs +1602 -1763
  27. llms/ui/markdown.mjs +2 -10
  28. llms/ui/model-selector.mjs +686 -0
  29. llms/ui/tailwind.input.css +1 -55
  30. llms/ui/threadStore.mjs +583 -0
  31. llms/ui/utils.mjs +118 -113
  32. llms/ui.json +1069 -0
  33. {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/METADATA +1 -1
  34. llms_py-3.0.0b2.dist-info/RECORD +58 -0
  35. llms/extensions/app/README.md +0 -20
  36. llms/extensions/app/__init__.py +0 -530
  37. llms/extensions/app/__pycache__/__init__.cpython-314.pyc +0 -0
  38. llms/extensions/app/__pycache__/db.cpython-314.pyc +0 -0
  39. llms/extensions/app/__pycache__/db_manager.cpython-314.pyc +0 -0
  40. llms/extensions/app/db.py +0 -644
  41. llms/extensions/app/db_manager.py +0 -195
  42. llms/extensions/app/requests.json +0 -9073
  43. llms/extensions/app/threads.json +0 -15290
  44. llms/extensions/app/ui/threadStore.mjs +0 -411
  45. llms/extensions/core_tools/CALCULATOR.md +0 -32
  46. llms/extensions/core_tools/__init__.py +0 -598
  47. llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
  48. llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +0 -201
  49. llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +0 -185
  50. llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +0 -101
  51. llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +0 -160
  52. llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +0 -66
  53. llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +0 -27
  54. llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +0 -72
  55. llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +0 -119
  56. llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +0 -98
  57. llms/extensions/core_tools/ui/codemirror/doc/docs.css +0 -225
  58. llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
  59. llms/extensions/core_tools/ui/codemirror/lib/codemirror.css +0 -344
  60. llms/extensions/core_tools/ui/codemirror/lib/codemirror.js +0 -9884
  61. llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +0 -942
  62. llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +0 -118
  63. llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +0 -962
  64. llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +0 -62
  65. llms/extensions/core_tools/ui/codemirror/mode/python/python.js +0 -402
  66. llms/extensions/core_tools/ui/codemirror/theme/dracula.css +0 -40
  67. llms/extensions/core_tools/ui/codemirror/theme/mocha.css +0 -135
  68. llms/extensions/core_tools/ui/index.mjs +0 -650
  69. llms/extensions/gallery/README.md +0 -61
  70. llms/extensions/gallery/__init__.py +0 -61
  71. llms/extensions/gallery/__pycache__/__init__.cpython-314.pyc +0 -0
  72. llms/extensions/gallery/__pycache__/db.cpython-314.pyc +0 -0
  73. llms/extensions/gallery/db.py +0 -298
  74. llms/extensions/gallery/ui/index.mjs +0 -482
  75. llms/extensions/katex/README.md +0 -39
  76. llms/extensions/katex/__init__.py +0 -6
  77. llms/extensions/katex/__pycache__/__init__.cpython-314.pyc +0 -0
  78. llms/extensions/katex/ui/README.md +0 -125
  79. llms/extensions/katex/ui/contrib/auto-render.js +0 -338
  80. llms/extensions/katex/ui/contrib/auto-render.min.js +0 -1
  81. llms/extensions/katex/ui/contrib/auto-render.mjs +0 -244
  82. llms/extensions/katex/ui/contrib/copy-tex.js +0 -127
  83. llms/extensions/katex/ui/contrib/copy-tex.min.js +0 -1
  84. llms/extensions/katex/ui/contrib/copy-tex.mjs +0 -105
  85. llms/extensions/katex/ui/contrib/mathtex-script-type.js +0 -109
  86. llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +0 -1
  87. llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +0 -24
  88. llms/extensions/katex/ui/contrib/mhchem.js +0 -3213
  89. llms/extensions/katex/ui/contrib/mhchem.min.js +0 -1
  90. llms/extensions/katex/ui/contrib/mhchem.mjs +0 -3109
  91. llms/extensions/katex/ui/contrib/render-a11y-string.js +0 -887
  92. llms/extensions/katex/ui/contrib/render-a11y-string.min.js +0 -1
  93. llms/extensions/katex/ui/contrib/render-a11y-string.mjs +0 -800
  94. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
  95. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
  96. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  97. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  98. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  99. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  100. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  101. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  102. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  103. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  104. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  105. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  106. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  107. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  108. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  109. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
  110. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
  111. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
  112. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  113. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  114. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  115. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
  116. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
  117. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
  118. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
  119. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
  120. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
  121. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  122. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  123. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  124. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
  125. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
  126. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
  127. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  128. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  129. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  130. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  131. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  132. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  133. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  134. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  135. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  136. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
  137. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
  138. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
  139. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
  140. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
  141. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  142. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
  143. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
  144. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  145. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
  146. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
  147. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  148. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
  149. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
  150. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  151. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  152. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  153. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  154. llms/extensions/katex/ui/index.mjs +0 -92
  155. llms/extensions/katex/ui/katex-swap.css +0 -1230
  156. llms/extensions/katex/ui/katex-swap.min.css +0 -1
  157. llms/extensions/katex/ui/katex.css +0 -1230
  158. llms/extensions/katex/ui/katex.js +0 -19080
  159. llms/extensions/katex/ui/katex.min.css +0 -1
  160. llms/extensions/katex/ui/katex.min.js +0 -1
  161. llms/extensions/katex/ui/katex.min.mjs +0 -1
  162. llms/extensions/katex/ui/katex.mjs +0 -18547
  163. llms/extensions/providers/__init__.py +0 -18
  164. llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  165. llms/extensions/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  166. llms/extensions/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  167. llms/extensions/providers/__pycache__/google.cpython-314.pyc +0 -0
  168. llms/extensions/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
  169. llms/extensions/providers/__pycache__/openai.cpython-314.pyc +0 -0
  170. llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  171. llms/extensions/providers/anthropic.py +0 -229
  172. llms/extensions/providers/chutes.py +0 -155
  173. llms/extensions/providers/google.py +0 -378
  174. llms/extensions/providers/nvidia.py +0 -105
  175. llms/extensions/providers/openai.py +0 -156
  176. llms/extensions/providers/openrouter.py +0 -72
  177. llms/extensions/system_prompts/README.md +0 -22
  178. llms/extensions/system_prompts/__init__.py +0 -45
  179. llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
  180. llms/extensions/system_prompts/ui/index.mjs +0 -280
  181. llms/extensions/system_prompts/ui/prompts.json +0 -1067
  182. llms/extensions/tools/__init__.py +0 -5
  183. llms/extensions/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  184. llms/extensions/tools/ui/index.mjs +0 -204
  185. llms/providers-extra.json +0 -356
  186. llms/ui/ctx.mjs +0 -365
  187. llms/ui/modules/chat/ChatBody.mjs +0 -691
  188. llms/ui/modules/chat/index.mjs +0 -828
  189. llms/ui/modules/layout.mjs +0 -243
  190. llms/ui/modules/model-selector.mjs +0 -851
  191. llms_py-3.0.0.dist-info/RECORD +0 -202
  192. {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/WHEEL +0 -0
  193. {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/entry_points.txt +0 -0
  194. {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/licenses/LICENSE +0 -0
  195. {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llms-py
3
- Version: 3.0.0
3
+ Version: 3.0.0b2
4
4
  Summary: A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers
5
5
  Home-page: https://github.com/ServiceStack/llms
6
6
  Author: ServiceStack
@@ -0,0 +1,58 @@
1
+ llms/__init__.py,sha256=DKwTZDsyYL_wHe7yvLw49Nf8PSgPSyWaeVdotUqSvrQ,84
2
+ llms/__main__.py,sha256=hrBulHIt3lmPm1BCyAEVtB6DQ0Hvc3gnIddhHCmJasg,151
3
+ llms/index.html,sha256=K-kQuV8Qk-ZdD0iyWbLBGxuo7jY8dXLlSY-cXFHv84c,2079
4
+ llms/llms.json,sha256=e9CDUaABFuNxcsF6lOlKBTJcX3MKAGY3jED7CgCUZF0,9699
5
+ llms/main.py,sha256=Gl69g6oNo7tRohJxZgCK27qtelhNxnmj1Li_uEoadrE,130839
6
+ llms/providers.json,sha256=_0YEqStJhnXKjQuXssayj8CH12VFAuQWuvyrBQtCWr4,226852
7
+ llms/ui.json,sha256=iBOmpNeD5-o8AgUa51ymS-KemovJ7bm9J1fnL0nf8jk,134025
8
+ llms/__pycache__/__init__.cpython-312.pyc,sha256=lg2oFc0aKgj536NOJxcIpbCpEWi47ptF8NufPphgUUk,204
9
+ llms/__pycache__/__init__.cpython-313.pyc,sha256=DvmykIYAjV4Xjv5NeC70BA0JIX8qtwEWP2dfzmOBrps,173
10
+ llms/__pycache__/__init__.cpython-314.pyc,sha256=9CxeBz41D_-ezno6pIOsnoMAFzdRX2uZjKkBLUm25RQ,206
11
+ llms/__pycache__/__main__.cpython-312.pyc,sha256=fcu9LVl5nfdSzg9HqoKyDGoDvENeIXKkjygN7FENEGE,321
12
+ llms/__pycache__/__main__.cpython-314.pyc,sha256=IFxtGVpJq_3whKuM5Ln7YMweKFNbHVp8M7VSrLK5h2A,324
13
+ llms/__pycache__/llms.cpython-312.pyc,sha256=S5dFI79JdUe2dQW4ogdB-CCNhudQeFaFGcfKxgJGBms,72080
14
+ llms/__pycache__/main.cpython-312.pyc,sha256=HrqApYAiiBmYN73HIx_Hl2-Xm1Gy7I_0zuR5j86qoRM,104940
15
+ llms/__pycache__/main.cpython-313.pyc,sha256=6NQ__SJ2rC9ItFLKLHL5ewb5RqxLzZabwgczA9wZd-w,74814
16
+ llms/__pycache__/main.cpython-314.pyc,sha256=EZZmS1VitUA1zdiwfIYW-b4cpEsbrFESNdGJRcv3vHU,164343
17
+ llms/__pycache__/plugins.cpython-314.pyc,sha256=fer8nTkidG_vQSx80tL2bAvMS0opDom93bewjseFcyg,3560
18
+ llms/ui/Analytics.mjs,sha256=LfWbUlpb__0EEYtHu6e4r8AeyhsNQeAxrg44RuNSR0M,73261
19
+ llms/ui/App.mjs,sha256=JMxFtsJ03sZZYmHseCOG3mei0TyB5WSCsqlLlnGCLDU,4478
20
+ llms/ui/Avatar.mjs,sha256=VdTFpzD1ZpYW6WhcLjmOkEtMGJGgG4RaeLd8GUKpBcU,3416
21
+ llms/ui/Brand.mjs,sha256=JLN_lPirNXqS332g0B_WVOlFRVg3lNe1Q56TRnpj0zQ,3411
22
+ llms/ui/ChatPrompt.mjs,sha256=Bpvp9ANq_nnZBpmzMbOnYp_rPATla1Xa9qMZzMegXFk,26588
23
+ llms/ui/Main.mjs,sha256=KlIUA-tj7yBKl2rTyzbLn2xp2MLlowMWI3XtSM2UR6I,45258
24
+ llms/ui/OAuthSignIn.mjs,sha256=3WzJ4mhwHgN2ymkb5cmYHpJi961KgctwAbM_uJ7Cq8k,3504
25
+ llms/ui/ProviderIcon.mjs,sha256=XdEJRm90Zaeu7AlcxfLTXqh_jj2F5JvFkug0XexZeQc,22900
26
+ llms/ui/ProviderStatus.mjs,sha256=aeYN0Rr2oYpEKGAAkqmdp618tY504rRgTSPbOaLCSzU,6081
27
+ llms/ui/Recents.mjs,sha256=asQgduWj1eP0o1ft5CnlS85jDpP60mkUD4xtmQpTxmo,8902
28
+ llms/ui/SettingsDialog.mjs,sha256=vyqLOrACBICwT8qQ10oJAMOYeA1phrAyz93mZygn-9Y,19956
29
+ llms/ui/Sidebar.mjs,sha256=bIRafgZRpNzxZwTxElJ1hM-zry2oz3DMp_aX8VRK1rU,11211
30
+ llms/ui/SignIn.mjs,sha256=hJ-lCZtt4GfVBv8ylGsZ7CB1yJLcZVhHqEdfGLjKKN4,2340
31
+ llms/ui/Welcome.mjs,sha256=r9j7unF9CF3k7gEQBMRMVsa2oSjgHGNn46Oa5l5BwlY,950
32
+ llms/ui/ai.mjs,sha256=k4kqD33Rx-lHVOqmVlFmAyqV3pKA5SyCjnD5Pmr69yU,3346
33
+ llms/ui/app.css,sha256=Qavq-7xEfzKZ67-LDIsmVpNbgaRkmiBP0HOrMhXpA6M,118798
34
+ llms/ui/fav.svg,sha256=_R6MFeXl6wBFT0lqcUxYQIDWgm246YH_3hSTW0oO8qw,734
35
+ llms/ui/index.mjs,sha256=O7DCCFQ0ozCkDIeTkp_Jk1lbwO_lxYm_jx_NClKA1zU,6353
36
+ llms/ui/markdown.mjs,sha256=0LUF2Tyvpv88ic-MjdUjAAdd1Rt8LYA_d7VRA-kBFuM,6518
37
+ llms/ui/model-selector.mjs,sha256=wREYMzM0ItfEVhNyKS16BA08jJCfo8MXWNoPY4mHrUI,35619
38
+ llms/ui/tailwind.input.css,sha256=5PiDdc5nyPE9Fheg_PgLnz3RR3C0o5x6M3M-KWVFo-4,14403
39
+ llms/ui/threadStore.mjs,sha256=r5KWZnQ3yf06cseFfwaIHFUrm190GhIrVEZ_vo8VHbM,16821
40
+ llms/ui/typography.css,sha256=6o7pbMIamRVlm2GfzSStpcOG4T5eFCK_WcQ3RIHKAsU,19587
41
+ llms/ui/utils.mjs,sha256=Lw2MSuN4qYSJsf0HwBOCgSI2i5o-hi_nEgFycd2DI0g,7340
42
+ llms/ui/lib/chart.js,sha256=dx8FdDX0Rv6OZtZjr9FQh5h-twFsKjfnb-FvFlQ--cU,196176
43
+ llms/ui/lib/charts.mjs,sha256=MNym9qE_2eoH6M7_8Gj9i6e6-Y3b7zw9UQWCUHRF6x0,1088
44
+ llms/ui/lib/color.js,sha256=DDG7Pr-qzJHTPISZNSqP_qJR8UflKHEc_56n6xrBugQ,8273
45
+ llms/ui/lib/highlight.min.mjs,sha256=sG7wq8bF-IKkfie7S4QSyh5DdHBRf0NqQxMOEH8-MT0,127458
46
+ llms/ui/lib/idb.min.mjs,sha256=CeTXyV4I_pB5vnibvJuyXdMs0iVF2ZL0Z7cdm3w_QaI,3853
47
+ llms/ui/lib/marked.min.mjs,sha256=QRHb_VZugcBJRD2EP6gYlVFEsJw5C2fQ8ImMf_pA2_s,39488
48
+ llms/ui/lib/servicestack-client.mjs,sha256=UVafVbzhJ_0N2lzv7rlzIbzwnWpoqXxGk3N3FSKgOOc,54534
49
+ llms/ui/lib/servicestack-vue.mjs,sha256=unTA8lM0tKy2PwZiJ8UEvrTuGmei8jNZnmmuQ5MKyV4,216753
50
+ llms/ui/lib/vue-router.min.mjs,sha256=fR30GHoXI1u81zyZ26YEU105pZgbbAKSXbpnzFKIxls,30418
51
+ llms/ui/lib/vue.min.mjs,sha256=iXh97m5hotl0eFllb3aoasQTImvp7mQoRJ_0HoxmZkw,163811
52
+ llms/ui/lib/vue.mjs,sha256=dS8LKOG01t9CvZ04i0tbFXHqFXOO_Ha4NmM3BytjQAs,537071
53
+ llms_py-3.0.0b2.dist-info/licenses/LICENSE,sha256=bus9cuAOWeYqBk2OuhSABVV1P4z7hgrEFISpyda_H5w,1532
54
+ llms_py-3.0.0b2.dist-info/METADATA,sha256=D8vEf8jkSvsAu3jOgJ-SIj8j3HsFqXjpJy5d2s_dT-o,2193
55
+ llms_py-3.0.0b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
+ llms_py-3.0.0b2.dist-info/entry_points.txt,sha256=WswyE7PfnkZMIxboC-MS6flBD6wm-CYU7JSUnMhqMfM,40
57
+ llms_py-3.0.0b2.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
58
+ llms_py-3.0.0b2.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- # App Extension
2
-
3
- This extension provides the core application logic and data persistence for the LLMs platform.
4
-
5
- ## Data Storage & Architecture
6
-
7
- ### Server-Side SQLite Migration
8
- The application has migrated from client-side IndexedDB storage to a robust server-side SQLite solution. This architectural shift ensures better data consistency, improved performance, and enables multi-device access to your chat history.
9
-
10
- ### Asset Management
11
- To keep the database efficient and portable, binary assets (images, audio, etc.) are not stored directly in the SQLite database. Instead:
12
- - All generated assets are stored in the local file system cache at `~/.llms/cache`.
13
- - The database stores only **relative URLs** pointing to these assets.
14
- - This approach allows for efficient caching and serving of static media.
15
-
16
- ### Concurrency Model
17
- To ensure data integrity and high performance without complex locking mechanisms, the system utilizes a **single background thread** for managing all write operations to the database. This design improves concurrency handling and eliminates database locking issues during high-load scenarios.
18
-
19
- ### Multi-Tenancy & Security
20
- When authentication is enabled, data isolation is automatically enforced. All core tables, including `threads` and `requests`, are scoped to the authenticated user, ensuring that users can only access their own data.
@@ -1,530 +0,0 @@
1
- import asyncio
2
- import json
3
- import os
4
- import time
5
- from datetime import datetime
6
- from typing import Any
7
-
8
- from aiohttp import web
9
-
10
- g_db = None
11
-
12
- try:
13
- from llms.extensions.app.db import AppDB
14
- except ImportError as e:
15
- print(f"Failed to import AppDB: {e}")
16
- AppDB = None
17
-
18
-
19
- def install(ctx):
20
- def get_db():
21
- global g_db
22
- if g_db is None and AppDB:
23
- try:
24
- db_path = os.path.join(ctx.get_user_path(), "app", "app.sqlite")
25
- g_db = AppDB(ctx, db_path)
26
- ctx.register_shutdown_handler(g_db.close)
27
-
28
- threads_json = "/home/mythz/src/ServiceStack/llms/llms/extensions/app/threads.json"
29
- requests_json = "/home/mythz/src/ServiceStack/llms/llms/extensions/app/requests.json"
30
- with open(threads_json) as f:
31
- threads = json.load(f)["threads"]
32
- threads.reverse()
33
- with open(requests_json) as f:
34
- requests = json.load(f)["requests"]
35
- requests.reverse()
36
- # g_db.import_db(threads, requests)
37
-
38
- except Exception as e:
39
- ctx.err("Failed to init AppDB", e)
40
- return g_db
41
-
42
- if not get_db():
43
- return
44
-
45
- def to_dto(row, json_columns):
46
- # as=column -> [0,1,2]
47
- if not isinstance(row, dict):
48
- return row
49
-
50
- to = {}
51
- for k, v in row.items():
52
- if k in json_columns and v is not None and isinstance(v, str):
53
- try:
54
- to[k] = json.loads(v)
55
- except Exception as e:
56
- ctx.err(f"Failed to parse JSON for {k}: {v} ({type(v)})", e)
57
- to[k] = v
58
- else:
59
- to[k] = v
60
- return to
61
-
62
- def thread_dto(row):
63
- return row and to_dto(row, ["messages", "modalities", "args", "modelInfo", "stats", "metadata"])
64
-
65
- def request_dto(row):
66
- return row and to_dto(row, ["usage"])
67
-
68
- def prompt_to_title(prompt):
69
- return prompt[:100] + ("..." if len(prompt) > 100 else "") if prompt else None
70
-
71
- def timestamp_messages(messages):
72
- timestamp = int(time.time() * 1000)
73
- for message in messages:
74
- if "timestamp" not in message:
75
- message["timestamp"] = timestamp
76
- timestamp += 1 # make unique
77
- return messages
78
-
79
- async def query_threads(request):
80
- rows = g_db.query_threads(request.query, user=ctx.get_username(request))
81
- dtos = [thread_dto(row) for row in rows]
82
- return web.json_response(dtos)
83
-
84
- ctx.add_get("threads", query_threads)
85
-
86
- async def create_thread(request):
87
- thread = await request.json()
88
- id = await g_db.create_thread_async(thread, user=ctx.get_username(request))
89
- row = g_db.get_thread(id, user=ctx.get_username(request))
90
- return web.json_response(thread_dto(row) if row else "")
91
-
92
- ctx.add_post("threads", create_thread)
93
-
94
- async def update_thread(request):
95
- thread = await request.json()
96
- id = request.match_info["id"]
97
- update_count = await g_db.update_thread_async(id, thread, user=ctx.get_username(request))
98
- if update_count == 0:
99
- raise Exception("Thread not found")
100
- row = g_db.get_thread(id, user=ctx.get_username(request))
101
- return web.json_response(thread_dto(row) if row else "")
102
-
103
- ctx.add_patch("threads/{id}", update_thread)
104
-
105
- async def delete_thread(request):
106
- id = request.match_info["id"]
107
- g_db.delete_thread(id, user=ctx.get_username(request))
108
- return web.json_response({})
109
-
110
- ctx.add_delete("threads/{id}", delete_thread)
111
-
112
- async def queue_chat_handler(request):
113
- # Check authentication if enabled
114
- is_authenticated, user_data = ctx.check_auth(request)
115
- if not is_authenticated:
116
- return web.json_response(ctx.error_auth_required, status=401)
117
-
118
- if not request.body_exists:
119
- raise Exception("messages required")
120
-
121
- chat = await request.json()
122
-
123
- messages = timestamp_messages(chat.get("messages", []))
124
- if len(messages) == 0:
125
- raise Exception("messages required")
126
-
127
- id = request.match_info["id"]
128
- thread = thread_dto(g_db.get_thread(id, user=ctx.get_username(request)))
129
- if not thread:
130
- raise Exception("Thread not found")
131
-
132
- update_thread = {
133
- "messages": messages,
134
- "startedAt": datetime.now(),
135
- "completedAt": None,
136
- "error": None,
137
- }
138
-
139
- model = chat.get("model", None)
140
- if model:
141
- update_thread["model"] = model
142
- metadata = chat.get("metadata", {})
143
- if len(metadata) > 0:
144
- update_thread["metadata"] = metadata
145
- if chat.get("modalities") or not thread.get("modalities"):
146
- update_thread["modalities"] = chat.get("modalities", ["text"])
147
- system_prompt = ctx.chat_to_system_prompt(chat)
148
- if system_prompt:
149
- update_thread["systemPrompt"] = system_prompt
150
-
151
- args = thread.get("args") or {}
152
- for k, v in chat.items():
153
- if k in ctx.request_args:
154
- args[k] = v
155
- update_thread["args"] = args
156
-
157
- # allow chat to override thread title
158
- title = chat.get("title")
159
- if title:
160
- update_thread["title"] = title
161
- else:
162
- # only update thread title if it's not already set
163
- title = thread.get("title")
164
- if not title:
165
- update_thread["title"] = title = prompt_to_title(ctx.last_user_prompt(chat))
166
-
167
- user = ctx.get_username(request)
168
- await g_db.update_thread_async(
169
- id,
170
- update_thread,
171
- user=user,
172
- )
173
- thread = thread_dto(g_db.get_thread(id, user=user))
174
- if not thread:
175
- raise Exception("Thread not found")
176
-
177
- metadata = thread.get("metadata", {})
178
- chat = {
179
- "model": thread.get("model"),
180
- "messages": thread.get("messages"),
181
- "modalities": thread.get("modalities"),
182
- "systemPrompt": thread.get("systemPrompt"),
183
- "metadata": metadata,
184
- }
185
- for k, v in thread.get("args", {}).items():
186
- if k in ctx.request_args:
187
- chat[k] = v
188
-
189
- context = {
190
- "chat": chat,
191
- "user": user,
192
- "threadId": id,
193
- "metadata": metadata,
194
- "tools": metadata.get("tools", "all"),
195
- }
196
-
197
- # execute chat in background thread
198
- async def run_chat(chat_req, context_req):
199
- try:
200
- await ctx.chat_completion(chat_req, context=context_req)
201
- except Exception as ex:
202
- ctx.err("run_chat", ex)
203
- # not necessary to update thread in db with error as it's done in chat_error filter
204
-
205
- asyncio.create_task(run_chat(chat, context))
206
-
207
- return web.json_response(thread_dto(thread))
208
-
209
- ctx.add_post("threads/{id}/chat", queue_chat_handler)
210
-
211
- async def get_thread_updates(request):
212
- id = request.match_info["id"]
213
- after = request.query.get("after", None)
214
- user = ctx.get_username(request)
215
- thread = g_db.get_thread(id, user=user)
216
- if not thread:
217
- raise Exception("Thread not found")
218
- if after:
219
- started = time.time()
220
- thread_id = thread.get("id")
221
- thread_updated_at = thread.get("updatedAt")
222
-
223
- while thread_updated_at <= after:
224
- thread_updated_at = g_db.get_thread_column(thread_id, "updatedAt", user=user)
225
- # if thread is not updated in 30 seconds, break
226
- if time.time() - started > 10:
227
- break
228
- await asyncio.sleep(1)
229
- ctx.dbg(f"get_thread_updates: {thread_id} / {thread_updated_at} < {after} / {thread_updated_at < after}")
230
- thread = g_db.get_thread(thread_id, user=user)
231
- return web.json_response(thread_dto(thread))
232
-
233
- ctx.add_get("threads/{id}/updates", get_thread_updates)
234
-
235
- async def cancel_thread(request):
236
- id = request.match_info["id"]
237
- await g_db.update_thread_async(
238
- id, {"completedAt": datetime.now(), "error": "Request was canceled"}, user=ctx.get_username(request)
239
- )
240
- thread = g_db.get_thread(id, user=ctx.get_username(request))
241
- ctx.dbg(f"cancel_thread: {id} / {thread.get('error')} / {thread.get('completedAt')}")
242
- return web.json_response(thread_dto(thread))
243
-
244
- ctx.add_post("threads/{id}/cancel", cancel_thread)
245
-
246
- async def query_requests(request):
247
- rows = g_db.query_requests(request.query, user=ctx.get_username(request))
248
- dtos = [request_dto(row) for row in rows]
249
- return web.json_response(dtos)
250
-
251
- ctx.add_get("requests", query_requests)
252
-
253
- async def delete_request(request):
254
- id = request.match_info["id"]
255
- g_db.delete_request(id, user=ctx.get_username(request))
256
- return web.json_response({})
257
-
258
- ctx.add_delete("requests/{id}", delete_request)
259
-
260
- async def requests_summary(request):
261
- rows = g_db.get_request_summary(user=ctx.get_username(request))
262
- stats = {
263
- "dailyData": {},
264
- "years": [],
265
- "totalCost": 0,
266
- "totalRequests": 0,
267
- "totalInputTokens": 0,
268
- "totalOutputTokens": 0,
269
- }
270
- years = set()
271
- for row in rows:
272
- date = row["date"]
273
- year = int(date[:4])
274
- years.add(year)
275
- stats["dailyData"][date] = {
276
- "cost": row["cost"],
277
- "requests": row["requests"],
278
- "inputTokens": row["inputTokens"],
279
- "outputTokens": row["outputTokens"],
280
- }
281
- stats["totalCost"] += row["cost"] or 0
282
- stats["totalRequests"] += row["requests"] or 0
283
- stats["totalInputTokens"] += row["inputTokens"] or 0
284
- stats["totalOutputTokens"] += row["outputTokens"] or 0
285
-
286
- stats["years"] = sorted(years)
287
- return web.json_response(stats)
288
-
289
- ctx.add_get("requests/summary", requests_summary)
290
-
291
- async def daily_requests_summary(request):
292
- day = request.match_info["day"]
293
- summary = g_db.get_daily_request_summary(day, user=ctx.get_username(request))
294
- return web.json_response(summary)
295
-
296
- ctx.add_get("requests/summary/{day}", daily_requests_summary)
297
-
298
- async def chat_request(openai_request, context):
299
- chat = openai_request
300
- user = context.get("user", None)
301
- provider = context.get("provider", None)
302
- thread_id = context.get("threadId", None)
303
- model_info = context.get("modelInfo", None)
304
-
305
- metadata = chat.get("metadata", {})
306
- model = chat.get("model", None)
307
- messages = timestamp_messages(chat.get("messages", []))
308
- title = context.get("title") or prompt_to_title(ctx.last_user_prompt(chat) if chat else None)
309
- started_at = context.get("startedAt")
310
- if not started_at:
311
- context["startedAt"] = started_at = datetime.now()
312
- if thread_id is None:
313
- thread = {
314
- "user": user,
315
- "model": model,
316
- "provider": provider,
317
- "modelInfo": model_info,
318
- "title": title,
319
- "messages": messages,
320
- "systemPrompt": ctx.chat_to_system_prompt(chat),
321
- "modalities": chat.get("modalities", ["text"]),
322
- "startedAt": started_at,
323
- "metadata": metadata,
324
- }
325
- thread_id = await g_db.create_thread_async(thread, user=user)
326
- context["threadId"] = thread_id
327
- else:
328
- update_thread = {
329
- "model": model,
330
- "provider": provider,
331
- "modelInfo": model_info,
332
- "startedAt": started_at,
333
- "messages": messages,
334
- "completedAt": None,
335
- "error": None,
336
- "metadata": metadata,
337
- }
338
- await g_db.update_thread_async(thread_id, update_thread, user=user)
339
-
340
- completed_at = g_db.get_thread_column(thread_id, "completedAt", user=user)
341
- if completed_at:
342
- context["completed"] = True
343
-
344
- ctx.register_chat_request_filter(chat_request)
345
-
346
- async def tool_request(chat_request, context):
347
- messages = chat_request.get("messages", [])
348
- ctx.dbg(f"tool_request: messages {len(messages)}")
349
- thread_id = context.get("threadId", None)
350
- if not thread_id:
351
- ctx.dbg("Missing threadId")
352
- return
353
- user = context.get("user", None)
354
- await g_db.update_thread_async(
355
- thread_id,
356
- {
357
- "messages": messages,
358
- },
359
- user=user,
360
- )
361
-
362
- completed_at = g_db.get_thread_column(thread_id, "completedAt", user=user)
363
- if completed_at:
364
- context["completed"] = True
365
-
366
- ctx.register_chat_tool_filter(tool_request)
367
-
368
- async def chat_response(openai_response, context):
369
- ctx.dbg("create_response")
370
- o = openai_response
371
- chat = context.get("chat")
372
- usage = o.get("usage", None)
373
- if not usage and not chat:
374
- ctx.dbg("Missing chat and usage")
375
- return
376
-
377
- user = context.get("user", None)
378
- thread_id = context.get("threadId", None)
379
- provider = context.get("provider", None)
380
- model_info = context.get("modelInfo", None)
381
- model_cost = context.get("modelCost", model_info.get("cost", None)) or {"input": 0, "output": 0}
382
- duration = context.get("duration", 0)
383
-
384
- metadata = o.get("metadata", {})
385
- choices = o.get("choices", [])
386
- tasks = []
387
- title = context.get("title") or prompt_to_title(ctx.last_user_prompt(chat) if chat else None)
388
- completed_at = datetime.now()
389
-
390
- model = model_info.get("name") or model_info.get("id")
391
- finish_reason = choices[0].get("finish_reason", None) if len(choices) > 0 else None
392
- input_price = model_cost.get("input", 0)
393
- output_price = model_cost.get("output", 0)
394
- input_tokens = usage.get("prompt_tokens", 0)
395
- output_tokens = usage.get("completion_tokens", 0)
396
- total_tokens = usage.get("total_tokens", input_tokens + output_tokens)
397
- cost = o.get("cost", ((input_price * input_tokens) + (output_price * output_tokens)) / 1000000)
398
-
399
- request = {
400
- "user": user,
401
- "model": model,
402
- "duration": duration,
403
- "cost": cost,
404
- "inputPrice": input_price,
405
- "inputTokens": input_tokens,
406
- "inputCachedTokens": usage.get("inputCachedTokens", 0),
407
- "outputPrice": output_price,
408
- "outputTokens": output_tokens,
409
- "finishReason": finish_reason,
410
- "provider": provider,
411
- "providerModel": o.get("model", None),
412
- "providerRef": o.get("provider", None),
413
- "threadId": thread_id,
414
- "title": title,
415
- "startedAt": context.get("startedAt"),
416
- "totalTokens": total_tokens,
417
- "usage": usage,
418
- "completedAt": completed_at,
419
- "toolHistory": o.get("tool_history", None),
420
- "ref": o.get("id", None),
421
- }
422
- tasks.append(g_db.create_request_async(request, user=user))
423
-
424
- if thread_id:
425
- messages = chat.get("messages", [])
426
- last_role = messages[-1].get("role", None) if len(messages) > 0 else None
427
- if last_role == "user" or last_role == "tool":
428
- user_message = messages[-1]
429
- user_message["model"] = model
430
- user_message["usage"] = {
431
- "tokens": input_tokens,
432
- "price": input_price,
433
- "cost": (input_price * input_tokens) / 1000000,
434
- }
435
- else:
436
- ctx.dbg(
437
- f"Missing user message for thread {thread_id}, {len(messages)} messages, last role: {last_role}"
438
- )
439
- assistant_message = ctx.chat_response_to_message(o)
440
- assistant_message["model"] = model
441
- assistant_message["usage"] = {
442
- "tokens": output_tokens,
443
- "price": output_price,
444
- "cost": (output_price * output_tokens) / 1000000,
445
- "duration": duration,
446
- }
447
- messages.append(assistant_message)
448
-
449
- update_thread = {
450
- "model": model,
451
- "providerModel": o.get("model"),
452
- "modelInfo": model_info,
453
- "messages": messages,
454
- "completedAt": completed_at,
455
- }
456
- if "error" in metadata:
457
- update_thread["error"] = metadata["error"]
458
- tasks.append(g_db.update_thread_async(thread_id, update_thread, user=user))
459
- else:
460
- ctx.dbg("Missing thread_id")
461
-
462
- await asyncio.gather(*tasks)
463
-
464
- # Update thread costs from all thread requests
465
- thread_requests = g_db.query_requests({"threadId": thread_id}, user=user)
466
- total_costs = 0
467
- total_input = 0
468
- total_output = 0
469
- for request in thread_requests:
470
- total_costs += request.get("cost", 0) or 0
471
- total_input += request.get("inputTokens", 0) or 0
472
- total_output += request.get("outputTokens", 0) or 0
473
- stats = {
474
- "inputTokens": total_input,
475
- "outputTokens": total_output,
476
- "cost": total_costs,
477
- "duration": duration,
478
- "requests": len(thread_requests),
479
- }
480
- g_db.update_thread(
481
- thread_id,
482
- {
483
- "inputTokens": total_input,
484
- "outputTokens": total_output,
485
- "cost": total_costs,
486
- "stats": stats,
487
- },
488
- user=user,
489
- )
490
-
491
- ctx.register_chat_response_filter(chat_response)
492
-
493
- async def chat_error(e: Exception, context: Any):
494
- error = ctx.error_message(e)
495
- ctx.dbg(f"Chat error: {error}")
496
- chat = context.get("chat")
497
- if not chat:
498
- ctx.dbg("Missing chat")
499
- return
500
-
501
- title = context.get("title") or prompt_to_title(ctx.last_user_prompt(chat) if chat else None)
502
- completed_at = datetime.now()
503
- user = context.get("user", None)
504
-
505
- thread_id = context.get("threadId", None)
506
- tasks = []
507
- if thread_id:
508
- tasks.append(g_db.update_thread_async(thread_id, {"completedAt": completed_at, "error": error}, user=user))
509
- else:
510
- ctx.dbg("Missing threadId")
511
-
512
- request = {
513
- "user": user,
514
- "model": chat.get("model", None),
515
- "title": title,
516
- "threadId": thread_id,
517
- "startedAt": context.get("startedAt"),
518
- "completedAt": completed_at,
519
- "error": error,
520
- "stackTrace": context.get("stackTrace", None),
521
- }
522
- tasks.append(g_db.create_request_async(request, user=user))
523
-
524
- if len(tasks) > 0:
525
- await asyncio.gather(*tasks)
526
-
527
- ctx.register_chat_error_filter(chat_error)
528
-
529
-
530
- __install__ = install