Skip to main content
Glama
critical-stream.ts31.8 kB
/** * Critical Reasoning Stream * * Implements skeptical, evaluative thinking with: * - Weakness identification in arguments and solutions * - Assumption challenging and questioning * - Risk assessment and threat analysis * - Flaw detection in logic and reasoning * - Skeptical and devil's advocate approach * - Counter-argument generation * - Progress tracking and timeout management * - Problem-specific weaknesses (Requirements 4.3, 15.3) */ import { KeyTermExtractor, type KeyTerms } from "../key-term-extractor"; import type { ReasoningStream, StreamProcessor } from "../stream"; import { StreamStatus, StreamType, type Insight, type Problem, type StreamResult } from "../types"; /** * Critical stream processor * * Implements the core critical reasoning logic with weakness detection, * assumption challenging, risk assessment, and counter-argument generation. * Generates problem-specific weaknesses using key term extraction. */ export class CriticalStreamProcessor implements StreamProcessor { private readonly keyTermExtractor: KeyTermExtractor; constructor() { this.keyTermExtractor = new KeyTermExtractor(); } /** * Process a problem using critical reasoning * * @param problem - Problem to analyze * @returns Promise resolving to stream result */ async process(problem: Problem): Promise<StreamResult> { const startTime = Date.now(); const reasoning: string[] = []; const insights: Insight[] = []; // Validate problem - throw for truly invalid problems if (!problem || !problem.id || !problem.description) { throw new Error("Invalid problem: missing required fields"); } try { // Extract key terms for problem-specific criticism (Req 4.3, 15.3) const keyTerms = this.keyTermExtractor.extract(problem.description, problem.context); const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the proposal"; // Step 1: Initial skeptical assessment reasoning.push( `Critically examining: ${problem.description.substring(0, 100)}${problem.description.length > 100 ? "..." : ""}` ); // Step 2: Identify weaknesses and flaws const weaknesses = this.identifyWeaknesses(problem, keyTerms); if (weaknesses.length > 0) { reasoning.push( `Identified ${weaknesses.length} potential weakness${weaknesses.length > 1 ? "es" : ""} in ${primaryTerm}` ); reasoning.push(`Logical gaps in ${primaryTerm} require clarification before proceeding`); reasoning.push( `Implementation challenges for ${primaryTerm} include complexity given current constraints` ); insights.push(...weaknesses); } // Step 3: Challenge assumptions const assumptions = this.challengeAssumptions(problem, keyTerms); if (assumptions.length > 0) { reasoning.push( `Questioning ${assumptions.length} underlying assumption${assumptions.length > 1 ? "s" : ""} about ${primaryTerm}` ); // Check for optimistic projections if (problem.context.includes("%")) { reasoning.push( `Projections for ${primaryTerm} appear optimistic - need validation of achievable targets` ); } insights.push(...assumptions); } // Step 4: Assess risks const risks = this.assessRisks(problem, keyTerms); if (risks.length > 0) { reasoning.push( `Risk assessment for ${primaryTerm} reveals ${risks.length} significant concern${risks.length > 1 ? "s" : ""}` ); reasoning.push( `Unintended consequences from ${primaryTerm} could have broader impact than anticipated` ); reasoning.push( `Worst-case scenario: ${primaryTerm} could fail and cause more harm than good` ); reasoning.push(`Risk mitigation strategies for ${primaryTerm} should be developed`); insights.push(...risks); } // Step 5: Detect logical flaws const flaws = this.detectFlaws(problem, keyTerms); reasoning.push( `Logical analysis of ${primaryTerm} identifies potential flaws and errors in reasoning` ); // Add specific reasoning for detected flaws for (const flaw of flaws) { if (flaw.content.toLowerCase().includes("circular")) { reasoning.push( `Circular reasoning detected in ${primaryTerm} - argument repeats itself without adding substance` ); } } if (flaws.length > 0) { insights.push(...flaws); } // Step 6: Play devil's advocate const counterArguments = this.generateCounterArguments(problem, keyTerms); if (counterArguments.length > 0) { reasoning.push( `Devil's advocate on ${primaryTerm}: ${counterArguments[0].content.substring(0, 80)}...` ); reasoning.push( `Counter-argument: alternative approaches to ${primaryTerm} may be more effective` ); reasoning.push( `Constructive criticism: ${primaryTerm} could improve by addressing root causes` ); insights.push(...counterArguments); } // Step 7: Evaluate evidence quality const evidenceAssessment = this.evaluateEvidence(problem, keyTerms); reasoning.push(evidenceAssessment.reasoning); if (evidenceAssessment.insight) { insights.push(evidenceAssessment.insight); } // Step 8: Consider constraints critically if (problem.constraints && problem.constraints.length > 0) { reasoning.push( `Constraints on ${primaryTerm}: ${problem.constraints.join(", ")} - these may be more limiting than acknowledged` ); reasoning.push( `Challenging conventional wisdom about ${primaryTerm}: the standard approach may not be optimal` ); const constraintContent = `Constraints on ${primaryTerm} (${problem.constraints.join(", ")}) may significantly limit feasibility`; insights.push({ content: constraintContent, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(constraintContent, keyTerms), }); } // Step 9: Generate conclusion const conclusion = this.generateConclusion(problem, insights, keyTerms); reasoning.push(`Therefore, ${conclusion}`); // Add balanced perspective reasoning.push( `While concerns about ${primaryTerm} exist, there could be potential if issues are addressed` ); // Calculate confidence based on thoroughness of criticism const confidence = this.calculateConfidence(problem, insights); const processingTime = Math.max(1, Date.now() - startTime); return { streamId: `critical-${problem.id}`, streamType: StreamType.CRITICAL, conclusion, reasoning, insights, confidence, processingTime, status: StreamStatus.COMPLETED, }; } catch (error) { const processingTime = Math.max(1, Date.now() - startTime); return { streamId: `critical-${problem.id}`, streamType: StreamType.CRITICAL, conclusion: "", reasoning, insights, confidence: 0, processingTime, status: StreamStatus.FAILED, error: error as Error, }; } } /** * Get the stream type this processor handles * * @returns Stream type identifier */ getStreamType(): StreamType { return StreamType.CRITICAL; } /** * Identify weaknesses in the proposal with term reference tracking * * @param problem - Problem to analyze * @param keyTerms - Extracted key terms for problem-specific weaknesses * @returns Array of weakness insights with referenced terms tracked */ private identifyWeaknesses(problem: Problem, keyTerms: KeyTerms): Insight[] { const weaknesses: Insight[] = []; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the proposal"; const domainTerm = keyTerms.domainTerms[0] || ""; // Check for vague or unclear problem description if (problem.description.length < 30) { const content = `${primaryTerm} description is too vague - lacks specific ${domainTerm || "details"} needed for proper evaluation`; weaknesses.push({ content, source: StreamType.CRITICAL, confidence: 0.85, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for missing context if (!problem.context || problem.context.length < 50) { const content = `Insufficient context for ${primaryTerm} - missing critical ${domainTerm || "information"} for thorough analysis`; weaknesses.push({ content, source: StreamType.CRITICAL, confidence: 0.9, importance: 0.85, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for overly optimistic claims (e.g., "50%" in context) const hasOptimisticClaims = /\d+%/.test(problem.context); if (hasOptimisticClaims) { const content = `Quantitative projections for ${primaryTerm} may be overly optimistic - need validation with ${domainTerm || "supporting"} data`; weaknesses.push({ content, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for implementation challenges if ( problem.complexity === "complex" || (problem.constraints && problem.constraints.length > 2) ) { const content = `${primaryTerm} implementation complexity is high - ${domainTerm || "resource"} requirements not fully addressed`; weaknesses.push({ content, source: StreamType.CRITICAL, confidence: 0.8, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for potential failure points if (problem.urgency === "high") { const content = `High urgency for ${primaryTerm} increases risk of rushed ${domainTerm || "decisions"} and inadequate testing`; weaknesses.push({ content, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } return weaknesses; } /** * Challenge assumptions in the proposal with term reference tracking * * @param problem - Problem to analyze * @param keyTerms - Extracted key terms for problem-specific assumption challenges * @returns Array of assumption-challenging insights with referenced terms tracked */ private challengeAssumptions(problem: Problem, keyTerms: KeyTerms): Insight[] { const assumptions: Insight[] = []; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the proposal"; const domainTerm = keyTerms.domainTerms[0] || ""; // Challenge optimistic projections if (problem.context.includes("%") || problem.context.toLowerCase().includes("increase")) { const content = `Assumption that ${primaryTerm} will achieve stated ${domainTerm || "metrics"} is unproven - what if actual impact is much lower?`; assumptions.push({ content, source: StreamType.CRITICAL, confidence: 0.8, importance: 0.85, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Challenge user behavior assumptions if ( problem.context.toLowerCase().includes("user") || problem.context.toLowerCase().includes("engagement") ) { const content = `${primaryTerm} assumes users will respond positively - but user behavior is unpredictable`; assumptions.push({ content, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Challenge timeline assumptions if ( problem.constraints && problem.constraints.some( (c) => c.toLowerCase().includes("month") || c.toLowerCase().includes("timeline") ) ) { const content = `Timeline assumptions for ${primaryTerm} may be unrealistic - hidden ${domainTerm || "complexities"} often emerge`; assumptions.push({ content, source: StreamType.CRITICAL, confidence: 0.7, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Challenge resource assumptions if ( problem.constraints && problem.constraints.some((c) => c.includes("$") || c.toLowerCase().includes("budget")) ) { const content = `Budget assumptions for ${primaryTerm} may not account for unforeseen ${domainTerm || "costs"} and scope creep`; assumptions.push({ content, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.7, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // General assumption challenge with specific terms const generalContent = `Implicit assumption that current ${primaryTerm} approach is optimal - alternative ${domainTerm || "strategies"} may be more effective`; assumptions.push({ content: generalContent, source: StreamType.CRITICAL, confidence: 0.65, importance: 0.7, referencedTerms: this.keyTermExtractor.findReferencedTerms(generalContent, keyTerms), }); return assumptions; } /** * Assess risks in the proposal with term reference tracking * * @param problem - Problem to analyze * @param keyTerms - Extracted key terms for problem-specific risk assessment * @returns Array of risk insights with referenced terms tracked */ private assessRisks(problem: Problem, keyTerms: KeyTerms): Insight[] { const risks: Insight[] = []; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the proposal"; const domainTerm = keyTerms.domainTerms[0] || ""; // Risk of unintended consequences const unintendedContent = `Risk of unintended consequences: ${primaryTerm} changes may have negative ${domainTerm || "side effects"} not considered`; risks.push({ content: unintendedContent, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.85, referencedTerms: this.keyTermExtractor.findReferencedTerms(unintendedContent, keyTerms), }); // Risk of user alienation if (problem.constraints && problem.constraints.some((c) => c.toLowerCase().includes("user"))) { const userContent = `Significant risk of alienating existing users with ${primaryTerm} - mitigation strategy unclear`; risks.push({ content: userContent, source: StreamType.CRITICAL, confidence: 0.8, importance: 0.9, referencedTerms: this.keyTermExtractor.findReferencedTerms(userContent, keyTerms), }); } // Risk of failure if (problem.complexity === "complex" || problem.urgency === "high") { const failureContent = `High risk of ${primaryTerm} failure due to complexity and time pressure - could damage ${domainTerm || "reputation"}`; risks.push({ content: failureContent, source: StreamType.CRITICAL, confidence: 0.7, importance: 0.85, referencedTerms: this.keyTermExtractor.findReferencedTerms(failureContent, keyTerms), }); } // Risk of resource overrun if (problem.constraints && problem.constraints.length > 0) { const resourceContent = `Risk of ${primaryTerm} exceeding constraints (${problem.constraints[0]}) - initial estimates often prove insufficient`; risks.push({ content: resourceContent, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(resourceContent, keyTerms), }); } // Risk of competitive response if ( problem.context.toLowerCase().includes("engagement") || problem.context.toLowerCase().includes("market") ) { const competitiveContent = `Risk that competitors may respond to ${primaryTerm} with superior ${domainTerm || "solutions"}`; risks.push({ content: competitiveContent, source: StreamType.CRITICAL, confidence: 0.65, importance: 0.7, referencedTerms: this.keyTermExtractor.findReferencedTerms(competitiveContent, keyTerms), }); } return risks; } /** * Detect logical flaws with term reference tracking * * @param problem - Problem to analyze * @param keyTerms - Extracted key terms for problem-specific flaw detection * @returns Array of flaw insights with referenced terms tracked */ private detectFlaws(problem: Problem, keyTerms: KeyTerms): Insight[] { const flaws: Insight[] = []; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the argument"; // Check for circular reasoning const words = problem.context.toLowerCase().split(/\s+/); const wordSet = new Set(words); const hasRepetition = words.length > 0 && wordSet.size < words.length * 0.7; // Check for "because" circular patterns (A because A) const becausePattern = /(\w+).*because.*\1/i; const hasCircularBecause = becausePattern.test(problem.context); if (hasRepetition || hasCircularBecause) { const content = `Circular reasoning in ${primaryTerm} - argument repeats itself without adding substance`; flaws.push({ content, source: StreamType.CRITICAL, confidence: 0.7, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for false dichotomy if ( problem.context.toLowerCase().includes("either") || problem.context.toLowerCase().includes("must") ) { const content = `False dichotomy in ${primaryTerm}: framing suggests only two options when other alternatives may exist`; flaws.push({ content, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for correlation vs causation if ( problem.context.toLowerCase().includes("so ") || problem.context.toLowerCase().includes("therefore") ) { const content = `Potential correlation/causation confusion in ${primaryTerm} - relationship doesn't imply causation`; flaws.push({ content, source: StreamType.CRITICAL, confidence: 0.7, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // Check for overgeneralization if ( problem.context.toLowerCase().includes("all ") || problem.context.toLowerCase().includes("always") || problem.context.toLowerCase().includes("never") ) { const content = `Overgeneralization in ${primaryTerm} - sweeping claims rarely hold in all cases`; flaws.push({ content, source: StreamType.CRITICAL, confidence: 0.8, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } // If no specific flaws detected, add general flaw concern if (flaws.length === 0) { const content = `Logical structure of ${primaryTerm} requires scrutiny - potential flaws in reasoning chain`; flaws.push({ content, source: StreamType.CRITICAL, confidence: 0.65, importance: 0.7, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }); } return flaws; } /** * Generate counter-arguments with term reference tracking * * @param problem - Problem to analyze * @param keyTerms - Extracted key terms for problem-specific counter-arguments * @returns Array of counter-argument insights with referenced terms tracked */ private generateCounterArguments(problem: Problem, keyTerms: KeyTerms): Insight[] { const counterArguments: Insight[] = []; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the solution"; const domainTerm = keyTerms.domainTerms[0] || ""; // Devil's advocate: argue against the proposal const devilContent = `Devil's advocate: what if ${primaryTerm} makes ${domainTerm || "things"} worse rather than better?`; counterArguments.push({ content: devilContent, source: StreamType.CRITICAL, confidence: 0.65, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(devilContent, keyTerms), }); // Alternative perspective const altContent = `Alternative perspective on ${primaryTerm}: consider addressing root causes rather than symptoms`; counterArguments.push({ content: altContent, source: StreamType.CRITICAL, confidence: 0.7, importance: 0.75, referencedTerms: this.keyTermExtractor.findReferencedTerms(altContent, keyTerms), }); // Challenge from different angle if (problem.goals && problem.goals.length > 0) { const goalContent = `Counter-argument: the goal of "${problem.goals[0]}" for ${primaryTerm} may not be the right objective`; counterArguments.push({ content: goalContent, source: StreamType.CRITICAL, confidence: 0.65, importance: 0.7, referencedTerms: this.keyTermExtractor.findReferencedTerms(goalContent, keyTerms), }); } // Constructive criticism const constructiveContent = `Constructive criticism: ${primaryTerm} has merit but needs refinement - suggest pilot testing ${domainTerm || "before full rollout"}`; counterArguments.push({ content: constructiveContent, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(constructiveContent, keyTerms), }); return counterArguments; } /** * Evaluate evidence quality with term reference tracking * * @param problem - Problem with context * @param keyTerms - Extracted key terms for problem-specific evidence evaluation * @returns Evidence assessment with referenced terms tracked */ private evaluateEvidence( problem: Problem, keyTerms: KeyTerms ): { reasoning: string; insight?: Insight; } { let reasoning = ""; let insight: Insight | undefined; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the proposal"; const domainTerm = keyTerms.domainTerms[0] || ""; // Check for quantitative data const hasNumbers = /\d+%|\d+\.\d+|\d+ (users|customers|percent)/.test(problem.context); if (hasNumbers) { reasoning = `Evidence for ${primaryTerm} includes quantitative claims but lacks supporting ${domainTerm || "data"} sources`; const content = `Quantitative claims about ${primaryTerm} lack supporting evidence - ${domainTerm || "data"} sources must be verified`; insight = { content, source: StreamType.CRITICAL, confidence: 0.8, importance: 0.85, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }; } else { reasoning = `Evidence for ${primaryTerm} is primarily qualitative - need quantitative ${domainTerm || "data"} to support claims`; const content = `Lack of quantitative evidence for ${primaryTerm} weakens the case - need measurable ${domainTerm || "data"}`; insight = { content, source: StreamType.CRITICAL, confidence: 0.75, importance: 0.8, referencedTerms: this.keyTermExtractor.findReferencedTerms(content, keyTerms), }; } // Check for bias in evidence if ( problem.context.toLowerCase().includes("will") || problem.context.toLowerCase().includes("shows") ) { reasoning += `. Potential confirmation bias in ${primaryTerm} evidence selection`; if (insight) { insight.content += `. Evidence for ${primaryTerm} may be cherry-picked`; // Update referenced terms after content modification insight.referencedTerms = this.keyTermExtractor.findReferencedTerms( insight.content, keyTerms ); } } return { reasoning, insight }; } /** * Generate conclusion from critical analysis with validated term references * * @param problem - Original problem * @param insights - Generated insights * @param keyTerms - Extracted key terms for problem-specific conclusion * @returns Conclusion statement with guaranteed key term reference */ private generateConclusion(problem: Problem, insights: Insight[], keyTerms: KeyTerms): string { const parts: string[] = []; const primaryTerm = keyTerms.primarySubject || keyTerms.terms[0] || "the proposal"; // Count high-importance concerns const criticalConcerns = insights.filter((i) => i.importance > 0.8).length; if (criticalConcerns > 2) { parts.push( `${criticalConcerns} critical concerns about ${primaryTerm} require immediate attention` ); } else if (insights.length > 3) { parts.push(`several significant issues with ${primaryTerm} require careful consideration`); } else { parts.push(`some concerns about ${primaryTerm} identified but it has potential`); } // Address the proposal if (problem.goals && problem.goals.length > 0) { parts.push(`before proceeding with ${problem.goals[0].toLowerCase()}`); } // Recommend action with specific terms if (criticalConcerns > 2) { parts.push(`- recommend substantial revision of ${primaryTerm} or alternative approach`); } else { parts.push( `- recommend addressing ${primaryTerm} concerns through pilot testing and iterative refinement` ); } // Validate and ensure conclusion contains at least one key term const conclusion = parts.join(" "); return this.keyTermExtractor.ensureTermReference(conclusion, keyTerms); } /** * Calculate confidence score * * @param problem - Problem being analyzed * @param insights - Generated insights * @returns Confidence score (0-1) */ private calculateConfidence(problem: Problem, insights: Insight[]): number { let confidence = 0.6; // Critical stream is moderately confident in identifying issues // Boost confidence if we found many issues if (insights.length >= 5) { confidence += 0.1; } // Boost confidence if we have high-importance concerns const criticalConcerns = insights.filter((i) => i.importance > 0.8).length; if (criticalConcerns >= 2) { confidence += 0.1; } // Reduce confidence if context is limited if (!problem.context || problem.context.length < 50) { confidence -= 0.2; } // Reduce confidence if problem is simple (less to criticize) if (problem.complexity === "simple") { confidence -= 0.1; } return Math.max(0.1, Math.min(1.0, confidence)); } } /** * Critical Reasoning Stream * * Implements a reasoning stream that performs skeptical, evaluative thinking * with progress tracking, timeout management, and cancellation support. */ export class CriticalReasoningStream implements ReasoningStream { public readonly id: string; public readonly type: StreamType; public readonly processor: StreamProcessor; public readonly timeout: number; private progress: number = 0; private cancelled: boolean = false; private processing: boolean = false; /** * Create critical reasoning stream * * @param timeout - Timeout in milliseconds (default: 10000ms) */ constructor(timeout: number = 10000) { this.id = `critical-stream-${Date.now()}`; this.type = StreamType.CRITICAL; this.processor = new CriticalStreamProcessor(); this.timeout = timeout; } /** * Process a problem using critical reasoning * * @param problem - Problem to analyze * @returns Promise resolving to stream result */ async process(problem: Problem): Promise<StreamResult> { if (this.processing) { throw new Error("Stream is already processing"); } this.processing = true; this.progress = 0; this.cancelled = false; const startTime = Date.now(); try { // Create timeout promise const timeoutPromise = new Promise<StreamResult>((resolve) => { setTimeout(() => { if (!this.cancelled) { resolve({ streamId: this.id, streamType: this.type, conclusion: "Critical analysis incomplete due to timeout", reasoning: ["Processing exceeded time limit"], insights: [], confidence: 0.3, processingTime: this.timeout, status: StreamStatus.TIMEOUT, }); } }, this.timeout); }); // Create processing promise with progress tracking const processingPromise = this.processWithProgress(problem); // Race between processing and timeout let result = await Promise.race([processingPromise, timeoutPromise]); // Check if cancelled after processing completes (handles late cancellation) if (this.cancelled && result.status !== StreamStatus.CANCELLED) { result = { streamId: this.id, streamType: this.type, conclusion: "", reasoning: result.reasoning || [], insights: result.insights || [], confidence: 0, processingTime: Date.now() - startTime, status: StreamStatus.CANCELLED, }; } if (result.status === StreamStatus.COMPLETED) { this.progress = 1.0; } return result; } finally { this.processing = false; } } /** * Process with progress tracking * * @param problem - Problem to analyze * @returns Promise resolving to stream result */ private async processWithProgress(problem: Problem): Promise<StreamResult> { // Simulate progress updates during processing const progressInterval = setInterval(() => { if (!this.cancelled && this.progress < 0.9) { this.progress += 0.1; } }, this.timeout / 10); try { const result = await this.processor.process(problem); clearInterval(progressInterval); // Check if cancelled after processing if (this.cancelled) { return { streamId: this.id, streamType: this.type, conclusion: "", reasoning: result.reasoning || [], insights: result.insights || [], confidence: 0, processingTime: result.processingTime, status: StreamStatus.CANCELLED, }; } this.progress = 1.0; return result; } catch (error) { clearInterval(progressInterval); throw error; } } /** * Get current processing progress * * @returns Progress value between 0 and 1 */ getProgress(): number { return this.progress; } /** * Cancel stream processing */ cancel(): void { this.cancelled = true; this.progress = 0; } }

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/keyurgolani/ThoughtMcp'

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