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.
- llms/__pycache__/main.cpython-314.pyc +0 -0
- llms/index.html +37 -26
- llms/llms.json +21 -70
- llms/main.py +731 -1426
- llms/providers.json +1 -1
- llms/{extensions/analytics/ui/index.mjs → ui/Analytics.mjs} +238 -154
- llms/ui/App.mjs +63 -133
- llms/ui/Avatar.mjs +86 -0
- llms/ui/Brand.mjs +52 -0
- llms/ui/ChatPrompt.mjs +597 -0
- llms/ui/Main.mjs +862 -0
- llms/ui/OAuthSignIn.mjs +61 -0
- llms/ui/ProviderIcon.mjs +36 -0
- llms/ui/ProviderStatus.mjs +104 -0
- llms/{extensions/app/ui → ui}/Recents.mjs +57 -82
- llms/ui/{modules/chat/SettingsDialog.mjs → SettingsDialog.mjs} +9 -9
- llms/{extensions/app/ui/index.mjs → ui/Sidebar.mjs} +57 -122
- llms/ui/SignIn.mjs +65 -0
- llms/ui/Welcome.mjs +8 -0
- llms/ui/ai.mjs +13 -117
- llms/ui/app.css +49 -1776
- llms/ui/index.mjs +171 -87
- llms/ui/lib/charts.mjs +13 -9
- llms/ui/lib/servicestack-vue.mjs +3 -3
- llms/ui/lib/vue.min.mjs +9 -10
- llms/ui/lib/vue.mjs +1602 -1763
- llms/ui/markdown.mjs +2 -10
- llms/ui/model-selector.mjs +686 -0
- llms/ui/tailwind.input.css +1 -55
- llms/ui/threadStore.mjs +583 -0
- llms/ui/utils.mjs +118 -113
- llms/ui.json +1069 -0
- {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/METADATA +1 -1
- llms_py-3.0.0b2.dist-info/RECORD +58 -0
- llms/extensions/app/README.md +0 -20
- llms/extensions/app/__init__.py +0 -530
- llms/extensions/app/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/app/__pycache__/db.cpython-314.pyc +0 -0
- llms/extensions/app/__pycache__/db_manager.cpython-314.pyc +0 -0
- llms/extensions/app/db.py +0 -644
- llms/extensions/app/db_manager.py +0 -195
- llms/extensions/app/requests.json +0 -9073
- llms/extensions/app/threads.json +0 -15290
- llms/extensions/app/ui/threadStore.mjs +0 -411
- llms/extensions/core_tools/CALCULATOR.md +0 -32
- llms/extensions/core_tools/__init__.py +0 -598
- llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +0 -201
- llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +0 -185
- llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +0 -101
- llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +0 -160
- llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +0 -66
- llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +0 -27
- llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +0 -72
- llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +0 -119
- llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +0 -98
- llms/extensions/core_tools/ui/codemirror/doc/docs.css +0 -225
- llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
- llms/extensions/core_tools/ui/codemirror/lib/codemirror.css +0 -344
- llms/extensions/core_tools/ui/codemirror/lib/codemirror.js +0 -9884
- llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +0 -942
- llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +0 -118
- llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +0 -962
- llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +0 -62
- llms/extensions/core_tools/ui/codemirror/mode/python/python.js +0 -402
- llms/extensions/core_tools/ui/codemirror/theme/dracula.css +0 -40
- llms/extensions/core_tools/ui/codemirror/theme/mocha.css +0 -135
- llms/extensions/core_tools/ui/index.mjs +0 -650
- llms/extensions/gallery/README.md +0 -61
- llms/extensions/gallery/__init__.py +0 -61
- llms/extensions/gallery/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/gallery/__pycache__/db.cpython-314.pyc +0 -0
- llms/extensions/gallery/db.py +0 -298
- llms/extensions/gallery/ui/index.mjs +0 -482
- llms/extensions/katex/README.md +0 -39
- llms/extensions/katex/__init__.py +0 -6
- llms/extensions/katex/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/katex/ui/README.md +0 -125
- llms/extensions/katex/ui/contrib/auto-render.js +0 -338
- llms/extensions/katex/ui/contrib/auto-render.min.js +0 -1
- llms/extensions/katex/ui/contrib/auto-render.mjs +0 -244
- llms/extensions/katex/ui/contrib/copy-tex.js +0 -127
- llms/extensions/katex/ui/contrib/copy-tex.min.js +0 -1
- llms/extensions/katex/ui/contrib/copy-tex.mjs +0 -105
- llms/extensions/katex/ui/contrib/mathtex-script-type.js +0 -109
- llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +0 -1
- llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +0 -24
- llms/extensions/katex/ui/contrib/mhchem.js +0 -3213
- llms/extensions/katex/ui/contrib/mhchem.min.js +0 -1
- llms/extensions/katex/ui/contrib/mhchem.mjs +0 -3109
- llms/extensions/katex/ui/contrib/render-a11y-string.js +0 -887
- llms/extensions/katex/ui/contrib/render-a11y-string.min.js +0 -1
- llms/extensions/katex/ui/contrib/render-a11y-string.mjs +0 -800
- llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- llms/extensions/katex/ui/index.mjs +0 -92
- llms/extensions/katex/ui/katex-swap.css +0 -1230
- llms/extensions/katex/ui/katex-swap.min.css +0 -1
- llms/extensions/katex/ui/katex.css +0 -1230
- llms/extensions/katex/ui/katex.js +0 -19080
- llms/extensions/katex/ui/katex.min.css +0 -1
- llms/extensions/katex/ui/katex.min.js +0 -1
- llms/extensions/katex/ui/katex.min.mjs +0 -1
- llms/extensions/katex/ui/katex.mjs +0 -18547
- llms/extensions/providers/__init__.py +0 -18
- llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/chutes.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/google.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/openai.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
- llms/extensions/providers/anthropic.py +0 -229
- llms/extensions/providers/chutes.py +0 -155
- llms/extensions/providers/google.py +0 -378
- llms/extensions/providers/nvidia.py +0 -105
- llms/extensions/providers/openai.py +0 -156
- llms/extensions/providers/openrouter.py +0 -72
- llms/extensions/system_prompts/README.md +0 -22
- llms/extensions/system_prompts/__init__.py +0 -45
- llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/system_prompts/ui/index.mjs +0 -280
- llms/extensions/system_prompts/ui/prompts.json +0 -1067
- llms/extensions/tools/__init__.py +0 -5
- llms/extensions/tools/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/tools/ui/index.mjs +0 -204
- llms/providers-extra.json +0 -356
- llms/ui/ctx.mjs +0 -365
- llms/ui/modules/chat/ChatBody.mjs +0 -691
- llms/ui/modules/chat/index.mjs +0 -828
- llms/ui/modules/layout.mjs +0 -243
- llms/ui/modules/model-selector.mjs +0 -851
- llms_py-3.0.0.dist-info/RECORD +0 -202
- {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/WHEEL +0 -0
- {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.0.dist-info → llms_py-3.0.0b2.dist-info}/top_level.txt +0 -0
llms/ui/App.mjs
CHANGED
|
@@ -1,119 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { inject, ref, watch, onMounted, onUnmounted } from "vue"
|
|
2
2
|
import { useRouter, useRoute } from "vue-router"
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
// Vertical Sidebar Icons
|
|
6
|
-
const LeftBar = {
|
|
7
|
-
template: `
|
|
8
|
-
<div class="select-none flex flex-col space-y-2 pt-2.5 px-1">
|
|
9
|
-
<div v-for="(icon, id) in $ctx.left" :key="id" class="relative flex items-center justify-center">
|
|
10
|
-
<component :is="icon.component"
|
|
11
|
-
class="size-7 p-1 cursor-pointer text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 rounded block"
|
|
12
|
-
:class="{ 'bg-gray-200 dark:bg-gray-700' : icon.isActive({ ...$layout }) }"
|
|
13
|
-
@mouseenter="tooltip = icon.id"
|
|
14
|
-
@mouseleave="tooltip = ''"
|
|
15
|
-
/>
|
|
16
|
-
<div v-if="tooltip === icon.id && !icon.isActive({ ...$layout })"
|
|
17
|
-
class="absolute left-full top-1/2 -translate-y-1/2 ml-2 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-800 rounded shadow-md z-50 whitespace-nowrap pointer-events-none" style="z-index: 60">
|
|
18
|
-
{{icon.title ?? icon.name}}
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
`,
|
|
23
|
-
setup() {
|
|
24
|
-
const tooltip = ref('')
|
|
25
|
-
return {
|
|
26
|
-
tooltip,
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const LeftPanel = {
|
|
32
|
-
template: `
|
|
33
|
-
<div v-if="component" class="flex flex-col h-full border-r border-gray-200 dark:border-gray-700">
|
|
34
|
-
<button type="button" class="absolute top-2 right-2 p-1 rounded-md text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 lg:hidden z-20">
|
|
35
|
-
<svg class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
|
36
|
-
</button>
|
|
37
|
-
<component :is="component" />
|
|
38
|
-
</div>
|
|
39
|
-
`,
|
|
40
|
-
setup() {
|
|
41
|
-
/**@type {AppContext} */
|
|
42
|
-
const ctx = inject('ctx')
|
|
43
|
-
const component = computed(() => ctx.component(ctx.layout.left))
|
|
44
|
-
return {
|
|
45
|
-
component,
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const TopBar = {
|
|
51
|
-
template: `
|
|
52
|
-
<div class="select-none flex space-x-1">
|
|
53
|
-
<div v-for="(icon, id) in $ctx.top" :key="id" class="relative flex items-center justify-center">
|
|
54
|
-
<component :is="icon.component"
|
|
55
|
-
class="size-7 p-1 cursor-pointer text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 block border border-transparent"
|
|
56
|
-
:class="{ 'bg-gray-100 dark:bg-gray-800 border-gray-300 dark:border-gray-600 rounded' : icon.isActive({ ...$layout }) }"
|
|
57
|
-
@mouseenter="tooltip = icon.id"
|
|
58
|
-
@mouseleave="tooltip = ''"
|
|
59
|
-
/>
|
|
60
|
-
<div v-if="tooltip === icon.id && !icon.isActive({ ...$layout })"
|
|
61
|
-
class="absolute top-full mt-2 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-800 rounded shadow-md z-50 whitespace-nowrap pointer-events-none"
|
|
62
|
-
:class="last2.includes(id) ? 'right-0' : 'left-1/2 -translate-x-1/2'">
|
|
63
|
-
{{icon.title ?? icon.name}}
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
`,
|
|
68
|
-
setup() {
|
|
69
|
-
const tooltip = ref('')
|
|
70
|
-
const last2 = ref(Object.keys($ctx.top).slice(-2))
|
|
71
|
-
return {
|
|
72
|
-
tooltip,
|
|
73
|
-
last2,
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const TopPanel = {
|
|
79
|
-
template: `
|
|
80
|
-
<component v-if="component" :is="component" class="mb-2" />
|
|
81
|
-
`,
|
|
82
|
-
setup() {
|
|
83
|
-
/**@type {AppContext} */
|
|
84
|
-
const ctx = inject('ctx')
|
|
85
|
-
const component = computed(() => ctx.component(ctx.layout.top))
|
|
86
|
-
return {
|
|
87
|
-
component,
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
3
|
+
import Sidebar from "./Sidebar.mjs"
|
|
91
4
|
|
|
92
5
|
export default {
|
|
93
6
|
components: {
|
|
94
|
-
|
|
95
|
-
LeftPanel,
|
|
96
|
-
TopBar,
|
|
97
|
-
TopPanel,
|
|
7
|
+
Sidebar,
|
|
98
8
|
},
|
|
99
|
-
|
|
9
|
+
props: ['config', 'models'],
|
|
10
|
+
setup(props) {
|
|
100
11
|
const router = useRouter()
|
|
101
12
|
const route = useRoute()
|
|
102
13
|
|
|
103
|
-
/**@type {AppContext} */
|
|
104
14
|
const ctx = inject('ctx')
|
|
105
15
|
const ai = ctx.ai
|
|
106
16
|
const isMobile = ref(false)
|
|
107
17
|
const modal = ref()
|
|
108
18
|
|
|
109
19
|
const checkMobile = () => {
|
|
110
|
-
|
|
111
|
-
isMobile.value = window.innerWidth <
|
|
20
|
+
const wasMobile = isMobile.value
|
|
21
|
+
isMobile.value = window.innerWidth < 1024 // lg breakpoint
|
|
112
22
|
|
|
113
|
-
//console.log('checkMobile', wasMobile, isMobile.value)
|
|
114
23
|
// Only auto-adjust sidebar state when transitioning between mobile/desktop
|
|
24
|
+
if (wasMobile !== isMobile.value) {
|
|
25
|
+
if (isMobile.value) {
|
|
26
|
+
ai.isSidebarOpen = false
|
|
27
|
+
} else {
|
|
28
|
+
ai.isSidebarOpen = true
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const toggleSidebar = () => {
|
|
34
|
+
ai.isSidebarOpen = !ai.isSidebarOpen
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const closeSidebar = () => {
|
|
115
38
|
if (isMobile.value) {
|
|
116
|
-
|
|
39
|
+
ai.isSidebarOpen = false
|
|
117
40
|
}
|
|
118
41
|
}
|
|
119
42
|
|
|
@@ -135,54 +58,61 @@ export default {
|
|
|
135
58
|
|
|
136
59
|
watch(() => route.query.open, (newVal) => {
|
|
137
60
|
modal.value = ctx.modalComponents[newVal]
|
|
138
|
-
console.log('open', newVal
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
watch(() => ctx.state.selectedModel, (newVal) => {
|
|
142
|
-
ctx.chat.setSelectedModel(ctx.chat.getModel(newVal))
|
|
61
|
+
console.log('open', newVal)
|
|
143
62
|
})
|
|
144
63
|
|
|
145
|
-
return { ai, modal, isMobile, closeModal }
|
|
64
|
+
return { ai, modal, isMobile, toggleSidebar, closeSidebar, closeModal }
|
|
146
65
|
},
|
|
147
66
|
template: `
|
|
148
|
-
<div class="flex h-screen">
|
|
67
|
+
<div class="flex h-screen bg-white dark:bg-gray-900">
|
|
149
68
|
<!-- Mobile Overlay -->
|
|
150
|
-
<div
|
|
151
|
-
|
|
152
|
-
|
|
69
|
+
<div
|
|
70
|
+
v-if="isMobile && ai.isSidebarOpen && !(ai.requiresAuth && !ai.auth)"
|
|
71
|
+
@click="closeSidebar"
|
|
72
|
+
class="fixed inset-0 bg-black/50 z-40 lg:hidden"
|
|
153
73
|
></div>
|
|
154
74
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
/>
|
|
75
|
+
<!-- Sidebar (hidden when auth required and not authenticated) -->
|
|
76
|
+
<div
|
|
77
|
+
v-if="!(ai.requiresAuth && !ai.auth) && ai.isSidebarOpen"
|
|
78
|
+
:class="[
|
|
79
|
+
'transition-transform duration-300 ease-in-out z-50',
|
|
80
|
+
'w-72 xl:w-80 flex-shrink-0',
|
|
81
|
+
'lg:relative',
|
|
82
|
+
'fixed inset-y-0 left-0'
|
|
83
|
+
]"
|
|
84
|
+
>
|
|
85
|
+
<Sidebar @thread-selected="closeSidebar" @toggle-sidebar="toggleSidebar" />
|
|
167
86
|
</div>
|
|
168
87
|
|
|
169
88
|
<!-- Main Area -->
|
|
170
|
-
<div
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
89
|
+
<div class="flex-1 flex flex-col">
|
|
90
|
+
<!-- Collapsed Sidebar Toggle Button -->
|
|
91
|
+
<div
|
|
92
|
+
v-if="!(ai.requiresAuth && !ai.auth) && !ai.isSidebarOpen"
|
|
93
|
+
class="fixed top-4 left-0"
|
|
94
|
+
>
|
|
95
|
+
<button type="button"
|
|
96
|
+
@click="toggleSidebar"
|
|
97
|
+
class="group p-1 text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
|
|
98
|
+
title="Open sidebar"
|
|
99
|
+
>
|
|
100
|
+
<div class="relative w-5 h-5">
|
|
101
|
+
<!-- Default sidebar icon -->
|
|
102
|
+
<svg class="absolute inset-0 group-hover:hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
103
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
104
|
+
<line x1="9" y1="3" x2="9" y2="21"></line>
|
|
105
|
+
</svg>
|
|
106
|
+
<!-- Hover state: |→ icon -->
|
|
107
|
+
<svg class="absolute inset-0 hidden group-hover:block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="m17.172 11l-4.657-4.657l1.414-1.414L21 12l-7.071 7.071l-1.414-1.414L17.172 13H8v-2zM4 19V5h2v14z"/></svg>
|
|
175
108
|
</div>
|
|
176
|
-
|
|
177
|
-
</div>
|
|
178
|
-
<TopPanel v-if="$ai.hasAccess" id="top-panel" :class="$ctx.cls('top-panel', 'shrink-0')" />
|
|
179
|
-
<div id="page" :class="$ctx.cls('page', 'flex-1 overflow-y-auto min-h-0 flex flex-col')">
|
|
180
|
-
<RouterView class="h-full" />
|
|
181
|
-
</div>
|
|
109
|
+
</button>
|
|
182
110
|
</div>
|
|
111
|
+
|
|
112
|
+
<RouterView />
|
|
183
113
|
</div>
|
|
184
114
|
|
|
185
|
-
<component v-if="modal" :is="modal"
|
|
115
|
+
<component v-if="modal" :is="modal" @done="closeModal" />
|
|
186
116
|
</div>
|
|
187
117
|
`,
|
|
188
118
|
}
|
llms/ui/Avatar.mjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { computed, inject, ref, onMounted, onUnmounted } from "vue"
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
template: `
|
|
5
|
+
<div v-if="$ai.auth?.profileUrl" class="relative" ref="avatarContainer">
|
|
6
|
+
<img
|
|
7
|
+
@click.stop="toggleMenu"
|
|
8
|
+
:src="$ai.auth.profileUrl"
|
|
9
|
+
:title="authTitle"
|
|
10
|
+
class="size-8 rounded-full cursor-pointer hover:ring-2 hover:ring-gray-300"
|
|
11
|
+
/>
|
|
12
|
+
<div
|
|
13
|
+
v-if="showMenu"
|
|
14
|
+
@click.stop
|
|
15
|
+
class="absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 z-50 border border-gray-200 dark:border-gray-700"
|
|
16
|
+
>
|
|
17
|
+
<div class="px-4 py-2 text-sm text-gray-700 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700">
|
|
18
|
+
<div class="font-medium whitespace-nowrap overflow-hidden text-ellipsis">{{ $ai.auth.displayName || $ai.auth.userName }}</div>
|
|
19
|
+
<div class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap overflow-hidden text-ellipsis">{{ $ai.auth.email }}</div>
|
|
20
|
+
</div>
|
|
21
|
+
<button type="button"
|
|
22
|
+
@click="handleLogout"
|
|
23
|
+
class="w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center whitespace-nowrap"
|
|
24
|
+
>
|
|
25
|
+
<svg class="w-4 h-4 mr-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
26
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
|
|
27
|
+
</svg>
|
|
28
|
+
Sign Out
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
`,
|
|
33
|
+
setup() {
|
|
34
|
+
const ctx = inject('ctx')
|
|
35
|
+
const ai = ctx.ai
|
|
36
|
+
const showMenu = ref(false)
|
|
37
|
+
const avatarContainer = ref(null)
|
|
38
|
+
|
|
39
|
+
const authTitle = computed(() => {
|
|
40
|
+
if (!ai.auth) return ''
|
|
41
|
+
const { userId, userName, displayName, bearerToken, roles } = ai.auth
|
|
42
|
+
const name = userName || displayName
|
|
43
|
+
const prefix = roles && roles.includes('Admin') ? 'Admin' : 'Name'
|
|
44
|
+
const sb = [
|
|
45
|
+
name ? `${prefix}: ${name}` : '',
|
|
46
|
+
`API Key: ${bearerToken}`,
|
|
47
|
+
`${userId}`,
|
|
48
|
+
]
|
|
49
|
+
return sb.filter(x => x).join('\n')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
function toggleMenu() {
|
|
53
|
+
showMenu.value = !showMenu.value
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function handleLogout() {
|
|
57
|
+
showMenu.value = false
|
|
58
|
+
await ai.signOut()
|
|
59
|
+
// Reload the page to show sign-in screen
|
|
60
|
+
window.location.reload()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Close menu when clicking outside
|
|
64
|
+
const handleClickOutside = (event) => {
|
|
65
|
+
if (showMenu.value && avatarContainer.value && !avatarContainer.value.contains(event.target)) {
|
|
66
|
+
showMenu.value = false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onMounted(() => {
|
|
71
|
+
document.addEventListener('click', handleClickOutside)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
onUnmounted(() => {
|
|
75
|
+
document.removeEventListener('click', handleClickOutside)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
authTitle,
|
|
80
|
+
handleLogout,
|
|
81
|
+
showMenu,
|
|
82
|
+
toggleMenu,
|
|
83
|
+
avatarContainer,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
llms/ui/Brand.mjs
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
template:`
|
|
3
|
+
<div class="flex-shrink-0 pl-2 pr-4 py-4 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 min-h-16 select-none">
|
|
4
|
+
<div class="flex items-center justify-between">
|
|
5
|
+
<div class="flex items-center space-x-2">
|
|
6
|
+
<button type="button"
|
|
7
|
+
@click="$emit('toggle-sidebar')"
|
|
8
|
+
class="group relative text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none transition-colors"
|
|
9
|
+
title="Collapse sidebar"
|
|
10
|
+
>
|
|
11
|
+
<div class="relative size-5">
|
|
12
|
+
<!-- Default sidebar icon -->
|
|
13
|
+
<svg class="absolute inset-0 group-hover:hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
14
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
15
|
+
<line x1="9" y1="3" x2="9" y2="21"></line>
|
|
16
|
+
</svg>
|
|
17
|
+
<!-- Hover state: |← icon -->
|
|
18
|
+
<svg class="absolute inset-0 hidden group-hover:block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="m10.071 4.929l1.414 1.414L6.828 11H16v2H6.828l4.657 4.657l-1.414 1.414L3 12zM18.001 19V5h2v14z"/></svg>
|
|
19
|
+
</div>
|
|
20
|
+
</button>
|
|
21
|
+
|
|
22
|
+
<button type="button"
|
|
23
|
+
@click="$emit('home')"
|
|
24
|
+
class="text-lg font-semibold text-gray-900 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none transition-colors"
|
|
25
|
+
title="Go back to initial state"
|
|
26
|
+
>
|
|
27
|
+
History
|
|
28
|
+
</button>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="flex items-center space-x-2">
|
|
32
|
+
<button type="button"
|
|
33
|
+
@click="$emit('analytics')"
|
|
34
|
+
class="text-gray-900 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none transition-colors"
|
|
35
|
+
title="Analytics"
|
|
36
|
+
>
|
|
37
|
+
<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M5 22a1 1 0 0 1-1-1v-8a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1m5 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1m5 0a1 1 0 0 1-1-1V9a1 1 0 0 1 2 0v12a1 1 0 0 1-1 1m5 0a1 1 0 0 1-1-1v-4a1 1 0 0 1 2 0v4a1 1 0 0 1-1 1"/></svg>
|
|
38
|
+
</button>
|
|
39
|
+
|
|
40
|
+
<button type="button"
|
|
41
|
+
@click="$emit('new')"
|
|
42
|
+
class="text-gray-900 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none transition-colors"
|
|
43
|
+
title="New Chat"
|
|
44
|
+
>
|
|
45
|
+
<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z"/></g></svg>
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
`,
|
|
51
|
+
emits:['home','new','analytics','toggle-sidebar'],
|
|
52
|
+
}
|