ruby_conversations 1.0.9 → 1.0.11

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: 247b000cfed0f52453c93f9ba188a79a3b09e0e7d96dbb6866faee48e2f33386
4
+ data.tar.gz: d65f04b9333a3afecf5b05e7ddd51b030a7a0f9974d4cee84fa212216b68d140
5
5
  SHA512:
6
- metadata.gz: 2a4f6e671026766297cf3cd4ad9ed0c66c7f4beac979480349447c3b257a69ce88aa8b38ebbf7e5ea1961e29341e749bfea8a4626f743908d64f1ecbd93efd07
7
- data.tar.gz: 6abdb98f3d9df53efb8c12e894c6648417b964733f4a3ac0a0a9d28609a2faf146f7ac30f1aacb2ce71b32bdb85afecce8c46dbed67821fffa76ea2236f4a58a
6
+ metadata.gz: 6ec989c1dd0510d247dbdc329b64af6c729ea60347cf1011edc73fbeed465c00f53f09819ae6dc7af767f47e0f99520c535af267225826261241198317764c76
7
+ data.tar.gz: e02836afeeb708033c85f83001ce40d79798cf70fe1cdb6e1b8d586f65106b520f73f23f67055e91f23adc20e7f1b61c5b2171caf1be5c3eba13d4f6e1d858db
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles chat-related functionality for Conversation
6
+ module ConversationChat
7
+ extend ActiveSupport::Concern
8
+
9
+ def execute(system_message: nil)
10
+ validate_conversation_state
11
+ response = generate_chat_response(system_message)
12
+ store_and_update_conversation(response)
13
+ end
14
+
15
+ def llm
16
+ case model_identifier
17
+ when 'claude-3-7-sonnet'
18
+ 'us.anthropic.claude-3-sonnet-20250219-v1:0'
19
+ else
20
+ model_identifier
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def validate_conversation_state
27
+ message = messages.last
28
+ raise ArgumentError, 'Conversation must have at least one message to execute' unless message
29
+ end
30
+
31
+ def generate_chat_response(system_message)
32
+ chat = setup_llm_chat(system_message: system_message)
33
+ chat.ask(messages.last.request)
34
+ end
35
+
36
+ def store_and_update_conversation(response)
37
+ update_last_message_response(messages.last, response)
38
+ RubyConversations.client.store_conversation_or_message(self, messages.last)
39
+
40
+ {
41
+ response: response,
42
+ conversation: self
43
+ }
44
+ end
45
+
46
+ def setup_llm_chat(system_message: nil)
47
+ configure_llm_credentials
48
+ build_chat(system_message)
49
+ end
50
+
51
+ def update_last_message_response(message, response)
52
+ message.response = response.to_h.to_json
53
+ end
54
+
55
+ def build_chat(system_message)
56
+ chat = RubyLLM.chat(model: llm, provider: provider).with_temperature(0.0)
57
+ chat.with_tool(tool) if tool.present?
58
+ chat.add_message(role: :system, content: system_message) if system_message.present?
59
+ chat
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles message-related functionality for Conversation
6
+ module ConversationMessages
7
+ extend ActiveSupport::Concern
8
+
9
+ def initialize_messages(message_attributes)
10
+ (message_attributes || []).each do |msg_data|
11
+ processed_prompts = process_message_prompts(msg_data)
12
+
13
+ message_instance = RubyConversations::Message.new(msg_data.except('id', 'conversation_id', 'created_at',
14
+ 'updated_at'))
15
+ message_instance.message_prompts = processed_prompts
16
+ @messages << message_instance # Add to the messages array
17
+ end
18
+ end
19
+
20
+ def ask_multiple(prompt_inputs, description: nil)
21
+ MessageBuilder.new(self).build_from_multiple_prompts(prompt_inputs, description: description)
22
+ self
23
+ end
24
+
25
+ def ask(name, description: nil, inputs: {})
26
+ MessageBuilder.new(self).build_from_single_prompt(name, description: description, inputs: inputs)
27
+ self
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles the management of LLM credentials for AI conversations.
6
+ # This concern provides methods for configuring LLM credentials from either
7
+ # environment variables or an AWS credential provider.
8
+ module LlmCredentials
9
+ extend ActiveSupport::Concern
10
+
11
+ private
12
+
13
+ def configure_llm_credentials
14
+ RubyLLM.configure do |config|
15
+ credentials = ENV['AWS_ACCESS_KEY_ID'].present? ? env_credentials : provider_credentials
16
+ config.bedrock_region = ENV.fetch('AWS_REGION', 'us-west-2')
17
+ config.bedrock_api_key = credentials[:api_key]
18
+ config.bedrock_secret_key = credentials[:secret_key]
19
+ config.bedrock_session_token = credentials[:session_token]
20
+ end
21
+ end
22
+
23
+ def env_credentials
24
+ {
25
+ api_key: ENV.fetch('AWS_ACCESS_KEY_ID', nil),
26
+ secret_key: ENV.fetch('AWS_SECRET_ACCESS_KEY', nil),
27
+ session_token: ENV.fetch('AWS_SESSION_TOKEN', nil)
28
+ }
29
+ end
30
+
31
+ def provider_credentials
32
+ credential_provider = AwsCredentialProvider.instance
33
+ credential_provider.refresh_if_expired!
34
+ {
35
+ api_key: credential_provider.access_key_id,
36
+ secret_key: credential_provider.secret_access_key,
37
+ session_token: credential_provider.session_token
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles API-related attribute functionality for Message
6
+ module MessageApiAttributes
7
+ extend ActiveSupport::Concern
8
+
9
+ def message_attributes_for_api
10
+ {
11
+ request: request,
12
+ response: response,
13
+ model_identifier: model_identifier,
14
+ change_description: change_description,
15
+ llm: llm
16
+ }.compact
17
+ end
18
+
19
+ def message_base_attributes
20
+ {
21
+ 'request' => request,
22
+ 'response' => response,
23
+ 'model_identifier' => model_identifier,
24
+ 'change_description' => change_description
25
+ }
26
+ end
27
+
28
+ def remote_attributes
29
+ base_attributes.compact
30
+ end
31
+
32
+ private
33
+
34
+ def base_attributes
35
+ RubyConversations::Concerns::MessageAttributes::ATTRIBUTE_NAMES.each_with_object({}) do |attr_name, attrs|
36
+ attrs[attr_name] = public_send(attr_name)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles attribute-related functionality for Message
6
+ module MessageAttributes
7
+ extend ActiveSupport::Concern
8
+
9
+ ATTRIBUTE_NAMES = %w[
10
+ id ai_conversation_id request response model_identifier
11
+ tool change_description llm created_at updated_at
12
+ ].freeze
13
+
14
+ included do
15
+ # Define core message attributes
16
+ attr_accessor :request, :response, :model_identifier, :change_description
17
+
18
+ # Define relationship attributes
19
+ attr_accessor :ai_conversation, :message_prompts, :prompts
20
+
21
+ # Common validations
22
+ validates :llm, presence: true
23
+ validates :request, presence: true
24
+
25
+ # Override initialize to ensure arrays are initialized
26
+ def initialize(attributes = {})
27
+ @message_prompts = []
28
+ @prompts = []
29
+ super
30
+ end
31
+ end
32
+
33
+ def remote_attributes
34
+ base_attributes.compact
35
+ end
36
+
37
+ private
38
+
39
+ def base_attributes
40
+ ATTRIBUTE_NAMES.each_with_object({}) do |attr_name, attrs|
41
+ attrs[attr_name] = public_send(attr_name)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles message processing functionality for Conversation
6
+ module MessageProcessing
7
+ extend ActiveSupport::Concern
8
+
9
+ def process_message_prompts(message_data)
10
+ prompts_data = extract_prompts_data(message_data)
11
+ return [] unless prompts_data
12
+
13
+ prompts_data.map do |prompt_data|
14
+ process_single_prompt(prompt_data)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def extract_prompts_data(message_data)
21
+ message_data['message_prompts'] ||
22
+ message_data[:message_prompts] ||
23
+ message_data['ai_message_prompts_attributes'] ||
24
+ message_data[:ai_message_prompts_attributes]
25
+ end
26
+
27
+ def process_single_prompt(prompt_data)
28
+ inputs_data = extract_inputs_data(prompt_data)
29
+ prompt_instance = RubyConversations::MessagePrompt.new(
30
+ prompt_data.except('id', 'message_id', 'created_at', 'updated_at')
31
+ )
32
+
33
+ process_prompt_inputs(prompt_instance, inputs_data)
34
+ prompt_instance
35
+ end
36
+
37
+ def extract_inputs_data(prompt_data)
38
+ prompt_data['message_inputs'] ||
39
+ prompt_data[:message_inputs] ||
40
+ prompt_data['ai_message_inputs_attributes'] ||
41
+ prompt_data[:ai_message_inputs_attributes] || []
42
+ end
43
+
44
+ def process_prompt_inputs(prompt_instance, inputs_data)
45
+ inputs_data.each do |input_data|
46
+ input_instance = RubyConversations::MessageInput.new(
47
+ input_data.except('id', 'message_prompt_id', 'created_at', 'updated_at')
48
+ )
49
+ prompt_instance.message_inputs << input_instance
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyConversations
4
+ module Concerns
5
+ # Handles validation-related functionality for Message
6
+ module MessageValidation
7
+ extend ActiveSupport::Concern
8
+
9
+ private
10
+
11
+ def validate_messages
12
+ messages.each do |message|
13
+ next if message.valid?
14
+
15
+ message.errors.full_messages.each do |msg|
16
+ errors.add(:messages, "invalid: #{msg}")
17
+ end
18
+ end
19
+ end
20
+
21
+ def validate_message_level(message)
22
+ return if message.valid?
23
+
24
+ message.errors.full_messages.each do |msg|
25
+ errors.add(:base, "Message error: #{msg}")
26
+ end
27
+ end
28
+
29
+ def validate_prompt_level(prompt)
30
+ return if prompt.valid?
31
+
32
+ prompt.errors.full_messages.each do |msg|
33
+ errors.add(:base, "Message prompt error: #{msg}")
34
+ end
35
+ end
36
+
37
+ def validate_input_level(input)
38
+ return if input.valid?
39
+
40
+ input.errors.full_messages.each do |msg|
41
+ errors.add(:base, "Message prompt input error: #{msg}")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,22 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_model'
4
- require_relative '../concerns/ruby_conversations/conversation_chat'
5
- require_relative '../concerns/ruby_conversations/conversation_messages'
6
- require_relative '../concerns/ruby_conversations/llm_credentials'
7
- require_relative '../concerns/ruby_conversations/message_validation'
8
- require_relative '../concerns/ruby_conversations/message_processing'
9
- require_relative '../concerns/ruby_conversations/storable'
4
+
10
5
  module RubyConversations
11
6
  # Represents a conversation thread, managing messages and interactions with the LLM.
12
7
  class Conversation
13
8
  include ActiveModel::Model
14
- include ConversationChat
15
- include ConversationMessages
16
- include LlmCredentials
17
- include MessageValidation
18
- include MessageProcessing
19
- include Storable
9
+ include RubyConversations::Concerns::ConversationChat
10
+ include RubyConversations::Concerns::ConversationMessages
11
+ include RubyConversations::Concerns::LlmCredentials
12
+ include RubyConversations::Concerns::MessageValidation
13
+ include RubyConversations::Concerns::MessageProcessing
20
14
 
21
15
  # Define attributes needed for API interaction & local state
22
16
  attr_accessor :id, :conversationable_type, :conversationable_id, :conversationable,
@@ -1,16 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_model'
4
- require_relative 'message_prompt'
5
- require_relative '../concerns/ruby_conversations/message_attributes'
6
- require_relative '../concerns/ruby_conversations/message_api_attributes'
7
4
 
8
5
  module RubyConversations
9
6
  # Represents a message in a conversation, either from the user or AI
10
7
  class Message
11
8
  include ActiveModel::Model
12
- include MessageAttributes
13
- include MessageApiAttributes
9
+ include Concerns::MessageAttributes
10
+ include Concerns::MessageApiAttributes
14
11
 
15
12
  # Define attributes
16
13
  attr_accessor :id, :conversation_id, :llm,
@@ -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 = 11
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.11
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
@@ -242,14 +256,13 @@ extensions: []
242
256
  extra_rdoc_files: []
243
257
  files:
244
258
  - README.md
245
- - app/models/concerns/ruby_conversations/conversation_chat.rb
246
- - app/models/concerns/ruby_conversations/conversation_messages.rb
247
- - app/models/concerns/ruby_conversations/llm_credentials.rb
248
- - app/models/concerns/ruby_conversations/message_api_attributes.rb
249
- - app/models/concerns/ruby_conversations/message_attributes.rb
250
- - app/models/concerns/ruby_conversations/message_processing.rb
251
- - app/models/concerns/ruby_conversations/message_validation.rb
252
- - app/models/concerns/ruby_conversations/storable.rb
259
+ - app/models/ruby_conversations/concerns/conversation_chat.rb
260
+ - app/models/ruby_conversations/concerns/conversation_messages.rb
261
+ - app/models/ruby_conversations/concerns/llm_credentials.rb
262
+ - app/models/ruby_conversations/concerns/message_api_attributes.rb
263
+ - app/models/ruby_conversations/concerns/message_attributes.rb
264
+ - app/models/ruby_conversations/concerns/message_processing.rb
265
+ - app/models/ruby_conversations/concerns/message_validation.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,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Handles chat-related functionality for Conversation
5
- module ConversationChat
6
- extend ActiveSupport::Concern
7
-
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
- }
20
- end
21
-
22
- def llm
23
- case model_identifier
24
- when 'claude-3-7-sonnet'
25
- 'us.anthropic.claude-3-7-sonnet-20250219-v1:0'
26
- else
27
- model_identifier
28
- end
29
- end
30
-
31
- private
32
-
33
- def setup_llm_chat(system_message: nil)
34
- configure_llm_credentials
35
- build_chat(system_message)
36
- end
37
-
38
- def update_last_message_response(message, response)
39
- message.response = response.to_h.to_json
40
- end
41
-
42
- def build_chat(system_message)
43
- chat = RubyLLM.chat(model: llm, provider: provider).with_temperature(0.0)
44
- chat.with_tool(tool) if tool.present?
45
- chat.add_message(role: :system, content: system_message) if system_message.present?
46
- chat
47
- end
48
- end
49
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Handles message-related functionality for Conversation
5
- module ConversationMessages
6
- extend ActiveSupport::Concern
7
-
8
- def ask_multiple(prompt_inputs, description: nil)
9
- MessageBuilder.new(self).build_from_multiple_prompts(prompt_inputs, description: description)
10
- self
11
- end
12
-
13
- def ask(name, description: nil, inputs: {})
14
- MessageBuilder.new(self).build_from_single_prompt(name, description: description, inputs: inputs)
15
- self
16
- end
17
- end
18
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Handles the management of LLM credentials for AI conversations.
5
- # This concern provides methods for configuring LLM credentials from either
6
- # environment variables or an AWS credential provider.
7
- module LlmCredentials
8
- extend ActiveSupport::Concern
9
-
10
- private
11
-
12
- def configure_llm_credentials
13
- RubyLLM.configure do |config|
14
- credentials = ENV['AWS_ACCESS_KEY_ID'].present? ? env_credentials : provider_credentials
15
- config.bedrock_region = ENV.fetch('AWS_REGION', 'us-west-2')
16
- config.bedrock_api_key = credentials[:api_key]
17
- config.bedrock_secret_key = credentials[:secret_key]
18
- config.bedrock_session_token = credentials[:session_token]
19
- end
20
- end
21
-
22
- def env_credentials
23
- {
24
- api_key: ENV.fetch('AWS_ACCESS_KEY_ID', nil),
25
- secret_key: ENV.fetch('AWS_SECRET_ACCESS_KEY', nil),
26
- session_token: ENV.fetch('AWS_SESSION_TOKEN', nil)
27
- }
28
- end
29
-
30
- def provider_credentials
31
- credential_provider = AwsCredentialProvider.instance
32
- credential_provider.refresh_if_expired!
33
- {
34
- api_key: credential_provider.access_key_id,
35
- secret_key: credential_provider.secret_access_key,
36
- session_token: credential_provider.session_token
37
- }
38
- end
39
- end
40
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Handles API-related attribute functionality for Message
5
- module MessageApiAttributes
6
- extend ActiveSupport::Concern
7
-
8
- def message_attributes_for_api
9
- {
10
- request: request,
11
- response: response,
12
- model_identifier: model_identifier,
13
- change_description: change_description,
14
- llm: llm
15
- }.compact
16
- end
17
-
18
- def message_base_attributes
19
- {
20
- 'request' => request,
21
- 'response' => response,
22
- 'model_identifier' => model_identifier,
23
- 'change_description' => change_description
24
- }
25
- end
26
-
27
- def remote_attributes
28
- base_attributes.compact
29
- end
30
-
31
- private
32
-
33
- def base_attributes
34
- MessageAttributes::ATTRIBUTE_NAMES.each_with_object({}) do |attr_name, attrs|
35
- attrs[attr_name] = public_send(attr_name)
36
- end
37
- end
38
- end
39
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Handles attribute-related functionality for Message
5
- module MessageAttributes
6
- extend ActiveSupport::Concern
7
-
8
- ATTRIBUTE_NAMES = %w[
9
- id ai_conversation_id request response model_identifier
10
- tool change_description llm created_at updated_at
11
- ].freeze
12
-
13
- included do
14
- # Define core message attributes
15
- attr_accessor :request, :response, :model_identifier, :change_description
16
-
17
- # Define relationship attributes
18
- attr_accessor :ai_conversation, :message_prompts, :prompts
19
-
20
- # Common validations
21
- validates :llm, presence: true
22
- validates :request, presence: true
23
-
24
- # Override initialize to ensure arrays are initialized
25
- def initialize(attributes = {})
26
- @message_prompts = []
27
- @prompts = []
28
- super
29
- end
30
- end
31
-
32
- def remote_attributes
33
- base_attributes.compact
34
- end
35
-
36
- private
37
-
38
- def base_attributes
39
- ATTRIBUTE_NAMES.each_with_object({}) do |attr_name, attrs|
40
- attrs[attr_name] = public_send(attr_name)
41
- end
42
- end
43
- end
44
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Handles message processing and initialization logic
5
- module MessageProcessing
6
- extend ActiveSupport::Concern
7
-
8
- private
9
-
10
- def process_message_prompts(msg_data)
11
- prompts_data = extract_prompts_data(msg_data)
12
- prompts_data.map { |prompt_data| build_message_prompt(prompt_data) }
13
- end
14
-
15
- def extract_prompts_data(msg_data)
16
- prompts_data = msg_data.delete(:prompts) ||
17
- msg_data.delete(:message_prompts) ||
18
- msg_data.delete('message_prompts') ||
19
- msg_data.delete(:ai_message_prompts_attributes) ||
20
- msg_data.delete('ai_message_prompts_attributes')
21
- prompts_data || []
22
- end
23
-
24
- def build_message_prompt(prompt_data)
25
- inputs_data = extract_inputs_data(prompt_data)
26
- processed_inputs = inputs_data.map { |input_data| build_message_input(input_data) }
27
-
28
- prompt_instance = RubyConversations::MessagePrompt.new(
29
- prompt_data.except('id', 'message_id', 'created_at', 'updated_at')
30
- )
31
- prompt_instance.message_inputs = processed_inputs
32
- prompt_instance
33
- end
34
-
35
- def extract_inputs_data(prompt_data)
36
- inputs_data = prompt_data.delete(:inputs) ||
37
- prompt_data.delete(:message_inputs) ||
38
- prompt_data.delete('message_inputs')
39
- inputs_data || []
40
- end
41
-
42
- def build_message_input(input_data)
43
- RubyConversations::MessageInput.new(
44
- input_data.except('id', 'message_prompt_id', 'created_at', 'updated_at')
45
- )
46
- end
47
- end
48
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyConversations
4
- # Provides validation methods for AI conversation messages, prompts, and inputs.
5
- # This concern handles the validation of the message hierarchy in AI conversations,
6
- # ensuring that all messages, their prompts, and inputs are valid.
7
- module MessageValidation
8
- extend ActiveSupport::Concern
9
-
10
- private
11
-
12
- def validate_messages
13
- messages.each do |message|
14
- validate_message_level(message)
15
- message.ai_message_prompts.each do |prompt|
16
- validate_prompt_level(prompt)
17
- prompt.message_inputs.each do |input|
18
- validate_input_level(input)
19
- end
20
- end
21
- end
22
- end
23
-
24
- def validate_message_level(message)
25
- return if message.valid?
26
-
27
- message.errors.full_messages.each do |msg|
28
- errors.add(:base, "Message error: #{msg}")
29
- end
30
- end
31
-
32
- def validate_prompt_level(prompt)
33
- return if prompt.valid?
34
-
35
- prompt.errors.full_messages.each do |msg|
36
- errors.add(:base, "Message prompt error: #{msg}")
37
- end
38
- end
39
-
40
- def validate_input_level(input)
41
- return if input.valid?
42
-
43
- input.errors.full_messages.each do |msg|
44
- errors.add(:base, "Message prompt input error: #{msg}")
45
- end
46
- end
47
- end
48
- end
@@ -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