feat: support import and export with prompts (#330)
* feat: support import and export prompts * test: update importExports.test.ts * Delete .gitpod.yml
This commit is contained in:
		
							parent
							
								
									462ca9bb04
								
							
						
					
					
						commit
						d68f77867d
					
				|  | @ -1,4 +1,4 @@ | |||
| import { ExportFormatV1, ExportFormatV2 } from '@/types/export'; | ||||
| import { ExportFormatV1, ExportFormatV2, ExportFormatV4 } from '@/types/export'; | ||||
| import { OpenAIModels, OpenAIModelID } from '@/types/openai'; | ||||
| import { DEFAULT_SYSTEM_PROMPT } from '@/utils/app/const'; | ||||
| import { it, describe, expect } from 'vitest'; | ||||
|  | @ -8,6 +8,7 @@ import { | |||
|   isExportFormatV1, | ||||
|   isExportFormatV2, | ||||
|   isExportFormatV3, | ||||
|   isExportFormatV4, | ||||
|   isLatestExportFormat, | ||||
| } from '@/utils/app/importExport'; | ||||
| 
 | ||||
|  | @ -47,6 +48,18 @@ describe('Export Format Functions', () => { | |||
|       expect(isExportFormatV3(obj)).toBe(false); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('isExportFormatV4', () => { | ||||
|     it('should return true for v4 format', () => { | ||||
|       const obj = { version: 4, history: [], folders: [], prompts: [] }; | ||||
|       expect(isExportFormatV4(obj)).toBe(true); | ||||
|     }); | ||||
| 
 | ||||
|     it('should return false for non-v4 formats', () => { | ||||
|       const obj = { version: 5, history: [], folders: [], prompts: [] }; | ||||
|       expect(isExportFormatV4(obj)).toBe(false); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| describe('cleanData Functions', () => { | ||||
|  | @ -71,7 +84,7 @@ describe('cleanData Functions', () => { | |||
|       const obj = cleanData(data); | ||||
|       expect(isLatestExportFormat(obj)).toBe(true); | ||||
|       expect(obj).toEqual({ | ||||
|         version: 3, | ||||
|         version: 4, | ||||
|         history: [ | ||||
|           { | ||||
|             id: 1, | ||||
|  | @ -92,6 +105,7 @@ describe('cleanData Functions', () => { | |||
|           }, | ||||
|         ], | ||||
|         folders: [], | ||||
|         prompts:[] | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
|  | @ -125,7 +139,7 @@ describe('cleanData Functions', () => { | |||
|       const obj = cleanData(data); | ||||
|       expect(isLatestExportFormat(obj)).toBe(true); | ||||
|       expect(obj).toEqual({ | ||||
|         version: 3, | ||||
|         version: 4, | ||||
|         history: [ | ||||
|           { | ||||
|             id: '1', | ||||
|  | @ -152,7 +166,96 @@ describe('cleanData Functions', () => { | |||
|             type: 'chat', | ||||
|           }, | ||||
|         ], | ||||
|         prompts: [], | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('cleaning v4 data', () => { | ||||
|     it('should return the latest format', () => { | ||||
|       const data = { | ||||
|         version: 4, | ||||
|         history: [ | ||||
|           { | ||||
|             id: '1', | ||||
|             name: 'conversation 1', | ||||
|             messages: [ | ||||
|               { | ||||
|                 role: 'user', | ||||
|                 content: "what's up ?", | ||||
|               }, | ||||
|               { | ||||
|                 role: 'assistant', | ||||
|                 content: 'Hi', | ||||
|               }, | ||||
|             ], | ||||
|             model: OpenAIModels[OpenAIModelID.GPT_3_5], | ||||
|             prompt: DEFAULT_SYSTEM_PROMPT, | ||||
|             folderId: null, | ||||
|           }, | ||||
|         ], | ||||
|         folders: [ | ||||
|           { | ||||
|             id: '1', | ||||
|             name: 'folder 1', | ||||
|             type: 'chat', | ||||
|           }, | ||||
|         ], | ||||
|         prompts: [ | ||||
|           { | ||||
|             id: '1', | ||||
|             name: 'prompt 1', | ||||
|             description: '', | ||||
|             content: '', | ||||
|             model: OpenAIModels[OpenAIModelID.GPT_3_5], | ||||
|             folderId: null, | ||||
|           }, | ||||
|         ], | ||||
|       } as ExportFormatV4; | ||||
|        | ||||
|       const obj = cleanData(data); | ||||
|       expect(isLatestExportFormat(obj)).toBe(true); | ||||
|       expect(obj).toEqual({ | ||||
|         version: 4, | ||||
|         history: [ | ||||
|           { | ||||
|             id: '1', | ||||
|             name: 'conversation 1', | ||||
|             messages: [ | ||||
|               { | ||||
|                 role: 'user', | ||||
|                 content: "what's up ?", | ||||
|               }, | ||||
|               { | ||||
|                 role: 'assistant', | ||||
|                 content: 'Hi', | ||||
|               }, | ||||
|             ], | ||||
|             model: OpenAIModels[OpenAIModelID.GPT_3_5], | ||||
|             prompt: DEFAULT_SYSTEM_PROMPT, | ||||
|             folderId: null, | ||||
|           }, | ||||
|         ], | ||||
|         folders: [ | ||||
|           { | ||||
|             id: '1', | ||||
|             name: 'folder 1', | ||||
|             type: 'chat', | ||||
|           }, | ||||
|         ], | ||||
|         prompts: [ | ||||
|           { | ||||
|             id: '1', | ||||
|             name: 'prompt 1', | ||||
|             description: '', | ||||
|             content: '', | ||||
|             model: OpenAIModels[OpenAIModelID.GPT_3_5], | ||||
|             folderId: null, | ||||
|           }, | ||||
|         ], | ||||
| 
 | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
|    | ||||
| }); | ||||
|  |  | |||
|  | @ -296,11 +296,12 @@ const Home: React.FC<HomeProps> = ({ | |||
|   }; | ||||
| 
 | ||||
|   const handleImportConversations = (data: SupportedExportFormats) => { | ||||
|     const { history, folders }: LatestExportFormat = importData(data); | ||||
|     const { history, folders, prompts }: LatestExportFormat = importData(data); | ||||
| 
 | ||||
|     setConversations(history); | ||||
|     setSelectedConversation(history[history.length - 1]); | ||||
|     setFolders(folders); | ||||
|     setPrompts(prompts); | ||||
|   }; | ||||
| 
 | ||||
|   const handleSelectConversation = (conversation: Conversation) => { | ||||
|  |  | |||
|  | @ -1,12 +1,14 @@ | |||
| import { Conversation, Message } from './chat'; | ||||
| import { Folder } from './folder'; | ||||
| import { OpenAIModel } from './openai'; | ||||
| import { Prompt } from './prompt'; | ||||
| 
 | ||||
| export type SupportedExportFormats = | ||||
|   | ExportFormatV1 | ||||
|   | ExportFormatV2 | ||||
|   | ExportFormatV3; | ||||
| export type LatestExportFormat = ExportFormatV3; | ||||
|   | ExportFormatV3 | ||||
|   | ExportFormatV4; | ||||
| export type LatestExportFormat = ExportFormatV4; | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| interface ConversationV1 { | ||||
|  | @ -34,3 +36,10 @@ export interface ExportFormatV3 { | |||
|   history: Conversation[]; | ||||
|   folders: Folder[]; | ||||
| } | ||||
| 
 | ||||
| export interface ExportFormatV4 { | ||||
|   version: 4; | ||||
|   history: Conversation[]; | ||||
|   folders: Folder[]; | ||||
|   prompts: Prompt[] | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ import { | |||
|   ExportFormatV1, | ||||
|   ExportFormatV2, | ||||
|   ExportFormatV3, | ||||
|   ExportFormatV4, | ||||
|   LatestExportFormat, | ||||
|   SupportedExportFormats, | ||||
| } from '@/types/export'; | ||||
|  | @ -19,33 +20,44 @@ export function isExportFormatV3(obj: any): obj is ExportFormatV3 { | |||
|   return obj.version === 3; | ||||
| } | ||||
| 
 | ||||
| export const isLatestExportFormat = isExportFormatV3; | ||||
| export function isExportFormatV4(obj: any): obj is ExportFormatV4 { | ||||
|   return obj.version === 4; | ||||
| } | ||||
| 
 | ||||
| export const isLatestExportFormat = isExportFormatV4; | ||||
| 
 | ||||
| export function cleanData(data: SupportedExportFormats): LatestExportFormat { | ||||
|   if (isExportFormatV1(data)) { | ||||
|     return { | ||||
|       version: 3, | ||||
|       version: 4, | ||||
|       history: cleanConversationHistory(data), | ||||
|       folders: [], | ||||
|       prompts: [], | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   if (isExportFormatV2(data)) { | ||||
|     return { | ||||
|       version: 3, | ||||
|       version: 4, | ||||
|       history: cleanConversationHistory(data.history || []), | ||||
|       folders: (data.folders || []).map((chatFolder) => ({ | ||||
|         id: chatFolder.id.toString(), | ||||
|         name: chatFolder.name, | ||||
|         type: 'chat', | ||||
|       })), | ||||
|       prompts: [], | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   if (isExportFormatV3(data)) {     | ||||
|     return {...data, version: 4, prompts: []}; | ||||
|   } | ||||
| 
 | ||||
|   if(isExportFormatV4(data)){ | ||||
|     return data; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   throw new Error('Unsupported data format'); | ||||
| } | ||||
| 
 | ||||
|  | @ -59,6 +71,7 @@ function currentDate() { | |||
| export const exportData = () => { | ||||
|   let history = localStorage.getItem('conversationHistory'); | ||||
|   let folders = localStorage.getItem('folders'); | ||||
|   let prompts = localStorage.getItem('prompts'); | ||||
| 
 | ||||
|   if (history) { | ||||
|     history = JSON.parse(history); | ||||
|  | @ -68,10 +81,15 @@ export const exportData = () => { | |||
|     folders = JSON.parse(folders); | ||||
|   } | ||||
| 
 | ||||
|   if(prompts){ | ||||
|     prompts = JSON.parse(prompts); | ||||
|   } | ||||
| 
 | ||||
|   const data = { | ||||
|     version: 3, | ||||
|     version: 4, | ||||
|     history: history || [], | ||||
|     folders: folders || [], | ||||
|     prompts: prompts || [], | ||||
|   } as LatestExportFormat; | ||||
| 
 | ||||
|   const blob = new Blob([JSON.stringify(data, null, 2)], { | ||||
|  | @ -92,15 +110,17 @@ export const importData = ( | |||
|   data: SupportedExportFormats, | ||||
| ): LatestExportFormat => { | ||||
|   const cleanedData = cleanData(data); | ||||
|   const { history,folders, prompts } = cleanedData; | ||||
| 
 | ||||
|   const conversations = cleanedData.history; | ||||
|   const conversations = history; | ||||
|   localStorage.setItem('conversationHistory', JSON.stringify(conversations)); | ||||
|   localStorage.setItem( | ||||
|     'selectedConversation', | ||||
|     JSON.stringify(conversations[conversations.length - 1]), | ||||
|   ); | ||||
| 
 | ||||
|   localStorage.setItem('folders', JSON.stringify(cleanedData.folders)); | ||||
|   localStorage.setItem('folders', JSON.stringify(folders)); | ||||
|   localStorage.setItem('prompts', JSON.stringify(prompts)); | ||||
| 
 | ||||
|   return cleanedData; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue