llms-py 3.0.0b1__py3-none-any.whl → 3.0.0b3__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__/__init__.cpython-312.pyc +0 -0
- llms/__pycache__/__init__.cpython-313.pyc +0 -0
- llms/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/__pycache__/__main__.cpython-312.pyc +0 -0
- llms/__pycache__/__main__.cpython-314.pyc +0 -0
- llms/__pycache__/llms.cpython-312.pyc +0 -0
- llms/__pycache__/main.cpython-312.pyc +0 -0
- llms/__pycache__/main.cpython-313.pyc +0 -0
- llms/__pycache__/main.cpython-314.pyc +0 -0
- llms/__pycache__/plugins.cpython-314.pyc +0 -0
- llms/index.html +27 -57
- llms/llms.json +48 -15
- llms/main.py +923 -624
- 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 +150 -57
- llms/ui/ai.mjs +84 -50
- llms/ui/app.css +1 -4963
- llms/ui/ctx.mjs +196 -0
- llms/ui/index.mjs +117 -0
- 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} +91 -179
- llms/ui/{SettingsDialog.mjs → modules/chat/SettingsDialog.mjs} +8 -8
- llms/ui/{ChatPrompt.mjs → modules/chat/index.mjs} +281 -96
- llms/ui/modules/layout.mjs +267 -0
- llms/ui/modules/model-selector.mjs +851 -0
- llms/ui/{Recents.mjs → modules/threads/Recents.mjs} +10 -11
- llms/ui/{Sidebar.mjs → modules/threads/index.mjs} +48 -45
- llms/ui/{threadStore.mjs → modules/threads/threadStore.mjs} +21 -7
- llms/ui/tailwind.input.css +441 -79
- llms/ui/utils.mjs +83 -123
- {llms_py-3.0.0b1.dist-info → llms_py-3.0.0b3.dist-info}/METADATA +1 -1
- llms_py-3.0.0b3.dist-info/RECORD +65 -0
- llms/ui/Avatar.mjs +0 -85
- llms/ui/Brand.mjs +0 -52
- llms/ui/ModelSelector.mjs +0 -693
- llms/ui/OAuthSignIn.mjs +0 -92
- llms/ui/ProviderIcon.mjs +0 -36
- llms/ui/ProviderStatus.mjs +0 -105
- llms/ui/SignIn.mjs +0 -64
- llms/ui/SystemPromptEditor.mjs +0 -31
- llms/ui/SystemPromptSelector.mjs +0 -56
- llms/ui/Welcome.mjs +0 -8
- llms/ui.json +0 -1069
- llms_py-3.0.0b1.dist-info/RECORD +0 -49
- {llms_py-3.0.0b1.dist-info → llms_py-3.0.0b3.dist-info}/WHEEL +0 -0
- {llms_py-3.0.0b1.dist-info → llms_py-3.0.0b3.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.0b1.dist-info → llms_py-3.0.0b3.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.0b1.dist-info → llms_py-3.0.0b3.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ref, onMounted, watch, inject } from 'vue'
|
|
2
2
|
import { useRouter, useRoute } from 'vue-router'
|
|
3
3
|
import { useThreadStore } from './threadStore.mjs'
|
|
4
|
-
import { renderMarkdown } from './markdown.mjs'
|
|
5
4
|
|
|
6
5
|
const RecentResults = {
|
|
7
|
-
template
|
|
6
|
+
template: `
|
|
8
7
|
<div class="flex-1 overflow-y-auto" @scroll="onScroll">
|
|
9
8
|
<div class="mx-auto max-w-6xl px-4 py-4">
|
|
10
9
|
<div class="text-sm text-gray-600 dark:text-gray-400 mb-3" v-if="threads.length">
|
|
@@ -46,9 +45,10 @@ const RecentResults = {
|
|
|
46
45
|
q: String
|
|
47
46
|
},
|
|
48
47
|
setup(props) {
|
|
49
|
-
const
|
|
48
|
+
const ctx = inject('ctx')
|
|
49
|
+
const ai = ctx.ai
|
|
50
|
+
const config = ctx.state.config
|
|
50
51
|
const router = useRouter()
|
|
51
|
-
const config = inject('config')
|
|
52
52
|
const { threads, loadThreads } = useThreadStore()
|
|
53
53
|
let defaultVisibleCount = 25
|
|
54
54
|
const visibleCount = ref(defaultVisibleCount)
|
|
@@ -106,19 +106,19 @@ const RecentResults = {
|
|
|
106
106
|
const snippet = (t) => {
|
|
107
107
|
const highlight = (s) => clean(s).replace(new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'), `<mark>$1</mark>`)
|
|
108
108
|
const query = normalized(props.q)
|
|
109
|
-
if (!query) return (t.messages && t.messages.length) ? highlight(t.messages[t.messages.length-1].content) : ''
|
|
109
|
+
if (!query) return (t.messages && t.messages.length) ? highlight(t.messages[t.messages.length - 1].content) : ''
|
|
110
110
|
if (normalized(t.title).includes(query)) return highlight(t.title)
|
|
111
|
-
if (Array.isArray(t.messages)){
|
|
112
|
-
for (const m of t.messages){
|
|
111
|
+
if (Array.isArray(t.messages)) {
|
|
112
|
+
for (const m of t.messages) {
|
|
113
113
|
const c = normalized(m?.content)
|
|
114
|
-
if (c.includes(query)){
|
|
114
|
+
if (c.includes(query)) {
|
|
115
115
|
// return small excerpt around first match
|
|
116
116
|
const idx = c.indexOf(query)
|
|
117
117
|
const orig = (m?.content || '')
|
|
118
118
|
const start = Math.max(0, idx - 40)
|
|
119
119
|
const end = Math.min(orig.length, idx + query.length + 60)
|
|
120
|
-
const prefix = start>0 ? '…' : ''
|
|
121
|
-
const suffix = end<orig.length ? '…' : ''
|
|
120
|
+
const prefix = start > 0 ? '…' : ''
|
|
121
|
+
const suffix = end < orig.length ? '…' : ''
|
|
122
122
|
const snippet = prefix + orig.slice(start, end) + suffix
|
|
123
123
|
// return snippet
|
|
124
124
|
return highlight(snippet)
|
|
@@ -139,7 +139,6 @@ const RecentResults = {
|
|
|
139
139
|
snippet,
|
|
140
140
|
open,
|
|
141
141
|
formatDate,
|
|
142
|
-
renderMarkdown,
|
|
143
142
|
onScroll,
|
|
144
143
|
}
|
|
145
144
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { onMounted, inject } from 'vue'
|
|
2
2
|
import { useRouter } from 'vue-router'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import Brand from './Brand.mjs'
|
|
6
|
-
import { statsTitle, formatCost } from './utils.mjs'
|
|
7
|
-
|
|
8
|
-
const { humanifyNumber, humanifyMs } = useFormatters()
|
|
3
|
+
import ThreadStore from './threadStore.mjs'
|
|
4
|
+
import Recents from './Recents.mjs'
|
|
9
5
|
|
|
10
6
|
// Thread Item Component
|
|
11
7
|
const ThreadItem = {
|
|
@@ -21,10 +17,10 @@ const ThreadItem = {
|
|
|
21
17
|
{{ thread.title }}
|
|
22
18
|
</div>
|
|
23
19
|
<div class="text-xs text-gray-500 dark:text-gray-400 truncate">
|
|
24
|
-
<span>{{
|
|
25
|
-
<span v-if="thread.stats?.inputTokens" :title="statsTitle(thread.stats)">
|
|
26
|
-
• {{ humanifyNumber(thread.stats.inputTokens + thread.stats.outputTokens) }} toks
|
|
27
|
-
{{ thread.stats.cost ? ' ' +
|
|
20
|
+
<span>{{ $fmt.relativeTime(thread.updatedAt) }} • {{ thread.messages.length }} msgs</span>
|
|
21
|
+
<span v-if="thread.stats?.inputTokens" :title="$fmt.statsTitle(thread.stats)">
|
|
22
|
+
• {{ $fmt.humanifyNumber(thread.stats.inputTokens + thread.stats.outputTokens) }} toks
|
|
23
|
+
{{ thread.stats.cost ? ' ' + $fmt.cost(thread.stats.cost) : '' }}
|
|
28
24
|
</span>
|
|
29
25
|
</div>
|
|
30
26
|
<div v-if="thread.model" class="text-xs text-blue-600 dark:text-blue-400 truncate">
|
|
@@ -60,32 +56,12 @@ const ThreadItem = {
|
|
|
60
56
|
emits: ['select', 'delete'],
|
|
61
57
|
|
|
62
58
|
setup() {
|
|
63
|
-
const formatRelativeTime = (timestamp) => {
|
|
64
|
-
const now = new Date()
|
|
65
|
-
const date = new Date(timestamp)
|
|
66
|
-
const diffInSeconds = Math.floor((now - date) / 1000)
|
|
67
|
-
|
|
68
|
-
if (diffInSeconds < 60) return 'Just now'
|
|
69
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`
|
|
70
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`
|
|
71
|
-
if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`
|
|
72
|
-
|
|
73
|
-
return date.toLocaleDateString()
|
|
74
|
-
}
|
|
75
|
-
|
|
76
59
|
return {
|
|
77
|
-
formatRelativeTime,
|
|
78
|
-
humanifyNumber,
|
|
79
|
-
statsTitle,
|
|
80
|
-
formatCost,
|
|
81
60
|
}
|
|
82
61
|
}
|
|
83
62
|
}
|
|
84
63
|
|
|
85
64
|
const GroupedThreads = {
|
|
86
|
-
components: {
|
|
87
|
-
ThreadItem,
|
|
88
|
-
},
|
|
89
65
|
template: `
|
|
90
66
|
<!-- Today -->
|
|
91
67
|
<div v-if="groupedThreads.today.length > 0" class="mb-4">
|
|
@@ -156,15 +132,10 @@ const GroupedThreads = {
|
|
|
156
132
|
emits: ['select', 'delete'],
|
|
157
133
|
}
|
|
158
134
|
|
|
159
|
-
const
|
|
160
|
-
components: {
|
|
161
|
-
Brand,
|
|
162
|
-
GroupedThreads,
|
|
163
|
-
ThreadItem,
|
|
164
|
-
},
|
|
135
|
+
const ThreadsSidebar = {
|
|
165
136
|
template: `
|
|
166
|
-
<div class="flex flex-col h-full
|
|
167
|
-
<Brand @home="goToInitialState" @
|
|
137
|
+
<div class="flex flex-col h-full">
|
|
138
|
+
<Brand @home="goToInitialState" @toggle-sidebar="$emit('toggle-sidebar')" />
|
|
168
139
|
<!-- Thread List -->
|
|
169
140
|
<div class="flex-1 overflow-y-auto">
|
|
170
141
|
<div v-if="isLoading" class="p-4 text-center text-gray-500 dark:text-gray-400">
|
|
@@ -180,8 +151,19 @@ const Sidebar = {
|
|
|
180
151
|
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">Start a new chat to begin</p>
|
|
181
152
|
</div>
|
|
182
153
|
|
|
183
|
-
<div v-else class="py-2">
|
|
184
|
-
|
|
154
|
+
<div v-else class="relative py-2">
|
|
155
|
+
|
|
156
|
+
<div class="flex items-center space-x-2 absolute top-2 right-2">
|
|
157
|
+
<button type="button"
|
|
158
|
+
@click="createNewThread"
|
|
159
|
+
class="text-gray-900 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none transition-colors"
|
|
160
|
+
title="New Chat"
|
|
161
|
+
>
|
|
162
|
+
<svg class="size-5" 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>
|
|
163
|
+
</button>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<GroupedThreads :currentThread="currentThread" :groupedThreads="$threads.getGroupedThreads(50)"
|
|
185
167
|
@select="selectThread" @delete="deleteThread" />
|
|
186
168
|
</div>
|
|
187
169
|
</div>
|
|
@@ -189,9 +171,9 @@ const Sidebar = {
|
|
|
189
171
|
`,
|
|
190
172
|
emits: ['thread-selected', 'toggle-sidebar'],
|
|
191
173
|
setup(props, { emit }) {
|
|
192
|
-
const
|
|
174
|
+
const ctx = inject('ctx')
|
|
175
|
+
const ai = ctx.ai
|
|
193
176
|
const router = useRouter()
|
|
194
|
-
const threadStore = useThreadStore()
|
|
195
177
|
const {
|
|
196
178
|
threads,
|
|
197
179
|
currentThread,
|
|
@@ -201,7 +183,7 @@ const Sidebar = {
|
|
|
201
183
|
createThread,
|
|
202
184
|
deleteThread: deleteThreadFromStore,
|
|
203
185
|
clearCurrentThread
|
|
204
|
-
} =
|
|
186
|
+
} = ctx.threads
|
|
205
187
|
|
|
206
188
|
onMounted(async () => {
|
|
207
189
|
await loadThreads()
|
|
@@ -240,7 +222,6 @@ const Sidebar = {
|
|
|
240
222
|
}
|
|
241
223
|
|
|
242
224
|
return {
|
|
243
|
-
threadStore,
|
|
244
225
|
threads,
|
|
245
226
|
currentThread,
|
|
246
227
|
isLoading,
|
|
@@ -254,4 +235,26 @@ const Sidebar = {
|
|
|
254
235
|
}
|
|
255
236
|
}
|
|
256
237
|
|
|
257
|
-
export default
|
|
238
|
+
export default {
|
|
239
|
+
install(ctx) {
|
|
240
|
+
ctx.components({
|
|
241
|
+
ThreadsSidebar,
|
|
242
|
+
ThreadItem,
|
|
243
|
+
GroupedThreads,
|
|
244
|
+
Recents,
|
|
245
|
+
})
|
|
246
|
+
ctx.routes.push(...[
|
|
247
|
+
{ path: '/recents', component: Recents },
|
|
248
|
+
])
|
|
249
|
+
ThreadStore.install(ctx)
|
|
250
|
+
|
|
251
|
+
ctx.setLayout({
|
|
252
|
+
left: 'ThreadsSidebar',
|
|
253
|
+
})
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
async load(ctx) {
|
|
257
|
+
const { initDB } = ctx.threads
|
|
258
|
+
await initDB()
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ref, computed, unref } from 'vue'
|
|
2
2
|
import { openDB } from 'idb'
|
|
3
|
-
import { nextId
|
|
3
|
+
import { nextId } from '../../utils.mjs'
|
|
4
4
|
|
|
5
5
|
// Thread store for managing chat threads with IndexedDB
|
|
6
6
|
const threads = ref([])
|
|
@@ -8,6 +8,7 @@ const currentThread = ref(null)
|
|
|
8
8
|
const isLoading = ref(false)
|
|
9
9
|
|
|
10
10
|
let db = null
|
|
11
|
+
let ctx = null
|
|
11
12
|
|
|
12
13
|
// Initialize IndexedDB
|
|
13
14
|
async function initDB() {
|
|
@@ -103,20 +104,22 @@ async function logRequest(threadId, model, request, response) {
|
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
// Create a new thread
|
|
106
|
-
async function createThread(
|
|
107
|
+
async function createThread(args = {}) {
|
|
107
108
|
await initDB()
|
|
108
109
|
|
|
109
110
|
const thread = {
|
|
110
111
|
id: generateThreadId(),
|
|
111
|
-
title: title,
|
|
112
|
-
model: model?.id ?? '',
|
|
113
|
-
info: toModelInfo(model),
|
|
114
|
-
systemPrompt: systemPrompt,
|
|
115
112
|
messages: [],
|
|
116
113
|
createdAt: new Date().toISOString(),
|
|
117
|
-
updatedAt: new Date().toISOString()
|
|
114
|
+
updatedAt: new Date().toISOString(),
|
|
115
|
+
...args
|
|
116
|
+
}
|
|
117
|
+
if (!thread.title) {
|
|
118
|
+
thread.title = 'New Chat'
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
ctx.createThreadFilters.forEach(f => f(thread))
|
|
122
|
+
|
|
120
123
|
try {
|
|
121
124
|
const tx = db.transaction(['threads'], 'readwrite')
|
|
122
125
|
await tx.objectStore('threads').add(thread)
|
|
@@ -148,6 +151,8 @@ async function updateThread(threadId, updates) {
|
|
|
148
151
|
updatedAt: new Date().toISOString()
|
|
149
152
|
}
|
|
150
153
|
|
|
154
|
+
ctx.updateThreadFilters.forEach(f => f(updatedThread))
|
|
155
|
+
|
|
151
156
|
await store.put(updatedThread)
|
|
152
157
|
await tx.complete
|
|
153
158
|
|
|
@@ -570,3 +575,12 @@ export function useThreadStore() {
|
|
|
570
575
|
getAllThreadIds,
|
|
571
576
|
}
|
|
572
577
|
}
|
|
578
|
+
|
|
579
|
+
export default {
|
|
580
|
+
install(context) {
|
|
581
|
+
ctx = context
|
|
582
|
+
ctx.setGlobals({
|
|
583
|
+
threads: useThreadStore()
|
|
584
|
+
})
|
|
585
|
+
}
|
|
586
|
+
}
|