Class: Protege::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/protege/configuration.rb

Overview

Holds the process-wide Protege configuration set via Protege.configure. A single instance is memoized on the Protege module and read throughout the LOGI pipeline — the Orchestrator reads max_tool_turns, the Inference layer reads provider_id (each provider reads its own model / sampling / credentials from its providers slice), and the Gateway reads console_address. Mutated once at boot from a Rails initializer; treated as read-only thereafter (the Orchestrator even freezes it per delivery via Context).

Examples:

Configure in a Rails initializer

Protege.configure do |config|
  config.provider_id = :openrouter
  config.providers   = { openrouter: { model: 'anthropic/claude-sonnet-4-5' } }
end

Constant Summary collapse

DEFAULT_HTTP_USER_AGENT =

Generic, real-looking browser User-Agent sent by the built-in web tools (+web_search+, web_fetch) by default. Deliberately unbranded — a plain Chrome string that blends in — since some origins reject or fingerprint unusual agents.

'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' \
'(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializevoid

Initialize configuration with engine defaults.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/protege/configuration.rb', line 75

def initialize
  @nav_title         = '🥚 Protege'
  @console_address   = 'console@protege.local'
  @http_user_agent   = DEFAULT_HTTP_USER_AGENT
  @max_tool_turns    = 8
  @provider_id       = nil
  @logger            = nil
  @tools_path        = 'app/tools'
  @resolvers_path    = 'app/resolvers'
  @hooks_path        = 'app/hooks'
  @personas_path     = 'app/personas'
  @providers_path    = 'app/providers'
  @providers         = nil
  @attachment_policy = nil
  @inbound_access    = nil
  @tracing           = nil
end

Instance Attribute Details

#attachment_policyProtege::Gateway::AttachmentPolicy

The inbound attachment limits, assigned in the initializer via config.attachment_policy = Gateway.build_attachment_policy(...). Defaults to the engine's standard limits (10 MB/attachment, 10/message, 25 MB total). Consulted by the inbound mailbox and the send_email tool.

Returns:



137
138
139
# File 'lib/protege/configuration.rb', line 137

def attachment_policy
  @attachment_policy ||= Gateway.build_attachment_policy
end

#console_addressObject

Email address representing the dashboard user in local conversations. Messages from the dashboard use this as their from_address, and outbound replies to this address skip SMTP delivery.



36
37
38
# File 'lib/protege/configuration.rb', line 36

def console_address
  @console_address
end

#hooks_pathObject

Destination directories the extension scaffold generators (+protege:tool+, :resolver, :hook, :persona, :provider) write into, each relative to the app root. Defaults to the conventional app/tools, app/resolvers, app/hooks, app/personas, app/providers. Override in the initializer if a host groups its extensions elsewhere (e.g. config.tools_path = 'app/agents/tools'); the target must stay under an autoloaded path so Rails still loads the extension.



57
58
59
# File 'lib/protege/configuration.rb', line 57

def hooks_path
  @hooks_path
end

#http_user_agentObject

User-Agent the built-in web tools (+web_search+, web_fetch) send on outbound HTTP. Defaults to DEFAULT_HTTP_USER_AGENT — a generic browser string, not a Protege-branded one. Override to adopt your host machine's own browser agent, e.g. config.http_user_agent = ENV.fetch('HTTP_USER_AGENT', Protege::Configuration::DEFAULT_HTTP_USER_AGENT).



46
47
48
# File 'lib/protege/configuration.rb', line 46

def http_user_agent
  @http_user_agent
end

#inbound_accessProtege::Gateway::AccessPolicy

The global inbound access policy — the committed, org-wide ceiling on which senders may reach any persona. This is the static layer of the access-control guardrail; the runtime, per-persona layer lives in Protege::AccessRule records, and AccessControl intersects the two (each layer can only narrow, never widen).

Defaults to a bare permit-everyone policy, built lazily on first read so an unconfigured engine imposes no constraint.

Examples:

Restrict every persona to the company domain

config.inbound_access = Protege::Gateway.build_access_policy(allow: ['*@company.co'])

Returns:



153
154
155
# File 'lib/protege/configuration.rb', line 153

def inbound_access
  @inbound_access || Gateway.build_access_policy
end

#loggerLogger

Return the configured logger, lazily resolving a default.

Falls back to Rails.logger when running inside a Rails application, or a plain stdout logger otherwise (useful in isolated tests and scripts).

Returns:

  • (Logger)

    the active logger



99
100
101
# File 'lib/protege/configuration.rb', line 99

def logger
  @logger ||= defined?(Rails) ? Rails.logger : Logger.new($stdout)
end

#max_tool_turnsObject

Maximum tool-calling rounds before returning the last response.



31
32
33
# File 'lib/protege/configuration.rb', line 31

