@@ -108,7 +108,9 @@ async function main() {
108108 const [ command , ...rawParams ] = commandArgs ;
109109
110110 // Parse parameters into object format
111- const params : Record < string , string | boolean | number > = { } ;
111+ // ParsedValue supports primitives, arrays (for repeated flags), and objects (for complex params)
112+ type ParsedValue = string | boolean | number | null | ParsedValue [ ] | { [ key : string ] : ParsedValue } ;
113+ const params : Record < string , ParsedValue > = { } ;
112114 let i = 0 ;
113115 while ( i < rawParams . length ) {
114116 const arg = rawParams [ i ] ;
@@ -209,17 +211,18 @@ async function main() {
209211 i ++ ;
210212 } else {
211213 // Handle positional arguments - add them to a general array
212- if ( ! params . _positional ) {
214+ if ( ! params . _positional || ! Array . isArray ( params . _positional ) ) {
213215 params . _positional = [ ] ;
214216 }
215- params . _positional . push ( arg ) ;
217+ ( params . _positional as ParsedValue [ ] ) . push ( arg ) ;
216218 i ++ ;
217219 }
218220 }
219221
220222 // Handle positional arguments for single-parameter commands
221223 // This allows `./jtag help screenshot` instead of `./jtag help commandName=screenshot`
222- if ( params . _positional && params . _positional . length > 0 ) {
224+ const positional = params . _positional ;
225+ if ( Array . isArray ( positional ) && positional . length > 0 ) {
223226 // Map of commands to their primary parameter name
224227 const singleParamCommands : Record < string , string > = {
225228 'help' : 'commandName' ,
@@ -236,20 +239,27 @@ async function main() {
236239 const primaryParam = singleParamCommands [ command ] ;
237240 if ( primaryParam && ! params [ primaryParam ] ) {
238241 // Use first positional arg as the primary parameter
239- params [ primaryParam ] = params . _positional [ 0 ] ;
242+ params [ primaryParam ] = positional [ 0 ] as ParsedValue ;
240243 // Remove from positional array
241- params . _positional = params . _positional . slice ( 1 ) ;
242- if ( params . _positional . length === 0 ) {
244+ params . _positional = positional . slice ( 1 ) ;
245+ if ( ( params . _positional as ParsedValue [ ] ) . length === 0 ) {
243246 delete params . _positional ;
244247 }
245248 }
246249 }
247250
248251 // INTELLIGENT ENTRY POINT: Adapts behavior based on detected agent type
252+ type OutputFormat = 'json' | 'human' | 'auto' | 'compact' | 'ai-friendly' ;
253+ const formatValue = params . format as string | undefined ;
254+ const validFormats : OutputFormat [ ] = [ 'json' , 'human' , 'auto' , 'compact' , 'ai-friendly' ] ;
255+ const format : OutputFormat = ( formatValue && validFormats . includes ( formatValue as OutputFormat ) )
256+ ? formatValue as OutputFormat
257+ : 'auto' ;
258+
249259 const entryPoint = new EntryPointAdapter ( {
250- verbose : params . verbose ,
251- quiet : params . quiet ,
252- format : params . format || 'auto' ,
260+ verbose : params . verbose as boolean | undefined ,
261+ quiet : params . quiet as boolean | undefined ,
262+ format,
253263 showAgentInfo : ! params . quiet
254264 } ) ;
255265
@@ -290,7 +300,7 @@ async function main() {
290300 }
291301
292302 const clientOptions : JTAGClientConnectOptions = {
293- targetEnvironment : 'server' ,
303+ targetEnvironment : 'server' ,
294304 transportType : 'websocket' ,
295305 serverUrl : `ws://localhost:${ instanceConfig . ports . websocket_server } ` ,
296306 enableFallback : false ,
@@ -300,8 +310,7 @@ async function main() {
300310 cli : {
301311 command,
302312 args : commandArgs ,
303- timestamp : new Date ( ) . toISOString ( ) ,
304- sessionPersistence : sessionId ? 'reused' : 'new'
313+ timestamp : new Date ( ) . toISOString ( )
305314 }
306315 }
307316 } ;
@@ -326,7 +335,7 @@ async function main() {
326335
327336 const isConnectionRefused = connectionError . message . includes ( 'ECONNREFUSED' ) ||
328337 connectionError . message . includes ( 'connect' ) ||
329- ( err && typeof err === 'object' && 'code' in err && err . code === 'ECONNREFUSED' ) ;
338+ ( err && typeof err === 'object' && 'code' in err && ( err as { code ?: string } ) . code === 'ECONNREFUSED' ) ;
330339
331340 if ( behavior . logLevel === 'verbose' ) {
332341 console . log ( '=' . repeat ( 60 ) ) ;
@@ -337,7 +346,7 @@ async function main() {
337346 console . error ( '✅ IMMEDIATE ACTION: Run "npm start" and wait 60 seconds' ) ;
338347 } else {
339348 console . error ( '🔍 Connection details:' , connectionError . message ) ;
340- console . error ( '🔍 Error code:' , connectionError . code || 'unknown' ) ;
349+ console . error ( '🔍 Error code:' , ( connectionError as Error & { code ?: string } ) . code || 'unknown' ) ;
341350 }
342351 } else {
343352 // Clean JSON error for connection failures - send to stderr
@@ -373,10 +382,12 @@ async function main() {
373382 // AI commands need longer timeout due to queue + generation time
374383 // Genome commands can take longer for training operations
375384 // Interface commands (screenshot) may need to wait for html2canvas rendering
385+ // Inference commands (inference/generate) need time for local model generation
376386 const isAICommand = command . startsWith ( 'ai/' ) ;
377387 const isGenomeCommand = command . startsWith ( 'genome/' ) ;
378388 const isInterfaceCommand = command . startsWith ( 'interface/' ) ;
379- const timeoutMs = isGenomeCommand ? 300000 : isAICommand ? 60000 : isInterfaceCommand ? 60000 : 10000 ; // 5min for genome, 60s for AI/interface, 10s for others
389+ const isInferenceCommand = command . startsWith ( 'inference/' ) ;
390+ const timeoutMs = isGenomeCommand ? 300000 : ( isAICommand || isInferenceCommand ) ? 60000 : isInterfaceCommand ? 60000 : 10000 ; // 5min for genome, 60s for AI/inference/interface, 10s for others
380391 const timeoutSeconds = timeoutMs / 1000 ;
381392
382393 const commandTimeout = new Promise ( ( _ , reject ) =>
@@ -407,18 +418,22 @@ async function main() {
407418
408419 // Special parameter transformation for screenshot command
409420 if ( command === 'screenshot' ) {
421+ // Ensure options is an object
422+ if ( ! params . options || typeof params . options !== 'object' || Array . isArray ( params . options ) ) {
423+ params . options = { } ;
424+ }
425+ const options = params . options as { [ key : string ] : ParsedValue } ;
426+
410427 // Convert comma-separated presets to array
411428 if ( params . presets && typeof params . presets === 'string' ) {
412- params . options = params . options || { } ;
413- params . options . presets = params . presets . split ( ',' ) . map ( ( p : string ) => p . trim ( ) ) ;
429+ options . presets = params . presets . split ( ',' ) . map ( ( p : string ) => p . trim ( ) ) ;
414430 delete params . presets ;
415431 }
416-
432+
417433 // Convert comma-separated resolutions to array (if provided as JSON string)
418434 if ( params . resolutions && typeof params . resolutions === 'string' ) {
419435 try {
420- params . options = params . options || { } ;
421- params . options . resolutions = JSON . parse ( params . resolutions ) ;
436+ options . resolutions = JSON . parse ( params . resolutions ) ;
422437 delete params . resolutions ;
423438 } catch ( e ) {
424439 console . warn ( `⚠️ Invalid resolutions JSON: ${ params . resolutions } ` ) ;
0 commit comments