mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-20 05:38:14 +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
+11
-2
@@ -8,6 +8,7 @@ import type { BrowserWindow } from 'electron';
|
||||
import { IPC, type WebhookStatus } from '../shared/ipc';
|
||||
import { normalizeHermesPush } from '../shared/hermesPush';
|
||||
import { log } from './logger';
|
||||
import { handleMcpHttp, MCP_PATH } from './mcp';
|
||||
|
||||
export const WEBHOOK_PATH = '/eveflow/hook';
|
||||
const MAX_BODY_BYTES = 2 * 1024 * 1024;
|
||||
@@ -57,9 +58,10 @@ export async function startWebhookServer(getWindow: () => BrowserWindow | null,
|
||||
};
|
||||
|
||||
if (req.method === 'GET' && (req.url === '/health' || req.url === '/')) {
|
||||
return json(200, { ok: true, app: 'eveflow', path: WEBHOOK_PATH });
|
||||
return json(200, { ok: true, app: 'eveflow', path: WEBHOOK_PATH, mcp: MCP_PATH });
|
||||
}
|
||||
if (req.method !== 'POST' || !req.url?.startsWith(WEBHOOK_PATH)) {
|
||||
const isMcp = !!req.url && (req.url === MCP_PATH || req.url.startsWith(`${MCP_PATH}?`));
|
||||
if (!isMcp && (req.method !== 'POST' || !req.url?.startsWith(WEBHOOK_PATH))) {
|
||||
return json(404, { error: 'Not Found' });
|
||||
}
|
||||
|
||||
@@ -91,6 +93,13 @@ export async function startWebhookServer(getWindow: () => BrowserWindow | null,
|
||||
if (tooLarge) return;
|
||||
// Concatenate before decoding so multibyte UTF-8 (accents, emoji) split across chunks stays intact.
|
||||
const body = Buffer.concat(chunks).toString('utf8');
|
||||
if (isMcp) {
|
||||
handleMcpHttp(getWindow(), req, res, body).catch((err: Error) => {
|
||||
log('ERROR', 'mcp', err.message);
|
||||
if (!res.headersSent) json(500, { error: err.message });
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const raw: unknown = body.trim() ? JSON.parse(body) : {};
|
||||
const events = normalizeHermesPush(raw);
|
||||
|
||||
Reference in new issue
Block a user