llms-py 2.0.34__py3-none-any.whl → 3.0.0__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 (207) hide show
  1. llms/__init__.py +3 -1
  2. llms/__pycache__/__init__.cpython-312.pyc +0 -0
  3. llms/__pycache__/__init__.cpython-313.pyc +0 -0
  4. llms/__pycache__/__init__.cpython-314.pyc +0 -0
  5. llms/__pycache__/__main__.cpython-312.pyc +0 -0
  6. llms/__pycache__/__main__.cpython-314.pyc +0 -0
  7. llms/__pycache__/llms.cpython-312.pyc +0 -0
  8. llms/__pycache__/main.cpython-312.pyc +0 -0
  9. llms/__pycache__/main.cpython-313.pyc +0 -0
  10. llms/__pycache__/main.cpython-314.pyc +0 -0
  11. llms/__pycache__/plugins.cpython-314.pyc +0 -0
  12. llms/{ui/Analytics.mjs → extensions/analytics/ui/index.mjs} +154 -238
  13. llms/extensions/app/README.md +20 -0
  14. llms/extensions/app/__init__.py +530 -0
  15. llms/extensions/app/__pycache__/__init__.cpython-314.pyc +0 -0
  16. llms/extensions/app/__pycache__/db.cpython-314.pyc +0 -0
  17. llms/extensions/app/__pycache__/db_manager.cpython-314.pyc +0 -0
  18. llms/extensions/app/db.py +644 -0
  19. llms/extensions/app/db_manager.py +195 -0
  20. llms/extensions/app/requests.json +9073 -0
  21. llms/extensions/app/threads.json +15290 -0
  22. llms/{ui → extensions/app/ui}/Recents.mjs +91 -65
  23. llms/{ui/Sidebar.mjs → extensions/app/ui/index.mjs} +124 -58
  24. llms/extensions/app/ui/threadStore.mjs +411 -0
  25. llms/extensions/core_tools/CALCULATOR.md +32 -0
  26. llms/extensions/core_tools/__init__.py +598 -0
  27. llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
  28. llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +201 -0
  29. llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +185 -0
  30. llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +101 -0
  31. llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +160 -0
  32. llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +66 -0
  33. llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +27 -0
  34. llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +72 -0
  35. llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +119 -0
  36. llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +98 -0
  37. llms/extensions/core_tools/ui/codemirror/doc/docs.css +225 -0
  38. llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
  39. llms/extensions/core_tools/ui/codemirror/lib/codemirror.css +344 -0
  40. llms/extensions/core_tools/ui/codemirror/lib/codemirror.js +9884 -0
  41. llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +942 -0
  42. llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +118 -0
  43. llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +962 -0
  44. llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +62 -0
  45. llms/extensions/core_tools/ui/codemirror/mode/python/python.js +402 -0
  46. llms/extensions/core_tools/ui/codemirror/theme/dracula.css +40 -0
  47. llms/extensions/core_tools/ui/codemirror/theme/mocha.css +135 -0
  48. llms/extensions/core_tools/ui/index.mjs +650 -0
  49. llms/extensions/gallery/README.md +61 -0
  50. llms/extensions/gallery/__init__.py +61 -0
  51. llms/extensions/gallery/__pycache__/__init__.cpython-314.pyc +0 -0
  52. llms/extensions/gallery/__pycache__/db.cpython-314.pyc +0 -0
  53. llms/extensions/gallery/db.py +298 -0
  54. llms/extensions/gallery/ui/index.mjs +482 -0
  55. llms/extensions/katex/README.md +39 -0
  56. llms/extensions/katex/__init__.py +6 -0
  57. llms/extensions/katex/__pycache__/__init__.cpython-314.pyc +0 -0
  58. llms/extensions/katex/ui/README.md +125 -0
  59. llms/extensions/katex/ui/contrib/auto-render.js +338 -0
  60. llms/extensions/katex/ui/contrib/auto-render.min.js +1 -0
  61. llms/extensions/katex/ui/contrib/auto-render.mjs +244 -0
  62. llms/extensions/katex/ui/contrib/copy-tex.js +127 -0
  63. llms/extensions/katex/ui/contrib/copy-tex.min.js +1 -0
  64. llms/extensions/katex/ui/contrib/copy-tex.mjs +105 -0
  65. llms/extensions/katex/ui/contrib/mathtex-script-type.js +109 -0
  66. llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +1 -0
  67. llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +24 -0
  68. llms/extensions/katex/ui/contrib/mhchem.js +3213 -0
  69. llms/extensions/katex/ui/contrib/mhchem.min.js +1 -0
  70. llms/extensions/katex/ui/contrib/mhchem.mjs +3109 -0
  71. llms/extensions/katex/ui/contrib/render-a11y-string.js +887 -0
  72. llms/extensions/katex/ui/contrib/render-a11y-string.min.js +1 -0
  73. llms/extensions/katex/ui/contrib/render-a11y-string.mjs +800 -0
  74. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
  75. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
  76. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  77. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  78. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  79. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  80. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  81. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  82. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  83. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  84. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  85. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  86. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  87. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  88. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  89. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
  90. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
  91. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
  92. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  93. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  94. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  95. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
  96. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
  97. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
  98. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
  99. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
  100. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
  101. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  102. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  103. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  104. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
  105. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
  106. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
  107. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  108. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  109. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  110. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  111. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  112. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  113. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  114. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  115. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  116. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
  117. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
  118. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
  119. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
  120. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
  121. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  122. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
  123. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
  124. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  125. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
  126. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
  127. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  128. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
  129. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
  130. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  131. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  132. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  133. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  134. llms/extensions/katex/ui/index.mjs +92 -0
  135. llms/extensions/katex/ui/katex-swap.css +1230 -0
  136. llms/extensions/katex/ui/katex-swap.min.css +1 -0
  137. llms/extensions/katex/ui/katex.css +1230 -0
  138. llms/extensions/katex/ui/katex.js +19080 -0
  139. llms/extensions/katex/ui/katex.min.css +1 -0
  140. llms/extensions/katex/ui/katex.min.js +1 -0
  141. llms/extensions/katex/ui/katex.min.mjs +1 -0
  142. llms/extensions/katex/ui/katex.mjs +18547 -0
  143. llms/extensions/providers/__init__.py +18 -0
  144. llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  145. llms/extensions/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  146. llms/extensions/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  147. llms/extensions/providers/__pycache__/google.cpython-314.pyc +0 -0
  148. llms/extensions/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
  149. llms/extensions/providers/__pycache__/openai.cpython-314.pyc +0 -0
  150. llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  151. llms/extensions/providers/anthropic.py +229 -0
  152. llms/extensions/providers/chutes.py +155 -0
  153. llms/extensions/providers/google.py +378 -0
  154. llms/extensions/providers/nvidia.py +105 -0
  155. llms/extensions/providers/openai.py +156 -0
  156. llms/extensions/providers/openrouter.py +72 -0
  157. llms/extensions/system_prompts/README.md +22 -0
  158. llms/extensions/system_prompts/__init__.py +45 -0
  159. llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
  160. llms/extensions/system_prompts/ui/index.mjs +280 -0
  161. llms/extensions/system_prompts/ui/prompts.json +1067 -0
  162. llms/extensions/tools/__init__.py +5 -0
  163. llms/extensions/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  164. llms/extensions/tools/ui/index.mjs +204 -0
  165. llms/index.html +35 -77
  166. llms/llms.json +357 -1186
  167. llms/main.py +2847 -999
  168. llms/providers-extra.json +356 -0
  169. llms/providers.json +1 -0
  170. llms/ui/App.mjs +151 -60
  171. llms/ui/ai.mjs +132 -60
  172. llms/ui/app.css +2173 -161
  173. llms/ui/ctx.mjs +365 -0
  174. llms/ui/index.mjs +129 -0
  175. llms/ui/lib/charts.mjs +9 -13
  176. llms/ui/lib/servicestack-vue.mjs +3 -3
  177. llms/ui/lib/vue.min.mjs +10 -9
  178. llms/ui/lib/vue.mjs +1796 -1635
  179. llms/ui/markdown.mjs +18 -7
  180. llms/ui/modules/chat/ChatBody.mjs +691 -0
  181. llms/ui/{SettingsDialog.mjs → modules/chat/SettingsDialog.mjs} +9 -9
  182. llms/ui/modules/chat/index.mjs +828 -0
  183. llms/ui/modules/layout.mjs +243 -0
  184. llms/ui/modules/model-selector.mjs +851 -0
  185. llms/ui/tailwind.input.css +496 -80
  186. llms/ui/utils.mjs +161 -93
  187. {llms_py-2.0.34.dist-info → llms_py-3.0.0.dist-info}/METADATA +1 -1
  188. llms_py-3.0.0.dist-info/RECORD +202 -0
  189. llms/ui/Avatar.mjs +0 -85
  190. llms/ui/Brand.mjs +0 -52
  191. llms/ui/ChatPrompt.mjs +0 -590
  192. llms/ui/Main.mjs +0 -823
  193. llms/ui/ModelSelector.mjs +0 -78
  194. llms/ui/OAuthSignIn.mjs +0 -92
  195. llms/ui/ProviderIcon.mjs +0 -30
  196. llms/ui/ProviderStatus.mjs +0 -105
  197. llms/ui/SignIn.mjs +0 -64
  198. llms/ui/SystemPromptEditor.mjs +0 -31
  199. llms/ui/SystemPromptSelector.mjs +0 -56
  200. llms/ui/Welcome.mjs +0 -8
  201. llms/ui/threadStore.mjs +0 -563
  202. llms/ui.json +0 -1069
  203. llms_py-2.0.34.dist-info/RECORD +0 -48
  204. {llms_py-2.0.34.dist-info → llms_py-3.0.0.dist-info}/WHEEL +0 -0
  205. {llms_py-2.0.34.dist-info → llms_py-3.0.0.dist-info}/entry_points.txt +0 -0
  206. {llms_py-2.0.34.dist-info → llms_py-3.0.0.dist-info}/licenses/LICENSE +0 -0
  207. {llms_py-2.0.34.dist-info → llms_py-3.0.0.dist-info}/top_level.txt +0 -0
