mirror of
https://github.com/instructkr/claude-code.git
synced 2026-06-09 05:36:45 +00:00
feat: wizard entry points -- /setup command, claw setup subcommand, and RuntimeProviderConfig
The setup wizard was merged in PR #3017 but was orphaned -- it was not declared as a module in main.rs, making it unreachable. Additionally, the setup_wizard.rs imports RuntimeProviderConfig which did not exist on upstream/main. This commit makes the wizard accessible and adds the necessary RuntimeProviderConfig type. Changes: - Add RuntimeProviderConfig struct to runtime/src/config.rs with kind(), api_key(), base_url(), model() accessors. - Add parse_optional_provider_config() to parse the provider object from merged settings JSON. - Add provider() method to RuntimeConfig and RuntimeFeatureConfig. - Export RuntimeProviderConfig, save_user_provider_settings, clear_user_provider_settings, and default_config_home from runtime crate public API (runtime/src/lib.rs). - Add mod setup_wizard to rusty-claude-cli/src/main.rs. - Add claw setup CLI subcommand. - Add /setup slash command. - Add Setup variant to SlashCommand enum. - Add Setup to LocalHelpTopic enum. - Add setup to diagnostic subcommand matching. - Add subagentModel to TOP_LEVEL_FIELDS in config_validate.rs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -162,10 +162,46 @@ pub struct RuntimeFeatureConfig {
|
||||
trusted_roots: Vec<String>,
|
||||
api_timeout: ApiTimeoutConfig,
|
||||
rules_import: RulesImportConfig,
|
||||
provider: RuntimeProviderConfig,
|
||||
}
|
||||
|
||||
/// Controls which external AI coding framework rules are imported into the system prompt.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
/// Stored provider configuration from the setup wizard.
|
||||
///
|
||||
/// Represents the `provider` section in `~/.claw/settings.json`, used as a
|
||||
/// fallback when environment variables are absent (3-tier resolution:
|
||||
/// env var > .env file > stored config).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct RuntimeProviderConfig {
|
||||
kind: Option<String>,
|
||||
api_key: Option<String>,
|
||||
base_url: Option<String>,
|
||||
model: Option<String>,
|
||||
}
|
||||
|
||||
impl RuntimeProviderConfig {
|
||||
#[must_use]
|
||||
pub fn kind(&self) -> Option<&str> {
|
||||
self.kind.as_deref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn api_key(&self) -> Option<&str> {
|
||||
self.api_key.as_deref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn base_url(&self) -> Option<&str> {
|
||||
self.base_url.as_deref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn model(&self) -> Option<&str> {
|
||||
self.model.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RulesImportConfig {
|
||||
/// Import from all supported frameworks when files are detected.
|
||||
#[default]
|
||||
@@ -764,6 +800,7 @@ fn build_runtime_config(
|
||||
trusted_roots: parse_optional_trusted_roots(&merged_value)?,
|
||||
api_timeout: parse_optional_api_timeout_config(&merged_value)?,
|
||||
rules_import: parse_optional_rules_import(&merged_value)?,
|
||||
provider: parse_optional_provider_config(&merged_value)?,
|
||||
};
|
||||
|
||||
Ok(RuntimeConfig {
|
||||
@@ -891,6 +928,13 @@ impl RuntimeConfig {
|
||||
}
|
||||
|
||||
impl RuntimeFeatureConfig {
|
||||
/// Parsed provider configuration (kind, apiKey, baseUrl, model) from
|
||||
/// merged settings.
|
||||
#[must_use]
|
||||
pub fn provider(&self) -> &RuntimeProviderConfig {
|
||||
&self.provider
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_hooks(mut self, hooks: RuntimeHookConfig) -> Self {
|
||||
self.hooks = hooks;
|
||||
@@ -2104,6 +2148,25 @@ fn parse_optional_rules_import(root: &JsonValue) -> Result<RulesImportConfig, Co
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_optional_provider_config(root: &JsonValue) -> Result<RuntimeProviderConfig, ConfigError> {
|
||||
let Some(provider_value) = root.as_object().and_then(|object| object.get("provider")) else {
|
||||
return Ok(RuntimeProviderConfig::default());
|
||||
};
|
||||
let Some(object) = provider_value.as_object() else {
|
||||
return Ok(RuntimeProviderConfig::default());
|
||||
};
|
||||
let kind = optional_string(object, "kind", "provider")?.map(str::to_string);
|
||||
let api_key = optional_string(object, "apiKey", "provider")?.map(str::to_string);
|
||||
let base_url = optional_string(object, "baseUrl", "provider")?.map(str::to_string);
|
||||
let model = optional_string(object, "model", "provider")?.map(str::to_string);
|
||||
Ok(RuntimeProviderConfig {
|
||||
kind,
|
||||
api_key,
|
||||
base_url,
|
||||
model,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_filesystem_mode_label(value: &str) -> Result<FilesystemIsolationMode, ConfigError> {
|
||||
match value {
|
||||
"off" => Ok(FilesystemIsolationMode::Off),
|
||||
|
||||
Reference in New Issue
Block a user