soka 0.0.1.beta2
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +365 -0
- data/CHANGELOG.md +31 -0
- data/CLAUDE.md +213 -0
- data/LICENSE +21 -0
- data/README.md +650 -0
- data/Rakefile +10 -0
- data/examples/1_basic.rb +94 -0
- data/examples/2_event_handling.rb +120 -0
- data/examples/3_memory.rb +182 -0
- data/examples/4_hooks.rb +140 -0
- data/examples/5_error_handling.rb +85 -0
- data/examples/6_retry.rb +164 -0
- data/examples/7_tool_conditional.rb +180 -0
- data/examples/8_multi_provider.rb +112 -0
- data/lib/soka/agent.rb +130 -0
- data/lib/soka/agent_tool.rb +146 -0
- data/lib/soka/agent_tools/params_validator.rb +139 -0
- data/lib/soka/agents/dsl_methods.rb +140 -0
- data/lib/soka/agents/hook_manager.rb +68 -0
- data/lib/soka/agents/llm_builder.rb +32 -0
- data/lib/soka/agents/retry_handler.rb +74 -0
- data/lib/soka/agents/tool_builder.rb +78 -0
- data/lib/soka/configuration.rb +60 -0
- data/lib/soka/engines/base.rb +67 -0
- data/lib/soka/engines/concerns/prompt_template.rb +130 -0
- data/lib/soka/engines/concerns/response_processor.rb +103 -0
- data/lib/soka/engines/react.rb +136 -0
- data/lib/soka/engines/reasoning_context.rb +92 -0
- data/lib/soka/llm.rb +85 -0
- data/lib/soka/llms/anthropic.rb +124 -0
- data/lib/soka/llms/base.rb +114 -0
- data/lib/soka/llms/concerns/response_parser.rb +47 -0
- data/lib/soka/llms/concerns/streaming_handler.rb +78 -0
- data/lib/soka/llms/gemini.rb +106 -0
- data/lib/soka/llms/openai.rb +97 -0
- data/lib/soka/memory.rb +83 -0
- data/lib/soka/result.rb +136 -0
- data/lib/soka/test_helpers.rb +162 -0
- data/lib/soka/thoughts_memory.rb +112 -0
- data/lib/soka/version.rb +5 -0
- data/lib/soka.rb +49 -0
- data/sig/soka.rbs +4 -0
- metadata +158 -0
data/lib/soka/result.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soka
|
4
|
+
# Represents the result of an agent's reasoning process
|
5
|
+
class Result
|
6
|
+
attr_reader :input, :thoughts, :final_answer, :confidence_score, :status, :error, :execution_time
|
7
|
+
|
8
|
+
# Initialize a new Result instance
|
9
|
+
# @param attributes [Hash] Result attributes
|
10
|
+
# @option attributes [String] :input The original input
|
11
|
+
# @option attributes [Array] :thoughts Array of thought objects
|
12
|
+
# @option attributes [String] :final_answer The final answer
|
13
|
+
# @option attributes [Float] :confidence_score Confidence score (0.0-1.0)
|
14
|
+
# @option attributes [Symbol] :status The result status
|
15
|
+
# @option attributes [String] :error Error message if failed
|
16
|
+
# @option attributes [Float] :execution_time Time taken in seconds
|
17
|
+
def initialize(attributes = {})
|
18
|
+
@input = attributes[:input]
|
19
|
+
@thoughts = attributes[:thoughts] || []
|
20
|
+
@final_answer = attributes[:final_answer]
|
21
|
+
@confidence_score = attributes[:confidence_score] || 0.0
|
22
|
+
@status = attributes[:status] || :pending
|
23
|
+
@error = attributes[:error]
|
24
|
+
@execution_time = attributes[:execution_time]
|
25
|
+
@created_at = Time.now
|
26
|
+
end
|
27
|
+
|
28
|
+
# Status check methods
|
29
|
+
|
30
|
+
# Check if the result is successful
|
31
|
+
# @return [Boolean]
|
32
|
+
def successful?
|
33
|
+
status == :success
|
34
|
+
end
|
35
|
+
|
36
|
+
# Check if the result failed
|
37
|
+
# @return [Boolean]
|
38
|
+
def failed?
|
39
|
+
status == :failed
|
40
|
+
end
|
41
|
+
|
42
|
+
# Check if the result timed out
|
43
|
+
# @return [Boolean]
|
44
|
+
def timeout?
|
45
|
+
status == :timeout
|
46
|
+
end
|
47
|
+
|
48
|
+
# Check if max iterations were reached
|
49
|
+
# @return [Boolean]
|
50
|
+
def max_iterations_reached?
|
51
|
+
status == :max_iterations_reached
|
52
|
+
end
|
53
|
+
|
54
|
+
# Data access methods
|
55
|
+
|
56
|
+
# Get the number of iterations (thoughts)
|
57
|
+
# @return [Integer]
|
58
|
+
def iterations
|
59
|
+
thoughts.length
|
60
|
+
end
|
61
|
+
|
62
|
+
# Convert to hash representation
|
63
|
+
# @return [Hash]
|
64
|
+
def to_h
|
65
|
+
build_hash.compact
|
66
|
+
end
|
67
|
+
|
68
|
+
# Convert to JSON string
|
69
|
+
# @return [String]
|
70
|
+
def to_json(*)
|
71
|
+
to_h.to_json(*)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Get a summary of the result
|
75
|
+
# @return [String]
|
76
|
+
def summary
|
77
|
+
status_message_for(status)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get execution details
|
81
|
+
# @return [Hash]
|
82
|
+
def execution_details
|
83
|
+
{
|
84
|
+
iterations: iterations,
|
85
|
+
confidence: confidence_score ? format('%.1f%%', confidence_score * 100) : 'N/A',
|
86
|
+
time: execution_time ? "#{execution_time.round(2)}s" : 'N/A',
|
87
|
+
status: status
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def build_hash
|
94
|
+
base_attributes.merge(execution_attributes)
|
95
|
+
end
|
96
|
+
|
97
|
+
def base_attributes
|
98
|
+
{
|
99
|
+
input: input,
|
100
|
+
thoughts: thoughts,
|
101
|
+
final_answer: final_answer,
|
102
|
+
confidence_score: confidence_score,
|
103
|
+
status: status
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
def execution_attributes
|
108
|
+
{
|
109
|
+
error: error,
|
110
|
+
execution_time: execution_time,
|
111
|
+
iterations: iterations,
|
112
|
+
created_at: @created_at
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def status_message_for(current_status)
|
117
|
+
message_mapping[current_status] || "Status: #{current_status}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def message_mapping
|
121
|
+
{
|
122
|
+
success: "Success: #{truncate(final_answer)}",
|
123
|
+
failed: "Failed: #{error}",
|
124
|
+
timeout: 'Timeout: Execution exceeded time limit',
|
125
|
+
max_iterations_reached: "Max iterations reached: #{iterations} iterations"
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def truncate(text, length = 100)
|
130
|
+
return nil if text.nil?
|
131
|
+
return text if text.length <= length
|
132
|
+
|
133
|
+
"#{text[0..length]}..."
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soka
|
4
|
+
# RSpec test helpers for Soka framework
|
5
|
+
module TestHelpers
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
let(:mock_llm_response) { nil }
|
9
|
+
let(:mock_tool_responses) { {} }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def mock_ai_response(response_data)
|
14
|
+
@mock_llm_response = response_data
|
15
|
+
|
16
|
+
# Create a mock LLM that returns the specified response
|
17
|
+
mock_llm = instance_double(Soka::LLM::Base)
|
18
|
+
|
19
|
+
# Format the response content based on the response data
|
20
|
+
content = build_react_content(response_data)
|
21
|
+
|
22
|
+
result = create_mock_llm_result(content)
|
23
|
+
|
24
|
+
allow(mock_llm).to receive(:chat).and_return(result)
|
25
|
+
allow(Soka::LLM).to receive(:new).and_return(mock_llm)
|
26
|
+
|
27
|
+
mock_llm
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_mock_llm_result(content)
|
31
|
+
Soka::LLM::Result.new(
|
32
|
+
model: 'mock-model',
|
33
|
+
content: content,
|
34
|
+
input_tokens: 100,
|
35
|
+
output_tokens: 200,
|
36
|
+
finish_reason: 'stop',
|
37
|
+
raw_response: { mock: true }
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def mock_tool_response(tool_class, response)
|
42
|
+
@mock_tool_responses[tool_class] = response
|
43
|
+
|
44
|
+
# Create a mock instance of the tool
|
45
|
+
mock_tool = instance_double(tool_class)
|
46
|
+
allow(mock_tool).to receive(:class).and_return(tool_class)
|
47
|
+
allow(mock_tool).to receive(:execute).and_return(response)
|
48
|
+
|
49
|
+
# Allow the tool class to be instantiated with the mock
|
50
|
+
allow(tool_class).to receive(:new).and_return(mock_tool)
|
51
|
+
|
52
|
+
mock_tool
|
53
|
+
end
|
54
|
+
|
55
|
+
def allow_tool_to_fail(tool_class, error)
|
56
|
+
mock_tool = instance_double(tool_class)
|
57
|
+
allow(mock_tool).to receive(:class).and_return(tool_class)
|
58
|
+
allow(mock_tool).to receive(:execute).and_raise(error)
|
59
|
+
|
60
|
+
allow(tool_class).to receive(:new).and_return(mock_tool)
|
61
|
+
|
62
|
+
mock_tool
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_test_agent(options = {})
|
66
|
+
Class.new(Soka::Agent) do
|
67
|
+
provider :gemini
|
68
|
+
model 'gemini-2.5-flash'
|
69
|
+
max_iterations 5
|
70
|
+
timeout 10
|
71
|
+
end.new(**options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_test_tool(name: 'test_tool', description: 'Test tool', &block)
|
75
|
+
Class.new(Soka::AgentTool) do
|
76
|
+
desc description
|
77
|
+
|
78
|
+
define_singleton_method :tool_name do
|
79
|
+
name
|
80
|
+
end
|
81
|
+
|
82
|
+
define_method :call, &block || -> { 'Test response' }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def stub_env(env_vars)
|
87
|
+
env_vars.each do |key, value|
|
88
|
+
allow(ENV).to receive(:fetch).with(key).and_return(value)
|
89
|
+
allow(ENV).to receive(:[]).with(key).and_return(value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def with_configuration
|
94
|
+
original_config = Soka.configuration
|
95
|
+
Soka.reset!
|
96
|
+
yield
|
97
|
+
ensure
|
98
|
+
Soka.configuration = original_config
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def build_react_content(response_data)
|
104
|
+
content = []
|
105
|
+
|
106
|
+
# Build thoughts and actions
|
107
|
+
response_data[:thoughts].each_with_index do |thought_data, _index|
|
108
|
+
content << "<Thought>#{thought_data[:thought]}</Thought>"
|
109
|
+
|
110
|
+
next unless thought_data[:action]
|
111
|
+
|
112
|
+
action = thought_data[:action]
|
113
|
+
params_json = action[:params].to_json
|
114
|
+
|
115
|
+
content << build_action_content(action[:tool], params_json)
|
116
|
+
|
117
|
+
# The observation will be added by the engine
|
118
|
+
end
|
119
|
+
|
120
|
+
# Add final answer if present
|
121
|
+
content << "<Final_Answer>#{response_data[:final_answer]}</Final_Answer>" if response_data[:final_answer]
|
122
|
+
|
123
|
+
content.join("\n")
|
124
|
+
end
|
125
|
+
|
126
|
+
def build_action_content(tool, params_json)
|
127
|
+
<<~ACTION
|
128
|
+
<Action>
|
129
|
+
Tool: #{tool}
|
130
|
+
Parameters: #{params_json}
|
131
|
+
</Action>
|
132
|
+
ACTION
|
133
|
+
end
|
134
|
+
|
135
|
+
# Matcher helpers for RSpec
|
136
|
+
module Matchers
|
137
|
+
def be_successful
|
138
|
+
satisfy(&:successful?)
|
139
|
+
end
|
140
|
+
|
141
|
+
def be_failed
|
142
|
+
satisfy(&:failed?)
|
143
|
+
end
|
144
|
+
|
145
|
+
def final_answer?(expected = nil)
|
146
|
+
if expected
|
147
|
+
satisfy { |result| result.final_answer == expected }
|
148
|
+
else
|
149
|
+
satisfy { |result| !result.final_answer.nil? }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def thoughts_count?(count)
|
154
|
+
satisfy { |result| result.thoughts.length == count }
|
155
|
+
end
|
156
|
+
|
157
|
+
def confidence_score_above?(threshold)
|
158
|
+
satisfy { |result| result.confidence_score > threshold }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soka
|
4
|
+
# Stores and manages the thinking process history
|
5
|
+
class ThoughtsMemory
|
6
|
+
attr_reader :sessions
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@sessions = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(input, result)
|
13
|
+
session = {
|
14
|
+
input: input,
|
15
|
+
thoughts: result.thoughts || [],
|
16
|
+
final_answer: result.final_answer,
|
17
|
+
status: result.status,
|
18
|
+
confidence_score: result.confidence_score,
|
19
|
+
timestamp: Time.now
|
20
|
+
}
|
21
|
+
|
22
|
+
session[:error] = result.error if result.error
|
23
|
+
|
24
|
+
@sessions << session
|
25
|
+
end
|
26
|
+
|
27
|
+
def last_session
|
28
|
+
@sessions.last
|
29
|
+
end
|
30
|
+
|
31
|
+
def all_sessions
|
32
|
+
@sessions
|
33
|
+
end
|
34
|
+
|
35
|
+
def clear
|
36
|
+
@sessions.clear
|
37
|
+
end
|
38
|
+
|
39
|
+
def size
|
40
|
+
@sessions.size
|
41
|
+
end
|
42
|
+
|
43
|
+
def empty?
|
44
|
+
@sessions.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
def successful_sessions
|
48
|
+
@sessions.select { |s| s[:status] == :success }
|
49
|
+
end
|
50
|
+
|
51
|
+
def failed_sessions
|
52
|
+
@sessions.select { |s| s[:status] == :failed }
|
53
|
+
end
|
54
|
+
|
55
|
+
def average_confidence_score
|
56
|
+
successful = successful_sessions
|
57
|
+
return 0.0 if successful.empty?
|
58
|
+
|
59
|
+
total = successful.sum { |s| s[:confidence_score] || 0.0 }
|
60
|
+
total / successful.size
|
61
|
+
end
|
62
|
+
|
63
|
+
def average_iterations
|
64
|
+
return 0 if @sessions.empty?
|
65
|
+
|
66
|
+
total = @sessions.sum { |s| s[:thoughts].size }
|
67
|
+
total.to_f / @sessions.size
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
return '<Soka::ThoughtsMemory> (0 sessions)' if empty?
|
72
|
+
|
73
|
+
stats = build_stats
|
74
|
+
|
75
|
+
format_stats_string(stats)
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_stats
|
79
|
+
{
|
80
|
+
total: size,
|
81
|
+
successful: successful_sessions.size,
|
82
|
+
failed: failed_sessions.size,
|
83
|
+
avg_confidence: format('%.2f', average_confidence_score),
|
84
|
+
avg_iterations: format('%.1f', average_iterations)
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def format_stats_string(stats)
|
89
|
+
"<Soka::ThoughtsMemory> (#{stats[:total]} sessions, " \
|
90
|
+
"#{stats[:successful]} successful, #{stats[:failed]} failed, " \
|
91
|
+
"avg confidence: #{stats[:avg_confidence]}, " \
|
92
|
+
"avg iterations: #{stats[:avg_iterations]})"
|
93
|
+
end
|
94
|
+
|
95
|
+
def inspect
|
96
|
+
to_s
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_h
|
100
|
+
{
|
101
|
+
sessions: @sessions,
|
102
|
+
stats: {
|
103
|
+
total_sessions: size,
|
104
|
+
successful_sessions: successful_sessions.size,
|
105
|
+
failed_sessions: failed_sessions.size,
|
106
|
+
average_confidence_score: average_confidence_score,
|
107
|
+
average_iterations: average_iterations
|
108
|
+
}
|
109
|
+
}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/soka/version.rb
ADDED
data/lib/soka.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zeitwerk'
|
4
|
+
require 'faraday'
|
5
|
+
require 'dry-validation'
|
6
|
+
require 'dry-struct'
|
7
|
+
require 'dry-types'
|
8
|
+
|
9
|
+
# Main module for the Soka ReAct Agent Framework
|
10
|
+
# Provides AI agent capabilities with multiple LLM providers support
|
11
|
+
module Soka
|
12
|
+
class Error < StandardError; end
|
13
|
+
class ConfigurationError < Error; end
|
14
|
+
class LLMError < Error; end
|
15
|
+
class ToolError < Error; end
|
16
|
+
class AgentError < Error; end
|
17
|
+
class MemoryError < Error; end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :configuration
|
21
|
+
|
22
|
+
def setup
|
23
|
+
self.configuration ||= Configuration.new
|
24
|
+
yield(configuration) if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
def configure(&)
|
28
|
+
setup(&)
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset!
|
32
|
+
self.configuration = Configuration.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
loader = Zeitwerk::Loader.for_gem
|
37
|
+
loader.inflector.inflect(
|
38
|
+
'llm' => 'LLM',
|
39
|
+
'llms' => 'LLMs',
|
40
|
+
'ai' => 'AI',
|
41
|
+
'openai' => 'OpenAI',
|
42
|
+
'dsl_methods' => 'DSLMethods',
|
43
|
+
'llm_builder' => 'LLMBuilder'
|
44
|
+
)
|
45
|
+
loader.setup
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initialize default configuration
|
49
|
+
Soka.setup
|
data/sig/soka.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: soka
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.beta2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jiunjiun
|
8
|
+
bindir: exe
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: dry-struct
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.6'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '1.6'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: dry-types
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.7'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.7'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: dry-validation
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.10'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.10'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: faraday
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: zeitwerk
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.6'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.6'
|
82
|
+
description: Soka is a Ruby framework for building AI agents using the ReAct (Reasoning
|
83
|
+
and Acting) pattern. It supports multiple AI providers including Gemini Studio,
|
84
|
+
OpenAI, and Anthropic.
|
85
|
+
email:
|
86
|
+
- imjiunjiun@gmail.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".rspec"
|
92
|
+
- ".rubocop.yml"
|
93
|
+
- CHANGELOG.md
|
94
|
+
- CLAUDE.md
|
95
|
+
- LICENSE
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- examples/1_basic.rb
|
99
|
+
- examples/2_event_handling.rb
|
100
|
+
- examples/3_memory.rb
|
101
|
+
- examples/4_hooks.rb
|
102
|
+
- examples/5_error_handling.rb
|
103
|
+
- examples/6_retry.rb
|
104
|
+
- examples/7_tool_conditional.rb
|
105
|
+
- examples/8_multi_provider.rb
|
106
|
+
- lib/soka.rb
|
107
|
+
- lib/soka/agent.rb
|
108
|
+
- lib/soka/agent_tool.rb
|
109
|
+
- lib/soka/agent_tools/params_validator.rb
|
110
|
+
- lib/soka/agents/dsl_methods.rb
|
111
|
+
- lib/soka/agents/hook_manager.rb
|
112
|
+
- lib/soka/agents/llm_builder.rb
|
113
|
+
- lib/soka/agents/retry_handler.rb
|
114
|
+
- lib/soka/agents/tool_builder.rb
|
115
|
+
- lib/soka/configuration.rb
|
116
|
+
- lib/soka/engines/base.rb
|
117
|
+
- lib/soka/engines/concerns/prompt_template.rb
|
118
|
+
- lib/soka/engines/concerns/response_processor.rb
|
119
|
+
- lib/soka/engines/react.rb
|
120
|
+
- lib/soka/engines/reasoning_context.rb
|
121
|
+
- lib/soka/llm.rb
|
122
|
+
- lib/soka/llms/anthropic.rb
|
123
|
+
- lib/soka/llms/base.rb
|
124
|
+
- lib/soka/llms/concerns/response_parser.rb
|
125
|
+
- lib/soka/llms/concerns/streaming_handler.rb
|
126
|
+
- lib/soka/llms/gemini.rb
|
127
|
+
- lib/soka/llms/openai.rb
|
128
|
+
- lib/soka/memory.rb
|
129
|
+
- lib/soka/result.rb
|
130
|
+
- lib/soka/test_helpers.rb
|
131
|
+
- lib/soka/thoughts_memory.rb
|
132
|
+
- lib/soka/version.rb
|
133
|
+
- sig/soka.rbs
|
134
|
+
homepage: https://github.com/jiunjiun/soka
|
135
|
+
licenses: []
|
136
|
+
metadata:
|
137
|
+
homepage_uri: https://github.com/jiunjiun/soka
|
138
|
+
source_code_uri: https://github.com/jiunjiun/soka
|
139
|
+
changelog_uri: https://github.com/jiunjiun/soka/blob/main/CHANGELOG.md
|
140
|
+
rubygems_mfa_required: 'true'
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '3.4'
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
requirements: []
|
155
|
+
rubygems_version: 3.6.9
|
156
|
+
specification_version: 4
|
157
|
+
summary: A Ruby ReAct Agent Framework with multi-LLM support
|
158
|
+
test_files: []
|