@@ -26,6 +26,23 @@ vi.mock("@/lib/utils/shell.js", () => ({
2626 validateTerminalShellPath : vi . fn ( ( ) => Promise . resolve ( { valid : false , reason : "test" } ) ) ,
2727} ) )
2828
29+ // Helper to create a complete FlagOptions object with defaults
30+ function createFlagOptions ( overrides : Partial < FlagOptions > = { } ) : FlagOptions {
31+ return {
32+ continue : false ,
33+ print : false ,
34+ stdinPromptStream : false ,
35+ signalOnlyExit : false ,
36+ debug : false ,
37+ requireApproval : false ,
38+ autonomous : false ,
39+ exitOnError : false ,
40+ ephemeral : false ,
41+ oneshot : false ,
42+ ...overrides ,
43+ }
44+ }
45+
2946vi . mock ( "@/agent/index.js" , ( ) => ( {
3047 // eslint-disable-next-line @typescript-eslint/no-explicit-any
3148 ExtensionHost : vi . fn ( function ( this : any ) {
@@ -50,7 +67,7 @@ describe("run command validation", () => {
5067
5168 beforeEach ( ( ) => {
5269 tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "cli-test-" ) )
53- vi . spyOn ( process , "exit" ) . mockImplementation ( ( code ?: string | number ) => {
70+ vi . spyOn ( process , "exit" ) . mockImplementation ( ( code ?: string | number | null ) => {
5471 throw new Error ( `process.exit: ${ code } ` )
5572 } )
5673 consoleErrorSpy = vi . spyOn ( console , "error" ) . mockImplementation ( ( ) => { } )
@@ -65,21 +82,21 @@ describe("run command validation", () => {
6582
6683 describe ( "session ID validation" , ( ) => {
6784 it ( "should reject empty --session-id" , async ( ) => {
68- const flags : FlagOptions = { sessionId : "" }
85+ const flags = createFlagOptions ( { sessionId : "" } )
6986
7087 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
7188 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: --session-id requires a non-empty session id" )
7289 } )
7390
7491 it ( "should reject invalid --session-id format" , async ( ) => {
75- const flags : FlagOptions = { sessionId : "not-a-uuid" }
92+ const flags = createFlagOptions ( { sessionId : "not-a-uuid" } )
7693
7794 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
7895 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: --session-id must be a valid UUID session id" )
7996 } )
8097
8198 it ( "should reject empty --create-with-session-id" , async ( ) => {
82- const flags : FlagOptions = { createWithSessionId : "" }
99+ const flags = createFlagOptions ( { createWithSessionId : "" } )
83100
84101 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
85102 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -88,7 +105,7 @@ describe("run command validation", () => {
88105 } )
89106
90107 it ( "should reject invalid --create-with-session-id format" , async ( ) => {
91- const flags : FlagOptions = { createWithSessionId : "not-a-uuid" }
108+ const flags = createFlagOptions ( { createWithSessionId : "not-a-uuid" } )
92109
93110 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
94111 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -98,10 +115,10 @@ describe("run command validation", () => {
98115
99116 it ( "should reject --create-with-session-id with --session-id" , async ( ) => {
100117 const validUuid = "123e4567-e89b-12d3-a456-426614174000"
101- const flags : FlagOptions = {
118+ const flags = createFlagOptions ( {
102119 createWithSessionId : validUuid ,
103120 sessionId : validUuid ,
104- }
121+ } )
105122
106123 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
107124 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -111,18 +128,18 @@ describe("run command validation", () => {
111128
112129 it ( "should reject --session-id with --continue" , async ( ) => {
113130 const validUuid = "123e4567-e89b-12d3-a456-426614174000"
114- const flags : FlagOptions = {
131+ const flags = createFlagOptions ( {
115132 sessionId : validUuid ,
116133 continue : true ,
117- }
134+ } )
118135
119136 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
120137 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: cannot use --session-id with --continue" )
121138 } )
122139
123140 it ( "should reject prompt with resume flags" , async ( ) => {
124141 const validUuid = "123e4567-e89b-12d3-a456-426614174000"
125- const flags : FlagOptions = { sessionId : validUuid }
142+ const flags = createFlagOptions ( { sessionId : validUuid } )
126143
127144 await expect ( run ( "test prompt" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
128145 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -133,11 +150,11 @@ describe("run command validation", () => {
133150
134151 describe ( "provider validation" , ( ) => {
135152 it ( "should reject invalid provider" , async ( ) => {
136- const flags : FlagOptions = {
153+ const flags = createFlagOptions ( {
137154 // eslint-disable-next-line @typescript-eslint/no-explicit-any
138155 provider : "invalid-provider" as any ,
139156 print : true ,
140- }
157+ } )
141158
142159 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
143160 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -147,7 +164,7 @@ describe("run command validation", () => {
147164
148165 it ( "should reject missing API key" , async ( ) => {
149166 delete process . env . OPENROUTER_API_KEY
150- const flags : FlagOptions = { print : true }
167+ const flags = createFlagOptions ( { print : true } )
151168
152169 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
153170 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -159,64 +176,64 @@ describe("run command validation", () => {
159176 describe ( "autonomous mode validation" , ( ) => {
160177 it ( "should reject autonomous without workspace in non-cwd scenario" , async ( ) => {
161178 const nonExistentPath = path . join ( tempDir , "nonexistent" )
162- const flags : FlagOptions = {
179+ const flags = createFlagOptions ( {
163180 autonomous : true ,
164181 workspace : nonExistentPath ,
165182 timeout : 60 ,
166183 outputFormat : "json" ,
167184 print : true ,
168- }
185+ } )
169186
170187 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 78" )
171188 } )
172189
173190 it ( "should reject autonomous with non-directory workspace" , async ( ) => {
174191 const filePath = path . join ( tempDir , "file.txt" )
175192 fs . writeFileSync ( filePath , "content" )
176- const flags : FlagOptions = {
193+ const flags = createFlagOptions ( {
177194 autonomous : true ,
178195 workspace : filePath ,
179196 timeout : 60 ,
180197 outputFormat : "json" ,
181198 print : true ,
182- }
199+ } )
183200
184201 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 78" )
185202 } )
186203
187204 it ( "should enforce orchestrator mode in autonomous" , async ( ) => {
188- const flags : FlagOptions = {
205+ const flags = createFlagOptions ( {
189206 autonomous : true ,
190207 // eslint-disable-next-line @typescript-eslint/no-explicit-any
191208 mode : "code" as any ,
192209 workspace : tempDir ,
193210 timeout : 60 ,
194211 outputFormat : "json" ,
195212 print : true ,
196- }
213+ } )
197214
198215 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 78" )
199216 } )
200217
201218 it ( "should reject autonomous without timeout" , async ( ) => {
202- const flags : FlagOptions = {
219+ const flags = createFlagOptions ( {
203220 autonomous : true ,
204221 workspace : tempDir ,
205222 outputFormat : "json" ,
206223 print : true ,
207- }
224+ } )
208225
209226 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 78" )
210227 } )
211228 } )
212229
213230 describe ( "output format validation" , ( ) => {
214231 it ( "should reject invalid output format" , async ( ) => {
215- const flags : FlagOptions = {
232+ const flags = createFlagOptions ( {
216233 // eslint-disable-next-line @typescript-eslint/no-explicit-any
217234 outputFormat : "invalid" as any ,
218235 print : true ,
219- }
236+ } )
220237
221238 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
222239 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( expect . stringContaining ( "[CLI] Error: Invalid output format" ) )
@@ -227,9 +244,9 @@ describe("run command validation", () => {
227244 Object . defineProperty ( process . stdin , "isTTY" , { value : true , configurable : true } )
228245 Object . defineProperty ( process . stdout , "isTTY" , { value : true , configurable : true } )
229246
230- const flags : FlagOptions = {
247+ const flags = createFlagOptions ( {
231248 outputFormat : "json" ,
232- }
249+ } )
233250
234251 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
235252 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: --output-format requires --print mode" )
@@ -238,20 +255,20 @@ describe("run command validation", () => {
238255
239256 describe ( "stdin stream validation" , ( ) => {
240257 it ( "should reject --stdin-prompt-stream without --print" , async ( ) => {
241- const flags : FlagOptions = {
258+ const flags = createFlagOptions ( {
242259 stdinPromptStream : true ,
243- }
260+ } )
244261
245262 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
246263 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: --stdin-prompt-stream requires --print mode" )
247264 } )
248265
249266 it ( "should reject --stdin-prompt-stream with wrong output format" , async ( ) => {
250- const flags : FlagOptions = {
267+ const flags = createFlagOptions ( {
251268 stdinPromptStream : true ,
252269 print : true ,
253270 outputFormat : "json" ,
254- }
271+ } )
255272
256273 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
257274 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -260,10 +277,10 @@ describe("run command validation", () => {
260277 } )
261278
262279 it ( "should reject --signal-only-exit without --stdin-prompt-stream" , async ( ) => {
263- const flags : FlagOptions = {
280+ const flags = createFlagOptions ( {
264281 signalOnlyExit : true ,
265282 print : true ,
266- }
283+ } )
267284
268285 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
269286 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -274,11 +291,11 @@ describe("run command validation", () => {
274291 it ( "should reject --stdin-prompt-stream with TTY stdin" , async ( ) => {
275292 Object . defineProperty ( process . stdin , "isTTY" , { value : true , configurable : true } )
276293
277- const flags : FlagOptions = {
294+ const flags = createFlagOptions ( {
278295 stdinPromptStream : true ,
279296 print : true ,
280297 outputFormat : "stream-json" ,
281- }
298+ } )
282299
283300 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
284301 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: --stdin-prompt-stream requires piped stdin" )
@@ -287,11 +304,11 @@ describe("run command validation", () => {
287304 it ( "should reject prompt with --stdin-prompt-stream" , async ( ) => {
288305 Object . defineProperty ( process . stdin , "isTTY" , { value : false , configurable : true } )
289306
290- const flags : FlagOptions = {
307+ const flags = createFlagOptions ( {
291308 stdinPromptStream : true ,
292309 print : true ,
293310 outputFormat : "stream-json" ,
294- }
311+ } )
295312
296313 await expect ( run ( "test prompt" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
297314 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -303,12 +320,12 @@ describe("run command validation", () => {
303320 Object . defineProperty ( process . stdin , "isTTY" , { value : false , configurable : true } )
304321
305322 const validUuid = "123e4567-e89b-12d3-a456-426614174000"
306- const flags : FlagOptions = {
323+ const flags = createFlagOptions ( {
307324 stdinPromptStream : true ,
308325 print : true ,
309326 outputFormat : "stream-json" ,
310327 createWithSessionId : validUuid ,
311- }
328+ } )
312329
313330 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
314331 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -319,10 +336,10 @@ describe("run command validation", () => {
319336
320337 describe ( "consecutive mistake limit validation" , ( ) => {
321338 it ( "should reject negative consecutive mistake limit" , async ( ) => {
322- const flags : FlagOptions = {
339+ const flags = createFlagOptions ( {
323340 consecutiveMistakeLimit : - 1 ,
324341 print : true ,
325- }
342+ } )
326343
327344 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
328345 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -331,10 +348,10 @@ describe("run command validation", () => {
331348 } )
332349
333350 it ( "should reject non-integer consecutive mistake limit" , async ( ) => {
334- const flags : FlagOptions = {
351+ const flags = createFlagOptions ( {
335352 consecutiveMistakeLimit : 1.5 ,
336353 print : true ,
337- }
354+ } )
338355
339356 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
340357 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -345,11 +362,11 @@ describe("run command validation", () => {
345362
346363 describe ( "reasoning effort validation" , ( ) => {
347364 it ( "should reject invalid reasoning effort" , async ( ) => {
348- const flags : FlagOptions = {
365+ const flags = createFlagOptions ( {
349366 // eslint-disable-next-line @typescript-eslint/no-explicit-any
350367 reasoningEffort : "invalid" as any ,
351368 print : true ,
352- }
369+ } )
353370
354371 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
355372 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -360,10 +377,10 @@ describe("run command validation", () => {
360377
361378 describe ( "workspace validation" , ( ) => {
362379 it ( "should reject non-existent workspace path" , async ( ) => {
363- const flags : FlagOptions = {
380+ const flags = createFlagOptions ( {
364381 workspace : "/nonexistent/path" ,
365382 print : true ,
366- }
383+ } )
367384
368385 await expect ( run ( "test" , flags ) ) . rejects . toThrow ( "process.exit: 1" )
369386 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -374,10 +391,10 @@ describe("run command validation", () => {
374391
375392 describe ( "prompt file validation" , ( ) => {
376393 it ( "should reject non-existent prompt file" , async ( ) => {
377- const flags : FlagOptions = {
394+ const flags = createFlagOptions ( {
378395 promptFile : path . join ( tempDir , "nonexistent.txt" ) ,
379396 print : true ,
380- }
397+ } )
381398
382399 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
383400 expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
@@ -388,9 +405,9 @@ describe("run command validation", () => {
388405
389406 describe ( "no prompt validation" , ( ) => {
390407 it ( "should reject missing prompt in print mode" , async ( ) => {
391- const flags : FlagOptions = {
408+ const flags = createFlagOptions ( {
392409 print : true ,
393- }
410+ } )
394411
395412 await expect ( run ( undefined , flags ) ) . rejects . toThrow ( "process.exit: 1" )
396413 expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[CLI] Error: no prompt provided" )
0 commit comments