mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-20 21:58:56 +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
+22
-1
@@ -3,7 +3,9 @@ import { AlertTriangle, X } from 'lucide-react';
|
||||
import type { WindowMode } from '../shared/ipc';
|
||||
import { bridge } from './lib/bridge';
|
||||
import { Log } from './lib/log';
|
||||
import { handlePush, stopGeneration } from './services/conversation';
|
||||
import { handlePush, localToolContext, stopGeneration } from './services/conversation';
|
||||
import { initMcpBridge } from './services/mcpBridge';
|
||||
import { isQuietTime } from './lib/quietHours';
|
||||
import { speech } from './services/voice/speech';
|
||||
import { voiceController } from './services/voice/voiceController';
|
||||
import { useChat } from './state/chat';
|
||||
@@ -57,6 +59,7 @@ function useBoot(): boolean {
|
||||
})
|
||||
);
|
||||
disposers.push(api.hermes.onPush(handlePush));
|
||||
initMcpBridge(localToolContext);
|
||||
disposers.push(
|
||||
api.hotkeys.on((event) => {
|
||||
if (event === 'ptt-toggle') voiceController.toggle();
|
||||
@@ -95,6 +98,24 @@ function useBoot(): boolean {
|
||||
function useThemeSync(): void {
|
||||
const theme = useSettings((s) => s.settings.theme);
|
||||
const reduce = useSettings((s) => s.settings.ui.reduceMotion);
|
||||
// Quiet hours: computed every 30 s; dims the HUD (night theme) and silences pushes.
|
||||
const notif = useSettings((s) => s.settings.notifications);
|
||||
useEffect(() => {
|
||||
const tick = () => {
|
||||
const quiet = notif.quietEnabled && isQuietTime(notif.quietStart, notif.quietEnd);
|
||||
useChat.getState().setQuiet(quiet);
|
||||
document.documentElement.toggleAttribute('data-night', quiet && notif.nightTheme);
|
||||
};
|
||||
tick();
|
||||
const timer = setInterval(tick, 30_000);
|
||||
return () => clearInterval(timer);
|
||||
}, [notif]);
|
||||
useEffect(() => {
|
||||
const onVisible = () => { if (!document.hidden) useChat.getState().markRead(); };
|
||||
document.addEventListener('visibilitychange', onVisible);
|
||||
return () => document.removeEventListener('visibilitychange', onVisible);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.dataset.theme = theme;
|
||||
document.documentElement.dataset.motion = reduce ? 'reduce' : 'full';
|
||||
|
||||
Reference in new issue
Block a user