multi_prompt_local_storage

This commit is contained in:
lusixing
2026-01-31 11:11:25 -08:00
parent fb1377eb4b
commit ed1f6fc49d
7 changed files with 727 additions and 156 deletions

View File

@@ -95,7 +95,7 @@ export const aiService = {
}
const url = buildApiUrl(API_ENDPOINTS.AI.PROXY);
logApiDebug('AI Request', {
url,
hasToken: !!token,
@@ -114,7 +114,7 @@ export const aiService = {
if (!response.ok) {
const errorText = await response.text();
logApiDebug('AI Error Response', errorText);
let errorDetail = 'AI request failed';
try {
const errorData = JSON.parse(errorText);
@@ -131,7 +131,7 @@ export const aiService = {
model: data.model,
choicesCount: data.choices?.length,
});
return data;
} catch (error) {
console.error('AI proxy error:', error);
@@ -143,13 +143,14 @@ export const aiService = {
* Simple helper for single message chat
* @param content - User message content
* @param token - JWT token for authentication
* @param systemPrompt - Optional custom system prompt
* @returns AI response text
*/
async sendMessage(content: string, token?: string): Promise<string> {
async sendMessage(content: string, token?: string, systemPrompt?: string): Promise<string> {
const messages: AIMessage[] = [
{
role: 'system',
content: AI_CONFIG.DEFAULT_SYSTEM_PROMPT,
content: systemPrompt || AI_CONFIG.DEFAULT_SYSTEM_PROMPT,
},
{
role: 'user',
@@ -179,7 +180,7 @@ export const aiService = {
}
const url = buildApiUrl(API_ENDPOINTS.AI.PROXY);
logApiDebug('AI Image Request', {
url,
hasToken: !!token,
@@ -217,7 +218,7 @@ export const aiService = {
if (!response.ok) {
const errorText = await response.text();
logApiDebug('AI Image Error Response', errorText);
let errorDetail = 'AI image request failed';
try {
const errorData = JSON.parse(errorText);
@@ -233,7 +234,7 @@ export const aiService = {
id: data.id,
model: data.model,
});
return data.choices[0]?.message?.content || 'No response';
} catch (error) {
console.error('AI image proxy error:', error);

View File

@@ -0,0 +1,120 @@
/**
* Storage Service
*
* Handles local persistence of chat history and active conversations
* using AsyncStorage with user-specific isolation.
*/
import AsyncStorage from '@react-native-async-storage/async-storage';
// =============================================================================
// Constants
// =============================================================================
const STORAGE_KEYS = {
CHAT_HISTORY: '@sentinel:chat_history',
CURRENT_MESSAGES: '@sentinel:current_messages',
} as const;
// =============================================================================
// Service Implementation
// =============================================================================
export const storageService = {
/**
* Get user-specific storage key
*/
getUserKey(baseKey: string, userId: string | number): string {
return `${baseKey}:user_${userId}`;
},
/**
* Save the complete list of chat sessions to local storage for a specific user
*/
async saveChatHistory(history: any[], userId: string | number): Promise<void> {
try {
const jsonValue = JSON.stringify(history);
const key = this.getUserKey(STORAGE_KEYS.CHAT_HISTORY, userId);
await AsyncStorage.setItem(key, jsonValue);
console.log(`[Storage] Saved chat history for user ${userId}:`, history.length, 'sessions');
} catch (e) {
console.error('Error saving chat history:', e);
}
},
/**
* Load the list of chat sessions from local storage for a specific user
*/
async getChatHistory(userId: string | number): Promise<any[]> {
try {
const key = this.getUserKey(STORAGE_KEYS.CHAT_HISTORY, userId);
const jsonValue = await AsyncStorage.getItem(key);
const result = jsonValue != null ? JSON.parse(jsonValue) : [];
console.log(`[Storage] Loaded chat history for user ${userId}:`, result.length, 'sessions');
return result;
} catch (e) {
console.error('Error getting chat history:', e);
return [];
}
},
/**
* Save the current active conversation messages for a specific role and user
*/
async saveCurrentChat(roleId: string, messages: any[], userId: string | number): Promise<void> {
try {
const jsonValue = JSON.stringify(messages);
const key = `${this.getUserKey(STORAGE_KEYS.CURRENT_MESSAGES, userId)}:${roleId}`;
await AsyncStorage.setItem(key, jsonValue);
console.log(`[Storage] Saved current chat for user ${userId}, role ${roleId}:`, messages.length, 'messages');
} catch (e) {
console.error(`Error saving current chat for role ${roleId}:`, e);
}
},
/**
* Load the current active conversation messages for a specific role and user
*/
async getCurrentChat(roleId: string, userId: string | number): Promise<any[]> {
try {
const key = `${this.getUserKey(STORAGE_KEYS.CURRENT_MESSAGES, userId)}:${roleId}`;
const jsonValue = await AsyncStorage.getItem(key);
const result = jsonValue != null ? JSON.parse(jsonValue) : [];
console.log(`[Storage] Loaded current chat for user ${userId}, role ${roleId}:`, result.length, 'messages');
return result;
} catch (e) {
console.error(`Error getting current chat for role ${roleId}:`, e);
return [];
}
},
/**
* Clear all stored chat data for a specific user
*/
async clearUserData(userId: string | number): Promise<void> {
try {
const keys = await AsyncStorage.getAllKeys();
const userPrefix = `:user_${userId}`;
const userKeys = keys.filter(key => key.includes(userPrefix));
await AsyncStorage.multiRemove(userKeys);
console.log(`[Storage] Cleared all data for user ${userId}:`, userKeys.length, 'keys removed');
} catch (e) {
console.error('Error clearing user data:', e);
}
},
/**
* Clear all stored chat data (all users)
*/
async clearAllData(): Promise<void> {
try {
const keys = await AsyncStorage.getAllKeys();
const sentinelKeys = keys.filter(key => key.startsWith('@sentinel:'));
await AsyncStorage.multiRemove(sentinelKeys);
console.log('[Storage] Cleared all data:', sentinelKeys.length, 'keys removed');
} catch (e) {
console.error('Error clearing storage data:', e);
}
}
};