mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-19 05:09:30 +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
@@ -0,0 +1,43 @@
|
||||
/** Quiet-hours and spoken-summary helpers (pure, unit tested). */
|
||||
|
||||
function minutesOf(hhmm: string): number | null {
|
||||
const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
|
||||
if (!m) return null;
|
||||
const h = Number(m[1]);
|
||||
const min = Number(m[2]);
|
||||
if (h > 23 || min > 59) return null;
|
||||
return h * 60 + min;
|
||||
}
|
||||
|
||||
/** True when `now` falls inside [start, end), with ranges crossing midnight ("22:30" → "07:30"). */
|
||||
export function isQuietTime(start: string, end: string, now: Date = new Date()): boolean {
|
||||
const s = minutesOf(start);
|
||||
const e = minutesOf(end);
|
||||
if (s === null || e === null || s === e) return false;
|
||||
const cur = now.getHours() * 60 + now.getMinutes();
|
||||
return s < e ? cur >= s && cur < e : cur >= s || cur < e;
|
||||
}
|
||||
|
||||
/** True when the text or job name contains one of the comma-separated priority words. */
|
||||
export function isPriority(text: string, keywords: string, jobName = ''): boolean {
|
||||
const words = keywords
|
||||
.split(/[,;\n]/)
|
||||
.map((w) => w.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
if (!words.length) return false;
|
||||
const hay = `${jobName} ${text}`.toLowerCase();
|
||||
return words.some((w) => hay.includes(w));
|
||||
}
|
||||
|
||||
/** First `count` sentences of a text, for a short spoken summary of a long push. */
|
||||
export function summarize(text: string, count: number): string {
|
||||
const clean = text
|
||||
.replace(/```[\s\S]*?```/g, ' ')
|
||||
.replace(/[#*_>`|]/g, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
if (!clean) return '';
|
||||
const sentences = clean.match(/[^.!?…]+[.!?…]+["»)]?\s*|[^.!?…]+$/g) ?? [clean];
|
||||
const picked = sentences.slice(0, Math.max(1, count)).join('').trim();
|
||||
return picked.length < clean.length ? picked : clean;
|
||||
}
|
||||
Reference in new issue
Block a user