llms-py 3.0.0b2__py3-none-any.whl → 3.0.0b4__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.
- llms/__pycache__/main.cpython-314.pyc +0 -0
- llms/index.html +2 -1
- llms/llms.json +50 -17
- llms/main.py +484 -544
- llms/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
- llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
- llms/providers/__pycache__/google.cpython-314.pyc +0 -0
- llms/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
- llms/providers/__pycache__/openai.cpython-314.pyc +0 -0
- llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
- llms/providers/anthropic.py +189 -0
- llms/providers/chutes.py +152 -0
- llms/providers/google.py +306 -0
- llms/providers/nvidia.py +107 -0
- llms/providers/openai.py +159 -0
- llms/providers/openrouter.py +70 -0
- llms/providers-extra.json +356 -0
- llms/providers.json +1 -1
- llms/ui/App.mjs +132 -60
- llms/ui/ai.mjs +76 -10
- llms/ui/app.css +65 -28
- llms/ui/ctx.mjs +196 -0
- llms/ui/index.mjs +75 -171
- llms/ui/lib/charts.mjs +9 -13
- llms/ui/markdown.mjs +6 -0
- llms/ui/{Analytics.mjs → modules/analytics.mjs} +76 -64
- llms/ui/{Main.mjs → modules/chat/ChatBody.mjs} +59 -135
- llms/ui/{SettingsDialog.mjs → modules/chat/SettingsDialog.mjs} +8 -8
- llms/ui/{ChatPrompt.mjs → modules/chat/index.mjs} +242 -46
- llms/ui/modules/layout.mjs +267 -0
- llms/ui/modules/model-selector.mjs +851 -0
- llms/ui/{Recents.mjs → modules/threads/Recents.mjs} +0 -2
- llms/ui/{Sidebar.mjs → modules/threads/index.mjs} +46 -44
- llms/ui/{threadStore.mjs → modules/threads/threadStore.mjs} +10 -7
- llms/ui/utils.mjs +82 -123
- {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/METADATA +1 -1
- llms_py-3.0.0b4.dist-info/RECORD +65 -0
- llms/ui/Avatar.mjs +0 -86
- llms/ui/Brand.mjs +0 -52
- llms/ui/OAuthSignIn.mjs +0 -61
- llms/ui/ProviderIcon.mjs +0 -36
- llms/ui/ProviderStatus.mjs +0 -104
- llms/ui/SignIn.mjs +0 -65
- llms/ui/Welcome.mjs +0 -8
- llms/ui/model-selector.mjs +0 -686
- llms/ui.json +0 -1069
- llms_py-3.0.0b2.dist-info/RECORD +0 -58
- {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/WHEEL +0 -0
- {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/top_level.txt +0 -0
llms/ui/ctx.mjs
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
|
|
2
|
+
import { reactive } 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
|
+
}
|
|
15
|
+
getPrefs() {
|
|
16
|
+
return storageObject(this.storageKey)
|
|
17
|
+
}
|
|
18
|
+
setPrefs(o) {
|
|
19
|
+
storageObject(this.storageKey, Object.assign(this.getPrefs(), o))
|
|
20
|
+
}
|
|
21
|
+
get(url, options) {
|
|
22
|
+
return this.ctx.ai.get(combinePaths(this.baseUrl, url), options)
|
|
23
|
+
}
|
|
24
|
+
async getJson(url, options) {
|
|
25
|
+
return this.ctx.ai.getJson(combinePaths(this.baseUrl, url), options)
|
|
26
|
+
}
|
|
27
|
+
post(url, options) {
|
|
28
|
+
return this.ctx.ai.post(combinePaths(this.baseUrl, url), options)
|
|
29
|
+
}
|
|
30
|
+
async postJson(url, options) {
|
|
31
|
+
return this.ctx.ai.postJson(combinePaths(this.baseUrl, url), options)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class AppContext {
|
|
36
|
+
constructor({ app, routes, ai, fmt, utils }) {
|
|
37
|
+
this.app = app
|
|
38
|
+
this.routes = routes
|
|
39
|
+
this.ai = ai
|
|
40
|
+
this.fmt = fmt
|
|
41
|
+
this.utils = utils
|
|
42
|
+
this._components = {}
|
|
43
|
+
|
|
44
|
+
this.state = reactive({})
|
|
45
|
+
this.events = new EventBus()
|
|
46
|
+
this.modalComponents = {}
|
|
47
|
+
this.extensions = []
|
|
48
|
+
this.layout = reactive(storageObject(`llms.layout`))
|
|
49
|
+
this.chatRequestFilters = []
|
|
50
|
+
this.chatResponseFilters = []
|
|
51
|
+
this.chatErrorFilters = []
|
|
52
|
+
this.createThreadFilters = []
|
|
53
|
+
this.updateThreadFilters = []
|
|
54
|
+
this.top = {}
|
|
55
|
+
this.left = {}
|
|
56
|
+
|
|
57
|
+
if (!Array.isArray(this.layout.hide)) {
|
|
58
|
+
this.layout.hide = []
|
|
59
|
+
}
|
|
60
|
+
Object.assign(app.config.globalProperties, {
|
|
61
|
+
$ctx: this,
|
|
62
|
+
$state: this.state,
|
|
63
|
+
$layout: this.layout,
|
|
64
|
+
$ai: ai,
|
|
65
|
+
$fmt: fmt,
|
|
66
|
+
$utils: utils,
|
|
67
|
+
})
|
|
68
|
+
Object.keys(app.config.globalProperties).forEach(key => {
|
|
69
|
+
globalThis[key] = app.config.globalProperties[key]
|
|
70
|
+
})
|
|
71
|
+
document.addEventListener('keydown', (e) => this.handleKeydown(e))
|
|
72
|
+
}
|
|
73
|
+
async init() {
|
|
74
|
+
Object.assign(this.state, await this.ai.init(this))
|
|
75
|
+
}
|
|
76
|
+
setGlobals(globals) {
|
|
77
|
+
Object.entries(globals).forEach(([name, global]) => {
|
|
78
|
+
const globalName = '$' + name
|
|
79
|
+
globalThis[globalName] = this.app.config.globalProperties[globalName] = global
|
|
80
|
+
this[name] = global
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
_validateIcons(icons) {
|
|
84
|
+
Object.entries(icons).forEach(([id, icon]) => {
|
|
85
|
+
if (!icon.component) {
|
|
86
|
+
console.error(`Icon ${id} is missing component property`)
|
|
87
|
+
}
|
|
88
|
+
icon.id = id
|
|
89
|
+
if (!icon.name) {
|
|
90
|
+
icon.name = humanize(id)
|
|
91
|
+
}
|
|
92
|
+
if (typeof icon.isActive != 'function') {
|
|
93
|
+
icon.isActive = () => false
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
return icons
|
|
97
|
+
}
|
|
98
|
+
setTopIcons(icons) {
|
|
99
|
+
Object.assign(this.top, this._validateIcons(icons))
|
|
100
|
+
}
|
|
101
|
+
setLeftIcons(icons) {
|
|
102
|
+
Object.assign(this.left, this._validateIcons(icons))
|
|
103
|
+
}
|
|
104
|
+
component(name, component) {
|
|
105
|
+
if (!name) return name
|
|
106
|
+
if (component) {
|
|
107
|
+
this._components[name] = component
|
|
108
|
+
}
|
|
109
|
+
return component || this._components[name] || this.app.component(name)
|
|
110
|
+
}
|
|
111
|
+
components(components) {
|
|
112
|
+
if (components) {
|
|
113
|
+
Object.keys(components).forEach(name => {
|
|
114
|
+
this._components[name] = components[name]
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
return this._components
|
|
118
|
+
}
|
|
119
|
+
scope(extension) {
|
|
120
|
+
return new ExtensionScope(this, extension)
|
|
121
|
+
}
|
|
122
|
+
modals(modals) {
|
|
123
|
+
Object.keys(modals).forEach(name => {
|
|
124
|
+
this.modalComponents[name] = modals[name]
|
|
125
|
+
this.component(name, modals[name])
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
openModal(name) {
|
|
129
|
+
const component = this.modalComponents[name]
|
|
130
|
+
if (!component) {
|
|
131
|
+
console.error(`Modal ${name} not found`)
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
console.debug('openModal', name)
|
|
135
|
+
this.router.push({ query: { open: name } })
|
|
136
|
+
this.events.publish('modal:open', name)
|
|
137
|
+
return component
|
|
138
|
+
}
|
|
139
|
+
closeModal(name) {
|
|
140
|
+
console.debug('closeModal', name)
|
|
141
|
+
this.router.push({ query: { open: undefined } })
|
|
142
|
+
this.events.publish('modal:close', name)
|
|
143
|
+
}
|
|
144
|
+
handleKeydown(e) {
|
|
145
|
+
if (e.key === 'Escape') {
|
|
146
|
+
const modal = this.router.currentRoute.value?.query?.open
|
|
147
|
+
if (modal) {
|
|
148
|
+
this.closeModal(modal)
|
|
149
|
+
}
|
|
150
|
+
this.events.publish(`keydown:Escape`, e)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
setState(o) {
|
|
154
|
+
Object.assign(this.state, o)
|
|
155
|
+
//this.events.publish('update:state', this.state)
|
|
156
|
+
}
|
|
157
|
+
setLayout(o) {
|
|
158
|
+
Object.assign(this.layout, o)
|
|
159
|
+
storageObject(`llms.layout`, this.layout)
|
|
160
|
+
}
|
|
161
|
+
toggleLayout(key, toggle = undefined) {
|
|
162
|
+
const hide = toggle == undefined
|
|
163
|
+
? !this.layout.hide.includes(key)
|
|
164
|
+
: !toggle
|
|
165
|
+
console.log('toggleLayout', key, hide)
|
|
166
|
+
if (hide) {
|
|
167
|
+
this.layout.hide.push(key)
|
|
168
|
+
} else {
|
|
169
|
+
this.layout.hide = this.layout.hide.filter(k => k != key)
|
|
170
|
+
}
|
|
171
|
+
storageObject(`llms.layout`, this.layout)
|
|
172
|
+
}
|
|
173
|
+
layoutVisible(key) {
|
|
174
|
+
return !this.layout.hide.includes(key)
|
|
175
|
+
}
|
|
176
|
+
getPrefs() {
|
|
177
|
+
return storageObject(this.ai.prefsKey)
|
|
178
|
+
}
|
|
179
|
+
setPrefs(o) {
|
|
180
|
+
storageObject(this.ai.prefsKey, Object.assign(this.getPrefs(), o))
|
|
181
|
+
}
|
|
182
|
+
toggleTop(name) {
|
|
183
|
+
console.log('toggleTop', name)
|
|
184
|
+
this.layout.top = this.layout.top == name ? undefined : name
|
|
185
|
+
storageObject(`llms.layout`, this.layout)
|
|
186
|
+
}
|
|
187
|
+
togglePath(path) {
|
|
188
|
+
const currentPath = this.router.currentRoute.value?.path
|
|
189
|
+
console.log('togglePath', path, currentPath)
|
|
190
|
+
if (currentPath == path) {
|
|
191
|
+
this.toggleLayout('left')
|
|
192
|
+
} else {
|
|
193
|
+
this.router.push({ path })
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
llms/ui/index.mjs
CHANGED
|
@@ -1,176 +1,49 @@
|
|
|
1
1
|
|
|
2
|
-
import { createApp
|
|
2
|
+
import { createApp } from 'vue'
|
|
3
3
|
import { createWebHistory, createRouter } from "vue-router"
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const RecentsComponent = defineAsyncComponent(() => import(ai.base + '/ui/Recents.mjs'))
|
|
16
|
-
const AnalyticsComponent = defineAsyncComponent(() => import(ai.base + '/ui/Analytics.mjs'))
|
|
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 ThreadsModule from './modules/threads/index.mjs'
|
|
10
|
+
import ModelSelectorModule from './modules/model-selector.mjs'
|
|
11
|
+
import AnalyticsModule from './modules/analytics.mjs'
|
|
12
|
+
import { utilsFunctions, utilsFormatters } from './utils.mjs'
|
|
13
|
+
import { markdownFormatters } from './markdown.mjs'
|
|
14
|
+
import { AppContext } from './ctx.mjs'
|
|
17
15
|
|
|
18
16
|
const Components = {
|
|
19
|
-
SettingsDialog,
|
|
20
17
|
}
|
|
21
18
|
|
|
22
|
-
const BuiltInModules =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{ path: '/', component: MainComponent },
|
|
29
|
-
{ path: '/c/:id', component: MainComponent },
|
|
30
|
-
{ path: '/recents', component: RecentsComponent },
|
|
31
|
-
{ path: '/analytics', component: AnalyticsComponent },
|
|
32
|
-
{ path: '/:fallback(.*)*', component: MainComponent }
|
|
33
|
-
]
|
|
34
|
-
routes.forEach(r => r.path = ai.base + r.path)
|
|
35
|
-
const router = createRouter({
|
|
36
|
-
history: createWebHistory(),
|
|
37
|
-
routes,
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class AppExtension {
|
|
42
|
-
constructor(ctx, ext) {
|
|
43
|
-
this.ctx = ctx
|
|
44
|
-
Object.assign(this, ext)
|
|
45
|
-
this.baseUrl = `${ctx.ai.base}/ext/${this.id}`
|
|
46
|
-
this.storageKey = `llms.${this.id}`
|
|
47
|
-
if (!this.name) {
|
|
48
|
-
this.name = humanize(this.id)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
storageObject(o) {
|
|
52
|
-
return storageObject(this.storageKey, o)
|
|
53
|
-
}
|
|
19
|
+
const BuiltInModules = {
|
|
20
|
+
LayoutModule,
|
|
21
|
+
ChatModule,
|
|
22
|
+
ThreadsModule,
|
|
23
|
+
ModelSelectorModule,
|
|
24
|
+
AnalyticsModule,
|
|
54
25
|
}
|
|
55
26
|
|
|
56
|
-
class AppContext {
|
|
57
|
-
constructor({ app, config, models, extensions, routes, ai, router, threadStore, modules }) {
|
|
58
|
-
this.app = app
|
|
59
|
-
this.state = reactive({
|
|
60
|
-
config,
|
|
61
|
-
models,
|
|
62
|
-
extensions,
|
|
63
|
-
})
|
|
64
|
-
this.routes = routes
|
|
65
|
-
this.ai = ai
|
|
66
|
-
this.router = router
|
|
67
|
-
this.threadStore = threadStore
|
|
68
|
-
this.modules = modules
|
|
69
|
-
this.events = new EventBus()
|
|
70
|
-
this.modalComponents = {}
|
|
71
|
-
this.extensions = []
|
|
72
|
-
this.layout = reactive(storageObject(`llms.layout`))
|
|
73
|
-
this.chatRequestFilters = []
|
|
74
|
-
this.chatResponseFilters = []
|
|
75
|
-
this.chatErrorFilters = []
|
|
76
|
-
this.createThreadFilters = []
|
|
77
|
-
this.updateThreadFilters = []
|
|
78
|
-
|
|
79
|
-
app.config.globalProperties.$ctx = this
|
|
80
|
-
app.config.globalProperties.$state = this.state
|
|
81
|
-
app.config.globalProperties.$layout = this.layout
|
|
82
|
-
document.addEventListener('keydown', (e) => this.handleKeydown(e))
|
|
83
|
-
}
|
|
84
|
-
component(name, component) {
|
|
85
|
-
if (!name) return name
|
|
86
|
-
if (component) {
|
|
87
|
-
this.app.component(name, component)
|
|
88
|
-
}
|
|
89
|
-
return component || this.app.component(name)
|
|
90
|
-
}
|
|
91
|
-
components(components) {
|
|
92
|
-
Object.keys(components).forEach(name => {
|
|
93
|
-
this.app.component(name, components[name])
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
extension(extension) {
|
|
97
|
-
const ext = new AppExtension(this, extension)
|
|
98
|
-
this.extensions.push(ext)
|
|
99
|
-
return ext
|
|
100
|
-
}
|
|
101
|
-
modals(modals) {
|
|
102
|
-
Object.keys(modals).forEach(name => {
|
|
103
|
-
this.modalComponents[name] = modals[name]
|
|
104
|
-
this.component(name, modals[name])
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
openModal(name) {
|
|
108
|
-
const component = this.modalComponents[name]
|
|
109
|
-
if (!component) {
|
|
110
|
-
console.error(`Modal ${name} not found`)
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
console.debug('openModal', name)
|
|
114
|
-
this.router.push({ query: { open: name } })
|
|
115
|
-
this.events.publish('modal:open', name)
|
|
116
|
-
return component
|
|
117
|
-
}
|
|
118
|
-
closeModal(name) {
|
|
119
|
-
console.debug('closeModal', name)
|
|
120
|
-
this.router.push({ query: { open: undefined } })
|
|
121
|
-
this.events.publish('modal:close', name)
|
|
122
|
-
}
|
|
123
|
-
handleKeydown(e) {
|
|
124
|
-
if (e.key === 'Escape') {
|
|
125
|
-
const modal = this.router.currentRoute.value?.query?.open
|
|
126
|
-
if (modal) {
|
|
127
|
-
this.closeModal(modal)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
setState(o) {
|
|
132
|
-
Object.assign(this.state, o)
|
|
133
|
-
//this.events.publish('update:state', this.state)
|
|
134
|
-
}
|
|
135
|
-
setLayout(o) {
|
|
136
|
-
Object.assign(this.layout, o)
|
|
137
|
-
storageObject(`llms.layout`, this.layout)
|
|
138
|
-
}
|
|
139
|
-
getPrefs() {
|
|
140
|
-
return storageObject(this.ai.prefsKey)
|
|
141
|
-
}
|
|
142
|
-
setPrefs(o) {
|
|
143
|
-
storageObject(this.ai.prefsKey, o)
|
|
144
|
-
}
|
|
145
|
-
toggleLayout(o) {
|
|
146
|
-
Object.keys(o).forEach(key => {
|
|
147
|
-
this.layout[key] = this.layout[key] == o[key] ? undefined : o[key]
|
|
148
|
-
})
|
|
149
|
-
storageObject(`llms.layout`, this.layout)
|
|
150
|
-
}
|
|
151
|
-
getCurrentThread() {
|
|
152
|
-
return this.threadStore.currentThread.value
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
27
|
|
|
156
28
|
export async function createContext() {
|
|
157
|
-
const app = createApp(App
|
|
29
|
+
const app = createApp(App)
|
|
158
30
|
|
|
159
|
-
app.use(router)
|
|
160
31
|
app.use(ServiceStackVue)
|
|
161
32
|
Object.keys(Components).forEach(name => {
|
|
162
33
|
app.component(name, Components[name])
|
|
163
34
|
})
|
|
164
35
|
|
|
36
|
+
const fmt = Object.assign({}, useFormatters(), utilsFormatters(), markdownFormatters())
|
|
37
|
+
const utils = Object.assign({}, utilsFunctions())
|
|
38
|
+
const routes = []
|
|
165
39
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const exts = await (await fetch("/ext")).json()
|
|
40
|
+
const ctx = new AppContext({ app, routes, ai, fmt, utils })
|
|
41
|
+
app.provide('ctx', ctx)
|
|
42
|
+
await ctx.init()
|
|
170
43
|
|
|
171
44
|
// Load modules in parallel
|
|
172
|
-
const validExtensions =
|
|
173
|
-
|
|
45
|
+
const validExtensions = ctx.state.extensions.filter(x => x.path);
|
|
46
|
+
ctx.modules = await Promise.all(validExtensions.map(async extension => {
|
|
174
47
|
try {
|
|
175
48
|
const module = await import(extension.path)
|
|
176
49
|
return { extension, module }
|
|
@@ -180,25 +53,18 @@ export async function createContext() {
|
|
|
180
53
|
}
|
|
181
54
|
}))
|
|
182
55
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
router,
|
|
192
|
-
threadStore,
|
|
193
|
-
exts,
|
|
194
|
-
modules,
|
|
56
|
+
// Install built-in modules sequentially
|
|
57
|
+
Object.entries(BuiltInModules).forEach(([name, module]) => {
|
|
58
|
+
try {
|
|
59
|
+
module.install(ctx)
|
|
60
|
+
console.log(`Installed built-in: ${name}`)
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error(`Failed to install built-in ${name}:`, e)
|
|
63
|
+
}
|
|
195
64
|
})
|
|
196
|
-
app.provide('ctx', ctx)
|
|
197
|
-
|
|
198
|
-
BuiltInModules.forEach(ext => ext.install(ctx))
|
|
199
65
|
|
|
200
|
-
// Install sequentially
|
|
201
|
-
for (const result of modules) {
|
|
66
|
+
// Install extensions sequentially
|
|
67
|
+
for (const result of ctx.modules) {
|
|
202
68
|
if (result && result.module.default && result.module.default.install) {
|
|
203
69
|
try {
|
|
204
70
|
result.module.default.install(ctx)
|
|
@@ -209,5 +75,43 @@ export async function createContext() {
|
|
|
209
75
|
}
|
|
210
76
|
}
|
|
211
77
|
|
|
78
|
+
// Register all components with Vue
|
|
79
|
+
Object.entries(ctx._components).forEach(([name, component]) => {
|
|
80
|
+
app.component(name, component)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// Add fallback route and create router
|
|
84
|
+
routes.push({ path: '/:fallback(.*)*', component: ctx.component('Home') })
|
|
85
|
+
routes.forEach(r => r.path = ai.base + r.path)
|
|
86
|
+
ctx.router = createRouter({
|
|
87
|
+
history: createWebHistory(),
|
|
88
|
+
routes,
|
|
89
|
+
})
|
|
90
|
+
app.use(ctx.router)
|
|
91
|
+
|
|
92
|
+
ctx.router.beforeEach((to, from) => {
|
|
93
|
+
const title = to.meta.title || 'Chat'
|
|
94
|
+
console.log('beforeEach', to.path, title)
|
|
95
|
+
ctx.setLayout({ path: to.path })
|
|
96
|
+
ctx.setState({ title })
|
|
97
|
+
document.title = title
|
|
98
|
+
return true
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
if (ctx.layout.path && location.pathname === '/' && !location.search) {
|
|
102
|
+
console.log('redirecting to saved path: ', ctx.layout.path)
|
|
103
|
+
ctx.router.push({ path: ctx.layout.path })
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Load all extensions in parallel
|
|
107
|
+
await Promise.all(ctx.modules.filter(x => x.module.default && x.module.default.load).map(async result => {
|
|
108
|
+
try {
|
|
109
|
+
await result.module.default.load(ctx)
|
|
110
|
+
console.log(`Loaded extension: ${result.extension.id}`)
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.error(`Failed to load extension ${result.extension.id}:`, e)
|
|
113
|
+
}
|
|
114
|
+
}))
|
|
115
|
+
|
|
212
116
|
return ctx
|
|
213
117
|
}
|
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
|
|
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)',
|
|
11
|
-
{ background: 'rgba(255, 99, 132, 0.2)',
|
|
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)',
|
|
14
|
-
{ background: 'rgba(255, 159, 64, 0.2)',
|
|
15
|
-
{ background: 'rgba(67, 56, 202, 0.2)',
|
|
16
|
-
{ background: 'rgba(255, 99, 132, 0.2)',
|
|
17
|
-
{ background: 'rgba(14, 116, 144, 0.2)',
|
|
18
|
-
{ background: 'rgba(162, 28, 175, 0.2)',
|
|
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
|
]
|