def max_tool_turns
  @max_tool_turns
end

Brand shown in the dashboard nav header. Override to white-label the console, e.g. config.nav_title = 'Acme Support'. Defaults to '🥚 Protege'.



40
41
42
# File 'lib/protege/configuration.rb', line 40

def nav_title
  @nav_title
end

#personas_pathObject

Destination directories the extension scaffold generators (+protege:tool+, :resolver, :hook, :persona, :provider) write into, each relative to the app root. Defaults to the conventional app/tools, app/resolvers, app/hooks, app/personas, app/providers. Override in the initializer if a host groups its extensions elsewhere (e.g. config.tools_path = 'app/agents/tools'); the target must stay under an autoloaded path so Rails still loads the extension.



57
58
59
# File 'lib/protege/configuration.rb', line 57

def personas_path
  @personas_path
end

#provider_idObject

Symbolic id of the inference provider extension (e.g. :openrouter). The model, sampling, and credentials for that provider live in its #providers slice, not here.



28
29
30
# File 'lib/protege/configuration.rb', line 28

def provider_id
  @provider_id
end

#providersHash{Symbol=>Hash}

Per-provider options, a plain Hash keyed by provider id — the Rails-style config seam every provider (built-in or host-written) reads its settings from. Assigned wholesale in the initializer; assignment replaces the whole Hash, so include every provider you configure:

config.providers = {
openrouter: { api_key: ENV['OPENROUTER_API_KEY'], base_url: '...' },
my_llm:     { api_key: ENV['MY_LLM_KEY'], region: 'us' }
}

Defaults to { openrouter: {} } so the built-in is harmless when unused. A provider reads its own slice via #provider_options (keyed by its protege_id). Values are opaque to the engine — a host-written provider may put any keys it likes under its own id and read them back here.

Returns:

  • (Hash{Symbol=>Hash})

    per-provider options keyed by provider id



117
118
119
# File 'lib/protege/configuration.rb', line 117

def providers
  @providers ||= { openrouter: {} }
end

#providers_pathObject

Destination directories the extension scaffold generators (+protege:tool+, :resolver, :hook, :persona, :provider) write into, each relative to the app root. Defaults to the conventional app/tools, app/resolvers, app/hooks, app/personas, app/providers. Override in the initializer if a host groups its extensions elsewhere (e.g. config.tools_path = 'app/agents/tools'); the target must stay under an autoloaded path so Rails still loads the extension.



57
58
59
# File 'lib/protege/configuration.rb', line 57

def providers_path
  @providers_path
end

#resolvers_pathObject

Destination directories the extension scaffold generators (+protege:tool+, :resolver, :hook, :persona, :provider) write into, each relative to the app root. Defaults to the conventional app/tools, app/resolvers, app/hooks, app/personas, app/providers. Override in the initializer if a host groups its extensions elsewhere (e.g. config.tools_path = 'app/agents/tools'); the target must stay under an autoloaded path so Rails still loads the extension.



57
58
59
# File 'lib/protege/configuration.rb', line 57

def resolvers_path
  @resolvers_path
end

#tools_pathObject

Destination directories the extension scaffold generators (+protege:tool+, :resolver, :hook, :persona, :provider) write into, each relative to the app root. Defaults to the conventional app/tools, app/resolvers, app/hooks, app/personas, app/providers. Override in the initializer if a host groups its extensions elsewhere (e.g. config.tools_path = 'app/agents/tools'); the target must stay under an autoloaded path so Rails still loads the extension.



57
58
59
# File 'lib/protege/configuration.rb', line 57

def tools_path
  @tools_path
end

#tracingHash

Inference tracing options, a plain Hash — the on/off seam for durable turn snapshots. Assigned wholesale in the initializer (like #providers); assignment replaces the whole Hash. Defaults to { enabled: false }, so an unconfigured engine records nothing. When enabled is truthy, the harness emits a per-turn InferenceGeneratedEvent that the tracing subscriber snapshots into Protege::Trace rows.

Examples:

Turn tracing on

config.tracing = { enabled: true }

Returns:

  • (Hash)

    the tracing options, defaulting to { enabled: false }



167
168
169
# File 'lib/protege/configuration.rb', line 167

def tracing
  @tracing ||= { enabled: false }
end

Instance Method Details

#provider_options(id) ⇒ Hash

The options Hash for one provider, by id — the seam a Protege::Provider reads its settings from (typically provider_options(self.class.id)). Nil-safe: returns an empty Hash when the provider has no configured slice.

Parameters:

  • id (Symbol)

    the provider id (its protege_id)

Returns:

  • (Hash)

    that provider's options, or {} when unconfigured



127
128
129
# File 'lib/protege/configuration.rb', line 127

def provider_options(id)
  providers[id] || {}
end