Class: Ask::Agent::Middleware::Pipeline

Inherits:
Object
  • Object
show all
Defined in:
lib/ask/agent/middleware/pipeline.rb

Overview

A composable chain of middleware that wraps an LLM provider.

Middleware are applied in order — the first middleware registered wraps the outermost layer and sees the request first.

Examples:

pipeline = Pipeline.new
pipeline.use :retry_on_failure, max_retries: 5
pipeline.use :log_calls, logger: Rails.logger
pipeline.use :default_settings, temperature: 0.7

result = pipeline.invoke(provider, request) { provider.chat(**request) }

Constant Summary collapse

KNOWN_MIDDLEWARES =
{
  retry_on_failure: "Ask::Agent::Middleware::RetryOnFailure",
  log_calls: "Ask::Agent::Middleware::LogCalls",
  default_settings: "Ask::Agent::Middleware::DefaultSettings"
}.freeze

Instance Method Summary collapse

Constructor Details

#initializePipeline

Returns a new instance of Pipeline.



25
26
27
# File 'lib/ask/agent/middleware/pipeline.rb', line 25

def initialize
  @entries = []
end

Instance Method Details

#configured?Boolean

Returns whether any middleware has been registered.

Returns:

  • (Boolean)

    whether any middleware has been registered



40
41
42
# File 'lib/ask/agent/middleware/pipeline.rb', line 40

def configured?
  @entries.any?
end

#each(&block) ⇒ Object

Iterate over the configured middleware entries.



45
46
47
# File 'lib/ask/agent/middleware/pipeline.rb', line 45

def each(&block)
  @entries.each(&block)
end

#invoke(provider, request) { ... } ⇒ Object

Invoke the middleware chain around a provider call.

Builds a chain of lambdas from the innermost (actual provider) outward, then invokes it. Each middleware's Base#around_request wraps the next link.

Parameters:

  • provider (Object)

    the LLM provider

  • request (Hash)

    the request parameters

Yields:

  • the inner block that calls the provider

Returns:

  • (Object)

    the provider response



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ask/agent/middleware/pipeline.rb', line 59

def invoke(provider, request)
  inner = -> { yield }

  chain = inner
  @entries.reverse_each do |entry|
    instance = entry[:klass].new(**entry[:options])
    current = chain
    chain = -> { instance.around_request(provider, request) { current.call } }
  end

  chain.call
end

#use(middleware, **options) ⇒ Object

Register a middleware in the chain.

Parameters:

  • middleware (Symbol, Class)

    a symbol from KNOWN_MIDDLEWARES or a Middleware::Base subclass

  • options (Hash)

    keyword arguments passed to the middleware's constructor



33
34
35
36
37
# File 'lib/ask/agent/middleware/pipeline.rb', line 33

def use(middleware, **options)
  klass = resolve(middleware)
  @entries << { klass: klass, options: options }
  self
end