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.
Files changed (181) hide show
  1. llms/__pycache__/main.cpython-314.pyc +0 -0
  2. llms/{ui/modules/analytics.mjs → extensions/analytics/ui/index.mjs} +55 -164
  3. llms/extensions/app/__init__.py +519 -0
  4. llms/extensions/app/__pycache__/__init__.cpython-314.pyc +0 -0
  5. llms/extensions/app/__pycache__/db.cpython-314.pyc +0 -0
  6. llms/extensions/app/__pycache__/db_manager.cpython-314.pyc +0 -0
  7. llms/extensions/app/db.py +641 -0
  8. llms/extensions/app/db_manager.py +195 -0
  9. llms/extensions/app/requests.json +9073 -0
  10. llms/extensions/app/threads.json +15290 -0
  11. llms/{ui/modules/threads → extensions/app/ui}/Recents.mjs +82 -55
  12. llms/{ui/modules/threads → extensions/app/ui}/index.mjs +83 -20
  13. llms/extensions/app/ui/threadStore.mjs +407 -0
  14. llms/extensions/core_tools/__init__.py +598 -0
  15. llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
  16. llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +201 -0
  17. llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +185 -0
  18. llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +101 -0
  19. llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +160 -0
  20. llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +66 -0
  21. llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +27 -0
  22. llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +72 -0
  23. llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +119 -0
  24. llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +98 -0
  25. llms/extensions/core_tools/ui/codemirror/doc/docs.css +225 -0
  26. llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
  27. llms/extensions/core_tools/ui/codemirror/lib/codemirror.css +344 -0
  28. llms/extensions/core_tools/ui/codemirror/lib/codemirror.js +9884 -0
  29. llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +942 -0
  30. llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +118 -0
  31. llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +962 -0
  32. llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +62 -0
  33. llms/extensions/core_tools/ui/codemirror/mode/python/python.js +402 -0
  34. llms/extensions/core_tools/ui/codemirror/theme/dracula.css +40 -0
  35. llms/extensions/core_tools/ui/codemirror/theme/mocha.css +135 -0
  36. llms/extensions/core_tools/ui/index.mjs +650 -0
  37. llms/extensions/gallery/__init__.py +61 -0
  38. llms/extensions/gallery/__pycache__/__init__.cpython-314.pyc +0 -0
  39. llms/extensions/gallery/__pycache__/db.cpython-314.pyc +0 -0
  40. llms/extensions/gallery/db.py +298 -0
  41. llms/extensions/gallery/ui/index.mjs +481 -0
  42. llms/extensions/katex/__init__.py +6 -0
  43. llms/extensions/katex/__pycache__/__init__.cpython-314.pyc +0 -0
  44. llms/extensions/katex/ui/README.md +125 -0
  45. llms/extensions/katex/ui/contrib/auto-render.js +338 -0
  46. llms/extensions/katex/ui/contrib/auto-render.min.js +1 -0
  47. llms/extensions/katex/ui/contrib/auto-render.mjs +244 -0
  48. llms/extensions/katex/ui/contrib/copy-tex.js +127 -0
  49. llms/extensions/katex/ui/contrib/copy-tex.min.js +1 -0
  50. llms/extensions/katex/ui/contrib/copy-tex.mjs +105 -0
  51. llms/extensions/katex/ui/contrib/mathtex-script-type.js +109 -0
  52. llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +1 -0
  53. llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +24 -0
  54. llms/extensions/katex/ui/contrib/mhchem.js +3213 -0
  55. llms/extensions/katex/ui/contrib/mhchem.min.js +1 -0
  56. llms/extensions/katex/ui/contrib/mhchem.mjs +3109 -0
  57. llms/extensions/katex/ui/contrib/render-a11y-string.js +887 -0
  58. llms/extensions/katex/ui/contrib/render-a11y-string.min.js +1 -0
  59. llms/extensions/katex/ui/contrib/render-a11y-string.mjs +800 -0
  60. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
  61. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
  62. llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  63. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  64. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  65. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  66. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  67. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  68. llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  69. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  70. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  71. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  72. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  73. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  74. llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  75. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
  76. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
  77. llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
  78. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  79. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  80. llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  81. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
  82. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
  83. llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
  84. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
  85. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
  86. llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
  87. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  88. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  89. llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  90. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
  91. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
  92. llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
  93. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  94. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  95. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  96. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  97. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  98. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  99. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  100. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  101. llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  102. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
  103. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
  104. llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
  105. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
  106. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
  107. llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  108. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
  109. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
  110. llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  111. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
  112. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
  113. llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  114. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
  115. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
  116. llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  117. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  118. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  119. llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  120. llms/extensions/katex/ui/index.mjs +92 -0
  121. llms/extensions/katex/ui/katex-swap.css +1230 -0
  122. llms/extensions/katex/ui/katex-swap.min.css +1 -0
  123. llms/extensions/katex/ui/katex.css +1230 -0
  124. llms/extensions/katex/ui/katex.js +19080 -0
  125. llms/extensions/katex/ui/katex.min.css +1 -0
  126. llms/extensions/katex/ui/katex.min.js +1 -0
  127. llms/extensions/katex/ui/katex.min.mjs +1 -0
  128. llms/extensions/katex/ui/katex.mjs +18547 -0
  129. llms/extensions/providers/__init__.py +18 -0
  130. llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  131. llms/extensions/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  132. llms/extensions/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  133. llms/extensions/providers/__pycache__/google.cpython-314.pyc +0 -0
  134. llms/{providers → extensions/providers}/__pycache__/nvidia.cpython-314.pyc +0 -0
  135. llms/{providers → extensions/providers}/__pycache__/openai.cpython-314.pyc +0 -0
  136. llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  137. llms/{providers → extensions/providers}/anthropic.py +45 -5
  138. llms/{providers → extensions/providers}/chutes.py +21 -18
  139. llms/{providers → extensions/providers}/google.py +99 -27
  140. llms/{providers → extensions/providers}/nvidia.py +6 -8
  141. llms/{providers → extensions/providers}/openai.py +3 -6
  142. llms/{providers → extensions/providers}/openrouter.py +12 -10
  143. llms/extensions/system_prompts/__init__.py +45 -0
  144. llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
  145. llms/extensions/system_prompts/ui/index.mjs +285 -0
  146. llms/extensions/system_prompts/ui/prompts.json +1067 -0
  147. llms/extensions/tools/__init__.py +5 -0
  148. llms/extensions/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  149. llms/{ui/modules/tools.mjs → extensions/tools/ui/index.mjs} +12 -10
  150. llms/index.html +26 -38
  151. llms/llms.json +20 -1
  152. llms/main.py +845 -245
  153. llms/providers-extra.json +0 -32
  154. llms/ui/App.mjs +18 -20
  155. llms/ui/ai.mjs +38 -15
  156. llms/ui/app.css +1440 -59
  157. llms/ui/ctx.mjs +154 -18
  158. llms/ui/index.mjs +17 -14
  159. llms/ui/lib/vue.min.mjs +10 -9
  160. llms/ui/lib/vue.mjs +1796 -1635
  161. llms/ui/markdown.mjs +4 -2
  162. llms/ui/modules/chat/ChatBody.mjs +101 -334
  163. llms/ui/modules/chat/HomeTools.mjs +12 -0
  164. llms/ui/modules/chat/SettingsDialog.mjs +1 -1
  165. llms/ui/modules/chat/index.mjs +351 -314
  166. llms/ui/modules/layout.mjs +2 -26
  167. llms/ui/modules/model-selector.mjs +3 -3
  168. llms/ui/tailwind.input.css +35 -1
  169. llms/ui/utils.mjs +33 -3
  170. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/METADATA +1 -1
  171. llms_py-3.0.0b8.dist-info/RECORD +198 -0
  172. llms/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  173. llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  174. llms/providers/__pycache__/google.cpython-314.pyc +0 -0
  175. llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  176. llms/ui/modules/threads/threadStore.mjs +0 -586
  177. llms_py-3.0.0b6.dist-info/RECORD +0 -66
  178. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/WHEEL +0 -0
  179. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/entry_points.txt +0 -0
  180. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/licenses/LICENSE +0 -0
  181. {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/top_level.txt +0 -0
@@ -1,586 +0,0 @@
1
- import { ref, computed, unref } from 'vue'
2
- import { openDB } from 'idb'
3
- import { nextId } from '../../utils.mjs'
4
-
5
- // Thread store for managing chat threads with IndexedDB
6
- const threads = ref([])
7
- const currentThread = ref(null)
8
- const isLoading = ref(false)
9
-
10
- let db = null
11
- let ctx = null
12
-
13
- // Initialize IndexedDB
14
- async function initDB() {
15
- if (db) return db
16
-
17
- db = await openDB('LlmsThreads', 3, {
18
- upgrade(db, _oldVersion, _newVersion, transaction) {
19
- if (!db.objectStoreNames.contains('threads')) {
20
- // Create threads store
21
- const threadStore = db.createObjectStore('threads', {
22
- keyPath: 'id',
23
- autoIncrement: false
24
- })
25
-
26
- // Create indexes for efficient querying
27
- threadStore.createIndex('createdAt', 'createdAt')
28
- threadStore.createIndex('updatedAt', 'updatedAt')
29
- threadStore.createIndex('title', 'title')
30
- }
31
- if (!db.objectStoreNames.contains('requests')) {
32
- // Create requests store
33
- const requestStore = db.createObjectStore('requests', {
34
- keyPath: 'id',
35
- autoIncrement: false
36
- })
37
- requestStore.createIndex('threadId', 'threadId')
38
- requestStore.createIndex('model', 'model')
39
- requestStore.createIndex('provider', 'provider')
40
- requestStore.createIndex('inputTokens', 'inputTokens')
41
- requestStore.createIndex('outputTokens', 'outputTokens')
42
- requestStore.createIndex('cost', 'cost')
43
- requestStore.createIndex('duration', 'duration')
44
- requestStore.createIndex('created', 'created')
45
- }
46
- }
47
- })
48
-
49
- return db
50
- }
51
-
52
- // Generate unique thread ID
53
- function generateThreadId() {
54
- return Date.now().toString()
55
- }
56
-
57
- async function logRequest(threadId, model, request, response) {
58
- await initDB()
59
- const metadata = response.metadata || {}
60
- const usage = response.usage || {}
61
- const [inputPrice, outputPrice] = metadata.pricing ? metadata.pricing.split('/') : [0, 0]
62
- const lastUserContent = request.messages?.slice().reverse().find(m => m.role === 'user')?.content
63
- const content = Array.isArray(lastUserContent)
64
- ? lastUserContent.filter(c => c?.text).map(c => c.text).join(' ')
65
- : lastUserContent
66
- const title = content.slice(0, 100) + (content.length > 100 ? '...' : '')
67
- const inputTokens = usage?.prompt_tokens ?? 0
68
- const outputTokens = usage?.completion_tokens ?? 0
69
- const inputCachedTokens = usage?.prompt_token_details?.cached_tokens ?? 0
70
- const finishReason = response.choices[0]?.finish_reason || 'unknown'
71
-
72
- const subtractDays = (date, days) => {
73
- const result = new Date(date * 1000)
74
- result.setDate(result.getDate() - days)
75
- return parseInt(result.valueOf() / 1000)
76
- }
77
-
78
- const log = {
79
- id: nextId(),
80
- threadId: threadId,
81
- model: model.id,
82
- provider: model.provider,
83
- providerModel: response.model || model.provider_model,
84
- title,
85
- inputTokens,
86
- outputTokens,
87
- inputCachedTokens,
88
- totalTokens: usage.total_tokens ?? (inputTokens + outputTokens),
89
- inputPrice,
90
- outputPrice,
91
- cost: (parseFloat(inputPrice) * inputTokens / 1_000_000) + (parseFloat(outputPrice) * outputTokens / 1_000_000),
92
- duration: parseInt(metadata.duration) || 0,
93
- created: response.created ?? Math.floor(Date.now() / 1000),
94
- finishReason,
95
- providerRef: response.provider,
96
- ref: response.id || undefined,
97
- usage: usage,
98
- }
99
- console.debug('logRequest', log)
100
- const tx = db.transaction(['requests'], 'readwrite')
101
- await tx.objectStore('requests').add(log)
102
- await tx.complete
103
- return log
104
- }
105
-
106
- // Create a new thread
107
- async function createThread(args = {}) {
108
- await initDB()
109
-
110
- const thread = {
111
- id: generateThreadId(),
112
- messages: [],
113
- createdAt: new Date().toISOString(),
114
- updatedAt: new Date().toISOString(),
115
- ...args
116
- }
117
- if (!thread.title) {
118
- thread.title = 'New Chat'
119
- }
120
-
121
- ctx.createThreadFilters.forEach(f => f(thread))
122
-
123
- try {
124
- const tx = db.transaction(['threads'], 'readwrite')
125
- await tx.objectStore('threads').add(thread)
126
- await tx.complete
127
-
128
- threads.value.unshift(thread)
129
- // Note: currentThread will be set by router navigation
130
-
131
- } catch (e) {
132
- console.error('Error creating thread', e, thread)
133
- }
134
-
135
- return thread
136
- }
137
-
138
- // Update thread
139
- async function updateThread(threadId, updates) {
140
- await initDB()
141
-
142
- const tx = db.transaction(['threads'], 'readwrite')
143
- const store = tx.objectStore('threads')
144
-
145
- const thread = await store.get(threadId)
146
- if (!thread) throw new Error('Thread not found')
147
-
148
- const updatedThread = {
149
- ...thread,
150
- ...updates,
151
- updatedAt: new Date().toISOString()
152
- }
153
-
154
- ctx.updateThreadFilters.forEach(f => f(updatedThread))
155
-
156
- await store.put(updatedThread)
157
- await tx.complete
158
-
159
- // Update in memory
160
- const index = threads.value.findIndex(t => t.id === threadId)
161
- if (index !== -1) {
162
- threads.value[index] = updatedThread
163
- }
164
-
165
- if (currentThread.value?.id === threadId) {
166
- currentThread.value = updatedThread
167
- }
168
-
169
- return updatedThread
170
- }
171
-
172
- async function calculateThreadStats(threadId) {
173
- await initDB()
174
-
175
- const tx = db.transaction(['requests'], 'readonly')
176
- const store = tx.objectStore('requests')
177
- const index = store.index('threadId')
178
-
179
- const requests = await index.getAll(threadId)
180
-
181
- let inputTokens = 0
182
- let outputTokens = 0
183
- let cost = 0.0
184
- let duration = 0
185
-
186
- requests.forEach(req => {
187
- inputTokens += req.inputTokens || 0
188
- outputTokens += req.outputTokens || 0
189
- cost += req.cost || 0.0
190
- duration += req.duration || 0
191
- })
192
-
193
- return {
194
- inputTokens,
195
- outputTokens,
196
- cost,
197
- duration,
198
- requests: requests.length
199
- }
200
- }
201
-
202
- // Add message to thread
203
- async function addMessageToThread(threadId, message, usage) {
204
- const thread = await getThread(threadId)
205
- if (!thread) throw new Error('Thread not found')
206
-
207
- const newMessage = {
208
- id: nextId(),
209
- timestamp: new Date().toISOString(),
210
- ...message
211
- }
212
-
213
- // Add input and output token usage to previous 'input' message
214
- if (usage?.prompt_tokens != null) {
215
- const lastMessage = thread.messages[thread.messages.length - 1]
216
- if (lastMessage && lastMessage.role === 'user') {
217
- lastMessage.usage = {
218
- tokens: parseInt(usage.prompt_tokens),
219
- price: usage.input || '0',
220
- }
221
- }
222
- }
223
- if (usage?.completion_tokens != null) {
224
- newMessage.usage = {
225
- tokens: parseInt(usage.completion_tokens),
226
- price: usage.output || '0',
227
- duration: usage.duration || undefined,
228
- }
229
- }
230
-
231
- const updatedMessages = [...thread.messages, newMessage]
232
-
233
- // Auto-generate title from first user message if still "New Chat"
234
- let title = thread.title
235
- if (title === 'New Chat' && message.role === 'user' && updatedMessages.length <= 2) {
236
- let contentText = message.content
237
- if (Array.isArray(contentText)) {
238
- contentText = contentText.filter(c => c.type === 'text').map(c => c.text).join(' ')
239
- }
240
- title = contentText.slice(0, 200) + (contentText.length > 200 ? '...' : '')
241
- }
242
-
243
- const stats = await calculateThreadStats(threadId)
244
-
245
- await updateThread(threadId, {
246
- messages: updatedMessages,
247
- title: title,
248
- stats,
249
- })
250
-
251
- return newMessage
252
- }
253
-
254
- async function deleteMessageFromThread(threadId, messageId) {
255
- const thread = await getThread(threadId)
256
- if (!thread) throw new Error('Thread not found')
257
- const updatedMessages = thread.messages.filter(m => m.id !== messageId)
258
- await updateThread(threadId, { messages: updatedMessages })
259
- }
260
-
261
- async function updateMessageInThread(threadId, messageId, updates) {
262
- const thread = await getThread(threadId)
263
- if (!thread) throw new Error('Thread not found')
264
-
265
- const messageIndex = thread.messages.findIndex(m => m.id === messageId)
266
- if (messageIndex === -1) throw new Error('Message not found')
267
-
268
- const updatedMessages = [...thread.messages]
269
- updatedMessages[messageIndex] = {
270
- ...updatedMessages[messageIndex],
271
- ...updates
272
- }
273
-
274
- await updateThread(threadId, { messages: updatedMessages })
275
- }
276
-
277
- async function redoMessageFromThread(threadId, messageId) {
278
- const thread = await getThread(threadId)
279
- if (!thread) throw new Error('Thread not found')
280
-
281
- // Find the index of the message to redo
282
- const messageIndex = thread.messages.findIndex(m => m.id === messageId)
283
- if (messageIndex === -1) throw new Error('Message not found')
284
-
285
- // Keep only messages up to and including the target message
286
- const updatedMessages = thread.messages.slice(0, messageIndex + 1)
287
-
288
- // Update the thread with the new messages
289
- await updateThread(threadId, { messages: updatedMessages })
290
- }
291
-
292
- // Get all threads
293
- async function loadThreads() {
294
- await initDB()
295
- isLoading.value = true
296
-
297
- try {
298
- const tx = db.transaction(['threads'], 'readonly')
299
- const store = tx.objectStore('threads')
300
- const index = store.index('updatedAt')
301
-
302
- const allThreads = await index.getAll()
303
- threads.value = allThreads.reverse() // Most recent first
304
-
305
- return threads.value
306
- } finally {
307
- isLoading.value = false
308
- }
309
- }
310
-
311
- // Get single thread
312
- async function getThread(threadId) {
313
- await initDB()
314
-
315
- const tx = db.transaction(['threads'], 'readonly')
316
- const thread = await tx.objectStore('threads').get(threadId)
317
-
318
- return thread
319
- }
320
-
321
- // Delete thread
322
- async function deleteThread(threadId) {
323
- await initDB()
324
-
325
- const tx = db.transaction(['threads'], 'readwrite')
326
- await tx.objectStore('threads').delete(threadId)
327
- await tx.complete
328
-
329
- threads.value = threads.value.filter(t => t.id !== threadId)
330
-
331
- if (currentThread.value?.id === threadId) {
332
- currentThread.value = null
333
- }
334
- }
335
-
336
- // Set current thread
337
- async function setCurrentThread(threadId) {
338
- const thread = await getThread(threadId)
339
- if (thread) {
340
- currentThread.value = thread
341
- }
342
- return thread
343
- }
344
-
345
- // Set current thread from router params (router-aware version)
346
- async function setCurrentThreadFromRoute(threadId, router) {
347
- if (!threadId) {
348
- currentThread.value = null
349
- return null
350
- }
351
-
352
- const thread = await getThread(threadId)
353
- if (thread) {
354
- currentThread.value = thread
355
- return thread
356
- } else {
357
- // Thread not found, redirect to home
358
- if (router) {
359
- router.push((globalThis.ai?.base || '') + '/')
360
- }
361
- currentThread.value = null
362
- return null
363
- }
364
- }
365
-
366
- // Clear current thread (go back to initial state)
367
- function clearCurrentThread() {
368
- currentThread.value = null
369
- }
370
-
371
- function getGroupedThreads(total) {
372
- const now = new Date()
373
- const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
374
- const lastWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000)
375
- const lastMonth = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000)
376
-
377
- const groups = {
378
- today: [],
379
- lastWeek: [],
380
- lastMonth: [],
381
- older: {}
382
- }
383
-
384
- const takeThreads = threads.value.slice(0, total)
385
-
386
- takeThreads.forEach(thread => {
387
- const threadDate = new Date(thread.updatedAt)
388
-
389
- if (threadDate >= today) {
390
- groups.today.push(thread)
391
- } else if (threadDate >= lastWeek) {
392
- groups.lastWeek.push(thread)
393
- } else if (threadDate >= lastMonth) {
394
- groups.lastMonth.push(thread)
395
- } else {
396
- const year = threadDate.getFullYear()
397
- const month = threadDate.toLocaleString('default', { month: 'long' })
398
- const key = `${month} ${year}`
399
-
400
- if (!groups.older[key]) {
401
- groups.older[key] = []
402
- }
403
- groups.older[key].push(thread)
404
- }
405
- })
406
-
407
- return groups
408
- }
409
-
410
- // Group threads by time periods
411
- const groupedThreads = computed(() => getGroupedThreads(threads.value.length))
412
-
413
- async function getAllRequests() {
414
- await initDB()
415
-
416
- const tx = db.transaction(['requests'], 'readonly')
417
- const store = tx.objectStore('requests')
418
- const allRequests = await store.getAll()
419
- return allRequests
420
- }
421
-
422
- async function getRequest(requestId) {
423
- await initDB()
424
-
425
- const tx = db.transaction(['requests'], 'readonly')
426
- const store = tx.objectStore('requests')
427
- const request = await store.get(requestId)
428
- return request
429
- }
430
-
431
- async function getAllRequestIds() {
432
- await initDB()
433
-
434
- const tx = db.transaction(['requests'], 'readonly')
435
- const store = tx.objectStore('requests')
436
- const ids = await store.getAllKeys()
437
- return ids
438
- }
439
-
440
- async function getAllThreadIds() {
441
- await initDB()
442
- const tx = db.transaction(['threads'], 'readonly')
443
- const store = tx.objectStore('threads')
444
- const ids = await store.getAllKeys()
445
- return ids
446
- }
447
-
448
- // Query requests with pagination and filtering
449
- async function getRequests(filters = {}, limit = 20, offset = 0) {
450
- try {
451
- await initDB()
452
-
453
- const {
454
- model = null,
455
- provider = null,
456
- threadId = null,
457
- sortBy = 'created',
458
- sortOrder = 'desc',
459
- startDate = null,
460
- endDate = null
461
- } = filters
462
-
463
- const tx = db.transaction(['requests'], 'readonly')
464
- const store = tx.objectStore('requests')
465
-
466
- // Get all requests and filter in memory (IndexedDB limitations)
467
- const allRequests = await store.getAll()
468
-
469
- // Apply filters
470
- let results = allRequests.filter(req => {
471
- if (model && req.model !== model) return false
472
- if (provider && req.provider !== provider) return false
473
- if (threadId && req.threadId !== threadId) return false
474
- if (startDate && req.created < startDate) return false
475
- if (endDate && req.created > endDate) return false
476
- return true
477
- })
478
-
479
- // Sort
480
- results.sort((a, b) => {
481
- let aVal = a[sortBy]
482
- let bVal = b[sortBy]
483
-
484
- if (sortOrder === 'desc') {
485
- return bVal - aVal
486
- } else {
487
- return aVal - bVal
488
- }
489
- })
490
-
491
- // Paginate
492
- const total = results.length
493
- const paginatedResults = results.slice(offset, offset + limit)
494
-
495
- return {
496
- requests: paginatedResults,
497
- total,
498
- hasMore: offset + limit < total
499
- }
500
- } catch (error) {
501
- console.error('Error in getRequests:', error)
502
- return {
503
- requests: [],
504
- total: 0,
505
- hasMore: false
506
- }
507
- }
508
- }
509
-
510
- // Get unique values for filter options
511
- async function getFilterOptions() {
512
- try {
513
- await initDB()
514
-
515
- const tx = db.transaction(['requests'], 'readonly')
516
- const store = tx.objectStore('requests')
517
- const allRequests = await store.getAll()
518
-
519
- const models = [...new Set(allRequests.map(r => r.model).filter(m => m))].sort()
520
- const providers = [...new Set(allRequests.map(r => r.provider).filter(p => p))].sort()
521
-
522
- return {
523
- models,
524
- providers
525
- }
526
- } catch (error) {
527
- console.error('Error in getFilterOptions:', error)
528
- return {
529
- models: [],
530
- providers: []
531
- }
532
- }
533
- }
534
-
535
- // Delete a request by ID
536
- async function deleteRequest(requestId) {
537
- await initDB()
538
-
539
- const tx = db.transaction(['requests'], 'readwrite')
540
- await tx.objectStore('requests').delete(requestId)
541
- await tx.complete
542
- }
543
-
544
- // Export the store
545
- export function useThreadStore() {
546
- return {
547
- // State
548
- threads,
549
- currentThread,
550
- isLoading,
551
- groupedThreads,
552
-
553
- // Actions
554
- initDB,
555
- logRequest,
556
- createThread,
557
- updateThread,
558
- addMessageToThread,
559
- deleteMessageFromThread,
560
- updateMessageInThread,
561
- redoMessageFromThread,
562
- loadThreads,
563
- getThread,
564
- deleteThread,
565
- setCurrentThread,
566
- setCurrentThreadFromRoute,
567
- clearCurrentThread,
568
- getGroupedThreads,
569
- getRequest,
570
- getRequests,
571
- getAllRequests,
572
- getFilterOptions,
573
- deleteRequest,
574
- getAllRequestIds,
575
- getAllThreadIds,
576
- }
577
- }
578
-
579
- export default {
580
- install(context) {
581
- ctx = context
582
- ctx.setGlobals({
583
- threads: useThreadStore()
584
- })
585
- }
586
- }
@@ -1,66 +0,0 @@
1
- llms/__init__.py,sha256=DKwTZDsyYL_wHe7yvLw49Nf8PSgPSyWaeVdotUqSvrQ,84
2
- llms/__main__.py,sha256=hrBulHIt3lmPm1BCyAEVtB6DQ0Hvc3gnIddhHCmJasg,151
3
- llms/index.html,sha256=gABCGg8ALHyB8OSH745HXx7U0SrXuNtJry9buUbVDik,2117
4
- llms/llms.json,sha256=j7CmFdMpzNeo0nCPHHR4djYfzH_AFKKYIAH3cL3TKT8,10641
5
- llms/main.py,sha256=H6fZ0WwMwULC6xf0kX_tVZ8sqTWUBzqmJdG0C28SjDo,130535
6
- llms/providers-extra.json,sha256=rBVTg46s5bJ6ou9H45FW0RW1mvbW_cKMnjWQBgz-gUI,11107
7
- llms/providers.json,sha256=mP4vQ37LeRAZCpT3WPO2GZaZ3YsXodXBV5OVbVMBAmo,256222
8
- llms/__pycache__/__init__.cpython-312.pyc,sha256=lg2oFc0aKgj536NOJxcIpbCpEWi47ptF8NufPphgUUk,204
9
- llms/__pycache__/__init__.cpython-313.pyc,sha256=DvmykIYAjV4Xjv5NeC70BA0JIX8qtwEWP2dfzmOBrps,173
10
- llms/__pycache__/__init__.cpython-314.pyc,sha256=9CxeBz41D_-ezno6pIOsnoMAFzdRX2uZjKkBLUm25RQ,206
11
- llms/__pycache__/__main__.cpython-312.pyc,sha256=fcu9LVl5nfdSzg9HqoKyDGoDvENeIXKkjygN7FENEGE,321
12
- llms/__pycache__/__main__.cpython-314.pyc,sha256=IFxtGVpJq_3whKuM5Ln7YMweKFNbHVp8M7VSrLK5h2A,324
13
- llms/__pycache__/llms.cpython-312.pyc,sha256=S5dFI79JdUe2dQW4ogdB-CCNhudQeFaFGcfKxgJGBms,72080
14
- llms/__pycache__/main.cpython-312.pyc,sha256=HrqApYAiiBmYN73HIx_Hl2-Xm1Gy7I_0zuR5j86qoRM,104940
15
- llms/__pycache__/main.cpython-313.pyc,sha256=6NQ__SJ2rC9ItFLKLHL5ewb5RqxLzZabwgczA9wZd-w,74814
16
- llms/__pycache__/main.cpython-314.pyc,sha256=_qekyxUhkFTtuqCXUUinQMkbHVgOQggu6kZ13yrAtSc,167444
17
- llms/__pycache__/plugins.cpython-314.pyc,sha256=fer8nTkidG_vQSx80tL2bAvMS0opDom93bewjseFcyg,3560
18
- llms/providers/anthropic.py,sha256=KBwIPkGFkNCJxlLAY5MzFpEj7AB4d0WwpaOfZfvCrk0,8091
19
- llms/providers/chutes.py,sha256=TTDfWviHOoNfk2cXnY5UJK_fciRJ2drfz48u67TDmCM,6171
20
- llms/providers/google.py,sha256=aK9t7iPLmziUx7q6blF_G2MQUHFA1h8t461euxWWtVc,15104
21
- llms/providers/nvidia.py,sha256=HRcI1-fgMGq5_9s6br9YHVVOIaXRtOGCgUPSCHXB-_0,4355
22
- llms/providers/openai.py,sha256=zQqxXyF9v7CplmzebFIXd-Xfj7AcP_bIK6G8fPZh2p8,6355
23
- llms/providers/openrouter.py,sha256=unXvR2KMsosWJe8_7k-JhDM8V_XtVUtnNO2psgtkTNk,3055
24
- llms/providers/__pycache__/anthropic.cpython-314.pyc,sha256=tRLB3xJoPi0dLXY85JgXcD_DHIwhBcScx08NiHTiwdw,9158
25
- llms/providers/__pycache__/chutes.cpython-314.pyc,sha256=TFAoyWV3rwvmcVi17ACgdqPY0Vh_kITFJ-IOGAtZp8w,7404
26
- llms/providers/__pycache__/google.cpython-314.pyc,sha256=mprVq3i-Ma9La9EgUcUh7AXUaPWTBn6STM-w2LZN2Tc,13858
27
- llms/providers/__pycache__/nvidia.cpython-314.pyc,sha256=pE2P5sz0EjRp3DYy-MiEAf_kq3Ns03Q0f-DQGa8UOXQ,6155
28
- llms/providers/__pycache__/openai.cpython-314.pyc,sha256=-OnbDtGalUx3NtRU_sAwRL_TvrnKOworTliwS164IUY,8705
29
- llms/providers/__pycache__/openrouter.cpython-314.pyc,sha256=5zAegKxy40P1uX87T9KhaE5s54UXSq9fjsG0i2n84tc,5078
30
- llms/ui/App.mjs,sha256=PYdiU3hkn7nHbRVURpN0ruLMfPDulTCWb-BIe0-PT_I,7188
31
- llms/ui/ai.mjs,sha256=4I2MECybgh8nLm1oLSEJKbpW1KZ0mYkzgYOBUygKmfA,5315
32
- llms/ui/app.css,sha256=Tc3JVtpEkXnE0H2cyAmE5bhF96eUsVzBHFqAJAODawc,124819
33
- llms/ui/ctx.mjs,sha256=j8zHy08DWAXkmaNBBkcr6Fs-D7uApTIArsA0QqXl7OM,6395
34
- llms/ui/fav.svg,sha256=_R6MFeXl6wBFT0lqcUxYQIDWgm246YH_3hSTW0oO8qw,734
35
- llms/ui/index.mjs,sha256=-GTK8ftHEiCygv3dWVUdHlqGW7JoE0aLURYQmJ706aY,4171
36
- llms/ui/markdown.mjs,sha256=WcYnT7xZFOc-TXbghVGSBjQJdLGTXq9vZ1LEIaYdcao,6611
37
- llms/ui/tailwind.input.css,sha256=1CMKv3_YkX9q2w0yNAjmvcOIHArvLtreoSt6TZ7OM1w,15067
38
- llms/ui/typography.css,sha256=6o7pbMIamRVlm2GfzSStpcOG4T5eFCK_WcQ3RIHKAsU,19587
39
- llms/ui/utils.mjs,sha256=gbv8oCHP39GHEKt-oLZ-ZBMrkGd7bPRuTkYu4ggim1k,5401
40
- llms/ui/lib/chart.js,sha256=dx8FdDX0Rv6OZtZjr9FQh5h-twFsKjfnb-FvFlQ--cU,196176
41
- llms/ui/lib/charts.mjs,sha256=OPFAifcA4MPRv8pw6I7glVh7Xccv8guio0k35zPBDIY,926
42
- llms/ui/lib/color.js,sha256=DDG7Pr-qzJHTPISZNSqP_qJR8UflKHEc_56n6xrBugQ,8273
43
- llms/ui/lib/highlight.min.mjs,sha256=sG7wq8bF-IKkfie7S4QSyh5DdHBRf0NqQxMOEH8-MT0,127458
44
- llms/ui/lib/idb.min.mjs,sha256=CeTXyV4I_pB5vnibvJuyXdMs0iVF2ZL0Z7cdm3w_QaI,3853
45
- llms/ui/lib/marked.min.mjs,sha256=QRHb_VZugcBJRD2EP6gYlVFEsJw5C2fQ8ImMf_pA2_s,39488
46
- llms/ui/lib/servicestack-client.mjs,sha256=UVafVbzhJ_0N2lzv7rlzIbzwnWpoqXxGk3N3FSKgOOc,54534
47
- llms/ui/lib/servicestack-vue.mjs,sha256=4XxQLaKm26aexbY7lYTSMRmjZmBRzZgq7F8GZquuGrs,216947
48
- llms/ui/lib/vue-router.min.mjs,sha256=fR30GHoXI1u81zyZ26YEU105pZgbbAKSXbpnzFKIxls,30418
49
- llms/ui/lib/vue.min.mjs,sha256=iXh97m5hotl0eFllb3aoasQTImvp7mQoRJ_0HoxmZkw,163811
50
- llms/ui/lib/vue.mjs,sha256=dS8LKOG01t9CvZ04i0tbFXHqFXOO_Ha4NmM3BytjQAs,537071
51
- llms/ui/modules/analytics.mjs,sha256=uDotilFz7V4Bl-tCFaOnCvx-S0SGnM5vvPZ1xEytIAk,74167
52
- llms/ui/modules/layout.mjs,sha256=WTy85_8rSyBQooo2f5baw98RzNhpecw4pDpfhEgKv4s,12105
53
- llms/ui/modules/model-selector.mjs,sha256=dekgCdaqoWX_9fnpI8mhd6lU25JV7vxBoVQVVuF2p-I,67474
54
- llms/ui/modules/tools.mjs,sha256=ciFtujb60iIVjxAq-emEDs06iygZ6rSyMGwL0BG4xWI,9472
55
- llms/ui/modules/chat/ChatBody.mjs,sha256=5xbBLQShRtBXZjM_bShihZu1Pr7UpPS3vjw47vSvgU8,52861
56
- llms/ui/modules/chat/SettingsDialog.mjs,sha256=N_Xnd9eXkXuw8cVaKR77k16TgOitB9btInW8Qp-WK7U,19929
57
- llms/ui/modules/chat/index.mjs,sha256=AIgAffafq027vviAD26wtxHZ5mP2wiVgTtb4kwAs3yU,34387
58
- llms/ui/modules/threads/Recents.mjs,sha256=xiN5K9SYc0oJug60m6g_lPVw-75lNkp1ATuVUYgIgX8,8826
59
- llms/ui/modules/threads/index.mjs,sha256=0ZwVb6W2BT3mwK5bwKgtlJEGJ9IAnQr7qk3XNG1LnFU,11397
60
- llms/ui/modules/threads/threadStore.mjs,sha256=cGm6g4dn5q0u_K6Bu5xuoAmBuURquubK7R4ahSKNC_E,16886
61
- llms_py-3.0.0b6.dist-info/licenses/LICENSE,sha256=bus9cuAOWeYqBk2OuhSABVV1P4z7hgrEFISpyda_H5w,1532
62
- llms_py-3.0.0b6.dist-info/METADATA,sha256=dvFfu0f95YwYr_bApi7ZI9QMwhPlLc1PkWTD5tLO21Y,2193
63
- llms_py-3.0.0b6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
64
- llms_py-3.0.0b6.dist-info/entry_points.txt,sha256=WswyE7PfnkZMIxboC-MS6flBD6wm-CYU7JSUnMhqMfM,40
65
- llms_py-3.0.0b6.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
66
- llms_py-3.0.0b6.dist-info/RECORD,,