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.
Files changed (55) hide show
  1. llms/__pycache__/main.cpython-314.pyc +0 -0
  2. llms/{ui/modules/analytics.mjs → extensions/analytics/ui/index.mjs} +4 -2
  3. llms/extensions/core_tools/__init__.py +358 -0
  4. llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
  5. llms/extensions/gallery/__init__.py +61 -0
  6. llms/extensions/gallery/__pycache__/__init__.cpython-314.pyc +0 -0
  7. llms/extensions/gallery/__pycache__/db.cpython-314.pyc +0 -0
  8. llms/extensions/gallery/db.py +298 -0
  9. llms/extensions/gallery/ui/index.mjs +480 -0
  10. llms/extensions/providers/__init__.py +18 -0
  11. llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  12. llms/{providers → extensions/providers}/__pycache__/anthropic.cpython-314.pyc +0 -0
  13. llms/extensions/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  14. llms/extensions/providers/__pycache__/google.cpython-314.pyc +0 -0
  15. llms/{providers → extensions/providers}/__pycache__/nvidia.cpython-314.pyc +0 -0
  16. llms/{providers → extensions/providers}/__pycache__/openai.cpython-314.pyc +0 -0
  17. llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  18. llms/{providers → extensions/providers}/anthropic.py +1 -4
  19. llms/{providers → extensions/providers}/chutes.py +21 -18
  20. llms/{providers → extensions/providers}/google.py +99 -27
  21. llms/{providers → extensions/providers}/nvidia.py +6 -8
  22. llms/{providers → extensions/providers}/openai.py +3 -6
  23. llms/{providers → extensions/providers}/openrouter.py +12 -10
  24. llms/extensions/system_prompts/__init__.py +45 -0
  25. llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
  26. llms/extensions/system_prompts/ui/index.mjs +284 -0
  27. llms/extensions/system_prompts/ui/prompts.json +1067 -0
  28. llms/{ui/modules/tools.mjs → extensions/tools/ui/index.mjs} +4 -2
  29. llms/llms.json +17 -1
  30. llms/main.py +381 -170
  31. llms/providers-extra.json +0 -32
  32. llms/ui/App.mjs +17 -18
  33. llms/ui/ai.mjs +10 -3
  34. llms/ui/app.css +1553 -24
  35. llms/ui/ctx.mjs +70 -12
  36. llms/ui/index.mjs +13 -8
  37. llms/ui/modules/chat/ChatBody.mjs +11 -248
  38. llms/ui/modules/chat/HomeTools.mjs +254 -0
  39. llms/ui/modules/chat/SettingsDialog.mjs +1 -1
  40. llms/ui/modules/chat/index.mjs +278 -174
  41. llms/ui/modules/layout.mjs +2 -26
  42. llms/ui/modules/model-selector.mjs +1 -1
  43. llms/ui/modules/threads/index.mjs +5 -11
  44. llms/ui/modules/threads/threadStore.mjs +56 -2
  45. llms/ui/utils.mjs +21 -3
  46. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/METADATA +1 -1
  47. llms_py-3.0.0b7.dist-info/RECORD +80 -0
  48. llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  49. llms/providers/__pycache__/google.cpython-314.pyc +0 -0
  50. llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  51. llms_py-3.0.0b6.dist-info/RECORD +0 -66
  52. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/WHEEL +0 -0
  53. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/entry_points.txt +0 -0
  54. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b7.dist-info}/licenses/LICENSE +0 -0
  55. {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-50 overflow-y-auto" @click.self="close">
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>