This commit implements the complete M1 milestone (Config & Permissions) including: - New permissions crate with Tool, Action, Mode, and PermissionManager - Three permission modes: Plan (read-only default), AcceptEdits, Code - Pattern matching for permission rules (exact match and prefix with *) - Integration with config-agent for mode-based permission management - CLI integration with --mode flag to override configured mode - Permission checks for Read, Glob, and Grep operations - Comprehensive test suite (10 tests in permissions, 4 in config, 4 in CLI) Also fixes: - Fixed failing test in tools-fs (glob pattern issue) - Improved glob_list() root extraction to handle patterns like "/*.txt" All 21 workspace tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
2.2 KiB
Rust
77 lines
2.2 KiB
Rust
use directories::ProjectDirs;
|
|
use figment::{
|
|
Figment,
|
|
providers::{Env, Format, Serialized, Toml},
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::path::PathBuf;
|
|
use permissions::{Mode, PermissionManager};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Settings {
|
|
#[serde(default = "default_ollama_url")]
|
|
pub ollama_url: String,
|
|
#[serde(default = "default_model")]
|
|
pub model: String,
|
|
#[serde(default = "default_mode")]
|
|
pub mode: String, // "plan" (read-only) for now
|
|
#[serde(default)]
|
|
pub api_key: Option<String>, // For Ollama Cloud or other API authentication
|
|
}
|
|
|
|
fn default_ollama_url() -> String {
|
|
"http://localhost:11434".into()
|
|
}
|
|
fn default_model() -> String {
|
|
"qwen3:8b".into()
|
|
}
|
|
fn default_mode() -> String {
|
|
"plan".into()
|
|
}
|
|
|
|
impl Default for Settings {
|
|
fn default() -> Self {
|
|
Self {
|
|
ollama_url: default_ollama_url(),
|
|
model: default_model(),
|
|
mode: default_mode(),
|
|
api_key: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Settings {
|
|
/// Create a PermissionManager based on the configured mode
|
|
pub fn create_permission_manager(&self) -> PermissionManager {
|
|
let mode = Mode::from_str(&self.mode).unwrap_or(Mode::Plan);
|
|
PermissionManager::new(mode)
|
|
}
|
|
|
|
/// Get the Mode enum from the mode string
|
|
pub fn get_mode(&self) -> Mode {
|
|
Mode::from_str(&self.mode).unwrap_or(Mode::Plan)
|
|
}
|
|
}
|
|
|
|
pub fn load_settings(project_root: Option<&str>) -> Result<Settings, figment::Error> {
|
|
let mut fig = Figment::from(Serialized::defaults(Settings::default()));
|
|
|
|
// User file: ~/.config/owlen/config.toml
|
|
if let Some(pd) = ProjectDirs::from("dev", "owlibou", "owlen") {
|
|
let user = pd.config_dir().join("config.toml");
|
|
fig = fig.merge(Toml::file(user));
|
|
}
|
|
|
|
// Project file: <root>/.owlen.toml
|
|
if let Some(root) = project_root {
|
|
fig = fig.merge(Toml::file(PathBuf::from(root).join(".owlen.toml")));
|
|
}
|
|
|
|
// Environment variables have highest precedence
|
|
fig = fig.merge(Env::prefixed("OWLEN_").split("__"));
|
|
// Support OLLAMA_API_KEY, OLLAMA_MODEL, etc. (without nesting)
|
|
fig = fig.merge(Env::prefixed("OLLAMA_"));
|
|
|
|
fig.extract()
|
|
}
|