whoosh 1.0.1

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 (73) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +413 -0
  4. data/exe/whoosh +6 -0
  5. data/lib/whoosh/app.rb +655 -0
  6. data/lib/whoosh/auth/access_control.rb +26 -0
  7. data/lib/whoosh/auth/api_key.rb +30 -0
  8. data/lib/whoosh/auth/jwt.rb +88 -0
  9. data/lib/whoosh/auth/oauth2.rb +33 -0
  10. data/lib/whoosh/auth/rate_limiter.rb +86 -0
  11. data/lib/whoosh/auth/token_tracker.rb +40 -0
  12. data/lib/whoosh/cache/memory_store.rb +57 -0
  13. data/lib/whoosh/cache/redis_store.rb +72 -0
  14. data/lib/whoosh/cache.rb +26 -0
  15. data/lib/whoosh/cli/generators.rb +133 -0
  16. data/lib/whoosh/cli/main.rb +277 -0
  17. data/lib/whoosh/cli/project_generator.rb +172 -0
  18. data/lib/whoosh/config.rb +160 -0
  19. data/lib/whoosh/database.rb +47 -0
  20. data/lib/whoosh/dependency_injection.rb +103 -0
  21. data/lib/whoosh/endpoint.rb +79 -0
  22. data/lib/whoosh/env_loader.rb +46 -0
  23. data/lib/whoosh/errors.rb +68 -0
  24. data/lib/whoosh/http/response.rb +26 -0
  25. data/lib/whoosh/http.rb +73 -0
  26. data/lib/whoosh/instrumentation.rb +22 -0
  27. data/lib/whoosh/job.rb +24 -0
  28. data/lib/whoosh/jobs/memory_backend.rb +45 -0
  29. data/lib/whoosh/jobs/worker.rb +73 -0
  30. data/lib/whoosh/jobs.rb +50 -0
  31. data/lib/whoosh/logger.rb +62 -0
  32. data/lib/whoosh/mcp/client.rb +71 -0
  33. data/lib/whoosh/mcp/client_manager.rb +73 -0
  34. data/lib/whoosh/mcp/protocol.rb +39 -0
  35. data/lib/whoosh/mcp/server.rb +66 -0
  36. data/lib/whoosh/mcp/transport/sse.rb +26 -0
  37. data/lib/whoosh/mcp/transport/stdio.rb +33 -0
  38. data/lib/whoosh/metrics.rb +84 -0
  39. data/lib/whoosh/middleware/cors.rb +61 -0
  40. data/lib/whoosh/middleware/plugin_hooks.rb +27 -0
  41. data/lib/whoosh/middleware/request_limit.rb +28 -0
  42. data/lib/whoosh/middleware/request_logger.rb +39 -0
  43. data/lib/whoosh/middleware/security_headers.rb +28 -0
  44. data/lib/whoosh/middleware/stack.rb +25 -0
  45. data/lib/whoosh/openapi/generator.rb +50 -0
  46. data/lib/whoosh/openapi/schema_converter.rb +48 -0
  47. data/lib/whoosh/openapi/ui.rb +62 -0
  48. data/lib/whoosh/paginate.rb +64 -0
  49. data/lib/whoosh/performance.rb +20 -0
  50. data/lib/whoosh/plugins/base.rb +42 -0
  51. data/lib/whoosh/plugins/registry.rb +139 -0
  52. data/lib/whoosh/request.rb +93 -0
  53. data/lib/whoosh/response.rb +39 -0
  54. data/lib/whoosh/router.rb +112 -0
  55. data/lib/whoosh/schema.rb +194 -0
  56. data/lib/whoosh/serialization/json.rb +73 -0
  57. data/lib/whoosh/serialization/msgpack.rb +51 -0
  58. data/lib/whoosh/serialization/negotiator.rb +37 -0
  59. data/lib/whoosh/serialization/protobuf.rb +43 -0
  60. data/lib/whoosh/shutdown.rb +30 -0
  61. data/lib/whoosh/storage/local.rb +24 -0
  62. data/lib/whoosh/storage/s3.rb +31 -0
  63. data/lib/whoosh/storage.rb +20 -0
  64. data/lib/whoosh/streaming/llm_stream.rb +51 -0
  65. data/lib/whoosh/streaming/sse.rb +61 -0
  66. data/lib/whoosh/streaming/stream_body.rb +59 -0
  67. data/lib/whoosh/streaming/websocket.rb +51 -0
  68. data/lib/whoosh/test.rb +70 -0
  69. data/lib/whoosh/types.rb +11 -0
  70. data/lib/whoosh/uploaded_file.rb +47 -0
  71. data/lib/whoosh/version.rb +5 -0
  72. data/lib/whoosh.rb +86 -0
  73. metadata +265 -0
