@@ -16,6 +16,10 @@ vi.mock("./helpers.js", () => ({
1616 resolveCommandOptionArgs : resolveCommandOptionArgsMock ,
1717} ) ) ;
1818
19+ function setRawArgs ( command : Command , rawArgs : string [ ] ) : void {
20+ ( command as Command & { rawArgs : string [ ] } ) . rawArgs = rawArgs ;
21+ }
22+
1923describe ( "reparseProgramFromActionArgs" , ( ) => {
2024 beforeEach ( ( ) => {
2125 vi . clearAllMocks ( ) ;
@@ -26,12 +30,11 @@ describe("reparseProgramFromActionArgs", () => {
2630
2731 it ( "uses action command name + args as fallback argv" , async ( ) => {
2832 const program = new Command ( ) . name ( "openclaw" ) ;
33+ setRawArgs ( program , [ "node" , "openclaw" , "status" , "--json" ] ) ;
2934 const parseAsync = vi . spyOn ( program , "parseAsync" ) . mockResolvedValue ( program ) ;
3035 const actionCommand = {
3136 name : ( ) => "status" ,
32- parent : {
33- rawArgs : [ "node" , "openclaw" , "status" , "--json" ] ,
34- } ,
37+ parent : program ,
3538 } as unknown as Command ;
3639 resolveActionArgsMock . mockReturnValue ( [ "--json" ] ) ;
3740
@@ -47,18 +50,19 @@ describe("reparseProgramFromActionArgs", () => {
4750
4851 it ( "falls back to action args without command name when action has no name" , async ( ) => {
4952 const program = new Command ( ) . name ( "openclaw" ) ;
53+ setRawArgs ( program , [ "node" , "openclaw" ] ) ;
5054 const parseAsync = vi . spyOn ( program , "parseAsync" ) . mockResolvedValue ( program ) ;
5155 const actionCommand = {
5256 name : ( ) => "" ,
53- parent : { } ,
57+ parent : program ,
5458 } as unknown as Command ;
5559 resolveActionArgsMock . mockReturnValue ( [ "--json" ] ) ;
5660
5761 await reparseProgramFromActionArgs ( program , [ actionCommand ] ) ;
5862
5963 expect ( buildParseArgvMock ) . toHaveBeenCalledWith ( {
6064 programName : "openclaw" ,
61- rawArgs : undefined ,
65+ rawArgs : [ "node" , "openclaw" ] ,
6266 fallbackArgv : [ "--json" ] ,
6367 } ) ;
6468 expect ( parseAsync ) . toHaveBeenCalledWith ( [ "node" , "openclaw" , "status" ] ) ;
@@ -85,6 +89,27 @@ describe("reparseProgramFromActionArgs", () => {
8589 expect ( parseAsync ) . toHaveBeenCalledWith ( [ "node" , "openclaw" , "status" ] ) ;
8690 } ) ;
8791
92+ it ( "uses root raw args and reparses the root for nested lazy commands" , async ( ) => {
93+ const root = new Command ( ) . name ( "openclaw" ) ;
94+ setRawArgs ( root , [ "node" , "openclaw" , "workspaces" , "audit" , "export" , "--since" , "1" ] ) ;
95+ const workspaces = root . command ( "workspaces" ) ;
96+ const audit = workspaces . command ( "audit" ) ;
97+ const exportCommand = audit . command ( "export" ) ;
98+ const parseAsync = vi . spyOn ( root , "parseAsync" ) . mockResolvedValue ( root ) ;
99+ const auditParseAsync = vi . spyOn ( audit , "parseAsync" ) ;
100+ resolveActionArgsMock . mockReturnValue ( [ "--since" , "1" ] ) ;
101+
102+ await reparseProgramFromActionArgs ( audit , [ exportCommand ] ) ;
103+
104+ expect ( buildParseArgvMock ) . toHaveBeenCalledWith ( {
105+ programName : "openclaw" ,
106+ rawArgs : [ "node" , "openclaw" , "workspaces" , "audit" , "export" , "--since" , "1" ] ,
107+ fallbackArgv : [ "export" , "--since" , "1" ] ,
108+ } ) ;
109+ expect ( parseAsync ) . toHaveBeenCalledWith ( [ "node" , "openclaw" , "status" ] ) ;
110+ expect ( auditParseAsync ) . not . toHaveBeenCalled ( ) ;
111+ } ) ;
112+
88113 it ( "uses program root when action command is missing" , async ( ) => {
89114 const program = new Command ( ) . name ( "openclaw" ) ;
90115 const parseAsync = vi . spyOn ( program , "parseAsync" ) . mockResolvedValue ( program ) ;
0 commit comments