Class: Insika::Plugin::Loader::RegistrationAPI

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/plugin/loader.rb

Overview

Facade passed to the plugin. A contract is required only for tools and workflows (addressable by name); middleware/hooks/providers are STAGED and made effective by commit! only when register(api) returns without an exception (materializes the rollback guarantee — nothing partial remains).

Instance Method Summary collapse

Constructor Details

#initialize(registries:, plugin_id:, tool_names:, workflow_names:, tool_metadata:, config:, capability_names: [], channel_names: []) ⇒ RegistrationAPI

Returns a new instance of RegistrationAPI.



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/insika/plugin/loader.rb', line 175

def initialize(registries:, plugin_id:, tool_names:, workflow_names:,
               tool_metadata:, config:, capability_names: [], channel_names: [])
  @registries = registries
  @plugin_id = plugin_id
  @tool_names = tool_names
  @workflow_names = workflow_names
  @capability_names = capability_names
  @channel_names = channel_names
  @tool_metadata = 
  @config = config.freeze
  @staged_middleware = []
  @staged_providers = []
  @staged_hooks = []
  @staged_capabilities = []
end

Instance Method Details

#commit!Object

Atomic by construction: the hook pairs were already validated at stage time, so no line here raises (array <<, hooks.register of a valid pair).



283
284
285
286
287
288
289
290
291
292
# File 'lib/insika/plugin/loader.rb', line 283

def commit!
  @staged_middleware.each { |m| @registries[:middleware] << m }
  @staged_providers.each { |p| @registries[:context_providers] << p }
  @staged_hooks.each { |pair, before, after| @registries[:hooks].register(pair, before: before, after: after) }
  @staged_capabilities.each do |c|
    @registries[:capabilities].register(c[:capability], impl_name: c[:impl_name], kind: c[:kind],
                                                         plugin: @plugin_id, priority: c[:priority],
                                                         available: c[:available])
  end
end

#configObject



279
# File 'lib/insika/plugin/loader.rb', line 279

def config = @config

#register_capability(name, tool: nil, workflow: nil, priority: nil, available: nil) ⇒ Object

Mirrors register_tool ("not declared -> warn + ignore"), + tool:/workflow: exclusivity and the warn for kind :workflow (no consumer in this slice). Staged; made effective at commit! (nothing partial if register(api) raises).



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/insika/plugin/loader.rb', line 233

def register_capability(name, tool: nil, workflow: nil, priority: nil, available: nil)
  name = name.to_s
  unless @capability_names.include?(name)
    warn "[plugin #{@plugin_id}] capability '#{name}' not declared in contracts.capabilities — ignored"
    return
  end

  if tool && workflow
    warn "[plugin #{@plugin_id}] capability '#{name}': provide only tool: OR workflow:, not both — ignored"
    return
  end

  impl_name, kind =
    if tool then [tool.to_s, :tool]
    elsif workflow then [workflow.to_s, :workflow]
    end

  if impl_name.nil?
    warn "[plugin #{@plugin_id}] capability '#{name}': informe tool: ou workflow: — ignorada"
    return
  end

  if kind == :workflow
    warn "[plugin #{@plugin_id}] capability '#{name}' (kind: workflow) registered without a consumer " \
         "in this slice — agent exposure is follow-up"
  end

  @staged_capabilities << { capability: name, impl_name: impl_name, kind: kind,
                            priority: priority, available: available }
end

#register_channel(name, instance) ⇒ Object

a channel is an INSTANCE (it holds its credentials and its HTTP client), so unlike a tool there is no factory to defer. Declared-or- ignored like the others: the id is a URL segment, and a plugin quietly mounting a route nobody declared is exactly what the contract list prevents.



216
217
218
219
220
221
222
223
224
# File 'lib/insika/plugin/loader.rb', line 216

def register_channel(name, instance)
  name = name.to_s
  unless @channel_names.include?(name)
    warn "[plugin #{@plugin_id}] channel '#{name}' not declared in contracts.channels — ignored"
    return
  end

  @registries[:channels]&.register(name, instance, plugin: @plugin_id)
end

#register_context_provider(instance) ⇒ Object



265
# File 'lib/insika/plugin/loader.rb', line 265

def register_context_provider(instance) = @staged_providers << instance

#register_hook(pair, before: nil, after: nil) ⇒ Object

Validates the pair AT stage time (not only at commit): this way an invalid pair raises INSIDE register(api) -> the staging is discarded and the rollback covers everything. If validation happened only at commit!, middleware/providers would already have been made effective when the bad hook raised.



271
272
273
274
275
276
277
# File 'lib/insika/plugin/loader.rb', line 271

def register_hook(pair, before: nil, after: nil)
  unless Insika::Hooks::PAIRS.include?(pair)
    raise ArgumentError, "unknown hook pair: #{pair.inspect}"
  end

  @staged_hooks << [pair, before, after]
end

#register_middleware(instance) ⇒ Object



264
# File 'lib/insika/plugin/loader.rb', line 264

def register_middleware(instance) = @staged_middleware << instance

#register_policy(name, klass) ⇒ Object



226
227
228
# File 'lib/insika/plugin/loader.rb', line 226

def register_policy(name, klass)
  @registries[:policies].register(name, klass, plugin: @plugin_id)
end

#register_tool(name, klass = nil, &block) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/insika/plugin/loader.rb', line 191

def register_tool(name, klass = nil, &block)
  name = name.to_s
  unless @tool_names.include?(name)
    warn "[plugin #{@plugin_id}] tool '#{name}' not declared in contracts.tools — ignored"
    return
  end
  meta = @tool_metadata[name] || {}
  @registries[:tools].register(name, klass, plugin: @plugin_id,
                                            optional: !!meta["optional"],
                                            side_effect: !!meta["side_effect"], &block)
end

#register_workflow(name, callable = nil, &block) ⇒ Object



203
204
205
206
207
208
209
210
# File 'lib/insika/plugin/loader.rb', line 203

def register_workflow(name, callable = nil, &block)
  name = name.to_s
  unless @workflow_names.include?(name)
    warn "[plugin #{@plugin_id}] workflow '#{name}' not declared in contracts.workflows — ignored"
    return
  end
  @registries[:workflows].register(name, callable, plugin: @plugin_id, &block)
end