llms/ui/ctx.mjs ADDED
@@ -0,0 +1,365 @@
1
+
2
+ import { reactive, markRaw } from 'vue'
3
+ import { EventBus, humanize, combinePaths } from "@servicestack/client"
4
+ import { storageObject } from './utils.mjs'
5
+
6
+ export class ExtensionScope {
7
+ constructor(ctx, id) {
8
+ /**@type {AppContext} */
9
+ this.ctx = ctx
10
+ this.id = id
11
+ this.baseUrl = `${ctx.ai.base}/ext/${this.id}`
12
+ this.storageKey = `llms.${this.id}`
13
+ this.state = reactive({})
14
+ this.prefs = reactive(storageObject(this.storageKey))
15
+ }
16
+ getPrefs() {
17
+ return this.prefs
18
+ }
19
+ setPrefs(o) {
20
+ storageObject(this.storageKey, Object.assign(this.prefs, o))
21
+ }
22
+ savePrefs() {
23
+ storageObject(this.storageKey, this.prefs)
24
+ }
25
+ setState(o) {
26
+ Object.assign(this.state, o)
27
+ }
28
+ get(url, options) {
29
+ return this.ctx.ai.get(combinePaths(this.baseUrl, url), options)
30
+ }
31
+ delete(url, options) {
32
+ return this.ctx.ai.get(combinePaths(this.baseUrl, url), {
33
+ ...options,
34
+ method: 'DELETE'
35
+ })
36
+ }
37
+ async getJson(url, options) {
38
+ return this.ctx.ai.getJson(combinePaths(this.baseUrl, url), options)
39
+ }
40
+ async deleteJson(url, options) {
41
+ return this.ctx.ai.getJson(combinePaths(this.baseUrl, url), {
42
+ ...options,
43
+ method: 'DELETE'
44
+ })
45
+ }
46
+ post(url, options) {
47
+ return this.ctx.ai.post(combinePaths(this.baseUrl, url), options)
48
+ }
49
+ put(url, options) {
50
+ return this.ctx.ai.post(combinePaths(this.baseUrl, url), {
51
+ ...options,
52
+ method: 'PUT'
53
+ })
54
+ }
55
+ patch(url, options) {
56
+ return this.ctx.ai.post(combinePaths(this.baseUrl, url), {
57
+ ...options,
58
+ method: 'PATCH'
59
+ })
60
+ }
61
+ async postForm(url, options) {
62
+ return await this.ctx.ai.postForm(combinePaths(this.baseUrl, url), options)
63
+ }
64
+ async postJson(url, body) {
65
+ return this.ctx.ai.postJson(combinePaths(this.baseUrl, url), {
66
+ body: body instanceof FormData ? body : JSON.stringify(body)
67
+ })
68
+ }
69
+ async putJson(url, body) {
70
+ return this.ctx.ai.postJson(combinePaths(this.baseUrl, url), {
71
+ method: 'PUT',
72
+ body: body instanceof FormData ? body : JSON.stringify(body)
73
+ })
74
+ }
75
+ async patchJson(url, body) {
76
+ return this.ctx.ai.postJson(combinePaths(this.baseUrl, url), {
77
+ method: 'PATCH',
78
+ body: body instanceof FormData ? body : JSON.stringify(body)
79
+ })
80
+ }
81
+ async createJsonResult(res) {
82
+ return this.ctx.ai.createJsonResult(res)
83
+ }
84
+ createErrorStatus(status) {
85
+ return this.ctx.ai.createErrorStatus(status)
86
+ }
87
+ createErrorResult(e) {
88
+ return this.ctx.ai.createErrorResult(e)
89
+ }
90
+ setError(e, msg = null) {
91
+ const prefix = this.id ? `[${this.id}] ` : ''
92
+ this.ctx.setError(e, msg ? `${prefix} ${msg}` : prefix)
93
+ }
94
+ clearError() {
95
+ this.ctx.clearError()
96
+ }
97
+ toast(msg) {
98
+ this.ctx.toast(msg)
99
+ }
100
+ }
101
+
102
+ export class AppContext {
103
+ constructor({ app, routes, ai, fmt, utils, marked }) {
104
+ this.app = app
105
+ this.routes = routes
106
+ this.ai = ai
107
+ this.fmt = fmt
108
+ this.utils = utils
109
+ this._components = {}
110
+ this.marked = marked
111
+
112
+ this.state = reactive({})
113
+ this.events = new EventBus()
114
+ this.modalComponents = {}
115
+ this.extensions = []
116
+ this.markedFilters = []
117
+ this.chatRequestFilters = []
118
+ this.chatResponseFilters = []
119
+ this.chatErrorFilters = []
120
+ this.createThreadFilters = []
121
+ this.updateThreadFilters = []
122
+ this.top = {}
123
+ this.left = {}
124
+ this.layout = reactive(storageObject(`llms.layout`))
125
+ this.prefs = reactive(storageObject(ai.prefsKey))
126
+ this._onRouterBeforeEach = []
127
+ this._onClass = []
128
+
129
+ if (!Array.isArray(this.layout.hide)) {
130
+ this.layout.hide = []
131
+ }
132
+ Object.assign(app.config.globalProperties, {
133
+ $ctx: this,
134
+ $prefs: this.prefs,
135
+ $state: this.state,
136
+ $layout: this.layout,
137
+ $ai: ai,
138
+ $fmt: fmt,
139
+ $utils: utils,
140
+ })
141
+ Object.keys(app.config.globalProperties).forEach(key => {
142
+ globalThis[key] = app.config.globalProperties[key]
143
+ })
144
+ document.addEventListener('keydown', (e) => this.handleKeydown(e))
145
+ }
146
+ async init() {
147
+ Object.assign(this.state, await this.ai.init(this))
148
+ Object.assign(this.fmt, {
149
+ markdown: this.renderMarkdown.bind(this)
150
+ })
151
+ }
152
+ setGlobals(globals) {
153
+ Object.entries(globals).forEach(([name, global]) => {
154
+ const globalName = '$' + name
155
+ globalThis[globalName] = this.app.config.globalProperties[globalName] = global
156
+ this[name] = global
157
+ })
158
+ }
159
+ getPrefs() {
160
+ return this.prefs
161
+ }
162
+ setPrefs(o) {
163
+ storageObject(this.ai.prefsKey, Object.assign(this.prefs, o))
164
+ }
165
+ _validateIcons(icons) {
166
+ Object.entries(icons).forEach(([id, icon]) => {
167
+ if (!icon.component) {
168
+ console.error(`Icon ${id} is missing component property`)
169
+ }
170
+ icon.id = id
171
+ if (!icon.name) {
172
+ icon.name = humanize(id)
173
+ }
174
+ if (typeof icon.isActive != 'function') {
175
+ icon.isActive = () => false
176
+ }
177
+ })
178
+ return icons
179
+ }
180
+ setTopIcons(icons) {
181
+ Object.assign(this.top, this._validateIcons(icons))
182
+ }
183
+ setLeftIcons(icons) {
184
+ Object.assign(this.left, this._validateIcons(icons))
185
+ }
186
+ component(name, component) {
187
+ if (!name) return name
188
+ if (component) {
189
+ this._components[name] = component
190
+ }
191
+ return component || this._components[name] || this.app.component(name)
192
+ }
193
+ components(components) {
194
+ if (components) {
195
+ Object.keys(components).forEach(name => {
196
+ this._components[name] = components[name]
197
+ })
198
+ }
199
+ return this._components
200
+ }
201
+ scope(extension) {
202
+ return new ExtensionScope(this, extension)
203
+ }
204
+ modals(modals) {
205
+ Object.keys(modals).forEach(name => {
206
+ const modal = markRaw(modals[name])
207
+ this.modalComponents[name] = modal
208
+ this.component(name, modal)
209
+ })
210
+ }
211
+ openModal(name) {
212
+ const component = this.modalComponents[name]
213
+ if (!component) {
214
+ console.error(`Modal ${name} not found`)
215
+ return
216
+ }
217
+ console.debug('openModal', name)
218
+ this.router.push({ query: { open: name } })
219
+ this.events.publish('modal:open', name)
220
+ return component
221
+ }
222
+ closeModal(name) {
223
+ console.debug('closeModal', name)
224
+ this.router.push({ query: { open: undefined } })
225
+ this.events.publish('modal:close', name)
226
+ }
227
+ handleKeydown(e) {
228
+ if (e.key === 'Escape') {
229
+ const modal = this.router.currentRoute.value?.query?.open
230
+ if (modal) {
231
+ this.closeModal(modal)
232
+ }
233
+ this.events.publish(`keydown:Escape`, e)
234
+ }
235
+ }
236
+ setState(o) {
237
+ Object.assign(this.state, o)
238
+ }
239
+ setLayout(o) {
240
+ Object.assign(this.layout, o)
241
+ storageObject(`llms.layout`, this.layout)
242
+ }
243
+ toggleLayout(key, toggle = undefined) {
244
+ const hide = toggle == undefined
245
+ ? !this.layout.hide.includes(key)
246
+ : !toggle
247
+ console.log('toggleLayout', key, hide)
248
+ if (hide) {
249
+ this.layout.hide.push(key)
250
+ } else {
251
+ this.layout.hide = this.layout.hide.filter(k => k != key)
252
+ }
253
+ storageObject(`llms.layout`, this.layout)
254
+ }
255
+ layoutVisible(key) {
256
+ return !this.layout.hide.includes(key)
257
+ }
258
+ toggleTop(name, toggle) {
259
+ if (toggle === false) {
260
+ this.layout.top = undefined
261
+ } else if (toggle === true) {
262
+ this.layout.top = name
263
+ } else {
264
+ this.layout.top = this.layout.top == name ? undefined : name
265
+ }
266
+ storageObject(`llms.layout`, this.layout)
267
+ console.log('toggleTop', name, toggle, this.layout.top, this.layout.top === name)
268
+ return this.layout.top === name
269
+ }
270
+ togglePath(path, toggle) {
271
+ const currentPath = this.router.currentRoute.value?.path
272
+ console.log('togglePath', path, currentPath, toggle)
273
+ if (currentPath != path) {
274
+ if (toggle === undefined) {
275
+ toggle = true
276
+ }
277
+ this.router.push({ path })
278
+ }
279
+ this.toggleLayout('left', toggle)
280
+ return toggle
281
+ }
282
+
283
+ createErrorStatus(status) {
284
+ return this.ai.createErrorStatus(status)
285
+ }
286
+ createErrorResult(e) {
287
+ return this.ai.createErrorResult(e)
288
+ }
289
+ setError(error, msg = null) {
290
+ this.state.error = error
291
+ if (error) {
292
+ if (msg) {
293
+ console.error(error.message, msg, error)
294
+ } else {
295
+ console.error(error.message, error)
296
+ }
297
+ }
298
+ }
299
+ clearError() {
300
+ this.state.error = null
301
+ }
302
+
303
+ async getJson(url, options) {
304
+ return await this.ai.getJson(url, options)
305
+ }
306
+ async post(url, options) {
307
+ return await this.ai.post(url, options)
308
+ }
309
+ async postForm(url, options) {
310
+ return await this.ai.postForm(url, options)
311
+ }
312
+ async postJson(url, options) {
313
+ return await this.ai.postJson(url, options)
314
+ }
315
+ to(route) {
316
+ if (typeof route == 'string') {
317
+ route = route.startsWith(this.ai.base)
318
+ ? route
319
+ : combinePaths(this.ai.base, route)
320
+ const path = { path: route }
321
+ console.log('to', path)
322
+ this.router.push(path)
323
+ } else {
324
+ route.path = route.path.startsWith(this.ai.base)
325
+ ? route.path
326
+ : combinePaths(this.ai.base, route.path)
327
+ console.log('to', route)
328
+ this.router.push(route)
329
+ }
330
+ }
331
+
332
+ // Events
333
+ onRouterBeforeEach(callback) {
334
+ this._onRouterBeforeEach.push(callback)
335
+ }
336
+
337
+ onClass(callback) {
338
+ this._onClass.push(callback)
339
+ }
340
+
341
+ cls(id, cls) {
342
+ if (this._onClass.length) {
343
+ this._onClass.forEach(callback => {
344
+ cls = callback(id, cls) ?? cls
345
+ })
346
+ }
347
+ return cls
348
+ }
349
+ toast(msg) {
350
+ this.setState({ toast: msg })
351
+ }
352
+
353
+ renderMarkdown(content) {
354
+ if (Array.isArray(content)) {
355
+ content = content.filter(c => c.type === 'text').map(c => c.text).join('\n')
356
+ }
357
+ // Handled by katex
358
+ // if (content) {
359
+ // content = content
360
+ // .replaceAll(`\\[ \\boxed{`, '\n<span class="inline-block text-xl text-blue-500 bg-blue-50 dark:text-blue-400 dark:bg-blue-950 px-3 py-1 rounded">')
361
+ // .replaceAll('} \\]', '</span>\n')
362
+ // }
363
+ return this.marked.parse(content || '')
364
+ }
365
+ }
llms/ui/index.mjs ADDED
@@ -0,0 +1,129 @@
1
+
2
+ import { createApp } from 'vue'
3
+ import { createWebHistory, createRouter } from "vue-router"
4
+ import ServiceStackVue, { useFormatters } from "@servicestack/vue"
5
+ import App from './App.mjs'
6
+ import ai from './ai.mjs'
7
+ import LayoutModule from './modules/layout.mjs'
8
+ import ChatModule from './modules/chat/index.mjs'
9
+ import ModelSelectorModule from './modules/model-selector.mjs'
10
+ import { utilsFunctions, utilsFormatters } from './utils.mjs'
11
+ import { marked, markdownFormatters } from './markdown.mjs'
12
+ import { AppContext } from './ctx.mjs'
13
+
14
+ const Components = {
15
+ }
16
+
17
+ const BuiltInModules = {
18
+ LayoutModule,
19
+ ChatModule,
20
+ ModelSelectorModule,
21
+ }
22
+
23
+
24
+ export async function createContext() {
25
+ const app = createApp(App)
26
+
27
+ app.use(ServiceStackVue)
28
+ Object.keys(Components).forEach(name => {
29
+ app.component(name, Components[name])
30
+ })
31
+
32
+ const fmt = Object.assign({}, useFormatters(), utilsFormatters())
33
+ const utils = Object.assign({}, utilsFunctions())
34
+ const routes = []
35
+
36
+ const ctx = new AppContext({ app, routes, ai, fmt, utils, marked })
37
+ app.provide('ctx', ctx)
38
+ await ctx.init()
39
+
40
+ // Load modules in parallel
41
+ const validExtensions = ctx.state.extensions.filter(x => x.path);
42
+ ctx.modules = await Promise.all(validExtensions.map(async extension => {
43
+ try {
44
+ const module = await import(extension.path)
45
+ const order = module.default.order || 0
46
+ return { extension, module, order }
47
+ } catch (e) {
48
+ console.error(`Failed to load extension module ${extension.name}:`, e)
49
+ return null
50
+ }
51
+ }))
52
+
53
+ // sort modules by order
54
+ ctx.modules.sort((a, b) => a.order - b.order)
55
+
56
+ const installedModules = []
57
+
58
+ // Install built-in modules sequentially
59
+ Object.entries(BuiltInModules).forEach(([name, module]) => {
60
+ try {
61
+ module.install(ctx)
62
+ installedModules.push({ extension: { id: name }, module: { default: module } })
63
+ console.log(`Installed built-in: ${name}`)
64
+ } catch (e) {
65
+ console.error(`Failed to install built-in ${name}:`, e)
66
+ }
67
+ })
68
+
69
+ // Install extensions sequentially
70
+ for (const result of ctx.modules) {
71
+ if (result && result.module.default && result.module.default.install) {
72
+ try {
73
+ result.module.default.install(ctx)
74
+ installedModules.push(result)
75
+ console.log(`Installed extension: ${result.extension.id}`)
76
+ } catch (e) {
77
+ console.error(`Failed to install extension ${result.extension.id}:`, e)
78
+ }
79
+ }
80
+ }
81
+
82
+ // Register all components with Vue
83
+ Object.entries(ctx._components).forEach(([name, component]) => {
84
+ app.component(name, component)
85
+ })
86
+
87
+ // Add fallback route and create router
88
+ routes.push({ path: '/:fallback(.*)*', component: ctx.component('Home') })
89
+ routes.forEach(r => r.path = ai.base + r.path)
90
+ ctx.router = createRouter({
91
+ history: createWebHistory(),
92
+ routes,
93
+ })
94
+ app.use(ctx.router)
95
+
96
+ ctx.router.beforeEach((to, from) => {
97
+ const title = to.meta.title || 'Chat'
98
+ console.debug('router:change', to.path, title)
99
+ ctx.setLayout({ path: to.path })
100
+ ctx.setState({ title })
101
+ document.title = title
102
+ return true
103
+ })
104
+ ctx._onRouterBeforeEach.forEach(ctx.router.beforeEach)
105
+
106
+ if (ai.hasAccess) {
107
+ if (ctx.layout.path && location.pathname === '/' && !location.search) {
108
+ console.log('redirecting to saved path: ', ctx.layout.path)
109
+ ctx.router.push({ path: ctx.layout.path })
110
+ }
111
+ } else {
112
+ ctx.router.push({ path: '/' })
113
+ }
114
+
115
+ const loadModules = installedModules.filter(x => x.module.default && x.module.default.load)
116
+ console.log('Loading modules: ', loadModules.map(x => x.extension.id))
117
+
118
+ // Load all extensions in parallel
119
+ await Promise.all(loadModules.map(async result => {
120
+ try {
121
+ await result.module.default.load(ctx)
122
+ console.log(`Loaded extension: ${result.extension.id}`)
123
+ } catch (e) {
124
+ console.error(`Failed to load extension ${result.extension.id}:`, e)
125
+ }
126
+ }))
127
+
128
+ return ctx
129
+ }
llms/ui/lib/charts.mjs CHANGED
@@ -1,20 +1,16 @@
1
- import { useFormatters, useUtils } from "@servicestack/vue"
2
1
  import { Chart, registerables } from "chart.js"
