omni_agent 0.1.4 → 0.1.5

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: 68e52e8d8eb8a4f59c708d32e7464b7526c92f8e5342d6a85fe3c1244bf643e7
4
- data.tar.gz: 36d892f5d7593582f31cc15d957deab720c80c8416a48ba32df4253f24d10ac6
3
+ metadata.gz: 1513c46e356438c23dfd193f25c390df240f2d1d812813114e2e582222de2965
4
+ data.tar.gz: a9b05b4445128aea795b3f7f5ea80cb6bd668bf2b674c15651011ce6780e0c2e
5
5
  SHA512:
6
- metadata.gz: afaf69e6f85c7db759d6796477601945577550a80f86e53a694f52d07910ffe081e79aa18db0688a8aaf3b4cb5dae5e141beaefc43e4083c59e46af2f6496df3
7
- data.tar.gz: efc7e291b645b15c0fe2d528737597948aaa28b9cc5a2f1bffd153313f071c0bd659d3d5b885932a607cf21f55dd217f907f85e82a667cbc797c8d8b85b9674d
6
+ metadata.gz: 4ee226683fb316a82a18457b50bbe783712fe4ad9115befa4ab7c9421b31747acf2b3f609360c126a599ac8dded16a9cc4dda670e115f3bed3711147776956a3
7
+ data.tar.gz: 6ab849bcae377ccc919d6daf13b0556d9d6ed07b1cd16d645fe66fb026df4dd941d4f9a06b396ea044bb4ad0db886457c25ce1ca4a4c4d4de6306dc31edf47f2
data/CHANGELOG.md CHANGED
@@ -4,25 +4,27 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
- ## [0.1.0] - 2026-06-09
7
+ ## [0.1.5] - 2026-06-18
8
8
 
9
9
  ### Added
10
- - Initial release of OmniAgent as a Rails engine for building application-native AI agents.
11
- - Agent runtime with provider abstraction, tool-calling loop, callbacks, and prompt rendering.
12
- - OpenAI provider support via the `openai` gem.
13
- - Tool DSL with JSON schema generation.
14
- - Rails generators and tasks for agent scaffolding.
15
- - RSpec coverage for agent runtime, providers, tools, and integration flows.
10
+ - Added max tool iterations limit on the agent loop, with corresponding error raised when exceeded.
11
+ - Added retry logic to the OpenAI provider, configurable via `Configuration`.
16
12
 
17
- ## [0.1.1] - 2026-06-09
18
-
19
- ### Changed
20
- - Lowered Rails version needed.
13
+ ### Fixed
14
+ - Improved provider resolution error handling for unknown providers.
15
+ - Forced eager load of error aliases to avoid Zeitwerk autoloading issues.
21
16
 
22
- ## [0.1.2] - 2026-06-11
17
+ # [0.1.4] - 2026-06-16
23
18
 
24
19
  ### Fixed
25
- - Fixed Zeitwerk issue with `OmniAgent::Errors`
20
+ - Change invoke method to an instance method instead of a class method, to actually catch invocations of the `stop_generation!` method.
21
+
22
+ ### Changed
23
+ - Remove agent file from directory to prevent needing to change Zeitwerk initializer as Railtie wasn't allowing to change behaviour without it.
24
+
25
+ ### Added
26
+ - Add Railtie to project to handle concerns.
27
+ - Added docusaurus, the actual docs will be done later.
26
28
 
27
29
  ## [0.1.3] - 2026-06-12
28
30
 
@@ -36,14 +38,22 @@ All notable changes to this project will be documented in this file.
36
38
  - Added `history` as a context variable which are the messages to be sent to the provider.
37
39
  - Added support for nested datatypes in the `array` schema for tools
38
40
 
39
- # [0.1.4] - 2026-06-16
41
+ ## [0.1.2] - 2026-06-11
40
42
 
41
43
  ### Fixed
