llms-py 3.0.0b6__py3-none-any.whl → 3.0.0b7__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} +4 -2
- llms/extensions/core_tools/__init__.py +358 -0
- llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -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 +480 -0
- llms/extensions/providers/__init__.py +18 -0
- llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/{providers → 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 +1 -4
- 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 +284 -0
- llms/extensions/system_prompts/ui/prompts.json +1067 -0
- llms/{ui/modules/tools.mjs → extensions/tools/ui/index.mjs} +4 -2
- llms/llms.json +17 -1
- llms/main.py +381 -170
- llms/providers-extra.json +0 -32
- llms/ui/App.mjs +17 -18
- llms/ui/ai.mjs +10 -3
- llms/ui/app.css +1553 -24
- llms/ui/ctx.mjs +70 -12
- llms/ui/index.mjs +13 -8
- llms/ui/modules/chat/ChatBody.mjs +11 -248
- llms/ui/modules/chat/HomeTools.mjs +254 -0
- llms/ui/modules/chat/SettingsDialog.mjs +1 -1
- llms/ui/modules/chat/index.mjs +278 -174
- llms/ui/modules/layout.mjs +2 -26
- llms/ui/modules/model-selector.mjs +1 -1
- llms/ui/modules/threads/index.mjs +5 -11
- llms/ui/modules/threads/threadStore.mjs +56 -2
- llms/ui/utils.mjs +21 -3
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/METADATA +1 -1
- llms_py-3.0.0b7.dist-info/RECORD +80 -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_py-3.0.0b6.dist-info/RECORD +0 -66
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/WHEEL +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { ref, inject } from 'vue'
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
template: `
|
|
5
|
+
<!-- Export/Import buttons -->
|
|
6
|
+
<div class="mt-4 flex space-x-3 justify-center items-center">
|
|
7
|
+
<button type="button"
|
|
8
|
+
@click="(e) => e.altKey ? exportRequests() : exportThreads()"
|
|
9
|
+
:disabled="isExporting"
|
|
10
|
+
:title="'Export ' + threads?.threads?.value?.length + ' conversations'"
|
|
11
|
+
class="inline-flex items-center px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
12
|
+
>
|
|
13
|
+
<svg v-if="!isExporting" class="size-5 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
14
|
+
<path fill="currentColor" d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z"></path>
|
|
15
|
+
</svg>
|
|
16
|
+
<svg v-else class="size-5 mr-1 animate-spin" fill="none" viewBox="0 0 24 24">
|
|
17
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
18
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
19
|
+
</svg>
|
|
20
|
+
{{ isExporting ? 'Exporting...' : 'Export' }}
|
|
21
|
+
</button>
|
|
22
|
+
|
|
23
|
+
<button type="button"
|
|
24
|
+
@click="triggerImport"
|
|
25
|
+
:disabled="isImporting"
|
|
26
|
+
title="Import conversations from JSON file"
|
|
27
|
+
class="inline-flex items-center px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
28
|
+
>
|
|
29
|
+
<svg v-if="!isImporting" class="size-5 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
30
|
+
<path fill="currentColor" d="m14 12l-4-4v3H2v2h8v3m10 2V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v3h2V6h12v12H6v-3H4v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2"/>
|
|
31
|
+
</svg>
|
|
32
|
+
<svg v-else class="size-5 mr-1 animate-spin" fill="none" viewBox="0 0 24 24">
|
|
33
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
34
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
35
|
+
</svg>
|
|
36
|
+
{{ isImporting ? 'Importing...' : 'Import' }}
|
|
37
|
+
</button>
|
|
38
|
+
|
|
39
|
+
<!-- Hidden file input for import -->
|
|
40
|
+
<input
|
|
41
|
+
ref="fileInput"
|
|
42
|
+
type="file"
|
|
43
|
+
accept=".json"
|
|
44
|
+
@change="handleFileImport"
|
|
45
|
+
class="hidden"
|
|
46
|
+
/>
|
|
47
|
+
|
|
48
|
+
<DarkModeToggle />
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
`,
|
|
52
|
+
setup() {
|
|
53
|
+
const ctx = inject('ctx')
|
|
54
|
+
const threads = ctx.threads
|
|
55
|
+
|
|
56
|
+
const isExporting = ref(false)
|
|
57
|
+
const isImporting = ref(false)
|
|
58
|
+
const fileInput = ref(null)
|
|
59
|
+
|
|
60
|
+
async function exportThreads() {
|
|
61
|
+
if (isExporting.value) return
|
|
62
|
+
|
|
63
|
+
isExporting.value = true
|
|
64
|
+
try {
|
|
65
|
+
// Load all threads from IndexedDB
|
|
66
|
+
await threads.loadThreads()
|
|
67
|
+
const allThreads = threads.threads.value
|
|
68
|
+
|
|
69
|
+
// Create export data with metadata
|
|
70
|
+
const exportData = {
|
|
71
|
+
exportedAt: new Date().toISOString(),
|
|
72
|
+
version: '1.0',
|
|
73
|
+
source: 'llmspy',
|
|
74
|
+
threadCount: allThreads.length,
|
|
75
|
+
threads: allThreads
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Create and download JSON file
|
|
79
|
+
const jsonString = JSON.stringify(exportData, null, 2)
|
|
80
|
+
const blob = new Blob([jsonString], { type: 'application/json' })
|
|
81
|
+
const url = URL.createObjectURL(blob)
|
|
82
|
+
|
|
83
|
+
const link = document.createElement('a')
|
|
84
|
+
link.href = url
|
|
85
|
+
link.download = `llmsthreads-export-${new Date().toISOString().split('T')[0]}.json`
|
|
86
|
+
document.body.appendChild(link)
|
|
87
|
+
link.click()
|
|
88
|
+
document.body.removeChild(link)
|
|
89
|
+
URL.revokeObjectURL(url)
|
|
90
|
+
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('Failed to export threads:', error)
|
|
93
|
+
alert('Failed to export threads: ' + error.message)
|
|
94
|
+
} finally {
|
|
95
|
+
isExporting.value = false
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function exportRequests() {
|
|
100
|
+
if (isExporting.value) return
|
|
101
|
+
|
|
102
|
+
isExporting.value = true
|
|
103
|
+
try {
|
|
104
|
+
// Load all threads from IndexedDB
|
|
105
|
+
const allRequests = await threads.getAllRequests()
|
|
106
|
+
|
|
107
|
+
// Create export data with metadata
|
|
108
|
+
const exportData = {
|
|
109
|
+
exportedAt: new Date().toISOString(),
|
|
110
|
+
version: '1.0',
|
|
111
|
+
source: 'llmspy',
|
|
112
|
+
requestsCount: allRequests.length,
|
|
113
|
+
requests: allRequests
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Create and download JSON file
|
|
117
|
+
const jsonString = JSON.stringify(exportData, null, 2)
|
|
118
|
+
const blob = new Blob([jsonString], { type: 'application/json' })
|
|
119
|
+
const url = URL.createObjectURL(blob)
|
|
120
|
+
|
|
121
|
+
const link = document.createElement('a')
|
|
122
|
+
link.href = url
|
|
123
|
+
link.download = `llmsrequests-export-${new Date().toISOString().split('T')[0]}.json`
|
|
124
|
+
document.body.appendChild(link)
|
|
125
|
+
link.click()
|
|
126
|
+
document.body.removeChild(link)
|
|
127
|
+
URL.revokeObjectURL(url)
|
|
128
|
+
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('Failed to export requests:', error)
|
|
131
|
+
alert('Failed to export requests: ' + error.message)
|
|
132
|
+
} finally {
|
|
133
|
+
isExporting.value = false
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function triggerImport() {
|
|
138
|
+
if (isImporting.value) return
|
|
139
|
+
fileInput.value?.click()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function handleFileImport(event) {
|
|
143
|
+
const file = event.target.files?.[0]
|
|
144
|
+
if (!file) return
|
|
145
|
+
|
|
146
|
+
isImporting.value = true
|
|
147
|
+
var importType = 'threads'
|
|
148
|
+
try {
|
|
149
|
+
const text = await file.text()
|
|
150
|
+
const importData = JSON.parse(text)
|
|
151
|
+
importType = importData.threads
|
|
152
|
+
? 'threads'
|
|
153
|
+
: importData.requests
|
|
154
|
+
? 'requests'
|
|
155
|
+
: 'unknown'
|
|
156
|
+
|
|
157
|
+
// Import threads one by one
|
|
158
|
+
let importedCount = 0
|
|
159
|
+
let existingCount = 0
|
|
160
|
+
|
|
161
|
+
const db = await threads.initDB()
|
|
162
|
+
|
|
163
|
+
if (importData.threads) {
|
|
164
|
+
if (!Array.isArray(importData.threads)) {
|
|
165
|
+
throw new Error('Invalid import file: missing or invalid threads array')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const threadIds = new Set(await threads.getAllThreadIds())
|
|
169
|
+
|
|
170
|
+
for (const threadData of importData.threads) {
|
|
171
|
+
if (!threadData.id) {
|
|
172
|
+
console.warn('Skipping thread without ID:', threadData)
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
// Check if thread already exists
|
|
178
|
+
const existingThread = threadIds.has(threadData.id)
|
|
179
|
+
if (existingThread) {
|
|
180
|
+
existingCount++
|
|
181
|
+
} else {
|
|
182
|
+
// Add new thread directly to IndexedDB
|
|
183
|
+
const tx = db.transaction(['threads'], 'readwrite')
|
|
184
|
+
await tx.objectStore('threads').add(threadData)
|
|
185
|
+
await tx.complete
|
|
186
|
+
importedCount++
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error('Failed to import thread:', threadData.id, error)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Reload threads to reflect changes
|
|
194
|
+
await threads.loadThreads()
|
|
195
|
+
|
|
196
|
+
alert(`Import completed!\nNew threads: ${importedCount}\nExisting threads: ${existingCount}`)
|
|
197
|
+
}
|
|
198
|
+
if (importData.requests) {
|
|
199
|
+
if (!Array.isArray(importData.requests)) {
|
|
200
|
+
throw new Error('Invalid import file: missing or invalid requests array')
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const requestIds = new Set(await threads.getAllRequestIds())
|
|
204
|
+
|
|
205
|
+
for (const requestData of importData.requests) {
|
|
206
|
+
if (!requestData.id) {
|
|
207
|
+
console.warn('Skipping request without ID:', requestData)
|
|
208
|
+
continue
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
// Check if request already exists
|
|
213
|
+
const existingRequest = requestIds.has(requestData.id)
|
|
214
|
+
if (existingRequest) {
|
|
215
|
+
existingCount++
|
|
216
|
+
} else {
|
|
217
|
+
// Add new request directly to IndexedDB
|
|
218
|
+
const db = await threads.initDB()
|
|
219
|
+
const tx = db.transaction(['requests'], 'readwrite')
|
|
220
|
+
await tx.objectStore('requests').add(requestData)
|
|
221
|
+
await tx.complete
|
|
222
|
+
importedCount++
|
|
223
|
+
}
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error('Failed to import request:', requestData.id, error)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
alert(`Import completed!\nNew requests: ${importedCount}\nExisting requests: ${existingCount}`)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.error('Failed to import ' + importType + ':', error)
|
|
234
|
+
alert('Failed to import ' + importType + ': ' + error.message)
|
|
235
|
+
} finally {
|
|
236
|
+
isImporting.value = false
|
|
237
|
+
// Clear the file input
|
|
238
|
+
if (fileInput.value) {
|
|
239
|
+
fileInput.value.value = ''
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
exportThreads,
|
|
246
|
+
exportRequests,
|
|
247
|
+
isExporting,
|
|
248
|
+
triggerImport,
|
|
249
|
+
handleFileImport,
|
|
250
|
+
isImporting,
|
|
251
|
+
fileInput,
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -107,7 +107,7 @@ export function useSettings() {
|
|
|
107
107
|
|
|
108
108
|
export default {
|
|
109
109
|
template: `
|
|
110
|
-
<div v-if="isOpen" class="fixed inset-0 z-
|
|
110
|
+
<div v-if="isOpen" class="fixed inset-0 z-100 overflow-y-auto" @click.self="close">
|
|
111
111
|
<div class="flex min-h-screen items-center justify-center p-4">
|
|
112
112
|
<!-- Backdrop -->
|
|
113
113
|
<div class="fixed inset-0 bg-black/40 transition-opacity" @click="close"></div>
|