@@ -0,0 +1,51 @@
1
+ # lib/whoosh/streaming/websocket.rb
2
+ # frozen_string_literal: true
3
+
4
+ require "json"
5
+
6
+ module Whoosh
7
+ module Streaming
8
+ class WebSocket
9
+ def initialize(io)
10
+ @io = io
11
+ @closed = false
12
+ @on_message = nil
13
+ @on_close = nil
14
+ end
15
+
16
+ def send(data)
17
+ return if @closed
18
+ formatted = data.is_a?(String) ? data : JSON.generate(data)
19
+ @io.write(formatted + "\n")
20
+ @io.flush if @io.respond_to?(:flush)
21
+ rescue IOError, Errno::EPIPE
22
+ @closed = true
23
+ end
24
+
25
+ def on_message(&block)
26
+ @on_message = block
27
+ end
28
+
29
+ def on_close(&block)
30
+ @on_close = block
31
+ end
32
+
33
+ def trigger_message(msg)
34
+ @on_message&.call(msg)
35
+ end
36
+
37
+ def trigger_close
38
+ @on_close&.call
39
+ @closed = true
40
+ end
41
+
42
+ def close
43
+ @closed = true
44
+ end
45
+
46
+ def closed?
47
+ @closed
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,70 @@
1
+ # lib/whoosh/test.rb
2
+ # frozen_string_literal: true
3
+
4
+ require "rack/test"
5
+ require "json"
6
+
7
+ module Whoosh
8
+ module Test
9
+ include Rack::Test::Methods
10
+
11
+ # Override in your test class to return the Rack app
12
+ def app
13
+ raise NotImplementedError, "Define #app in your test class to return a Rack app"
14
+ end
15
+
16
+ # --- Request helpers ---
17
+
18
+ def post_json(path, body = {}, headers: {})
19
+ merged_headers = { "CONTENT_TYPE" => "application/json" }.merge(headers)
20
+ post path, JSON.generate(body), merged_headers
21
+ end
22
+
23
+ def put_json(path, body = {}, headers: {})
24
+ merged_headers = { "CONTENT_TYPE" => "application/json" }.merge(headers)
25
+ put path, JSON.generate(body), merged_headers
26
+ end
27
+
28
+ def patch_json(path, body = {}, headers: {})
29
+ merged_headers = { "CONTENT_TYPE" => "application/json" }.merge(headers)
30
+ patch path, JSON.generate(body), merged_headers
31
+ end
32
+
33
+ def get_with_auth(path, key:, header: "HTTP_X_API_KEY")
34
+ get path, {}, { header => key }
35
+ end
36
+
37
+ def post_with_auth(path, body = {}, key:, header: "HTTP_X_API_KEY")
38
+ post path, JSON.generate(body), { "CONTENT_TYPE" => "application/json", header => key }
39
+ end
40
+
41
+ # --- Response assertions ---
42
+
43
+ def assert_response(expected_status)
44
+ expect(last_response.status).to eq(expected_status)
45
+ end
46
+
47
+ def assert_json(expected_hash)
48
+ body = JSON.parse(last_response.body)
49
+ expected_hash.each do |key, value|
50
+ expect(body[key.to_s]).to eq(value)
51
+ end
52
+ end
53
+
54
+ def assert_json_path(path, expected_value)
55
+ body = JSON.parse(last_response.body)
56
+ keys = path.to_s.split(".")
57
+ value = keys.reduce(body) { |h, k| h.is_a?(Hash) ? h[k] : nil }
58
+ expect(value).to eq(expected_value)
59
+ end
60
+
61
+ def assert_json_includes(key)
62
+ body = JSON.parse(last_response.body)
63
+ expect(body).to have_key(key.to_s)
64
+ end
65
+
66
+ def response_json
67
+ JSON.parse(last_response.body)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-types"
4
+
5
+ module Whoosh
6
+ module Types
7
+ include Dry.Types()
8
+
9
+ Bool = Types::Params::Bool
10
+ end
11
+ end
@@ -0,0 +1,47 @@
1
+ # lib/whoosh/uploaded_file.rb
2
+ # frozen_string_literal: true
3
+
4
+ require "base64"
5
+
6
+ module Whoosh
7
+ class UploadedFile
8
+ attr_reader :filename, :content_type
9
+
10
+ def initialize(rack_hash, storage: nil)
11
+ @filename = rack_hash[:filename]
12
+ @content_type = rack_hash[:type]
13
+ @tempfile = rack_hash[:tempfile]
14
+ @storage = storage
15
+ end
16
+
17
+ def size
18
+ @tempfile.size
19
+ end
20
+
21
+ def read
22
+ @tempfile.rewind
23
+ @tempfile.read
24
+ end
25
+
26
+ def read_text
27
+ read.force_encoding("UTF-8")
28
+ end
29
+
30
+ def to_base64
31
+ Base64.strict_encode64(read)
32
+ end
33
+
34
+ def save(prefix = "")
35
+ raise Errors::DependencyError, "No storage adapter configured" unless @storage
36
+ @storage.save(self, prefix)
37
+ end
38
+
39
+ def validate!(types: nil, max_size: nil)
40
+ errors = []
41
+ errors << { field: "file", message: "No file uploaded" } if @filename.nil? || @filename.empty?
42
+ errors << { field: "file", message: "File type #{@content_type} not allowed" } if types && !types.include?(@content_type)
43
+ errors << { field: "file", message: "File too large (#{size} bytes > #{max_size})" } if max_size && size > max_size
44
+ raise Errors::ValidationError.new(errors) unless errors.empty?
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Whoosh
4
+ VERSION = "1.0.1"
5
+ end
data/lib/whoosh.rb ADDED
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "whoosh/version"
4
+
5
+ module Whoosh
6
+ autoload :App, "whoosh/app"
7
+ autoload :Cache, "whoosh/cache"
8
+ autoload :EnvLoader, "whoosh/env_loader"
9
+ autoload :Instrumentation, "whoosh/instrumentation"
10
+ autoload :Config, "whoosh/config"
11
+ autoload :Database, "whoosh/database"
12
+ autoload :DependencyInjection, "whoosh/dependency_injection"
13
+ autoload :Endpoint, "whoosh/endpoint"
14
+ autoload :Errors, "whoosh/errors"
15
+ autoload :Logger, "whoosh/logger"
16
+ autoload :Request, "whoosh/request"
17
+ autoload :Response, "whoosh/response"
18
+ autoload :Router, "whoosh/router"
19
+ autoload :Schema, "whoosh/schema"
20
+ autoload :Shutdown, "whoosh/shutdown"
21
+ autoload :Test, "whoosh/test"
22
+ autoload :Types, "whoosh/types"
23
+ autoload :HTTP, "whoosh/http"
24
+ autoload :Storage, "whoosh/storage"
25
+ autoload :UploadedFile, "whoosh/uploaded_file"
26
+ autoload :Performance, "whoosh/performance"
27
+ autoload :Job, "whoosh/job"
28
+ autoload :Jobs, "whoosh/jobs"
29
+ autoload :Metrics, "whoosh/metrics"
30
+ autoload :Paginate, "whoosh/paginate"
31
+
32
+ module Auth
33
+ autoload :ApiKey, "whoosh/auth/api_key"
34
+ autoload :Jwt, "whoosh/auth/jwt"
35
+ autoload :OAuth2, "whoosh/auth/oauth2"
36
+ autoload :RateLimiter, "whoosh/auth/rate_limiter"
37
+ autoload :TokenTracker, "whoosh/auth/token_tracker"
38
+ autoload :AccessControl, "whoosh/auth/access_control"
39
+ end
40
+
41
+ module MCP
42
+ autoload :Server, "whoosh/mcp/server"
43
+ autoload :Client, "whoosh/mcp/client"
44
+ autoload :ClientManager, "whoosh/mcp/client_manager"
45
+ autoload :Protocol, "whoosh/mcp/protocol"
46
+
47
+ module Transport
48
+ autoload :SSE, "whoosh/mcp/transport/sse"
49
+ autoload :Stdio, "whoosh/mcp/transport/stdio"
50
+ end
51
+ end
52
+
53
+ module Middleware
54
+ autoload :Stack, "whoosh/middleware/stack"
55
+ autoload :Cors, "whoosh/middleware/cors"
56
+ autoload :RequestLogger, "whoosh/middleware/request_logger"
57
+ autoload :SecurityHeaders, "whoosh/middleware/security_headers"
58
+ autoload :RequestLimit, "whoosh/middleware/request_limit"
59
+ autoload :PluginHooks, "whoosh/middleware/plugin_hooks"
60
+ end
61
+
62
+ module Streaming
63
+ autoload :SSE, "whoosh/streaming/sse"
64
+ autoload :WebSocket, "whoosh/streaming/websocket"
65
+ autoload :LlmStream, "whoosh/streaming/llm_stream"
66
+ autoload :StreamBody, "whoosh/streaming/stream_body"
67
+ end
68
+
69
+ module OpenAPI
70
+ autoload :Generator, "whoosh/openapi/generator"
71
+ autoload :UI, "whoosh/openapi/ui"
72
+ autoload :SchemaConverter, "whoosh/openapi/schema_converter"
73
+ end
74
+
75
+ module Serialization
76
+ autoload :Json, "whoosh/serialization/json"
77
+ autoload :Msgpack, "whoosh/serialization/msgpack"
78
+ autoload :Protobuf, "whoosh/serialization/protobuf"
79
+ autoload :Negotiator, "whoosh/serialization/negotiator"
80
+ end
81
+
82
+ module Plugins
83
+ autoload :Registry, "whoosh/plugins/registry"
84
+ autoload :Base, "whoosh/plugins/base"
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,265 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: whoosh
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Johannes Dwi Cahyo
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: base64
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.2'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.2'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rack
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: dry-schema
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.13'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.13'
54
+ - !ruby/object:Gem::Dependency
55
+ name: dry-types
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.7'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.7'
68
+ - !ruby/object:Gem::Dependency
69
+ name: thor
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.3'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.3'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rackup
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '2.1'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '2.1'
96
+ - !ruby/object:Gem::Dependency
97
+ name: webrick
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.8'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.8'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.13'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.13'
124
+ - !ruby/object:Gem::Dependency
125
+ name: rack-test
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '2.1'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '2.1'
138
+ - !ruby/object:Gem::Dependency
139
+ name: rake
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '13.0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '13.0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: benchmark-ips
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '2.13'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '2.13'
166
+ description: A fast, secure Ruby API framework inspired by FastAPI with built-in MCP
167
+ support, auto-generated OpenAPI docs, and seamless AI gem ecosystem integration.
168
+ executables:
169
+ - whoosh
170
+ extensions: []
171
+ extra_rdoc_files: []
172
+ files:
173
+ - LICENSE
174
+ - README.md
175
+ - exe/whoosh
176
+ - lib/whoosh.rb
177
+ - lib/whoosh/app.rb
178
+ - lib/whoosh/auth/access_control.rb
179
+ - lib/whoosh/auth/api_key.rb
180
+ - lib/whoosh/auth/jwt.rb
181
+ - lib/whoosh/auth/oauth2.rb
182
+ - lib/whoosh/auth/rate_limiter.rb
183
+ - lib/whoosh/auth/token_tracker.rb
184
+ - lib/whoosh/cache.rb
185
+ - lib/whoosh/cache/memory_store.rb
186
+ - lib/whoosh/cache/redis_store.rb
187
+ - lib/whoosh/cli/generators.rb
188
+ - lib/whoosh/cli/main.rb
189
+ - lib/whoosh/cli/project_generator.rb
190
+ - lib/whoosh/config.rb
191
+ - lib/whoosh/database.rb
192
+ - lib/whoosh/dependency_injection.rb
193
+ - lib/whoosh/endpoint.rb
194
+ - lib/whoosh/env_loader.rb
195
+ - lib/whoosh/errors.rb
196
+ - lib/whoosh/http.rb
197
+ - lib/whoosh/http/response.rb
198
+ - lib/whoosh/instrumentation.rb
199
+ - lib/whoosh/job.rb
200
+ - lib/whoosh/jobs.rb
201
+ - lib/whoosh/jobs/memory_backend.rb
202
+ - lib/whoosh/jobs/worker.rb
203
+ - lib/whoosh/logger.rb
204
+ - lib/whoosh/mcp/client.rb
205
+ - lib/whoosh/mcp/client_manager.rb
206
+ - lib/whoosh/mcp/protocol.rb
207
+ - lib/whoosh/mcp/server.rb
208
+ - lib/whoosh/mcp/transport/sse.rb
209
+ - lib/whoosh/mcp/transport/stdio.rb
210
+ - lib/whoosh/metrics.rb
211
+ - lib/whoosh/middleware/cors.rb
212
+ - lib/whoosh/middleware/plugin_hooks.rb
213
+ - lib/whoosh/middleware/request_limit.rb
214
+ - lib/whoosh/middleware/request_logger.rb
215
+ - lib/whoosh/middleware/security_headers.rb
216
+ - lib/whoosh/middleware/stack.rb
217
+ - lib/whoosh/openapi/generator.rb
218
+ - lib/whoosh/openapi/schema_converter.rb
219
+ - lib/whoosh/openapi/ui.rb
220
+ - lib/whoosh/paginate.rb
221
+ - lib/whoosh/performance.rb
222
+ - lib/whoosh/plugins/base.rb
223
+ - lib/whoosh/plugins/registry.rb
224
+ - lib/whoosh/request.rb
225
+ - lib/whoosh/response.rb
226
+ - lib/whoosh/router.rb
227
+ - lib/whoosh/schema.rb
228
+ - lib/whoosh/serialization/json.rb
229
+ - lib/whoosh/serialization/msgpack.rb
230
+ - lib/whoosh/serialization/negotiator.rb
231
+ - lib/whoosh/serialization/protobuf.rb
232
+ - lib/whoosh/shutdown.rb
233
+ - lib/whoosh/storage.rb
234
+ - lib/whoosh/storage/local.rb
235
+ - lib/whoosh/storage/s3.rb
236
+ - lib/whoosh/streaming/llm_stream.rb
237
+ - lib/whoosh/streaming/sse.rb
238
+ - lib/whoosh/streaming/stream_body.rb
239
+ - lib/whoosh/streaming/websocket.rb
240
+ - lib/whoosh/test.rb
241
+ - lib/whoosh/types.rb
242
+ - lib/whoosh/uploaded_file.rb
243
+ - lib/whoosh/version.rb
244
+ homepage: https://github.com/johannesdwicahyo/whoosh
245
+ licenses:
246
+ - MIT
247
+ metadata: {}
248
+ rdoc_options: []
249
+ require_paths:
250
+ - lib
251
+ required_ruby_version: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ">="
254
+ - !ruby/object:Gem::Version
255
+ version: 3.4.0
256
+ required_rubygems_version: !ruby/object:Gem::Requirement
257
+ requirements:
258
+ - - ">="
259
+ - !ruby/object:Gem::Version
260
+ version: '0'
261
+ requirements: []
262
+ rubygems_version: 3.6.9
263
+ specification_version: 4
264
+ summary: AI-first Ruby API framework
265
+ test_files: []