42
- - Change invoke method to an instance method instead of a class method, to actually catch invocations of the `stop_generation!` method.
44
+ - Fixed Zeitwerk issue with `OmniAgent::Errors`
45
+
46
+ ## [0.1.1] - 2026-06-09
43
47
 
44
48
  ### Changed
45
- - Remove agent file from directory to prevent needing to change Zeitwerk initializer as Railtie wasn't allowing to change behaviour without it.
49
+ - Lowered Rails version needed.
50
+
51
+ ## [0.1.0] - 2026-06-09
46
52
 
47
53
  ### Added
48
- - Add Railtie to project to handle concerns.
49
- - Added docusaurus, the actual docs will be done later.
54
+ - Initial release of OmniAgent as a Rails engine for building application-native AI agents.
55
+ - Agent runtime with provider abstraction, tool-calling loop, callbacks, and prompt rendering.
56
+ - OpenAI provider support via the `openai` gem.
57
+ - Tool DSL with JSON schema generation.
58
+ - Rails generators and tasks for agent scaffolding.
59
+ - RSpec coverage for agent runtime, providers, tools, and integration flows.
@@ -46,7 +46,7 @@ module OmniAgent
46
46
  end
47
47
 
48
48
  def agent_file_path
49
- File.join(destination_root, "#{file_name}.rb")
49
+ File.join(destination_root, "app", "agents", "#{file_name}.rb")
50
50
  end
51
51
 
52
52
  def prompt_file_path
@@ -159,8 +159,17 @@ module OmniAgent
159
159
  initial_messages_count = messages.length - 1
160
160
 
161
161
  filtered_tools = tool_filter(tools: available_tools, agent_tags: self.class.tags)
162
+ max_iterations = OmniAgent.configuration.max_tool_iterations
163
+ iterations = 0
162
164
 
163
165
  loop do
166
+ iterations += 1
167
+ if iterations > max_iterations
168
+ raise OmniAgent::MaxToolIterationsError,
169
+ "Exceeded max_tool_iterations (#{max_iterations}) without a final response. " \
170
+ "Increase OmniAgent.configuration.max_tool_iterations if more tool calls are expected."
171
+ end
172
+
164
173
  response = provider.chat(messages: messages, tools: filtered_tools, **@chat_options)
165
174
 
166
175
  if response.content && !response.tool_calls?
@@ -309,7 +318,15 @@ module OmniAgent
309
318
  end
310
319
 
311
320
  def resolve_provider(name, model)
312
- OmniAgent::Providers.registry[name.to_sym].new(model: model)
321
+ provider_class = OmniAgent::Providers.registry[name.to_sym]
322
+
323
+ unless provider_class
324
+ known = OmniAgent::Providers.registry.keys.join(", ")
325
+ raise OmniAgent::UnknownProviderError,
326
+ "Unknown provider #{name.inspect}. Known providers: #{known}"
327
+ end
328
+
329
+ provider_class.new(model: model)
313
330
  end
314
331
 
315
332
  def run_before_generation_callbacks(input:, context:, messages:)
@@ -1,10 +1,13 @@
1
1
  module OmniAgent
2
2
  class Configuration
3
- attr_accessor :default_provider, :default_model
3
+ attr_accessor :default_provider, :default_model, :max_retries, :retry_base_delay, :max_tool_iterations
4
4
 
5
5
  def initialize
6
6
  @default_provider = :openai
7
7
  @default_model = "gpt-4o-mini"
8
+ @max_retries = 3
9
+ @retry_base_delay = 0.5
10
+ @max_tool_iterations = 10
8
11
  end
9
12
  end
10
13
  end
@@ -2,8 +2,12 @@ module OmniAgent
2
2
  module Errors
3
3
  class Error < StandardError; end
4
4
  class MissingDependencyError < Error; end
5
+ class UnknownProviderError < Error; end
6
+ class MaxToolIterationsError < Error; end
5
7
  end
