Skip to content

Commit 857eebd

Browse files
committed
[WIP] Create Mock Provider
1 parent 7af1b17 commit 857eebd

File tree

7 files changed

+745
-0
lines changed

7 files changed

+745
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "options"
4+
require_relative "request"
5+
require_relative "embedding_request"
6+
7+
module ActiveAgent
8+
module Providers
9+
module Mock
10+
# Type for Request model
11+
class RequestType < ActiveModel::Type::Value
12+
def cast(value)
13+
case value
14+
when Request
15+
value
16+
when Hash
17+
Request.new(**value.deep_symbolize_keys)
18+
when nil
19+
nil
20+
else
21+
raise ArgumentError, "Cannot cast #{value.class} to Request"
22+
end
23+
end
24+
25+
def serialize(value)
26+
case value
27+
when Request
28+
value.serialize
29+
when Hash
30+
value
31+
when nil
32+
nil
33+
else
34+
raise ArgumentError, "Cannot serialize #{value.class}"
35+
end
36+
end
37+
38+
def deserialize(value)
39+
cast(value)
40+
end
41+
end
42+
43+
# Type for EmbeddingRequest model
44+
class EmbeddingRequestType < ActiveModel::Type::Value
45+
def cast(value)
46+
case value
47+
when EmbeddingRequest
48+
value
49+
when Hash
50+
EmbeddingRequest.new(**value.deep_symbolize_keys)
51+
when nil
52+
nil
53+
else
54+
raise ArgumentError, "Cannot cast #{value.class} to EmbeddingRequest"
55+
end
56+
end
57+
58+
def serialize(value)
59+
case value
60+
when EmbeddingRequest
61+
value.serialize
62+
when Hash
63+
value
64+
when nil
65+
nil
66+
else
67+
raise ArgumentError, "Cannot serialize #{value.class}"
68+
end
69+
end
70+
71+
def deserialize(value)
72+
cast(value)
73+
end
74+
end
75+
end
76+
end
77+
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
require "active_agent/providers/common/model"
4+
5+
module ActiveAgent
6+
module Providers
7+
module Mock
8+
# Embedding request model for Mock provider.
9+
class EmbeddingRequest < Common::BaseModel
10+
attribute :model, :string, default: "mock-embedding-model"
11+
attribute :input # String or array of strings to embed
12+
attribute :encoding_format, :string
13+
attribute :dimensions, :integer
14+
end
15+
end
16+
end
17+
end
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# frozen_string_literal: true
2+
3+
require "active_agent/providers/common/model"
4+
5+
module ActiveAgent
6+
module Providers
7+
module Mock
8+
module Messages
9+
# Assistant message for Mock provider.
10+
#
11+
# Drops extra fields that are part of the API response but not
12+
# part of the message structure (usage, id, model, stop_reason, type, etc).
13+
class Assistant < Common::BaseModel
14+
attribute :role, :string, as: "assistant"
15+
attribute :content # Can be string or array of content blocks
16+
attribute :name, :string
17+
18+
validates :content, presence: true
19+
20+
# Drop API response fields that aren't part of the message
21+
drop_attributes :usage, :id, :model, :stop_reason, :stop_sequence, :type
22+
23+
# Converts to common format.
24+
#
25+
# @return [Hash] message in canonical format with role and text content
26+
def to_common
27+
{
28+
role: role,
29+
content: extract_text_content,
30+
name: name
31+
}
32+
end
33+
34+
private
35+
36+
# Extracts text content from the content field.
37+
#
38+
# @return [String] Extracted text
39+
def extract_text_content
40+
case content
41+
when String
42+
content
43+
when Array
44+
content
45+
.select { |block| block.is_a?(Hash) && block[:type] == "text" }
46+
.map { |block| block[:text] }
47+
.join("\n")
48+
else
49+
content.to_s
50+
end
51+
end
52+
end
53+
end
54+
end
55+
end
56+
end
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
require "active_agent/providers/common/model"
4+
5+
module ActiveAgent
6+
module Providers
7+
module Mock
8+
# Configuration options for the Mock provider.
9+
#
10+
# This provider doesn't make real API calls, so most options are unused.
11+
# Included for consistency with other providers.
12+
class Options < Common::BaseModel
13+
attribute :base_url, :string, default: "https://mock.example.com"
14+
attribute :api_key, :string, default: "mock-api-key"
15+
16+
# Common Interface Compatibility
17+
alias_attribute :access_token, :api_key
18+
19+
def initialize(kwargs = {})
20+
kwargs = kwargs.deep_symbolize_keys if kwargs.respond_to?(:deep_symbolize_keys)
21+
super(**deep_compact(kwargs))
22+
end
23+
24+
def serialize
25+
super
26+
end
27+
end
28+
end
29+
end
30+
end
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# frozen_string_literal: true
2+
3+
require "active_agent/providers/common/model"
4+
require_relative "messages/assistant"
5+
6+
module ActiveAgent
7+
module Providers
8+
module Mock
9+
# Type for Messages array
10+
class MessagesType < ActiveModel::Type::Value
11+
def cast(value)
12+
return [] if value.nil?
13+
return value if value.is_a?(Array) && value.all? { |v| v.is_a?(Messages::Assistant) }
14+
15+
Array(value).map { |msg| cast_message(msg) }.compact
16+
end
17+
18+
def serialize(value)
19+
Array(value).map do |msg|
20+
msg.respond_to?(:serialize) ? msg.serialize : msg
21+
end
22+
end
23+
24+
private
25+
26+
def cast_message(value)
27+
case value
28+
when Messages::Assistant
29+
value
30+
when Hash
31+
role = value[:role]&.to_s || value["role"]&.to_s
32+
case role
33+
when "assistant"
34+
Messages::Assistant.new(**value.deep_symbolize_keys)
35+
else
36+
# For other roles (user, system), just pass through as-is
37+
value.deep_symbolize_keys
38+
end
39+
else
40+
value
41+
end
42+
end
43+
end
44+
45+
# Request model for Mock provider.
46+
#
47+
# Simplified request model that accepts messages and basic parameters.
48+
class Request < Common::BaseModel
49+
# Required parameters
50+
attribute :model, :string, default: "mock-model"
51+
attribute :messages, MessagesType.new
52+
53+
# Optional parameters
54+
attribute :temperature, :float
55+
attribute :max_tokens, :integer
56+
attribute :stream, :boolean, default: false
57+
attribute :tools # Array of tool definitions
58+
attribute :tool_choice # Tool choice configuration
59+
60+
# Common Format Compatibility
61+
def message=(value)
62+
self.messages ||= []
63+
self.messages << value
64+
end
65+
end
66+
end
67+
end
68+
end

0 commit comments

Comments
 (0)