Skip to main content
Glama
index.ts86.8 kB
import { z } from "zod"; import { EphemeralNotebookStore } from "../notebook/EphemeralNotebook.js"; import { getPresetForPattern } from "../notebook/presets.js"; import type { SessionState } from "../state/SessionState.js"; import type { AnalogicalReasoningData, AnalogyMapping, BayesianUpdateResult, CausalAnalysisResult, CausalEdge, CausalGraph, EthicalAssessment, HypothesisTestResult, Intervention, MonteCarloResult, OptimizationResult, ResearchFinding, ResearchResult, ResearchSource, SimulationResult, SummaryStats, } from "../types/index.js"; import { executePython } from "../utils/execution.js"; import { enhanceResponseWithNotebook } from "./notebookEnhancement.js"; // Initialize notebook store const notebookStore = new EphemeralNotebookStore(); /** * Helper function to generate dashboard HTML content */ function generateDashboardHTML(options: { title: string; visualizationType: string; data: any; panels: any[]; layout: string; interactive: boolean; }): string { const { title, visualizationType, data, panels, layout, interactive } = options; // Generate HTML with embedded Chart.js or D3.js visualization const chartScript = visualizationType === "chart" ? ` <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> const ctx = document.getElementById('mainChart').getContext('2d'); const chart = new Chart(ctx, { type: '${data.chartType || "bar"}', data: ${JSON.stringify(data.chartData || { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], datasets: [{ label: 'Dataset', data: [12, 19, 3, 5, 2], backgroundColor: 'rgba(75, 192, 192, 0.2)', borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 1 }] })}, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true }, tooltip: { enabled: ${interactive} } } } }); </script> ` : ""; const panelsHTML = panels.map((panel, index) => ` <div class="panel" style=" padding: 15px; margin: 10px; border: 1px solid #ddd; border-radius: 8px; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1); "> <h3>${panel.title || `Panel ${index + 1}`}</h3> <div class="panel-content"> ${panel.content || `<p>Panel content for ${panel.type || 'metric'}</p>`} ${panel.value ? `<div class="metric-value" style="font-size: 2em; font-weight: bold; color: #2196F3;">${panel.value}</div>` : ''} </div> </div> `).join(''); return ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>${title}</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; } .dashboard { max-width: 1200px; margin: 0 auto; } .header { background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .panels-container { display: ${layout === 'grid' ? 'grid' : 'flex'}; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; flex-wrap: ${layout === 'flex' ? 'wrap' : 'nowrap'}; } .chart-container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); height: 400px; margin-bottom: 20px; } canvas { width: 100% !important; height: 100% !important; } </style> </head> <body> <div class="dashboard"> <div class="header"> <h1>${title}</h1> <p>Interactive Dashboard - ${new Date().toLocaleString()}</p> </div> ${visualizationType === 'chart' ? ` <div class="chart-container"> <canvas id="mainChart"></canvas> </div> ` : ''} <div class="panels-container"> ${panelsHTML} </div> </div> ${chartScript} ${interactive ? ` <script> // Enable interactive features window.parent.postMessage({ type: 'ui-lifecycle-iframe-ready', payload: { ready: true } }, '*'); // Handle clicks on panels document.querySelectorAll('.panel').forEach((panel, index) => { panel.style.cursor = 'pointer'; panel.addEventListener('click', () => { window.parent.postMessage({ type: 'notify', payload: { message: 'Panel ' + (index + 1) + ' clicked' } }, '*'); }); }); </script> ` : ''} </body> </html> `; } /** * Helper function to generate remote DOM script for dynamic content */ function generateRemoteDomScript(options: { visualizationType: string; data: any; panels: any[]; interactive: boolean; }): string { const { visualizationType, data, panels, interactive } = options; return ` // Create dashboard container const container = document.createElement('ui-container'); container.style.padding = '20px'; // Add title const title = document.createElement('ui-text'); title.textContent = 'Dynamic Dashboard'; title.style.fontSize = '24px'; title.style.fontWeight = 'bold'; title.style.marginBottom = '20px'; container.appendChild(title); // Add panels ${panels.map((panel, index) => ` const panel${index} = document.createElement('ui-panel'); panel${index}.style.padding = '15px'; panel${index}.style.margin = '10px'; panel${index}.style.border = '1px solid #ddd'; panel${index}.style.borderRadius = '8px'; const panelTitle${index} = document.createElement('ui-text'); panelTitle${index}.textContent = '${panel.title || `Panel ${index + 1}`}'; panelTitle${index}.style.fontWeight = 'bold'; panel${index}.appendChild(panelTitle${index}); ${panel.value ? ` const panelValue${index} = document.createElement('ui-text'); panelValue${index}.textContent = '${panel.value}'; panelValue${index}.style.fontSize = '2em'; panelValue${index}.style.color = '#2196F3'; panel${index}.appendChild(panelValue${index}); ` : ''} ${interactive ? ` panel${index}.style.cursor = 'pointer'; panel${index}.onclick = () => { window.parent.postMessage({ type: 'tool', payload: { toolName: 'handlePanelClick', params: { panelId: ${index} } } }, '*'); }; ` : ''} container.appendChild(panel${index}); `).join('\n')} // Append to root root.appendChild(container); // Send ready signal window.parent.postMessage({ type: 'ui-lifecycle-iframe-ready', payload: { ready: true } }, '*'); `; } /** * Registers the unified Clear Thought tool with the MCP server * * This single tool provides access to all reasoning operations through * an operation parameter, following the Toolhost pattern. * * @param server - The MCP server instance * @param sessionState - The session state manager */ export const ClearThoughtParamsSchema = z.object({ operation: z .enum([ // Core thinking operations "sequential_thinking", "mental_model", "debugging_approach", "creative_thinking", "visual_reasoning", "metacognitive_monitoring", "scientific_method", // Collaborative operations "collaborative_reasoning", "decision_framework", "socratic_method", "structured_argumentation", // Systems and session operations "systems_thinking", "session_info", "session_export", "session_import", // Deep reasoning operations "pdr_reasoning", // New modules "research", "analogical_reasoning", "causal_analysis", "statistical_reasoning", "simulation", "optimization", "ethical_analysis", "visual_dashboard", "custom_framework", "code_execution", // Reasoning pattern operations "tree_of_thought", "beam_search", "mcts", "graph_of_thought", "orchestration_suggest", // Metagame operations "ooda_loop", "ulysses_protocol", // Notebook operations "notebook_create", "notebook_add_cell", "notebook_run_cell", "notebook_export", ]) .describe("What type of reasoning operation to perform"), // Common parameters prompt: z.string().describe("The problem, question, or challenge to work on"), context: z .string() .optional() .describe("Additional context or background information"), sessionId: z .string() .optional() .describe("Session identifier for continuity"), // Operation-specific parameters (will be validated based on operation) parameters: z .record(z.string(), z.unknown()) .optional() .describe("Operation-specific parameters"), // Advanced options advanced: z .object({ autoProgress: z .boolean() .optional() .describe("Automatically progress through stages when applicable"), saveToSession: z .boolean() .default(true) .describe("Save results to session state"), generateNextSteps: z .boolean() .default(true) .describe("Generate recommended next steps"), }) .optional() .describe("Advanced reasoning options"), }); export async function handleClearThoughtTool( sessionState: SessionState, args: z.infer<typeof ClearThoughtParamsSchema>, ): Promise<{ content: Array<{ type: "text"; text: string }>; isError?: boolean; }> { const startTime = Date.now(); try { // Special handling for code execution to allow real run if (args.operation === "code_execution") { const params = (args.parameters || {}) as any; const lang = (params.language as string) || "python"; const code = String(params.code || ""); const cfg = sessionState.getConfig(); if (lang !== "python" || !cfg.allowCodeExecution) { const preview = await executeClearThoughtOperation( sessionState, args.operation, { prompt: args.prompt, parameters: args.parameters }, ); return { content: [{ type: "text" as const, text: JSON.stringify(preview, null, 2) }], }; } const result = await executePython( code, cfg.pythonCommand, cfg.executionTimeoutMs, ); const executionResult: any = { toolOperation: "code_execution", ...result }; return { content: [ { type: "text", text: JSON.stringify(executionResult, null, 2), }, ], }; } // Auto-seed most operations with a brief sequential_thinking step const seedExclusions = new Set([ "sequential_thinking", "code_execution", "session_info", "session_export", "session_import", ]); const shouldSeed = !seedExclusions.has(args.operation); // Handle async operations if (args.operation === "notebook_run_cell") { const params = (args.parameters || {}) as any; try { const execution = await notebookStore.executeCell( params.notebookId || "", params.cellId || "", params.timeoutMs || 5000, ); const notebookResult: any = { toolOperation: "notebook_run_cell", notebookId: params.notebookId, cellId: params.cellId, execution: { id: execution.id, status: execution.status, outputs: execution.outputs, error: execution.error, duration: execution.completedAt ? execution.completedAt - execution.startedAt : undefined, }, }; return { content: [ { type: "text" as const, text: JSON.stringify(notebookResult, null, 2), }, ], }; } catch (error: any) { const errorResult: any = { toolOperation: "notebook_run_cell", notebookId: params.notebookId, cellId: params.cellId, error: error.message, success: false, }; return { content: [ { type: "text" as const, text: JSON.stringify(errorResult, null, 2), }, ], }; } } // Execute the main operation const result = await executeClearThoughtOperation( sessionState, args.operation, { prompt: args.prompt, parameters: args.parameters }, ); const enriched = shouldSeed ? { ...result, initialThought: await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt: `Plan approach for: ${args.prompt}`, parameters: { thoughtNumber: 1, totalThoughts: 3, nextThoughtNeeded: true, needsMoreThoughts: true, pattern: "chain", }, }, ), } : result; // Enhance response with notebook resources if applicable const baseResponse = { content: [{ type: "text" as const, text: JSON.stringify(enriched, null, 2) }], }; const enhancedResponse = enhanceResponseWithNotebook( baseResponse, args.operation, args.prompt, ); return enhancedResponse; } catch (error: any) { const errorResponse = { toolOperation: args.operation, error: error.message, success: false }; return { content: [ { type: "text" as const, text: JSON.stringify(errorResponse, null, 2), }, ], isError: true, }; } } // Backwards-compatible registration helper (kept for compatibility; unused by low-level Server) export function registerTools( server: { tool: Function }, sessionState: SessionState, ): void { server.tool( "clear_thought", "Unified Clear Thought reasoning tool - provides all reasoning operations through a single interface", ClearThoughtParamsSchema.shape, async (args: z.infer<typeof ClearThoughtParamsSchema>) => handleClearThoughtTool(sessionState, args), ); } /** * Unified Clear Thought reasoning operations * * This module provides all reasoning operations through a single interface, * following the websetsManager pattern without external dependencies. * * @param sessionState - The session state manager * @param operation - The operation to perform * @param args - Operation arguments */ export async function executeClearThoughtOperation( sessionState: SessionState, operation: string, args: { prompt: string; parameters?: Record<string, unknown> }, ): Promise<Record<string, unknown>> { const { prompt, parameters = {} } = args; // Optional reasoning pattern selection for sequential_thinking const specifiedPattern = (parameters as any).pattern as | "chain" | "tree" | "beam" | "mcts" | "graph" | "auto" | undefined; const patternParams = ((parameters as any).patternParams as Record<string, unknown>) || {}; const selectReasoningPattern = (): | "chain" | "tree" | "beam" | "mcts" | "graph" => { if (specifiedPattern && specifiedPattern !== "auto") return specifiedPattern; // Heuristic selection from prompt/params const ptext = `${prompt}`.toLowerCase(); if ( "depth" in patternParams || "breadth" in patternParams || ptext.includes("branch") || ptext.includes("options") ) { return "tree"; } if ( "beamWidth" in patternParams || ptext.includes("candidates") || ptext.includes("top-k") ) { return "beam"; } if ( "simulations" in patternParams || ptext.includes("uncertain") || ptext.includes("probability") || ptext.includes("stochastic") ) { return "mcts"; } if ( "nodes" in patternParams || "edges" in patternParams || ptext.includes("dependencies") || ptext.includes("graph") ) { return "graph"; } return "chain"; }; // Type guard to ensure parameters are properly typed const getParam = <T>(key: string, defaultValue: T): T => { return (parameters[key] as T) ?? defaultValue; }; // Unified handler for all operations switch (operation) { case "sequential_thinking": { // Choose reasoning pattern (default 'chain') and optionally dispatch const chosenPattern = selectReasoningPattern(); const thoughtData = { thought: prompt, thoughtNumber: parameters.thoughtNumber || 1, totalThoughts: parameters.totalThoughts || 1, nextThoughtNeeded: parameters.nextThoughtNeeded || false, isRevision: parameters.isRevision, revisesThought: parameters.revisesThought, branchFromThought: parameters.branchFromThought, branchId: parameters.branchId, needsMoreThoughts: parameters.needsMoreThoughts, }; const added = sessionState.addThought(thoughtData as any); const allThoughts = sessionState.getThoughts(); const recentThoughts = allThoughts.slice(-3); // If a non-chain pattern is selected, optionally execute the corresponding pattern operation let patternResult: Record<string, unknown> | undefined; if ( chosenPattern !== "chain" && !(parameters as any).__disablePatternDispatch ) { const opMap: Record<string, string> = { tree: "tree_of_thought", beam: "beam_search", mcts: "mcts", graph: "graph_of_thought", }; const mappedOp = opMap[chosenPattern]; if (mappedOp) { patternResult = await executeClearThoughtOperation( sessionState, mappedOp, { prompt, parameters: patternParams }, ); } } return { toolOperation: "sequential_thinking", selectedPattern: chosenPattern, patternResult, ...thoughtData, status: added ? "success" : "limit_reached", sessionContext: { sessionId: sessionState.sessionId, totalThoughts: allThoughts.length, remainingThoughts: sessionState.getRemainingThoughts(), recentThoughts: recentThoughts.map((t) => ({ thoughtNumber: t.thoughtNumber, isRevision: t.isRevision, })), }, }; } case "mental_model": { const modelData = { modelName: parameters.model || "first_principles", problem: prompt, steps: parameters.steps || [], reasoning: parameters.reasoning || "", conclusion: parameters.conclusion || "", }; sessionState.addMentalModel(modelData as any); const allModels = sessionState.getMentalModels(); return { toolOperation: "mental_model", ...modelData, sessionContext: { sessionId: sessionState.sessionId, totalModels: allModels.length, recentModels: allModels .slice(-3) .map((m) => ({ modelName: m.modelName, problem: m.problem })), }, }; } case "debugging_approach": { const debugData = { approachName: parameters.approach || "binary_search", issue: prompt, steps: parameters.steps || [], findings: parameters.findings || "", resolution: parameters.resolution || "", }; sessionState.addDebuggingSession(debugData as any); const allSessions = sessionState.getDebuggingSessions(); return { toolOperation: "debugging_approach", ...debugData, sessionContext: { sessionId: sessionState.sessionId, totalSessions: allSessions.length, recentSessions: allSessions .slice(-3) .map((s) => ({ approachName: s.approachName, issue: s.issue })), }, }; } case "creative_thinking": { /** * Creative Thinking Operation * * Generates idea seeds and connections using simple combinatorial techniques. * * Expected in prompt: Creative challenge or problem to brainstorm * * Expected in parameters (model should provide these or they'll be generated): * - techniques?: string[] - Creative techniques to apply (default: ["brainstorming", "SCAMPER"]) * - numIdeas?: number - Number of ideas to generate (default: 8) * - ideas?: string[] - Pre-existing ideas to build upon * * The model should either provide structured ideas or the system will generate them using combinatorial techniques. */ // Use provided parameters or generate ideas let ideas = (parameters.ideas as string[]) || []; const techniques = (parameters.techniques as string[]) || ["brainstorming", "SCAMPER"]; const numIdeas = getParam("numIdeas", 8); // Generate ideas if none provided if (ideas.length === 0 && prompt) { // Extract key tokens from prompt const tokens = prompt.toLowerCase() .replace(/[^a-z\s]/g, '') .split(/\s+/) .filter(t => t.length > 2); // SCAMPER verbs for idea generation const scamperVerbs = [ "substitute", "combine", "adapt", "modify", "put to other use", "eliminate", "reverse" ]; // Generate ideas by combining tokens with techniques for (let i = 0; i < numIdeas && tokens.length > 0; i++) { const token = tokens[i % tokens.length]; const verb = scamperVerbs[i % scamperVerbs.length]; const otherToken = tokens[(i + 1) % tokens.length]; ideas.push(`${verb} ${token} with ${otherToken}`); } } // Generate connections between concepts let connections = (parameters.connections as string[]) || []; if (connections.length === 0 && ideas.length > 1) { // Create connections between ideas for (let i = 0; i < Math.min(ideas.length - 1, 3); i++) { connections.push(`${ideas[i]} could lead to ${ideas[i + 1]}`); } } // Generate insights (top-ranked ideas by novelty and coverage) let insights = (parameters.insights as string[]) || []; if (insights.length === 0 && ideas.length > 0) { // Simple ranking: pick ideas with rare tokens (novelty) and prompt overlap (coverage) const promptTokens = new Set(prompt.toLowerCase().split(/\s+/)); const rankedIdeas = ideas .map(idea => { const ideaTokens = idea.toLowerCase().split(/\s+/); const coverage = ideaTokens.filter(t => promptTokens.has(t)).length / ideaTokens.length; const novelty = 1 - coverage; // Simple novelty heuristic const score = (coverage + novelty) / 2; return { idea, score }; }) .sort((a, b) => b.score - a.score) .slice(0, 3) .map(item => item.idea); insights = rankedIdeas; } const creativeData = { prompt: prompt, ideas, techniques, connections, insights, sessionId: `creative-${Date.now()}`, iteration: getParam("iteration", 1), nextIdeaNeeded: getParam("nextIdeaNeeded", false), }; sessionState.addCreativeSession(creativeData as any); const allSessions = sessionState.getCreativeSessions(); return { toolOperation: "creative_thinking", ...creativeData, sessionContext: { sessionId: sessionState.sessionId, totalSessions: allSessions.length, recentSessions: allSessions .slice(-3) .map((s) => ({ prompt: s.prompt, techniques: s.techniques })), }, }; } case "visual_reasoning": { const visualData = { operation: "create" as const, diagramId: getParam("diagramId", `diagram-${Date.now()}`), diagramType: getParam("diagramType", "flowchart"), iteration: getParam("iteration", 1), nextOperationNeeded: getParam("nextOperationNeeded", false), }; sessionState.addVisualOperation(visualData as any); const allOperations = sessionState.getVisualOperations(); return { toolOperation: "visual_reasoning", ...visualData, sessionContext: { sessionId: sessionState.sessionId, totalOperations: allOperations.length, recentOperations: allOperations .slice(-3) .map((v) => ({ diagramType: v.diagramType, operation: v.operation, })), }, }; } case "metacognitive_monitoring": { /** * Metacognitive Monitoring Operation * * Records stage, uncertainty areas, and recommended approach; suggests assessments. * * Expected in prompt: Task or problem being monitored * * Expected in parameters: * - stage?: 'planning' | 'monitoring' | 'evaluating' | 'reflecting' * - uncertaintyAreas?: string[] - Areas of uncertainty * - overallConfidence?: number - Confidence level (0-1) * - recommendedApproach?: string - Suggested approach */ const stage = getParam("stage", "monitoring") as string; const uncertaintyAreas = getParam("uncertaintyAreas", []) as string[]; const overallConfidence = getParam("overallConfidence", 0.5) as number; const recommendedApproach = getParam("recommendedApproach", "") as string; // Suggest assessments based on stage let suggestedAssessments: string[] = []; if (stage === "monitoring") { suggestedAssessments = ["knowledge", "progress", "overall"]; } else if (stage === "evaluating") { suggestedAssessments = ["effectiveness", "efficiency", "completeness"]; } else if (stage === "reflecting") { suggestedAssessments = ["lessons-learned", "improvements", "next-steps"]; } const metaData = { task: prompt, stage, overallConfidence, uncertaintyAreas, recommendedApproach, suggestedAssessments, monitoringId: `meta-${Date.now()}`, iteration: getParam("iteration", 1), nextAssessmentNeeded: suggestedAssessments.length > 0, }; sessionState.addMetacognitive(metaData as any); sessionState.updateKPI('overall_confidence', overallConfidence); const allSessions = sessionState.getMetacognitiveSessions(); return { toolOperation: "metacognitive_monitoring", ...metaData, sessionContext: { sessionId: sessionState.sessionId, totalSessions: allSessions.length, recentSessions: allSessions .slice(-3) .map((m) => ({ task: m.task, stage: m.stage })), }, }; } case "scientific_method": { const scientificData = { stage: getParam("stage", "hypothesis") as | "conclusion" | "iteration" | "hypothesis" | "observation" | "question" | "experiment" | "analysis", inquiryId: `sci-${Date.now()}`, iteration: getParam("iteration", 1), nextStageNeeded: getParam("nextStageNeeded", false), }; sessionState.addScientificInquiry(scientificData); const allInquiries = sessionState.getScientificInquiries(); return { toolOperation: "scientific_method", ...scientificData, sessionContext: { sessionId: sessionState.sessionId, totalInquiries: allInquiries.length, recentInquiries: allInquiries .slice(-3) .map((s) => ({ stage: s.stage })), }, }; } case "collaborative_reasoning": { /** * Collaborative Reasoning Operation * * Maintains personas and contributions; suggests next contribution types. * * Expected in prompt: Topic or problem for collaborative analysis * * Expected in parameters: * - personas?: Array<{id: string, name: string, expertise: string[]}> * - contributions?: Array<{personaId: string, content: string, type: string}> * - stage?: 'problem-definition' | 'exploration' | 'synthesis' | 'conclusion' */ const personas = (parameters.personas as any[]) || []; let contributions = (parameters.contributions as any[]) || []; const stage = getParam("stage", "problem-definition") as string; // Append a synthetic contribution from prompt if none provided if (contributions.length === 0 && prompt) { contributions.push({ personaId: "system", content: prompt, type: "observation", confidence: 0.8 }); } // Suggest next contribution types based on stage let suggestedContributionTypes: string[] = []; switch (stage) { case "problem-definition": suggestedContributionTypes = ["question", "concern", "observation"]; break; case "exploration": suggestedContributionTypes = ["insight", "suggestion", "challenge"]; break; case "synthesis": suggestedContributionTypes = ["synthesis", "insight", "question"]; break; case "conclusion": suggestedContributionTypes = ["synthesis", "concern", "observation"]; break; } const collaborativeData = { topic: prompt, personas, contributions, stage, suggestedContributionTypes, nextContributionNeeded: contributions.length < 3, sessionId: `collab-${Date.now()}`, }; return { toolOperation: "collaborative_reasoning", ...collaborativeData, sessionContext: { sessionId: sessionState.sessionId, stats: sessionState.getStats(), }, }; } case "decision_framework": { /** * Decision Framework Operation * * Accepts options/criteria and computes expected-utility or multi-criteria scores. * * Expected in prompt: Decision to be made * * Expected in parameters: * - options: Array<{id: string, name: string, attributes?: Record<string, any>}> * - criteria: Array<{name: string, weight: number, type: 'maximize'|'minimize'}> * - possibleOutcomes?: Array<{option: string, probability: number, value: number}> * - analysisType: 'expected-utility' | 'multi-criteria' */ const options = (parameters.options as any[]) || []; const criteria = (parameters.criteria as any[]) || []; const possibleOutcomes = (parameters.possibleOutcomes as any[]) || []; const analysisType = getParam("analysisType", "multi-criteria") as string; let result: any = {}; if (analysisType === "expected-utility" && possibleOutcomes.length > 0) { // Calculate expected values for each option const expectedValues: Record<string, number> = {}; options.forEach(opt => { const outcomes = possibleOutcomes.filter(o => o.option === opt.id || o.option === opt.name); expectedValues[opt.id || opt.name] = outcomes.reduce((sum, o) => sum + (o.probability * o.value), 0); }); result.expectedValues = expectedValues; const bestOption = Object.entries(expectedValues).reduce((best, [key, val]) => val > best.value ? {id: key, value: val} : best, {id: "", value: -Infinity}); result.recommendation = bestOption.id; } else if (analysisType === "multi-criteria" && criteria.length > 0) { // Multi-criteria scoring const scores: Record<string, number> = {}; const totalWeight = criteria.reduce((sum, c) => sum + (c.weight || 1), 0); options.forEach(opt => { let score = 0; criteria.forEach(criterion => { const value = opt.attributes?.[criterion.name] || 0; const normalizedWeight = (criterion.weight || 1) / totalWeight; score += value * normalizedWeight; }); scores[opt.id || opt.name] = score; }); result.multiCriteriaScores = scores; const bestOption = Object.entries(scores).reduce((best, [key, val]) => val > best.value ? {id: key, value: val} : best, {id: "", value: -Infinity}); result.recommendation = bestOption.id; } const decisionData = { decisionStatement: prompt, options, criteria, possibleOutcomes, analysisType, ...result, suggestedNextStage: result.recommendation ? "implementation" : "gather-more-data", decisionId: `decision-${Date.now()}`, }; return { toolOperation: "decision_framework", ...decisionData, sessionContext: { sessionId: sessionState.sessionId, stats: sessionState.getStats(), }, }; } case "socratic_method": { /** * Socratic Method Operation * * Builds claims/premises/conclusion structures through questioning. * * Expected in prompt: Initial question or claim to examine * * Expected in parameters: * - claim?: string - The claim being examined * - premises?: string[] - Supporting premises * - stage?: 'clarification' | 'assumptions' | 'reasons' | 'viewpoints' | 'consequences' */ const claim = getParam("claim", ""); let premises = (parameters.premises as string[]) || []; const stage = getParam("stage", "clarification"); // Extract premises from prompt if not provided if (premises.length === 0 && prompt) { // Look for numbered or bulleted reasons const lines = prompt.split(/\n/); lines.forEach(line => { if (/^[\d\-\*•]/.test(line.trim())) { premises.push(line.replace(/^[\d\-\*•\.\)]+\s*/, '').trim()); } }); } // Calculate confidence based on premise strength const strengthKeywords = ['clearly', 'obviously', 'certainly', 'definitely']; const weaknessKeywords = ['maybe', 'perhaps', 'possibly', 'might']; let confidence = 0.5; const allText = `${claim} ${premises.join(' ')}`.toLowerCase(); strengthKeywords.forEach(word => { if (allText.includes(word)) confidence += 0.1; }); weaknessKeywords.forEach(word => { if (allText.includes(word)) confidence -= 0.1; }); confidence = Math.max(0, Math.min(1, confidence)); const socraticData = { question: prompt, claim, premises, conclusion: parameters.conclusion || "", argumentType: parameters.argumentType || "deductive", confidence, stage, nextArgumentNeeded: premises.length < 2, sessionId: `socratic-${Date.now()}`, }; return { toolOperation: "socratic_method", ...socraticData, sessionContext: { sessionId: sessionState.sessionId, stats: sessionState.getStats(), }, }; } case "structured_argumentation": { const argumentData = { claim: prompt, premises: parameters.premises || [], conclusion: parameters.conclusion || "", argumentType: parameters.argumentType || "deductive", confidence: parameters.confidence || 0.5, respondsTo: parameters.respondsTo, supports: parameters.supports || [], contradicts: parameters.contradicts || [], strengths: parameters.strengths || [], weaknesses: parameters.weaknesses || [], relevance: parameters.relevance || 0.5, sessionId: `arg-${Date.now()}`, iteration: parameters.iteration || 1, nextArgumentNeeded: parameters.nextArgumentNeeded || false, }; return { toolOperation: "structured_argumentation", ...argumentData, sessionContext: { sessionId: sessionState.sessionId, stats: sessionState.getStats(), }, }; } case "systems_thinking": { /** * Systems Thinking Operation * * Analyzes complex systems by identifying components, relationships, and feedback loops. * * Expected in prompt: A description of the system to analyze * * Expected in parameters (model should provide these based on analysis): * - components: string[] - Key elements/entities in the system * - relationships: Array<{from: string, to: string, type: string, strength?: number}> - How components interact * - feedbackLoops: Array<{components: string[], type: 'positive'|'negative', description: string}> - Reinforcing or balancing loops * - emergentProperties: string[] - Properties that arise from system interactions * - leveragePoints: string[] - High-impact intervention opportunities * * The model should analyze the system described in the prompt and structure it into these components. */ // Use provided parameters or default to empty arrays const components = (parameters.components as string[]) || []; const relationships = (parameters.relationships as any[]) || []; const feedbackLoops = (parameters.feedbackLoops as any[]) || []; const emergentProperties = (parameters.emergentProperties as string[]) || []; const leveragePoints = (parameters.leveragePoints as string[]) || []; // Validate and detect feedback loops from relationships if not provided if (feedbackLoops.length === 0 && relationships.length > 0) { const graph = new Map<string, Set<string>>(); relationships.forEach((rel: any) => { if (!graph.has(rel.from)) graph.set(rel.from, new Set()); graph.get(rel.from)!.add(rel.to); }); // Simple cycle detection (depth 2-3) for (const [start, targets] of graph.entries()) { for (const mid of targets) { if (graph.has(mid)) { for (const end of graph.get(mid)!) { if (end === start) { // Found 2-cycle feedbackLoops.push({ components: [start, mid], type: 'negative', description: `${start} -> ${mid} -> ${start}` }); } else if (graph.has(end) && graph.get(end)!.has(start)) { // Found 3-cycle feedbackLoops.push({ components: [start, mid, end], type: 'positive', description: `${start} -> ${mid} -> ${end} -> ${start}` }); } } } } } } const systemsData = { system: prompt, components, relationships, feedbackLoops, emergentProperties, leveragePoints, sessionId: `systems-${Date.now()}`, iteration: parameters.iteration || 1, nextAnalysisNeeded: parameters.nextAnalysisNeeded || false, }; // Update KPI for systems components if (components.length > 0) { sessionState.updateKPI('systems_components_count', components.length); } return { toolOperation: "systems_thinking", ...systemsData, sessionContext: { sessionId: sessionState.sessionId, stats: sessionState.getStats(), }, }; } case "session_info": { return { toolOperation: "session_info", sessionId: sessionState.sessionId, stats: sessionState.getStats(), }; } case "session_export": { return { toolOperation: "session_export", sessionData: sessionState.export(), }; } case "session_import": { return { toolOperation: "session_import", result: "Session import completed", }; } // -------------------- New modules -------------------- case "pdr_reasoning": { // PDR uses sequential thinking with progressive refinement pattern return await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt, parameters: { ...parameters, pattern: "chain", patternParams: { depth: 3, breadth: 2, }, }, }, ); } case "research": { /** * Research Operation * * Structures research intent and placeholders for downstream web tooling (no external calls here). * * Expected in prompt: Research question or topic to investigate * * Expected in parameters (model should provide these): * - subqueries?: string[] - Specific sub-questions to research * - findings?: ResearchFinding[] - Any pre-existing findings * - citations?: ResearchSource[] - Any pre-existing sources * * The model should break down the research prompt into specific, searchable questions. */ const subqueries = (parameters.subqueries as string[]) || []; let findings = (parameters.findings as ResearchFinding[]) || []; let citations = (parameters.citations as ResearchSource[]) || []; // If no structured input, create placeholder findings from prompt if (findings.length === 0 && prompt) { // Split prompt into claims and questions const sentences = prompt.split(/[.!?]+/).filter(s => s.trim().length > 0); for (const sentence of sentences.slice(0, 3)) { // Limit to first 3 sentences const trimmed = sentence.trim(); if (trimmed) { // Create placeholder finding findings.push({ claim: `Research needed: ${trimmed}`, evidence: "[Evidence to be gathered]", confidence: 0.0, // No evidence yet sources: [] // No sources yet }); } } } // Generate sub-queries if none provided let derivedSubqueries = subqueries; if (derivedSubqueries.length === 0 && prompt) { // Simple heuristic: look for question words and create variants const questionStarters = ['What', 'How', 'Why', 'When', 'Where', 'Who']; const keywords = prompt.split(/\s+/).filter(w => w.length > 3).slice(0, 3); for (const starter of questionStarters.slice(0, 3)) { for (const keyword of keywords.slice(0, 2)) { derivedSubqueries.push(`${starter} ${keyword.toLowerCase()}?`); } } derivedSubqueries = derivedSubqueries.slice(0, 5); // Limit to 5 subqueries } const result: ResearchResult = { query: prompt, findings, citations, }; return { toolOperation: "research", ...result, subqueries: derivedSubqueries, note: "This operation structures research intent. Use external tools for actual web search and data gathering." }; } case "analogical_reasoning": { /** * Analogical Reasoning Operation * * Maps source→target concept roles using pattern templates. * * Expected in prompt: Description of analogy or domains to compare * * Expected in parameters (model should provide these): * - sourceDomain: string - The familiar domain to map from * - targetDomain: string - The unfamiliar domain to map to * - mappings?: AnalogyMapping[] - Explicit concept mappings * - inferredInsights?: string[] - Insights derived from the analogy * * The model should identify the two domains being compared and map concepts between them. */ let sourceDomain = getParam("sourceDomain", ""); let targetDomain = getParam("targetDomain", ""); let mappings = (parameters.mappings as AnalogyMapping[]) || []; let inferredInsights = (parameters.inferredInsights as string[]) || []; // If domains not provided, try to extract from prompt if (!sourceDomain || !targetDomain) { // Look for "X is like Y" patterns const analogyPatterns = [ /([\w\s]+)\s+is\s+like\s+([\w\s]+)/gi, /([\w\s]+)\s+resembles\s+([\w\s]+)/gi, /([\w\s]+)\s+similar\s+to\s+([\w\s]+)/gi, /compare\s+([\w\s]+)\s+(?:to|with)\s+([\w\s]+)/gi ]; for (const pattern of analogyPatterns) { const match = pattern.exec(prompt); if (match) { sourceDomain = match[1].trim(); targetDomain = match[2].trim(); break; } } // Fallback: split on common separators if (!sourceDomain || !targetDomain) { const parts = prompt.split(/\s+(?:and|vs|versus|compared to)\s+/i); if (parts.length >= 2) { sourceDomain = parts[0].trim(); targetDomain = parts[1].trim(); } } } // Generate mappings if none provided and both domains exist if (mappings.length === 0 && sourceDomain && targetDomain) { // Extract core nouns from both domains const extractNouns = (text: string): string[] => { return text.toLowerCase() .replace(/[^a-z\s]/g, '') .split(/\s+/) .filter(word => word.length > 2 && word.length < 15) .slice(0, 5); // Limit to 5 concepts }; const sourceNouns = extractNouns(sourceDomain); const targetNouns = extractNouns(targetDomain); // Create mappings by position and similarity for (let i = 0; i < Math.min(sourceNouns.length, targetNouns.length); i++) { mappings.push({ sourceConcept: sourceNouns[i], targetConcept: targetNouns[i], mappingType: i === 0 ? "role" : "structure", // First mapping is role, others structure strength: 0.7 - (i * 0.1) // Decreasing confidence }); } // Create cross-mappings for semantic similarity for (const sourceNoun of sourceNouns.slice(0, 2)) { for (const targetNoun of targetNouns.slice(0, 2)) { // Simple heuristic: similar starting letters or length if (sourceNoun[0] === targetNoun[0] || Math.abs(sourceNoun.length - targetNoun.length) <= 1) { mappings.push({ sourceConcept: sourceNoun, targetConcept: targetNoun, mappingType: "behavior", strength: 0.5 }); break; // Only one cross-mapping per source } } } } // Generate insights if none provided if (inferredInsights.length === 0 && mappings.length > 0) { // Generate insights based on mappings for (const mapping of mappings.slice(0, 3)) { switch (mapping.mappingType) { case "role": inferredInsights.push(`${mapping.targetConcept} plays a similar role to ${mapping.sourceConcept}`); break; case "structure": inferredInsights.push(`The structure of ${mapping.targetConcept} mirrors ${mapping.sourceConcept}`); break; case "behavior": inferredInsights.push(`${mapping.targetConcept} behaves similarly to ${mapping.sourceConcept}`); break; case "constraint": inferredInsights.push(`${mapping.targetConcept} has similar constraints as ${mapping.sourceConcept}`); break; } } // Add general insight if (sourceDomain && targetDomain) { inferredInsights.push(`Understanding ${sourceDomain} can help explain ${targetDomain}`); } } const data: AnalogicalReasoningData = { sourceDomain, targetDomain, mappings, inferredInsights, sessionId: `analogy-${Date.now()}`, }; return { toolOperation: "analogical_reasoning", ...data }; } case "causal_analysis": { /** * Causal Analysis Operation * * Builds a lightweight causal graph and calculates intervention effects from text. * * Expected in prompt: Description of causal relationships in natural language * * Expected in parameters (model should provide these based on analysis): * - graph?: { nodes: string[], edges: Array<{from: string, to: string, weight?: number}> } - Causal graph structure * - intervention?: { variable: string, setTo?: number|string|boolean, delta?: number } - Intervention to analyze * - notes?: string[] - Additional observations * * The model should extract causal relationships from the prompt and structure them into a graph. * If an intervention is specified, the model should predict downstream effects. */ // Use provided graph or extract from prompt let graph = getParam("graph", { nodes: [], edges: [] }) as CausalGraph; // If no graph provided, extract from prompt using heuristics if (graph.nodes.length === 0 && prompt) { const text = prompt.toLowerCase(); // Extract nodes via noun phrases (simple heuristic) const nodeMatches = text.match(/\b[a-z]+(?:\s+[a-z]+){0,2}\b/g) || []; const candidateNodes = [...new Set(nodeMatches.filter(n => n.length > 2))]; // Extract edges via causal templates const causalPatterns = [ /([\w\s]+)\s+(?:causes?|increases?|boosts?|improves?)\s+([\w\s]+)/g, /([\w\s]+)\s+(?:reduces?|decreases?|hurts?|harms?)\s+([\w\s]+)/g, /([\w\s]+)\s*->\s*([\w\s]+)/g, /([\w\s]+)\s+leads to\s+([\w\s]+)/g ]; const edges: CausalEdge[] = []; const nodes = new Set<string>(); for (const pattern of causalPatterns) { let match; while ((match = pattern.exec(text)) !== null) { const from = match[1].trim(); const to = match[2].trim(); if (from && to && from !== to) { nodes.add(from); nodes.add(to); // Determine polarity from pattern const weight = pattern.source.includes('reduces?|decreases?|hurts?|harms?') ? -1 : 1; edges.push({ from, to, weight }); } } } graph = { nodes: Array.from(nodes), edges }; } // Calculate intervention effects if intervention provided const intervention = parameters.intervention as Intervention | undefined; let predictedEffects: Record<string, number> | undefined; let counterfactual: Record<string, number> | undefined; if (intervention && graph.edges.length > 0) { predictedEffects = {}; // Simple propagation: for each outgoing edge from intervention variable for (const edge of graph.edges) { if (edge.from === intervention.variable) { const weight = edge.weight || 1; const delta = intervention.delta || (intervention.setTo ? 1 : 0); predictedEffects[edge.to] = (predictedEffects[edge.to] || 0) + (weight * delta); } } // Simple counterfactual: negate the intervention if (Object.keys(predictedEffects).length > 0) { counterfactual = {}; for (const [target, effect] of Object.entries(predictedEffects)) { counterfactual[target] = -effect; } } } const result: CausalAnalysisResult = { graph, intervention, predictedEffects, counterfactual, notes: (parameters.notes as string[]) || [] }; // Update KPIs if (graph.nodes.length > 0) { sessionState.updateKPI('causal_nodes', graph.nodes.length); } if (graph.edges.length > 0) { sessionState.updateKPI('causal_edges', graph.edges.length); } return { toolOperation: "causal_analysis", ...result }; } case "statistical_reasoning": { const mode = getParam("mode", "summary"); let out: Record<string, unknown> = { mode }; if (mode === "summary") { const arr = (parameters.data as number[]) || []; const n = arr.length; const mean = n ? arr.reduce((a, b) => a + b, 0) / n : 0; const variance = n ? arr.reduce((s, x) => s + (x - mean) ** 2, 0) / n : 0; const stddev = Math.sqrt(variance); const stats: SummaryStats = { mean, variance, stddev, min: n ? Math.min(...arr) : 0, max: n ? Math.max(...arr) : 0, n, }; out = { toolOperation: "statistical_reasoning", stats }; } else if (mode === "bayes") { const prior = (parameters.prior as Record<string, number>) || { true: 0.5, false: 0.5, }; const likelihood = (parameters.likelihood as Record< string, number >) || { true: 0.6, false: 0.4 }; // Normalize prior if needed const priorSum = Object.values(prior).reduce((a, b) => a + b, 0) || 1; const normalizedPrior: Record<string, number> = Object.fromEntries( Object.entries(prior).map(([k, v]) => [k, v / priorSum]), ); // Compute evidence and posterior const evidence = Object.keys(likelihood).reduce( (acc, h) => acc + (normalizedPrior[h] ?? 0) * (likelihood[h] ?? 0), 0, ) || 1; const posterior: Record<string, number> = Object.fromEntries( Object.keys(likelihood).map((h) => [ h, ((normalizedPrior[h] ?? 0) * (likelihood[h] ?? 0)) / evidence, ]), ); const bayesianResult: BayesianUpdateResult<string> = { prior: normalizedPrior, likelihood, posterior, evidence, }; out = { toolOperation: "statistical_reasoning", bayesianResult }; } else if (mode === "hypothesis_test") { const testResult: HypothesisTestResult = { test: getParam("test", "z"), statistic: getParam("testStatistic", 0), pValue: getParam("pValue", 0.05), dof: getParam("dof", undefined as unknown as number | undefined), effectSize: getParam( "effectSize", undefined as unknown as number | undefined, ), }; out = { toolOperation: "statistical_reasoning", testResult }; } else if (mode === "monte_carlo") { const samplesArr = (parameters.samples as number[]) || []; const n = samplesArr.length; const mean = n ? samplesArr.reduce((a, b) => a + b, 0) / n : 0; const variance = n ? samplesArr.reduce((s, x) => s + (x - mean) ** 2, 0) / n : 0; const stddev = Math.sqrt(variance); const sorted = [...samplesArr].sort((a, b) => a - b); const percentile = { p05: sorted.length ? sorted[Math.floor(0.05 * (sorted.length - 1))] : 0, p50: sorted.length ? sorted[Math.floor(0.5 * (sorted.length - 1))] : 0, p95: sorted.length ? sorted[Math.floor(0.95 * (sorted.length - 1))] : 0, } as Record<string, number>; const mcResult: MonteCarloResult = { samples: n, mean, stddev, percentile, }; out = { toolOperation: "statistical_reasoning", mcResult }; } return out; } case "simulation": { /** * Simulation Operation * * Runs a toy discrete-time state update for named variables. * * Expected in prompt: Description of the system to simulate * * Expected in parameters (model should provide these): * - initial?: Record<string,number> - Initial state variables * - updateRules?: Array<{target: string, rule: string}> - Update rules like "x = x + 1" * - steps?: number - Number of simulation steps (default: 10) * * The model should define initial conditions and update rules for the simulation. */ const steps = getParam("steps", 10); const initial = (parameters.initial as Record<string, number>) || {}; const updateRules = (parameters.updateRules as Array<{target: string, rule: string}>) || []; // Initialize state let currentState = { ...initial }; const trajectory: Array<Record<string, number>> = []; // If no initial state provided, try to extract from prompt if (Object.keys(currentState).length === 0 && prompt) { // Simple heuristic: look for "x=5" patterns const initMatches = prompt.match(/([a-zA-Z]\w*)\s*=\s*([\d\.]+)/g); if (initMatches) { for (const match of initMatches) { const [, variable, value] = match.match(/([a-zA-Z]\w*)\s*=\s*([\d\.]+)/) || []; if (variable && value) { currentState[variable] = parseFloat(value); } } } } // If no update rules provided, create simple increment rules let rules = updateRules; if (rules.length === 0 && Object.keys(currentState).length > 0) { rules = Object.keys(currentState).map(variable => ({ target: variable, rule: `${variable} + 1` })); } // Run simulation for (let step = 0; step < steps; step++) { // Record current state trajectory.push({ ...currentState }); // Apply update rules const newState = { ...currentState }; for (const rule of rules) { try { // Safe evaluation of simple expressions const expression = rule.rule; // Replace variables with current values let evaluatedExpression = expression; for (const [variable, value] of Object.entries(currentState)) { const regex = new RegExp(`\\b${variable}\\b`, 'g'); evaluatedExpression = evaluatedExpression.replace(regex, value.toString()); } // Simple safe evaluation (only allows basic math) if (/^[\d\s+\-*/().]+$/.test(evaluatedExpression)) { const result = Function(`"use strict"; return (${evaluatedExpression})`)(); if (typeof result === 'number' && !isNaN(result)) { newState[rule.target] = result; } } } catch (error) { // Skip invalid rules continue; } } currentState = newState; } const simResult: SimulationResult = { steps, trajectory, finalState: currentState, }; return { toolOperation: "simulation", ...simResult }; } case "optimization": { /** * Optimization Operation * * Simple hill-climb or grid search over bounded variables with objective callback. * * Expected in prompt: Description of optimization problem * * Expected in parameters (model should provide these): * - variables: Record<string,{min:number,max:number,step?:number}> - Variables to optimize * - objective: string - Objective function expression * - iterations?: number - Number of iterations for hill climbing (default: 100) * - method?: "grid"|"hill" - Optimization method (default: "grid") * * The model should define the optimization problem structure. */ const variables = (parameters.variables as Record<string, {min: number, max: number, step?: number}>) || {}; const objective = (parameters.objective as string) || ""; const iterations = getParam("iterations", 100); const method = getParam("method", "grid") as "grid" | "hill"; let bestDecisionVector: number[] = []; let bestObjective = -Infinity; let actualIterations = 0; let constraintsSatisfied = false; // Validate inputs if (Object.keys(variables).length === 0 || !objective) { return { toolOperation: "optimization", bestDecisionVector: [], bestObjective: 0, iterations: 0, constraintsSatisfied: false, error: "Variables and objective function required" }; } // Helper function to evaluate objective safely const evaluateObjective = (assignment: Record<string, number>): number => { try { // Replace variables in objective with values let expression = objective; for (const [variable, value] of Object.entries(assignment)) { const regex = new RegExp(`\\b${variable}\\b`, 'g'); expression = expression.replace(regex, value.toString()); } // Safe evaluation (only basic math) if (/^[\d\s+\-*/().]+$/.test(expression)) { const result = Function(`"use strict"; return (${expression})`)(); return typeof result === 'number' && !isNaN(result) ? result : -Infinity; } return -Infinity; } catch { return -Infinity; } }; const variableNames = Object.keys(variables); if (method === "grid") { // Grid search: cartesian product over steps const generateGridPoints = (varIndex: number, currentAssignment: Record<string, number>): void => { if (varIndex >= variableNames.length) { // Evaluate this point const objectiveValue = evaluateObjective(currentAssignment); actualIterations++; if (objectiveValue > bestObjective) { bestObjective = objectiveValue; bestDecisionVector = variableNames.map(name => currentAssignment[name]); constraintsSatisfied = true; } return; } const varName = variableNames[varIndex]; const varSpec = variables[varName]; const step = varSpec.step || 1; for (let value = varSpec.min; value <= varSpec.max; value += step) { currentAssignment[varName] = value; generateGridPoints(varIndex + 1, currentAssignment); } }; generateGridPoints(0, {}); } else if (method === "hill") { // Hill climbing: random start then coordinate ascent const assignment: Record<string, number> = {}; // Random start for (const [name, spec] of Object.entries(variables)) { assignment[name] = spec.min + Math.random() * (spec.max - spec.min); } let currentObjective = evaluateObjective(assignment); bestObjective = currentObjective; bestDecisionVector = variableNames.map(name => assignment[name]); for (let iter = 0; iter < iterations; iter++) { actualIterations++; let improved = false; // Try improving each variable for (const [name, spec] of Object.entries(variables)) { const step = spec.step || (spec.max - spec.min) / 10; const originalValue = assignment[name]; // Try step up if (originalValue + step <= spec.max) { assignment[name] = originalValue + step; const newObjective = evaluateObjective(assignment); if (newObjective > currentObjective) { currentObjective = newObjective; improved = true; continue; } } // Try step down if (originalValue - step >= spec.min) { assignment[name] = originalValue - step; const newObjective = evaluateObjective(assignment); if (newObjective > currentObjective) { currentObjective = newObjective; improved = true; continue; } } // Restore original value if no improvement assignment[name] = originalValue; } // Update best if improved if (currentObjective > bestObjective) { bestObjective = currentObjective; bestDecisionVector = variableNames.map(name => assignment[name]); constraintsSatisfied = true; } // Stop if no improvement if (!improved) break; } } const optResult: OptimizationResult = { bestDecisionVector, bestObjective: bestObjective === -Infinity ? 0 : bestObjective, iterations: actualIterations, constraintsSatisfied, }; return { toolOperation: "optimization", ...optResult }; } case "ethical_analysis": { /** * Ethical Analysis Operation * * Scores findings/risks/mitigations based on selected ethical framework. * * Expected in prompt: Description of situation or decision to analyze ethically * * Expected in parameters (model should provide these): * - framework?: "utilitarian"|"rights"|"fairness"|"compliance" - Ethical framework to apply * - findings?: string[] - Pre-identified ethical considerations * - risks?: string[] - Pre-identified ethical risks * - mitigations?: string[] - Pre-identified mitigations * * The model should analyze the prompt through the lens of the specified ethical framework. */ // Handle "multiple" framework by defaulting to utilitarian for base analysis let framework = getParam("framework", "utilitarian") as string; const multiFramework = framework === "multiple"; if (multiFramework) { framework = "utilitarian"; // Default to utilitarian for base analysis } let findings = (parameters.findings as string[]) || []; let risks = (parameters.risks as string[]) || []; let mitigations = (parameters.mitigations as string[]) || []; // If no structured input provided, extract from prompt if (findings.length === 0 && risks.length === 0 && prompt) { const text = prompt.toLowerCase(); // Framework-specific keyword extraction const frameworkKeywords: Record<string, {positive: string[], negative: string[], mitigation: string[]}> = { utilitarian: { positive: ['benefit', 'happiness', 'welfare', 'utility', 'wellbeing', 'satisfaction'], negative: ['harm', 'suffering', 'pain', 'damage', 'cost', 'negative impact'], mitigation: ['compensate', 'offset', 'balance', 'optimize', 'maximize benefit'] }, rights: { positive: ['rights', 'freedom', 'autonomy', 'consent', 'dignity', 'respect'], negative: ['violation', 'coercion', 'discrimination', 'exploitation', 'unfair'], mitigation: ['consent', 'transparency', 'due process', 'appeal', 'protection'] }, fairness: { positive: ['equal', 'fair', 'just', 'equitable', 'impartial', 'unbiased'], negative: ['bias', 'unfair', 'discrimination', 'inequality', 'prejudice'], mitigation: ['diverse', 'inclusive', 'representative', 'balanced', 'audit'] }, compliance: { positive: ['legal', 'compliant', 'regulation', 'standard', 'policy', 'guideline'], negative: ['illegal', 'violation', 'breach', 'non-compliant', 'regulatory risk'], mitigation: ['audit', 'review', 'documentation', 'training', 'oversight'] } }; const keywords = frameworkKeywords[framework] || frameworkKeywords.utilitarian; // Fallback to utilitarian if framework not found // Extract findings (positive indicators) for (const keyword of keywords.positive) { if (text.includes(keyword)) { findings.push(`Identified ${keyword} considerations`); } } // Extract risks (negative indicators) for (const keyword of keywords.negative) { if (text.includes(keyword)) { risks.push(`Risk of ${keyword}`); } } // Extract mitigations for (const keyword of keywords.mitigation) { if (text.includes(keyword)) { mitigations.push(`Consider ${keyword} measures`); } } // Add default framework-specific suggestions if none found if (findings.length === 0) { switch (framework) { case 'utilitarian': findings.push('Consider overall welfare impact', 'Evaluate benefits vs costs'); break; case 'rights': findings.push('Assess impact on individual rights', 'Consider autonomy and dignity'); break; case 'fairness': findings.push('Evaluate equitable treatment', 'Check for bias or discrimination'); break; case 'compliance': findings.push('Review regulatory requirements', 'Ensure legal compliance'); break; } } } // Calculate score based on framework let score = getParam("score", undefined) as number | undefined; if (score === undefined) { // Simple scoring: positive findings vs risks const positiveWeight = findings.length; const negativeWeight = risks.length; const mitigationWeight = mitigations.length; // Score from 0 to 1, where 1 is most ethical if (positiveWeight + negativeWeight + mitigationWeight === 0) { score = 0.5; // Neutral if no information } else { score = Math.min(1, Math.max(0, (positiveWeight + mitigationWeight * 0.5) / (positiveWeight + negativeWeight + mitigationWeight) )); } } const ethicalResult: EthicalAssessment = { framework: framework as EthicalAssessment["framework"], findings, risks, mitigations, score, }; return { toolOperation: "ethical_analysis", ...ethicalResult }; } case "visual_dashboard": { /** * Visual Dashboard Operation * * Creates interactive visual dashboards using MCP UI patterns. * Supports HTML, external URLs, and remote DOM components. * * Expected in prompt: Description of what to visualize * * Expected in parameters: * - visualizationType: 'chart' | 'graph' | 'metrics' | 'custom' * - data: Object containing the data to visualize * - panels: Array of dashboard panels with their configurations * - layout: 'grid' | 'flex' | 'tabs' | 'stack' * - interactive: boolean - Enable interactive features * - uiType: 'rawHtml' | 'externalUrl' | 'remoteDom' * - refreshRate: number - Auto-refresh interval in milliseconds */ const visualizationType = getParam("visualizationType", "chart"); const data = parameters.data || {}; const panels = (parameters.panels as Array<any>) || []; const layout = getParam("layout", "grid"); const interactive = getParam("interactive", true); const uiType = getParam("uiType", "rawHtml"); const refreshRate = getParam("refreshRate", 0); // Generate content based on type let uiResource; try { if (uiType === "rawHtml") { // Generate inline HTML with charts/graphs const htmlContent = generateDashboardHTML({ title: prompt, visualizationType, data, panels, layout, interactive, }); // Note: createUIResource is not available in current setup uiResource = { uri: `ui://dashboard/${Date.now()}`, content: { type: "rawHtml", htmlString: htmlContent, }, encoding: "blob", // Use blob encoding like graphing-calculator }; } else if (uiType === "externalUrl") { // Use external visualization service const externalUrl = String(parameters.externalUrl || "https://example.com/dashboard"); // Note: createUIResource is not available in current setup uiResource = { uri: `ui://dashboard/${Date.now()}`, content: { type: "externalUrl", iframeUrl: externalUrl, }, encoding: "text", }; } else if (uiType === "remoteDom") { // Generate remote DOM script for dynamic content const remoteDomScript = generateRemoteDomScript({ visualizationType, data, panels, interactive, }); // Note: createUIResource is not available in current setup uiResource = { uri: `ui://dashboard/${Date.now()}`, content: { type: "remoteDom", script: remoteDomScript, framework: "react", }, encoding: "blob", }; } else { // Fallback to simple HTML // Note: createUIResource is not available in current setup uiResource = { uri: `ui://dashboard/${Date.now()}`, content: { type: "rawHtml", htmlString: "<h1>Dashboard</h1><p>No visualization type specified</p>", }, encoding: "text", }; } } catch (error) { // Error handling with error UI resource // Note: createUIResource is not available in current setup uiResource = { uri: `ui://dashboard-error/${Date.now()}`, content: { type: "rawHtml", htmlString: ` <div style="padding: 20px; font-family: system-ui;"> <h2 style="color: #dc3545;">Dashboard Creation Error</h2> <p>${error instanceof Error ? error.message : "Unknown error occurred"}</p> </div> `, }, encoding: "text", }; } // Return format matching graphing-calculator pattern return { content: [uiResource], }; } case "custom_framework": { return { toolOperation: "custom_framework", framework: { name: prompt, stages: parameters.stages || [], rules: parameters.rules || [], metrics: parameters.metrics || [], }, }; } case "code_execution": { // Handled above in the main function return { toolOperation: "code_execution", result: "Code execution requires special handling", }; } // Reasoning pattern operations case "tree_of_thought": { // Create notebook with preset if not exists const sessionId = sessionState.sessionId; let notebook = notebookStore.getNotebookBySession(sessionId); if (!notebook && getParam("createNotebook", true)) { notebook = notebookStore.createNotebook(sessionId); const preset = getPresetForPattern("tree_of_thought"); if (preset) { for (const cell of preset.cells) { notebookStore.addCell( notebook.id, cell.type, cell.source, cell.language, ); } } } // Alias to sequential_thinking with tree pattern return await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt, parameters: { pattern: "tree", patternParams: { depth: (parameters as any).depth || 3, breadth: (parameters as any).breadth || 3, branches: (parameters as any).branches || [], evaluations: (parameters as any).evaluations || [], selectedPath: (parameters as any).selectedPath || null, }, thoughtNumber: (parameters as any).thoughtNumber || 1, totalThoughts: (parameters as any).totalThoughts || 3, nextThoughtNeeded: (parameters as any).nextThoughtNeeded ?? true, needsMoreThoughts: (parameters as any).needsMoreThoughts ?? true, __disablePatternDispatch: true, notebookId: notebook?.id, } as Record<string, unknown>, }, ); } case "beam_search": { // Create notebook with preset if not exists const sessionId = sessionState.sessionId; let notebook = notebookStore.getNotebookBySession(sessionId); if (!notebook && getParam("createNotebook", true)) { notebook = notebookStore.createNotebook(sessionId); const preset = getPresetForPattern("beam_search"); if (preset) { for (const cell of preset.cells) { notebookStore.addCell( notebook.id, cell.type, cell.source, cell.language, ); } } } // Alias to sequential_thinking with beam pattern return await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt, parameters: { pattern: "beam", patternParams: { beamWidth: (parameters as any).beamWidth || 3, candidates: (parameters as any).candidates || [], scores: (parameters as any).scores || [], iterations: (parameters as any).iterations || 5, }, thoughtNumber: (parameters as any).thoughtNumber || 1, totalThoughts: (parameters as any).totalThoughts || 3, nextThoughtNeeded: (parameters as any).nextThoughtNeeded ?? true, needsMoreThoughts: (parameters as any).needsMoreThoughts ?? true, __disablePatternDispatch: true, notebookId: notebook?.id, } as Record<string, unknown>, }, ); } case "mcts": { // Create notebook with preset if not exists const sessionId = sessionState.sessionId; let notebook = notebookStore.getNotebookBySession(sessionId); if (!notebook && getParam("createNotebook", true)) { notebook = notebookStore.createNotebook(sessionId); const preset = getPresetForPattern("mcts"); if (preset) { for (const cell of preset.cells) { notebookStore.addCell( notebook.id, cell.type, cell.source, cell.language, ); } } } // Alias to sequential_thinking with mcts pattern return await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt, parameters: { pattern: "mcts", patternParams: { simulations: (parameters as any).simulations || 100, explorationConstant: (parameters as any).explorationConstant || Math.SQRT2, tree: (parameters as any).tree || { root: { visits: 0, value: 0, children: [] }, }, bestAction: (parameters as any).bestAction || null, }, thoughtNumber: (parameters as any).thoughtNumber || 1, totalThoughts: (parameters as any).totalThoughts || 3, nextThoughtNeeded: (parameters as any).nextThoughtNeeded ?? true, needsMoreThoughts: (parameters as any).needsMoreThoughts ?? true, __disablePatternDispatch: true, notebookId: notebook?.id, } as Record<string, unknown>, }, ); } case "graph_of_thought": { // Create notebook with preset if not exists const sessionId = sessionState.sessionId; let notebook = notebookStore.getNotebookBySession(sessionId); if (!notebook && getParam("createNotebook", true)) { notebook = notebookStore.createNotebook(sessionId); const preset = getPresetForPattern("graph_of_thought"); if (preset) { for (const cell of preset.cells) { notebookStore.addCell( notebook.id, cell.type, cell.source, cell.language, ); } } } // Alias to sequential_thinking with graph pattern return await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt, parameters: { pattern: "graph", patternParams: { nodes: (parameters as any).nodes || [], edges: (parameters as any).edges || [], paths: (parameters as any).paths || [], optimalPath: (parameters as any).optimalPath || null, }, thoughtNumber: (parameters as any).thoughtNumber || 1, totalThoughts: (parameters as any).totalThoughts || 3, nextThoughtNeeded: (parameters as any).nextThoughtNeeded ?? true, needsMoreThoughts: (parameters as any).needsMoreThoughts ?? true, __disablePatternDispatch: true, notebookId: notebook?.id, } as Record<string, unknown>, }, ); } case "orchestration_suggest": { // Create notebook with preset if not exists const sessionId = sessionState.sessionId; let notebook = notebookStore.getNotebookBySession(sessionId); if (!notebook && getParam("createNotebook", true)) { notebook = notebookStore.createNotebook(sessionId); const preset = getPresetForPattern("orchestration_suggest"); if (preset) { for (const cell of preset.cells) { notebookStore.addCell( notebook.id, cell.type, cell.source, cell.language, ); } } } // Kick off a brief sequential_thinking step to seed orchestration with context const initialThought = await executeClearThoughtOperation( sessionState, "sequential_thinking", { prompt: `Plan approach for task: ${prompt}`, parameters: { thoughtNumber: 1, totalThoughts: 3, nextThoughtNeeded: true, needsMoreThoughts: true, pattern: "chain", }, }, ); return { toolOperation: "orchestration_suggest", task: prompt, suggestedTools: ["sequential_thinking", "mental_model"], reasoning: "Initialized with a short sequential_thinking pass to decompose the task, then apply a mental model for framing.", initialThought, workflow: [ { step: "sequential_thinking", purpose: "quick task decomposition (1-3 thoughts)", }, { step: "mental_model", purpose: "apply appropriate model to frame solution", }, ], notebookId: notebook?.id, }; } // Notebook operations case "notebook_create": { const sessionId = sessionState.sessionId; const notebook = notebookStore.createNotebook(sessionId); // Add preset if pattern specified const pattern = getParam("pattern", "") as string; if (pattern) { const preset = getPresetForPattern(pattern); if (preset) { for (const cell of preset.cells) { notebookStore.addCell( notebook.id, cell.type, cell.source, cell.language, ); } } } return { toolOperation: "notebook_create", notebookId: notebook.id, sessionId: notebook.sessionId, createdAt: new Date(notebook.createdAt).toISOString(), pattern: pattern || "blank", }; } case "notebook_add_cell": { const notebookId = getParam("notebookId", "") as string; const cellType = getParam("cellType", "code") as "markdown" | "code"; const source = getParam("source", "") as string; const language = getParam("language", "javascript") as | "javascript" | "typescript"; const index = getParam("index", undefined) as number | undefined; const cell = notebookStore.addCell( notebookId, cellType, source, language, index, ); return { toolOperation: "notebook_add_cell", notebookId, cell: cell ? { id: cell.id, type: cell.type, source: cell.source, language: cell.language, status: cell.status, } : null, success: cell !== null, }; } case "notebook_run_cell": { // This is handled in handleClearThoughtTool due to async requirements return { toolOperation: "notebook_run_cell", message: "This operation is handled asynchronously in handleClearThoughtTool", }; } case "notebook_export": { const notebookId = getParam("notebookId", "") as string; const format = getParam("format", "srcmd") as "srcmd" | "json"; if (format === "srcmd") { const srcmd = notebookStore.exportToSrcMd(notebookId); return { toolOperation: "notebook_export", notebookId, format: "srcmd", content: srcmd, success: srcmd !== null, }; } else { const json = notebookStore.exportToJson(notebookId); return { toolOperation: "notebook_export", notebookId, format: "json", content: json, success: json !== null, }; } } // =============== Metagame Operations =============== case "ooda_loop": { const { createOODASession, advancePhase, createOODANode, suggestNextActions, evaluateEvidenceQuality, exportToMarkdown, } = await import("../types/reasoning-patterns/ooda-loop.js"); // Get or create session const oodaSessionId = getParam( "sessionId", `ooda-${Date.now()}`, ) as string; let oodaSession = sessionState.getOODASession(oodaSessionId); if (!oodaSession) { oodaSession = createOODASession({ maxLoopTimeMs: getParam("maxLoopTimeMs", 15 * 60 * 1000) as number, autoAdvance: getParam("autoAdvance", true) as boolean, minEvidence: getParam("minEvidence", 2) as number, }); sessionState.setOODASession(oodaSessionId, oodaSession); } // Process the current phase const evidence = getParam("evidence", []) as string[]; // Create node for current phase const node = createOODANode(prompt, oodaSession.currentPhase, evidence); // Add hypotheses if provided const hypotheses = getParam("hypotheses", []) as Array<{ statement: string; confidence: number; }>; for (const hyp of hypotheses) { const hypId = `hyp-${Date.now()}-${Math.random()}`; oodaSession.hypotheses.set(hypId, { id: hypId, statement: hyp.statement, confidence: hyp.confidence, status: "proposed", carriedForward: false, }); } // Calculate metrics node.phaseTimeMs = Date.now() - new Date(oodaSession.loopStartTime || oodaSession.createdAt).getTime(); oodaSession.metrics.evidenceQuality = evaluateEvidenceQuality(node); // Add node to session oodaSession.nodes.push(node); oodaSession.iteration++; // Track KPIs sessionState.updateKPI( "ooda_loop_time", oodaSession.metrics.avgLoopTimeMs, "Avg Loop Time (ms)", 5 * 60 * 1000, "down", ); sessionState.updateKPI( "ooda_learning_rate", oodaSession.metrics.learningRate, "Learning Rate", 0.7, "up", ); sessionState.updateKPI( "ooda_evidence_quality", oodaSession.metrics.evidenceQuality, "Evidence Quality", 0.8, "up", ); // Auto-advance if configured if ( oodaSession.config.autoAdvance && evidence.length >= oodaSession.config.minEvidence ) { oodaSession = advancePhase(oodaSession); } // Get suggestions const suggestions = suggestNextActions(oodaSession); // Save session sessionState.setOODASession(oodaSessionId, oodaSession); return { toolOperation: "ooda_loop", sessionId: oodaSessionId, currentPhase: oodaSession.currentPhase, loopNumber: oodaSession.loopNumber, metrics: oodaSession.metrics, suggestions, hypotheses: Array.from(oodaSession.hypotheses.values()), export: getParam("includeExport", false) ? exportToMarkdown(oodaSession) : undefined, sessionContext: { sessionId: sessionState.sessionId, kpis: sessionState.getKPIs(), }, }; } case "ulysses_protocol": { const { createUlyssesSession, advancePhase, createUlyssesNode, checkConstraints, suggestNextActions, makeFinalDecision, exportToMarkdown, } = await import("../types/reasoning-patterns/ulysses-protocol.js"); // Get or create session const ulyssesSessionId = getParam( "sessionId", `ulysses-${Date.now()}`, ) as string; let ulyssesSession = sessionState.getUlyssesSession(ulyssesSessionId); if (!ulyssesSession) { ulyssesSession = createUlyssesSession({ constraints: { timeboxMs: getParam("timeboxMs", 4 * 60 * 60 * 1000) as number, maxIterations: getParam("maxIterations", 3) as number, minConfidence: getParam("minConfidence", 0.8) as number, maxScopeDrift: getParam("maxScopeDrift", 1) as number, }, policy: { autoEscalate: getParam("autoEscalate", true) as boolean, notifyWhen: getParam("notifyWhen", [ "gateFail", "timeboxNear", ]) as any, allowOverride: getParam("allowOverride", false) as boolean, }, }); sessionState.setUlyssesSession(ulyssesSessionId, ulyssesSession); } // Process the current phase const confidence = getParam("confidence", 0.5) as number; const evidence = getParam("evidence", []) as string[]; const iteration = ulyssesSession.currentPhase === "implementation" ? ulyssesSession.implementationIteration : undefined; // Create node const node = createUlyssesNode( prompt, ulyssesSession.currentPhase, confidence, iteration, ); node.evidence = evidence; node.timeSpentMs = Date.now() - new Date(ulyssesSession.startTime).getTime(); // Check for scope changes const scopeChange = getParam("scopeChange", null) as any; if (scopeChange) { node.scopeChange = scopeChange; } // Add node to session ulyssesSession.nodes.push(node); ulyssesSession.iteration++; // Increment implementation iteration if in that phase if (ulyssesSession.currentPhase === "implementation") { ulyssesSession.implementationIteration++; ulyssesSession.metrics.iterations = ulyssesSession.implementationIteration; } // Check constraints and escalate if needed const constraintCheck = checkConstraints(ulyssesSession); if (constraintCheck.escalation) { node.escalated = constraintCheck.escalation; } // Track KPIs sessionState.updateKPI( "ulysses_confidence", ulyssesSession.metrics.confidence, "Confidence", 0.8, "up", ); sessionState.updateKPI( "ulysses_iterations", ulyssesSession.metrics.iterations, "Iterations", 3, "down", ); sessionState.updateKPI( "ulysses_scope_drift", ulyssesSession.metrics.scopeDrift, "Scope Drift", 1, "down", ); sessionState.updateKPI( "ulysses_time_remaining", ulyssesSession.metrics.timeRemainingMs, "Time Remaining (ms)", 0, "up", ); // Try to advance phase if requested const attemptAdvance = getParam("attemptAdvance", false) as boolean; let phaseAdvanced = false; if (attemptAdvance) { const result = advancePhase(ulyssesSession, evidence); phaseAdvanced = result.success; if (result.success && result.newPhase) { ulyssesSession.currentPhase = result.newPhase; } } // Make final decision if in ship_or_abort phase if ( ulyssesSession.currentPhase === "ship_or_abort" && getParam("makeFinalDecision", false) ) { const rationale = getParam( "decisionRationale", "Based on current metrics and constraints", ) as string; ulyssesSession.finalDecision = makeFinalDecision( ulyssesSession, rationale, ); } // Get suggestions const suggestions = suggestNextActions(ulyssesSession); // Save session sessionState.setUlyssesSession(ulyssesSessionId, ulyssesSession); return { toolOperation: "ulysses_protocol", sessionId: ulyssesSessionId, currentPhase: ulyssesSession.currentPhase, gates: ulyssesSession.gates, metrics: ulyssesSession.metrics, constraints: ulyssesSession.constraints, constraintViolations: constraintCheck.violations, escalation: constraintCheck.escalation, suggestions, phaseAdvanced, finalDecision: ulyssesSession.finalDecision, export: getParam("includeExport", false) ? exportToMarkdown(ulyssesSession) : undefined, sessionContext: { sessionId: sessionState.sessionId, kpis: sessionState.getKPIs(), }, }; } default: return { toolOperation: "unknown", error: `Unknown operation: ${operation}`, availableOperations: [ "sequential_thinking", "mental_model", "debugging_approach", "creative_thinking", "visual_reasoning", "metacognitive_monitoring", "scientific_method", "collaborative_reasoning", "decision_framework", "socratic_method", "structured_argumentation", "systems_thinking", "session_info", "session_export", "session_import", "pdr_reasoning", "research", "analogical_reasoning", "causal_analysis", "statistical_reasoning", "simulation", "optimization", "ethical_analysis", "visual_dashboard", "custom_framework", "code_execution", "tree_of_thought", "beam_search", "mcts", "graph_of_thought", "orchestration_suggest", "notebook_create", "notebook_add_cell", "notebook_run_cell", "notebook_export", ], }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/waldzellai/clearthought-onepointfive'

If you have feedback or need assistance with the MCP directory API, please join our Discord server