refactor(config): make the settings contract frontend-agnostic
rhema-config held both vocabularies: the stored settings and the terminal UI's theme, palette, and onboarding state, under one Config type with a global directory. A second frontend had to take the UI settings to get the profiles, and every path helper resolved $XDG_CONFIG_HOME/rhema no matter who called. The crate now ships only the framework's contract. Settings is the stored section, flattenable as one serde field. Home carries the directory conventions as a value, so a frontend keeps its settings, skills, subagents, and SYSTEM.md under its own base while .agents/skills stays machine-global. Store is the seam a foreign frontend implements over its own file and format, YamlStore is the reference impl, and Platform collects home, store, and keychain namespace at one construction site. KeyringSecretStore::named gives each frontend its own OS keychain service, so two frontends never share credentials by accident. examples/godcode.rs builds the whole shape runnable: its own directory, its own JSON document, its own namespace. rhema-code's store::Document flattens the section beside its UI fields, the layout on disk unchanged. serde's flatten silently drops unknown keys, so the load path re-checks every leftover key against the section: a typo'd profiles: stays loud inside the bigger document. CodingAgentConfig gains home: Option<Home>, so a frontend redirects skill discovery without calling the framework. claw and acp name their keychain namespaces, and the mcp, coding-agent, and subagents crates read conventions from the Home they are handed.
This commit is contained in:
1 parent
d067f4632f
commit
df4cf87a20
2 files changed
+4
-4
No files matched your search
@@ -210,7 +210,7 @@ impl ClawConfig {
|
||||
/// The default config path: `<config-base>/rhema/claw.yaml`, the same
|
||||
/// base the stored rhema config lives under.
|
||||
pub fn default_path() -> Result<PathBuf, ConfigError> {
|
||||
Ok(rhema_config::Config::dir()?.join("claw.yaml"))
|
||||
Ok(rhema_config::Home::discover()?.config.join("claw.yaml"))
|
||||
}
|
||||
|
||||
/// The state dir: `$XDG_STATE_HOME/rhema/claw`, else
|
||||
|
||||
@@ -169,11 +169,11 @@ fn mock_backends() -> Arc<rhema_claw::BackendRegistry> {
|
||||
/// the keyless llama-cpp backend is always constructible — and a
|
||||
/// dispatch against an unreachable provider fails loudly per turn.
|
||||
fn resolve_backends(config: &ClawConfig) -> Result<Arc<rhema_claw::BackendRegistry>, ClawError> {
|
||||
let stored = match rhema_config::Config::load() {
|
||||
let stored = match rhema_config::Settings::load() {
|
||||
Ok(stored) => stored,
|
||||
Err(err) => {
|
||||
eprintln!("warning: ignoring unreadable rhema config: {err}");
|
||||
rhema_config::Config::default()
|
||||
rhema_config::Settings::default()
|
||||
}
|
||||
};
|
||||
let profile = stored.effective(None);
|
||||
@@ -205,7 +205,7 @@ fn resolve_backends(config: &ClawConfig) -> Result<Arc<rhema_claw::BackendRegist
|
||||
// included; it never writes it, so no migration runs here — the
|
||||
// file's logins belong to the frontends. In a container the
|
||||
// keychain is unreachable and the literal tier serves.
|
||||
let secrets = rhema_config::secrets::KeyringSecretStore::new();
|
||||
let secrets = rhema_config::secrets::KeyringSecretStore::named("claw");
|
||||
let backends =
|
||||
rhema_claw::backends::discover(config, &profile, &env, &claw_rows, Some(&secrets));
|
||||
// The config's provider/model pair seeds the active backend when it
|
||||
|
||||
Reference in new issue
Block a user