simforge 0.5.0 → 0.5.2

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: 662f1ce8942083e856907a38568a40b252c4d6360f043fc25da58900a46e36e7
4
- data.tar.gz: 9d74cf518171472d22b49c6b8fb3544e258607e5284acebe0f6b46e71213e0cd
3
+ metadata.gz: b9f2c1b27222c1a19c1ee819c021349f8f7cd479432e38a8b8ed5d218b13b026
4
+ data.tar.gz: '059c030ed76519b30a5fd187392af8af0d29ba6a0704132359792ef4381fed9c'
5
5
  SHA512:
6
- metadata.gz: 556e17aa0f010ecb394f7a5937c3c02a43ef0d76bffe00082899074a19f26c555bec5c4d47dfe1afa98c34f7093beae5dd4b4a4d2d9d00a68d0155aadd979aea
7
- data.tar.gz: 14cd3fbc8c4ea4096036ce312e6eac67ab7b57a634c10faba0962fa3dd10368928ebc3c25c1236b5ff6019a8db36094b0a4e4a8eeb737da2c76fc42e5525cd62
6
+ metadata.gz: 7057e4d20182d99a6c71b0a5fe4f52f7d661230a111967a805421f5459463371ecc8849a7bbfcb7f313e16a3bf9623b50002393eeed91ef7e311cbfe43fd6e3a
7
+ data.tar.gz: a76648e123b02fc6a00124910c42624c9da7819df4b8437d8fb1b8aed64498d72871749da56e20a8ba94bc86d2ba0dd013da70ca843900138e33b65ac5e00e12
data/README.md ADDED
@@ -0,0 +1,342 @@
1
+ # Simforge Ruby SDK
2
+
3
+ Ruby client library for [Simforge](https://simforge.goharvest.ai) - trace and monitor your Ruby application's function execution with nested span support.
4
+
5
+ ## Installation
6
+
7
+ Add to your `Gemfile`:
8
+
9
+ ```ruby
10
+ gem 'simforge'
11
+ ```
12
+
13
+ Or install directly:
14
+
15
+ ```bash
16
+ gem install simforge
17
+ ```
18
+
19
+ ## Requirements
20
+
21
+ - Ruby >= 3.1
22
+ - No external runtime dependencies (uses stdlib only)
23
+
24
+ ## Quick Start
25
+
26
+ ```ruby
27
+ require 'simforge'
28
+
29
+ # Configure once at application startup
30
+ Simforge.configure(
31
+ api_key: ENV.fetch('SIMFORGE_API_KEY')
32
+ )
33
+
34
+ # Add tracing to your classes
35
+ class OrderService
36
+ include Simforge::Traceable
37
+ simforge_function "order-processing"
38
+
39
+ simforge_span :process_order, type: "function"
40
+ def process_order(order_id)
41
+ # Your code here
42
+ { status: "completed" }
43
+ end
44
+ end
45
+
46
+ # Use your code normally - spans are sent automatically
47
+ service = OrderService.new
48
+ service.process_order("order-123")
49
+
50
+ # Flush traces before exit (automatic via at_exit hook)
51
+ Simforge.flush_traces
52
+ ```
53
+
54
+ ## Configuration
55
+
56
+ ### Basic Configuration
57
+
58
+ ```ruby
59
+ Simforge.configure(
60
+ api_key: "your-api-key"
61
+ )
62
+ ```
63
+
64
+ ### Custom Service URL
65
+
66
+ ```ruby
67
+ Simforge.configure(
68
+ api_key: "your-api-key",
69
+ service_url: "https://custom.example.com"
70
+ )
71
+ ```
72
+
73
+ ### Disabling Span Sending
74
+
75
+ The `enabled` option controls whether spans are sent to Simforge. When disabled, your code executes normally but no spans are created or sent.
76
+
77
+ ```ruby
78
+ # Disable tracing (useful for development/test environments)
79
+ Simforge.configure(
80
+ api_key: ENV.fetch('SIMFORGE_API_KEY', 'dummy-key'),
81
+ enabled: false
82
+ )
83
+ ```
84
+
85
+ **Common patterns:**
86
+
87
+ ```ruby
88
+ # Rails: Enable only in production
89
+ Simforge.configure(
90
+ api_key: ENV.fetch('SIMFORGE_API_KEY', 'dummy-key'),
91
+ enabled: Rails.env.production?
92
+ )
93
+
94
+ # Environment variable control
95
+ Simforge.configure(
96
+ api_key: ENV.fetch('SIMFORGE_API_KEY', 'dummy-key'),
97
+ enabled: ENV.fetch('SIMFORGE_ENABLED', 'false') == 'true'
98
+ )
99
+
100
+ # Multi-environment control
101
+ Simforge.configure(
102
+ api_key: ENV.fetch('SIMFORGE_API_KEY', 'dummy-key'),
103
+ enabled: ['production', 'staging'].include?(ENV['RACK_ENV'])
104
+ )
105
+ ```
106
+
107
+ When `enabled: false`:
108
+ - ✅ Code executes normally with no performance impact
109
+ - ✅ Return values and errors work as expected
110
+ - ✅ Nested spans are properly skipped
111
+ - ❌ No HTTP requests are made
112
+ - ❌ No span data is collected or sent
113
+
114
+ ## Usage
115
+
116
+ ### Class-Level Trace Function Key
117
+
118
+ All spans in the class share the same trace function key:
119
+
120
+ ```ruby
121
+ class PaymentService
122
+ include Simforge::Traceable
123
+ simforge_function "payment-processing"
124
+
125
+ simforge_span :charge_card, type: "function"
126
+ def charge_card(amount)
127
+ # Traced automatically
128
+ end
129
+
130
+ simforge_span :refund, type: "function"
131
+ def refund(transaction_id)
132
+ # Also uses "payment-processing" key
133
+ end
134
+ end
135
+ ```
136
+
137
+ ### Per-Span Trace Function Key
138
+
139
+ Each span can declare its own key:
140
+
141
+ ```ruby
142
+ class NotificationService
143
+ include Simforge::Traceable
144
+
145
+ simforge_span :send_email, trace_function_key: "email-notifications", type: "function"
146
+ def send_email(to, subject)
147
+ # Uses "email-notifications" key
148
+ end
149
+
150
+ simforge_span :send_sms, trace_function_key: "sms-notifications", type: "function"
151
+ def send_sms(to, message)
152
+ # Uses "sms-notifications" key
153
+ end
154
+ end
155
+ ```
156
+
157
+ ### Span Types
158
+
159
+ Simforge supports the following span types:
160
+
161
+ - `"llm"` - LLM API calls
162
+ - `"agent"` - Agent decision loops
163
+ - `"function"` - Business logic functions
164
+ - `"guardrail"` - Validation and safety checks
165
+ - `"handoff"` - Human-in-the-loop interactions
166
+ - `"custom"` - Custom span types (default)
167
+
168
+ ```ruby
169
+ simforge_span :validate_input, type: "guardrail"
170
+ simforge_span :call_openai, type: "llm"
171
+ simforge_span :agent_loop, type: "agent"
172
+ ```
173
+
174
+ ### Custom Span Names
175
+
176
+ By default, the method name is used as the span name. Override it:
177
+
178
+ ```ruby
179
+ simforge_span :process_order, name: "ProcessOrderV2", type: "function"
180
+ def process_order(order_id)
181
+ # Span will be named "ProcessOrderV2"
182
+ end
183
+ ```
184
+
185
+ ### Nested Spans
186
+
187
+ Spans automatically track parent-child relationships:
188
+
189
+ ```ruby
190
+ class OrderPipeline
191
+ include Simforge::Traceable
192
+ simforge_function "order-pipeline"
193
+
194
+ simforge_span :process, type: "function"
195
+ def process(order_id)
196
+ validate(order_id)
197
+ # More processing
198
+ end
199
+
200
+ simforge_span :validate, type: "guardrail"
201
+ def validate(order_id)
202
+ check_fraud(order_id)
203
+ # More validation
204
+ end
205
+
206
+ simforge_span :check_fraud, type: "guardrail"
207
+ def check_fraud(order_id)
208
+ # Fraud checking logic
209
+ end
210
+ end
211
+
212
+ # Creates 3 nested spans:
213
+ # process (parent)
214
+ # └─ validate (child)
215
+ # └─ check_fraud (grandchild)
216
+ ```
217
+
218
+ ### Input/Output Capture
219
+
220
+ Positional and keyword arguments are automatically captured:
221
+
222
+ ```ruby
223
+ simforge_span :process_order, type: "function"
224
+ def process_order(order_id, priority: :normal)
225
+ # Input captured: { "order_id" => "123", "priority" => "normal" }
226
+ { status: "completed" }
227
+ # Output captured: { "status" => "completed" }
228
+ end
229
+ ```
230
+
231
+ ### Metadata
232
+
233
+ Add custom metadata to spans:
234
+
235
+ ```ruby
236
+ # Definition-time metadata
237
+ simforge_span :process_order,
238
+ type: "function",
239
+ metadata: { "region" => "us-east", "version" => "v2" }
240
+ def process_order(order_id)
241
+ # ...
242
+ end
243
+
244
+ # Runtime metadata (inside a span)
245
+ simforge_span :process_order, type: "function"
246
+ def process_order(order_id)
247
+ Simforge.current_span.set_metadata(
248
+ "user_id" => current_user.id,
249
+ "request_id" => request.id
250
+ )
251
+ # Runtime metadata merges with definition-time metadata
252
+ end
253
+ ```
254
+
255
+ ### Wrapping External Code
256
+
257
+ Wrap third-party library methods without modifying them:
258
+
259
+ ```ruby
260
+ class ExternalHttpClient
261
+ def get(url)
262
+ # Third-party code
263
+ end
264
+ end
265
+
266
+ # Add tracing via wrap
267
+ Simforge::Traceable.wrap(
268
+ ExternalHttpClient,
269
+ :get,
270
+ trace_function_key: "http-client",
271
+ type: "function"
272
+ )
273
+
274
+ # Now traced automatically
275
+ client = ExternalHttpClient.new
276
+ client.get("https://api.example.com")
277
+ ```
278
+
279
+ ### Error Handling
280
+
281
+ Errors are automatically captured and re-raised:
282
+
283
+ ```ruby
284
+ simforge_span :risky_operation, type: "function"
285
+ def risky_operation
286
+ raise StandardError, "Something went wrong"
287
+ end
288
+
289
+ begin
290
+ service.risky_operation
291
+ rescue StandardError => e
292
+ # Error is captured in span and re-raised
293
+ puts "Caught: #{e.message}"
294
+ end
295
+ ```
296
+
297
+ ## Lifecycle
298
+
299
+ ### Automatic Flush
300
+
301
+ Spans are sent in background threads and automatically flushed on exit via `at_exit` hook.
302
+
303
+ ### Manual Flush
304
+
305
+ Wait for all pending spans to be sent:
306
+
307
+ ```ruby
308
+ Simforge.flush_traces
309
+ # Blocks until all background threads complete
310
+ ```
311
+
312
+ ### Reset Client
313
+
314
+ Clear the global client (useful for testing):
315
+
316
+ ```ruby
317
+ Simforge.reset!
318
+ ```
319
+
320
+ ## Thread Safety
321
+
322
+ - Each thread has its own span context stack (using `Thread.current`)
323
+ - Nested spans only work within the same thread
324
+ - Background span sending is thread-safe
325
+
326
+ ## Examples
327
+
328
+ See [simforge-ruby-example/](../simforge-ruby-example/) for complete working examples:
329
+
330
+ - [test_span.rb](../simforge-ruby-example/scripts/test_span.rb) - Basic span creation
331
+ - [test_nested_spans.rb](../simforge-ruby-example/scripts/test_nested_spans.rb) - Nested span hierarchies
332
+ - [test_wrap.rb](../simforge-ruby-example/scripts/test_wrap.rb) - Wrapping external code
333
+ - [test_enabled.rb](../simforge-ruby-example/scripts/test_enabled.rb) - Using the enabled flag
334
+ - [test_metadata.rb](../simforge-ruby-example/scripts/test_metadata.rb) - Custom metadata
335
+
336
+ ## Development
337
+
338
+ See [DEVELOPMENT.md](DEVELOPMENT.md) for development setup, testing, and publishing instructions.
339
+
340
+ ## License
341
+
342
+ MIT
@@ -12,18 +12,23 @@ module Simforge
12
12
  class Client
13
13
  SPAN_TYPES = %w[llm agent function guardrail handoff custom].freeze
14
14
 
15
- attr_reader :api_key, :service_url
15
+ attr_reader :api_key, :service_url, :enabled
16
16
 
17
- def initialize(api_key:, service_url: nil)
17
+ def initialize(api_key:, service_url: nil, enabled: true)
18
18
  @api_key = api_key
19
19
  @service_url = service_url || DEFAULT_SERVICE_URL
20
+ @enabled = enabled
21
+ if @enabled && (@api_key.nil? || @api_key.to_s.strip.empty?)
22
+ warn "Simforge: api_key is empty — tracing is disabled. Provide a valid API key to enable tracing."
23
+ @enabled = false
24
+ end
20
25
  @http_client = HttpClient.new(api_key:, service_url: @service_url)
21
26
  end
22
27
 
23
28
  # Execute a block inside a span context, sending trace data on completion.
24
29
  # Called by Traceable — not intended for direct use.
25
- def execute_span(trace_function_key:, span_name:, span_type:, function_name:, args:, kwargs:)
26
- validate_span_type!(span_type)
30
+ def execute_span(trace_function_key:, span_name:, span_type:, function_name:, args:, kwargs:, metadata: nil)
31
+ return yield unless @enabled
27
32
 
28
33
  parent = SpanContext.current
29
34
  trace_id = parent ? parent[:trace_id] : SecureRandom.uuid
@@ -33,30 +38,51 @@ module Simforge
33
38
 
34
39
  result = nil
35
40
  error = nil
41
+ runtime_metadata = nil
36
42
 
37
43
  begin
38
- result = SpanContext.with_span(trace_id:, span_id:) { yield }
44
+ SpanContext.with_span(trace_id:, span_id:) do
45
+ result = yield
46
+ ensure
47
+ # Capture runtime metadata before the span context is popped
48
+ runtime_metadata = SpanContext.current&.dig(:metadata)
49
+ end
39
50
  rescue => e
40
51
  error = e.message
41
52
  raise
42
53
  ensure
43
- ended_at = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ")
44
-
45
- send_span(
46
- trace_function_key:,
47
- trace_id:,
48
- span_id:,
49
- parent_span_id:,
50
- span_name:,
51
- span_type:,
52
- function_name:,
53
- args:,
54
- kwargs:,
55
- result:,
56
- error:,
57
- started_at:,
58
- ended_at:
59
- )
54
+ # Never crash the host app due to span building/sending
55
+ begin
56
+ ended_at = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ")
57
+
58
+ # Merge runtime metadata with definition-time metadata (runtime wins)
59
+ merged_metadata = if runtime_metadata
60
+ (metadata || {}).merge(runtime_metadata)
61
+ else
62
+ metadata
63
+ end
64
+
65
+ send_span(
66
+ trace_function_key:,
67
+ trace_id:,
68
+ span_id:,
69
+ parent_span_id:,
70
+ span_name:,
71
+ span_type:,
72
+ function_name:,
73
+ metadata: merged_metadata,
74
+ args:,
75
+ kwargs:,
76
+ result:,
77
+ error:,
78
+ started_at:,
79
+ ended_at:
80
+ )
81
+ rescue Exception # rubocop:disable Lint/RescueException
82
+ # Silently ignore — user's result/exception takes priority
83
+ # Catches Exception (not just StandardError) to handle SystemStackError
84
+ # from deeply nested serialization
85
+ end
60
86
  end
61
87
 
62
88
  result
@@ -71,7 +97,7 @@ module Simforge
71
97
  end
72
98
 
73
99
  def send_span(trace_function_key:, trace_id:, span_id:, parent_span_id:,
74
- span_name:, span_type:, function_name:, args:, kwargs:, result:, error:,
100
+ span_name:, span_type:, function_name:, metadata:, args:, kwargs:, result:, error:,
75
101
  started_at:, ended_at:)
76
102
  # Human-readable JSON (input/output fields)
77
103
  human_inputs = Serialize.serialize_inputs(args, kwargs)
@@ -92,6 +118,7 @@ module Simforge
92
118
  span_data["input_serialized"] = marshalled_input if marshalled_input
93
119
  span_data["output_serialized"] = marshalled_output if marshalled_output
94
120
  span_data["error"] = error if error
121
+ span_data["metadata"] = metadata if metadata
95
122
 
96
123
  raw_span = {
97
124
  "id" => span_id,
@@ -1,6 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Simforge
4
+ # Handle to the current active span, allowing runtime metadata to be set.
5
+ class CurrentSpan
6
+ def initialize(context)
7
+ @context = context
8
+ end
9
+
10
+ # Set custom metadata on this span. Merges with any existing metadata
11
+ # (both definition-time and previous runtime calls), with later values
12
+ # taking precedence on conflict.
13
+ def set_metadata(metadata)
14
+ return unless metadata.is_a?(Hash)
15
+
16
+ @context[:metadata] = (@context[:metadata] || {}).merge(metadata)
17
+ end
18
+ end
19
+
4
20
  # Thread-local span stack for tracking nested spans.
5
21
  # Each entry is a Hash with :trace_id and :span_id keys.
6
22
  module SpanContext
@@ -26,6 +26,41 @@ module Simforge
26
26
  base.extend(ClassMethods)
27
27
  end
28
28
 
29
+ # Wrap an existing method on an external class with span tracing.
30
+ # Use this to trace third-party library calls without modifying their source.
31
+ #
32
+ # @example
33
+ # Simforge::Traceable.wrap(OpenAI::Client, :chat,
34
+ # trace_function_key: "openai", name: "Chat", type: "llm")
35
+ #
36
+ # @param klass [Class, Module] the class to wrap
37
+ # @param method_name [Symbol] the method to wrap
38
+ # @param trace_function_key [String] the trace function key
39
+ # @param name [String, nil] explicit span name (defaults to method name)
40
+ # @param type [String] span type: llm, agent, function, guardrail, handoff, custom
41
+ def self.wrap(klass, method_name, trace_function_key:, name: nil, type: "custom", metadata: nil)
42
+ span_name = name || method_name.to_s
43
+ method_name_str = method_name.to_s
44
+ span_metadata = metadata
45
+
46
+ wrapper = Module.new do
47
+ define_method(method_name) do |*args, **kwargs, &block|
48
+ Simforge.client.send(:execute_span,
49
+ trace_function_key:,
50
+ span_name:,
51
+ span_type: type,
52
+ function_name: method_name_str,
53
+ metadata: span_metadata,
54
+ args:,
55
+ kwargs:) do
56
+ super(*args, **kwargs, &block)
57
+ end
58
+ end
59
+ end
60
+
61
+ klass.prepend(wrapper)
62
+ end
63
+
29
64
  module ClassMethods
30
65
  # Set the trace function key for this class.
31
66
  # All spans declared in this class will be grouped under this key.
@@ -52,7 +87,7 @@ module Simforge
52
87
  # @param trace_function_key [String, nil] trace function key (overrides class-level simforge_function)
53
88
  # @param name [String, nil] explicit span name (defaults to method name)
54
89
  # @param type [String] span type: llm, agent, function, guardrail, handoff, custom
55
- def simforge_span(method_name, trace_function_key: nil, name: nil, type: "custom")
90
+ def simforge_span(method_name, trace_function_key: nil, name: nil, type: "custom", metadata: nil)
56
91
  trace_function_key ||= @simforge_function_key
57
92
  unless trace_function_key
58
93
  raise "No trace function key provided. Pass `trace_function_key:` to `simforge_span` " \
@@ -61,14 +96,15 @@ module Simforge
61
96
 
62
97
  # If the method already exists (inline or after-method style), wrap it immediately
63
98
  if method_defined?(method_name) || private_method_defined?(method_name)
64
- _simforge_wrap_method(method_name, trace_function_key:, name:, type:)
99
+ _simforge_wrap_method(method_name, trace_function_key:, name:, type:, metadata:)
65
100
  else
66
101
  # Method doesn't exist yet (before-method style) — register for method_added hook
67
102
  @_simforge_pending_spans ||= {}
68
103
  @_simforge_pending_spans[method_name] = {
69
104
  trace_function_key:,
70
105
  name:,
71
- type:
106
+ type:,
107
+ metadata:
72
108
  }
73
109
  end
74
110
  end
@@ -83,9 +119,10 @@ module Simforge
83
119
  _simforge_wrap_method(method_name, **config)
84
120
  end
85
121
 
86
- def _simforge_wrap_method(method_name, trace_function_key:, name: nil, type: "custom")
122
+ def _simforge_wrap_method(method_name, trace_function_key:, name: nil, type: "custom", metadata: nil)
87
123
  span_name = name || method_name.to_s
88
124
  method_name_str = method_name.to_s
125
+ span_metadata = metadata
89
126
 
90
127
  wrapper = Module.new do
91
128
  define_method(method_name) do |*args, **kwargs, &block|
@@ -94,6 +131,7 @@ module Simforge
94
131
  span_name:,
95
132
  span_type: type,
96
133
  function_name: method_name_str,
134
+ metadata: span_metadata,
97
135
  args:,
98
136
  kwargs:) do
99
137
  super(*args, **kwargs, &block)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Simforge
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.2"
5
5
  end
data/lib/simforge.rb CHANGED
@@ -18,8 +18,8 @@ module Simforge
18
18
  # @example
19
19
  # Simforge.configure(api_key: ENV["SIMFORGE_API_KEY"])
20
20
  #
21
- def configure(api_key:, service_url: nil)
22
- @client = Client.new(api_key:, service_url:)
21
+ def configure(api_key:, service_url: nil, enabled: true)
22
+ @client = Client.new(api_key:, service_url:, enabled:)
23
23
  end
24
24
 
25
25
  # Returns the global client, raising if not configured.
@@ -31,5 +31,18 @@ module Simforge
31
31
  def reset!
32
32
  @client = nil
33
33
  end
34
+
35
+ # Get a handle to the current active span.
36
+ #
37
+ # Call this from inside a traced method to get a span handle that allows
38
+ # setting metadata at runtime.
39
+ #
40
+ # @return [CurrentSpan, nil] the current span, or nil if outside a span context
41
+ def current_span
42
+ entry = SpanContext.current
43
+ return nil unless entry
44
+
45
+ CurrentSpan.new(entry)
46
+ end
34
47
  end
35
48
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simforge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harvest Team
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2026-01-29 00:00:00.000000000 Z
11
+ date: 2026-02-05 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: rake
@@ -29,40 +30,68 @@ dependencies:
29
30
  requirements:
30
31
  - - "~>"
31
32
  - !ruby/object:Gem::Version
32
- version: '3.0'
33
+ version: '3.13'
33
34
  type: :development
34
35
  prerelease: false
35
36
  version_requirements: !ruby/object:Gem::Requirement
36
37
  requirements:
37
38
  - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.13'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-standard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
38
67
  - !ruby/object:Gem::Version
39
68
  version: '3.0'
40
69
  - !ruby/object:Gem::Dependency
41
70
  name: standard
42
71
  requirement: !ruby/object:Gem::Requirement
43
72
  requirements:
44
- - - "~>"
73
+ - - ">="
45
74
  - !ruby/object:Gem::Version
46
75
  version: '1.0'
47
76
  type: :development
48
77
  prerelease: false
49
78
  version_requirements: !ruby/object:Gem::Requirement
50
79
  requirements:
51
- - - "~>"
80
+ - - ">="
52
81
  - !ruby/object:Gem::Version
53
82
  version: '1.0'
54
83
  - !ruby/object:Gem::Dependency
55
84
  name: webmock
56
85
  requirement: !ruby/object:Gem::Requirement
57
86
  requirements:
58
- - - "~>"
87
+ - - ">="
59
88
  - !ruby/object:Gem::Version
60
89
  version: '3.0'
61
90
  type: :development
62
91
  prerelease: false
63
92
  version_requirements: !ruby/object:Gem::Requirement
64
93
  requirements:
65
- - - "~>"
94
+ - - ">="
66
95
  - !ruby/object:Gem::Version
67
96
  version: '3.0'
68
97
  description: Client library for sending function execution spans to the Simforge API.
@@ -73,6 +102,7 @@ executables: []
73
102
  extensions: []
74
103
  extra_rdoc_files: []
75
104
  files:
105
+ - README.md
76
106
  - lib/simforge.rb
77
107
  - lib/simforge/client.rb
78
108
  - lib/simforge/constants.rb
@@ -88,6 +118,7 @@ metadata:
88
118
  homepage_uri: https://simforge.goharvest.ai
89
119
  source_code_uri: https://simforge.goharvest.ai
90
120
  rubygems_mfa_required: 'true'
121
+ post_install_message:
91
122
  rdoc_options: []
92
123
  require_paths:
93
124
  - lib
@@ -102,7 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
133
  - !ruby/object:Gem::Version
103
134
  version: '0'
104
135
  requirements: []
105
- rubygems_version: 3.6.6
136
+ rubygems_version: 3.3.26
137
+ signing_key:
106
138
  specification_version: 4
107
139
  summary: Simforge Ruby SDK for function tracing and span management
108
140
  test_files: []