@@ -5,11 +5,11 @@ import test from 'ava';
55
66// Helper function to parse prompt from args (mimics the logic in cli.tsx)
77function parsePrompt ( args : string [ ] ) : string | undefined {
8- const isRunCommand = args [ 0 ] === 'run' ;
9- if ( ! isRunCommand ) {
8+ const runCommandIndex = args . findIndex ( arg => arg === 'run' ) ;
9+ if ( runCommandIndex === - 1 ) {
1010 return undefined ;
1111 }
12- const afterRunArgs = args . slice ( 1 ) ;
12+ const afterRunArgs = args . slice ( runCommandIndex + 1 ) ;
1313 if ( afterRunArgs . length === 0 ) {
1414 return undefined ;
1515 }
@@ -92,7 +92,7 @@ test('CLI parsing: returns undefined when run command has no prompt', t => {
9292} ) ;
9393
9494test ( 'CLI parsing: handles mixed arguments with run command' , t => {
95- const args = [ 'run' , 'create' , 'a' , 'new' , 'file' ] ;
95+ const args = [ '--vscode' , ' run', 'create' , 'a' , 'new' , 'file' ] ;
9696 const prompt = parsePrompt ( args ) ;
9797
9898 t . is ( prompt , 'create a new file' ) ;
@@ -255,7 +255,7 @@ function resolvePlainMode(opts: {
255255 env : NodeJS . ProcessEnv ;
256256} ) : { plainMode : boolean ; vscodeMode : boolean } {
257257 const { args, stdoutIsTTY, env} = opts ;
258- const nonInteractiveMode = args [ 0 ] === 'run' ;
258+ const nonInteractiveMode = args . findIndex ( arg => arg === 'run' ) !== - 1 ;
259259 const vscodeMode = args . includes ( '--vscode' ) ;
260260 const plainRequested = args . includes ( '--plain' ) ;
261261 const noPlainRequested = args . includes ( '--no-plain' ) ;
@@ -281,9 +281,9 @@ test('plain mode: filters --plain and --no-plain from prompt args', t => {
281281 t . is ( parsePrompt ( [ 'run' , 'do' , '--no-plain' , 'a' , 'thing' ] ) , 'do a thing' ) ;
282282} ) ;
283283
284- test ( 'plain mode: explicit --plain enables it on a TTY without CI when run is args[0] ' , t => {
284+ test ( 'plain mode: explicit --plain enables it on a TTY without CI' , t => {
285285 const { plainMode} = resolvePlainMode ( {
286- args : [ 'run ' , 'hi ' , '--plain ' ] ,
286+ args : [ '--plain ' , 'run ' , 'hi ' ] ,
287287 stdoutIsTTY : true ,
288288 env : { } ,
289289 } ) ;
@@ -319,7 +319,7 @@ test('plain mode: auto-enables for run when GITHUB_ACTIONS is set', t => {
319319
320320test ( 'plain mode: --no-plain wins over auto-detection' , t => {
321321 const { plainMode} = resolvePlainMode ( {
322- args : [ 'run ' , 'hi ' , '--no-plain ' ] ,
322+ args : [ '--no-plain ' , 'run ' , 'hi ' ] ,
323323 stdoutIsTTY : false ,
324324 env : { CI : 'true' } ,
325325 } ) ;
@@ -337,7 +337,7 @@ test('plain mode: stays off for interactive sessions even on a non-TTY', t => {
337337
338338test ( 'plain mode: --vscode suppresses auto-detection' , t => {
339339 const { plainMode, vscodeMode} = resolvePlainMode ( {
340- args : [ 'run ' , 'hi ' , '--vscode ' ] ,
340+ args : [ '--vscode ' , 'run ' , 'hi ' ] ,
341341 stdoutIsTTY : false ,
342342 env : { CI : 'true' } ,
343343 } ) ;
@@ -454,7 +454,7 @@ function resolveResumeFlags(args: string[]): {
454454 mutuallyExclusiveError : boolean ;
455455 nonInteractiveError : boolean ;
456456} {
457- const nonInteractiveMode = args [ 0 ] === 'run' ;
457+ const nonInteractiveMode = args . findIndex ( arg => arg === 'run' ) !== - 1 ;
458458
459459 const continueRequested =
460460 args . includes ( '--continue' ) || args . includes ( '-c' ) ;
@@ -560,14 +560,14 @@ test('resume flags: neither flag alone is not a mutual-exclusion error', t => {
560560 t . false ( resolveResumeFlags ( [ ] ) . mutuallyExclusiveError ) ;
561561} ) ;
562562
563- test ( 'resume flags: --continue combined with `run` (not at args[0]) is not a non-interactive error' , t => {
563+ test ( 'resume flags: --continue combined with `run` is an error' , t => {
564564 const { nonInteractiveError} = resolveResumeFlags ( [ '--continue' , 'run' , 'hi' ] ) ;
565- t . false ( nonInteractiveError ) ;
565+ t . true ( nonInteractiveError ) ;
566566} ) ;
567567
568- test ( 'resume flags: --resume combined with `run` (not at args[0]) is not a non-interactive error' , t => {
568+ test ( 'resume flags: --resume combined with `run` is an error' , t => {
569569 const { nonInteractiveError} = resolveResumeFlags ( [ '--resume' , 'run' , 'hi' ] ) ;
570- t . false ( nonInteractiveError ) ;
570+ t . true ( nonInteractiveError ) ;
571571} ) ;
572572
573573test ( 'resume flags: --continue without `run` is not a non-interactive error' , t => {
@@ -623,9 +623,9 @@ function parseReviewArgs(args: string[]): ReviewParseResult {
623623 }
624624 }
625625 if ( reviewArgs . length === 0 ) {
626- return { prompt : undefined , error : true } ;
626+ return { prompt : '/review' , error : false } ;
627627 }
628- return { prompt : `/review ${ reviewArgs . join ( ' ' ) } ` , error : false } ;
628+ return { prompt : `/review ${ reviewArgs [ 0 ] } ` , error : false } ;
629629}
630630
631631test ( 'review CLI: parses review with branch name' , t => {
@@ -640,10 +640,10 @@ test('review CLI: parses review with PR number', t => {
640640 t . false ( result . error ) ;
641641} ) ;
642642
643- test ( 'review CLI: errors when no target provided ' , t => {
643+ test ( 'review CLI: no args produces /review ' , t => {
644644 const result = parseReviewArgs ( [ 'review' ] ) ;
645- t . is ( result . prompt , undefined ) ;
646- t . true ( result . error ) ;
645+ t . is ( result . prompt , '/review' ) ;
646+ t . false ( result . error ) ;
647647} ) ;
648648
649649test ( 'review CLI: returns undefined when not a review command' , t => {
@@ -746,3 +746,28 @@ test('review CLI: handles multiple mixed flags', t => {
746746 ] ) ;
747747 t . is ( result . prompt , '/review feature' ) ;
748748} ) ;
749+
750+ // Run command with flags before 'run' (the blocker fix)
751+ test ( 'CLI parsing: handles flags before run command' , t => {
752+ const args = [ '--plain' , 'run' , 'say' , 'hi' ] ;
753+ const prompt = parsePrompt ( args ) ;
754+ t . is ( prompt , 'say hi' ) ;
755+ } ) ;
756+
757+ test ( 'CLI parsing: handles --provider before run command' , t => {
758+ const args = [ '--provider' , 'ollama' , 'run' , 'analyze' , 'code' ] ;
759+ const prompt = parsePrompt ( args ) ;
760+ t . is ( prompt , 'analyze code' ) ;
761+ } ) ;
762+
763+ test ( 'CLI parsing: handles --mode before run command' , t => {
764+ const args = [ '--mode' , 'plan' , 'run' , 'audit' , 'module' ] ;
765+ const prompt = parsePrompt ( args ) ;
766+ t . is ( prompt , 'audit module' ) ;
767+ } ) ;
768+
769+ // Review should only use first arg, not join all
770+ test ( 'review CLI: only uses first positional arg' , t => {
771+ const result = parseReviewArgs ( [ 'review' , 'feature' , 'extra' , 'args' ] ) ;
772+ t . is ( result . prompt , '/review feature' ) ;
773+ } ) ;
0 commit comments