@@ -162,6 +162,7 @@ pub struct RuntimeFeatureConfig {
162162 trusted_roots : Vec < String > ,
163163 api_timeout : ApiTimeoutConfig ,
164164 rules_import : RulesImportConfig ,
165+ provider : RuntimeProviderConfig ,
165166}
166167
167168/// Controls which external AI coding framework rules are imported into the system prompt.
@@ -189,6 +190,41 @@ impl RulesImportConfig {
189190 }
190191}
191192
193+ /// Stored provider configuration from the setup wizard.
194+ ///
195+ /// Represents the `provider` section in `~/.claw/settings.json`, used as a
196+ /// fallback when environment variables are absent (3-tier resolution:
197+ /// env var > .env file > stored config).
198+ #[ derive( Debug , Clone , PartialEq , Eq , Default ) ]
199+ pub struct RuntimeProviderConfig {
200+ kind : Option < String > ,
201+ api_key : Option < String > ,
202+ base_url : Option < String > ,
203+ model : Option < String > ,
204+ }
205+
206+ impl RuntimeProviderConfig {
207+ #[ must_use]
208+ pub fn kind ( & self ) -> Option < & str > {
209+ self . kind . as_deref ( )
210+ }
211+
212+ #[ must_use]
213+ pub fn api_key ( & self ) -> Option < & str > {
214+ self . api_key . as_deref ( )
215+ }
216+
217+ #[ must_use]
218+ pub fn base_url ( & self ) -> Option < & str > {
219+ self . base_url . as_deref ( )
220+ }
221+
222+ #[ must_use]
223+ pub fn model ( & self ) -> Option < & str > {
224+ self . model . as_deref ( )
225+ }
226+ }
227+
192228/// Ordered chain of fallback model identifiers used when the primary
193229/// provider returns a retryable failure (429/500/503/etc.). The chain is
194230/// strict: each entry is tried in order until one succeeds.
@@ -764,6 +800,7 @@ fn build_runtime_config(
764800 trusted_roots : parse_optional_trusted_roots ( & merged_value) ?,
765801 api_timeout : parse_optional_api_timeout_config ( & merged_value) ?,
766802 rules_import : parse_optional_rules_import ( & merged_value) ?,
803+ provider : parse_optional_provider_config ( & merged_value) ?,
767804 } ;
768805
769806 Ok ( RuntimeConfig {
@@ -878,6 +915,11 @@ impl RuntimeConfig {
878915 & self . feature_config . rules_import
879916 }
880917
918+ #[ must_use]
919+ pub fn provider ( & self ) -> & RuntimeProviderConfig {
920+ & self . feature_config . provider
921+ }
922+
881923 /// Merge config-level default trusted roots with per-call roots.
882924 ///
883925 /// Config roots are defaults and are kept first; per-call roots extend the
@@ -891,6 +933,13 @@ impl RuntimeConfig {
891933}
892934
893935impl RuntimeFeatureConfig {
936+ /// Parsed provider configuration (kind, apiKey, baseUrl, model) from
937+ /// merged settings.
938+ #[ must_use]
939+ pub fn provider ( & self ) -> & RuntimeProviderConfig {
940+ & self . provider
941+ }
942+
894943 #[ must_use]
895944 pub fn with_hooks ( mut self , hooks : RuntimeHookConfig ) -> Self {
896945 self . hooks = hooks;
@@ -2104,6 +2153,25 @@ fn parse_optional_rules_import(root: &JsonValue) -> Result<RulesImportConfig, Co
21042153 }
21052154}
21062155
2156+ fn parse_optional_provider_config ( root : & JsonValue ) -> Result < RuntimeProviderConfig , ConfigError > {
2157+ let Some ( provider_value) = root. as_object ( ) . and_then ( |object| object. get ( "provider" ) ) else {
2158+ return Ok ( RuntimeProviderConfig :: default ( ) ) ;
2159+ } ;
2160+ let Some ( object) = provider_value. as_object ( ) else {
2161+ return Ok ( RuntimeProviderConfig :: default ( ) ) ;
2162+ } ;
2163+ let kind = optional_string ( object, "kind" , "provider" ) ?. map ( str:: to_string) ;
2164+ let api_key = optional_string ( object, "apiKey" , "provider" ) ?. map ( str:: to_string) ;
2165+ let base_url = optional_string ( object, "baseUrl" , "provider" ) ?. map ( str:: to_string) ;
2166+ let model = optional_string ( object, "model" , "provider" ) ?. map ( str:: to_string) ;
2167+ Ok ( RuntimeProviderConfig {
2168+ kind,
2169+ api_key,
2170+ base_url,
2171+ model,
2172+ } )
2173+ }
2174+
21072175fn parse_filesystem_mode_label ( value : & str ) -> Result < FilesystemIsolationMode , ConfigError > {
21082176 match value {
21092177 "off" => Ok ( FilesystemIsolationMode :: Off ) ,
0 commit comments