3
2
  Chart.register(...registerables)
4
3
 
5
- const { humanifyMs, humanifyNumber, formatDate } = useFormatters()
6
- const { delay } = useUtils()
7
-
8
- export const resultLimits = [5,10,25,50,100]
4
+ export const resultLimits = [5, 10, 25, 50, 100]
9
5
  export const colors = [
10
- { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' }, //blue
11
- { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
6
+ { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' }, //blue
7
+ { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
12
8
  { background: 'rgba(153, 102, 255, 0.2)', border: 'rgb(153, 102, 255)' },
13
- { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' },
14
- { background: 'rgba(255, 159, 64, 0.2)', border: 'rgb(255, 159, 64)' },
15
- { background: 'rgba(67, 56, 202, 0.2)', border: 'rgb(67, 56, 202)' },
16
- { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
17
- { background: 'rgba(14, 116, 144, 0.2)', border: 'rgb(14, 116, 144)' },
18
- { background: 'rgba(162, 28, 175, 0.2)', border: 'rgb(162, 28, 175)' },
9
+ { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' },
10
+ { background: 'rgba(255, 159, 64, 0.2)', border: 'rgb(255, 159, 64)' },
11
+ { background: 'rgba(67, 56, 202, 0.2)', border: 'rgb(67, 56, 202)' },
12
+ { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
13
+ { background: 'rgba(14, 116, 144, 0.2)', border: 'rgb(14, 116, 144)' },
14
+ { background: 'rgba(162, 28, 175, 0.2)', border: 'rgb(162, 28, 175)' },
19
15
  { background: 'rgba(201, 203, 207, 0.2)', border: 'rgb(201, 203, 207)' },
20
16
  ]