@@ -12,6 +12,12 @@ const writeConfigFileMock = vi.hoisted(() => vi.fn().mockResolvedValue(undefined
1212const replaceConfigFileMock = vi . hoisted ( ( ) =>
1313 vi . fn ( async ( params : { nextConfig : unknown } ) => await writeConfigFileMock ( params . nextConfig ) ) ,
1414) ;
15+ const commitConfigWithPendingPluginInstallsMock = vi . hoisted ( ( ) =>
16+ vi . fn ( async ( params : { nextConfig : Record < string , unknown > } ) => {
17+ await writeConfigFileMock ( params . nextConfig ) ;
18+ return { config : params . nextConfig } ;
19+ } ) ,
20+ ) ;
1521const transformConfigWithPendingPluginInstallsMock = vi . hoisted ( ( ) =>
1622 vi . fn (
1723 async ( params : {
@@ -56,6 +62,16 @@ const transformConfigWithPendingPluginInstallsMock = vi.hoisted(() =>
5662const wizardMocks = vi . hoisted ( ( ) => ( {
5763 createClackPrompter : vi . fn ( ) ,
5864} ) ) ;
65+ const authChoiceMocks = vi . hoisted ( ( ) => ( {
66+ applyAuthChoice : vi . fn ( ) ,
67+ warnIfModelConfigLooksOff : vi . fn ( async ( ) => { } ) ,
68+ } ) ) ;
69+ const onboardChannelsMocks = vi . hoisted ( ( ) => ( {
70+ setupChannels : vi . fn ( async ( config : Record < string , unknown > ) => config ) ,
71+ } ) ) ;
72+ const onboardHelpersMocks = vi . hoisted ( ( ) => ( {
73+ ensureWorkspaceAndSessions : vi . fn ( async ( ) => { } ) ,
74+ } ) ) ;
5975
6076vi . mock ( "../config/config.js" , async ( ) => ( {
6177 ...( await vi . importActual < typeof import ( "../config/config.js" ) > ( "../config/config.js" ) ) ,
@@ -68,13 +84,27 @@ vi.mock("../cli/plugins-install-record-commit.js", async () => ({
6884 ...( await vi . importActual < typeof import ( "../cli/plugins-install-record-commit.js" ) > (
6985 "../cli/plugins-install-record-commit.js" ,
7086 ) ) ,
87+ commitConfigWithPendingPluginInstalls : commitConfigWithPendingPluginInstallsMock ,
7188 transformConfigWithPendingPluginInstalls : transformConfigWithPendingPluginInstallsMock ,
7289} ) ) ;
7390
7491vi . mock ( "../wizard/clack-prompter.js" , ( ) => ( {
7592 createClackPrompter : wizardMocks . createClackPrompter ,
7693} ) ) ;
7794
95+ vi . mock ( "./auth-choice.js" , ( ) => ( {
96+ applyAuthChoice : authChoiceMocks . applyAuthChoice ,
97+ warnIfModelConfigLooksOff : authChoiceMocks . warnIfModelConfigLooksOff ,
98+ } ) ) ;
99+
100+ vi . mock ( "./onboard-channels.js" , ( ) => ( {
101+ setupChannels : onboardChannelsMocks . setupChannels ,
102+ } ) ) ;
103+
104+ vi . mock ( "./onboard-helpers.js" , ( ) => ( {
105+ ensureWorkspaceAndSessions : onboardHelpersMocks . ensureWorkspaceAndSessions ,
106+ } ) ) ;
107+
78108import { WizardCancelledError } from "../wizard/prompts.js" ;
79109import { agentsAddCommand , testing } from "./agents.commands.add.js" ;
80110
@@ -85,8 +115,13 @@ describe("agents add command", () => {
85115 readConfigFileSnapshotMock . mockClear ( ) ;
86116 writeConfigFileMock . mockClear ( ) ;
87117 replaceConfigFileMock . mockClear ( ) ;
118+ commitConfigWithPendingPluginInstallsMock . mockClear ( ) ;
88119 transformConfigWithPendingPluginInstallsMock . mockClear ( ) ;
89120 wizardMocks . createClackPrompter . mockClear ( ) ;
121+ authChoiceMocks . applyAuthChoice . mockClear ( ) ;
122+ authChoiceMocks . warnIfModelConfigLooksOff . mockClear ( ) ;
123+ onboardChannelsMocks . setupChannels . mockClear ( ) ;
124+ onboardHelpersMocks . ensureWorkspaceAndSessions . mockClear ( ) ;
90125 runtime . log . mockClear ( ) ;
91126 runtime . error . mockClear ( ) ;
92127 runtime . exit . mockClear ( ) ;
@@ -136,6 +171,33 @@ describe("agents add command", () => {
136171 expect ( writeConfigFileMock ) . not . toHaveBeenCalled ( ) ;
137172 } ) ;
138173
174+ it ( "skips catalog validation when checking the interactive wizard model config" , async ( ) => {
175+ readConfigFileSnapshotMock . mockResolvedValue ( {
176+ ...baseConfigSnapshot ,
177+ config : { agents : { list : [ ] } } ,
178+ sourceConfig : { agents : { list : [ ] } } ,
179+ } ) ;
180+ wizardMocks . createClackPrompter . mockReturnValue ( {
181+ intro : vi . fn ( ) ,
182+ text : vi . fn ( ) . mockResolvedValueOnce ( "Jon" ) . mockResolvedValueOnce ( "/tmp/openclaw-jon" ) ,
183+ confirm : vi . fn ( ) . mockResolvedValue ( false ) ,
184+ note : vi . fn ( ) ,
185+ outro : vi . fn ( ) ,
186+ } ) ;
187+
188+ await agentsAddCommand ( { } , runtime ) ;
189+
190+ expect ( authChoiceMocks . warnIfModelConfigLooksOff ) . toHaveBeenCalledOnce ( ) ;
191+ expect ( authChoiceMocks . warnIfModelConfigLooksOff ) . toHaveBeenCalledWith (
192+ expect . objectContaining ( { agents : expect . any ( Object ) } ) ,
193+ expect . any ( Object ) ,
194+ expect . objectContaining ( {
195+ agentId : "jon" ,
196+ validateCatalog : false ,
197+ } ) ,
198+ ) ;
199+ } ) ;
200+
139201 it ( "copies only portable auth profiles when seeding a new agent store" , async ( ) => {
140202 const root = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "openclaw-agents-add-auth-copy-" ) ) ;
141203 try {
0 commit comments