omniai 3.8.0 → 3.9.0

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: 444922e4ffb4b54da232b01faab2b171f39ec2547830a7c02a4dc607173acae9
4
- data.tar.gz: 221d5e646b968f9cb422c64547966855518351038c9f1d7248961778785dd8fc
3
+ metadata.gz: 79d29d3011d03634e81f70e37b83af802c8881afb6920769a2b49e165f244735
4
+ data.tar.gz: 15b2e1cc6af34b9692f2d0628c8a94754f7d2dafc6b545bd739c2d4d88fe8141
5
5
  SHA512:
6
- metadata.gz: 30da07946fab93796f28c4d831ef00f0b609051e664a1cdc01373af8e6079d857239bf26be88d5cbeb6e9d25c7c2bcc08588979e3393da661bc73057e4c34bcb
7
- data.tar.gz: '09907c95ccd31c1f672f2fcc324a11a23b63799916db570a4a4fcaee4677249f430e15071a3f5e5ca34e72d867dedfc039a52527aa2dc9d6ffe7734b4f7d7dc7'
6
+ metadata.gz: d3d3636fc343966d21f40c7b09b566bcc3a3375e5d52e3b700f9d9db6e69194cb6d657cc25f721216ece7f8fa3d775216ca1baaaeb527b865d16be9398aaee47
7
+ data.tar.gz: bb45ac481dd2b27edf8e62ba66667ed1d17e77b4c44ab7505b17af0b78db4e8c7550d25fd67b8e5556b97e8455a8c65db443fcfb52abc3a2c3c4130904fafb65
data/README.md CHANGED
@@ -545,6 +545,28 @@ end
545
545
  client.chat('What is the weather in "London" in Celsius and "Paris" in Fahrenheit?', tools: [WeatherTool.new])
546
546
  ```
547
547
 
548
+ #### Per-Round Usage
549
+
550
+ A tool-call chain makes one request per round, but only the final `Response` is returned. Pass `on_response:` to receive each round's `Response` as it completes, before that round's tool calls run. It fires for single-round chats too and is independent of `stream:`.
551
+
552
+ Usage then survives an abort. When a stream block or a tool raises mid-chain, `process!` unwinds without returning a `Response`, but the rounds already handed over are still accounted for:
553
+
554
+ ```ruby
555
+ rounds = []
556
+
557
+ stream = proc do |chunk|
558
+ raise TooManyRounds if rounds.length >= 20
559
+
560
+ print(chunk.text)
561
+ end
562
+
563
+ begin
564
+ client.chat(prompt, tools:, stream:, on_response: proc { |round| rounds << round })
565
+ rescue TooManyRounds
566
+ rounds.filter_map(&:usage).sum { |usage| usage.input_tokens.to_i + usage.output_tokens.to_i }
567
+ end
568
+ ```
569
+
548
570
  #### Extended Thinking / Reasoning
549
571
 
550
572
  Some models support extended thinking or reasoning capabilities. OmniAI provides a unified `thinking:` option that works across all supported providers:
data/lib/omniai/chat.rb CHANGED
@@ -66,6 +66,8 @@ module OmniAI
66
66
  # @param stream [Proc, IO, nil] optional
67
67
  # @param tools [Array<OmniAI::Tool>, nil] optional
68
68
  # @param format [:json, :text, OmniAI::Schema::Object, nil] optional
69
+ # @param on_response [Proc, nil] optional - called with each completed round's `Response` before its tool
70
+ # calls run
69
71
  # @param options [Hash] optional (used for vendor specific options)
70
72
  #
71
73
  # @yield [prompt] optional
@@ -80,6 +82,7 @@ module OmniAI
80
82
  stream: nil,
81
83
  tools: nil,
82
84
  format: nil,
85
+ on_response: nil,
83
86
  **options,
84
87
  &block
85
88
  )
@@ -94,6 +97,7 @@ module OmniAI
94
97
  @stream = stream
95
98
  @tools = tools
96
99
  @format = format
100
+ @on_response = on_response
97
101
  @options = options || {}
98
102
  end
99
103
 
@@ -112,6 +116,8 @@ module OmniAI
112
116
  raise SSLError, e.message, cause: e
113
117
  end
114
118
 
119
+ @on_response&.call(completion)
120
+
115
121
  if tools? && completion.tool_call_list?
116
122
  next_completion = spawn!(
117
123
  @prompt.dup.tap do |prompt|
@@ -165,6 +171,7 @@ module OmniAI
165
171
  stream: @stream,
166
172
  tools: @tools,
167
173
  format: @format,
174
+ on_response: @on_response,
168
175
  **@options
169
176
  )
170
177
  end
data/lib/omniai/client.rb CHANGED
@@ -191,13 +191,16 @@ module OmniAI
191
191
  # @param temperature [Float, nil] optional
192
192
  # @param stream [Proc, nil] optional
193
193
  # @param tools [Array<OmniAI::Tool>] optional
194
+ # @param on_response [Proc, nil] optional - called with each completed round's `Response` before its tool
195
+ # calls run
194
196
  # @param options [Hash, nil] optional
195
197
  #
196
198
  # @yield [prompt] optional
197
199
  # @yieldparam prompt [OmniAI::Chat::Prompt]
198
200
  #
199
201
  # @return [OmniAI::Chat::Response]
200
- def chat(prompt = nil, model:, temperature: nil, format: nil, stream: nil, tools: nil, options: {}, &)
202
+ def chat(prompt = nil, model:, temperature: nil, format: nil, stream: nil, tools: nil, on_response: nil,
203
+ options: {}, &)
201
204
  raise NotImplementedError, "#{self.class.name}#chat undefined"
202
205
  end
203
206
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmniAI
4
- VERSION = "3.8.0"
4
+ VERSION = "3.9.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre