- Fix timeframe parameter handling in enhanced-screenshot API route - Support both 'timeframe' (singular) and 'timeframes' (array) parameters - Add proper sessionId propagation for real-time progress tracking - Enhance MACD analysis prompt with detailed crossover definitions - Add progress tracker service with Server-Sent Events support - Fix Next.js build errors in chart components (module variable conflicts) - Change dev environment port from 9000:3000 to 9001:3000 - Improve AI analysis layout detection logic - Add comprehensive progress tracking through all service layers
116 lines
3.2 KiB
TypeScript
116 lines
3.2 KiB
TypeScript
import { EventEmitter } from 'events'
|
|
|
|
export type ProgressStatus = 'pending' | 'active' | 'completed' | 'error'
|
|
|
|
export interface ProgressStep {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
status: ProgressStatus
|
|
startTime?: number
|
|
endTime?: number
|
|
details?: string
|
|
}
|
|
|
|
export interface AnalysisProgress {
|
|
sessionId: string
|
|
currentStep: number
|
|
totalSteps: number
|
|
steps: ProgressStep[]
|
|
timeframeProgress?: {
|
|
current: number
|
|
total: number
|
|
currentTimeframe?: string
|
|
}
|
|
}
|
|
|
|
class ProgressTracker extends EventEmitter {
|
|
private sessions: Map<string, AnalysisProgress> = new Map()
|
|
|
|
createSession(sessionId: string, steps: ProgressStep[]): AnalysisProgress {
|
|
const progress: AnalysisProgress = {
|
|
sessionId,
|
|
currentStep: 0,
|
|
totalSteps: steps.length,
|
|
steps: steps.map(step => ({ ...step, status: 'pending' }))
|
|
}
|
|
|
|
this.sessions.set(sessionId, progress)
|
|
this.emit(`progress:${sessionId}`, progress)
|
|
return progress
|
|
}
|
|
|
|
updateStep(sessionId: string, stepId: string, status: ProgressStatus, details?: string): void {
|
|
console.log(`🔍 Progress Update: ${sessionId} -> ${stepId} -> ${status}${details ? ` (${details})` : ''}`)
|
|
const progress = this.sessions.get(sessionId)
|
|
if (!progress) {
|
|
console.log(`🔍 Warning: No session found for ${sessionId}`)
|
|
return
|
|
}
|
|
|
|
const updatedSteps = progress.steps.map(step => {
|
|
if (step.id === stepId) {
|
|
const updatedStep = {
|
|
...step,
|
|
status,
|
|
details: details || step.details
|
|
}
|
|
|
|
if (status === 'active' && !step.startTime) {
|
|
updatedStep.startTime = Date.now()
|
|
} else if ((status === 'completed' || status === 'error') && !step.endTime) {
|
|
updatedStep.endTime = Date.now()
|
|
}
|
|
|
|
return updatedStep
|
|
}
|
|
return step
|
|
})
|
|
|
|
const currentStepIndex = updatedSteps.findIndex(step => step.status === 'active')
|
|
|
|
const updatedProgress: AnalysisProgress = {
|
|
...progress,
|
|
steps: updatedSteps,
|
|
currentStep: currentStepIndex >= 0 ? currentStepIndex + 1 : progress.currentStep
|
|
}
|
|
|
|
this.sessions.set(sessionId, updatedProgress)
|
|
console.log(`🔍 Emitting progress event for ${sessionId}, currentStep: ${updatedProgress.currentStep}`)
|
|
this.emit(`progress:${sessionId}`, updatedProgress)
|
|
}
|
|
|
|
updateTimeframeProgress(sessionId: string, current: number, total: number, currentTimeframe?: string): void {
|
|
const progress = this.sessions.get(sessionId)
|
|
if (!progress) return
|
|
|
|
const updatedProgress: AnalysisProgress = {
|
|
...progress,
|
|
timeframeProgress: {
|
|
current,
|
|
total,
|
|
currentTimeframe
|
|
}
|
|
}
|
|
|
|
this.sessions.set(sessionId, updatedProgress)
|
|
this.emit(`progress:${sessionId}`, updatedProgress)
|
|
}
|
|
|
|
getProgress(sessionId: string): AnalysisProgress | undefined {
|
|
return this.sessions.get(sessionId)
|
|
}
|
|
|
|
deleteSession(sessionId: string): void {
|
|
this.sessions.delete(sessionId)
|
|
this.emit(`progress:${sessionId}:complete`)
|
|
}
|
|
|
|
// Get all active sessions (for debugging)
|
|
getActiveSessions(): string[] {
|
|
return Array.from(this.sessions.keys())
|
|
}
|
|
}
|
|
|
|
export const progressTracker = new ProgressTracker()
|