ask-llm-providers 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf20ba02f9ecd52cdbc18f93ff8a22f75e9d33d845dd80ab7880d35454cd27c0
4
- data.tar.gz: 982162bc42de9c71dfe83dabdd40b69a95b618ead9a056ffcafcaee8c77a5bd7
3
+ metadata.gz: e0a952555ce477b6a2e1ad523112f779a25cd526e0f255a8b6bac78dca33e1c8
4
+ data.tar.gz: 1b90e7fe032a0295fff1a9284045b08bb1a3f82d6c3559b9ecf7f47b7a0d2d0c
5
5
  SHA512:
6
- metadata.gz: f4a361c8bf519e443793c31c4f21dc4f1a5872b4b64f1f7483499f22328a4db091fa6b4e287c0e56ece26777a5ea00e6a3a099c428def8a1cd91a5f61d88a74b
7
- data.tar.gz: 93d0092ed08a53a12be9e822e7f8b4dc889695c39cd3f82f6167422110c8318c0e923b7f1cd1b00aa7104d5fb9f947490a43217ae35af703c570e7a5d8eb918a
6
+ metadata.gz: 57eea3bd9cb97969545688494f37be34cc029e94ea7ee0224efd8041b7534e8b6fab82af2c35f276ef9a7b7f8a64a84edff94972b92508554d37b4dafe556f90
7
+ data.tar.gz: 0fc0ba47aa5437fd38cc0734ca84b15736072d925dea337d3a8f12f2226379c0fa6824e9648829ca5c67860460039457402ec87740690844c89eed97d6c6a3eb
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module LLM
5
- VERSION = "0.1.6"
5
+ VERSION = "0.1.8"
6
6
  end
7
7
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module Providers
5
+ # DeepSeek API — an OpenAI-compatible provider at api.deepseek.com.
6
+ # Supports DeepSeek V2, V3, V4 Chat, R1 reasoning, and all DeepSeek models
7
+ # via the OpenAI-compatible endpoint.
8
+ #
9
+ # Configuration via environment:
10
+ # DEEPSEEK_API_KEY — required, your DeepSeek API key
11
+ # DEEPSEEK_API_BASE — optional, base URL (default: https://api.deepseek.com)
12
+ class DeepSeek < OpenAI
13
+ def api_base
14
+ @config.base_url || ENV["DEEPSEEK_API_BASE"] || "https://api.deepseek.com"
15
+ end
16
+
17
+ def headers
18
+ key = @config.api_key || ENV["DEEPSEEK_API_KEY"]
19
+ h = { "Content-Type" => "application/json" }
20
+ h["Authorization"] = "Bearer #{key}" if key
21
+ h
22
+ end
23
+
24
+ class << self
25
+ def slug; "deepseek"; end
26
+ def configuration_options; %i[api_key base_url]; end
27
+ def configuration_requirements; %i[api_key]; end
28
+ def configured?(config)
29
+ key = config.respond_to?(:api_key) ? config.api_key : nil
30
+ key ||= ENV["DEEPSEEK_API_KEY"]
31
+ key.to_s.length > 0
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -71,16 +71,23 @@ module Ask
71
71
  config.reject { |k, _| known.include?(k.to_sym) }
72
72
  end
73
73
 
74
- # Restore provider-specific keys after normalize_config strips standard ones.
74
+ # Resolve provider config from passed options, env vars, and ask-auth chain.
75
75
  def normalize_config(config)
76
76
  return config if !config.is_a?(Hash)
77
77
 
78
+ slug = self.class.slug
79
+ env_key = ENV["#{slug.upcase}_API_KEY"]
80
+ auth_key = Ask::Auth.resolve(:"#{slug}_api_key") rescue nil
81
+
78
82
  merged = {
79
- api_key: config[:api_key] || config["api_key"] || config[:openai_api_key],
80
- base_url: config[:base_url] || config["base_url"],
83
+ api_key: config[:api_key] || config["api_key"] ||
84
+ config[:"#{slug}_api_key"] || config[:openai_api_key] ||
85
+ env_key || auth_key,
86
+ base_url: config[:base_url] || config["base_url"] ||
87
+ ENV["#{slug.upcase}_API_BASE"],
81
88
  organization_id: config[:organization_id] || config["organization_id"],
82
89
  project_id: config[:project_id] || config["project_id"]
83
- }.merge(@provider_keys)
90
+ }.merge(config.reject { |k, _| %i[api_key base_url organization_id project_id openai_api_key].include?(k.to_sym) })
84
91
 
85
92
  Ask::LLM::Config.new(merged)
86
93
  end
@@ -174,23 +181,3 @@ module Ask
174
181
  end
