llms-py 2.0.20__tar.gz → 2.0.22__tar.gz
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_py-2.0.20/llms_py.egg-info → llms_py-2.0.22}/PKG-INFO +1 -1
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/main.py +1 -1
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Main.mjs +129 -51
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/ai.mjs +1 -1
- llms_py-2.0.22/llms/ui/lib/chart.js +14 -0
- llms_py-2.0.22/llms/ui/lib/charts.mjs +20 -0
- llms_py-2.0.22/llms/ui/lib/color.js +14 -0
- llms_py-2.0.22/llms/ui/lib/highlight.min.mjs +1243 -0
- llms_py-2.0.22/llms/ui/lib/idb.min.mjs +8 -0
- llms_py-2.0.22/llms/ui/lib/marked.min.mjs +8 -0
- llms_py-2.0.22/llms/ui/lib/servicestack-client.mjs +1 -0
- llms_py-2.0.22/llms/ui/lib/servicestack-vue.mjs +37 -0
- llms_py-2.0.22/llms/ui/lib/vue-router.min.mjs +6 -0
- llms_py-2.0.22/llms/ui/lib/vue.min.mjs +12 -0
- llms_py-2.0.22/llms/ui/lib/vue.mjs +18369 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/threadStore.mjs +10 -0
- {llms_py-2.0.20 → llms_py-2.0.22/llms_py.egg-info}/PKG-INFO +1 -1
- {llms_py-2.0.20 → llms_py-2.0.22}/llms_py.egg-info/SOURCES.txt +11 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/pyproject.toml +1 -1
- {llms_py-2.0.20 → llms_py-2.0.22}/setup.py +1 -1
- {llms_py-2.0.20 → llms_py-2.0.22}/LICENSE +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/MANIFEST.in +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/README.md +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/__init__.py +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/__main__.py +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/index.html +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/llms.json +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Analytics.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/App.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Avatar.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Brand.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/ChatPrompt.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/ModelSelector.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/ProviderIcon.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/ProviderStatus.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Recents.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/SettingsDialog.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Sidebar.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/SignIn.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/SystemPromptEditor.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/SystemPromptSelector.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/Welcome.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/app.css +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/fav.svg +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/markdown.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/tailwind.input.css +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/typography.css +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui/utils.mjs +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms/ui.json +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms_py.egg-info/dependency_links.txt +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms_py.egg-info/entry_points.txt +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms_py.egg-info/not-zip-safe +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms_py.egg-info/requires.txt +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/llms_py.egg-info/top_level.txt +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/requirements.txt +0 -0
- {llms_py-2.0.20 → llms_py-2.0.22}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llms-py
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.22
|
|
4
4
|
Summary: A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers
|
|
5
5
|
Home-page: https://github.com/ServiceStack/llms
|
|
6
6
|
Author: ServiceStack
|
|
@@ -61,7 +61,7 @@ export default {
|
|
|
61
61
|
<!-- Export/Import buttons -->
|
|
62
62
|
<div class="mt-2 flex space-x-3 justify-center">
|
|
63
63
|
<button type="button"
|
|
64
|
-
@click="exportThreads"
|
|
64
|
+
@click="(e) => e.altKey ? exportRequests() : exportThreads()"
|
|
65
65
|
:disabled="isExporting"
|
|
66
66
|
:title="'Export ' + threads?.threads?.value?.length + ' conversations'"
|
|
67
67
|
class="inline-flex items-center px-3 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
@@ -411,7 +411,7 @@ export default {
|
|
|
411
411
|
const exportData = {
|
|
412
412
|
exportedAt: new Date().toISOString(),
|
|
413
413
|
version: '1.0',
|
|
414
|
-
source: '
|
|
414
|
+
source: 'llmspy',
|
|
415
415
|
threadCount: allThreads.length,
|
|
416
416
|
threads: allThreads
|
|
417
417
|
}
|
|
@@ -423,7 +423,7 @@ export default {
|
|
|
423
423
|
|
|
424
424
|
const link = document.createElement('a')
|
|
425
425
|
link.href = url
|
|
426
|
-
link.download = `
|
|
426
|
+
link.download = `llmsthreads-export-${new Date().toISOString().split('T')[0]}.json`
|
|
427
427
|
document.body.appendChild(link)
|
|
428
428
|
link.click()
|
|
429
429
|
document.body.removeChild(link)
|
|
@@ -437,6 +437,44 @@ export default {
|
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
|
|
440
|
+
async function exportRequests() {
|
|
441
|
+
if (isExporting.value) return
|
|
442
|
+
|
|
443
|
+
isExporting.value = true
|
|
444
|
+
try {
|
|
445
|
+
// Load all threads from IndexedDB
|
|
446
|
+
const allRequests = await threads.getAllRequests()
|
|
447
|
+
|
|
448
|
+
// Create export data with metadata
|
|
449
|
+
const exportData = {
|
|
450
|
+
exportedAt: new Date().toISOString(),
|
|
451
|
+
version: '1.0',
|
|
452
|
+
source: 'llmspy',
|
|
453
|
+
requestsCount: allRequests.length,
|
|
454
|
+
requests: allRequests
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Create and download JSON file
|
|
458
|
+
const jsonString = JSON.stringify(exportData, null, 2)
|
|
459
|
+
const blob = new Blob([jsonString], { type: 'application/json' })
|
|
460
|
+
const url = URL.createObjectURL(blob)
|
|
461
|
+
|
|
462
|
+
const link = document.createElement('a')
|
|
463
|
+
link.href = url
|
|
464
|
+
link.download = `llmsrequests-export-${new Date().toISOString().split('T')[0]}.json`
|
|
465
|
+
document.body.appendChild(link)
|
|
466
|
+
link.click()
|
|
467
|
+
document.body.removeChild(link)
|
|
468
|
+
URL.revokeObjectURL(url)
|
|
469
|
+
|
|
470
|
+
} catch (error) {
|
|
471
|
+
console.error('Failed to export requests:', error)
|
|
472
|
+
alert('Failed to export requests: ' + error.message)
|
|
473
|
+
} finally {
|
|
474
|
+
isExporting.value = false
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
440
478
|
function triggerImport() {
|
|
441
479
|
if (isImporting.value) return
|
|
442
480
|
fileInput.value?.click()
|
|
@@ -447,71 +485,110 @@ export default {
|
|
|
447
485
|
if (!file) return
|
|
448
486
|
|
|
449
487
|
isImporting.value = true
|
|
488
|
+
var importType = 'threads'
|
|
450
489
|
try {
|
|
451
490
|
const text = await file.text()
|
|
452
491
|
const importData = JSON.parse(text)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
492
|
+
importType = importData.threads
|
|
493
|
+
? 'threads'
|
|
494
|
+
: importData.requests
|
|
495
|
+
? 'requests'
|
|
496
|
+
: 'unknown'
|
|
458
497
|
|
|
459
498
|
// Import threads one by one
|
|
460
499
|
let importedCount = 0
|
|
461
500
|
let updatedCount = 0
|
|
462
501
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
502
|
+
const db = await threads.initDB()
|
|
503
|
+
|
|
504
|
+
if (importData.threads) {
|
|
505
|
+
if (!Array.isArray(importData.threads)) {
|
|
506
|
+
throw new Error('Invalid import file: missing or invalid threads array')
|
|
467
507
|
}
|
|
468
508
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
509
|
+
for (const threadData of importData.threads) {
|
|
510
|
+
if (!threadData.id) {
|
|
511
|
+
console.warn('Skipping thread without ID:', threadData)
|
|
512
|
+
continue
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
// Check if thread already exists
|
|
517
|
+
const existingThread = await threads.getThread(threadData.id)
|
|
518
|
+
|
|
519
|
+
if (existingThread) {
|
|
520
|
+
// Update existing thread
|
|
521
|
+
await threads.updateThread(threadData.id, {
|
|
522
|
+
title: threadData.title,
|
|
523
|
+
model: threadData.model,
|
|
524
|
+
systemPrompt: threadData.systemPrompt,
|
|
525
|
+
messages: threadData.messages || [],
|
|
526
|
+
createdAt: threadData.createdAt,
|
|
527
|
+
// Keep the existing updatedAt or use imported one
|
|
528
|
+
updatedAt: threadData.updatedAt || existingThread.updatedAt
|
|
529
|
+
})
|
|
530
|
+
updatedCount++
|
|
531
|
+
} else {
|
|
532
|
+
// Add new thread directly to IndexedDB
|
|
533
|
+
const tx = db.transaction(['threads'], 'readwrite')
|
|
534
|
+
await tx.objectStore('threads').add({
|
|
535
|
+
id: threadData.id,
|
|
536
|
+
title: threadData.title || 'Imported Chat',
|
|
537
|
+
model: threadData.model || '',
|
|
538
|
+
systemPrompt: threadData.systemPrompt || '',
|
|
539
|
+
messages: threadData.messages || [],
|
|
540
|
+
createdAt: threadData.createdAt || new Date().toISOString(),
|
|
541
|
+
updatedAt: threadData.updatedAt || new Date().toISOString()
|
|
542
|
+
})
|
|
543
|
+
await tx.complete
|
|
544
|
+
importedCount++
|
|
545
|
+
}
|
|
546
|
+
} catch (error) {
|
|
547
|
+
console.error('Failed to import thread:', threadData.id, error)
|
|
501
548
|
}
|
|
502
|
-
} catch (error) {
|
|
503
|
-
console.error('Failed to import thread:', threadData.id, error)
|
|
504
549
|
}
|
|
550
|
+
|
|
551
|
+
// Reload threads to reflect changes
|
|
552
|
+
await threads.loadThreads()
|
|
553
|
+
|
|
554
|
+
alert(`Import completed!\nNew threads: ${importedCount}\nUpdated threads: ${updatedCount}`)
|
|
505
555
|
}
|
|
556
|
+
if (importData.requests) {
|
|
557
|
+
if (!Array.isArray(importData.requests)) {
|
|
558
|
+
throw new Error('Invalid import file: missing or invalid requests array')
|
|
559
|
+
}
|
|
506
560
|
|
|
507
|
-
|
|
508
|
-
|
|
561
|
+
for (const requestData of importData.requests) {
|
|
562
|
+
if (!requestData.id) {
|
|
563
|
+
console.warn('Skipping request without ID:', requestData)
|
|
564
|
+
continue
|
|
565
|
+
}
|
|
509
566
|
|
|
510
|
-
|
|
567
|
+
try {
|
|
568
|
+
// Check if request already exists
|
|
569
|
+
const existingRequest = await threads.getRequest(requestData.id)
|
|
570
|
+
|
|
571
|
+
if (existingRequest) {
|
|
572
|
+
updatedCount++
|
|
573
|
+
} else {
|
|
574
|
+
// Add new request directly to IndexedDB
|
|
575
|
+
const db = await threads.initDB()
|
|
576
|
+
const tx = db.transaction(['requests'], 'readwrite')
|
|
577
|
+
await tx.objectStore('requests').add(requestData)
|
|
578
|
+
await tx.complete
|
|
579
|
+
importedCount++
|
|
580
|
+
}
|
|
581
|
+
} catch (error) {
|
|
582
|
+
console.error('Failed to import request:', requestData.id, error)
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
alert(`Import completed!\nNew requests: ${importedCount}\nUpdated requests: ${updatedCount}`)
|
|
587
|
+
}
|
|
511
588
|
|
|
512
589
|
} catch (error) {
|
|
513
|
-
console.error('Failed to import
|
|
514
|
-
alert('Failed to import
|
|
590
|
+
console.error('Failed to import ' + importType + ':', error)
|
|
591
|
+
alert('Failed to import ' + importType + ': ' + error.message)
|
|
515
592
|
} finally {
|
|
516
593
|
isImporting.value = false
|
|
517
594
|
// Clear the file input
|
|
@@ -725,6 +802,7 @@ export default {
|
|
|
725
802
|
cancelEdit,
|
|
726
803
|
configUpdated,
|
|
727
804
|
exportThreads,
|
|
805
|
+
exportRequests,
|
|
728
806
|
isExporting,
|
|
729
807
|
triggerImport,
|
|
730
808
|
handleFileImport,
|