6
8
 
7
9
  Error = Errors::Error
8
10
  MissingDependencyError = Errors::MissingDependencyError
11
+ UnknownProviderError = Errors::UnknownProviderError
12
+ MaxToolIterationsError = Errors::MaxToolIterationsError
9
13
  end
@@ -49,6 +49,29 @@ module OmniAgent
49
49
  raise NotImplementedError, "Providers must define a default model"
50
50
  end
51
51
 
52
+ # Override in subclasses to flag exceptions worth retrying (rate limits, timeouts, 5xx).
53
+ def retryable_error?(_error)
54
+ false
55
+ end
56
+
57
+ def with_retries
58
+ max_retries = OmniAgent.configuration.max_retries
59
+ base_delay = OmniAgent.configuration.retry_base_delay
60
+ attempt = 0
61
+
62
+ begin
63
+ yield
64
+ rescue => e
65
+ raise unless retryable_error?(e)
66
+
67
+ attempt += 1
68
+ raise if attempt > max_retries
69
+
70
+ sleep(base_delay * (2**(attempt - 1)))
71
+ retry
72
+ end
73
+ end
74
+
52
75
  def validate_message_payload!(message, index, role_name)
53
76
  has_content = message.key?(:content) || message.key?("content")
54
77
  content_value = message[:content] || message["content"]
@@ -44,7 +44,7 @@ module OmniAgent
44
44
  payload[:tools] = openai_tools if openai_tools.any?
45
45
  payload.merge!(options) if options.any?
46
46
 
47
- response = client.chat.completions.create(**payload)
47
+ response = with_retries { client.chat.completions.create(**payload) }
48
48
 
49
49
  parse_response(response, payload)
50
50
  rescue => e
@@ -53,6 +53,13 @@ module OmniAgent
53
53
 
54
54
  protected
55
55
 
56
+ def retryable_error?(error)
57
+ defined?(::OpenAI::Errors) &&
58
+ (error.is_a?(::OpenAI::Errors::RateLimitError) ||
59
+ error.is_a?(::OpenAI::Errors::InternalServerError) ||
60
+ error.is_a?(::OpenAI::Errors::APIConnectionError))
61
+ end
62
+
56
63
  def client
57
64
  @client ||= ::OpenAI::Client.new(api_key: @api_key)
58
65
  end
@@ -1,3 +1,3 @@
1
1
  module OmniAgent
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
data/lib/omni_agent.rb CHANGED
@@ -7,6 +7,12 @@ loader.inflector.inflect("openai" => "OpenAI")
7
7
  loader.ignore(File.expand_path("generators", __dir__))
8
8
  loader.setup
9
9
 
10
+ # errors.rb defines top-level aliases (OmniAgent::MissingDependencyError, etc.)
11
+ # that Zeitwerk cannot autoload, since they don't map to a file path of their
12
+ # own. Force it to load eagerly so the aliases exist regardless of which
13
+ # constant is referenced first.
14
+ require "omni_agent/errors"
15
+
10
16
 
11
17
  module OmniAgent
12
18
  class << self
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omni_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - ACR1209
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-06-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -82,7 +81,6 @@ metadata:
82
81
  homepage_uri: https://github.com/ACR1209/omni_agent
83
82
  source_code_uri: https://github.com/ACR1209/omni_agent
84
83
  changelog_uri: https://github.com/ACR1209/omni_agent/blob/main/CHANGELOG.md
85
- post_install_message:
86
84
  rdoc_options: []
87
85
  require_paths:
88
86
  - lib
@@ -97,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
95
  - !ruby/object:Gem::Version
98
96
  version: '0'
99
97
  requirements: []
100
- rubygems_version: 3.5.11
101
- signing_key:
98
+ rubygems_version: 3.6.9
102
99
  specification_version: 4
103
100
  summary: Rails engine for building AI agents with tools.
104
101
  test_files: []