UNPKG

smart-thinking-mcp

Version:

Un serveur MCP avancé pour le raisonnement multi-dimensionnel, adaptatif et collaboratif

630 lines (619 loc) 34.9 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const platform_stdio_1 = require("./utils/platform-stdio"); const zod_1 = require("zod"); const thought_graph_1 = require("./thought-graph"); const memory_manager_1 = require("./memory-manager"); const tool_integrator_1 = require("./tool-integrator"); const quality_evaluator_1 = require("./quality-evaluator"); const visualizer_1 = require("./visualizer"); const embedding_service_1 = require("./embedding-service"); const metrics_calculator_1 = require("./metrics-calculator"); const verification_memory_1 = require("./verification-memory"); const service_container_1 = require("./services/service-container"); const path_1 = __importDefault(require("path")); const fs_1 = require("fs"); const config_1 = require("./config"); const path_utils_1 = require("./utils/path-utils"); const uuid_1 = require("uuid"); // Import UUID library /** * Point d'entrée du serveur MCP Smart-Thinking */ // Helper function to generate unique IDs function generateUniqueId() { return (0, uuid_1.v4)(); } // Protection contre les messages non-JSON envoyés à stdout const originalStdoutWrite = process.stdout.write; // Fonction de gestion des sorties pour éviter les problèmes de types const safeStdoutWrite = function () { const chunk = arguments[0]; if (typeof chunk === 'string') { const trimmed = chunk.trim(); // Si ça ressemble à du JSON mais n'en est pas if ((trimmed.startsWith('{') || trimmed.startsWith('[')) && !isValidJSON(trimmed)) { console.error('[ERREUR] JSON invalide détecté:', chunk); try { // Sur Windows, ajoutons un saut de ligne supplémentaire pour éviter les problèmes de buffering const safeMessage = JSON.stringify({ jsonrpc: "2.0", result: { content: [{ type: "text", text: chunk }] } }) + (config_1.PlatformConfig.IS_WINDOWS ? '\n' : ''); return originalStdoutWrite.call(process.stdout, safeMessage, arguments[1], arguments[2]); } catch (e) { console.error('[ERREUR] Impossible de corriger le JSON:', e); process.stderr.write(chunk, arguments[1]); if (typeof arguments[2] === 'function') arguments[2](); return true; } } // Si c'est du texte brut (non-JSON) if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) { console.error('[INFO] Texte non-JSON redirigé vers stderr:', chunk); process.stderr.write(chunk, arguments[1]); if (typeof arguments[2] === 'function') arguments[2](); return true; } } // Comportement normal pour le JSON valide ou les non-strings return originalStdoutWrite.apply(process.stdout, arguments); }; // Remplacer process.stdout.write par notre version sécurisée process.stdout.write = safeStdoutWrite; /** * Vérifie si une chaîne est un JSON valide * @param str Chaîne à vérifier * @returns true si la chaîne est un JSON valide */ function isValidJSON(str) { if (typeof str !== 'string') return false; const trimmed = str.trim(); if (!trimmed) return false; // Vérifier si la chaîne a une structure JSON de base if (!(trimmed.startsWith('{') && trimmed.endsWith('}')) && !(trimmed.startsWith('[') && trimmed.endsWith(']'))) { return false; } try { JSON.parse(trimmed); return true; } catch (e) { return false; } } // Récupérer les informations du package.json pour la version const packageInfo = require(path_1.default.join(__dirname, '..', 'package.json')); const version = packageInfo.version || '1.0.3'; // Afficher un message de bienvenue (désactivé pour éviter les messages en rouge sur Cline) // console.error(` // ╔══════════════════════════════════════════════════════════════╗ // ║ ║ // ║ Smart-Thinking MCP Server ║ // ║ Un outil de raisonnement multi-dimensionnel avancé ║ // ║ ║ // ║ Version: ${version} ║ // ║ ║ // ║ Démarrage du serveur... ║ // ║ ║ // ╚══════════════════════════════════════════════════════════════╝ // `); // Initialisation des services const COHERE_API_KEY = 'DckObDtnnRkPQQK6dwooI7mAB60HmmhNh1OBD23K'; const embeddingService = new embedding_service_1.EmbeddingService(COHERE_API_KEY); const metricsCalculator = new metrics_calculator_1.MetricsCalculator(); const qualityEvaluator = new quality_evaluator_1.QualityEvaluator(); const toolIntegrator = new tool_integrator_1.ToolIntegrator(); // Note: ThoughtGraph and MemoryManager instances are typically created per request or session // For simplicity in this example, we'll manage session context within the handler. // A more robust implementation might use a factory or manage instances per session ID. const globalEmbeddingService = embeddingService; // Keep a global instance const globalQualityEvaluator = qualityEvaluator; // Keep a global instance const globalToolIntegrator = toolIntegrator; // Keep a global instance const globalMetricsCalculator = metricsCalculator; // Keep a global instance // Get ServiceContainer instance first const serviceContainer = service_container_1.ServiceContainer.getInstance(); // Initialize services if not already done (assuming initializeServices handles idempotency or is called only once) serviceContainer.initializeServices(globalToolIntegrator, globalMetricsCalculator, globalEmbeddingService); // Now get the verification service const globalVerificationService = serviceContainer.getVerificationService(); const globalMemoryManager = new memory_manager_1.MemoryManager(globalEmbeddingService); // Global memory manager for persistence const visualizer = new visualizer_1.Visualizer(); // Visualizer can likely remain global const verificationMemory = verification_memory_1.VerificationMemory.getInstance(); // Singleton // Configuration des dépendances (assurez-vous que les services globaux sont configurés) verificationMemory.setEmbeddingService(globalEmbeddingService); // Ensure quality evaluator uses the correct verification service instance globalQualityEvaluator.setVerificationService(globalVerificationService); // Note: Event listeners on a per-session graph would need careful management. // For this fix, we'll assume events are handled within the request lifecycle or globally if appropriate. // Créer une instance du serveur MCP const server = new mcp_js_1.McpServer({ name: "smart-thinking-mcp", version: version, capabilities: {} }); // ====================================================================== // REFACTORISATION DES SCHÉMAS POUR COMPATIBILITÉ MCP // ====================================================================== // 1. Définition des types d'énumération en constantes nommées pour plus de clarté const ThoughtTypeEnum = zod_1.z.enum(['regular', 'revision', 'meta', 'hypothesis', 'conclusion']); const ConnectionTypeEnum = zod_1.z.enum([ 'supports', 'contradicts', 'refines', 'branches', 'derives', 'associates', 'exemplifies', 'generalizes', 'compares', 'contrasts', 'questions', 'extends', 'analyzes', 'synthesizes', 'applies', 'evaluates', 'cites', 'extended-by', 'analyzed-by', 'component-of', 'applied-by', 'evaluated-by', 'cited-by' ]); const TemporalityEnum = zod_1.z.enum(['before', 'after', 'during', 'concurrent']); const CertaintyEnum = zod_1.z.enum(['definite', 'high', 'moderate', 'low', 'speculative']); const DirectionalityEnum = zod_1.z.enum(['unidirectional', 'bidirectional', 'multidirectional']); const ScopeEnum = zod_1.z.enum(['broad', 'specific', 'partial', 'complete']); const NatureEnum = zod_1.z.enum(['causal', 'correlational', 'sequential', 'hierarchical', 'associative']); const VisualizationTypeEnum = zod_1.z.enum(['graph', 'chronological', 'thematic', 'hierarchical', 'force', 'radial']); const ClusterByEnum = zod_1.z.enum(['type', 'theme', 'metric', 'connectivity']); const DirectionEnum = zod_1.z.enum(['LR', 'RL', 'TB', 'BT']); // 2. Définition explicite des schémas d'attributs const ConnectionAttributesSchema = zod_1.z.object({ temporality: TemporalityEnum.optional(), certainty: CertaintyEnum.optional(), directionality: DirectionalityEnum.optional(), scope: ScopeEnum.optional(), nature: NatureEnum.optional(), // Utiliser un type spécifique au lieu de any customAttributes: zod_1.z.record(zod_1.z.string()).optional() }); // 3. Schéma pour les connexions avec tous les types explicites const ConnectionSchema = zod_1.z.object({ targetId: zod_1.z.string().describe("ID de la pensée cible"), type: ConnectionTypeEnum.describe("Type de connexion"), strength: zod_1.z.number().min(0).max(1).describe("Force de la connexion (0 à 1)"), description: zod_1.z.string().optional().describe("Description optionnelle de la connexion"), attributes: ConnectionAttributesSchema.optional(), inferred: zod_1.z.boolean().optional().describe("Si la connexion a été inférée automatiquement"), inferenceConfidence: zod_1.z.number().min(0).max(1).optional().describe("Confiance dans l'inférence (0 à 1)"), bidirectional: zod_1.z.boolean().optional().describe("Si la relation est intrinsèquement bidirectionnelle") }); // 4. Schémas pour les options avancées // Remplacer les z.any() par des types spécifiques const MetricThresholdsSchema = zod_1.z.object({ confidence: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional(), relevance: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional(), quality: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional() }); const FilterOptionsSchema = zod_1.z.object({ nodeTypes: zod_1.z.array(ThoughtTypeEnum).optional(), connectionTypes: zod_1.z.array(ConnectionTypeEnum).optional(), metricThresholds: MetricThresholdsSchema.optional(), textSearch: zod_1.z.string().optional(), dateRange: zod_1.z.tuple([zod_1.z.date(), zod_1.z.date()]).optional(), // Remplacer z.any() par z.unknown() pour les types inconnus customFilters: zod_1.z.record(zod_1.z.unknown()).optional() }).optional(); const InteractivityOptionsSchema = zod_1.z.object({ zoomable: zod_1.z.boolean().optional(), draggable: zod_1.z.boolean().optional(), selectable: zod_1.z.boolean().optional(), tooltips: zod_1.z.boolean().optional(), expandableNodes: zod_1.z.boolean().optional(), initialZoom: zod_1.z.number().optional(), zoomRange: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional(), highlightOnHover: zod_1.z.boolean().optional() }).optional(); // 5. Schéma des options de visualisation const VisualizationOptionsSchema = zod_1.z.object({ clusterBy: ClusterByEnum.optional() .describe('Critère de regroupement des nœuds en clusters'), direction: DirectionEnum.optional().default('TB') .describe('Direction de la disposition hiérarchique'), centerNode: zod_1.z.string().optional() .describe('ID du nœud central pour les visualisations radiales ou hiérarchiques'), maxDepth: zod_1.z.number().optional() .describe('Profondeur maximale pour les visualisations hiérarchiques ou radiales'), filters: FilterOptionsSchema .describe('Options de filtrage des nœuds et des liens'), interactivity: InteractivityOptionsSchema .describe('Options d\'interactivité pour la visualisation') }).optional(); /** * Schéma des paramètres pour l'outil smartthinking * ---------------------------------------------- * Ce schéma définit tous les paramètres que Claude peut utiliser * pour interagir avec l'outil Smart-Thinking */ const SmartThinkingParamsSchema = zod_1.z.object({ thought: zod_1.z.string().describe('Le contenu de la pensée à analyser - PARAMÈTRE OBLIGATOIRE - Cette pensée sera ajoutée au graphe de raisonnement'), thoughtType: ThoughtTypeEnum.default('regular') .describe('Type de pensée dans le graphe de raisonnement - Détermine la fonction de cette pensée'), connections: zod_1.z.array(ConnectionSchema).default([]) .describe('Connexions à d\'autres pensées - Permet de lier cette pensée à d\'autres pensées du graphe'), requestSuggestions: zod_1.z.boolean().default(false) .describe('Demander des suggestions d\'amélioration du raisonnement'), generateVisualization: zod_1.z.boolean().default(false) .describe('Générer une visualisation du graphe de pensée'), visualizationType: VisualizationTypeEnum.default('graph') .describe('Type de visualisation à générer'), suggestTools: zod_1.z.boolean().default(true) .describe('Suggérer des outils MCP pertinents pour cette étape du raisonnement'), sessionId: zod_1.z.string().optional() .describe('Identifiant de session pour maintenir l\'état entre les appels'), userId: zod_1.z.string().optional() .describe('Identifiant de l\'utilisateur pour la personnalisation'), help: zod_1.z.boolean().default(true) .describe('Afficher le guide d\'utilisation complet'), requestVerification: zod_1.z.boolean().default(false) .describe('Demander explicitement une vérification des informations'), containsCalculations: zod_1.z.boolean().default(false) .describe('Indique si la pensée contient des calculs à vérifier'), visualizationOptions: VisualizationOptionsSchema .describe('Options avancées pour la visualisation') }); /** * Définition de l'outil smartthinking * ----------------------------------- * Cet outil permet à Claude d'utiliser le système de raisonnement Smart-Thinking */ server.tool('smartthinking', SmartThinkingParamsSchema.shape, async (params) => { // Si help=true et aucune pensée n'est fournie, afficher le guide d'utilisation if (params.help && !params.thought) { return { content: [ { type: 'text', text: `# Smart-Thinking - Guide d'utilisation Smart-Thinking est un outil de raisonnement multi-dimensionnel qui organise les pensées en graphe plutôt qu'en séquence linéaire, permettant une analyse plus riche et interconnectée des problèmes complexes. ## Paramètres principaux - **thought** (obligatoire): La pensée à analyser - **thoughtType**: Type de pensée (regular, revision, meta, hypothesis, conclusion) - **connections**: Liens vers d'autres pensées [{targetId, type, strength}] - **requestSuggestions**: Demander des suggestions d'amélioration - **generateVisualization**: Créer une représentation visuelle du graphe - **requestVerification**: Vérifier les informations contenues dans la pensée - **containsCalculations**: Activer la vérification des calculs mathématiques ## Types de pensées - **regular**: Pensée standard pour développer une idée - **meta**: Réflexion sur le processus de raisonnement lui-même - **hypothesis**: Formulation d'une hypothèse à tester - **revision**: Modification d'une pensée précédente - **conclusion**: Synthèse finale ou déduction ## Types de connexions - **supports**: Pensée qui renforce une autre - **contradicts**: Pensée qui s'oppose à une autre - **refines**: Pensée qui précise ou améliore une autre - **branches**: Pensée qui explore une nouvelle direction - **derives**: Pensée qui découle logiquement d'une autre - **associates**: Pensée simplement liée à une autre ## Types de visualisations - **graph**: Réseau standard de connexions - **chronological**: Timeline d'évolution du raisonnement - **thematic**: Clusters par thèmes similaires - **hierarchical**: Structure arborescente - **force**: Disposition basée sur forces d'attraction/répulsion - **radial**: Cercles concentriques autour d'une pensée centrale ## Exemple d'utilisation \`\`\` Utilise l'outil smartthinking avec: thought: "L'intelligence artificielle transformera profondément le marché du travail" thoughtType: "hypothesis" generateVisualization: true \`\`\` ` } ] }; } // Vérifier si le paramètre 'thought' est présent if (!params.thought) { console.error('Smart-Thinking: ERROR - Paramètre "thought" manquant'); return { isError: true, content: [ { type: 'text', text: JSON.stringify({ error: "Le paramètre 'thought' est obligatoire.", message: "Vous devez fournir une pensée à analyser." }, null, 2) } ] }; } // console.error('Smart-Thinking: traitement de la pensée pour session:', params.sessionId || 'generating new'); // --- Session Management & State Loading --- // Ensure a unique session ID for each interaction if none is provided const currentSessionId = params.sessionId || generateUniqueId(); console.error(`Smart-Thinking: Using session ID: ${currentSessionId}`); // Log the used session ID const memoryManager = globalMemoryManager; // Use global manager for persistence // Create a new graph instance for the session const sessionThoughtGraph = new thought_graph_1.ThoughtGraph(currentSessionId, globalEmbeddingService, globalQualityEvaluator); // Attempt to load previous graph state for this session const loadedStateJson = await memoryManager.loadGraphState(currentSessionId); if (loadedStateJson) { const importSuccess = sessionThoughtGraph.importEnrichedGraph(loadedStateJson); if (importSuccess) { console.error(`Smart-Thinking [${currentSessionId}]: État du graphe précédent chargé avec succès.`); } else { console.error(`Smart-Thinking [${currentSessionId}]: Échec du chargement/parsing de l'état du graphe précédent.`); // Continue with an empty graph for this session } } else { console.error(`Smart-Thinking [${currentSessionId}]: Aucun état de graphe précédent trouvé, nouvelle session de graphe démarrée.`); } // Use global services (assuming they are stateless or manage their own state) // Use the global memoryManager instance directly const verificationService = globalVerificationService; const qualityEvaluator = globalQualityEvaluator; // Use global // const memoryManager = globalMemoryManager; // REMOVED local redeclaration const metricsCalculator = globalMetricsCalculator; // Use global const toolIntegrator = globalToolIntegrator; // Use global // Traitement de la pensée const preliminaryResult = await verificationService.performPreliminaryVerification(params.thought, !!params.containsCalculations); // Add thought to the session-specific graph instance const thoughtId = sessionThoughtGraph.addThought(preliminaryResult.preverifiedThought, params.thoughtType, params.connections // Note: addThought now implicitly uses the graph's sessionId ); // Évaluation de la qualité (maintenant asynchrone) using the session graph const qualityMetrics = await qualityEvaluator.evaluate(thoughtId, sessionThoughtGraph); // Update metrics on the session graph instance sessionThoughtGraph.updateThoughtMetrics(thoughtId, qualityMetrics); // Détermination du statut de vérification let verificationStatus = 'unverified'; let certaintySummary = "Information non vérifiée"; if (preliminaryResult.verificationInProgress) { if (preliminaryResult.initialVerification) { verificationStatus = 'partially_verified'; certaintySummary = `Calculs vérifiés préalablement, niveau de confiance initial: ${Math.round(qualityMetrics.confidence * 100)}%.`; } else { verificationStatus = 'verification_in_progress'; certaintySummary = "Vérification des calculs en cours..."; } } else if (params.containsCalculations) { certaintySummary = `Information non vérifiée, niveau de confiance: ${Math.round(qualityMetrics.confidence * 100)}%. Aucun calcul n'a été détecté pour vérification.`; } else { certaintySummary = `Information non vérifiée, niveau de confiance: ${Math.round(qualityMetrics.confidence * 100)}%. Pour une vérification complète, utilisez le paramètre requestVerification=true.`; } // Préparation de la réponse initiale const response = { thoughtId, thought: preliminaryResult.preverifiedThought, thoughtType: params.thoughtType || 'regular', qualityMetrics, isVerified: preliminaryResult.initialVerification, verificationStatus: verificationStatus, certaintySummary: certaintySummary, reliabilityScore: metricsCalculator.calculateReliabilityScore(qualityMetrics, preliminaryResult.initialVerification ? 'partially_verified' : 'unverified', preliminaryResult.verifiedCalculations, undefined // Pas de score précédent pour la première pensée ) }; // Traitement des calculs vérifiés if (preliminaryResult.verifiedCalculations && preliminaryResult.verifiedCalculations.length > 0) { response.isVerified = true; response.verificationStatus = 'partially_verified'; response.verification = { status: preliminaryResult.initialVerification ? 'partially_verified' : 'inconclusive', confidence: qualityMetrics.confidence, sources: ['Vérification préliminaire des calculs'], verificationSteps: ['Détection et vérification préliminaire des expressions mathématiques'], verifiedCalculations: preliminaryResult.verifiedCalculations }; const correctCalculations = preliminaryResult.verifiedCalculations.filter((calc) => calc.isCorrect).length; const totalCalculations = preliminaryResult.verifiedCalculations.length; if (totalCalculations > 0) { const calculationAccuracy = correctCalculations / totalCalculations; response.reliabilityScore = (qualityMetrics.confidence * 0.7) + (calculationAccuracy * 0.3); } } // Vérification des informations précédemment vérifiées (using session ID) const thought = sessionThoughtGraph.getThought(thoughtId); // Get from session graph // Récupérer les IDs des pensées connectées const connectedThoughtIds = params.connections?.map(conn => conn.targetId) || []; // Appel amélioré avec type de pensée et connexions const previousResult = await verificationService.checkPreviousVerification(thought?.content || params.thought, currentSessionId, // Pass current session ID params.thoughtType || 'regular', connectedThoughtIds); if (previousResult.previousVerification) { response.isVerified = previousResult.isVerified; response.verificationStatus = previousResult.verificationStatus; response.certaintySummary = previousResult.certaintySummary; response.verification = previousResult.verification; response.reliabilityScore = metricsCalculator.calculateReliabilityScore(qualityMetrics, previousResult.verificationStatus, preliminaryResult.verifiedCalculations, response.reliabilityScore // Utiliser le score déjà calculé comme référence ); // Update the thought within the session graph instance if (thought) { thought.metadata.previousVerification = { similarity: previousResult.previousVerification.similarity, status: previousResult.previousVerification.status, confidence: previousResult.previousVerification.confidence, timestamp: previousResult.previousVerification.timestamp }; } } // Vérification approfondie si nécessaire // Ensure qualityMetrics is awaited before accessing its properties if ((qualityMetrics.confidence < config_1.VerificationConfig.CONFIDENCE.VERIFICATION_REQUIRED || params.requestVerification) && !previousResult.previousVerification) { // Débogage silencieux // console.error(`Smart-Thinking [${currentSessionId}]: Confiance faible ou vérification demandée, vérification complète nécessaire...`); try { if (thought) { // Ensure thought exists in session graph response.verificationStatus = 'verification_in_progress'; const verification = await verificationService.deepVerify(thought, params.containsCalculations || false, false, currentSessionId // Pass current session ID ); response.verification = verification; response.isVerified = verification.status === 'verified' || verification.status === 'partially_verified' || (!!verification.verifiedCalculations && verification.verifiedCalculations.length > 0); response.verificationStatus = verification.status; response.reliabilityScore = metricsCalculator.calculateReliabilityScore(qualityMetrics, verification.status, verification.verifiedCalculations, response.reliabilityScore // Utiliser le score déjà calculé comme référence ); response.certaintySummary = metricsCalculator.generateCertaintySummary(verification.status, response.reliabilityScore); if (verification.verifiedCalculations && verification.verifiedCalculations.length > 0) { response.thought = verificationService.annotateThoughtWithVerifications(response.thought, verification.verifiedCalculations); // Update content in the session graph instance sessionThoughtGraph.updateThoughtContent(thoughtId, response.thought); } } } catch (error) { // Suppression des logs d'erreur // console.error('Smart-Thinking: Erreur lors de la vérification complète:', error); response.verificationStatus = 'inconclusive'; // Ensure qualityMetrics is awaited before accessing its properties here too response.certaintySummary = `Erreur lors de la vérification: ${error instanceof Error ? error.message : 'Erreur inconnue'}. Niveau de confiance: ${Math.round(qualityMetrics.confidence * 100)}%.`; } } // Fonctionnalités additionnelles selon les paramètres if (params.suggestTools) { // suggestTools is now async response.suggestedTools = await toolIntegrator.suggestTools(params.thought); // Tool suggestions are likely context-dependent, not session-dependent } // Génération de visualisation si demandée (using session graph) if (params.generateVisualization) { try { const visualizationType = params.visualizationType || 'graph'; const visualizationOptions = params.visualizationOptions || {}; // Pass the session-specific graph to the visualizer methods const generateVisualizationAsync = async () => { switch (visualizationType) { case 'chronological': // Pass session graph return await Promise.resolve(visualizer.generateChronologicalVisualization(sessionThoughtGraph)); case 'thematic': // Pass session graph return await Promise.resolve(visualizer.generateThematicVisualization(sessionThoughtGraph)); case 'hierarchical': // Pass session graph return await Promise.resolve(visualizer.generateHierarchicalVisualization(sessionThoughtGraph, visualizationOptions.centerNode, { direction: visualizationOptions.direction, levelSeparation: 100, clusterBy: visualizationOptions.clusterBy })); case 'force': // Pass session graph return await Promise.resolve(visualizer.generateForceDirectedVisualization(sessionThoughtGraph, { clusterBy: visualizationOptions.clusterBy, forceStrength: 0.5, centerNode: visualizationOptions.centerNode })); case 'radial': // Pass session graph return await Promise.resolve(visualizer.generateRadialVisualization(sessionThoughtGraph, visualizationOptions.centerNode, { maxDepth: visualizationOptions.maxDepth, radialDistance: 120 })); case 'graph': default: // Pass session graph return await Promise.resolve(visualizer.generateVisualization(sessionThoughtGraph, thoughtId)); } }; response.visualization = await generateVisualizationAsync(); if (visualizationOptions.filters && response.visualization) { response.visualization = visualizer.applyFilters(response.visualization, visualizationOptions.filters); } if (response.visualization && response.visualization.nodes.length > 100) { response.visualization = visualizer.simplifyVisualization(response.visualization); } } catch (error) { // Suppression des logs d'erreur // console.error('Smart-Thinking: Erreur lors de la génération de la visualisation:', error); } } // Récupération des mémoires et suggestions (pass session ID) using globalMemoryManager const relevantMemoriesPromise = globalMemoryManager.getRelevantMemories(params.thought, 3, currentSessionId); // Pass session ID to suggestNextSteps response.suggestedNextSteps = await sessionThoughtGraph.suggestNextSteps(3, currentSessionId); response.relevantMemories = await relevantMemoriesPromise; // Stockage de la pensée dans la mémoire (pass session ID) // REMOVED: Quality check - always add thought to memory for the session const tags = params.thought .toLowerCase() .split(/\W+/) .filter((word) => word.length > 4) .slice(0, 5); // Pass session ID when adding memory using globalMemoryManager globalMemoryManager.addMemory(response.thought, tags, currentSessionId); // Use response.thought which might be annotated // console.error(`Smart-Thinking [${currentSessionId}]: pensée traitée avec succès, id:`, thoughtId); // --- State Saving --- // Export and save the updated graph state before returning using globalMemoryManager const currentStateJson = sessionThoughtGraph.exportEnrichedGraph(); await globalMemoryManager.saveGraphState(currentSessionId, currentStateJson); console.error(`Smart-Thinking [${currentSessionId}]: État actuel du graphe sauvegardé.`); // Retour de la réponse formatée pour MCP return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; }); // Initialisation du transport avec notre version améliorée pour la compatibilité cross-plateforme const transport = new platform_stdio_1.EnhancedStdioServerTransport(); /** * Crée le répertoire de données si nécessaire * Compatible avec toutes les plateformes (Windows, Mac, Linux) */ async function ensureDataDirExists() { // Utiliser l'utilitaire de chemins pour un chemin normalisé const dataDir = path_utils_1.PathUtils.getDataDirectory(); try { await fs_1.promises.mkdir(dataDir, { recursive: true }); // console.error(`Smart-Thinking: Répertoire data créé ou confirmé: ${dataDir}`); // Sur Windows, vérifier les droits d'accès explicitement if (config_1.PlatformConfig.IS_WINDOWS) { try { // Vérifier l'accès en écriture await fs_1.promises.access(dataDir, fs_1.promises.constants.W_OK); } catch (accessError) { // console.error(`Smart-Thinking: AVERTISSEMENT - Problème de permissions sur le répertoire data: ${accessError instanceof Error ? accessError.message : String(accessError)}`); // console.error('Smart-Thinking: Essayez d\'exécuter l\'application avec des droits d\'administrateur ou choisissez un autre emplacement.'); } } } catch (error) { // Erreur ignorée, utiliser un répertoire par défaut sans message // Essayer un répertoire alternatif sur Windows en cas d'échec if (config_1.PlatformConfig.IS_WINDOWS) { const altDataDir = path_1.default.join(process.env.USERPROFILE || '', 'Documents', 'Smart-Thinking', 'data'); try { await fs_1.promises.mkdir(altDataDir, { recursive: true }); // Log supprimé pour éviter les messages sur Cline } catch (altError) { // Log d'erreur supprimé } } } } // Démarrage du serveur async function start() { try { await ensureDataDirExists(); await server.connect(transport); // Démarrage silencieux pour éviter les messages en rouge sur Cline // console.error('Smart-Thinking MCP Server démarré avec succès.'); // console.error('L\'outil "smartthinking" est maintenant disponible pour Claude.'); } catch (error) { // Sortie silencieuse en cas d'erreur pour éviter les messages en rouge process.exit(1); } } start(); //# sourceMappingURL=index.js.map