omniai 1.7.0 → 1.8.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +3 -10
  4. data/lib/omniai/chat/choice.rb +68 -0
  5. data/lib/omniai/chat/content.rb +10 -2
  6. data/lib/omniai/chat/file.rb +3 -3
  7. data/lib/omniai/chat/function.rb +57 -0
  8. data/lib/omniai/chat/message/builder.rb +67 -0
  9. data/lib/omniai/chat/message.rb +64 -45
  10. data/lib/omniai/chat/payload.rb +85 -0
  11. data/lib/omniai/chat/prompt.rb +30 -16
  12. data/lib/omniai/chat/response.rb +70 -0
  13. data/lib/omniai/chat/stream.rb +61 -0
  14. data/lib/omniai/chat/text.rb +2 -2
  15. data/lib/omniai/chat/tool_call.rb +54 -0
  16. data/lib/omniai/chat/tool_call_message.rb +61 -0
  17. data/lib/omniai/chat/tool_call_result.rb +51 -0
  18. data/lib/omniai/chat/url.rb +2 -2
  19. data/lib/omniai/chat/usage.rb +60 -0
  20. data/lib/omniai/chat.rb +61 -34
  21. data/lib/omniai/context.rb +12 -0
  22. data/lib/omniai/embed/response.rb +2 -2
  23. data/lib/omniai/tool.rb +6 -2
  24. data/lib/omniai/version.rb +1 -1
  25. metadata +12 -16
  26. data/lib/omniai/chat/response/choice.rb +0 -35
  27. data/lib/omniai/chat/response/chunk.rb +0 -15
  28. data/lib/omniai/chat/response/completion.rb +0 -15
  29. data/lib/omniai/chat/response/delta.rb +0 -11
  30. data/lib/omniai/chat/response/delta_choice.rb +0 -25
  31. data/lib/omniai/chat/response/function.rb +0 -25
  32. data/lib/omniai/chat/response/message.rb +0 -11
  33. data/lib/omniai/chat/response/message_choice.rb +0 -25
  34. data/lib/omniai/chat/response/part.rb +0 -38
  35. data/lib/omniai/chat/response/payload.rb +0 -72
  36. data/lib/omniai/chat/response/resource.rb +0 -22
  37. data/lib/omniai/chat/response/stream.rb +0 -27
  38. data/lib/omniai/chat/response/tool_call.rb +0 -30
  39. data/lib/omniai/chat/response/usage.rb +0 -35
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # Used when processing everything at once.
6
+ class Response
7
+ # @return [Hash]
8
+ attr_accessor :data
9
+
10
+ # @param data [Hash]
11
+ # @param context [Context, nil]
12
+ def initialize(data:, context: nil)
13
+ @data = data
14
+ @context = context
15
+ end
16
+
17
+ # @return [Payload]
18
+ def completion
19
+ @completion ||= Payload.deserialize(@data, context: @context)
20
+ end
21
+
22
+ # @return [Usage, nil]
23
+ def usage
24
+ completion.usage
25
+ end
26
+
27
+ # @return [Array<Choice>]
28
+ def choices
29
+ completion.choices
30
+ end
31
+
32
+ # @return [Array<Message>]
33
+ def messages
34
+ completion.messages
35
+ end
36
+
37
+ # @param index [Integer]
38
+ # @return [Choice]
39
+ def choice(index: 0)
40
+ completion.choice(index:)
41
+ end
42
+
43
+ # @param index [Integer]
44
+ # @return [Message]
45
+ def message(index: 0)
46
+ completion.message(index:)
47
+ end
48
+
49
+ # @return [String]
50
+ def text
51
+ message.text
52
+ end
53
+
54
+ # @return [Boolean]
55
+ def text?
56
+ message.text?
57
+ end
58
+
59
+ # @return [Array<ToolCall>]
60
+ def tool_call_list
61
+ choice.tool_call_list
62
+ end
63
+
64
+ # @return [Boolean]
65
+ def tool_call_list?
66
+ tool_call_list&.any?
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # Used when streaming to process chunks of data.
6
+ class Stream
7
+ # @param logger [OmniAI::Client]
8
+ # @param body [HTTP::Response::Body]
9
+ # @param context [Context, nil]
10
+ def initialize(body:, logger: nil, context: nil)
11
+ @body = body
12
+ @logger = logger
13
+ @context = context
14
+ end
15
+
16
+ # @yield [payload]
17
+ # @yieldparam payload [OmniAI::Chat::Payload]
18
+ def stream!(&)
19
+ @body.each do |chunk|
20
+ parser.feed(chunk) do |type, data, id|
21
+ process!(type, data, id, &)
22
+ end
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ # @param type [String]
29
+ # @param data [String]
30
+ # @param id [String]
31
+ def log(type, data, id)
32
+ arguments = [
33
+ ("type=#{type.inspect}" if type),
34
+ ("data=#{data.inspect}" if data),
35
+ ("id=#{id.inspect}" if id),
36
+ ].compact
37
+
38
+ @logger&.debug("Stream#process! #{arguments.join(' ')}")
39
+ end
40
+
41
+ # @param type [String]
42
+ # @param data [String]
43
+ # @param id [String]
44
+ #
45
+ # @yield [payload]
46
+ # @yieldparam payload [OmniAI::Chat::Payload]
47
+ def process!(type, data, id, &block)
48
+ log(type, data, id)
49
+
50
+ return if data.eql?('[DONE]')
51
+
52
+ block.call(Payload.deserialize(JSON.parse(data), context: @context))
53
+ end
54
+
55
+ # @return [EventStreamParser::Parser]
56
+ def parser
57
+ @parser ||= EventStreamParser::Parser.new
58
+ end
59
+ end
60
+ end
61
+ end
@@ -25,7 +25,7 @@ module OmniAI
25
25
 