175
182
  end
176
183
  end
177
-
178
- # When the OpenAI provider is subclassed (e.g. OpenCode), normalize_config
179
- # should also check for env vars matching the subclass slug.
180
- def normalize_config(config)
181
- return config if !config.is_a?(Hash)
182
-
183
- slug = self.class.slug
184
- env_key = ENV["#{slug.upcase}_API_KEY"]
185
- env_base = ENV["#{slug.upcase}_API_BASE"]
186
-
187
- merged = {
188
- api_key: config[:api_key] || config["api_key"] || config[:"#{slug}_api_key"] || config[:"#{slug}_api_key"] || config[:openai_api_key] || env_key,
189
- base_url: config[:base_url] || config["base_url"] || env_base,
190
- organization_id: config[:organization_id] || config["organization_id"],
191
- project_id: config[:project_id] || config["project_id"]
192
- }.merge(config.reject { |k, _| %i[api_key base_url organization_id project_id openai_api_key].include?(k.to_sym) })
193
-
194
- # Also preserve original config for subclass-specific key access
195
- Ask::LLM::Config.new(merged)
196
- end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module Providers
5
+ # OpenRouter API — an OpenAI-compatible aggregator at openrouter.ai.
6
+ # Provides access to many models through a single endpoint.
7
+ #
8
+ # Configuration via environment:
9
+ # OPENROUTER_API_KEY — required, your OpenRouter API key
10
+ # OPENROUTER_API_BASE — optional, base URL (default: https://openrouter.ai/api/v1)
11
+ class OpenRouter < OpenAI
12
+ def api_base
13
+ @config.base_url || ENV["OPENROUTER_API_BASE"] || "https://openrouter.ai/api/v1"
14
+ end
15
+
16
+ def headers
17
+ h = super
18
+ key = @config.api_key || ENV["OPENROUTER_API_KEY"]
19
+ h["Authorization"] = "Bearer #{key}" if key
20
+ h["HTTP-Referer"] = ENV["OPENROUTER_REFERER"] || "https://github.com/ask-rb"
21
+ h["X-Title"] = ENV["OPENROUTER_APP_TITLE"] || "ask-rb"
22
+ h
23
+ end
24
+
25
+ class << self
26
+ def slug; "openrouter"; end
27
+ def configuration_options; %i[api_key base_url]; end
28
+ def configuration_requirements; %i[api_key]; end
29
+ def configured?(config)
30
+ key = config.respond_to?(:api_key) ? config.api_key : nil
31
+ key ||= ENV["OPENROUTER_API_KEY"]
32
+ key.to_s.length > 0
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -23,6 +23,8 @@ require_relative "ask/provider/cloudflare"
23
23
  require_relative "ask/provider/opencode"
24
24
  require_relative "ask/provider/opencode_go"
25
25
  require_relative "ask/provider/mimo"
26
+ require_relative "ask/provider/deepseek"
27
+ require_relative "ask/provider/openrouter"
26
28
 
27
29
  # Register providers with the Ask::Provider registry
28
30
  Ask::Provider.register(:openai, Ask::Providers::OpenAI)
@@ -35,6 +37,8 @@ Ask::Provider.register(:cloudflare, Ask::Providers::Cloudflare)
35
37
  Ask::Provider.register(:opencode, Ask::Providers::OpenCode)
36
38
  Ask::Provider.register(:opencode_go, Ask::Providers::OpenCodeGo)
37
39
  Ask::Provider.register(:mimo, Ask::Providers::Mimo)
40
+ Ask::Provider.register(:deepseek, Ask::Providers::DeepSeek)
41
+ Ask::Provider.register(:openrouter, Ask::Providers::OpenRouter)
38
42
 
39
43
  # Register known models for each provider in the catalog
40
44
  [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-llm-providers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto
@@ -182,6 +182,7 @@ files:
182
182
  - lib/ask/provider/anthropic.rb
183
183
  - lib/ask/provider/bedrock.rb
184
184
  - lib/ask/provider/cloudflare.rb
185
+ - lib/ask/provider/deepseek.rb
185
186
  - lib/ask/provider/google.rb
186
187
  - lib/ask/provider/mimo.rb
187
188
  - lib/ask/provider/mistral.rb
@@ -189,6 +190,7 @@ files:
189
190
  - lib/ask/provider/openai.rb
190
191
  - lib/ask/provider/opencode.rb
191
192
  - lib/ask/provider/opencode_go.rb
193
+ - lib/ask/provider/openrouter.rb
192
194
  - lib/ask/skills/providers.model_select/SKILL.md
193
195
  homepage: https://github.com/ask-rb/ask-llm-providers
194
196
  licenses: