Class: Rubino::Config::Loader

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/config/loader.rb

Overview

Responsible for loading configuration from YAML files and environment.

Config is GLOBAL by design (#50): there is ONE config.yml, under RUBINO_HOME (default ~/.rubino), shared by every rubino instance on the machine — the same single-home model Hermes uses (~/.hermes/config.yaml). So ‘/think` / `/config set` in one instance changes the setting for all of them; there is no per-project/per-cwd override layer. Per-project config (cf. Claude Code’s .claude/settings.json hierarchy) is a separate, unbuilt feature, not the current contract. The merge is: user config.yml over built-in defaults (with $ENV expansion).

Constant Summary collapse

CONFIG_FILENAME =
"config.yml"
ENV_FILENAME =
".env"
ENV_VAR_PATTERN =
/\$\{([A-Z_][A-Z0-9_]*)\}/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(home_path: nil) ⇒ Loader

Returns a new instance of Loader.



39
40
41
42
43
# File 'lib/rubino/config/loader.rb', line 39

def initialize(home_path: nil)
  @home_path = home_path || self.class.default_home_path
  @config_path = File.join(@home_path, CONFIG_FILENAME)
  @env_path = File.join(@home_path, ENV_FILENAME)
end

Instance Attribute Details

#config_pathObject (readonly)

Returns the value of attribute config_path.



25
26
27
# File 'lib/rubino/config/loader.rb', line 25

def config_path
  @config_path
end

#env_pathObject (readonly)

Returns the value of attribute env_path.



25
26
27
# File 'lib/rubino/config/loader.rb', line 25

def env_path
  @env_path
end

#home_pathObject (readonly)

Returns the value of attribute home_path.



25
26
27
# File 'lib/rubino/config/loader.rb', line 25

def home_path
  @home_path
end

Class Method Details

.default_home_pathObject

Single source of truth for the home directory: RUBINO_HOME when set, else ~/.rubino. Rubino.home_path delegates here so the server (which loads config via the Loader) and the CLI commands (config/setup/doctor) resolve the SAME directory — previously the server honoured $RUBINO_HOME while the CLI recomputed File.join(Rubino.home_path, “config.yml”) off the YAML ‘paths.home` default (~/.rubino), a split brain at first boot.



34
35
36
37
# File 'lib/rubino/config/loader.rb', line 34

def self.default_home_path
  env = ENV["RUBINO_HOME"].to_s.strip
  env.empty? ? File.expand_path("~/.rubino") : File.expand_path(env)
end

Instance Method Details

#config_exists?Boolean

Returns true if a config file exists

Returns:

  • (Boolean)


74
75
76
# File 'lib/rubino/config/loader.rb', line 74

def config_exists?
  File.exist?(@config_path)
end

#create_default_config!Object

Creates the initial config file with defaults



79
80
81
82
83
# File 'lib/rubino/config/loader.rb', line 79

def create_default_config!
  FileUtils.mkdir_p(@home_path)
  File.write(@config_path, Defaults.to_yaml)
  @config_path
end

#loadObject

Loads configuration from file, merging with defaults.

Every way a config.yml can be unusable is normalized into a single ConfigError with a clean, actionable message here — at the source —so no raw Ruby/Psych backtrace can escape to the boot path (CFG-1 / CFG-R2). Covers: a YAML syntax error, an alias/anchor reference (safe_load rejects aliases by design), a config path that is a directory or a symlink to one (Errno::EISDIR), a non-Hash top-level (a bare scalar like ‘foo`, or a sequence), and any other read/parse failure.



55
56
57
58
59
60
61
# File 'lib/rubino/config/loader.rb', line 55

def load
  raw = load_raw_config

  load_env_file if File.exist?(@env_path)

  deep_merge(Defaults.to_hash, expand_env_vars(raw))
end

#raw_configObject

The RAW user config.yml as a Hash (NOT merged with defaults), or {} when no file exists. Public so the boot guard / doctor can run LOAD-time schema validation (F8) over exactly what the user hand-edited — defaults are valid by construction, so merging them in would hide the user’s mistakes. Same normalization as #load (a malformed shape raises ConfigError), so callers get a clean error, never a raw Psych backtrace.



69
70
71
# File 'lib/rubino/config/loader.rb', line 69

def raw_config
  load_raw_config
end