26
26
  # @param data [Hash]
27
27
  def self.deserialize(data, context: nil)
28
- deserialize = context&.deserializers&.[](:text)
28
+ deserialize = context&.deserializer(:text)
29
29
  return deserialize.call(data, context:) if deserialize
30
30
 
31
31
  new(data['text'])
@@ -35,7 +35,7 @@ module OmniAI
35
35
  #
36
36
  # @return [Hash]
37
37
  def serialize(context: nil)
38
- serializer = context&.serializers&.[](:text)
38
+ serializer = context&.serializer(:text)
39
39
  return serializer.call(self, context:) if serializer
40
40
 
41
41
  { type: 'text', text: @text }
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # A tool-call that includes an ID / function.
6
+ class ToolCall
7
+ # @return [String]
8
+ attr_accessor :id
9
+
10
+ # @return [Function]
11
+ attr_accessor :function
12
+
13
+ # @param id [String]
14
+ # @param function [Function]
15
+ def initialize(id:, function:)
16
+ @id = id
17
+ @function = function
18
+ end
19
+
20
+ # @return [String]
21
+ def inspect
22
+ "#<#{self.class.name} id=#{id.inspect} function=#{function.inspect}>"
23
+ end
24
+
25
+ # @param data [Hash]
26
+ # @param context [Context] optional
27
+ #
28
+ # @return [Function]
29
+ def self.deserialize(data, context: nil)
30
+ deserialize = context&.deserializer(:tool_call)
31
+ return deserialize.call(data, context:) if deserialize
32
+
33
+ id = data['id']
34
+ function = Function.deserialize(data['function'], context:)
35
+
36
+ new(id:, function:)
37
+ end
38
+
39
+ # @param context [Context] optional
40
+ #
41
+ # @return [Hash]
42
+ def serialize(context: nil)
43
+ serializer = context&.serializer(:tool_call)
44
+ return serializer.call(self, context:) if serializer
45
+
46
+ {
47
+ id: @id,
48
+ type: 'function',
49
+ function: @function.serialize(context:),
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # A specific message that contains the result of a tool call.
6
+ class ToolCallMessage < Message
7
+ # @return [String]
8
+ attr_accessor :tool_call_id
9
+
10
+ # @param content [String]
11
+ # @param tool_call_id [String]
12
+ def initialize(content:, tool_call_id:, role: OmniAI::Chat::Role::TOOL)
13
+ super(content:, role:)
14
+ @tool_call_id = tool_call_id
15
+ end
16
+
17
+ # @return [String]
18
+ def inspect
19
+ "#<#{self.class.name} content=#{content.inspect} tool_call_id=#{tool_call_id.inspect}>"
20
+ end
21
+
22
+ # Usage:
23
+ #
24
+ # ToolCall.deserialize({ 'role' => 'tool', content: '{ 'temperature': 0 }' }) # => #<ToolCall ...>
25
+ #
26
+ # @param data [Hash]
27
+ # @param context [Context] optional
28
+ #
29
+ # @return [ToolMessage]
30
+ def self.deserialize(data, context: nil)
31
+ deserialize = context&.deserializer(:tool_message)
32
+ return deserialize.call(data, context:) if deserialize
33
+
34
+ role = data['role']
35
+ content = JSON.parse(data['content'])
36
+ tool_call_id = data['tool_call_id']
37
+
38
+ new(role:, content:, tool_call_id:)
39
+ end
40
+
41
+ # Usage:
42
+ #
43
+ # message.serialize # => { role: :user, content: 'Hello!' }
44
+ # message.serialize # => { role: :user, content: [{ type: 'text', text: 'Hello!' }] }
45
+ #
46
+ # @param context [Context] optional
47
+ #
48
+ # @return [Hash]
49
+ def serialize(context: nil)
50
+ serializer = context&.serializer(:tool_message)
51
+ return serializer.call(self, context:) if serializer
52
+
53
+ role = @role
54
+ content = JSON.generate(@content)
55
+ tool_call_id = @tool_call_id
56
+
57
+ { role:, content:, tool_call_id: }
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # The result of a tool call.
6
+ class ToolCallResult
7
+ # @return [Object]
8
+ attr_accessor :content
9
+
10
+ # @return [ToolCall]
11
+ attr_accessor :tool_call_id
12
+
13
+ # @param content [Object]
14
+ # @param tool_call [ToolCall]
15
+ def initialize(content:, tool_call_id:)
16
+ @content = content
17
+ @tool_call_id = tool_call_id
18
+ end
19
+
20
+ # @return [String]
21
+ def inspect
22
+ "#<#{self.class.name} content=#{content.inspect} tool_call_id=#{tool_call_id.inspect}>"
23
+ end
24
+
25
+ # @param context [Context] optional
26
+ # @return [Hash]
27
+ def serialize(context: nil)
28
+ serializer = context&.serializer(:tool_call_result)
29
+ return serializer.call(self, context:) if serializer
30
+
31
+ content = JSON.generate(@content)
32
+ tool_call_id = @tool_call_id
33
+
34
+ { content:, tool_call_id: }
35
+ end
36
+
37
+ # @param data [Hash]
38
+ # @param context [Context] optional
39
+ # @return [ToolCallResult]
40
+ def self.deserialize(data, context: nil)
41
+ deserialize = context&.deserializer(:tool_call_result)
42
+ return deserialize.call(data, context:) if deserialize
43
+
44
+ content = JSON.parse(data['content'])
45
+ tool_call_id = data['tool_call_id']
46
+
47
+ new(content:, tool_call_id:)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -28,7 +28,7 @@ module OmniAI
28
28
 
29
29
  # @param data [Hash]
30
30
  def self.deserialize(data, context: nil)
31
- deserialize = context&.deserializers&.[](:url)
31
+ deserialize = context&.deserializer(:url)
32
32
  return deserialize.call(data, context:) if deserialize
33
33
 
34
34
  type = /(?<type>\w+)_url/.match(data['type'])[:type]
@@ -45,7 +45,7 @@ module OmniAI
45
45
  content = fetch!
46
46
  Text.new("<file>#{filename}: #{content}</file>").serialize(context:)
47
47
  else
48
- serializer = context&.serializers&.[](:url)
48
+ serializer = context&.serializer(:url)
49
49
  return serializer.call(self, context:) if serializer
50
50
 
51
51
  {
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # The usage of a chat in terms of tokens (input / output / total).
6
+ class Usage
7
+ # @return [Integer]
8
+ attr_accessor :input_tokens
9
+
10
+ # @return [Integer]
11
+ attr_accessor :output_tokens
12
+
13
+ # @return [Integer]
14
+ attr_accessor :total_tokens
15
+
16
+ # @param input_tokens [Integer]
17
+ # @param output_tokens [Integer]
18
+ # @param total_tokens [Integer]
19
+ def initialize(input_tokens:, output_tokens:, total_tokens:)
20
+ @input_tokens = input_tokens
21
+ @output_tokens = output_tokens
22
+ @total_tokens = total_tokens
23
+ end
24
+
25
+ # @return [String]
26
+ def inspect
27
+ "#<#{self.class.name} input_tokens=#{input_tokens} output_tokens=#{output_tokens} total_tokens=#{total_tokens}>"
28
+ end
29
+
30
+ # @param data [Hash]
31
+ # @param context [OmniAI::Context] optional
32
+ #
33
+ # @return [OmniAI::Chat::Usage]
34
+ def self.deserialize(data, context: nil)
35
+ deserialize = context&.deserializer(:usage)
36
+ return deserialize.call(data, context:) if deserialize
37
+
38
+ input_tokens = data['input_tokens']
39
+ output_tokens = data['output_tokens']
40
+ total_tokens = data['total_tokens']
41
+
42
+ new(input_tokens:, output_tokens:, total_tokens:)
43
+ end
44
+
45
+ # @param context [OmniAI::Context] optional
46
+ #
47
+ # @return [Hash]
48
+ def serialize(context: nil)
49
+ serialize = context&.serializer(:usage)
50
+ return serialize.call(self, context:) if serialize
51
+
52
+ {
53
+ input_tokens:,
54
+ output_tokens:,
55
+ total_tokens:,
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
data/lib/omniai/chat.rb CHANGED
@@ -27,14 +27,23 @@ module OmniAI
27
27
  class Chat
28
28
  JSON_PROMPT = 'Respond with valid JSON. Do not include any non-JSON in the response.'
29
29
 
30
- # An error raised when a chat makes a tool-call for a tool that cannot be found.
31
- class ToolCallLookupError < Error
32
- def initialize(tool_call)
33
- super("missing tool for tool_call=#{tool_call.inspect}")
30
+ # An error raised for tool-call issues.
31
+ class ToolCallError < Error
32
+ # @param tool_call [OmniAI::Chat::ToolCall]
33
+ # @param message [String]
34
+ def initialize(tool_call:, message:)
35
+ super(message)
34
36
  @tool_call = tool_call
35
37
  end
36
38
  end
37
39
 
40
+ # An error raised when a tool-call is missing.
41
+ class ToolCallMissingError < ToolCallError
42
+ def initialize(tool_call:)
43
+ super(tool_call:, message: "missing tool for tool_call=#{tool_call.inspect}")
44
+ end
45
+ end
46
+
38
47
  module Role
39
48
  ASSISTANT = 'assistant'
40
49
  USER = 'user'
@@ -87,10 +96,22 @@ module OmniAI
87
96
 
88
97
  protected
89
98
 
99
+ # Override to provide an context for serializers / deserializes for a provider.
100
+ #
101
+ # @return [Context, nil]
102
+ def context
103
+ nil
104
+ end
105
+
106
+ # @return [Logger, nil]
107
+ def logger
108
+ @client.logger
109
+ end
110
+
90
111
  # Used to spawn another chat with the same configuration using different messages.
91
112
  #
92
113
  # @param prompt [OmniAI::Chat::Prompt]
93
- # @return [OmniAI::Chat::Prompt]
114
+ # @return [OmniAI::Chat]
94
115
  def spawn!(prompt)
95
116
  self.class.new(
96
117
  prompt,
@@ -100,7 +121,7 @@ module OmniAI
100
121
  stream: @stream,
101
122
  tools: @tools,
102
123
  format: @format
103
- ).process!
124
+ )
104
125
  end
105
126
 
106
127
  # @return [Hash]
@@ -114,7 +135,7 @@ module OmniAI
114
135
  end
115
136
 
116
137
  # @param response [HTTP::Response]
117
- # @return [OmniAI::Chat::Response::Completion]
138
+ # @return [OmniAI::Chat::Response]
118
139
  def parse!(response:)
119
140
  if @stream
120
141
  stream!(response:)
@@ -124,31 +145,32 @@ module OmniAI
124
145
  end
125
146
 
126
147
  # @param response [HTTP::Response]
127
- # @return [OmniAI::Chat::Response::Completion]
148
+ # @return [OmniAI::Chat::Response]
128
149
  def complete!(response:)
129
- completion = self.class::Response::Completion.new(data: response.parse)
130
-
131
- if @tools && completion.tool_call_list.any?
132
- spawn!([
133
- *@prompt.serialize,
134
- *completion.choices.map(&:message).map(&:data),
135
- *(completion.tool_call_list.map { |tool_call| execute_tool_call(tool_call) }),
136
- ])
150
+ completion = self.class::Response.new(data: response.parse, context:)
151
+
152
+ if @tools && completion.tool_call_list?
153
+ spawn!(
154
+ @prompt.dup.tap do |prompt|
155
+ prompt.messages += completion.messages
156
+ prompt.messages += build_tool_call_messages(completion.tool_call_list)
157
+ end
158
+ ).process!
137
159
  else
138
160
  completion
139
161
  end
140
162
  end
141
163
 
142
164
  # @param response [HTTP::Response]
143
- # @return [OmniAI::Chat::Response::Stream]
165
+ # @return [OmniAI::Chat::Stream]
144
166
  def stream!(response:)
145
167
  raise Error, "#{self.class.name}#stream! unstreamable" unless @stream
146
168
 
147
- self.class::Response::Stream.new(response:).stream! do |chunk|
169
+ self.class::Stream.new(body: response.body, logger:, context:).stream! do |chunk|
148
170
  case @stream
149
171
  when IO, StringIO
150
- if chunk.content?
151
- @stream << chunk.content
172
+ if chunk.text
173
+ @stream << chunk.text
152
174
  @stream.flush
153
175
  end
154
176
  else @stream.call(chunk)
@@ -160,31 +182,36 @@ module OmniAI
160
182
 
161
183
  # @return [HTTP::Response]
162
184
  def request!
185
+ logger&.debug("Chat#request! payload=#{payload.inspect}")
186
+
163
187
  @client
164
188
  .connection
165
189
  .accept(:json)
166
190
  .post(path, json: payload)
167
191
  end
168
192
 
193
+ # @param tool_call_list [Array<OmniAI::Chat::ToolCall>]
194
+ # @return [Array<Message>]
195
+ def build_tool_call_messages(tool_call_list)
196
+ tool_call_list.map do |tool_call|
197
+ content = execute_tool_call(tool_call)
198
+ ToolCallMessage.new(content:, tool_call_id: tool_call.id)
199
+ end
200
+ end
201
+
202
+ # @raise [ToolCallError]
169
203
  # @param tool_call [OmniAI::Chat::ToolCall]
204
+ # @return [ToolCallResult]
170
205
  def execute_tool_call(tool_call)
171
- function = tool_call.function
206
+ logger&.debug("Chat#execute_tool_call tool_call=#{tool_call.inspect}")
172
207
 
173
- tool = @tools.find { |entry| function.name == entry.name } || raise(ToolCallLookupError, tool_call)
174
- result = tool.call(function.arguments)
208
+ function = tool_call.function
209
+ tool = @tools.find { |entry| function.name == entry.name } || raise(ToolCallMissingError, tool_call)
210
+ content = tool.call(function.arguments)
175
211
 
176
- prepare_tool_call_message(tool_call:, content: result)
177
- end
212
+ logger&.debug("Chat#execute_tool_call content=#{content.inspect}")
178
213
 
179
- # @param tool_call [OmniAI::Chat::ToolCall]
180
- # @param content [String]
181
- def prepare_tool_call_message(tool_call:, content:)
182
- {
183
- role: Role::TOOL,
184
- name: tool_call.function.name,
185
- tool_call_id: tool_call.id,
186
- content:,
187
- }
214
+ content
188
215
  end
189
216
  end
190
217
  end
@@ -39,5 +39,17 @@ module OmniAI
39
39
  @serializers = {}
40
40
  @deserializers = {}
41
41
  end
42
+
43
+ # @param name [Symbol]
44
+ # @return [Proc, nil]
45
+ def serializer(name)
46
+ @serializers[name]
47
+ end
48
+
49
+ # @param name [Symbol]
50
+ # @return [Proc, nil]
51
+ def deserializer(name)
52
+ @deserializers[name]
53
+ end
42
54
  end
43
55
  end
@@ -22,7 +22,7 @@ module OmniAI
22
22
  # @return [Usage]
23
23
  def usage
24
24
  @usage ||= begin
25
- deserializer = @context&.deserializers&.[](:usage)
25
+ deserializer = @context&.deserializer(:usage)
26
26
 
27
27
  if deserializer
28
28
  deserializer.call(@data, context: @context)
@@ -45,7 +45,7 @@ module OmniAI
45
45
  # @return [Array<Array<Float>>]
46
46
  def embeddings
47
47
  @embeddings ||= begin
48
- deserializer = @context&.deserializers&.[](:embeddings)
48
+ deserializer = @context&.deserializer(:embeddings)
49
49
 
50
50
  if deserializer
51
51
  deserializer.call(@data, context: @context)
data/lib/omniai/tool.rb CHANGED
@@ -44,7 +44,7 @@ module OmniAI
44
44
  end
45
45
 
46
46
  # @example
47
- # tool.prepare
47
+ # tool.serialize
48
48
  # # {
49
49
  # # type: 'function',
50
50
  # # function: {
@@ -60,8 +60,12 @@ module OmniAI
60
60
  # # }
61
61
  # # }
62
62
  #
63
+ # @param context [Context] optional
63
64
  # @return [Hash]
64
- def prepare
65
+ def serialize(context: nil)
66
+ serialize = context&.serializer(:tool)
67
+ return serialize.call(self, context:) if serialize
68
+
65
69
  {
66
70
  type: 'function',
67
71
  function: {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmniAI
4
- VERSION = '1.7.0'
4
+ VERSION = '1.8.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-02 00:00:00.000000000 Z
11
+ date: 2024-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -68,27 +68,23 @@ files:
68
68
  - exe/omniai
69
69
  - lib/omniai.rb
70
70
  - lib/omniai/chat.rb
71
+ - lib/omniai/chat/choice.rb
71
72
  - lib/omniai/chat/content.rb
72
73
  - lib/omniai/chat/file.rb
74
+ - lib/omniai/chat/function.rb
73
75
  - lib/omniai/chat/media.rb
74
76
  - lib/omniai/chat/message.rb
77
+ - lib/omniai/chat/message/builder.rb
78
+ - lib/omniai/chat/payload.rb
75
79
  - lib/omniai/chat/prompt.rb
76
- - lib/omniai/chat/response/choice.rb
77
- - lib/omniai/chat/response/chunk.rb
78
- - lib/omniai/chat/response/completion.rb
79
- - lib/omniai/chat/response/delta.rb
80
- - lib/omniai/chat/response/delta_choice.rb
81
- - lib/omniai/chat/response/function.rb
82
- - lib/omniai/chat/response/message.rb
83
- - lib/omniai/chat/response/message_choice.rb
84
- - lib/omniai/chat/response/part.rb
85
- - lib/omniai/chat/response/payload.rb
86
- - lib/omniai/chat/response/resource.rb
87
- - lib/omniai/chat/response/stream.rb
88
- - lib/omniai/chat/response/tool_call.rb
89
- - lib/omniai/chat/response/usage.rb
80
+ - lib/omniai/chat/response.rb
81
+ - lib/omniai/chat/stream.rb
90
82
  - lib/omniai/chat/text.rb
83
+ - lib/omniai/chat/tool_call.rb
84
+ - lib/omniai/chat/tool_call_message.rb
85
+ - lib/omniai/chat/tool_call_result.rb
91
86
  - lib/omniai/chat/url.rb
87
+ - lib/omniai/chat/usage.rb
92
88
  - lib/omniai/cli.rb
93
89
  - lib/omniai/cli/base_handler.rb
94
90
  - lib/omniai/cli/chat_handler.rb