Class: CompletionKit::ProviderCredential

Inherits:
ApplicationRecord show all
Includes:
Turbo::Broadcastable
Defined in:
app/models/completion_kit/provider_credential.rb

Constant Summary collapse

PROVIDERS =
%w[openai anthropic ollama openrouter azure_foundry].freeze
PROVIDER_LABELS =
{
  "openai" => "OpenAI",
  "anthropic" => "Anthropic",
  "ollama" => "Ollama / OpenAI-compatible endpoint",
  "openrouter" => "OpenRouter",
  "azure_foundry" => "Azure AI Foundry"
}.freeze

Constants inherited from ApplicationRecord

ApplicationRecord::TenantScopedUniquenessValidator

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.discovery_in_progress?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'app/models/completion_kit/provider_credential.rb', line 65

def self.discovery_in_progress?
  where(discovery_status: "discovering").exists?
end

Instance Method Details

#as_json(options = {}) ⇒ Object



15
16
17
18
19
20
# File 'app/models/completion_kit/provider_credential.rb', line 15

def as_json(options = {})
  {
    id: id, provider: provider, api_endpoint: api_endpoint, api_version: api_version,
    created_at: created_at, updated_at: updated_at
  }
end

#available_modelsObject



49
50
51
52
53
# File 'app/models/completion_kit/provider_credential.rb', line 49

def available_models
  LlmClient.for_provider(provider, config_hash).available_models
rescue StandardError
  []
end

#azure_foundry?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'app/models/completion_kit/provider_credential.rb', line 36

def azure_foundry?
  provider == "azure_foundry"
end

#broadcast_discovery_completeObject



113
114
115
116
# File 'app/models/completion_kit/provider_credential.rb', line 113

def broadcast_discovery_complete
  broadcast_discovery_progress
  broadcast_model_dropdowns
end

#broadcast_discovery_progressObject



102
103
104
105
106
107
108
109
110
111
# File 'app/models/completion_kit/provider_credential.rb', line 102

def broadcast_discovery_progress
  safely_broadcast do
    broadcast_replace_to(
      "completion_kit_provider_#{id}",
      target: "discovery_status_#{id}",
      html: render_partial("completion_kit/provider_credentials/discovery_status", provider_credential: self)
    )
  end
  broadcast_provider_models
end

#broadcast_provider_modelsObject



118
119
120
121
122
123
124
125
126
127
128
# File 'app/models/completion_kit/provider_credential.rb', line 118

def broadcast_provider_models
  safely_broadcast do
    Turbo::StreamsChannel.broadcast_action_to(
      "completion_kit_provider_#{id}",
      action: "replace",
      target: "provider_models_#{id}",
      method: "morph",
      html: render_partial("completion_kit/provider_credentials/models_card", provider_credential: self)
    )
  end
end

#config_hashObject



40
41
42
43
44
45
46
47
# File 'app/models/completion_kit/provider_credential.rb', line 40

def config_hash
  {
    provider: provider,
    api_key: api_key,
    api_endpoint: api_endpoint,
    api_version: api_version
  }.compact
end

#configured?Boolean

Returns:

  • (Boolean)


55
56
57
58
59
# File 'app/models/completion_kit/provider_credential.rb', line 55

def configured?
  LlmClient.for_provider(provider, config_hash).configured?
rescue StandardError
  false
end

#display_providerObject



22
23
24
# File 'app/models/completion_kit/provider_credential.rb', line 22

def display_provider
  PROVIDER_LABELS[provider] || provider.titleize
end

#in_use?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'app/models/completion_kit/provider_credential.rb', line 91

def in_use?
  prompt_count.positive? || judge_count.positive?
end

#in_use_messageObject



95
96
97
98
99
100
# File 'app/models/completion_kit/provider_credential.rb', line 95

def in_use_message
  parts = []
  parts << "#{prompt_count} #{'prompt'.pluralize(prompt_count)}" if prompt_count.positive?
  parts << "#{judge_count} judge #{'run'.pluralize(judge_count)}" if judge_count.positive?
  "#{display_provider} is still in use by #{parts.to_sentence}. Remove those references before deleting it."
end

#judge_countObject



75
76
77
78
79
# File 'app/models/completion_kit/provider_credential.rb', line 75

def judge_count
  model_ids = Model.where(provider: provider).pluck(:model_id)
  return 0 if model_ids.empty?
  Run.where(judge_model: model_ids).distinct.count(:judge_model)
end

#last_used_atObject



81
82
83
84
85
86
87
88
89
# File 'app/models/completion_kit/provider_credential.rb', line 81

def last_used_at
  model_ids = Model.where(provider: provider).pluck(:model_id)
  return nil if model_ids.empty?
  prompt_scope = Prompt.where(llm_model: model_ids).select(:id)
  Run.where("prompt_id IN (:prompts) OR judge_model IN (:models)",
            prompts: prompt_scope, models: model_ids)
     .where.not(status: "pending")
     .maximum(:created_at)
end

#model_countObject



61
62
63
# File 'app/models/completion_kit/provider_credential.rb', line 61

def model_count
  Model.where(provider: provider).active.count
end

#prompt_countObject



69
70
71
72
73
# File 'app/models/completion_kit/provider_credential.rb', line 69

def prompt_count
  model_ids = Model.where(provider: provider).pluck(:model_id)
  return 0 if model_ids.empty?
  Prompt.where(llm_model: model_ids, current: true).count
end