@@ -61,7 +61,7 @@ export default {
6161 <!-- Export/Import buttons -->
6262 <div class="mt-2 flex space-x-3 justify-center">
6363 <button type="button"
64- @click="exportThreads"
64+ @click="(e) => e.altKey ? exportRequests() : exportThreads() "
6565 :disabled="isExporting"
6666 :title="'Export ' + threads?.threads?.value?.length + ' conversations'"
6767 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 {
411411 const exportData = {
412412 exportedAt : new Date ( ) . toISOString ( ) ,
413413 version : '1.0' ,
414- source : 'ServiceStack.AI.Chat ' ,
414+ source : 'llmspy ' ,
415415 threadCount : allThreads . length ,
416416 threads : allThreads
417417 }
@@ -423,7 +423,7 @@ export default {
423423
424424 const link = document . createElement ( 'a' )
425425 link . href = url
426- link . download = `aichat-threads -export-${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } .json`
426+ link . download = `llmsthreads -export-${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } .json`
427427 document . body . appendChild ( link )
428428 link . click ( )
429429 document . body . removeChild ( link )
@@ -437,6 +437,44 @@ export default {
437437 }
438438 }
439439
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+
440478 function triggerImport ( ) {
441479 if ( isImporting . value ) return
442480 fileInput . value ?. click ( )
@@ -447,71 +485,110 @@ export default {
447485 if ( ! file ) return
448486
449487 isImporting . value = true
488+ var importType = 'threads'
450489 try {
451490 const text = await file . text ( )
452491 const importData = JSON . parse ( text )
453-
454- // Validate import data structure
455- if ( ! importData . threads || ! Array . isArray ( importData . threads ) ) {
456- throw new Error ( 'Invalid import file: missing or invalid threads array' )
457- }
492+ importType = importData . threads
493+ ? 'threads'
494+ : importData . requests
495+ ? 'requests'
496+ : 'unknown'
458497
459498 // Import threads one by one
460499 let importedCount = 0
461500 let updatedCount = 0
462501
463- for ( const threadData of importData . threads ) {
464- if ( ! threadData . id ) {
465- console . warn ( 'Skipping thread without ID:' , threadData )
466- continue
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' )
467507 }
468508
469- try {
470- // Check if thread already exists
471- const existingThread = await threads . getThread ( threadData . id )
472-
473- if ( existingThread ) {
474- // Update existing thread
475- await threads . updateThread ( threadData . id , {
476- title : threadData . title ,
477- model : threadData . model ,
478- systemPrompt : threadData . systemPrompt ,
479- messages : threadData . messages || [ ] ,
480- createdAt : threadData . createdAt ,
481- // Keep the existing updatedAt or use imported one
482- updatedAt : threadData . updatedAt || existingThread . updatedAt
483- } )
484- updatedCount ++
485- } else {
486- // Add new thread directly to IndexedDB
487- //await threads.initDB()
488- const db = await threads . initDB ( )
489- const tx = db . transaction ( [ 'threads' ] , 'readwrite' )
490- await tx . objectStore ( 'threads' ) . add ( {
491- id : threadData . id ,
492- title : threadData . title || 'Imported Chat' ,
493- model : threadData . model || '' ,
494- systemPrompt : threadData . systemPrompt || '' ,
495- messages : threadData . messages || [ ] ,
496- createdAt : threadData . createdAt || new Date ( ) . toISOString ( ) ,
497- updatedAt : threadData . updatedAt || new Date ( ) . toISOString ( )
498- } )
499- await tx . complete
500- importedCount ++
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 )
501548 }
502- } catch ( error ) {
503- console . error ( 'Failed to import thread:' , threadData . id , error )
504549 }
550+
551+ // Reload threads to reflect changes
552+ await threads . loadThreads ( )
553+
554+ alert ( `Import completed!\nNew threads: ${ importedCount } \nUpdated threads: ${ updatedCount } ` )
505555 }
556+ if ( importData . requests ) {
557+ if ( ! Array . isArray ( importData . requests ) ) {
558+ throw new Error ( 'Invalid import file: missing or invalid requests array' )
559+ }
506560
507- // Reload threads to reflect changes
508- await threads . loadThreads ( )
561+ for ( const requestData of importData . requests ) {
562+ if ( ! requestData . id ) {
563+ console . warn ( 'Skipping request without ID:' , requestData )
564+ continue
565+ }
509566
510- alert ( `Import completed!\nNew threads: ${ importedCount } \nUpdated threads: ${ updatedCount } ` )
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+ }
511588
512589 } catch ( error ) {
513- console . error ( 'Failed to import threads :' , error )
514- alert ( 'Failed to import threads : ' + error . message )
590+ console . error ( 'Failed to import ' + importType + ' :', error )
591+ alert ( 'Failed to import ' + importType + ' : ' + error . message )
515592 } finally {
516593 isImporting . value = false
517594 // Clear the file input
@@ -725,6 +802,7 @@ export default {
725802 cancelEdit,
726803 configUpdated,
727804 exportThreads,
805+ exportRequests,
728806 isExporting,
729807 triggerImport,
730808 handleFileImport,
0 commit comments