1use crate::agent::registry::AgentOverride;
2use crate::client::permissions::PermissionMode;
3use crate::session::scoping::find_git_root;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::path::Path;
7
8#[derive(Debug, Deserialize, Serialize, Default, Clone)]
9pub struct AcpCliConfig {
10 pub default_agent: Option<String>,
11 pub default_permissions: Option<PermissionMode>,
12 pub timeout: Option<u64>,
13 pub format: Option<String>,
14 pub agents: Option<HashMap<String, AgentOverride>>,
15 pub auth_token: Option<String>,
18}
19
20impl AcpCliConfig {
21 pub fn load() -> Self {
23 dirs::home_dir()
24 .map(|h| h.join(".acp-cli").join("config.json"))
25 .map(Self::load_from)
26 .unwrap_or_default()
27 }
28
29 pub fn load_project(cwd: &Path) -> Self {
32 find_git_root(cwd)
33 .map(|root| root.join(".acp-cli.json"))
34 .map(Self::load_from)
35 .unwrap_or_default()
36 }
37
38 pub fn load_from(path: impl AsRef<Path>) -> Self {
39 std::fs::read_to_string(path.as_ref())
40 .ok()
41 .and_then(|s| serde_json::from_str(&s).ok())
42 .unwrap_or_default()
43 }
44
45 pub fn merge(self, project: AcpCliConfig) -> AcpCliConfig {
47 AcpCliConfig {
48 default_agent: project.default_agent.or(self.default_agent),
49 default_permissions: project.default_permissions.or(self.default_permissions),
50 timeout: project.timeout.or(self.timeout),
51 format: project.format.or(self.format),
52 agents: match (self.agents, project.agents) {
53 (Some(mut base), Some(proj)) => {
54 base.extend(proj);
55 Some(base)
56 }
57 (base, proj) => proj.or(base),
58 },
59 auth_token: project.auth_token.or(self.auth_token),
60 }
61 }
62}