llms-py 3.0.0b6__py3-none-any.whl → 3.0.0b8__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/{ui/modules/analytics.mjs → extensions/analytics/ui/index.mjs} +55 -164
- llms/extensions/app/__init__.py +519 -0
- 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 +641 -0
- llms/extensions/app/db_manager.py +195 -0
- llms/extensions/app/requests.json +9073 -0
- llms/extensions/app/threads.json +15290 -0
- llms/{ui/modules/threads → extensions/app/ui}/Recents.mjs +82 -55
- llms/{ui/modules/threads → extensions/app/ui}/index.mjs +83 -20
- llms/extensions/app/ui/threadStore.mjs +407 -0
- llms/extensions/core_tools/__init__.py +598 -0
- llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +201 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +185 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +101 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +160 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +66 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +27 -0
- llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +72 -0
- llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +119 -0
- llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +98 -0
- llms/extensions/core_tools/ui/codemirror/doc/docs.css +225 -0
- llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
- llms/extensions/core_tools/ui/codemirror/lib/codemirror.css +344 -0
- llms/extensions/core_tools/ui/codemirror/lib/codemirror.js +9884 -0
- llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +942 -0
- llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +118 -0
- llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +962 -0
- llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +62 -0
- llms/extensions/core_tools/ui/codemirror/mode/python/python.js +402 -0
- llms/extensions/core_tools/ui/codemirror/theme/dracula.css +40 -0
- llms/extensions/core_tools/ui/codemirror/theme/mocha.css +135 -0
- llms/extensions/core_tools/ui/index.mjs +650 -0
- llms/extensions/gallery/__init__.py +61 -0
- 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 +298 -0
- llms/extensions/gallery/ui/index.mjs +481 -0
- llms/extensions/katex/__init__.py +6 -0
- llms/extensions/katex/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/katex/ui/README.md +125 -0
- llms/extensions/katex/ui/contrib/auto-render.js +338 -0
- llms/extensions/katex/ui/contrib/auto-render.min.js +1 -0
- llms/extensions/katex/ui/contrib/auto-render.mjs +244 -0
- llms/extensions/katex/ui/contrib/copy-tex.js +127 -0
- llms/extensions/katex/ui/contrib/copy-tex.min.js +1 -0
- llms/extensions/katex/ui/contrib/copy-tex.mjs +105 -0
- llms/extensions/katex/ui/contrib/mathtex-script-type.js +109 -0
- llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +1 -0
- llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +24 -0
- llms/extensions/katex/ui/contrib/mhchem.js +3213 -0
- llms/extensions/katex/ui/contrib/mhchem.min.js +1 -0
- llms/extensions/katex/ui/contrib/mhchem.mjs +3109 -0
- llms/extensions/katex/ui/contrib/render-a11y-string.js +887 -0
- llms/extensions/katex/ui/contrib/render-a11y-string.min.js +1 -0
- llms/extensions/katex/ui/contrib/render-a11y-string.mjs +800 -0
- 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 +92 -0
- llms/extensions/katex/ui/katex-swap.css +1230 -0
- llms/extensions/katex/ui/katex-swap.min.css +1 -0
- llms/extensions/katex/ui/katex.css +1230 -0
- llms/extensions/katex/ui/katex.js +19080 -0
- llms/extensions/katex/ui/katex.min.css +1 -0
- llms/extensions/katex/ui/katex.min.js +1 -0
- llms/extensions/katex/ui/katex.min.mjs +1 -0
- llms/extensions/katex/ui/katex.mjs +18547 -0
- llms/extensions/providers/__init__.py +18 -0
- 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/{providers → extensions/providers}/__pycache__/nvidia.cpython-314.pyc +0 -0
- llms/{providers → extensions/providers}/__pycache__/openai.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
- llms/{providers → extensions/providers}/anthropic.py +45 -5
- llms/{providers → extensions/providers}/chutes.py +21 -18
- llms/{providers → extensions/providers}/google.py +99 -27
- llms/{providers → extensions/providers}/nvidia.py +6 -8
- llms/{providers → extensions/providers}/openai.py +3 -6
- llms/{providers → extensions/providers}/openrouter.py +12 -10
- llms/extensions/system_prompts/__init__.py +45 -0
- llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/system_prompts/ui/index.mjs +285 -0
- llms/extensions/system_prompts/ui/prompts.json +1067 -0
- llms/extensions/tools/__init__.py +5 -0
- llms/extensions/tools/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/{ui/modules/tools.mjs → extensions/tools/ui/index.mjs} +12 -10
- llms/index.html +26 -38
- llms/llms.json +20 -1
- llms/main.py +845 -245
- llms/providers-extra.json +0 -32
- llms/ui/App.mjs +18 -20
- llms/ui/ai.mjs +38 -15
- llms/ui/app.css +1440 -59
- llms/ui/ctx.mjs +154 -18
- llms/ui/index.mjs +17 -14
- llms/ui/lib/vue.min.mjs +10 -9
- llms/ui/lib/vue.mjs +1796 -1635
- llms/ui/markdown.mjs +4 -2
- llms/ui/modules/chat/ChatBody.mjs +101 -334
- llms/ui/modules/chat/HomeTools.mjs +12 -0
- llms/ui/modules/chat/SettingsDialog.mjs +1 -1
- llms/ui/modules/chat/index.mjs +351 -314
- llms/ui/modules/layout.mjs +2 -26
- llms/ui/modules/model-selector.mjs +3 -3
- llms/ui/tailwind.input.css +35 -1
- llms/ui/utils.mjs +33 -3
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/METADATA +1 -1
- llms_py-3.0.0b8.dist-info/RECORD +198 -0
- 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__/openrouter.cpython-314.pyc +0 -0
- llms/ui/modules/threads/threadStore.mjs +0 -586
- llms_py-3.0.0b6.dist-info/RECORD +0 -66
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/WHEEL +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/top_level.txt +0 -0
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { ref, onMounted, watch, inject } from 'vue'
|
|
2
2
|
import { useRouter, useRoute } from 'vue-router'
|
|
3
|
-
import { useThreadStore } from './threadStore.mjs'
|
|
4
3
|
|
|
5
4
|
const RecentResults = {
|
|
6
5
|
template: `
|
|
7
6
|
<div class="flex-1 overflow-y-auto" @scroll="onScroll">
|
|
8
7
|
<div class="mx-auto max-w-6xl px-4 py-4">
|
|
9
|
-
<div class="text-sm text-gray-600 dark:text-gray-400 mb-3"
|
|
10
|
-
<span v-if="q">{{
|
|
11
|
-
<span v-else>
|
|
8
|
+
<div class="text-sm text-gray-600 dark:text-gray-400 mb-3">
|
|
9
|
+
<span v-if="q">{{ total }} result{{ total===1?'':'s' }}</span>
|
|
10
|
+
<span v-else>All conversations</span>
|
|
12
11
|
</div>
|
|
13
12
|
|
|
14
|
-
<div v-if="!threads.length" class="text-gray-500 dark:text-gray-400">No conversations
|
|
13
|
+
<div v-if="!loading && threads.length === 0" class="text-gray-500 dark:text-gray-400">No conversations found.</div>
|
|
15
14
|
|
|
16
15
|
<table class="w-full">
|
|
17
16
|
<tbody>
|
|
18
|
-
<tr v-for="t in
|
|
19
|
-
<td class="py-3 px-1 border-b border-gray-200 dark:border-gray-700 max-w-
|
|
17
|
+
<tr v-for="t in threads" :key="t.id" class="hover:bg-gray-50 dark:hover:bg-gray-800">
|
|
18
|
+
<td class="py-3 px-1 border-b border-gray-200 dark:border-gray-700 max-w-2xl">
|
|
20
19
|
<button type="button" @click="open(t.id)" class="w-full text-left">
|
|
21
20
|
<div class="flex items-start justify-between gap-3">
|
|
22
21
|
<div class="min-w-0 flex-1">
|
|
@@ -32,12 +31,13 @@ const RecentResults = {
|
|
|
32
31
|
<div class="text-right whitespace-nowrap">
|
|
33
32
|
<div class="text-xs text-gray-500 dark:text-gray-400">{{ formatDate(t.updatedAt || t.createdAt) }}</div>
|
|
34
33
|
<div class="text-[11px] text-gray-500/80 dark:text-gray-400/80">{{ (t.messages?.length || 0) }} messages</div>
|
|
35
|
-
<div v-if="t.model" class="text-[11px] text-blue-600 dark:text-blue-400">{{ t.model }}</div>
|
|
34
|
+
<div v-if="t.model" class="text-[11px] text-blue-600 dark:text-blue-400 max-w-[140px] truncate" :title="t.model">{{ t.model }}</div>
|
|
36
35
|
</div>
|
|
37
36
|
</td>
|
|
38
37
|
</tr>
|
|
39
38
|
</tbody>
|
|
40
39
|
</table>
|
|
40
|
+
<div v-if="loading" class="py-4 text-center text-gray-500 dark:text-gray-400">Loading...</div>
|
|
41
41
|
</div>
|
|
42
42
|
</div>
|
|
43
43
|
`,
|
|
@@ -47,59 +47,81 @@ const RecentResults = {
|
|
|
47
47
|
setup(props) {
|
|
48
48
|
const ctx = inject('ctx')
|
|
49
49
|
const ai = ctx.ai
|
|
50
|
-
const config = ctx.state.config
|
|
51
50
|
const router = useRouter()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
|
|
52
|
+
const threads = ref([])
|
|
53
|
+
const loading = ref(false)
|
|
54
|
+
const noMore = ref(false)
|
|
55
|
+
const total = ref(0)
|
|
56
|
+
let skip = 0
|
|
57
|
+
const take = 25
|
|
58
|
+
|
|
59
|
+
// Simple debounce function
|
|
60
|
+
function debounce(fn, delay) {
|
|
61
|
+
let timeoutID = null
|
|
62
|
+
return function () {
|
|
63
|
+
clearTimeout(timeoutID)
|
|
64
|
+
timeoutID = setTimeout(() => fn.apply(this, arguments), delay)
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
console.log('end', Date.now() - start)
|
|
68
|
-
})
|
|
66
|
+
}
|
|
69
67
|
|
|
70
68
|
const normalized = (s) => (s || '').toString().toLowerCase()
|
|
71
|
-
|
|
72
69
|
const replaceChars = new Set('<>`*|#'.split(''))
|
|
73
70
|
const clean = s => [...s].map(c => replaceChars.has(c) ? ' ' : c).join('')
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
const loadMore = async (reset = false) => {
|
|
73
|
+
if (reset) {
|
|
74
|
+
skip = 0
|
|
75
|
+
threads.value = []
|
|
76
|
+
noMore.value = false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (loading.value || noMore.value) return
|
|
80
|
+
|
|
81
|
+
loading.value = true
|
|
82
|
+
try {
|
|
83
|
+
const query = {
|
|
84
|
+
take,
|
|
85
|
+
skip,
|
|
86
|
+
...(props.q ? { q: props.q } : {})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const results = await ctx.threads.query(query)
|
|
90
|
+
|
|
91
|
+
if (results.length < take) {
|
|
92
|
+
noMore.value = true
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (reset) {
|
|
96
|
+
threads.value = results
|
|
97
|
+
} else {
|
|
98
|
+
threads.value.push(...results)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
skip += results.length
|
|
102
|
+
|
|
103
|
+
total.value = threads.value.length
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.error("Failed to load threads", e)
|
|
106
|
+
} finally {
|
|
107
|
+
loading.value = false
|
|
108
|
+
}
|
|
89
109
|
}
|
|
90
110
|
|
|
111
|
+
const update = debounce(() => loadMore(true), 250)
|
|
112
|
+
|
|
113
|
+
onMounted(() => {
|
|
114
|
+
loadMore(true)
|
|
115
|
+
})
|
|
116
|
+
|
|
91
117
|
const onScroll = (e) => {
|
|
92
118
|
const el = e.target
|
|
93
|
-
if (el.scrollTop + el.clientHeight >= el.scrollHeight -
|
|
94
|
-
|
|
95
|
-
visibleCount.value = Math.min(visibleCount.value + defaultVisibleCount, filtered.value.length)
|
|
96
|
-
updateVisible()
|
|
97
|
-
}
|
|
119
|
+
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) { // 50px threshold
|
|
120
|
+
loadMore()
|
|
98
121
|
}
|
|
99
122
|
}
|
|
100
123
|
|
|
101
124
|
watch(() => props.q, () => {
|
|
102
|
-
visibleCount.value = defaultVisibleCount
|
|
103
125
|
update()
|
|
104
126
|
})
|
|
105
127
|
|
|
@@ -107,7 +129,11 @@ const RecentResults = {
|
|
|
107
129
|
const highlight = (s) => clean(s).replace(new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'), `<mark>$1</mark>`)
|
|
108
130
|
const query = normalized(props.q)
|
|
109
131
|
if (!query) return (t.messages && t.messages.length) ? highlight(t.messages[t.messages.length - 1].content) : ''
|
|
132
|
+
|
|
133
|
+
// Check title
|
|
110
134
|
if (normalized(t.title).includes(query)) return highlight(t.title)
|
|
135
|
+
|
|
136
|
+
// Check messages
|
|
111
137
|
if (Array.isArray(t.messages)) {
|
|
112
138
|
for (const m of t.messages) {
|
|
113
139
|
const c = normalized(m?.content)
|
|
@@ -119,23 +145,23 @@ const RecentResults = {
|
|
|
119
145
|
const end = Math.min(orig.length, idx + query.length + 60)
|
|
120
146
|
const prefix = start > 0 ? '…' : ''
|
|
121
147
|
const suffix = end < orig.length ? '…' : ''
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
return highlight(snippet)
|
|
148
|
+
const snippetText = prefix + orig.slice(start, end) + suffix
|
|
149
|
+
return highlight(snippetText)
|
|
125
150
|
}
|
|
126
151
|
}
|
|
127
152
|
}
|
|
128
|
-
|
|
153
|
+
|
|
154
|
+
// Fallback to last message if no specific match found (e.g. matched on hidden metadata or partial?)
|
|
155
|
+
return (t.messages && t.messages.length) ? highlight(t.messages[t.messages.length - 1].content) : ''
|
|
129
156
|
}
|
|
130
157
|
|
|
131
158
|
const open = (id) => router.push(`${ai.base}/c/${id}`)
|
|
132
159
|
const formatDate = (iso) => new Date(iso).toLocaleString()
|
|
133
160
|
|
|
134
161
|
return {
|
|
135
|
-
config,
|
|
136
162
|
threads,
|
|
137
|
-
|
|
138
|
-
|
|
163
|
+
loading,
|
|
164
|
+
total,
|
|
139
165
|
snippet,
|
|
140
166
|
open,
|
|
141
167
|
formatDate,
|
|
@@ -153,9 +179,10 @@ export default {
|
|
|
153
179
|
<!-- Header -->
|
|
154
180
|
<div class="border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 px-4 py-3 min-h-16">
|
|
155
181
|
<div class="max-w-6xl mx-auto flex items-center justify-between gap-3">
|
|
156
|
-
<
|
|
157
|
-
<div class="flex-1 flex items-center gap-2">
|
|
182
|
+
<label for="search-history" class="cursor-pointer text-lg font-semibold text-gray-900 dark:text-gray-100">Search History</label>
|
|
183
|
+
<div class="flex-1 flex items-center gap-2 max-w-sm">
|
|
158
184
|
<input
|
|
185
|
+
id="search-history"
|
|
159
186
|
v-model="q"
|
|
160
187
|
type="search"
|
|
161
188
|
placeholder="Search titles and messages..."
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { onMounted, inject } from 'vue'
|
|
2
2
|
import { useRouter } from 'vue-router'
|
|
3
|
+
import { appendQueryString } from '@servicestack/client'
|
|
3
4
|
import ThreadStore from './threadStore.mjs'
|
|
4
5
|
import Recents from './Recents.mjs'
|
|
5
6
|
|
|
7
|
+
let ext
|
|
8
|
+
|
|
6
9
|
// Thread Item Component
|
|
7
10
|
const ThreadItem = {
|
|
8
11
|
template: `
|
|
@@ -70,7 +73,20 @@ const GroupedThreads = {
|
|
|
70
73
|
v-for="thread in groupedThreads.today"
|
|
71
74
|
:key="thread.id"
|
|
72
75
|
:thread="thread"
|
|
73
|
-
:is-active="currentThread?.id
|
|
76
|
+
:is-active="currentThread?.id == thread.id"
|
|
77
|
+
@select="$emit('select', $event)"
|
|
78
|
+
@delete="$emit('delete', $event)"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<!-- Yesterday -->
|
|
83
|
+
<div v-if="groupedThreads.yesterday.length > 0" class="mb-4">
|
|
84
|
+
<h3 class="px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider select-none">Yesterday</h3>
|
|
85
|
+
<ThreadItem
|
|
86
|
+
v-for="thread in groupedThreads.yesterday"
|
|
87
|
+
:key="thread.id"
|
|
88
|
+
:thread="thread"
|
|
89
|
+
:is-active="currentThread?.id == thread.id"
|
|
74
90
|
@select="$emit('select', $event)"
|
|
75
91
|
@delete="$emit('delete', $event)"
|
|
76
92
|
/>
|
|
@@ -83,7 +99,7 @@ const GroupedThreads = {
|
|
|
83
99
|
v-for="thread in groupedThreads.lastWeek"
|
|
84
100
|
:key="thread.id"
|
|
85
101
|
:thread="thread"
|
|
86
|
-
:is-active="currentThread?.id
|
|
102
|
+
:is-active="currentThread?.id == thread.id"
|
|
87
103
|
@select="$emit('select', $event)"
|
|
88
104
|
@delete="$emit('delete', $event)"
|
|
89
105
|
/>
|
|
@@ -96,7 +112,7 @@ const GroupedThreads = {
|
|
|
96
112
|
v-for="thread in groupedThreads.lastMonth"
|
|
97
113
|
:key="thread.id"
|
|
98
114
|
:thread="thread"
|
|
99
|
-
:is-active="currentThread?.id
|
|
115
|
+
:is-active="currentThread?.id == thread.id"
|
|
100
116
|
@select="$emit('select', $event)"
|
|
101
117
|
@delete="$emit('delete', $event)"
|
|
102
118
|
/>
|
|
@@ -109,7 +125,7 @@ const GroupedThreads = {
|
|
|
109
125
|
v-for="thread in monthThreads"
|
|
110
126
|
:key="thread.id"
|
|
111
127
|
:thread="thread"
|
|
112
|
-
:is-active="currentThread?.id
|
|
128
|
+
:is-active="currentThread?.id == thread.id"
|
|
113
129
|
@select="$emit('select', $event)"
|
|
114
130
|
@delete="$emit('delete', $event)"
|
|
115
131
|
/>
|
|
@@ -135,7 +151,7 @@ const GroupedThreads = {
|
|
|
135
151
|
const ThreadsSidebar = {
|
|
136
152
|
template: `
|
|
137
153
|
<div class="flex flex-col h-full">
|
|
138
|
-
<Brand
|
|
154
|
+
<Brand />
|
|
139
155
|
<!-- Thread List -->
|
|
140
156
|
<div class="flex-1 overflow-y-auto">
|
|
141
157
|
<div v-if="isLoading" class="p-4 text-center text-gray-500 dark:text-gray-400">
|
|
@@ -169,8 +185,7 @@ const ThreadsSidebar = {
|
|
|
169
185
|
</div>
|
|
170
186
|
</div>
|
|
171
187
|
`,
|
|
172
|
-
|
|
173
|
-
setup(props, { emit }) {
|
|
188
|
+
setup(props) {
|
|
174
189
|
const ctx = inject('ctx')
|
|
175
190
|
const ai = ctx.ai
|
|
176
191
|
const router = useRouter()
|
|
@@ -191,7 +206,6 @@ const ThreadsSidebar = {
|
|
|
191
206
|
|
|
192
207
|
const selectThread = async (threadId) => {
|
|
193
208
|
router.push(`${ai.base}/c/${threadId}`)
|
|
194
|
-
emit('thread-selected')
|
|
195
209
|
}
|
|
196
210
|
|
|
197
211
|
const deleteThread = async (threadId) => {
|
|
@@ -205,20 +219,16 @@ const ThreadsSidebar = {
|
|
|
205
219
|
}
|
|
206
220
|
|
|
207
221
|
const createNewThread = async () => {
|
|
208
|
-
|
|
209
|
-
router.push(`${ai.base}/c/${newThread.id}`)
|
|
210
|
-
emit('thread-selected')
|
|
222
|
+
ctx.threads.startNewThread({ title: 'New Chat', model: ctx.chat.getSelectedModel() })
|
|
211
223
|
}
|
|
212
224
|
|
|
213
225
|
const goToInitialState = () => {
|
|
214
226
|
clearCurrentThread()
|
|
215
|
-
|
|
216
|
-
emit('thread-selected')
|
|
227
|
+
ctx.to(`/`)
|
|
217
228
|
}
|
|
218
229
|
|
|
219
230
|
const goToAnalytics = () => {
|
|
220
|
-
|
|
221
|
-
emit('thread-selected')
|
|
231
|
+
ctx.to(`/analytics`)
|
|
222
232
|
}
|
|
223
233
|
|
|
224
234
|
return {
|
|
@@ -235,8 +245,62 @@ const ThreadsSidebar = {
|
|
|
235
245
|
}
|
|
236
246
|
}
|
|
237
247
|
|
|
248
|
+
function useRequests(ext) {
|
|
249
|
+
async function query(query) {
|
|
250
|
+
return (await ext.getJson(appendQueryString(`/requests`, query))).response || []
|
|
251
|
+
}
|
|
252
|
+
async function deleteById(requestId) {
|
|
253
|
+
if (!requestId) {
|
|
254
|
+
throw new Error('Request ID is required')
|
|
255
|
+
}
|
|
256
|
+
return await ext.deleteJson(`/requests/${requestId}`)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function getThreadIds(query) {
|
|
260
|
+
return (await ext.getJson(appendQueryString(`/requests?fields=threadId¬_null=threadId&as=column&take=10000`, query))).response || []
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function getSummary() {
|
|
264
|
+
return (await ext.getJson(`/requests/summary`)).response
|
|
265
|
+
}
|
|
266
|
+
async function getDailySummary(day) {
|
|
267
|
+
return (await ext.getJson(`/requests/summary/${day}`)).response
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Get unique values for filter options
|
|
271
|
+
async function getFilterOptions() {
|
|
272
|
+
const results = await query({
|
|
273
|
+
select: 'distinct',
|
|
274
|
+
fields: 'model,provider',
|
|
275
|
+
not_null: 'model,provider',
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
if (results) {
|
|
279
|
+
const models = [...new Set(results.map(r => r.model).filter(m => m))].sort()
|
|
280
|
+
const providers = [...new Set(results.map(r => r.provider).filter(p => p))].sort()
|
|
281
|
+
console.log('getFilterOptions', models, providers)
|
|
282
|
+
return {
|
|
283
|
+
models,
|
|
284
|
+
providers
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
query,
|
|
291
|
+
deleteById,
|
|
292
|
+
getThreadIds,
|
|
293
|
+
getSummary,
|
|
294
|
+
getDailySummary,
|
|
295
|
+
getFilterOptions,
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
238
299
|
export default {
|
|
300
|
+
order: -100,
|
|
301
|
+
|
|
239
302
|
install(ctx) {
|
|
303
|
+
ext = ctx.scope('app')
|
|
240
304
|
ctx.components({
|
|
241
305
|
ThreadsSidebar,
|
|
242
306
|
ThreadItem,
|
|
@@ -248,13 +312,12 @@ export default {
|
|
|
248
312
|
])
|
|
249
313
|
ThreadStore.install(ctx)
|
|
250
314
|
|
|
315
|
+
ctx.setGlobals({
|
|
316
|
+
requests: useRequests(ext)
|
|
317
|
+
})
|
|
318
|
+
|
|
251
319
|
ctx.setLayout({
|
|
252
320
|
left: 'ThreadsSidebar',
|
|
253
321
|
})
|
|
254
|
-
},
|
|
255
|
-
|
|
256
|
-
async load(ctx) {
|
|
257
|
-
const { initDB } = ctx.threads
|
|
258
|
-
await initDB()
|
|
259
322
|
}
|
|
260
323
|
}
|