@@ -4,10 +4,53 @@ import path from "node:path";
44import { beforeEach , describe , expect , it , vi } from "vitest" ;
55import { withEnvAsync } from "../test-utils/env.js" ;
66import "./test-helpers/fast-core-tools.js" ;
7+ import { createGatewayTool } from "./tools/gateway-tool.js" ;
8+ import { callGatewayTool } from "./tools/gateway.js" ;
79
8- function createGatewayToolModuleMocks ( ) {
9- return {
10- callGatewayTool : vi . fn ( async ( method : string ) => {
10+ const { callGatewayToolMock, readGatewayCallOptionsMock } = vi . hoisted ( ( ) => ( {
11+ callGatewayToolMock : vi . fn ( ) ,
12+ readGatewayCallOptionsMock : vi . fn ( ( ) => ( { } ) ) ,
13+ } ) ) ;
14+
15+ vi . mock ( "./tools/gateway.js" , ( ) => ( {
16+ callGatewayTool : callGatewayToolMock ,
17+ readGatewayCallOptions : readGatewayCallOptionsMock ,
18+ } ) ) ;
19+
20+ function requireGatewayTool ( agentSessionKey ?: string ) {
21+ return createGatewayTool ( {
22+ ...( agentSessionKey ? { agentSessionKey } : { } ) ,
23+ config : { commands : { restart : true } } ,
24+ } ) ;
25+ }
26+
27+ function expectConfigMutationCall ( params : {
28+ callGatewayTool : {
29+ mock : {
30+ calls : Array < readonly unknown [ ] > ;
31+ } ;
32+ } ;
33+ action : "config.apply" | "config.patch" ;
34+ raw : string ;
35+ sessionKey : string ;
36+ } ) {
37+ expect ( params . callGatewayTool ) . toHaveBeenCalledWith ( "config.get" , expect . any ( Object ) , { } ) ;
38+ expect ( params . callGatewayTool ) . toHaveBeenCalledWith (
39+ params . action ,
40+ expect . any ( Object ) ,
41+ expect . objectContaining ( {
42+ raw : params . raw . trim ( ) ,
43+ baseHash : "hash-1" ,
44+ sessionKey : params . sessionKey ,
45+ } ) ,
46+ ) ;
47+ }
48+
49+ describe ( "gateway tool" , ( ) => {
50+ beforeEach ( ( ) => {
51+ callGatewayToolMock . mockClear ( ) ;
52+ readGatewayCallOptionsMock . mockClear ( ) ;
53+ callGatewayToolMock . mockImplementation ( async ( method : string ) => {
1154 if ( method === "config.get" ) {
1255 return {
1356 hash : "hash-1" ,
@@ -43,58 +86,7 @@ function createGatewayToolModuleMocks() {
4386 } ;
4487 }
4588 return { ok : true } ;
46- } ) ,
47- readGatewayCallOptions : vi . fn ( ( ) => ( { } ) ) ,
48- } ;
49- }
50-
51- vi . mock ( "./tools/gateway.js" , ( ) => createGatewayToolModuleMocks ( ) ) ;
52-
53- let createOpenClawTools : typeof import ( "./openclaw-tools.js" ) . createOpenClawTools ;
54-
55- async function loadFreshOpenClawToolsModuleForTest ( ) {
56- vi . resetModules ( ) ;
57- vi . doMock ( "./tools/gateway.js" , ( ) => createGatewayToolModuleMocks ( ) ) ;
58- ( { createOpenClawTools } = await import ( "./openclaw-tools.js" ) ) ;
59- }
60-
61- function requireGatewayTool ( agentSessionKey ?: string ) {
62- const tool = createOpenClawTools ( {
63- ...( agentSessionKey ? { agentSessionKey } : { } ) ,
64- config : { commands : { restart : true } } ,
65- } ) . find ( ( candidate ) => candidate . name === "gateway" ) ;
66- expect ( tool ) . toBeDefined ( ) ;
67- if ( ! tool ) {
68- throw new Error ( "missing gateway tool" ) ;
69- }
70- return tool ;
71- }
72-
73- function expectConfigMutationCall ( params : {
74- callGatewayTool : {
75- mock : {
76- calls : Array < readonly unknown [ ] > ;
77- } ;
78- } ;
79- action : "config.apply" | "config.patch" ;
80- raw : string ;
81- sessionKey : string ;
82- } ) {
83- expect ( params . callGatewayTool ) . toHaveBeenCalledWith ( "config.get" , expect . any ( Object ) , { } ) ;
84- expect ( params . callGatewayTool ) . toHaveBeenCalledWith (
85- params . action ,
86- expect . any ( Object ) ,
87- expect . objectContaining ( {
88- raw : params . raw . trim ( ) ,
89- baseHash : "hash-1" ,
90- sessionKey : params . sessionKey ,
91- } ) ,
92- ) ;
93- }
94-
95- describe ( "gateway tool" , ( ) => {
96- beforeEach ( async ( ) => {
97- await loadFreshOpenClawToolsModuleForTest ( ) ;
89+ } ) ;
9890 } ) ;
9991
10092 it ( "marks gateway as owner-only" , async ( ) => {
@@ -147,7 +139,6 @@ describe("gateway tool", () => {
147139 } ) ;
148140
149141 it ( "passes config.apply through gateway call" , async ( ) => {
150- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
151142 const sessionKey = "agent:main:whatsapp:dm:+15555550123" ;
152143 const tool = requireGatewayTool ( sessionKey ) ;
153144
@@ -167,7 +158,6 @@ describe("gateway tool", () => {
167158 } ) ;
168159
169160 it ( "passes config.patch through gateway call" , async ( ) => {
170- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
171161 const sessionKey = "agent:main:whatsapp:dm:+15555550123" ;
172162 const tool = requireGatewayTool ( sessionKey ) ;
173163
@@ -186,7 +176,6 @@ describe("gateway tool", () => {
186176 } ) ;
187177
188178 it ( "rejects config.patch when it changes exec approval settings" , async ( ) => {
189- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
190179 const tool = requireGatewayTool ( ) ;
191180
192181 await expect (
@@ -204,7 +193,6 @@ describe("gateway tool", () => {
204193 } ) ;
205194
206195 it ( "rejects config.patch when a legacy tools.bash alias changes exec security" , async ( ) => {
207- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
208196 vi . mocked ( callGatewayTool ) . mockImplementationOnce ( async ( method : string ) => {
209197 if ( method === "config.get" ) {
210198 return { hash : "hash-1" , config : { } } ;
@@ -230,7 +218,6 @@ describe("gateway tool", () => {
230218 } ) ;
231219
232220 it ( "rejects config.apply when it changes exec security settings" , async ( ) => {
233- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
234221 const tool = requireGatewayTool ( ) ;
235222
236223 await expect (
@@ -250,7 +237,6 @@ describe("gateway tool", () => {
250237 } ) ;
251238
252239 it ( "rejects config.apply when protected exec settings are omitted" , async ( ) => {
253- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
254240 const tool = requireGatewayTool ( ) ;
255241
256242 await expect (
@@ -270,7 +256,6 @@ describe("gateway tool", () => {
270256 } ) ;
271257
272258 it ( "passes update.run through gateway call" , async ( ) => {
273- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
274259 const sessionKey = "agent:main:whatsapp:dm:+15555550123" ;
275260 const tool = requireGatewayTool ( sessionKey ) ;
276261
@@ -299,7 +284,6 @@ describe("gateway tool", () => {
299284 } ) ;
300285
301286 it ( "returns a path-scoped schema lookup result" , async ( ) => {
302- const { callGatewayTool } = await import ( "./tools/gateway.js" ) ;
303287 const tool = requireGatewayTool ( ) ;
304288
305289 const result = await tool . execute ( "call5" , {
0 commit comments