mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 14:26:41 +02:00
style: auto-format codebase with Prettier
Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
This commit is contained in:
parent
0241f5554c
commit
d36b321d9d
3952 changed files with 661498 additions and 739751 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -2,300 +2,300 @@
|
|||
* Conversation Service - CRUD operations via Backend API
|
||||
*/
|
||||
import {
|
||||
conversationApi,
|
||||
chatApi,
|
||||
modelApi,
|
||||
templateApi,
|
||||
usageApi,
|
||||
type Conversation as ApiConversation,
|
||||
type Message as ApiMessage,
|
||||
type ChatMessage,
|
||||
type TokenUsage,
|
||||
conversationApi,
|
||||
chatApi,
|
||||
modelApi,
|
||||
templateApi,
|
||||
usageApi,
|
||||
type Conversation as ApiConversation,
|
||||
type Message as ApiMessage,
|
||||
type ChatMessage,
|
||||
type TokenUsage,
|
||||
} from './api';
|
||||
|
||||
// Re-export types with backwards-compatible naming (snake_case for mobile)
|
||||
export type Conversation = {
|
||||
id: string;
|
||||
user_id: string;
|
||||
model_id: string;
|
||||
template_id?: string;
|
||||
space_id?: string;
|
||||
conversation_mode: 'free' | 'guided' | 'template';
|
||||
document_mode: boolean;
|
||||
title?: string;
|
||||
is_archived: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
id: string;
|
||||
user_id: string;
|
||||
model_id: string;
|
||||
template_id?: string;
|
||||
space_id?: string;
|
||||
conversation_mode: 'free' | 'guided' | 'template';
|
||||
document_mode: boolean;
|
||||
title?: string;
|
||||
is_archived: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type Message = {
|
||||
id: string;
|
||||
conversation_id: string;
|
||||
sender: 'user' | 'assistant' | 'system';
|
||||
message_text: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
id: string;
|
||||
conversation_id: string;
|
||||
sender: 'user' | 'assistant' | 'system';
|
||||
message_text: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type TokenUsageType = {
|
||||
id: string;
|
||||
conversation_id: string;
|
||||
message_id: string;
|
||||
user_id: string;
|
||||
model_id: string;
|
||||
prompt_tokens: number;
|
||||
completion_tokens: number;
|
||||
total_tokens: number;
|
||||
estimated_cost: number;
|
||||
created_at: string;
|
||||
id: string;
|
||||
conversation_id: string;
|
||||
message_id: string;
|
||||
user_id: string;
|
||||
model_id: string;
|
||||
prompt_tokens: number;
|
||||
completion_tokens: number;
|
||||
total_tokens: number;
|
||||
estimated_cost: number;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
// Helper to convert API response to local format
|
||||
function toLocalConversation(conv: ApiConversation): Conversation {
|
||||
return {
|
||||
id: conv.id,
|
||||
user_id: conv.userId,
|
||||
model_id: conv.modelId,
|
||||
template_id: conv.templateId,
|
||||
space_id: conv.spaceId,
|
||||
conversation_mode: conv.conversationMode,
|
||||
document_mode: conv.documentMode,
|
||||
title: conv.title,
|
||||
is_archived: conv.isArchived,
|
||||
created_at: conv.createdAt,
|
||||
updated_at: conv.updatedAt,
|
||||
};
|
||||
return {
|
||||
id: conv.id,
|
||||
user_id: conv.userId,
|
||||
model_id: conv.modelId,
|
||||
template_id: conv.templateId,
|
||||
space_id: conv.spaceId,
|
||||
conversation_mode: conv.conversationMode,
|
||||
document_mode: conv.documentMode,
|
||||
title: conv.title,
|
||||
is_archived: conv.isArchived,
|
||||
created_at: conv.createdAt,
|
||||
updated_at: conv.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
function toLocalMessage(msg: ApiMessage): Message {
|
||||
return {
|
||||
id: msg.id,
|
||||
conversation_id: msg.conversationId,
|
||||
sender: msg.sender,
|
||||
message_text: msg.messageText,
|
||||
created_at: msg.createdAt,
|
||||
updated_at: msg.updatedAt,
|
||||
};
|
||||
return {
|
||||
id: msg.id,
|
||||
conversation_id: msg.conversationId,
|
||||
sender: msg.sender,
|
||||
message_text: msg.messageText,
|
||||
created_at: msg.createdAt,
|
||||
updated_at: msg.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt eine neue Konversation in der Datenbank
|
||||
*/
|
||||
export async function createConversation(
|
||||
userId: string,
|
||||
modelId: string,
|
||||
mode: 'free' | 'guided' | 'template' = 'free',
|
||||
templateId?: string,
|
||||
documentMode: boolean = false,
|
||||
spaceId?: string
|
||||
userId: string,
|
||||
modelId: string,
|
||||
mode: 'free' | 'guided' | 'template' = 'free',
|
||||
templateId?: string,
|
||||
documentMode: boolean = false,
|
||||
spaceId?: string
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
console.log('🔵 Erstelle Konversation mit Space ID:', spaceId || 'keine');
|
||||
try {
|
||||
console.log('🔵 Erstelle Konversation mit Space ID:', spaceId || 'keine');
|
||||
|
||||
const conversation = await conversationApi.createConversation({
|
||||
modelId,
|
||||
conversationMode: mode,
|
||||
templateId,
|
||||
documentMode,
|
||||
spaceId,
|
||||
});
|
||||
const conversation = await conversationApi.createConversation({
|
||||
modelId,
|
||||
conversationMode: mode,
|
||||
templateId,
|
||||
documentMode,
|
||||
spaceId,
|
||||
});
|
||||
|
||||
if (!conversation) {
|
||||
console.error('Fehler beim Erstellen der Konversation');
|
||||
return null;
|
||||
}
|
||||
if (!conversation) {
|
||||
console.error('Fehler beim Erstellen der Konversation');
|
||||
return null;
|
||||
}
|
||||
|
||||
return conversation.id;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen der Konversation:', error);
|
||||
return null;
|
||||
}
|
||||
return conversation.id;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen der Konversation:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt eine neue Nachricht zur Konversation hinzu
|
||||
*/
|
||||
export async function addMessage(
|
||||
conversationId: string,
|
||||
sender: 'user' | 'assistant' | 'system',
|
||||
messageText: string
|
||||
conversationId: string,
|
||||
sender: 'user' | 'assistant' | 'system',
|
||||
messageText: string
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
// Validate sender
|
||||
let validSender = sender;
|
||||
if (!['user', 'assistant', 'system'].includes(validSender)) {
|
||||
console.error('Ungültiger Sender-Wert:', sender);
|
||||
validSender = 'user';
|
||||
}
|
||||
try {
|
||||
// Validate sender
|
||||
let validSender = sender;
|
||||
if (!['user', 'assistant', 'system'].includes(validSender)) {
|
||||
console.error('Ungültiger Sender-Wert:', sender);
|
||||
validSender = 'user';
|
||||
}
|
||||
|
||||
console.log('Füge Nachricht hinzu mit Sender:', validSender);
|
||||
console.log('Füge Nachricht hinzu mit Sender:', validSender);
|
||||
|
||||
const message = await conversationApi.addMessage(conversationId, validSender, messageText);
|
||||
const message = await conversationApi.addMessage(conversationId, validSender, messageText);
|
||||
|
||||
if (!message) {
|
||||
console.error('Fehler beim Hinzufügen der Nachricht');
|
||||
return null;
|
||||
}
|
||||
if (!message) {
|
||||
console.error('Fehler beim Hinzufügen der Nachricht');
|
||||
return null;
|
||||
}
|
||||
|
||||
return message.id;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hinzufügen der Nachricht:', error);
|
||||
return null;
|
||||
}
|
||||
return message.id;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hinzufügen der Nachricht:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Nachrichten einer Konversation
|
||||
*/
|
||||
export async function getMessages(conversationId: string): Promise<Message[]> {
|
||||
try {
|
||||
const messages = await conversationApi.getMessages(conversationId);
|
||||
return messages.map(toLocalMessage);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Nachrichten:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const messages = await conversationApi.getMessages(conversationId);
|
||||
return messages.map(toLocalMessage);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Nachrichten:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generiert einen Titel für die Konversation basierend auf der ersten Benutzeranfrage
|
||||
*/
|
||||
export async function generateConversationTitle(userQuestion: string): Promise<string> {
|
||||
try {
|
||||
console.log(
|
||||
'Generiere Titel für Konversation basierend auf:',
|
||||
userQuestion.substring(0, 50) + (userQuestion.length > 50 ? '...' : '')
|
||||
);
|
||||
try {
|
||||
console.log(
|
||||
'Generiere Titel für Konversation basierend auf:',
|
||||
userQuestion.substring(0, 50) + (userQuestion.length > 50 ? '...' : '')
|
||||
);
|
||||
|
||||
const titlePrompt = `Schreibe eine kurze, prägnante Überschrift (maximal 5 Wörter) für unseren Chat mit dieser Frage: "${userQuestion}"`;
|
||||
const titlePrompt = `Schreibe eine kurze, prägnante Überschrift (maximal 5 Wörter) für unseren Chat mit dieser Frage: "${userQuestion}"`;
|
||||
|
||||
const response = await chatApi.createCompletion({
|
||||
messages: [{ role: 'user', content: titlePrompt }],
|
||||
modelId: '550e8400-e29b-41d4-a716-446655440004', // GPT-4o-Mini
|
||||
temperature: 0.3,
|
||||
maxTokens: 50,
|
||||
});
|
||||
const response = await chatApi.createCompletion({
|
||||
messages: [{ role: 'user', content: titlePrompt }],
|
||||
modelId: '550e8400-e29b-41d4-a716-446655440004', // GPT-4o-Mini
|
||||
temperature: 0.3,
|
||||
maxTokens: 50,
|
||||
});
|
||||
|
||||
if (!response) {
|
||||
return 'Neue Konversation';
|
||||
}
|
||||
if (!response) {
|
||||
return 'Neue Konversation';
|
||||
}
|
||||
|
||||
// Clean up title
|
||||
let cleanTitle = response.content
|
||||
.trim()
|
||||
.replace(/^["']|["']$/g, '')
|
||||
.replace(/\.$/g, '');
|
||||
// Clean up title
|
||||
let cleanTitle = response.content
|
||||
.trim()
|
||||
.replace(/^["']|["']$/g, '')
|
||||
.replace(/\.$/g, '');
|
||||
|
||||
if (cleanTitle.length > 100) {
|
||||
cleanTitle = cleanTitle.substring(0, 97) + '...';
|
||||
}
|
||||
if (cleanTitle.length > 100) {
|
||||
cleanTitle = cleanTitle.substring(0, 97) + '...';
|
||||
}
|
||||
|
||||
console.log('Generierter Titel:', cleanTitle);
|
||||
return cleanTitle;
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Titelgenerierung:', error);
|
||||
return 'Neue Konversation';
|
||||
}
|
||||
console.log('Generierter Titel:', cleanTitle);
|
||||
return cleanTitle;
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Titelgenerierung:', error);
|
||||
return 'Neue Konversation';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert den Titel einer Konversation
|
||||
*/
|
||||
export async function updateConversationTitle(
|
||||
conversationId: string,
|
||||
title: string
|
||||
conversationId: string,
|
||||
title: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const success = await conversationApi.updateTitle(conversationId, title);
|
||||
try {
|
||||
const success = await conversationApi.updateTitle(conversationId, title);
|
||||
|
||||
if (!success) {
|
||||
console.error('Fehler beim Aktualisieren des Konversationstitels');
|
||||
return false;
|
||||
}
|
||||
if (!success) {
|
||||
console.error('Fehler beim Aktualisieren des Konversationstitels');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Aktualisieren des Konversationstitels:', error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Aktualisieren des Konversationstitels:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt einen System-Prompt aus einer Vorlage
|
||||
*/
|
||||
export async function getSystemPromptFromTemplate(templateId: string): Promise<string | null> {
|
||||
try {
|
||||
const template = await templateApi.getTemplate(templateId);
|
||||
try {
|
||||
const template = await templateApi.getTemplate(templateId);
|
||||
|
||||
if (!template) {
|
||||
console.error('Fehler beim Laden der Vorlage');
|
||||
return null;
|
||||
}
|
||||
if (!template) {
|
||||
console.error('Fehler beim Laden der Vorlage');
|
||||
return null;
|
||||
}
|
||||
|
||||
return template.systemPrompt;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
return template.systemPrompt;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sendet eine Benutzeranfrage an das LLM-Modell und speichert die Antwort
|
||||
*/
|
||||
export async function sendMessageAndGetResponse(
|
||||
conversationId: string,
|
||||
userMessage: string,
|
||||
modelId: string,
|
||||
templateId?: string,
|
||||
documentMode: boolean = false
|
||||
conversationId: string,
|
||||
userMessage: string,
|
||||
modelId: string,
|
||||
templateId?: string,
|
||||
documentMode: boolean = false
|
||||
): Promise<{
|
||||
userMessageId: string | null;
|
||||
assistantMessageId: string | null;
|
||||
assistantResponse: string;
|
||||
title?: string;
|
||||
documentContent?: string;
|
||||
userMessageId: string | null;
|
||||
assistantMessageId: string | null;
|
||||
assistantResponse: string;
|
||||
title?: string;
|
||||
documentContent?: string;
|
||||
}> {
|
||||
try {
|
||||
console.log('Starte sendMessageAndGetResponse mit:', {
|
||||
conversationId,
|
||||
userMessage: userMessage.substring(0, 50) + (userMessage.length > 50 ? '...' : ''),
|
||||
modelId,
|
||||
});
|
||||
try {
|
||||
console.log('Starte sendMessageAndGetResponse mit:', {
|
||||
conversationId,
|
||||
userMessage: userMessage.substring(0, 50) + (userMessage.length > 50 ? '...' : ''),
|
||||
modelId,
|
||||
});
|
||||
|
||||
// Load the model from API
|
||||
const modelData = await modelApi.getModel(modelId);
|
||||
// Load the model from API
|
||||
const modelData = await modelApi.getModel(modelId);
|
||||
|
||||
if (!modelData) {
|
||||
console.log('Verwende Standard-Parameter, da Modell nicht geladen werden konnte');
|
||||
} else {
|
||||
console.log('Modell geladen:', {
|
||||
id: modelData.id,
|
||||
name: modelData.name,
|
||||
parameters: modelData.parameters,
|
||||
deployment: modelData.parameters?.deployment,
|
||||
});
|
||||
}
|
||||
if (!modelData) {
|
||||
console.log('Verwende Standard-Parameter, da Modell nicht geladen werden konnte');
|
||||
} else {
|
||||
console.log('Modell geladen:', {
|
||||
id: modelData.id,
|
||||
name: modelData.name,
|
||||
parameters: modelData.parameters,
|
||||
deployment: modelData.parameters?.deployment,
|
||||
});
|
||||
}
|
||||
|
||||
// Save the user message
|
||||
const userMessageId = await addMessage(conversationId, 'user', userMessage);
|
||||
console.log('Benutzernachricht gespeichert mit ID:', userMessageId);
|
||||
// Save the user message
|
||||
const userMessageId = await addMessage(conversationId, 'user', userMessage);
|
||||
console.log('Benutzernachricht gespeichert mit ID:', userMessageId);
|
||||
|
||||
// Load all messages for context
|
||||
const messages = await getMessages(conversationId);
|
||||
console.log(`${messages.length} Nachrichten für Kontext geladen`);
|
||||
// Load all messages for context
|
||||
const messages = await getMessages(conversationId);
|
||||
console.log(`${messages.length} Nachrichten für Kontext geladen`);
|
||||
|
||||
// Build chat messages for API
|
||||
const chatMessages: ChatMessage[] = [];
|
||||
// Build chat messages for API
|
||||
const chatMessages: ChatMessage[] = [];
|
||||
|
||||
// Load system prompt from template if available
|
||||
let systemPrompt: string | null = null;
|
||||
if (templateId) {
|
||||
systemPrompt = await getSystemPromptFromTemplate(templateId);
|
||||
if (systemPrompt) {
|
||||
console.log('System-Prompt aus Vorlage geladen');
|
||||
// Load system prompt from template if available
|
||||
let systemPrompt: string | null = null;
|
||||
if (templateId) {
|
||||
systemPrompt = await getSystemPromptFromTemplate(templateId);
|
||||
if (systemPrompt) {
|
||||
console.log('System-Prompt aus Vorlage geladen');
|
||||
|
||||
if (documentMode) {
|
||||
const documentModePrompt = `
|
||||
if (documentMode) {
|
||||
const documentModePrompt = `
|
||||
${systemPrompt}
|
||||
|
||||
WICHTIG: Du befindest dich im Dokumentmodus. Deine Aufgabe ist es, dem Benutzer zu helfen, ein Dokument zu erstellen und zu verbessern.
|
||||
|
|
@ -311,14 +311,14 @@ CHAT: Hier antwortest du auf die Frage oder das Feedback des Nutzers.
|
|||
DOKUMENT:
|
||||
Hier steht dein Vorschlag für das Dokument in Markdown-Format, ohne Codeblock-Markierungen.
|
||||
`;
|
||||
chatMessages.push({ role: 'system', content: documentModePrompt });
|
||||
console.log('Dokumentmodus-Prompt hinzugefügt');
|
||||
} else {
|
||||
chatMessages.push({ role: 'system', content: systemPrompt });
|
||||
}
|
||||
}
|
||||
} else if (documentMode) {
|
||||
const documentModePrompt = `
|
||||
chatMessages.push({ role: 'system', content: documentModePrompt });
|
||||
console.log('Dokumentmodus-Prompt hinzugefügt');
|
||||
} else {
|
||||
chatMessages.push({ role: 'system', content: systemPrompt });
|
||||
}
|
||||
}
|
||||
} else if (documentMode) {
|
||||
const documentModePrompt = `
|
||||
Du befindest dich im Dokumentmodus. Deine Aufgabe ist es, dem Benutzer zu helfen, ein Dokument zu erstellen und zu verbessern.
|
||||
|
||||
1. Das Dokument wird in einem separaten Bereich neben dem Chat angezeigt.
|
||||
|
|
@ -332,219 +332,219 @@ CHAT: Hier antwortest du auf die Frage oder das Feedback des Nutzers.
|
|||
DOKUMENT:
|
||||
Hier steht dein Vorschlag für das Dokument in Markdown-Format, ohne Codeblock-Markierungen.
|
||||
`;
|
||||
chatMessages.push({ role: 'system', content: documentModePrompt });
|
||||
console.log('Standard-Dokumentmodus-Prompt hinzugefügt');
|
||||
}
|
||||
chatMessages.push({ role: 'system', content: documentModePrompt });
|
||||
console.log('Standard-Dokumentmodus-Prompt hinzugefügt');
|
||||
}
|
||||
|
||||
// Add all conversation messages
|
||||
chatMessages.push(
|
||||
...messages.map((msg) => ({
|
||||
role: msg.sender === 'user' ? 'user' : msg.sender === 'assistant' ? 'assistant' : 'system',
|
||||
content: msg.message_text,
|
||||
})) as ChatMessage[]
|
||||
);
|
||||
// Add all conversation messages
|
||||
chatMessages.push(
|
||||
...(messages.map((msg) => ({
|
||||
role: msg.sender === 'user' ? 'user' : msg.sender === 'assistant' ? 'assistant' : 'system',
|
||||
content: msg.message_text,
|
||||
})) as ChatMessage[])
|
||||
);
|
||||
|
||||
console.log('Nachrichten für OpenAI konvertiert:', chatMessages.length, 'Nachrichten');
|
||||
console.log('Nachrichten für OpenAI konvertiert:', chatMessages.length, 'Nachrichten');
|
||||
|
||||
// Send request to AI
|
||||
console.log('Sende Anfrage an LLM-Modell mit Parametern:', {
|
||||
temperature: modelData?.parameters?.temperature || 0.7,
|
||||
maxTokens: modelData?.parameters?.max_tokens || 800,
|
||||
});
|
||||
// Send request to AI
|
||||
console.log('Sende Anfrage an LLM-Modell mit Parametern:', {
|
||||
temperature: modelData?.parameters?.temperature || 0.7,
|
||||
maxTokens: modelData?.parameters?.max_tokens || 800,
|
||||
});
|
||||
|
||||
const result = await chatApi.createCompletion({
|
||||
messages: chatMessages,
|
||||
modelId,
|
||||
temperature: modelData?.parameters?.temperature || 0.7,
|
||||
maxTokens: modelData?.parameters?.max_tokens || 800,
|
||||
});
|
||||
const result = await chatApi.createCompletion({
|
||||
messages: chatMessages,
|
||||
modelId,
|
||||
temperature: modelData?.parameters?.temperature || 0.7,
|
||||
maxTokens: modelData?.parameters?.max_tokens || 800,
|
||||
});
|
||||
|
||||
let assistantResponse: string;
|
||||
let tokenUsage: TokenUsage | undefined;
|
||||
let assistantResponse: string;
|
||||
let tokenUsage: TokenUsage | undefined;
|
||||
|
||||
if (!result) {
|
||||
assistantResponse =
|
||||
'Es konnte keine Antwort generiert werden. Bitte stelle sicher, dass das Backend läuft.';
|
||||
} else {
|
||||
assistantResponse = result.content;
|
||||
tokenUsage = result.usage;
|
||||
if (!result) {
|
||||
assistantResponse =
|
||||
'Es konnte keine Antwort generiert werden. Bitte stelle sicher, dass das Backend läuft.';
|
||||
} else {
|
||||
assistantResponse = result.content;
|
||||
tokenUsage = result.usage;
|
||||
|
||||
console.log('Antwort vom LLM-Modell erhalten:', {
|
||||
length: assistantResponse.length,
|
||||
preview: assistantResponse.substring(0, 50) + (assistantResponse.length > 50 ? '...' : ''),
|
||||
tokenUsage,
|
||||
});
|
||||
}
|
||||
console.log('Antwort vom LLM-Modell erhalten:', {
|
||||
length: assistantResponse.length,
|
||||
preview: assistantResponse.substring(0, 50) + (assistantResponse.length > 50 ? '...' : ''),
|
||||
tokenUsage,
|
||||
});
|
||||
}
|
||||
|
||||
// Extract document content if in document mode
|
||||
let documentContent: string | undefined;
|
||||
let chatResponse = assistantResponse;
|
||||
// Extract document content if in document mode
|
||||
let documentContent: string | undefined;
|
||||
let chatResponse = assistantResponse;
|
||||
|
||||
if (documentMode) {
|
||||
console.log(
|
||||
'Analysiere LLM-Antwort für Dokumentextraktion:',
|
||||
assistantResponse.substring(0, 200) + '...'
|
||||
);
|
||||
if (documentMode) {
|
||||
console.log(
|
||||
'Analysiere LLM-Antwort für Dokumentextraktion:',
|
||||
assistantResponse.substring(0, 200) + '...'
|
||||
);
|
||||
|
||||
const chatMatch = assistantResponse.match(/CHAT:(.*?)(?=DOKUMENT:|$)/s);
|
||||
const documentMatch = assistantResponse.match(
|
||||
/DOKUMENT:[\s\n]*(```markdown|```|`markdown)?([^`].*?)(?:```|`+)?$/s
|
||||
);
|
||||
const chatMatch = assistantResponse.match(/CHAT:(.*?)(?=DOKUMENT:|$)/s);
|
||||
const documentMatch = assistantResponse.match(
|
||||
/DOKUMENT:[\s\n]*(```markdown|```|`markdown)?([^`].*?)(?:```|`+)?$/s
|
||||
);
|
||||
|
||||
console.log('Dokument-Regex Match:', documentMatch ? 'Ja' : 'Nein');
|
||||
console.log('Dokument-Regex Match:', documentMatch ? 'Ja' : 'Nein');
|
||||
|
||||
if (chatMatch && chatMatch[1]) {
|
||||
chatResponse = chatMatch[1].trim();
|
||||
console.log('Chat-Antwort extrahiert:', chatResponse.substring(0, 50) + '...');
|
||||
}
|
||||
if (chatMatch && chatMatch[1]) {
|
||||
chatResponse = chatMatch[1].trim();
|
||||
console.log('Chat-Antwort extrahiert:', chatResponse.substring(0, 50) + '...');
|
||||
}
|
||||
|
||||
if (documentMatch && documentMatch[2]) {
|
||||
documentContent = documentMatch[2].trim();
|
||||
console.log(
|
||||
'Dokument-Inhalt extrahiert:',
|
||||
(documentContent?.substring(0, 50) || '') + '...'
|
||||
);
|
||||
}
|
||||
}
|
||||
if (documentMatch && documentMatch[2]) {
|
||||
documentContent = documentMatch[2].trim();
|
||||
console.log(
|
||||
'Dokument-Inhalt extrahiert:',
|
||||
(documentContent?.substring(0, 50) || '') + '...'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Save assistant message
|
||||
const assistantMessageId = await addMessage(conversationId, 'assistant', chatResponse);
|
||||
console.log('Assistentenantwort gespeichert mit ID:', assistantMessageId);
|
||||
// Save assistant message
|
||||
const assistantMessageId = await addMessage(conversationId, 'assistant', chatResponse);
|
||||
console.log('Assistentenantwort gespeichert mit ID:', assistantMessageId);
|
||||
|
||||
// Log token usage if available
|
||||
if (tokenUsage && assistantMessageId && userMessageId) {
|
||||
try {
|
||||
const estimatedCost = calculateTokenCost(
|
||||
tokenUsage.prompt_tokens,
|
||||
tokenUsage.completion_tokens,
|
||||
modelData?.costSettings
|
||||
);
|
||||
// Log token usage if available
|
||||
if (tokenUsage && assistantMessageId && userMessageId) {
|
||||
try {
|
||||
const estimatedCost = calculateTokenCost(
|
||||
tokenUsage.prompt_tokens,
|
||||
tokenUsage.completion_tokens,
|
||||
modelData?.costSettings
|
||||
);
|
||||
|
||||
await usageApi.logTokenUsage({
|
||||
conversationId,
|
||||
messageId: assistantMessageId,
|
||||
modelId,
|
||||
promptTokens: tokenUsage.prompt_tokens,
|
||||
completionTokens: tokenUsage.completion_tokens,
|
||||
totalTokens: tokenUsage.total_tokens,
|
||||
estimatedCost,
|
||||
});
|
||||
console.log('Token-Nutzung erfolgreich geloggt');
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Loggen der Token-Nutzung:', error);
|
||||
}
|
||||
}
|
||||
await usageApi.logTokenUsage({
|
||||
conversationId,
|
||||
messageId: assistantMessageId,
|
||||
modelId,
|
||||
promptTokens: tokenUsage.prompt_tokens,
|
||||
completionTokens: tokenUsage.completion_tokens,
|
||||
totalTokens: tokenUsage.total_tokens,
|
||||
estimatedCost,
|
||||
});
|
||||
console.log('Token-Nutzung erfolgreich geloggt');
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Loggen der Token-Nutzung:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate title for new conversations
|
||||
const allMessages = await getMessages(conversationId);
|
||||
let title: string | undefined;
|
||||
// Generate title for new conversations
|
||||
const allMessages = await getMessages(conversationId);
|
||||
let title: string | undefined;
|
||||
|
||||
if (allMessages.length <= 2) {
|
||||
title = await generateConversationTitle(userMessage);
|
||||
if (allMessages.length <= 2) {
|
||||
title = await generateConversationTitle(userMessage);
|
||||
|
||||
if (title) {
|
||||
const success = await updateConversationTitle(conversationId, title);
|
||||
console.log('Konversationstitel aktualisiert:', success ? 'erfolgreich' : 'fehlgeschlagen');
|
||||
}
|
||||
}
|
||||
if (title) {
|
||||
const success = await updateConversationTitle(conversationId, title);
|
||||
console.log('Konversationstitel aktualisiert:', success ? 'erfolgreich' : 'fehlgeschlagen');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
userMessageId,
|
||||
assistantMessageId,
|
||||
assistantResponse: chatResponse,
|
||||
title,
|
||||
documentContent,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Senden der Nachricht:', error);
|
||||
return {
|
||||
userMessageId,
|
||||
assistantMessageId,
|
||||
assistantResponse: chatResponse,
|
||||
title,
|
||||
documentContent,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Senden der Nachricht:', error);
|
||||
|
||||
if (error instanceof Error) {
|
||||
console.error('Fehlerdetails:', {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
console.error('Fehlerdetails:', {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
userMessageId: null,
|
||||
assistantMessageId: null,
|
||||
assistantResponse: `Es ist ein Fehler aufgetreten: ${error instanceof Error ? error.message : 'Unbekannter Fehler'}. Bitte versuche es später erneut.`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
userMessageId: null,
|
||||
assistantMessageId: null,
|
||||
assistantResponse: `Es ist ein Fehler aufgetreten: ${error instanceof Error ? error.message : 'Unbekannter Fehler'}. Bitte versuche es später erneut.`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to calculate token cost
|
||||
function calculateTokenCost(
|
||||
promptTokens: number,
|
||||
completionTokens: number,
|
||||
costSettings?: { prompt_per_1k_tokens?: number; completion_per_1k_tokens?: number }
|
||||
promptTokens: number,
|
||||
completionTokens: number,
|
||||
costSettings?: { prompt_per_1k_tokens?: number; completion_per_1k_tokens?: number }
|
||||
): number {
|
||||
const promptCost = costSettings?.prompt_per_1k_tokens || 0.0001;
|
||||
const completionCost = costSettings?.completion_per_1k_tokens || 0.0002;
|
||||
const promptCost = costSettings?.prompt_per_1k_tokens || 0.0001;
|
||||
const completionCost = costSettings?.completion_per_1k_tokens || 0.0002;
|
||||
|
||||
const cost = (promptTokens * promptCost + completionTokens * completionCost) / 1000;
|
||||
return Number(cost.toFixed(6));
|
||||
const cost = (promptTokens * promptCost + completionTokens * completionCost) / 1000;
|
||||
return Number(cost.toFixed(6));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle aktiven (nicht archivierten) Konversationen eines Benutzers
|
||||
*/
|
||||
export async function getConversations(userId: string, spaceId?: string): Promise<Conversation[]> {
|
||||
try {
|
||||
const conversations = await conversationApi.getConversations(spaceId);
|
||||
return conversations.map(toLocalConversation);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Konversationen:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const conversations = await conversationApi.getConversations(spaceId);
|
||||
return conversations.map(toLocalConversation);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Konversationen:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle archivierten Konversationen eines Benutzers
|
||||
*/
|
||||
export async function getArchivedConversations(userId: string): Promise<Conversation[]> {
|
||||
try {
|
||||
const conversations = await conversationApi.getArchivedConversations();
|
||||
return conversations.map(toLocalConversation);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der archivierten Konversationen:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const conversations = await conversationApi.getArchivedConversations();
|
||||
return conversations.map(toLocalConversation);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der archivierten Konversationen:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Archiviert eine Konversation
|
||||
*/
|
||||
export async function archiveConversation(conversationId: string): Promise<boolean> {
|
||||
try {
|
||||
return await conversationApi.archiveConversation(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Archivieren der Konversation:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await conversationApi.archiveConversation(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Archivieren der Konversation:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stellt eine archivierte Konversation wieder her
|
||||
*/
|
||||
export async function unarchiveConversation(conversationId: string): Promise<boolean> {
|
||||
try {
|
||||
return await conversationApi.unarchiveConversation(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Wiederherstellen der Konversation:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await conversationApi.unarchiveConversation(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Wiederherstellen der Konversation:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht eine Konversation dauerhaft
|
||||
*/
|
||||
export async function deleteConversation(conversationId: string): Promise<boolean> {
|
||||
try {
|
||||
return await conversationApi.deleteConversation(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen der Konversation:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await conversationApi.deleteConversation(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen der Konversation:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,157 +5,157 @@ import { documentApi, type Document as ApiDocument } from './api';
|
|||
|
||||
// Re-export type with backwards-compatible naming (snake_case for mobile)
|
||||
export interface Document {
|
||||
id: string;
|
||||
conversation_id: string;
|
||||
version: number;
|
||||
content: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
id: string;
|
||||
conversation_id: string;
|
||||
version: number;
|
||||
content: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// Helper to convert API response to local format
|
||||
function toLocalDocument(doc: ApiDocument): Document {
|
||||
return {
|
||||
id: doc.id,
|
||||
conversation_id: doc.conversationId,
|
||||
version: doc.version,
|
||||
content: doc.content,
|
||||
created_at: doc.createdAt,
|
||||
updated_at: doc.updatedAt,
|
||||
};
|
||||
return {
|
||||
id: doc.id,
|
||||
conversation_id: doc.conversationId,
|
||||
version: doc.version,
|
||||
content: doc.content,
|
||||
created_at: doc.createdAt,
|
||||
updated_at: doc.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt ein neues Dokument in einer Konversation
|
||||
*/
|
||||
export async function createDocument(
|
||||
conversationId: string,
|
||||
content: string
|
||||
conversationId: string,
|
||||
content: string
|
||||
): Promise<Document | null> {
|
||||
try {
|
||||
console.log(
|
||||
`Erstelle Dokument für Konversation ${conversationId} mit Inhalt: ${content.substring(0, 50)}...`
|
||||
);
|
||||
try {
|
||||
console.log(
|
||||
`Erstelle Dokument für Konversation ${conversationId} mit Inhalt: ${content.substring(0, 50)}...`
|
||||
);
|
||||
|
||||
const document = await documentApi.createDocument(conversationId, content);
|
||||
const document = await documentApi.createDocument(conversationId, content);
|
||||
|
||||
if (!document) {
|
||||
console.error('Fehler beim Erstellen des Dokuments');
|
||||
return null;
|
||||
}
|
||||
if (!document) {
|
||||
console.error('Fehler beim Erstellen des Dokuments');
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log('Dokument erfolgreich erstellt:', document);
|
||||
return toLocalDocument(document);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen des Dokuments:', error);
|
||||
if (error instanceof Error) {
|
||||
console.error('Error details:', error.message, error.stack);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
console.log('Dokument erfolgreich erstellt:', document);
|
||||
return toLocalDocument(document);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen des Dokuments:', error);
|
||||
if (error instanceof Error) {
|
||||
console.error('Error details:', error.message, error.stack);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt eine neue Version eines Dokuments
|
||||
*/
|
||||
export async function createDocumentVersion(
|
||||
conversationId: string,
|
||||
content: string
|
||||
conversationId: string,
|
||||
content: string
|
||||
): Promise<Document | null> {
|
||||
try {
|
||||
const document = await documentApi.createDocumentVersion(conversationId, content);
|
||||
try {
|
||||
const document = await documentApi.createDocumentVersion(conversationId, content);
|
||||
|
||||
if (!document) {
|
||||
console.error('Fehler beim Erstellen der neuen Dokumentversion');
|
||||
return null;
|
||||
}
|
||||
if (!document) {
|
||||
console.error('Fehler beim Erstellen der neuen Dokumentversion');
|
||||
return null;
|
||||
}
|
||||
|
||||
return toLocalDocument(document);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen der neuen Dokumentversion:', error);
|
||||
return null;
|
||||
}
|
||||
return toLocalDocument(document);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen der neuen Dokumentversion:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt die aktuellste Version eines Dokuments für eine Konversation
|
||||
*/
|
||||
export async function getLatestDocument(conversationId: string): Promise<Document | null> {
|
||||
try {
|
||||
console.log(`Lade neuestes Dokument für Konversation ${conversationId}`);
|
||||
try {
|
||||
console.log(`Lade neuestes Dokument für Konversation ${conversationId}`);
|
||||
|
||||
const document = await documentApi.getLatestDocument(conversationId);
|
||||
const document = await documentApi.getLatestDocument(conversationId);
|
||||
|
||||
if (!document) {
|
||||
console.log('Kein Dokument gefunden');
|
||||
return null;
|
||||
}
|
||||
if (!document) {
|
||||
console.log('Kein Dokument gefunden');
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(`Neuestes Dokument gefunden: Version ${document.version}, ID ${document.id}`);
|
||||
return toLocalDocument(document);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden des aktuellen Dokuments:', error);
|
||||
return null;
|
||||
}
|
||||
console.log(`Neuestes Dokument gefunden: Version ${document.version}, ID ${document.id}`);
|
||||
return toLocalDocument(document);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden des aktuellen Dokuments:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Versionen eines Dokuments für eine Konversation
|
||||
*/
|
||||
export async function getAllDocumentVersions(conversationId: string): Promise<Document[]> {
|
||||
try {
|
||||
console.log(`Lade alle Dokumentversionen für Konversation ${conversationId}`);
|
||||
try {
|
||||
console.log(`Lade alle Dokumentversionen für Konversation ${conversationId}`);
|
||||
|
||||
const documents = await documentApi.getAllDocumentVersions(conversationId);
|
||||
const documents = await documentApi.getAllDocumentVersions(conversationId);
|
||||
|
||||
console.log(`${documents.length} Dokumentversionen geladen`);
|
||||
console.log(`${documents.length} Dokumentversionen geladen`);
|
||||
|
||||
if (documents.length > 0) {
|
||||
console.log(`Erstes Dokument: ID=${documents[0].id}, Version=${documents[0].version}`);
|
||||
} else {
|
||||
console.log('Keine Dokumente gefunden');
|
||||
}
|
||||
if (documents.length > 0) {
|
||||
console.log(`Erstes Dokument: ID=${documents[0].id}, Version=${documents[0].version}`);
|
||||
} else {
|
||||
console.log('Keine Dokumente gefunden');
|
||||
}
|
||||
|
||||
return documents.map(toLocalDocument);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Dokumentversionen:', error);
|
||||
return [];
|
||||
}
|
||||
return documents.map(toLocalDocument);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Dokumentversionen:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob für eine Konversation ein Dokument existiert
|
||||
*/
|
||||
export async function hasDocument(conversationId: string): Promise<boolean> {
|
||||
try {
|
||||
return await documentApi.hasDocument(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Prüfen auf Dokument:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await documentApi.hasDocument(conversationId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Prüfen auf Dokument:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht eine spezifische Dokumentversion
|
||||
*/
|
||||
export async function deleteDocumentVersion(documentId: string): Promise<boolean> {
|
||||
try {
|
||||
console.log(`=== LÖSCH-OPERATION GESTARTET FÜR DOKUMENT ID ${documentId} ===`);
|
||||
try {
|
||||
console.log(`=== LÖSCH-OPERATION GESTARTET FÜR DOKUMENT ID ${documentId} ===`);
|
||||
|
||||
const success = await documentApi.deleteDocumentVersion(documentId);
|
||||
const success = await documentApi.deleteDocumentVersion(documentId);
|
||||
|
||||
if (success) {
|
||||
console.log(`=== DOKUMENT ${documentId} ERFOLGREICH GELÖSCHT ===`);
|
||||
} else {
|
||||
console.error('Fehler beim Löschen der Dokumentversion');
|
||||
}
|
||||
if (success) {
|
||||
console.log(`=== DOKUMENT ${documentId} ERFOLGREICH GELÖSCHT ===`);
|
||||
} else {
|
||||
console.error('Fehler beim Löschen der Dokumentversion');
|
||||
}
|
||||
|
||||
return success;
|
||||
} catch (error) {
|
||||
console.error('Unerwarteter Fehler beim Löschen der Dokumentversion:', error);
|
||||
if (error instanceof Error) {
|
||||
console.error('Fehlerstack:', error.stack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
} catch (error) {
|
||||
console.error('Unerwarteter Fehler beim Löschen der Dokumentversion:', error);
|
||||
if (error instanceof Error) {
|
||||
console.error('Fehlerstack:', error.stack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ import { availableModels } from '../config/azure';
|
|||
|
||||
// Typendefinition für ein KI-Modell
|
||||
export interface Model {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
parameters?: {
|
||||
temperature?: number;
|
||||
max_tokens?: number;
|
||||
provider?: string;
|
||||
deployment?: string;
|
||||
endpoint?: string;
|
||||
api_version?: string;
|
||||
};
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
parameters?: {
|
||||
temperature?: number;
|
||||
max_tokens?: number;
|
||||
provider?: string;
|
||||
deployment?: string;
|
||||
endpoint?: string;
|
||||
api_version?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -23,14 +23,14 @@ export interface Model {
|
|||
* @returns Eine Liste von verfügbaren Modellen
|
||||
*/
|
||||
export async function getModels(): Promise<Model[]> {
|
||||
try {
|
||||
// In einer echten Anwendung würde hier eine API-Anfrage erfolgen
|
||||
// Für jetzt verwenden wir die Fallback-Modelle aus der Konfiguration
|
||||
return availableModels;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Modelle:', error);
|
||||
return availableModels; // Fallback auf lokale Modelle
|
||||
}
|
||||
try {
|
||||
// In einer echten Anwendung würde hier eine API-Anfrage erfolgen
|
||||
// Für jetzt verwenden wir die Fallback-Modelle aus der Konfiguration
|
||||
return availableModels;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Modelle:', error);
|
||||
return availableModels; // Fallback auf lokale Modelle
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -39,14 +39,14 @@ export async function getModels(): Promise<Model[]> {
|
|||
* @returns Das Modell oder undefined, wenn nicht gefunden
|
||||
*/
|
||||
export async function getModelById(id: string): Promise<Model | undefined> {
|
||||
try {
|
||||
const models = await getModels();
|
||||
return models.find(model => model.id === id);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen des Modells:', error);
|
||||
// Fallback: Suche in lokalen Modellen
|
||||
return availableModels.find(model => model.id === id);
|
||||
}
|
||||
try {
|
||||
const models = await getModels();
|
||||
return models.find((model) => model.id === id);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen des Modells:', error);
|
||||
// Fallback: Suche in lokalen Modellen
|
||||
return availableModels.find((model) => model.id === id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -54,11 +54,11 @@ export async function getModelById(id: string): Promise<Model | undefined> {
|
|||
* @returns Das Standard-Modell
|
||||
*/
|
||||
export async function getDefaultModel(): Promise<Model> {
|
||||
try {
|
||||
const models = await getModels();
|
||||
return models[0]; // Das erste Modell in der Liste als Standard
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen des Standard-Modells:', error);
|
||||
return availableModels[0]; // Fallback auf lokales Standard-Modell
|
||||
}
|
||||
}
|
||||
try {
|
||||
const models = await getModels();
|
||||
return models[0]; // Das erste Modell in der Liste als Standard
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen des Standard-Modells:', error);
|
||||
return availableModels[0]; // Fallback auf lokales Standard-Modell
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,188 +13,188 @@ export type { TokenUsage };
|
|||
|
||||
// Chat response type (kept for compatibility)
|
||||
export type ChatResponse = {
|
||||
id: string;
|
||||
choices: {
|
||||
content_filter_results?: any;
|
||||
finish_reason: string;
|
||||
index: number;
|
||||
logprobs: any;
|
||||
message?: {
|
||||
content: string;
|
||||
refusal?: any;
|
||||
role: string;
|
||||
};
|
||||
}[];
|
||||
created: number;
|
||||
model: string;
|
||||
object: string;
|
||||
prompt_filter_results?: any[];
|
||||
system_fingerprint?: string;
|
||||
usage: {
|
||||
prompt_tokens: number;
|
||||
completion_tokens: number;
|
||||
total_tokens: number;
|
||||
completion_tokens_details?: any;
|
||||
prompt_tokens_details?: any;
|
||||
};
|
||||
id: string;
|
||||
choices: {
|
||||
content_filter_results?: any;
|
||||
finish_reason: string;
|
||||
index: number;
|
||||
logprobs: any;
|
||||
message?: {
|
||||
content: string;
|
||||
refusal?: any;
|
||||
role: string;
|
||||
};
|
||||
}[];
|
||||
created: number;
|
||||
model: string;
|
||||
object: string;
|
||||
prompt_filter_results?: any[];
|
||||
system_fingerprint?: string;
|
||||
usage: {
|
||||
prompt_tokens: number;
|
||||
completion_tokens: number;
|
||||
total_tokens: number;
|
||||
completion_tokens_details?: any;
|
||||
prompt_tokens_details?: any;
|
||||
};
|
||||
};
|
||||
|
||||
// Return type for chat request
|
||||
export type ChatRequestResult = {
|
||||
content: string;
|
||||
usage: TokenUsage;
|
||||
content: string;
|
||||
usage: TokenUsage;
|
||||
};
|
||||
|
||||
// Logging configuration
|
||||
console.log('Chat Service Konfiguration:', {
|
||||
backendUrl: process.env.EXPO_PUBLIC_BACKEND_URL || 'http://localhost:3001',
|
||||
availableModels: availableModels.length,
|
||||
backendUrl: process.env.EXPO_PUBLIC_BACKEND_URL || 'http://localhost:3001',
|
||||
availableModels: availableModels.length,
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates estimated cost for an LLM request
|
||||
*/
|
||||
export async function calculateTokenCost(
|
||||
promptTokens: number,
|
||||
completionTokens: number,
|
||||
modelId: string
|
||||
promptTokens: number,
|
||||
completionTokens: number,
|
||||
modelId: string
|
||||
): Promise<number> {
|
||||
try {
|
||||
// Get cost settings from model
|
||||
const modelData = await modelApi.getModel(modelId);
|
||||
try {
|
||||
// Get cost settings from model
|
||||
const modelData = await modelApi.getModel(modelId);
|
||||
|
||||
if (!modelData || !modelData.costSettings) {
|
||||
console.warn('Fehler beim Laden der Kosteninformationen, verwende Standardwerte');
|
||||
const promptCost = 0.0001;
|
||||
const completionCost = 0.0002;
|
||||
if (!modelData || !modelData.costSettings) {
|
||||
console.warn('Fehler beim Laden der Kosteninformationen, verwende Standardwerte');
|
||||
const promptCost = 0.0001;
|
||||
const completionCost = 0.0002;
|
||||
|
||||
const cost = (promptTokens * promptCost + completionTokens * completionCost) / 1000;
|
||||
return Number(cost.toFixed(6));
|
||||
}
|
||||
const cost = (promptTokens * promptCost + completionTokens * completionCost) / 1000;
|
||||
return Number(cost.toFixed(6));
|
||||
}
|
||||
|
||||
const promptCost = modelData.costSettings.prompt_per_1k_tokens || 0.0001;
|
||||
const completionCost = modelData.costSettings.completion_per_1k_tokens || 0.0002;
|
||||
const promptCost = modelData.costSettings.prompt_per_1k_tokens || 0.0001;
|
||||
const completionCost = modelData.costSettings.completion_per_1k_tokens || 0.0002;
|
||||
|
||||
const cost = (promptTokens * promptCost + completionTokens * completionCost) / 1000;
|
||||
return Number(cost.toFixed(6));
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Kostenberechnung:', error);
|
||||
return Number(((promptTokens * 0.0001 + completionTokens * 0.0002) / 1000).toFixed(6));
|
||||
}
|
||||
const cost = (promptTokens * promptCost + completionTokens * completionCost) / 1000;
|
||||
return Number(cost.toFixed(6));
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Kostenberechnung:', error);
|
||||
return Number(((promptTokens * 0.0001 + completionTokens * 0.0002) / 1000).toFixed(6));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs token usage to the database
|
||||
*/
|
||||
export async function logTokenUsage(
|
||||
usage: TokenUsage,
|
||||
conversationId: string,
|
||||
messageId: string,
|
||||
userId: string,
|
||||
modelId: string
|
||||
usage: TokenUsage,
|
||||
conversationId: string,
|
||||
messageId: string,
|
||||
userId: string,
|
||||
modelId: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
const estimatedCost = await calculateTokenCost(
|
||||
usage.prompt_tokens,
|
||||
usage.completion_tokens,
|
||||
modelId
|
||||
);
|
||||
try {
|
||||
const estimatedCost = await calculateTokenCost(
|
||||
usage.prompt_tokens,
|
||||
usage.completion_tokens,
|
||||
modelId
|
||||
);
|
||||
|
||||
const success = await usageApi.logTokenUsage({
|
||||
conversationId,
|
||||
messageId,
|
||||
modelId,
|
||||
promptTokens: usage.prompt_tokens,
|
||||
completionTokens: usage.completion_tokens,
|
||||
totalTokens: usage.total_tokens,
|
||||
estimatedCost,
|
||||
});
|
||||
const success = await usageApi.logTokenUsage({
|
||||
conversationId,
|
||||
messageId,
|
||||
modelId,
|
||||
promptTokens: usage.prompt_tokens,
|
||||
completionTokens: usage.completion_tokens,
|
||||
totalTokens: usage.total_tokens,
|
||||
estimatedCost,
|
||||
});
|
||||
|
||||
if (success) {
|
||||
console.log('Token-Nutzung erfolgreich gespeichert:', {
|
||||
conversationId,
|
||||
messageId,
|
||||
totalTokens: usage.total_tokens,
|
||||
estimatedCost,
|
||||
});
|
||||
} else {
|
||||
console.error('Fehler beim Speichern der Token-Nutzung');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Loggen der Token-Nutzung:', error);
|
||||
}
|
||||
if (success) {
|
||||
console.log('Token-Nutzung erfolgreich gespeichert:', {
|
||||
conversationId,
|
||||
messageId,
|
||||
totalTokens: usage.total_tokens,
|
||||
estimatedCost,
|
||||
});
|
||||
} else {
|
||||
console.error('Fehler beim Speichern der Token-Nutzung');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Loggen der Token-Nutzung:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat request via the backend
|
||||
*/
|
||||
export async function sendChatRequest(
|
||||
messages: ChatMessage[],
|
||||
temperature: number = 0.7,
|
||||
maxTokens: number = 800
|
||||
messages: ChatMessage[],
|
||||
temperature: number = 0.7,
|
||||
maxTokens: number = 800
|
||||
): Promise<string | ChatRequestResult> {
|
||||
console.log('sendChatRequest gestartet mit:', {
|
||||
messagesCount: messages.length,
|
||||
maxTokens,
|
||||
});
|
||||
console.log('sendChatRequest gestartet mit:', {
|
||||
messagesCount: messages.length,
|
||||
maxTokens,
|
||||
});
|
||||
|
||||
try {
|
||||
// Find model deployment from system message
|
||||
let modelId = '550e8400-e29b-41d4-a716-446655440000'; // Default to GPT-O3-Mini
|
||||
try {
|
||||
// Find model deployment from system message
|
||||
let modelId = '550e8400-e29b-41d4-a716-446655440000'; // Default to GPT-O3-Mini
|
||||
|
||||
const systemMessage = messages.find(
|
||||
(msg) => msg.role === 'system' && msg.content.startsWith('MODEL:')
|
||||
);
|
||||
if (systemMessage) {
|
||||
const deployment = systemMessage.content.split(':')[1].trim();
|
||||
console.log('Modell in system Nachricht erkannt:', deployment);
|
||||
const systemMessage = messages.find(
|
||||
(msg) => msg.role === 'system' && msg.content.startsWith('MODEL:')
|
||||
);
|
||||
if (systemMessage) {
|
||||
const deployment = systemMessage.content.split(':')[1].trim();
|
||||
console.log('Modell in system Nachricht erkannt:', deployment);
|
||||
|
||||
// Map deployment to model ID
|
||||
const deploymentToModelId: Record<string, string> = {
|
||||
'gpt-o3-mini-se': '550e8400-e29b-41d4-a716-446655440000',
|
||||
'gpt-4o-mini-se': '550e8400-e29b-41d4-a716-446655440004',
|
||||
'gpt-4o-se': '550e8400-e29b-41d4-a716-446655440005',
|
||||
};
|
||||
// Map deployment to model ID
|
||||
const deploymentToModelId: Record<string, string> = {
|
||||
'gpt-o3-mini-se': '550e8400-e29b-41d4-a716-446655440000',
|
||||
'gpt-4o-mini-se': '550e8400-e29b-41d4-a716-446655440004',
|
||||
'gpt-4o-se': '550e8400-e29b-41d4-a716-446655440005',
|
||||
};
|
||||
|
||||
modelId = deploymentToModelId[deployment] || modelId;
|
||||
} else {
|
||||
console.warn('Keine System-Nachricht mit MODEL-Präfix gefunden!');
|
||||
}
|
||||
modelId = deploymentToModelId[deployment] || modelId;
|
||||
} else {
|
||||
console.warn('Keine System-Nachricht mit MODEL-Präfix gefunden!');
|
||||
}
|
||||
|
||||
console.log('Verwende Model ID:', modelId);
|
||||
console.log('Verwende Model ID:', modelId);
|
||||
|
||||
// Filter out MODEL: system messages before sending to API
|
||||
const filteredMessages = messages.filter(
|
||||
(msg) => !(msg.role === 'system' && msg.content.startsWith('MODEL:'))
|
||||
);
|
||||
// Filter out MODEL: system messages before sending to API
|
||||
const filteredMessages = messages.filter(
|
||||
(msg) => !(msg.role === 'system' && msg.content.startsWith('MODEL:'))
|
||||
);
|
||||
|
||||
// Send request to backend
|
||||
const result = await chatApi.createCompletion({
|
||||
messages: filteredMessages,
|
||||
modelId,
|
||||
temperature,
|
||||
maxTokens,
|
||||
});
|
||||
// Send request to backend
|
||||
const result = await chatApi.createCompletion({
|
||||
messages: filteredMessages,
|
||||
modelId,
|
||||
temperature,
|
||||
maxTokens,
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
return 'Es tut mir leid, aber ich konnte keine Antwort generieren. Bitte stelle sicher, dass das Backend läuft.';
|
||||
}
|
||||
if (!result) {
|
||||
return 'Es tut mir leid, aber ich konnte keine Antwort generieren. Bitte stelle sicher, dass das Backend läuft.';
|
||||
}
|
||||
|
||||
return {
|
||||
content: result.content,
|
||||
usage: result.usage,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Chat-Anfrage:', error);
|
||||
return {
|
||||
content: result.content,
|
||||
usage: result.usage,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Chat-Anfrage:', error);
|
||||
|
||||
if (error instanceof Error) {
|
||||
console.error('Fehlerdetails:', {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
console.error('Fehlerdetails:', {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
|
||||
return `Es tut mir leid, aber ich konnte keine Antwort generieren. Bitte stelle sicher, dass das Backend läuft. Fehlerdetails: ${error instanceof Error ? error.message : 'Unbekannter Fehler'}`;
|
||||
}
|
||||
return `Es tut mir leid, aber ich konnte keine Antwort generieren. Bitte stelle sicher, dass das Backend läuft. Fehlerdetails: ${error instanceof Error ? error.message : 'Unbekannter Fehler'}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,249 +5,249 @@ import { spaceApi, type Space as ApiSpace, type SpaceMember as ApiSpaceMember }
|
|||
|
||||
// Re-export types with backwards-compatible naming (snake_case for mobile)
|
||||
export type Space = {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
owner_id: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
is_archived: boolean;
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
owner_id: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
is_archived: boolean;
|
||||
};
|
||||
|
||||
export type SpaceMember = {
|
||||
id: string;
|
||||
space_id: string;
|
||||
user_id: string;
|
||||
role: 'owner' | 'admin' | 'member' | 'viewer';
|
||||
invitation_status: 'pending' | 'accepted' | 'declined';
|
||||
invited_by?: string;
|
||||
invited_at: string;
|
||||
joined_at?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
id: string;
|
||||
space_id: string;
|
||||
user_id: string;
|
||||
role: 'owner' | 'admin' | 'member' | 'viewer';
|
||||
invitation_status: 'pending' | 'accepted' | 'declined';
|
||||
invited_by?: string;
|
||||
invited_at: string;
|
||||
joined_at?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
// Helper to convert API response to local format
|
||||
function toLocalSpace(space: ApiSpace): Space {
|
||||
return {
|
||||
id: space.id,
|
||||
name: space.name,
|
||||
description: space.description,
|
||||
owner_id: space.ownerId,
|
||||
created_at: space.createdAt,
|
||||
updated_at: space.updatedAt,
|
||||
is_archived: space.isArchived,
|
||||
};
|
||||
return {
|
||||
id: space.id,
|
||||
name: space.name,
|
||||
description: space.description,
|
||||
owner_id: space.ownerId,
|
||||
created_at: space.createdAt,
|
||||
updated_at: space.updatedAt,
|
||||
is_archived: space.isArchived,
|
||||
};
|
||||
}
|
||||
|
||||
function toLocalSpaceMember(member: ApiSpaceMember): SpaceMember {
|
||||
return {
|
||||
id: member.id,
|
||||
space_id: member.spaceId,
|
||||
user_id: member.userId,
|
||||
role: member.role,
|
||||
invitation_status: member.invitationStatus,
|
||||
invited_by: member.invitedBy,
|
||||
invited_at: member.invitedAt,
|
||||
joined_at: member.joinedAt,
|
||||
created_at: member.createdAt,
|
||||
updated_at: member.updatedAt,
|
||||
};
|
||||
return {
|
||||
id: member.id,
|
||||
space_id: member.spaceId,
|
||||
user_id: member.userId,
|
||||
role: member.role,
|
||||
invitation_status: member.invitationStatus,
|
||||
invited_by: member.invitedBy,
|
||||
invited_at: member.invitedAt,
|
||||
joined_at: member.joinedAt,
|
||||
created_at: member.createdAt,
|
||||
updated_at: member.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all spaces for a user (both owned and member of)
|
||||
*/
|
||||
export async function getUserSpaces(userId: string): Promise<Space[]> {
|
||||
try {
|
||||
const spaces = await spaceApi.getUserSpaces();
|
||||
return spaces.map(toLocalSpace);
|
||||
} catch (error) {
|
||||
console.error('Error in getUserSpaces:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const spaces = await spaceApi.getUserSpaces();
|
||||
return spaces.map(toLocalSpace);
|
||||
} catch (error) {
|
||||
console.error('Error in getUserSpaces:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get spaces the user owns
|
||||
*/
|
||||
export async function getOwnedSpaces(userId: string): Promise<Space[]> {
|
||||
try {
|
||||
const spaces = await spaceApi.getOwnedSpaces();
|
||||
return spaces.map(toLocalSpace);
|
||||
} catch (error) {
|
||||
console.error('Error in getOwnedSpaces:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const spaces = await spaceApi.getOwnedSpaces();
|
||||
return spaces.map(toLocalSpace);
|
||||
} catch (error) {
|
||||
console.error('Error in getOwnedSpaces:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single space by ID
|
||||
*/
|
||||
export async function getSpace(spaceId: string): Promise<Space | null> {
|
||||
try {
|
||||
const space = await spaceApi.getSpace(spaceId);
|
||||
if (!space) {
|
||||
return null;
|
||||
}
|
||||
return toLocalSpace(space);
|
||||
} catch (error) {
|
||||
console.error('Error in getSpace:', error);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const space = await spaceApi.getSpace(spaceId);
|
||||
if (!space) {
|
||||
return null;
|
||||
}
|
||||
return toLocalSpace(space);
|
||||
} catch (error) {
|
||||
console.error('Error in getSpace:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new space
|
||||
*/
|
||||
export async function createSpace(
|
||||
userId: string,
|
||||
name: string,
|
||||
description?: string
|
||||
userId: string,
|
||||
name: string,
|
||||
description?: string
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const space = await spaceApi.createSpace(name, description);
|
||||
return space?.id || null;
|
||||
} catch (error) {
|
||||
console.error('Error in createSpace:', error);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const space = await spaceApi.createSpace(name, description);
|
||||
return space?.id || null;
|
||||
} catch (error) {
|
||||
console.error('Error in createSpace:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a space
|
||||
*/
|
||||
export async function updateSpace(
|
||||
spaceId: string,
|
||||
updates: { name?: string; description?: string; is_archived?: boolean }
|
||||
spaceId: string,
|
||||
updates: { name?: string; description?: string; is_archived?: boolean }
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
return await spaceApi.updateSpace(spaceId, {
|
||||
name: updates.name,
|
||||
description: updates.description,
|
||||
isArchived: updates.is_archived,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in updateSpace:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.updateSpace(spaceId, {
|
||||
name: updates.name,
|
||||
description: updates.description,
|
||||
isArchived: updates.is_archived,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in updateSpace:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a space
|
||||
*/
|
||||
export async function deleteSpace(spaceId: string): Promise<boolean> {
|
||||
try {
|
||||
return await spaceApi.deleteSpace(spaceId);
|
||||
} catch (error) {
|
||||
console.error('Error in deleteSpace:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.deleteSpace(spaceId);
|
||||
} catch (error) {
|
||||
console.error('Error in deleteSpace:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get members of a space
|
||||
*/
|
||||
export async function getSpaceMembers(spaceId: string): Promise<SpaceMember[]> {
|
||||
try {
|
||||
const members = await spaceApi.getSpaceMembers(spaceId);
|
||||
return members.map(toLocalSpaceMember);
|
||||
} catch (error) {
|
||||
console.error('Error in getSpaceMembers:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const members = await spaceApi.getSpaceMembers(spaceId);
|
||||
return members.map(toLocalSpaceMember);
|
||||
} catch (error) {
|
||||
console.error('Error in getSpaceMembers:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a member to a space (invite)
|
||||
*/
|
||||
export async function inviteUserToSpace(
|
||||
spaceId: string,
|
||||
userId: string,
|
||||
invitedByUserId: string,
|
||||
role: 'admin' | 'member' | 'viewer' = 'member'
|
||||
spaceId: string,
|
||||
userId: string,
|
||||
invitedByUserId: string,
|
||||
role: 'admin' | 'member' | 'viewer' = 'member'
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
return await spaceApi.inviteUser(spaceId, userId, role);
|
||||
} catch (error) {
|
||||
console.error('Error in inviteUserToSpace:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.inviteUser(spaceId, userId, role);
|
||||
} catch (error) {
|
||||
console.error('Error in inviteUserToSpace:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept or decline a space invitation
|
||||
*/
|
||||
export async function respondToInvitation(
|
||||
spaceId: string,
|
||||
userId: string,
|
||||
status: 'accepted' | 'declined'
|
||||
spaceId: string,
|
||||
userId: string,
|
||||
status: 'accepted' | 'declined'
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
return await spaceApi.respondToInvitation(spaceId, status);
|
||||
} catch (error) {
|
||||
console.error('Error in respondToInvitation:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.respondToInvitation(spaceId, status);
|
||||
} catch (error) {
|
||||
console.error('Error in respondToInvitation:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a member from a space
|
||||
*/
|
||||
export async function removeMember(spaceId: string, userId: string): Promise<boolean> {
|
||||
try {
|
||||
return await spaceApi.removeMember(spaceId, userId);
|
||||
} catch (error) {
|
||||
console.error('Error in removeMember:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.removeMember(spaceId, userId);
|
||||
} catch (error) {
|
||||
console.error('Error in removeMember:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a member's role
|
||||
*/
|
||||
export async function changeMemberRole(
|
||||
spaceId: string,
|
||||
userId: string,
|
||||
newRole: 'admin' | 'member' | 'viewer'
|
||||
spaceId: string,
|
||||
userId: string,
|
||||
newRole: 'admin' | 'member' | 'viewer'
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
return await spaceApi.changeMemberRole(spaceId, userId, newRole);
|
||||
} catch (error) {
|
||||
console.error('Error in changeMemberRole:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.changeMemberRole(spaceId, userId, newRole);
|
||||
} catch (error) {
|
||||
console.error('Error in changeMemberRole:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's role in a space
|
||||
*/
|
||||
export async function getUserRoleInSpace(
|
||||
spaceId: string,
|
||||
userId: string
|
||||
spaceId: string,
|
||||
userId: string
|
||||
): Promise<'owner' | 'admin' | 'member' | 'viewer' | null> {
|
||||
try {
|
||||
return await spaceApi.getUserRoleInSpace(spaceId);
|
||||
} catch (error) {
|
||||
console.error('Error in getUserRoleInSpace:', error);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return await spaceApi.getUserRoleInSpace(spaceId);
|
||||
} catch (error) {
|
||||
console.error('Error in getUserRoleInSpace:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pending space invitations for a user
|
||||
*/
|
||||
export async function getPendingInvitations(
|
||||
userId: string
|
||||
userId: string
|
||||
): Promise<Array<{ invitation: SpaceMember; space: Space }>> {
|
||||
try {
|
||||
const invitations = await spaceApi.getPendingInvitations();
|
||||
return invitations.map((inv) => ({
|
||||
invitation: toLocalSpaceMember(inv.invitation),
|
||||
space: toLocalSpace(inv.space),
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error in getPendingInvitations:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const invitations = await spaceApi.getPendingInvitations();
|
||||
return invitations.map((inv) => ({
|
||||
invitation: toLocalSpaceMember(inv.invitation),
|
||||
space: toLocalSpace(inv.space),
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error in getPendingInvitations:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,159 +5,159 @@ import { templateApi, type Template as ApiTemplate } from './api';
|
|||
|
||||
// Re-export type with backwards-compatible naming (snake_case for mobile)
|
||||
export interface Template {
|
||||
id: string;
|
||||
user_id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
system_prompt: string;
|
||||
initial_question: string | null;
|
||||
model_id: string | null;
|
||||
color: string;
|
||||
is_default: boolean;
|
||||
document_mode: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
id: string;
|
||||
user_id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
system_prompt: string;
|
||||
initial_question: string | null;
|
||||
model_id: string | null;
|
||||
color: string;
|
||||
is_default: boolean;
|
||||
document_mode: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// Helper to convert API response to local format
|
||||
function toLocalTemplate(template: ApiTemplate): Template {
|
||||
return {
|
||||
id: template.id,
|
||||
user_id: template.userId,
|
||||
name: template.name,
|
||||
description: template.description || null,
|
||||
system_prompt: template.systemPrompt,
|
||||
initial_question: template.initialQuestion || null,
|
||||
model_id: template.modelId || null,
|
||||
color: template.color,
|
||||
is_default: template.isDefault,
|
||||
document_mode: template.documentMode,
|
||||
created_at: template.createdAt,
|
||||
updated_at: template.updatedAt,
|
||||
};
|
||||
return {
|
||||
id: template.id,
|
||||
user_id: template.userId,
|
||||
name: template.name,
|
||||
description: template.description || null,
|
||||
system_prompt: template.systemPrompt,
|
||||
initial_question: template.initialQuestion || null,
|
||||
model_id: template.modelId || null,
|
||||
color: template.color,
|
||||
is_default: template.isDefault,
|
||||
document_mode: template.documentMode,
|
||||
created_at: template.createdAt,
|
||||
updated_at: template.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Vorlagen eines Benutzers
|
||||
*/
|
||||
export async function getTemplates(userId: string): Promise<Template[]> {
|
||||
try {
|
||||
const templates = await templateApi.getTemplates();
|
||||
return templates.map(toLocalTemplate);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Vorlagen:', error);
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const templates = await templateApi.getTemplates();
|
||||
return templates.map(toLocalTemplate);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Vorlagen:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt eine bestimmte Vorlage anhand ihrer ID
|
||||
*/
|
||||
export async function getTemplateById(templateId: string): Promise<Template | null> {
|
||||
try {
|
||||
const template = await templateApi.getTemplate(templateId);
|
||||
if (!template) {
|
||||
return null;
|
||||
}
|
||||
return toLocalTemplate(template);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const template = await templateApi.getTemplate(templateId);
|
||||
if (!template) {
|
||||
return null;
|
||||
}
|
||||
return toLocalTemplate(template);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt eine neue Vorlage
|
||||
*/
|
||||
export async function createTemplate(
|
||||
template: Omit<Template, 'id' | 'created_at' | 'updated_at'>
|
||||
template: Omit<Template, 'id' | 'created_at' | 'updated_at'>
|
||||
): Promise<Template | null> {
|
||||
try {
|
||||
const result = await templateApi.createTemplate({
|
||||
name: template.name,
|
||||
description: template.description || undefined,
|
||||
systemPrompt: template.system_prompt,
|
||||
initialQuestion: template.initial_question || undefined,
|
||||
modelId: template.model_id || undefined,
|
||||
color: template.color,
|
||||
documentMode: template.document_mode,
|
||||
});
|
||||
try {
|
||||
const result = await templateApi.createTemplate({
|
||||
name: template.name,
|
||||
description: template.description || undefined,
|
||||
systemPrompt: template.system_prompt,
|
||||
initialQuestion: template.initial_question || undefined,
|
||||
modelId: template.model_id || undefined,
|
||||
color: template.color,
|
||||
documentMode: template.document_mode,
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
console.error('Fehler beim Erstellen der Vorlage');
|
||||
return null;
|
||||
}
|
||||
if (!result) {
|
||||
console.error('Fehler beim Erstellen der Vorlage');
|
||||
return null;
|
||||
}
|
||||
|
||||
return toLocalTemplate(result);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen der Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
return toLocalTemplate(result);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen der Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert eine bestehende Vorlage
|
||||
*/
|
||||
export async function updateTemplate(
|
||||
templateId: string,
|
||||
updates: Partial<Omit<Template, 'id' | 'user_id' | 'created_at' | 'updated_at'>>
|
||||
templateId: string,
|
||||
updates: Partial<Omit<Template, 'id' | 'user_id' | 'created_at' | 'updated_at'>>
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const apiUpdates: Parameters<typeof templateApi.updateTemplate>[1] = {};
|
||||
try {
|
||||
const apiUpdates: Parameters<typeof templateApi.updateTemplate>[1] = {};
|
||||
|
||||
if (updates.name !== undefined) apiUpdates.name = updates.name;
|
||||
if (updates.description !== undefined)
|
||||
apiUpdates.description = updates.description || undefined;
|
||||
if (updates.system_prompt !== undefined) apiUpdates.systemPrompt = updates.system_prompt;
|
||||
if (updates.initial_question !== undefined)
|
||||
apiUpdates.initialQuestion = updates.initial_question || undefined;
|
||||
if (updates.model_id !== undefined) apiUpdates.modelId = updates.model_id || undefined;
|
||||
if (updates.color !== undefined) apiUpdates.color = updates.color;
|
||||
if (updates.document_mode !== undefined) apiUpdates.documentMode = updates.document_mode;
|
||||
if (updates.name !== undefined) apiUpdates.name = updates.name;
|
||||
if (updates.description !== undefined)
|
||||
apiUpdates.description = updates.description || undefined;
|
||||
if (updates.system_prompt !== undefined) apiUpdates.systemPrompt = updates.system_prompt;
|
||||
if (updates.initial_question !== undefined)
|
||||
apiUpdates.initialQuestion = updates.initial_question || undefined;
|
||||
if (updates.model_id !== undefined) apiUpdates.modelId = updates.model_id || undefined;
|
||||
if (updates.color !== undefined) apiUpdates.color = updates.color;
|
||||
if (updates.document_mode !== undefined) apiUpdates.documentMode = updates.document_mode;
|
||||
|
||||
return await templateApi.updateTemplate(templateId, apiUpdates);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Aktualisieren der Vorlage:', error);
|
||||
return false;
|
||||
}
|
||||
return await templateApi.updateTemplate(templateId, apiUpdates);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Aktualisieren der Vorlage:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht eine Vorlage
|
||||
*/
|
||||
export async function deleteTemplate(templateId: string): Promise<boolean> {
|
||||
try {
|
||||
return await templateApi.deleteTemplate(templateId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen der Vorlage:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await templateApi.deleteTemplate(templateId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen der Vorlage:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt eine Vorlage als Standard
|
||||
*/
|
||||
export async function setDefaultTemplate(templateId: string, userId: string): Promise<boolean> {
|
||||
try {
|
||||
return await templateApi.setDefaultTemplate(templateId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Setzen der Standard-Vorlage:', error);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return await templateApi.setDefaultTemplate(templateId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Setzen der Standard-Vorlage:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt die Standard-Vorlage des Benutzers
|
||||
*/
|
||||
export async function getDefaultTemplate(userId: string): Promise<Template | null> {
|
||||
try {
|
||||
const template = await templateApi.getDefaultTemplate();
|
||||
if (!template) {
|
||||
return null;
|
||||
}
|
||||
return toLocalTemplate(template);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Standard-Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const template = await templateApi.getDefaultTemplate();
|
||||
if (!template) {
|
||||
return null;
|
||||
}
|
||||
return toLocalTemplate(template);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Standard-Vorlage:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue