ruby_coded 0.2.0 → 0.2.1

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: 387a789f865a55493f5653662fb9bdd12225b8966be2670ab1ed4cfd281ce410
4
- data.tar.gz: d3d60bf8a6152d966dca9d4d7bd868e16c6df649c75ad8e0639d1774e9e8888b
3
+ metadata.gz: 35cd5d9fc4b17b8a4aa4cefce67e02f6be01053fef3cb73046281804434a3d85
4
+ data.tar.gz: 4b53ca7258244edcc8cb1e7c31dfadc91c2c897b9b24acea3e5cdac21d086485
5
5
  SHA512:
6
- metadata.gz: 74c2dd8fc13a6ed1e9451982931fd4ae61c0343e2df652a753487b9e4a9d43fe08c9266dcc8baabcfd4670c546ae75a01ab36e95dcb0389186752d2b602030d0
7
- data.tar.gz: ea510740d48de995099240d5f1574b7fec383e3a90f4e75b30e4c5fd67975090dc8a7b25475fdced5fe7cec5398a0b01bf38e180ecd5e64b1f98dbb9fe14f1da
6
+ metadata.gz: 00d9c124eeadef16b3492f6c2e394a439cff10a92516afedb053d9626a83d2029d96ceaa1898f8da4f4d4a29ae8c1876ef181f0e20259fb401b30e76a972f341
7
+ data.tar.gz: eb10ce9285ba09b7cf9cd3e24caf6dd28938586328b49e0cb155560ab58697d5e2fbda3ce8da3b61492ba7c23ccd2e8236307f260b1588430cbd63102aee82ff
data/.rubocop_todo.yml CHANGED
@@ -55,10 +55,12 @@ Metrics/AbcSize:
55
55
  Exclude:
56
56
  - 'lib/ruby_coded/chat/state.rb'
57
57
 
58
- # Offense count: 1
58
+ # Offense count: 3
59
59
  # Configuration parameters: CountComments, Max, CountAsOne.
60
60
  Metrics/ClassLength:
61
61
  Exclude:
62
+ - 'lib/ruby_coded/auth/auth_manager.rb'
63
+ - 'lib/ruby_coded/chat/app.rb'
62
64
  - 'lib/ruby_coded/chat/state.rb'
63
65
 
64
66
  # Offense count: 2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.1] - 2026-04-17
4
+
5
+ ### Fixed
6
+
7
+ - **Startup crash when stored model provider is not authenticated**: The CLI no longer raises `RubyLLM::ConfigurationError` at startup when the model saved in `~/.ruby_coded/config.yaml` belongs to a provider that has no credentials on the current machine (e.g. switching computers with only Anthropic authenticated but a GPT model stored). Instead, the app falls back to the default model of the authenticated provider and shows an in-chat system message suggesting `/login` or `/model` to adjust.
8
+
9
+ ### Added
10
+
11
+ - `AuthManager#provider_for_model` and `AuthManager#model_provider_authenticated?` helpers to detect the provider of a given model name and validate that its credentials are available.
12
+
3
13
  ## [0.2.0] - 2026-04-16
4
14
 
5
15
  ### Added
@@ -48,6 +48,23 @@ module RubyCoded
48
48
  PROVIDERS.keys.select { |name| credential_store.retrieve(name) }
49
49
  end
50
50
 
51
+ def provider_for_model(model_name)
52
+ return nil if model_name.nil? || model_name.to_s.strip.empty?
53
+
54
+ normalized = model_name.to_s.downcase
55
+ return :openai if normalized.match?(/\A(gpt|o\d)/)
56
+ return :anthropic if normalized.start_with?("claude")
57
+
58
+ nil
59
+ end
60
+
61
+ def model_provider_authenticated?(model_name)
62
+ provider = provider_for_model(model_name)
63
+ return false unless provider
64
+
65
+ authenticated_provider_names.include?(provider)
66
+ end
67
+
51
68
  def check_authentication
52
69
  return if configured_providers.any? { |name| credential_store.retrieve(name) }
53
70
 
@@ -29,12 +29,18 @@ module RubyCoded
29
29
  include LoginHandler
30
30
  include OAuthHandler
31
31
 
32
- def initialize(model:, user_config: nil, auth_manager: nil)
32
+ def initialize(model:, user_config: nil, auth_manager: nil, fallback_from_model: nil)
33
33
  @model = model
34
34
  @user_config = user_config
35
35
  @auth_manager = auth_manager
36
+ @fallback_from_model = fallback_from_model
36
37
  apply_plugin_extensions!
37
- @state = State.new(model: model)
38
+ build_components!
39
+ announce_model_fallback
40
+ end
41
+
42
+ def build_components!
43
+ @state = State.new(model: @model)
38
44
  @credentials_store = Auth::CredentialsStore.new
39
45
  @llm_bridge = create_bridge
40
46
  @input_handler = InputHandler.new(@state)
@@ -94,6 +100,17 @@ module RubyCoded
94
100
  credentials_store: @credentials_store, auth_manager: @auth_manager)
95
101
  end
96
102
 
103
+ def announce_model_fallback
104
+ return unless @fallback_from_model && !@fallback_from_model.to_s.strip.empty?
105
+ return if @fallback_from_model == @model
106
+
107
+ @state.add_message(
108
+ :system,
109
+ "Model #{@fallback_from_model} is not available (provider not authenticated). " \
110
+ "Switched to #{@model}. Use /login to authenticate or /model to change."
111
+ )
112
+ end
113
+
97
114
  def apply_selected_model
98
115
  selected = @state.selected_model
99
116
  return @state.exit_model_select! unless selected
@@ -20,6 +20,7 @@ module RubyCoded
20
20
  @user_cfg = UserConfig.new
21
21
  @prompt = TTY::Prompt.new
22
22
  @auth_manager = Auth::AuthManager.new
23
+ @fallback_from_model = nil
23
24
 
24
25
  ask_for_directory_permission unless @user_cfg.directory_trusted?
25
26
  @auth_manager.check_authentication
@@ -38,12 +39,22 @@ module RubyCoded
38
39
  end
39
40
 
40
41
  def start_chat
41
- Chat::App.new(model: resolved_chat_model, user_config: @user_cfg, auth_manager: @auth_manager).run
42
+ model = resolved_chat_model
43
+ Chat::App.new(
44
+ model: model,
45
+ user_config: @user_cfg,
46
+ auth_manager: @auth_manager,
47
+ fallback_from_model: @fallback_from_model
48
+ ).run
42
49
  end
43
50
 
44
51
  def resolved_chat_model
45
52
  stored = @user_cfg.get_config("model")
46
- return stored.to_s if stored && !stored.to_s.strip.empty?
53
+ if stored && !stored.to_s.strip.empty?
54
+ return stored.to_s if @auth_manager.model_provider_authenticated?(stored.to_s)
55
+
56
+ @fallback_from_model = stored.to_s
57
+ end
47
58
 
48
59
  provider = @auth_manager.authenticated_provider_names.first
49
60
  PROVIDER_DEFAULT_MODELS.fetch(provider, RubyLLM.config.default_model).to_s
@@ -2,7 +2,7 @@
2
2
 
3
3
  # This module contains the version of the RubyCoded gem
4
4
  module RubyCoded
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.1"
6
6
 
7
7
  def self.gem_version
8
8
  Gem::Version.new(VERSION).freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_coded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cesar Rodriguez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-04-16 00:00:00.000000000 Z
11
+ date: 2026-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday