raix 0.7.3 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90b0072e3af33e82ccfb040554e9645920e34b4477457ba79335582c9325a7bd
4
- data.tar.gz: beeb6e0b98b473597d2191b5005fc89cb57fe69633cfe1e8927a6c1c0f61048f
3
+ metadata.gz: '08737974243ed41d4db2406405a4d081e31972cf173cfc3b2859cb97eabf0848'
4
+ data.tar.gz: 0d78927f5a35fad586f300bff4d86ce773d7bb7cd9f6787320e1cff6297f1aed
5
5
  SHA512:
6
- metadata.gz: cbc28460d07263899c0e45be8ccfd3fa522b3162ad2a53d640c1ff0cccb6c7d96f7ab4bef2afa809d47733a98a4a502602b78a6c53918e676955da9d88220f69
7
- data.tar.gz: d5e4f7dedaeb3ab2de64168f17a9de920a18894d5acfff22c0e00b870bdf96c77478130a61d47f82f7cc01a566b1cbc95f41fb43241cb3ece24c743b80993fed
6
+ metadata.gz: c0eec6ef99a37cd8ba69dfec62c8be70c9a8f6ed0be78b24ed184bde364c78f5189ccac71e3196f56af4c85390844b044c30be1b69172fe4e0f3c584903ea7c0
7
+ data.tar.gz: 90f084213b11dd737b55ed89fd21e75cf23b4c0ef5ab0daca8652f974b9fdb0f40a68ee07ea2abcd0b6af715ae3edc684643034b7e7e3455f7d05fae9ee1e473
data/.rubocop.yml CHANGED
@@ -35,3 +35,9 @@ Metrics/PerceivedComplexity:
35
35
 
36
36
  Metrics/ParameterLists:
37
37
  Enabled: false
38
+
39
+ Style/FrozenStringLiteralComment:
40
+ Enabled: false
41
+
42
+ Style/MultilineBlockChain:
43
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.4.2
data/CHANGELOG.md CHANGED
@@ -1,4 +1,20 @@
1
+ ## [0.8.0] - 2024-05-08
2
+ ### Added
3
+ * **MCP integration (Experimental)** — new `Raix::MCP` concern and `mcp` DSL for declaring remote MCP servers.
4
+ * Automatically fetches `tools/list`, registers remote tools as OpenAI‑compatible function schemas, and defines proxy methods that forward `tools/call`.
5
+ * `ChatCompletion#tools` now returns remote MCP tools alongside local `function` declarations.
6
+
7
+ ### Changed
8
+ * `lib/raix.rb` now requires `raix/mcp` so the concern is auto‑loaded.
9
+
10
+ ### Fixed
11
+ * Internal transcript handling spec expectations updated.
12
+
13
+ ### Specs
14
+ * Added `spec/raix/mcp_spec.rb` with comprehensive stubs for tools discovery & call flow.
15
+
1
16
  ## [0.7.3] - 2025-04-23
17
+ - commit function call and result to transcript in one operation for thread safety
2
18
 
3
19
  ## [0.7.2] - 2025-04-19
4
20
  - adds support for `messages` parameter in `chat_completion` to override the transcript
data/Gemfile CHANGED
@@ -5,11 +5,6 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in raix-rails.gemspec
6
6
  gemspec
7
7
 
8
- gem "activesupport", ">= 6.0"
9
- gem "faraday-retry"
10
- gem "open_router", "~> 0.3"
11
- gem "ruby-openai", "~> 7.0"
12
-
13
8
  group :development do
14
9
  gem "dotenv", ">= 2"
15
10
  gem "guard"
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- raix (0.7.3)
4
+ raix (0.8.0)
5
5
  activesupport (>= 6.0)
6
+ faraday-retry (~> 2.0)
6
7
  open_router (~> 0.2)
7
- ruby-openai (~> 7.0)
8
+ ruby-openai (~> 7)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
@@ -43,10 +44,10 @@ GEM
43
44
  multipart-post (~> 2)
44
45
  faraday-net_http (3.1.0)
45
46
  net-http
46
- faraday-retry (2.2.1)
47
+ faraday-retry (2.3.1)
47
48
  faraday (~> 2.0)
48
- ffi (1.17.0-arm64-darwin)
49
- ffi (1.17.0-x86_64-linux-gnu)
49
+ ffi (1.17.2-arm64-darwin)
50
+ ffi (1.17.2-x86_64-linux-gnu)
50
51
  formatador (1.1.0)
51
52
  guard (2.18.1)
52
53
  formatador (>= 0.2.4)
@@ -84,9 +85,9 @@ GEM
84
85
  net-http (0.4.1)
85
86
  uri
86
87
  netrc (0.11.0)
87
- nokogiri (1.16.6-arm64-darwin)
88
+ nokogiri (1.18.8-arm64-darwin)
88
89
  racc (~> 1.4)
89
- nokogiri (1.16.6-x86_64-linux)
90
+ nokogiri (1.18.8-x86_64-linux-gnu)
90
91
  racc (~> 1.4)
91
92
  notiffany (0.1.3)
92
93
  nenv (~> 0.1)
@@ -216,18 +217,14 @@ PLATFORMS
216
217
  x86_64-linux
217
218
 
218
219
  DEPENDENCIES
219
- activesupport (>= 6.0)
220
220
  dotenv (>= 2)
221
- faraday-retry
222
221
  guard
223
222
  guard-rspec
224
- open_router (~> 0.3)
225
223
  pry (>= 0.14)
226
224
  raix!
227
225
  rake (~> 13.0)
228
226
  rspec (~> 3.0)
229
227
  rubocop (~> 1.21)
230
- ruby-openai (~> 7.0)
231
228
  solargraph-rails (~> 0.2.0.pre)
232
229
  sorbet
233
230
  tapioca
data/README.md CHANGED
@@ -452,6 +452,50 @@ question.ask("Any question")
452
452
  # => RuntimeError: Please define a yes and/or no block
