@@ -88,10 +88,15 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
8888 res . end ( JSON . stringify ( { success : true , indexes : [ ] , totalSize : 0 , totalSizeFormatted : '0 B' } ) ) ;
8989 return true ;
9090 }
91- // Get config for index directory path
92- const configResult = await executeCodexLens ( [ 'config' , '--json' ] ) ;
91+
92+ // Execute all CLI commands in parallel
93+ const [ configResult , projectsResult , statusResult ] = await Promise . all ( [
94+ executeCodexLens ( [ 'config' , '--json' ] ) ,
95+ executeCodexLens ( [ 'projects' , 'list' , '--json' ] ) ,
96+ executeCodexLens ( [ 'status' , '--json' ] )
97+ ] ) ;
98+
9399 let indexDir = '' ;
94-
95100 if ( configResult . success ) {
96101 try {
97102 const config = extractJSON ( configResult . output ) ;
@@ -104,8 +109,6 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
104109 }
105110 }
106111
107- // Get project list using 'projects list' command
108- const projectsResult = await executeCodexLens ( [ 'projects' , 'list' , '--json' ] ) ;
109112 let indexes : any [ ] = [ ] ;
110113 let totalSize = 0 ;
111114 let vectorIndexCount = 0 ;
@@ -115,7 +118,8 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
115118 try {
116119 const projectsData = extractJSON ( projectsResult . output ) ;
117120 if ( projectsData . success && Array . isArray ( projectsData . result ) ) {
118- const { statSync, existsSync } = await import ( 'fs' ) ;
121+ const { stat, readdir } = await import ( 'fs/promises' ) ;
122+ const { existsSync } = await import ( 'fs' ) ;
119123 const { basename, join } = await import ( 'path' ) ;
120124
121125 for ( const project of projectsData . result ) {
@@ -136,15 +140,14 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
136140 // Try to get actual index size from index_root
137141 if ( project . index_root && existsSync ( project . index_root ) ) {
138142 try {
139- const { readdirSync } = await import ( 'fs' ) ;
140- const files = readdirSync ( project . index_root ) ;
143+ const files = await readdir ( project . index_root ) ;
141144 for ( const file of files ) {
142145 try {
143146 const filePath = join ( project . index_root , file ) ;
144- const stat = statSync ( filePath ) ;
145- projectSize += stat . size ;
146- if ( ! lastModified || stat . mtime > lastModified ) {
147- lastModified = stat . mtime ;
147+ const fileStat = await stat ( filePath ) ;
148+ projectSize += fileStat . size ;
149+ if ( ! lastModified || fileStat . mtime > lastModified ) {
150+ lastModified = fileStat . mtime ;
148151 }
149152 // Check for vector/embedding files
150153 if ( file . includes ( 'vector' ) || file . includes ( 'embedding' ) ||
@@ -194,8 +197,7 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
194197 }
195198 }
196199
197- // Also get summary stats from status command
198- const statusResult = await executeCodexLens ( [ 'status' , '--json' ] ) ;
200+ // Parse summary stats from status command (already fetched in parallel)
199201 let statusSummary : any = { } ;
200202
201203 if ( statusResult . success ) {
@@ -250,6 +252,71 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
250252 return true ;
251253 }
252254
255+ // API: CodexLens Dashboard Init - Aggregated endpoint for page initialization
256+ if ( pathname === '/api/codexlens/dashboard-init' ) {
257+ try {
258+ const venvStatus = await checkVenvStatus ( ) ;
259+
260+ if ( ! venvStatus . ready ) {
261+ res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
262+ res . end ( JSON . stringify ( {
263+ installed : false ,
264+ status : venvStatus ,
265+ config : { index_dir : '~/.codexlens/indexes' , index_count : 0 } ,
266+ semantic : { available : false }
267+ } ) ) ;
268+ return true ;
269+ }
270+
271+ // Parallel fetch all initialization data
272+ const [ configResult , statusResult , semanticStatus ] = await Promise . all ( [
273+ executeCodexLens ( [ 'config' , '--json' ] ) ,
274+ executeCodexLens ( [ 'status' , '--json' ] ) ,
275+ checkSemanticStatus ( )
276+ ] ) ;
277+
278+ // Parse config
279+ let config = { index_dir : '~/.codexlens/indexes' , index_count : 0 } ;
280+ if ( configResult . success ) {
281+ try {
282+ const configData = extractJSON ( configResult . output ) ;
283+ if ( configData . success && configData . result ) {
284+ config . index_dir = configData . result . index_dir || configData . result . index_root || config . index_dir ;
285+ }
286+ } catch ( e ) {
287+ console . error ( '[CodexLens] Failed to parse config for dashboard init:' , e . message ) ;
288+ }
289+ }
290+
291+ // Parse status
292+ let statusData : any = { } ;
293+ if ( statusResult . success ) {
294+ try {
295+ const status = extractJSON ( statusResult . output ) ;
296+ if ( status . success && status . result ) {
297+ config . index_count = status . result . projects_count || 0 ;
298+ statusData = status . result ;
299+ }
300+ } catch ( e ) {
301+ console . error ( '[CodexLens] Failed to parse status for dashboard init:' , e . message ) ;
302+ }
303+ }
304+
305+ res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
306+ res . end ( JSON . stringify ( {
307+ installed : true ,
308+ status : venvStatus ,
309+ config,
310+ semantic : semanticStatus ,
311+ statusData
312+ } ) ) ;
313+ } catch ( err ) {
314+ res . writeHead ( 500 , { 'Content-Type' : 'application/json' } ) ;
315+ res . end ( JSON . stringify ( { success : false , error : err . message } ) ) ;
316+ }
317+ return true ;
318+ }
319+
253320 // API: CodexLens Bootstrap (Install)
254321 if ( pathname === '/api/codexlens/bootstrap' && req . method === 'POST' ) {
255322 handlePostRequest ( req , res , async ( ) => {
0 commit comments