Class: Insika::LLMConfigurator
- Inherits:
-
Object
- Object
- Insika::LLMConfigurator
- Defined in:
- lib/insika/llm_configurator.rb
Overview
Applies the authored LLM providers (LLMProviderStore) to RubyLLM at RUNTIME.
Goal: swap a provider's key/base WITHOUT a restart —
RubyLLM exposes config.<api>_api_key= / config.<api>_api_base=, so
reconfiguring is a matter of setting those accessors per provider.
Core constraint: this file does NOT require ruby_llm at load-time — the
require is lazy, inside apply (and injectable via configure: for tests,
which run without the gem/key). A provider that RubyLLM doesn't recognize (no
matching accessor) does NOT blow up: it goes into skipped (degrades to "restart
recommended", like OpenClaw), the rest applies.
⚠️ GOTCHA — the DEFAULT target is a global singleton (RubyLLM research, §10).
With no configure:, apply/unapply mutate the PROCESS-WIDE config
(RubyLLM.config). They are therefore admin operations (rare, operator-driven:
a provider key/base edit in the Studio), NOT a per-request/per-turn path — a
concurrent turn reading the config mid-mutation would observe a torn key/base.
This is tolerable ONLY because reconfiguration is infrequent and single-writer
(one reactor). Do NOT call this per turn, and do NOT reach for it to vary the
MODEL per turn — the model is chosen at chat build time (ModelResolver ->
chat(model:)), never by mutating the global.
PER-GRAPH credentials are no longer hypothetical (RFC-0017 A2): the DSL runtime
passes configure: targeting its own RubyLLM.context — an isolated config dup
— so an operator's key edit in an EMBEDDED graph applies to that graph and stops
there. See DSL::Runtime#llm_configure and docs/EMBEDDING.md.
Instance Method Summary collapse
-
#apply(providers = nil) ⇒ Object
Reconfigures RubyLLM with
providers(raw records, with the real api_key) or, if nil, with ALL from the store. -
#initialize(provider_store:, configure: nil) ⇒ LLMConfigurator
constructor
A new instance of LLMConfigurator.
-
#unapply(api) ⇒ Object
UNDOES a provider's config in RubyLLM at runtime (delete without a restart, §9.5): clears
<api>_api_key/<api>_api_base.
Constructor Details
#initialize(provider_store:, configure: nil) ⇒ LLMConfigurator
Returns a new instance of LLMConfigurator.
30 31 32 33 |
# File 'lib/insika/llm_configurator.rb', line 30 def initialize(provider_store:, configure: nil) @provider_store = provider_store @configure = configure # ->(&blk){ blk.call(config_target) }; default = RubyLLM end |
Instance Method Details
#apply(providers = nil) ⇒ Object
Reconfigures RubyLLM with providers (raw records, with the real api_key) or,
if nil, with ALL from the store. -> { applied: [api], skipped: [reason:] }.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/insika/llm_configurator.rb', line 37 def apply(providers = nil) records = providers || @provider_store.all_raw applied = [] skipped = [] with_config do |config| records.each do |rec| api = fetch(rec, :api) key = fetch(rec, :api_key) if key.nil? || key.to_s.empty? skipped << { api: api, reason: "sem api_key" } next end if set_accessor(config, "#{api}_api_key", key) base = fetch(rec, :base_url) set_accessor(config, "#{api}_api_base", base) if base && !base.to_s.empty? applied << api else skipped << { api: api, reason: "provider '#{api}' not recognized by RubyLLM" } end end end { applied: applied, skipped: skipped } end |
#unapply(api) ⇒ Object
UNDOES a provider's config in RubyLLM at runtime (delete without a restart,
§9.5): clears <api>_api_key/<api>_api_base. A provider that RubyLLM
doesn't recognize (no accessor) -> unapplied: false (nothing applied, nothing to undo).
-> { unapplied: bool }.
68 69 70 71 72 73 74 75 76 |
# File 'lib/insika/llm_configurator.rb', line 68 def unapply(api) api = api.to_s unapplied = false with_config do |config| unapplied = set_accessor(config, "#{api}_api_key", nil) set_accessor(config, "#{api}_api_base", nil) end { unapplied: unapplied } end |