Module: Relay::Concerns::Context

Included in:
Pages::Base, Router, Routes::Base
Defined in:
app/concerns/context.rb

Overview

Shared Relay provider, model, and persisted context selection.

This concern centralizes the session-backed logic for resolving the current provider, chat model, and Relay::Models::Context so pages and routes stay in sync.

Instance Method Summary collapse

Instance Method Details

#contextsArray<Relay::Models::Context>

Returns Saved contexts for the current user and provider, newest first.

Returns:



46
47
48
49
50
51
52
# File 'app/concerns/context.rb', line 46

def contexts
  @contexts ||= Relay::Models::Context.where(user_id: user.id, provider:)
    .reverse_order(:updated_at)
    .all
    .select { valid_model?(_1[:model]) }
    .select { _1.messages.any? }
end

#ctxRelay::Models::Context

Returns The active persisted context for the current user and provider.

Returns:



36
37
38
39
40
41
# File 'app/concerns/context.rb', line 36

def ctx
  @ctx ||= begin
    context = current_context || default_context
    sync_context!(context)
  end
end

#current_contextRelay::Models::Context?

Returns The currently selected context for the session, if it matches the current provider.

Returns:

  • (Relay::Models::Context, nil)

    The currently selected context for the session, if it matches the current provider.



67
68
69
70
71
72
73
# File 'app/concerns/context.rb', line 67

def current_context
  return unless session["context_id"]
  context = Relay::Models::Context.where(user_id: user.id, provider:, id: session["context_id"]).first
  return context if context && valid_model?(context[:model])
  session.delete("context_id")
  nil
end

#default_contextRelay::Models::Context

Returns The default context for the current provider/model selection.

Returns:



78
79
80
81
82
# File 'app/concerns/context.rb', line 78

def default_context
  Relay::Models::Context.where(user_id: user.id, provider:, model:)
    .reverse_order(:updated_at)
    .first || Relay::Models::Context.create(user_id: user.id, provider:, model:)
end

#default_modelString

Returns the default chat model for the current provider.

Returns:

  • (String)

    Returns the default chat model for the current provider.



116
117
118
119
120
121
122
123
# File 'app/concerns/context.rb', line 116

def default_model
  case (provider = llms.fetch(self.provider)).name
  when :deepseek then "deepseek-v4-flash"
  when :openai then "gpt-5.4"
  when :xai then "grok-3"
  else provider.default_model
  end
end

#llmLLM::Provider

Returns The selected provider object.

Returns:

  • (LLM::Provider)

    The selected provider object.



29
30
31
# File 'app/concerns/context.rb', line 29

def llm
  ctx.llm
end

#llmsHash<String, LLM::Provider>

Returns A map of initialized LLM providers.

Returns:

  • (Hash<String, LLM::Provider>)

    A map of initialized LLM providers.



96
97
98
99
100
101
102
103
104
# File 'app/concerns/context.rb', line 96

def llms
  @llms ||= {
    "openai" => LLM.openai(key: ENV["OPENAI_SECRET"]),
    "google" => LLM.google(key: ENV["GOOGLE_SECRET"]),
    "anthropic" => LLM.anthropic(key: ENV["ANTHROPIC_SECRET"]),
    "deepseek" => LLM.deepseek(key: ENV["DEEPSEEK_SECRET"]),
    "xai" => LLM.xai(key: ENV["XAI_SECRET"])
  }.transform_values(&:persist!)
end

#mcpsArray<Relay::Models::MCP>

Returns Saved MCP servers for the current user, newest first.

Returns:



57
58
59
60
61
# File 'app/concerns/context.rb', line 57

def mcps
  @mcps ||= user ? Relay::Models::MCP.summary_dataset(user.mcps_dataset).
    reverse_order(:created_at).
    all : []
end

#modelString?

Returns The requested model.

Returns:

  • (String, nil)

    The requested model.



22
23
24
# File 'app/concerns/context.rb', line 22

def model
  session["model"] = normalize_model(session["model"])
end

#modelsArray<Relay::Models::ModelRecord>

Returns Models for the current provider.

Returns:



109
110
111
# File 'app/concerns/context.rb', line 109

def models
  Relay::Models::ModelRecord.where(provider:).order(:name).all
end

#normalize_model(id) ⇒ String

Parameters:

  • id (String, nil)

Returns:

  • (String)


135
136
137
138
# File 'app/concerns/context.rb', line 135

def normalize_model(id)
  return id if id && valid_model?(id)
  default_model
end

#providerString

Returns The requested provider, defaulting to deepseek.

Returns:

  • (String)

    The requested provider, defaulting to deepseek.



15
16
17
# File 'app/concerns/context.rb', line 15

def provider
  session["provider"] || "deepseek"
end

#sync_context!(context) ⇒ Relay::Models::Context

Parameters:

Returns:



87
88
89
90
91
# File 'app/concerns/context.rb', line 87

def sync_context!(context)
  session["context_id"] = context.id
  session["model"] = normalize_model(context[:model])
  context
end

#userRelay::Models::User?

Returns:



142
143
144
# File 'app/concerns/context.rb', line 142

def user
  @user ||= Relay::Models::User[session["user_id"]] if session["user_id"]
end

#valid_model?(id) ⇒ Boolean

Parameters:

  • id (String, nil)

Returns:

  • (Boolean)


128
129
130
# File 'app/concerns/context.rb', line 128

def valid_model?(id)
  models.any? { _1.model_id == id }
end