@@ -97,6 +97,13 @@ const mocks = vi.hoisted(() => ({
9797 : { } ) ,
9898 } ) ,
9999 ) ,
100+ resolveCommandSecretRefsViaGateway : vi . fn ( async ( { config } : { config : unknown } ) => ( {
101+ resolvedConfig : config ,
102+ diagnostics : [ ] ,
103+ targetStatesByPath : { } ,
104+ hadUnresolvedTargets : false ,
105+ } ) ) ,
106+ getTtsCommandSecretTargetIds : vi . fn ( ( ) => new Set ( [ "messages.tts.providers.*.apiKey" ] ) ) ,
100107 createEmbeddingProvider : vi . fn ( async ( ) => ( {
101108 provider : {
102109 id : "openai" ,
@@ -188,6 +195,14 @@ vi.mock("../gateway/connection-details.js", () => ({
188195 } ) ) ,
189196} ) ) ;
190197
198+ vi . mock ( "./command-secret-gateway.js" , ( ) => ( {
199+ resolveCommandSecretRefsViaGateway : mocks . resolveCommandSecretRefsViaGateway ,
200+ } ) ) ;
201+
202+ vi . mock ( "./command-secret-targets.js" , ( ) => ( {
203+ getTtsCommandSecretTargetIds : mocks . getTtsCommandSecretTargetIds ,
204+ } ) ) ;
205+
191206vi . mock ( "../media-understanding/runtime.js" , ( ) => ( {
192207 describeImageFile :
193208 mocks . describeImageFile as typeof import ( "../media-understanding/runtime.js" ) . describeImageFile ,
@@ -311,6 +326,15 @@ describe("capability cli", () => {
311326 mocks . generateVideo . mockReset ( ) ;
312327 mocks . transcribeAudioFile . mockClear ( ) ;
313328 mocks . textToSpeech . mockClear ( ) ;
329+ mocks . resolveCommandSecretRefsViaGateway
330+ . mockReset ( )
331+ . mockImplementation ( async ( { config } : { config : unknown } ) => ( {
332+ resolvedConfig : config ,
333+ diagnostics : [ ] ,
334+ targetStatesByPath : { } ,
335+ hadUnresolvedTargets : false ,
336+ } ) ) ;
337+ mocks . getTtsCommandSecretTargetIds . mockClear ( ) ;
314338 mocks . setTtsProvider . mockClear ( ) ;
315339 mocks . resolveExplicitTtsOverrides . mockClear ( ) ;
316340 mocks . buildMediaUnderstandingRegistry . mockReset ( ) . mockReturnValue ( new Map ( ) ) ;
@@ -1057,6 +1081,58 @@ describe("capability cli", () => {
10571081 expect ( mocks . setTtsProvider ) . not . toHaveBeenCalled ( ) ;
10581082 } ) ;
10591083
1084+ it ( "resolves static TTS SecretRefs before local conversion" , async ( ) => {
1085+ const sourceConfig = {
1086+ messages : {
1087+ tts : {
1088+ providers : {
1089+ minimax : {
1090+ apiKey : { source : "exec" , provider : "mockexec" , id : "minimax/tts/apiKey" } ,
1091+ } ,
1092+ } ,
1093+ } ,
1094+ } ,
1095+ } ;
1096+ const resolvedConfig = {
1097+ messages : {
1098+ tts : {
1099+ providers : {
1100+ minimax : {
1101+ apiKey : "resolved-minimax-key" ,
1102+ } ,
1103+ } ,
1104+ } ,
1105+ } ,
1106+ } ;
1107+ mocks . loadConfig . mockReturnValueOnce ( sourceConfig ) ;
1108+ mocks . resolveCommandSecretRefsViaGateway . mockResolvedValueOnce ( {
1109+ resolvedConfig,
1110+ diagnostics : [ ] ,
1111+ targetStatesByPath : {
1112+ "messages.tts.providers.minimax.apiKey" : "resolved_local" ,
1113+ } ,
1114+ hadUnresolvedTargets : false ,
1115+ } ) ;
1116+
1117+ await runRegisteredCli ( {
1118+ register : registerCapabilityCli as ( program : Command ) => void ,
1119+ argv : [ "capability" , "tts" , "convert" , "--text" , "hello" , "--json" ] ,
1120+ } ) ;
1121+
1122+ expect ( mocks . resolveCommandSecretRefsViaGateway ) . toHaveBeenCalledWith ( {
1123+ config : sourceConfig ,
1124+ commandName : "infer tts convert" ,
1125+ targetIds : new Set ( [ "messages.tts.providers.*.apiKey" ] ) ,
1126+ mode : "enforce_resolved" ,
1127+ } ) ;
1128+ expect ( mocks . resolveExplicitTtsOverrides ) . toHaveBeenCalledWith (
1129+ expect . objectContaining ( { cfg : resolvedConfig } ) ,
1130+ ) ;
1131+ expect ( mocks . textToSpeech ) . toHaveBeenCalledWith (
1132+ expect . objectContaining ( { cfg : resolvedConfig } ) ,
1133+ ) ;
1134+ } ) ;
1135+
10601136 it ( "disables TTS fallback when explicit provider or voice/model selection is requested" , async ( ) => {
10611137 await runRegisteredCli ( {
10621138 register : registerCapabilityCli as ( program : Command ) => void ,
0 commit comments