453
453
  ```
454
454
 
455
+ ## Model Context Protocol (Experimental)
456
+
457
+ The `Raix::MCP` module provides integration with the Model Context Protocol, allowing you to connect your Raix-powered application to remote MCP servers. This feature is currently **experimental**.
458
+
459
+ ### Usage
460
+
461
+ Include the `Raix::MCP` module in your class and declare MCP servers using the `mcp` DSL:
462
+
463
+ ```ruby
464
+ class McpConsumer
465
+ include Raix::ChatCompletion
466
+ include Raix::FunctionDispatch
467
+ include Raix::MCP
468
+
469
+ mcp "https://your-mcp-server.example.com/sse"
470
+ end
471
+ ```
472
+
473
+ ### Features
474
+
475
+ - Automatically fetches available tools from the remote MCP server using `tools/list`
476
+ - Registers remote tools as OpenAI-compatible function schemas
477
+ - Defines proxy methods that forward requests to the remote server via `tools/call`
478
+ - Seamlessly integrates with the existing `FunctionDispatch` workflow
479
+ - Handles transcript recording to maintain consistent conversation history
480
+
481
+ ### Filtering Tools
482
+
483
+ You can filter which remote tools to include:
484
+
485
+ ```ruby
486
+ class FilteredMcpConsumer
487
+ include Raix::ChatCompletion
488
+ include Raix::FunctionDispatch
489
+ include Raix::MCP
490
+
491
+ # Only include specific tools
492
+ mcp "https://server.example.com/sse", only: [:tool_one, :tool_two]
493
+
494
+ # Or exclude specific tools
495
+ mcp "https://server.example.com/sse", except: [:tool_to_exclude]
496
+ end
497
+ ```
498
+
455
499
  ## Response Format (Experimental)
456
500
 
457
501
  The `ResponseFormat` class provides a way to declare a JSON schema for the response format of an AI chat completion. It's particularly useful when you need structured responses from AI models, ensuring the output conforms to your application's requirements.
data/lib/raix/mcp.rb ADDED
@@ -0,0 +1,337 @@
1
+ # Simple integration layer that lets Raix classes declare an MCP server
2
+ # with a single DSL call:
3
+ #
4
+ # mcp "https://my-server.example.com/sse"
5
+ #
6
+ # The concern fetches the remote server's tool list (via JSON‑RPC 2.0
7
+ # `tools/list`) and exposes each remote tool as if it were an inline
8
+ # `function` declared with Raix::FunctionDispatch. When the tool is
9
+ # invoked by the model, the generated instance method forwards the
10
+ # request to the remote server using `tools/call`, captures the result,
11
+ # and appends the appropriate messages to the transcript so that the
12
+ # conversation history stays consistent.
13
+
14
+ require "active_support/concern"
15
+ require "active_support/inflector"
16
+ require "securerandom"
17
+ require "faraday"
18
+ require "uri"
19
+ require "json"
20
+
21
+ module Raix
22
+ # Model Context Protocol integration for Raix
23
+ #
24
+ # Allows declaring MCP servers with a simple DSL that automatically:
25
+ # - Queries tools from the remote server
26
+ # - Exposes each tool as a function callable by LLMs
27
+ # - Handles transcript recording and response processing
28
+ module MCP
29
+ extend ActiveSupport::Concern
30
+
31
+ JSONRPC_VERSION = "2.0".freeze
32
+ PROTOCOL_VERSION = "2024-11-05".freeze # Current supported protocol version
33
+ CONNECTION_TIMEOUT = 10
34
+ OPEN_TIMEOUT = 30
35
+
36
+ class_methods do
37
+ # Declare an MCP server by URL.
38
+ #
39
+ # mcp "https://server.example.com/sse"
40
+ #
41
+ # This will automatically:
42
+ # • query `tools/list` on the server
43
+ # • register each remote tool with FunctionDispatch so that the
44
+ # OpenAI / OpenRouter request body includes its JSON‑Schema
45
+ # • define an instance method for each tool that forwards the
46
+ # call to the server and appends the proper messages to the
47
+ # transcript.
48
+ # NOTE TO SELF: NEVER MOCK SERVER RESPONSES! THIS MUST WORK WITH REAL SERVERS!
49
+ def mcp(url, only: nil, except: nil)
50
+ @mcp_servers ||= {}
51
+
52
+ return if @mcp_servers.key?(url) # avoid duplicate definitions
53
+
54
+ # Connect and initialize the SSE endpoint
55
+
56
+ result = Thread::Queue.new
57
+ Thread.new do
58
+ establish_sse_connection(url, result:)
59
+ end
60
+ tools = result.pop
61
+
62
+ if tools.empty?
63
+ puts "[MCP DEBUG] No tools found from MCP server at #{url}"
64
+ return nil
65
+ end
66
+
67
+ # 3. Register each tool so ChatCompletion#tools picks them up
68
+ # Apply filters
69
+ filtered_tools = if only.present?
70
+ only_symbols = Array(only).map(&:to_sym)
71
+ tools.select { |tool| only_symbols.include?(tool["name"].to_sym) }
72
+ elsif except.present?
73
+ except_symbols = Array(except).map(&:to_sym)
74
+ tools.reject { |tool| except_symbols.include?(tool["name"].to_sym) }
75
+ else
76
+ tools
77
+ end
78
+
79
+ # Ensure FunctionDispatch is included in the class
80
+ # Explicit include in the class context
81
+ include FunctionDispatch unless included_modules.include?(FunctionDispatch)
82
+ puts "[MCP DEBUG] FunctionDispatch included in #{name}"
83
+
84
+ filtered_tools.each do |tool|
85
+ remote_name = tool[:name]
86
+ # TODO: Revisit later whether this much context is needed in the function name
87
+ local_name = "#{url.parameterize.underscore}_#{remote_name}".gsub("https_", "").to_sym
88
+
89
+ description = tool["description"]
90
+ input_schema = tool["inputSchema"] || {}
91
+
92
+ # --- register with FunctionDispatch (adds to .functions)
93
+ function(local_name, description, **{}) # placeholder parameters replaced next
94
+ latest_definition = functions.last
95
+ latest_definition[:parameters] = input_schema.deep_symbolize_keys if input_schema.present?
96
+
97
+ # --- define an instance method that proxies to the server
98
+ define_method(local_name) do |**arguments|
99
+ arguments ||= {}
100
+
101
+ call_id = SecureRandom.uuid
102
+ result = Thread::Queue.new
103
+ Thread.new do
104
+ self.class.establish_sse_connection(url, name: remote_name, arguments:, result:)
105
+ end
106
+
107
+ content_item = result.pop
108
+
109
+ # Decide what to add to the transcript
110
+ content_text = if content_item.is_a?(Hash) && content_item["type"] == "text"
111
+ content_item["text"]
112
+ else
113
+ content_item.to_json
114
+ end
115
+
116
+ # Mirror FunctionDispatch transcript behaviour
117
+ transcript << [
118
+ {
119
+ role: "assistant",
120
+ content: nil,
121
+ tool_calls: [
122
+ {
123
+ id: call_id,
124
+ type: "function",
125
+ function: {
126
+ name: remote_name,
127
+ arguments: arguments.to_json
128
+ }
129
+ }
130
+ ]
131
+ },
132
+ {
133
+ role: "tool",
134
+ tool_call_id: call_id,
135
+ name: remote_name,
136
+ content: content_text
137
+ }
138
+ ]
139
+
140
+ # Continue the chat loop if requested (same semantics as FunctionDispatch)
141
+ chat_completion(**chat_completion_args) if loop
142
+
143
+ content_text
144
+ end
145
+ end
146
+
147
+ # Store the URL and tools for future use
148
+ @mcp_servers[url] = { tools: }
149
+ end
150
+
151
+ # Establishes an SSE connection to +url+ and returns the JSON‑RPC POST endpoint
152
+ # advertised by the server. The MCP specification allows two different event
153
+ # formats during initialization:
154
+ #
155
+ # 1. A generic JSON‑RPC *initialize* event (the behaviour previously
156
+ # implemented):
157
+ #
158
+ # event: message (implicit when no explicit event type is given)
159
+ # data: {"jsonrpc":"2.0","method":"initialize","params":{"endpoint_url":"https://…/rpc"}}
160
+ #
161
+ # 2. A dedicated *endpoint* event, as implemented by the reference
162
+ # TypeScript SDK and the public GitMCP server used in our test-suite:
163
+ #
164
+ # event: endpoint\n
165
+ # data: /rpc\n
166
+ #
167
+ # This method now supports **both** formats.
168
+ #
169
+ # It uses Net::HTTP directly rather than Faraday streaming because the latter
170
+ # does not consistently surface partial body reads across adapters. The
171
+ # implementation reads the response body incrementally, splitting on the
172
+ # SSE record delimiter (double newline) and processing each event until an
173
+ # endpoint is discovered (or a timeout / connection error occurs).
174
+ def establish_sse_connection(url, name: nil, arguments: {}, result: nil)
175
+ puts "[MCP DEBUG] Establishing MCP connection with URL: #{url}"
176
+
177
+ headers = {
178
+ "Accept" => "text/event-stream",
179
+ "Cache-Control" => "no-cache",
180
+ "Connection" => "keep-alive",
181
+ "MCP-Version" => PROTOCOL_VERSION
182
+ }
183
+
184
+ endpoint_url = nil
185
+ buffer = ""
186
+
187
+ connection = Faraday.new(url:) do |faraday|
188
+ faraday.options.timeout = CONNECTION_TIMEOUT
189
+ faraday.options.open_timeout = OPEN_TIMEOUT
190
+ end
191
+
192
+ connection.get do |req|
193
+ req.headers = headers
194
+ req.options.on_data = proc do |chunk, _size|
195
+ buffer << chunk
196
+
197
+ # Process complete SSE events (separated by a blank line)
198
+ while (idx = buffer.index("\n\n"))
199
+ event_text = buffer.slice!(0..idx + 1) # include delimiter
200
+ event_type, event_data = parse_sse_fields(event_text)
201
+
202
+ case event_type
203
+ when "endpoint"
204
+ # event data is expected to be a plain string with the endpoint
205
+ puts "[MCP DEBUG] Found endpoint event: #{event_data}"
206
+ endpoint_url = build_absolute_url(url, event_data)
207
+ initialize_mcp_connection(connection, endpoint_url)
208
+ when "message"
209
+ puts "[MCP DEBUG] Received message: #{event_data}"
210
+ dispatch_event(event_data, connection, endpoint_url, name, arguments, result)
211
+ else
212
+ puts "[MCP DEBUG] Unexpected event type: #{event_type} with data: #{event_data}"
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ # Parses an SSE *event block* (text up to the blank line delimiter) and
220
+ # returns `[event_type, data]` where *event_type* defaults to "message" when
221
+ # no explicit `event:` field is present. The *data* combines all `data:`
222
+ # lines separated by newlines, as per the SSE specification.
223
+ def parse_sse_fields(event_text)
224
+ event_type = "message"
225
+ data_lines = []
226
+
227
+ event_text.each_line do |line|
228
+ case line
229
+ when /^event:\s*(.+)$/
230
+ event_type = Regexp.last_match(1).strip
231
+ when /^data:\s*(.*)$/
232
+ data_lines << Regexp.last_match(1)
233
+ end
234
+ end
235
+
236
+ [event_type, data_lines.join("\n").strip]
237
+ end
238
+
239
+ # Builds an absolute URL for +candidate+ relative to +base+.
240
+ # If +candidate+ is already absolute, it is returned unchanged.
241
+ def build_absolute_url(base, candidate)
242
+ uri = URI.parse(candidate)
243
+ return candidate if uri.absolute?
244
+
245
+ URI.join(base, candidate).to_s
246
+ rescue URI::InvalidURIError
247
+ candidate # fall back to original string
248
+ end
249
+
250
+ def initialize_mcp_connection(connection, endpoint_url)
251
+ puts "[MCP DEBUG] Initializing MCP connection with URL: #{endpoint_url}"
252
+ connection.post(endpoint_url) do |req|
253
+ req.headers["Content-Type"] = "application/json"
254
+ req.body = {
255
+ jsonrpc: JSONRPC_VERSION,
256
+ id: SecureRandom.uuid,
257
+ method: "initialize",
258
+ params: {
259
+ protocolVersion: PROTOCOL_VERSION,
260
+ capabilities: {
261
+ roots: {
262
+ listChanged: true
263
+ },
264
+ sampling: {}
265
+ },
266
+ clientInfo: {
267
+ name: "Raix",
268
+ version: Raix::VERSION
269
+ }
270
+ }
271
+ }.to_json
272
+ end
273
+ end
274
+
275
+ def dispatch_event(event_data, connection, endpoint_url, name, arguments, result)
276
+ event_data = JSON.parse(event_data, symbolize_names: true)
277
+ case event_data
278
+ in { result: { capabilities: { tools: { listChanged: true } } } }
279
+ puts "[MCP DEBUG] Received listChanged event"
280
+ acknowledge_event(connection, endpoint_url)
281
+ fetch_mcp_tools(connection, endpoint_url)
282
+ in { result: { tools: } }
283
+ puts "[MCP DEBUG] Received tools event: #{tools}"
284
+ if name.present?
285
+ puts "[MCP DEBUG] Calling function: #{name} with params: #{arguments.inspect}"
286
+ remote_dispatch(connection, endpoint_url, name, arguments)
287
+ else
288
+ result << tools # will unblock the pop on the main thread
289
+ connection.close
290
+ end
291
+ in { result: { content: } }
292
+ puts "[MCP DEBUG] Received content event: #{content}"
293
+ result << content # will unblock the pop on the main thread
294
+ connection.close
295
+ else
296
+ puts "[MCP DEBUG] Received unexpected event: #{event_data}"
297
+ end
298
+ end
299
+
300
+ def remote_dispatch(connection, endpoint_url, name, arguments)
301
+ connection.post(endpoint_url) do |req|
302
+ req.headers["Content-Type"] = "application/json"
303
+ req.body = {
304
+ jsonrpc: JSONRPC_VERSION,
305
+ id: SecureRandom.uuid,
306
+ method: "tools/call",
307
+ params: { name:, arguments: }
308
+ }.to_json
309
+ end
310
+ end
311
+
312
+ def acknowledge_event(connection, endpoint_url)
313
+ puts "[MCP DEBUG] Acknowledging event"
314
+ connection.post(endpoint_url) do |req|
315
+ req.headers["Content-Type"] = "application/json"
316
+ req.body = {
317
+ jsonrpc: JSONRPC_VERSION,
318
+ method: "notifications/initialized"
319
+ }.to_json
320
+ end
321
+ end
322
+
323
+ def fetch_mcp_tools(connection, endpoint_url)
324
+ puts "[MCP DEBUG] Fetching tools"
325
+ connection.post(endpoint_url) do |req|
326
+ req.headers["Content-Type"] = "application/json"
327
+ req.body = {
328
+ jsonrpc: JSONRPC_VERSION,
329
+ id: SecureRandom.uuid,
330
+ method: "tools/list",
331
+ params: {}
332
+ }.to_json
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end
data/lib/raix/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Raix
4
- VERSION = "0.7.3"
4
+ VERSION = "0.8.0"
5
5
  end
data/lib/raix.rb CHANGED
@@ -6,6 +6,7 @@ require_relative "raix/function_dispatch"
6
6
  require_relative "raix/prompt_declarations"
7
7
  require_relative "raix/predicate"
8
8
  require_relative "raix/response_format"
9
+ require_relative "raix/mcp"
9
10
 
10
11
  # The Raix module provides configuration options for the Raix gem.
11
12
  module Raix
data/raix.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.require_paths = ["lib"]
30
30
 
31
31
  spec.add_dependency "activesupport", ">= 6.0"
32
+ spec.add_dependency "faraday-retry", "~> 2.0"
32
33
  spec.add_dependency "open_router", "~> 0.2"
33
- spec.add_dependency "ruby-openai", "~> 7.0"
34
+ spec.add_dependency "ruby-openai", "~> 7"
34
35
  end
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Obie Fernandez
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
10
  date: 2025-04-23 00:00:00.000000000 Z
@@ -24,6 +23,20 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '6.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: faraday-retry
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
27
40
  - !ruby/object:Gem::Dependency
28
41
  name: open_router
29
42
  requirement: !ruby/object:Gem::Requirement
@@ -44,15 +57,14 @@ dependencies:
44
57
  requirements:
45
58
  - - "~>"
46
59
  - !ruby/object:Gem::Version
47
- version: '7.0'
60
+ version: '7'
48
61
  type: :runtime
49
62
  prerelease: false
50
63
  version_requirements: !ruby/object:Gem::Requirement
51
64
  requirements:
52
65
  - - "~>"
53
66
  - !ruby/object:Gem::Version
54
- version: '7.0'
55
- description:
67
+ version: '7'
56
68
  email:
57
69
  - obiefernandez@gmail.com
58
70
  executables: []
@@ -74,6 +86,7 @@ files:
74
86
  - lib/raix.rb
75
87
  - lib/raix/chat_completion.rb
76
88
  - lib/raix/function_dispatch.rb
89
+ - lib/raix/mcp.rb
77
90
  - lib/raix/message_adapters/base.rb
78
91
  - lib/raix/predicate.rb
79
92
  - lib/raix/prompt_declarations.rb
@@ -88,7 +101,6 @@ metadata:
88
101
  homepage_uri: https://github.com/OlympiaAI/raix
89
102
  source_code_uri: https://github.com/OlympiaAI/raix
90
103
  changelog_uri: https://github.com/OlympiaAI/raix/blob/main/CHANGELOG.md
91
- post_install_message:
92
104
  rdoc_options: []
93
105
  require_paths:
94
106
  - lib
@@ -103,8 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
115
  - !ruby/object:Gem::Version
104
116
  version: '0'
105
117
  requirements: []
106
- rubygems_version: 3.5.21
107
- signing_key:
118
+ rubygems_version: 3.6.2
108
119
  specification_version: 4
109
120
  summary: Ruby AI eXtensions
110
121
  test_files: []