feat(cli): add ansi_basic theme fallback and offline provider shim for limited‑color terminals
- Detect terminal color support and automatically switch to the new `ansi_basic` theme when only 16‑color support is available. - Introduce `OfflineProvider` that supplies a placeholder model and friendly messages when no providers are reachable, keeping the TUI usable. - Add `CONFIG_SCHEMA_VERSION` (`1.1.0`) with schema migration logic and default handling in `Config`. - Update configuration saving to persist the schema version and ensure defaults. - Register the `ansi_basic` theme in `theme.rs`. - Extend `ChatApp` with `set_status_message` to display custom status lines. - Update documentation (architecture, Vim mode state machine) to reflect new behavior. - Add async‑trait and futures dependencies required for the offline provider implementation.
This commit is contained in:
@@ -10,9 +10,15 @@ use std::time::Duration;
|
||||
/// Default location for the OWLEN configuration file
|
||||
pub const DEFAULT_CONFIG_PATH: &str = "~/.config/owlen/config.toml";
|
||||
|
||||
/// Current schema version written to `config.toml`.
|
||||
pub const CONFIG_SCHEMA_VERSION: &str = "1.1.0";
|
||||
|
||||
/// Core configuration shared by all OWLEN clients
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
/// Schema version for on-disk configuration files
|
||||
#[serde(default = "Config::default_schema_version")]
|
||||
pub schema_version: String,
|
||||
/// General application settings
|
||||
pub general: GeneralSettings,
|
||||
/// MCP (Multi-Client-Provider) settings
|
||||
@@ -57,6 +63,7 @@ impl Default for Config {
|
||||
);
|
||||
|
||||
Self {
|
||||
schema_version: Self::default_schema_version(),
|
||||
general: GeneralSettings::default(),
|
||||
mcp: McpSettings::default(),
|
||||
providers,
|
||||
@@ -97,6 +104,10 @@ impl McpServerConfig {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn default_schema_version() -> String {
|
||||
CONFIG_SCHEMA_VERSION.to_string()
|
||||
}
|
||||
|
||||
/// Load configuration from disk, falling back to defaults when missing
|
||||
pub fn load(path: Option<&Path>) -> Result<Self> {
|
||||
let path = match path {
|
||||
@@ -106,10 +117,27 @@ impl Config {
|
||||
|
||||
if path.exists() {
|
||||
let content = fs::read_to_string(&path)?;
|
||||
let mut config: Config =
|
||||
let parsed: toml::Value =
|
||||
toml::from_str(&content).map_err(|e| crate::Error::Config(e.to_string()))?;
|
||||
let previous_version = parsed
|
||||
.get("schema_version")
|
||||
.and_then(|value| value.as_str())
|
||||
.unwrap_or("0.0.0")
|
||||
.to_string();
|
||||
if let Some(agent_table) = parsed.get("agent").and_then(|value| value.as_table()) {
|
||||
if agent_table.contains_key("max_tool_calls") {
|
||||
log::warn!(
|
||||
"Configuration option agent.max_tool_calls is deprecated and ignored. \
|
||||
The agent now uses agent.max_iterations."
|
||||
);
|
||||
}
|
||||
}
|
||||
let mut config: Config = parsed
|
||||
.try_into()
|
||||
.map_err(|e: toml::de::Error| crate::Error::Config(e.to_string()))?;
|
||||
config.ensure_defaults();
|
||||
config.mcp.apply_backward_compat();
|
||||
config.apply_schema_migrations(&previous_version);
|
||||
config.validate()?;
|
||||
Ok(config)
|
||||
} else {
|
||||
@@ -130,8 +158,10 @@ impl Config {
|
||||
fs::create_dir_all(dir)?;
|
||||
}
|
||||
|
||||
let mut snapshot = self.clone();
|
||||
snapshot.schema_version = Config::default_schema_version();
|
||||
let content =
|
||||
toml::to_string_pretty(self).map_err(|e| crate::Error::Config(e.to_string()))?;
|
||||
toml::to_string_pretty(&snapshot).map_err(|e| crate::Error::Config(e.to_string()))?;
|
||||
fs::write(path, content)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -171,6 +201,9 @@ impl Config {
|
||||
|
||||
ensure_provider_config(self, "ollama");
|
||||
ensure_provider_config(self, "ollama-cloud");
|
||||
if self.schema_version.is_empty() {
|
||||
self.schema_version = Self::default_schema_version();
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate configuration invariants and surface actionable error messages.
|
||||
@@ -181,6 +214,17 @@ impl Config {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply_schema_migrations(&mut self, previous_version: &str) {
|
||||
if previous_version != CONFIG_SCHEMA_VERSION {
|
||||
log::info!(
|
||||
"Upgrading configuration schema from '{}' to '{}'",
|
||||
previous_version,
|
||||
CONFIG_SCHEMA_VERSION
|
||||
);
|
||||
}
|
||||
self.schema_version = CONFIG_SCHEMA_VERSION.to_string();
|
||||
}
|
||||
|
||||
fn validate_default_provider(&self) -> Result<()> {
|
||||
if self.general.default_provider.trim().is_empty() {
|
||||
return Err(crate::Error::Config(
|
||||
|
||||
Reference in New Issue
Block a user