@@ -42,6 +42,7 @@ import type { DeepDebuggerInputs } from '../../operations/DeepDebugger';
4242import { generatePortToken } from 'worker/utils/cryptoUtils' ;
4343import { getPreviewDomain , getProtocolForHost } from 'worker/utils/urls' ;
4444import { isDev } from 'worker/utils/envs' ;
45+ import { InMemoryAnalyzer } from '../../../services/static-analysis' ;
4546
4647// Screenshot capture configuration
4748const SCREENSHOT_CONFIG = {
@@ -589,13 +590,25 @@ export abstract class BaseCodingBehavior<TState extends BaseProjectState>
589590 */
590591 async runStaticAnalysisCode ( files ?: string [ ] ) : Promise < StaticAnalysisResponse > {
591592 try {
592- // Check if we have cached static analysis
593- if ( this . staticAnalysisCache ) {
593+ // Only use cache for full (unscoped) analysis
594+ if ( ! files && this . staticAnalysisCache ) {
594595 return this . staticAnalysisCache ;
595596 }
596-
597- const analysisResponse = await this . deploymentManager . runStaticAnalysis ( files ) ;
598- this . staticAnalysisCache = analysisResponse ;
597+
598+ // Use in-memory analysis for browser-rendered projects (no sandbox)
599+ const templateDetails = this . getTemplateDetails ( ) ;
600+ let analysisResponse : StaticAnalysisResponse ;
601+
602+ if ( templateDetails ?. renderMode === 'browser' ) {
603+ analysisResponse = await this . runInMemoryAnalysis ( files ) ;
604+ } else {
605+ analysisResponse = await this . deploymentManager . runStaticAnalysis ( files ) ;
606+ }
607+
608+ // Only cache full (unscoped) analysis results
609+ if ( ! files ) {
610+ this . staticAnalysisCache = analysisResponse ;
611+ }
599612
600613 const { lint, typecheck } = analysisResponse ;
601614 this . broadcast ( WebSocketMessageResponses . STATIC_ANALYSIS_RESULTS , {
@@ -610,6 +623,26 @@ export abstract class BaseCodingBehavior<TState extends BaseProjectState>
610623 }
611624 }
612625
626+ /**
627+ * Run in-memory static analysis for browser-rendered projects
628+ * Performs static analysis directly in the worker without using the sandbox
629+ */
630+ private async runInMemoryAnalysis ( filePaths ?: string [ ] ) : Promise < StaticAnalysisResponse > {
631+ const allFiles = this . fileManager . getAllFiles ( ) ;
632+ const filePathSet = filePaths ? new Set ( filePaths ) : null ;
633+ const filesToAnalyze = filePathSet
634+ ? allFiles . filter ( ( f ) => filePathSet . has ( f . filePath ) )
635+ : allFiles ;
636+
637+ const fileInputs = filesToAnalyze . map ( ( f ) => ( {
638+ path : f . filePath ,
639+ content : f . fileContents ,
640+ } ) ) ;
641+
642+ const analyzer = new InMemoryAnalyzer ( ) ;
643+ return analyzer . analyze ( fileInputs ) ;
644+ }
645+
613646 /**
614647 * Apply deterministic code fixes for common TypeScript errors
615648 */
@@ -685,8 +718,14 @@ export abstract class BaseCodingBehavior<TState extends BaseProjectState>
685718 }
686719
687720 async fetchAllIssues ( resetIssues : boolean = false ) : Promise < AllIssues > {
688- if ( ! this . state . sandboxInstanceId ) {
689- return { runtimeErrors : [ ] , staticAnalysis : { success : false , lint : { issues : [ ] , } , typecheck : { issues : [ ] , } } } ;
721+ const templateDetails = this . getTemplateDetails ( ) ;
722+ const isBrowserOnly = templateDetails ?. renderMode === 'browser' ;
723+
724+ // For browser-rendered projects (no sandbox), only run static analysis
725+ if ( isBrowserOnly ) {
726+ const staticAnalysis = await this . runStaticAnalysisCode ( ) ;
727+ this . logger . info ( "Fetched issues (browser-rendered):" , JSON . stringify ( { runtimeErrors : [ ] , staticAnalysis } ) ) ;
728+ return { runtimeErrors : [ ] , staticAnalysis } ;
690729 }
691730 const [ runtimeErrors , staticAnalysis ] = await Promise . all ( [
692731 this . fetchRuntimeErrors ( resetIssues ) ,
0 commit comments