ruby_conversations 1.0.9 → 1.0.10

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: 5c9ac759157e0a174601a8eb345c21dc4cb6916408d757a54b2e7ffb44173b01
4
- data.tar.gz: 6357e028b36fc6a1ad772f52ede341d638e393d6b03f9530b5951dfeaa8677da
3
+ metadata.gz: d32de256fcc9a8676794a2da52b5e7f1d6340dee5db4614232b8ffb42dde3bae
4
+ data.tar.gz: d557589614b047b2e33cf5c8ec1e81fdaf8cafc6b605e37084aaad6bbb6cd58f
5
5
  SHA512:
6
- metadata.gz: 2a4f6e671026766297cf3cd4ad9ed0c66c7f4beac979480349447c3b257a69ce88aa8b38ebbf7e5ea1961e29341e749bfea8a4626f743908d64f1ecbd93efd07
7
- data.tar.gz: 6abdb98f3d9df53efb8c12e894c6648417b964733f4a3ac0a0a9d28609a2faf146f7ac30f1aacb2ce71b32bdb85afecce8c46dbed67821fffa76ea2236f4a58a
6
+ metadata.gz: 6412f0ff57642fce95b680e7024c69fa1ec1e20a7718ed93f0370d73d2d5a4d435179b0effd569c7be9720298f4b4d6bda1f6d15873e87b313ff366e6c302da4
7
+ data.tar.gz: 83f0c09530212693fc8e5ada3506a9469c1c07a770d34fc3931cd6a9401f1eca54c48a3f86ccdb66fc4c1765555dd38ae3c62ec9bfc405af8a9aac5a31fd8d81
@@ -6,17 +6,9 @@ module RubyConversations
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  def execute(system_message: nil)
9
- message = messages.last
10
- raise ArgumentError, 'Conversation must have at least one message to execute' unless message
11
-
12
- chat = setup_llm_chat(system_message: system_message)
13
- response = chat.ask(message.request)
14
- update_last_message_response(message, response)
15
- json_response = save_conversation
16
- {
17
- response: response,
18
- conversation: json_response
19
- }
9
+ validate_conversation_state
10
+ response = generate_chat_response(system_message)
11
+ store_and_update_conversation(response)
20
12
  end
21
13
 
22
14
  def llm
@@ -30,6 +22,26 @@ module RubyConversations
30
22
 
31
23
  private
32
24
 
25
+ def validate_conversation_state
26
+ message = messages.last
27
+ raise ArgumentError, 'Conversation must have at least one message to execute' unless message
28
+ end
29
+
30
+ def generate_chat_response(system_message)
31
+ chat = setup_llm_chat(system_message: system_message)
32
+ chat.ask(messages.last.request)
33
+ end
34
+
35
+ def store_and_update_conversation(response)
36
+ update_last_message_response(messages.last, response)
37
+ RubyConversations.client.store_conversation_or_message(self, messages.last)
38
+
39
+ {
40
+ response: response,
41
+ conversation: self
42
+ }
43
+ end
44
+
33
45
  def setup_llm_chat(system_message: nil)
34
46
  configure_llm_credentials
35
47
  build_chat(system_message)
@@ -6,7 +6,7 @@ require_relative '../concerns/ruby_conversations/conversation_messages'
6
6
  require_relative '../concerns/ruby_conversations/llm_credentials'
7
7
  require_relative '../concerns/ruby_conversations/message_validation'
8
8
  require_relative '../concerns/ruby_conversations/message_processing'
9
- require_relative '../concerns/ruby_conversations/storable'
9
+
10
10
  module RubyConversations
11
11
  # Represents a conversation thread, managing messages and interactions with the LLM.
12
12
  class Conversation
@@ -16,7 +16,6 @@ module RubyConversations
16
16
  include LlmCredentials
17
17
  include MessageValidation
18
18
  include MessageProcessing
19
- include Storable
20
19
 
21
20
  # Define attributes needed for API interaction & local state
22
21
  attr_accessor :id, :conversationable_type, :conversationable_id, :conversationable,
@@ -2,26 +2,67 @@
2
2
 
3
3
  require 'faraday'
4
4
  require 'jwt'
5
+ require 'logger'
5
6
 
6
7
  module RubyConversations
7
8
  # HTTP client for interacting with the conversations API
8
9
  class Client
10
+ attr_reader :client
11
+
9
12
  PROMPT_ATTRIBUTES = %w[
10
13
  id name message role temperature valid_placeholders created_at updated_at latest_version_id
11
14
  ].freeze
12
15
 
16
+ # Initialize a new API client
17
+ # @param url [String] The base URL for the API
18
+ # @param jwt_secret [String, #call] The JWT secret or a callable that returns a JWT token
13
19
  def initialize(url:, jwt_secret:)
14
20
  @url = url
15
21
  @jwt_secret = jwt_secret
16
22
  @jwt_token = nil
17
23
  @jwt_expiration = nil
24
+ @logger = Logger.new($stdout)
25
+ @client = build_client
18
26
  end
19
27
 
28
+ # Store a conversation or add a message to an existing conversation
29
+ # @param conversation [Conversation] The conversation to store
30
+ # @param message [Message] The message to store
31
+ # @return [Hash] The API response data
32
+ def store_conversation_or_message(conversation, message)
33
+ if conversation.id.present?
34
+ store_message(conversation, message)
35
+ else
36
+ store_conversation(conversation)
37
+ end
38
+ end
39
+
40
+ # Store a new conversation
41
+ # @param conversation [Conversation] The conversation to store
42
+ # @return [Hash] The API response data
43
+ # @raise [Error] If the API response is missing a conversation ID
20
44
  def store_conversation(conversation)
21
45
  response = client.post('api/ai_conversations', conversation.conversation_attributes_for_storage)
46
+ data = handle_response(response)
47
+ raise RubyConversations::Error, 'API response missing conversation ID' unless data['id'].present?
48
+
49
+ conversation.id = data['id']
50
+ data
51
+ end
52
+
53
+ # Store a message in an existing conversation
54
+ # @param conversation [Conversation] The conversation to add the message to
55
+ # @param message [Message] The message to store
56
+ # @return [Hash] The API response data
57
+ def store_message(conversation, message)
58
+ response = client.post("api/ai_conversations/#{conversation.id}/ai_messages",
59
+ { ai_message: message.attributes_for_api })
22
60
  handle_response(response)
23
61
  end
24
62
 
63
+ # Fetch a prompt by name
64
+ # @param name [String] The name of the prompt to fetch
65
+ # @return [Hash] The prompt attributes
25
66
  def fetch_prompt(name)
26
67
  response = client.get("api/prompts/#{name}")
27
68
  data = handle_response(response)
@@ -36,10 +77,6 @@ module RubyConversations
36
77
  end
37
78
  end
38
79
 
39
- def client
40
- @client ||= build_client
41
- end
42
-
43
80
  def build_client
44
81
  Faraday.new(url: @url) do |faraday|
45
82
  faraday.request :json
@@ -55,7 +92,7 @@ module RubyConversations
55
92
  end
56
93
 
57
94
  def token_expired?
58
- @jwt_token.nil? || @jwt_expiration.nil? || Time.now.to_i >= @jwt_expiration
95
+ [@jwt_token, @jwt_expiration].any?(&:nil?) || Time.now.to_i >= @jwt_expiration
59
96
  end
60
97
 
61
98
  def refresh_jwt
@@ -79,12 +116,10 @@ module RubyConversations
79
116
  end
80
117
 
81
118
  def handle_response(response)
82
- case response.status
83
- when 200, 201
84
- response.body
85
- else
86
- raise Error, "API request failed: #{response.body}"
87
- end
119
+ return response.body if response.success?
120
+
121
+ @logger.error("API request failed: #{response.body.inspect}")
122
+ raise RubyConversations::Error, "API request failed: #{response.body}"
88
123
  end
89
124
  end
90
125
  end
@@ -3,7 +3,7 @@
3
3
  module RubyConversations
4
4
  MAJOR = 1
5
5
  MINOR = 0
6
- PATCH = 9
6
+ PATCH = 10
7
7
 
8
8
  VERSION = "#{RubyConversations::MAJOR}.#{RubyConversations::MINOR}.#{RubyConversations::PATCH}".freeze
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_conversations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Shippy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-10 00:00:00.000000000 Z
11
+ date: 2025-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rubocop-factory_bot
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: rubocop-rails
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -249,7 +263,6 @@ files:
249
263
  - app/models/concerns/ruby_conversations/message_attributes.rb
250
264
  - app/models/concerns/ruby_conversations/message_processing.rb
251
265
  - app/models/concerns/ruby_conversations/message_validation.rb
252
- - app/models/concerns/ruby_conversations/storable.rb
253
266
  - app/models/ruby_conversations/conversation.rb
254
267
  - app/models/ruby_conversations/message.rb
255
268
  - app/models/ruby_conversations/message_builder.rb
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Module for handling storage functionality in Ruby Conversations
5
- # Provides methods for storing and retrieving conversation data
6
- module Storable
7
- extend ActiveSupport::Concern
8
-
9
- def save_conversation
10
- RubyConversations.client.store_conversation(self)
11
- end
12
- end
13
- end