mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-17 20:28:43 +02:00
feat: serveur MCP, heures calmes, mode mission, widget glanceable, barge-in (v2.4.0) (#14)
Serveur MCP local - Endpoint /mcp (JSON-RPC 2.0, Streamable HTTP, réponses JSON) sur le serveur webhook : initialize, tools/list, tools/call, ping. Même secret que le webhook. 14 outils : capture_screen (image MCP), lock_session, open_app, open_url, media_key, clipboard_get/set, find_files, speak_text, notify_user, set_hud_state, get_app_status, get_conversation_history, show_message. Les outils UI transitent par IPC vers le renderer. - Les mêmes actions système sont proposées au modèle en chat completions. Notifications - Heures calmes (plage horaire, franchissement de minuit), mots prioritaires, échecs de crons toujours lus, résumé vocal des messages entrants (n premières phrases), thème nuit automatique, compteur de non-lus. Conversation - Mode mission : bouton dans la barre de commande, second modèle Hermes (hermes.missionModel) pour les tâches longues. - Barge-in : la parole de l'utilisateur coupe la voix ; seuil d'énergie et ratio relevés pendant la synthèse pour ignorer l'écho. Widget compact - Bandeau glanceable : état, dernière phrase, non-lus, indicateurs heures calmes et mission. Tests : 28 tests unitaires (heures calmes, priorité, résumé), e2e Electron sous Xvfb : MCP initialize/tools/list/tools/call (presse-papiers, capture en image, état et message via le renderer), bandeau compact, aucune erreur. Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
af8bdc5e9d
commit
6fc38d335b
24 files changed
+668
-31
No files matched your search
@@ -57,6 +57,16 @@ interface ChatStore {
|
||||
pingCount: number;
|
||||
/** Time to first token of the current reply, in ms. */
|
||||
latencyMs: number | null;
|
||||
/** Pushes received while the window was hidden / compact, cleared when the user looks. */
|
||||
unread: number;
|
||||
/** Mission mode routes the next messages to the "mission" model (long tasks). */
|
||||
missionMode: boolean;
|
||||
/** True while quiet hours apply (computed by App). */
|
||||
quiet: boolean;
|
||||
incUnread: () => void;
|
||||
markRead: () => void;
|
||||
setMissionMode: (on: boolean) => void;
|
||||
setQuiet: (quiet: boolean) => void;
|
||||
|
||||
addMessage: (message: Omit<ChatMessage, 'id' | 'timestamp'> & Partial<Pick<ChatMessage, 'id' | 'timestamp'>>) => string;
|
||||
updateMessage: (id: string, patch: Partial<ChatMessage> | ((m: ChatMessage) => Partial<ChatMessage>)) => void;
|
||||
@@ -91,6 +101,13 @@ export const useChat = create<ChatStore>((set, get) => ({
|
||||
draft: '',
|
||||
pingCount: 0,
|
||||
latencyMs: null,
|
||||
unread: 0,
|
||||
missionMode: false,
|
||||
quiet: false,
|
||||
incUnread: () => set((s) => ({ unread: Math.min(99, s.unread + 1) })),
|
||||
markRead: () => set((s) => (s.unread ? { unread: 0 } : {})),
|
||||
setMissionMode: (missionMode) => set({ missionMode }),
|
||||
setQuiet: (quiet) => set((s) => (s.quiet === quiet ? {} : { quiet })),
|
||||
|
||||
addMessage: (message) => {
|
||||
const id = message.id ?? uid('msg');
|
||||
|
||||
+3
-3
@@ -43,7 +43,7 @@ interface HermesStore {
|
||||
webhook: WebhookStatus | null;
|
||||
busy: boolean;
|
||||
|
||||
client: () => HermesClient;
|
||||
client: (modelOverride?: string) => HermesClient;
|
||||
connect: () => Promise<void>;
|
||||
refreshJobs: () => Promise<void>;
|
||||
refreshSessions: () => Promise<void>;
|
||||
@@ -93,10 +93,10 @@ export const useHermes = create<HermesStore>((set, get) => ({
|
||||
webhook: null,
|
||||
busy: false,
|
||||
|
||||
client: () => {
|
||||
client: (modelOverride) => {
|
||||
const config = useSettings.getState().settings.hermes;
|
||||
// Without an explicit model, use the alias advertised by /v1/models (Hermes rejects unknown names).
|
||||
const model = config.model.trim() || get().models[0]?.id || '';
|
||||
const model = (modelOverride ?? '').trim() || config.model.trim() || get().models[0]?.id || '';
|
||||
return new HermesClient({ ...config, model });
|
||||
},
|
||||
|
||||
|
||||
+18
-1
@@ -39,6 +39,20 @@ export interface WebhookSettings {
|
||||
secret: string;
|
||||
}
|
||||
|
||||
export interface NotificationSettings {
|
||||
/** Quiet hours: no spoken pushes, no chime, dimmed HUD (24 h "HH:MM"). */
|
||||
quietEnabled: boolean;
|
||||
quietStart: string;
|
||||
quietEnd: string;
|
||||
/** Pushes whose text or job name contains one of these words are spoken even during quiet hours. */
|
||||
priorityKeywords: string;
|
||||
/** Speak only the first sentences of incoming pushes (cron reports can be long). */
|
||||
summarizeIncoming: boolean;
|
||||
summarySentences: number;
|
||||
/** Dim the HUD (night theme) during quiet hours. */
|
||||
nightTheme: boolean;
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
version: 2;
|
||||
assistantName: string;
|
||||
@@ -49,6 +63,7 @@ export interface Settings {
|
||||
voice: VoiceSettings;
|
||||
speech: SpeechSettings;
|
||||
webhook: WebhookSettings;
|
||||
notifications: NotificationSettings;
|
||||
ui: {
|
||||
showTelemetry: boolean;
|
||||
showReasoning: boolean;
|
||||
@@ -73,7 +88,8 @@ export const DEFAULT_SETTINGS: Settings = {
|
||||
reasoningEffort: '',
|
||||
instructions:
|
||||
"Tu es l'interface vocale EveFlow (style JARVIS). Réponds en français, de façon concise et orale quand la question est simple; utilise le Markdown uniquement pour le contenu structuré (code, listes, tableaux). Les images doivent être des URL http(s) ou des fichiers du dossier partagé.",
|
||||
localTools: true
|
||||
localTools: true,
|
||||
missionModel: ''
|
||||
},
|
||||
voice: {
|
||||
provider: 'openai-compatible',
|
||||
@@ -113,6 +129,7 @@ export const DEFAULT_SETTINGS: Settings = {
|
||||
speakIncoming: true
|
||||
},
|
||||
webhook: { enabled: true, port: 7842, secret: '' },
|
||||
notifications: { quietEnabled: false, quietStart: '22:30', quietEnd: '07:30', priorityKeywords: 'urgent, alerte, alarme, panne', summarizeIncoming: true, summarySentences: 2, nightTheme: true },
|
||||
ui: { showTelemetry: true, showReasoning: false, reduceMotion: false, compactOpacity: 0.92 },
|
||||
hermesSessionId: ''
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user