docs: add complete guide, env files, fix docker-compose

- Add GUIDE.md: complete user documentation covering installation,
  Docker deployment, AI providers, MCP server, N8N integration,
  email config, admin panel, env var reference, troubleshooting
- Add mcp-server/.env.example with all MCP-specific variables
- Update .env.docker.example with all 42 environment variables
- Fix docker-compose.yml: parameterize PostgreSQL credentials,
  add missing env vars (CUSTOM_OPENAI, AI_PROVIDER_CHAT,
  ALLOW_REGISTRATION, RESEND_API_KEY)
- Track memento-note/.env.example
This commit is contained in:
Sepehr Ramezani
2026-04-20 22:57:09 +02:00
parent e4d4e23dc7
commit 5b7cbcbc49
23 changed files with 1054 additions and 996 deletions

View File

@@ -40,17 +40,17 @@ export class CustomOpenAIProvider implements AIProvider {
model: this.model,
schema: z.object({
tags: z.array(z.object({
tag: z.string().describe('Le nom du tag, court et en minuscules'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
tag: z.string().describe('Short tag name in lowercase'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: `Analyse la note suivante et suggère entre 1 et 5 tags pertinents.
Contenu de la note: "${content}"`,
prompt: `Analyze the following note and suggest 1 to 5 relevant tags.
Note content: "${content}"`,
});
return object.tags;
} catch (e) {
console.error('Erreur génération tags Custom OpenAI:', e);
console.error('Error generating tags (Custom OpenAI):', e);
return [];
}
}
@@ -63,7 +63,7 @@ export class CustomOpenAIProvider implements AIProvider {
});
return embedding;
} catch (e) {
console.error('Erreur embeddings Custom OpenAI:', e);
console.error('Error generating embeddings (Custom OpenAI):', e);
return [];
}
}
@@ -74,8 +74,8 @@ export class CustomOpenAIProvider implements AIProvider {
model: this.model,
schema: z.object({
titles: z.array(z.object({
title: z.string().describe('Le titre suggéré'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
title: z.string().describe('Suggested title'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: prompt,
@@ -83,7 +83,7 @@ export class CustomOpenAIProvider implements AIProvider {
return object.titles;
} catch (e) {
console.error('Erreur génération titres Custom OpenAI:', e);
console.error('Error generating titles (Custom OpenAI):', e);
return [];
}
}
@@ -97,7 +97,7 @@ export class CustomOpenAIProvider implements AIProvider {
return text.trim();
} catch (e) {
console.error('Erreur génération texte Custom OpenAI:', e);
console.error('Error generating text (Custom OpenAI):', e);
throw e;
}
}
@@ -112,7 +112,7 @@ export class CustomOpenAIProvider implements AIProvider {
return { text: text.trim() };
} catch (e) {
console.error('Erreur chat Custom OpenAI:', e);
console.error('Error in chat (Custom OpenAI):', e);
throw e;
}
}

View File

@@ -24,17 +24,17 @@ export class DeepSeekProvider implements AIProvider {
model: this.model,
schema: z.object({
tags: z.array(z.object({
tag: z.string().describe('Le nom du tag, court et en minuscules'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
tag: z.string().describe('Short tag name in lowercase'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: `Analyse la note suivante et suggère entre 1 et 5 tags pertinents.
Contenu de la note: "${content}"`,
prompt: `Analyze the following note and suggest 1 to 5 relevant tags.
Note content: "${content}"`,
});
return object.tags;
} catch (e) {
console.error('Erreur génération tags DeepSeek:', e);
console.error('Error generating tags (DeepSeek):', e);
return [];
}
}
@@ -47,7 +47,7 @@ export class DeepSeekProvider implements AIProvider {
});
return embedding;
} catch (e) {
console.error('Erreur embeddings DeepSeek:', e);
console.error('Error generating embeddings (DeepSeek):', e);
return [];
}
}
@@ -58,8 +58,8 @@ export class DeepSeekProvider implements AIProvider {
model: this.model,
schema: z.object({
titles: z.array(z.object({
title: z.string().describe('Le titre suggéré'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
title: z.string().describe('Suggested title'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: prompt,
@@ -67,7 +67,7 @@ export class DeepSeekProvider implements AIProvider {
return object.titles;
} catch (e) {
console.error('Erreur génération titres DeepSeek:', e);
console.error('Error generating titles (DeepSeek):', e);
return [];
}
}
@@ -81,7 +81,7 @@ export class DeepSeekProvider implements AIProvider {
return text.trim();
} catch (e) {
console.error('Erreur génération texte DeepSeek:', e);
console.error('Error generating text (DeepSeek):', e);
throw e;
}
}
@@ -96,7 +96,7 @@ export class DeepSeekProvider implements AIProvider {
return { text: text.trim() };
} catch (e) {
console.error('Erreur chat DeepSeek:', e);
console.error('Error in chat (DeepSeek):', e);
throw e;
}
}

View File

@@ -75,7 +75,7 @@ Note content: "${content}"`;
return JSON.parse(jsonMatch[0]);
}
// Support pour le format { "tags": [...] }
// Support for { "tags": [...] } format
const objectMatch = text.match(/\{\s*"tags"\s*:\s*(\[[\s\S]*\])\s*\}/);
if (objectMatch && objectMatch[1]) {
return JSON.parse(objectMatch[1]);
@@ -83,7 +83,7 @@ Note content: "${content}"`;
return [];
} catch (e) {
console.error('Erreur API directe Ollama:', e);
console.error('Error in Ollama API:', e);
return [];
}
}
@@ -104,7 +104,7 @@ Note content: "${content}"`;
const data = await response.json();
return data.embedding;
} catch (e) {
console.error('Erreur embeddings directs Ollama:', e);
console.error('Error generating embeddings (Ollama):', e);
return [];
}
}
@@ -116,7 +116,7 @@ Note content: "${content}"`;
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: this.modelName,
prompt: `${prompt}\n\nRéponds UNIQUEMENT sous forme de tableau JSON : [{"title": "string", "confidence": number}]`,
prompt: `${prompt}\n\nRespond ONLY as a JSON array: [{"title": "string", "confidence": number}]`,
stream: false,
}),
});
@@ -126,7 +126,7 @@ Note content: "${content}"`;
const data = await response.json();
const text = data.response;
// Extraire le JSON de la réponse
// Extract JSON from response
const jsonMatch = text.match(/\[\s*\{[\s\S]*\}\s*\]/);
if (jsonMatch) {
return JSON.parse(jsonMatch[0]);
@@ -134,7 +134,7 @@ Note content: "${content}"`;
return [];
} catch (e) {
console.error('Erreur génération titres Ollama:', e);
console.error('Error generating titles (Ollama):', e);
return [];
}
}
@@ -156,7 +156,7 @@ Note content: "${content}"`;
const data = await response.json();
return data.response.trim();
} catch (e) {
console.error('Erreur génération texte Ollama:', e);
console.error('Error generating text (Ollama):', e);
throw e;
}
}
@@ -187,7 +187,7 @@ Note content: "${content}"`;
const data = await response.json();
return { text: data.message?.content?.trim() || '' };
} catch (e) {
console.error('Erreur chat Ollama:', e);
console.error('Error in chat (Ollama):', e);
throw e;
}
}

View File

@@ -24,17 +24,17 @@ export class OpenAIProvider implements AIProvider {
model: this.model,
schema: z.object({
tags: z.array(z.object({
tag: z.string().describe('Le nom du tag, court et en minuscules'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
tag: z.string().describe('Short tag name in lowercase'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: `Analyse la note suivante et suggère entre 1 et 5 tags pertinents.
Contenu de la note: "${content}"`,
prompt: `Analyze the following note and suggest 1 to 5 relevant tags.
Note content: "${content}"`,
});
return object.tags;
} catch (e) {
console.error('Erreur génération tags OpenAI:', e);
console.error('Error generating tags (OpenAI):', e);
return [];
}
}
@@ -47,7 +47,7 @@ export class OpenAIProvider implements AIProvider {
});
return embedding;
} catch (e) {
console.error('Erreur embeddings OpenAI:', e);
console.error('Error generating embeddings (OpenAI):', e);
return [];
}
}
@@ -58,8 +58,8 @@ export class OpenAIProvider implements AIProvider {
model: this.model,
schema: z.object({
titles: z.array(z.object({
title: z.string().describe('Le titre suggéré'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
title: z.string().describe('Suggested title'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: prompt,
@@ -67,7 +67,7 @@ export class OpenAIProvider implements AIProvider {
return object.titles;
} catch (e) {
console.error('Erreur génération titres OpenAI:', e);
console.error('Error generating titles (OpenAI):', e);
return [];
}
}
@@ -81,7 +81,7 @@ export class OpenAIProvider implements AIProvider {
return text.trim();
} catch (e) {
console.error('Erreur génération texte OpenAI:', e);
console.error('Error generating text (OpenAI):', e);
throw e;
}
}
@@ -96,7 +96,7 @@ export class OpenAIProvider implements AIProvider {
return { text: text.trim() };
} catch (e) {
console.error('Erreur chat OpenAI:', e);
console.error('Error in chat (OpenAI):', e);
throw e;
}
}

View File

@@ -24,17 +24,17 @@ export class OpenRouterProvider implements AIProvider {
model: this.model,
schema: z.object({
tags: z.array(z.object({
tag: z.string().describe('Le nom du tag, court et en minuscules'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
tag: z.string().describe('Short tag name in lowercase'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: `Analyse la note suivante et suggère entre 1 et 5 tags pertinents.
Contenu de la note: "${content}"`,
prompt: `Analyze the following note and suggest 1 to 5 relevant tags.
Note content: "${content}"`,
});
return object.tags;
} catch (e) {
console.error('Erreur génération tags OpenRouter:', e);
console.error('Error generating tags (OpenRouter):', e);
return [];
}
}
@@ -47,7 +47,7 @@ export class OpenRouterProvider implements AIProvider {
});
return embedding;
} catch (e) {
console.error('Erreur embeddings OpenRouter:', e);
console.error('Error generating embeddings (OpenRouter):', e);
return [];
}
}
@@ -58,8 +58,8 @@ export class OpenRouterProvider implements AIProvider {
model: this.model,
schema: z.object({
titles: z.array(z.object({
title: z.string().describe('Le titre suggéré'),
confidence: z.number().min(0).max(1).describe('Le niveau de confiance entre 0 et 1')
title: z.string().describe('Suggested title'),
confidence: z.number().min(0).max(1).describe('Confidence level between 0 and 1')
}))
}),
prompt: prompt,
@@ -67,7 +67,7 @@ export class OpenRouterProvider implements AIProvider {
return object.titles;
} catch (e) {
console.error('Erreur génération titres OpenRouter:', e);
console.error('Error generating titles (OpenRouter):', e);
return [];
}
}
@@ -81,7 +81,7 @@ export class OpenRouterProvider implements AIProvider {
return text.trim();
} catch (e) {
console.error('Erreur génération texte OpenRouter:', e);
console.error('Error generating text (OpenRouter):', e);
throw e;
}
}
@@ -96,7 +96,7 @@ export class OpenRouterProvider implements AIProvider {
return { text: text.trim() };
} catch (e) {
console.error('Erreur chat OpenRouter:', e);
console.error('Error in chat (OpenRouter):', e);
throw e;
}
}