Class: LittleGhost::Configuration
- Inherits:
-
Object
- Object
- LittleGhost::Configuration
- Defined in:
- lib/little_ghost/configuration.rb
Overview
Configure shared services and lookup rules before agents start. A configuration collects model profiles, persistence, paths, instrumentation, and runtime hooks for an application.
LittleGhost.configure do |config|
config.default_model :customer_support
config.service_name "support-api"
end
LittleGhost.configuration.default_model # => "customer_support"
LittleGhost.configuration.service_name # => "support-api"
Prompt and skill lookup paths default to app/prompts and app/skills
under the application root. Applications may append shared roots or replace
the arrays entirely.
Configuration is a mutable builder, while each Runtime owns a settings
snapshot. The first runtime for a root loads config/little_ghost.rb once;
later mutations do not alter that runtime, and one configuration cannot load
files for two different roots.
Session actor resolvers belong at an authentication boundary. Multi-tenant applications should derive actor identity from trusted authenticated state, not from an unverified request field.
Constant Summary collapse
- FILE_LOAD_MUTEX =
:nodoc:
Mutex.new
- CONFIGURATION_KEYS =
:nodoc:
%i[invocation service_name].freeze
- DEFAULT_PROMPT_PATHS =
:nodoc:
["app/prompts"].freeze
- DEFAULT_SKILL_PATHS =
:nodoc:
["app/skills"].freeze
Instance Method Summary collapse
-
#[](name) ⇒ Object
Looks up an arbitrary setting by symbol or string-compatible name.
-
#[]=(name, value) ⇒ Object
Adds or replaces an arbitrary setting.
-
#catalog_source(source) ⇒ Object
Adds an explicit catalog source.
-
#configure {|_self| ... } ⇒ Object
Yields this builder for setup and returns the same instance.
-
#default_model(value = :__read__) ⇒ Object
Fallback logical role for the default resolver.
-
#default_model=(value) ⇒ Object
Replaces the fallback logical role and normalizes it to a String.
-
#initialize(values = {}) ⇒ Configuration
constructor
Starts a mutable builder with optional
values. -
#instrument(subscriber) ⇒ Object
Adds an Instrumentation::Subscriber to each new runtime and returns it.
-
#load_file!(root: nil) ⇒ Object
:nodoc:.
-
#log_events_to(destination = :__read__) ⇒ Object
:call-seq: log_events_to() -> :stdout, :stderr, nil log_events_to(destination) -> destination.
-
#log_events_to=(destination) ⇒ Object
Replaces the console destination for structured framework events.
-
#model_resolver(value = :__read__) ⇒ Object
Installs a complete resolver override for subsequently built runtimes.
- #model_resolver=(value) ⇒ Object
-
#models(value = :__read__) ⇒ Object
Logical model profiles for the default resolver.
-
#models=(value) ⇒ Object
Replaces logical model profiles for subsequently built runtimes.
-
#models_path(value = :__read__) ⇒ Object
Model YAML path.
-
#models_path=(value) ⇒ Object
Replaces the model YAML path for subsequently built runtimes.
-
#name ⇒ Object
Replaces the service name attached to telemetry from new runtimes.
-
#prompt_paths ⇒ Object
Mutable prompt lookup paths, in precedence order.
-
#prompt_paths=(value) ⇒ Object
Replaces prompt lookup paths with
valueconverted to an Array. -
#provider_adapter(name, callable = nil, &factory) ⇒ Object
Registers a provider adapter factory under
name. -
#provider_credentials(callable = nil, &resolver) ⇒ Object
Installs a trusted callable that returns credential options for a named provider connection when each executable model is constructed.
-
#providers(value = :__read__) ⇒ Object
Trusted provider connections for the default or custom resolver.
-
#providers=(value) ⇒ Object
Replaces trusted provider connections for subsequently built runtimes.
-
#providers_path(value = :__read__) ⇒ Object
Provider YAML path.
-
#providers_path=(value) ⇒ Object
Replaces the provider YAML path for subsequently built runtimes.
-
#root(value = :__read__) ⇒ Object
:call-seq: root() -> Pathname root(path) -> Pathname.
-
#root=(value) ⇒ Object
Replaces the application root after resolving it to a stable real path.
-
#runtime_hook(hook_class) ⇒ Object
Adds a Runtime::Hook subclass to each new runtime and returns it.
-
#sandbox ⇒ Object
Sandbox declaration used for subsequently built runtimes.
-
#sandbox=(value) ⇒ Object
Selects the Sandbox subclass instantiated around each run's workspace.
-
#session_actor(value = :__read__, &resolver) ⇒ Object
:call-seq: session_actor() -> callable, nil session_actor(callable) -> callable session_actor { |invocation| ... } -> callable.
-
#session_store ⇒ Object
Session-store declaration used for subsequently built runtimes.
-
#session_store=(value) ⇒ Object
Selects session persistence with a
:providerand its constructor options. -
#settings(root: nil) ⇒ Object
:nodoc:.
-
#skill_paths ⇒ Object
Mutable skill lookup paths, in precedence order.
-
#skill_paths=(value) ⇒ Object
Replaces skill lookup paths with
valueconverted to an Array. -
#skill_resource_root ⇒ Object
Optional trusted root exposed to skills for resource lookup.
-
#skill_resource_root=(value) ⇒ Object
Replaces the trusted skill resource root for new runtimes.
-
#workspace ⇒ Object
Workspace declaration used for subsequently built runtimes.
-
#workspace=(value) ⇒ Object
Selects the Workspace subclass instantiated for each run.
Constructor Details
#initialize(values = {}) ⇒ Configuration
Starts a mutable builder with optional values.
Prompt paths default to app/prompts and skill paths to app/skills.
Collection settings are copied so callers can safely reuse their input
arrays after construction.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/little_ghost/configuration.rb', line 87 def initialize(values = {}) @configuration_values = { prompt_paths: DEFAULT_PROMPT_PATHS.dup, skill_paths: DEFAULT_SKILL_PATHS.dup, skill_resource_root: nil, workspace: nil, sandbox: nil, instrumentation_subscribers: [], runtime_hooks: [] }.merge(values) @configuration_values[:prompt_paths] = Array(@configuration_values[:prompt_paths]).dup @configuration_values[:skill_paths] = Array(@configuration_values[:skill_paths]).dup @configuration_values[:instrumentation_subscribers] = Array( @configuration_values[:instrumentation_subscribers] ).dup @configuration_values[:runtime_hooks] = Array(@configuration_values[:runtime_hooks]).dup @configuration_values[:provider_adapters] = @configuration_values.fetch(:provider_adapters, {}).dup @configuration_values[:catalog_sources] = Array(@configuration_values[:catalog_sources]).dup @configuration_values[:provider_credentials] ||= nil end |
Instance Method Details
#[](name) ⇒ Object
Looks up an arbitrary setting by symbol or string-compatible name.
292 293 294 |
# File 'lib/little_ghost/configuration.rb', line 292 def [](name) configuration_values.fetch(name.to_sym) end |
#[]=(name, value) ⇒ Object
Adds or replaces an arbitrary setting.
297 298 299 |
# File 'lib/little_ghost/configuration.rb', line 297 def []=(name, value) configuration_values[name.to_sym] = value end |
#catalog_source(source) ⇒ Object
Adds an explicit catalog source. Sources refresh only when callers invoke ModelResolver#refresh!.
248 249 250 251 252 253 254 |
# File 'lib/little_ghost/configuration.rb', line 248 def catalog_source(source) raise ArgumentError, "catalog source must be a Models::Catalog::Source" unless source.is_a?(Models::Catalog::Source) configuration_values[:catalog_sources] << source @resolved_model_resolver = nil source end |
#configure {|_self| ... } ⇒ Object
Yields this builder for setup and returns the same instance.
109 110 111 112 |
# File 'lib/little_ghost/configuration.rb', line 109 def configure yield self if block_given? self end |
#default_model(value = :__read__) ⇒ Object
Fallback logical role for the default resolver.
156 157 158 159 160 161 162 |
# File 'lib/little_ghost/configuration.rb', line 156 def default_model(value = :__read__) return configuration_values[:default_model] if value == :__read__ configuration_values[:default_model] = value.to_s reset_model_resolver value.to_s end |
#default_model=(value) ⇒ Object
Replaces the fallback logical role and normalizes it to a String.
165 166 167 |
# File 'lib/little_ghost/configuration.rb', line 165 def default_model=(value) default_model(value) end |
#instrument(subscriber) ⇒ Object
Adds an Instrumentation::Subscriber to each new runtime and returns it.
307 308 309 310 311 312 313 314 |
# File 'lib/little_ghost/configuration.rb', line 307 def instrument(subscriber) unless subscriber.is_a?(Instrumentation::Subscriber) raise ArgumentError, "instrumentation subscriber must be a LittleGhost::Instrumentation::Subscriber" end configuration_values[:instrumentation_subscribers] << subscriber subscriber end |
#load_file!(root: nil) ⇒ Object
:nodoc:
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/little_ghost/configuration.rb', line 421 def load_file!(root: nil) # :nodoc: requested_root = canonical_root(root || self.root) FILE_LOAD_MUTEX.synchronize do (@configuration_file_mutex ||= Mutex.new).synchronize do if @configuration_file_root return self if @configuration_file_root == requested_root raise ConfigurationError, "configuration file is already loaded for #{@configuration_file_root}" end path = File.join(requested_root, "config/little_ghost.rb") LittleGhost.with_configuration(self) { Kernel.load(path) } if File.file?(path) @configuration_file_root = requested_root end end self end |
#log_events_to(destination = :__read__) ⇒ Object
:call-seq:
log_events_to() -> :stdout, :stderr, nil
log_events_to(destination) -> destination
Sends structured framework events to :stdout or :stderr. This setting
controls the process-wide Events console destination; the most recent
setting replaces it without changing other event listeners. By default,
events have no console destination. Passing nil disables console output.
The console listener redacts sensitive values and writes one JSON object
per line.
326 327 328 329 330 |
# File 'lib/little_ghost/configuration.rb', line 326 def log_events_to(destination = :__read__) return Events.console_output if destination == :__read__ Events.console_output = destination end |
#log_events_to=(destination) ⇒ Object
Replaces the console destination for structured framework events.
333 334 335 |
# File 'lib/little_ghost/configuration.rb', line 333 def log_events_to=(destination) log_events_to(destination) end |
#model_resolver(value = :__read__) ⇒ Object
Installs a complete resolver override for subsequently built runtimes.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/little_ghost/configuration.rb', line 188 def model_resolver(value = :__read__) if value != :__read__ validate_model_resolver_class!(value) configuration_values[:model_resolver] = value @resolved_model_resolver = nil return value end @model_resolver_mutex ||= Mutex.new @model_resolver_mutex.synchronize do @resolved_model_resolver ||= begin providers = resolved_providers credential_resolver = configuration_values[:provider_credentials] || providers&.method(:credentials) configured = configuration_values[:model_resolver] if configured validate_model_resolver_configuration! configured.new( providers:, provider_adapters: configuration_values[:provider_adapters], catalog_sources: configuration_values[:catalog_sources], credential_resolver: ) else profiles, file_default = resolved_models ModelResolver.new( providers:, profiles:, default_model: configuration_values.fetch(:default_model, file_default), provider_adapters: configuration_values[:provider_adapters], catalog_sources: configuration_values[:catalog_sources], credential_resolver: ) end end end end |
#model_resolver=(value) ⇒ Object
226 227 228 |
# File 'lib/little_ghost/configuration.rb', line 226 def model_resolver=(value) model_resolver(value) end |
#models(value = :__read__) ⇒ Object
Logical model profiles for the default resolver. Role names cannot contain a colon because that syntax identifies a canonical model target.
141 142 143 144 145 146 147 148 |
# File 'lib/little_ghost/configuration.rb', line 141 def models(value = :__read__) return configuration_values[:models] if value == :__read__ raise ArgumentError, "models must be a Hash" unless value.is_a?(Hash) configuration_values[:models] = value reset_model_resolver value end |
#models=(value) ⇒ Object
Replaces logical model profiles for subsequently built runtimes.
151 152 153 |
# File 'lib/little_ghost/configuration.rb', line 151 def models=(value) models(value) end |
#models_path(value = :__read__) ⇒ Object
Model YAML path. The conventional path is optional; an explicitly set path must exist when a runtime is built.
180 |
# File 'lib/little_ghost/configuration.rb', line 180 def models_path(value = :__read__) = configuration_path(:models_path, "models.yml", value) |
#models_path=(value) ⇒ Object
Replaces the model YAML path for subsequently built runtimes.
183 184 185 |
# File 'lib/little_ghost/configuration.rb', line 183 def models_path=(value) models_path(value) end |
#name ⇒ Object
Replaces the service name attached to telemetry from new runtimes. :method: service_name= :call-seq:
service_name=(value) -> value
52 53 54 55 56 57 58 |
# File 'lib/little_ghost/configuration.rb', line 52 CONFIGURATION_KEYS.each do |name| define_method(name) do |value = :__read__| return configuration_values[name] if value == :__read__ configuration_values[name] = value end end |
#prompt_paths ⇒ Object
Mutable prompt lookup paths, in precedence order.
385 |
# File 'lib/little_ghost/configuration.rb', line 385 def prompt_paths = configuration_values[:prompt_paths] |
#prompt_paths=(value) ⇒ Object
Replaces prompt lookup paths with value converted to an Array.
388 389 390 |
# File 'lib/little_ghost/configuration.rb', line 388 def prompt_paths=(value) configuration_values[:prompt_paths] = Array(value) end |
#provider_adapter(name, callable = nil, &factory) ⇒ Object
Registers a provider adapter factory under name.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/little_ghost/configuration.rb', line 231 def provider_adapter(name, callable = nil, &factory) implementation = factory || callable if implementation.is_a?(Class) unless implementation <= Providers::Base raise ArgumentError, "provider adapter class must inherit LittleGhost::Providers::Base" end elsif !implementation.respond_to?(:call) raise ArgumentError, "provider adapter must be a Providers::Base class or callable factory" end configuration_values[:provider_adapters][name.to_s] = implementation @resolved_model_resolver = nil implementation end |
#provider_credentials(callable = nil, &resolver) ⇒ Object
Installs a trusted callable that returns credential options for a named provider connection when each executable model is constructed.
258 259 260 261 262 263 264 265 266 |
# File 'lib/little_ghost/configuration.rb', line 258 def provider_credentials(callable = nil, &resolver) value = resolver || callable return configuration_values[:provider_credentials] unless value raise ArgumentError, "provider credential resolver must be callable" unless value.respond_to?(:call) configuration_values[:provider_credentials] = value @resolved_model_resolver = nil value end |
#providers(value = :__read__) ⇒ Object
Trusted provider connections for the default or custom resolver.
122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/little_ghost/configuration.rb', line 122 def providers(value = :__read__) return configuration_values[:providers] if value == :__read__ unless value.is_a?(Hash) || value.is_a?(Providers::Configuration) raise ArgumentError, "providers must be a Hash or LittleGhost::Providers::Configuration" end configuration_values[:providers] = value reset_model_resolver value end |
#providers=(value) ⇒ Object
Replaces trusted provider connections for subsequently built runtimes.
135 136 137 |
# File 'lib/little_ghost/configuration.rb', line 135 def providers=(value) providers(value) end |
#providers_path(value = :__read__) ⇒ Object
Provider YAML path. The conventional path is optional; an explicitly set path must exist when a runtime is built.
171 |
# File 'lib/little_ghost/configuration.rb', line 171 def providers_path(value = :__read__) = configuration_path(:providers_path, "providers.yml", value) |
#providers_path=(value) ⇒ Object
Replaces the provider YAML path for subsequently built runtimes.
174 175 176 |
# File 'lib/little_ghost/configuration.rb', line 174 def providers_path=(value) providers_path(value) end |
#root(value = :__read__) ⇒ Object
:call-seq:
root() -> Pathname
root(path) -> Pathname
The resolved application root, defaulting to Dir.pwd.
Setting or reading an invalid root raises ConfigurationError. Symlinks are resolved so runtimes and lookup paths share one stable boundary.
375 376 377 378 379 380 381 382 |
# File 'lib/little_ghost/configuration.rb', line 375 def root(value = :__read__) if value != :__read__ return configuration_values[:root] = canonical_root(value) end configured = configuration_values[:root] configured ? canonical_root(configured) : inferred_root end |
#root=(value) ⇒ Object
Replaces the application root after resolving it to a stable real path.
302 303 304 |
# File 'lib/little_ghost/configuration.rb', line 302 def root=(value) root(value) end |
#runtime_hook(hook_class) ⇒ Object
Adds a Runtime::Hook subclass to each new runtime and returns it.
338 339 340 341 342 343 344 345 |
# File 'lib/little_ghost/configuration.rb', line 338 def runtime_hook(hook_class) unless hook_class.is_a?(Class) && hook_class <= Runtime::Hook raise ArgumentError, "runtime_hook must be a LittleGhost::Runtime::Hook class" end configuration_values[:runtime_hooks] << hook_class hook_class end |
#sandbox ⇒ Object
Sandbox declaration used for subsequently built runtimes.
117 118 |
# File 'lib/little_ghost/configuration.rb', line 117 def sandbox = configuration_values[:sandbox] # Session-store declaration used for subsequently built runtimes. |
#sandbox=(value) ⇒ Object
Selects the Sandbox subclass instantiated around each run's workspace.
274 275 276 |
# File 'lib/little_ghost/configuration.rb', line 274 def sandbox=(value) @configuration_values[:sandbox] = component_class(value, Sandbox, :sandbox) end |
#session_actor(value = :__read__, &resolver) ⇒ Object
:call-seq:
session_actor() -> callable, nil
session_actor(callable) -> callable
session_actor { |invocation| ... } -> callable
The callable that derives the persistence actor for each invocation.
Pass either a callable or a block. The configured resolver should use trusted authenticated identity in multi-tenant applications.
356 357 358 359 360 361 362 363 364 365 |
# File 'lib/little_ghost/configuration.rb', line 356 def session_actor(value = :__read__, &resolver) return configuration_values[:session_actor] if value == :__read__ && !resolver raise ArgumentError, "Provide a session actor resolver or a block, not both" if value != :__read__ && resolver configured = resolver || value raise ArgumentError, "session_actor must be callable" unless configured.respond_to?(:call) configuration_values[:session_actor] = configured end |
#session_store ⇒ Object
Session-store declaration used for subsequently built runtimes.
119 |
# File 'lib/little_ghost/configuration.rb', line 119 def session_store = configuration_values[:session_store] |
#session_store=(value) ⇒ Object
Selects session persistence with a :provider and its constructor options.
The provider must be a SessionStore subclass. Runtime construction creates and owns the store instance.
282 283 284 285 286 287 288 289 |
# File 'lib/little_ghost/configuration.rb', line 282 def session_store=(value) unless value.is_a?(Hash) raise ArgumentError, "session_store must be a hash with a provider" end provider = value[:provider] @configuration_values[:session_store] = value.merge(provider: component_class(provider, SessionStore, :session_store)) end |
#settings(root: nil) ⇒ Object
:nodoc:
408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/little_ghost/configuration.rb', line 408 def settings(root: nil) # :nodoc: requested_root = root && canonical_root(root) values = configuration_values.dup values[:prompt_paths] = Array(values[:prompt_paths]).dup values[:skill_paths] = Array(values[:skill_paths]).dup values[:instrumentation_subscribers] = Array(values[:instrumentation_subscribers]).dup values[:runtime_hooks] = Array(values[:runtime_hooks]).dup values[:model_resolver] = model_resolver values[:default_model] = values[:model_resolver].default_model values[:root] = requested_root || values[:root] || self.root values end |
#skill_paths ⇒ Object
Mutable skill lookup paths, in precedence order.
393 |
# File 'lib/little_ghost/configuration.rb', line 393 def skill_paths = configuration_values[:skill_paths] |
#skill_paths=(value) ⇒ Object
Replaces skill lookup paths with value converted to an Array.
396 397 398 |
# File 'lib/little_ghost/configuration.rb', line 396 def skill_paths=(value) configuration_values[:skill_paths] = Array(value) end |
#skill_resource_root ⇒ Object
Optional trusted root exposed to skills for resource lookup.
401 |
# File 'lib/little_ghost/configuration.rb', line 401 def skill_resource_root = configuration_values[:skill_resource_root] |
#skill_resource_root=(value) ⇒ Object
Replaces the trusted skill resource root for new runtimes.
404 405 406 |
# File 'lib/little_ghost/configuration.rb', line 404 def skill_resource_root=(value) configuration_values[:skill_resource_root] = value end |
#workspace ⇒ Object
Workspace declaration used for subsequently built runtimes.
115 116 |
# File 'lib/little_ghost/configuration.rb', line 115 def workspace = configuration_values[:workspace] # Sandbox declaration used for subsequently built runtimes. |
#workspace=(value) ⇒ Object
Selects the Workspace subclass instantiated for each run.
269 270 271 |
# File 'lib/little_ghost/configuration.rb', line 269 def workspace=(value) @configuration_values[:workspace] = component_class(value, Workspace, :workspace) end |