bitfab 0.23.2 → 0.23.3

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: 8a66c02d783c0a8acbe6e22b82394fcf7805df0bbec4ebf35eff5246a9c086cc
4
- data.tar.gz: cd9f879e95a0b77ede2176db482ab925bcafb3f28d0a31388af3db0e64e99510
3
+ metadata.gz: b16e8767e1610a6e1a1ec7ab0f03a17b4eb365b991d26fa60f4aa6b9f3d39ac4
4
+ data.tar.gz: f511a486af389b33aafbdcab66518f8b4381cceb137faec4e483fe81484379c6
5
5
  SHA512:
6
- metadata.gz: a8cda8f967f41bdd4d11367a961ea6c2bf567d9fad4b5f963d6894f0274e30f358c324b00eff8a34efee77e07550a1330d5f632095c29ea378d6ce4b95970623
7
- data.tar.gz: d82f7d930e2b99b3201beadfa01c9919584b96439096d3d2825be48ef5685b25286f9ca97e18ddfd373c039e85134fc49a0e4ed01271334ed0162a91effc1f8a
6
+ metadata.gz: e4e09e2cba8fe57b31adbedceabaff1720a80a20e4216821bbd0389bc5b45c05203a4aca205e49623ff934670a21d181bff8a27a0777ea905682f149d97360d4
7
+ data.tar.gz: d2b56368cd69b9555e95431679e98acec87fb54d6c4da9ec2db2f72f0c86074b24e43abe67f5ae0a02355de7244280b31730a3feef6574a68ee0437e672ffd02
data/README.md CHANGED
@@ -291,17 +291,18 @@ fn.wrap(OpenAI::Client, :embeddings, name: "Embed", type: "llm")
291
291
 
292
292
  ### Replay with Mock Strategies
293
293
 
294
- Replay reruns historical traces through your code so you can compare outputs after an iteration. By default every child span runs real code - fine for offline traces, but expensive when children make paid LLM/API calls. Three strategies control whether child spans return their historical output instead of executing:
294
+ Replay reruns historical traces through your code so you can compare outputs after an iteration. By default, spans tagged with `mock_on_replay: true` return their historical output and other child spans run real code. Three strategies control whether child spans return their historical output instead of executing:
295
295
 
296
296
  ```ruby
297
- # "none" (default): everything runs real code
297
+ # "marked" (default): only spans tagged with `mock_on_replay: true` return historical output
298
+ client.replay(pipeline, :process, trace_function_key: "my-fn")
299
+ client.replay(pipeline, :process, trace_function_key: "my-fn", mock: "marked")
300
+
301
+ # "none": everything runs real code
298
302
  client.replay(pipeline, :process, trace_function_key: "my-fn", mock: "none")
299
303
 
300
304
  # "all": every child span returns its historical output
301
305
  client.replay(pipeline, :process, trace_function_key: "my-fn", mock: "all")
302
-
303
- # "marked": only spans tagged with `mock_on_replay: true` return historical output
304
- client.replay(pipeline, :process, trace_function_key: "my-fn", mock: "marked")
305
306
  ```
306
307
 
307
308
  Tag the spans you want mocked at definition time:
@@ -330,7 +331,7 @@ class Pipeline
330
331
  end
331
332
  ```
332
333
 
333
- Use `mock: "marked"` when you want to iterate on `process`'s logic without paying for the LLM call each run. Use `mock: "all"` for the cheapest possible replay (every child span returns its recorded output).
334
+ Use the default `mock: "marked"` behavior when you want to iterate on `process`'s logic without paying for the LLM call each run. Use `mock: "all"` for the cheapest possible replay (every child span returns its recorded output).
334
335
 
335
336
  ### Error Handling
336
337
 
data/lib/bitfab/client.rb CHANGED
@@ -72,9 +72,9 @@ module Bitfab
72
72
  # replay runs into a single experiment batch
73
73
  # @param dataset_id [String, nil] optional UUID of the dataset this replay
74
74
  # runs against, stored on the resulting experiment for durable attribution
75
- # @param mock [String] mock strategy for child spans: "none" (default),
76
- # "all", or "marked". "all" mocks every child span; "marked" only mocks
77
- # spans declared with mock_on_replay: true.
75
+ # @param mock [String] mock strategy for child spans: "marked" (default),
76
+ # "none", or "all". "marked" only mocks spans declared with
77
+ # mock_on_replay: true; "all" mocks every child span.
78
78
  # @param adapt_inputs [#call, nil] optional hook to reshape recorded inputs
79
79
  # onto the method's current signature when its shape changed after the
80
80
  # traces were captured. Receives (args, kwargs, ctx) where ctx is
@@ -87,7 +87,7 @@ module Bitfab
87
87
  # A raising callback never crashes the run.
88
88
  # @return [Hash] with :items, :test_run_id, :test_run_url
89
89
  def replay(receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
90
- name: nil, code_change_description: nil, code_change_files: nil, experiment_group_id: nil, dataset_id: nil, mock: "none",
90
+ name: nil, code_change_description: nil, code_change_files: nil, experiment_group_id: nil, dataset_id: nil, mock: "marked",
91
91
  adapt_inputs: nil, environment: nil, on_progress: nil)
92
92
  Replay.run(
93
93
  self, receiver, method_name,
@@ -673,7 +673,7 @@ module Bitfab
673
673
  # @param method_name [Symbol] the method to wrap
674
674
  # @param name [String, nil] explicit span name (defaults to method name)
675
675
  # @param type [String] span type
676
- # @param mock_on_replay [Boolean] mark this span for the "marked" mock strategy
676
+ # @param mock_on_replay [Boolean] mark this span for the default "marked" mock strategy
677
677
  def wrap(klass, method_name, name: nil, type: "custom", mock_on_replay: false)
678
678
  Bitfab::Traceable.wrap(
679
679
  klass, method_name,
data/lib/bitfab/replay.rb CHANGED
@@ -7,10 +7,10 @@ require_relative "traceable"
7
7
  module Bitfab
8
8
  # Replay mock strategies. Mirrors the Python and TypeScript SDKs.
9
9
  #
10
- # - "none" : every child span runs real code (default)
11
- # - "all" : every child span returns its historical output
12
10
  # - "marked" : only spans declared with mock_on_replay: true return historical
13
- # output; everything else runs real code
11
+ # output; everything else runs real code (default)
12
+ # - "none" : every child span runs real code
13
+ # - "all" : every child span returns its historical output
14
14
  MOCK_STRATEGIES = %w[none all marked].freeze
15
15
 
16
16
  # Thread-local replay context management.
@@ -40,7 +40,7 @@ module Bitfab
40
40
  ctx[:pending_persistence] = pending_persistence if pending_persistence
41
41
  if mock_tree
42
42
  ctx[:mock_tree] = mock_tree
43
- ctx[:mock_strategy] = mock_strategy || "none"
43
+ ctx[:mock_strategy] = mock_strategy || "marked"
44
44
  ctx[:call_counters] = {}
45
45
  end
46
46
  # The per-trace DB branch (resolved server-side) and the Bitfab trace ID
@@ -92,9 +92,9 @@ module Bitfab
92
92
  # replay runs into a single experiment batch
93
93
  # @param dataset_id [String, nil] optional UUID of the dataset this replay
94
94
  # runs against, stored on the resulting experiment for durable attribution
95
- # @param mock [String] mock strategy for child spans: "none" (default),
96
- # "all", or "marked". "all" mocks every child span; "marked" only mocks
97
- # spans declared with mock_on_replay: true.
95
+ # @param mock [String] mock strategy for child spans: "marked" (default),
96
+ # "none", or "all". "marked" only mocks spans declared with
97
+ # mock_on_replay: true; "all" mocks every child span.
98
98
  # @param adapt_inputs [#call, nil] optional hook to reshape recorded inputs
99
99
  # onto the method's current signature when its shape changed after the
100
100
  # traces were captured. Receives (args, kwargs, ctx) where ctx is
@@ -112,7 +112,7 @@ module Bitfab
112
112
  # @return [Hash] with :items, :test_run_id, :test_run_url
113
113
  def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, name: nil,
114
114
  max_concurrency: 10, code_change_description: nil, code_change_files: nil, experiment_group_id: nil,
115
- dataset_id: nil, mock: "none",
115
+ dataset_id: nil, mock: "marked",
116
116
  adapt_inputs: nil, environment: nil, on_progress: nil)
117
117
  unless MOCK_STRATEGIES.include?(mock.to_s)
118
118
  raise ArgumentError, "Invalid mock strategy '#{mock}'. Must be one of: #{MOCK_STRATEGIES.join(", ")}"
@@ -349,8 +349,14 @@ module Bitfab
349
349
 
350
350
  mock_tree = nil
351
351
  if mock_strategy == "all" || mock_strategy == "marked"
352
- tree = http_client.get_span_tree(server_item["externalSpanId"])
353
- mock_tree = build_mock_tree(tree["root"] || {})
352
+ begin
353
+ tree = http_client.get_span_tree(server_item["externalSpanId"])
354
+ mock_tree = build_mock_tree(tree["root"] || {})
355
+ rescue Exception => e # rubocop:disable Lint/RescueException
356
+ raise if e.is_a?(SystemExit) || e.is_a?(SignalException)
357
+ raise if mock_strategy == "all"
358
+ mock_tree = nil
359
+ end
354
360
  end
355
361
 
356
362
  adapt_ctx = {trace_id: server_item["traceId"], source_span_id: server_item["externalSpanId"]}
@@ -481,7 +487,7 @@ module Bitfab
481
487
 
482
488
  # Execute a single replay item: deserialize inputs, call method with replay context.
483
489
  def execute_item(item, receiver, method_name, test_run_id, input_source_span_id = nil, metrics = {},
484
- input_source_trace_id: nil, mock_strategy: "none", mock_tree: nil, adapt_inputs: nil, adapt_ctx: nil,
490
+ input_source_trace_id: nil, mock_strategy: "marked", mock_tree: nil, adapt_inputs: nil, adapt_ctx: nil,
485
491
  db_branch_lease: nil, source_bitfab_trace_id: nil, db_snapshot_ref: nil)
486
492
  args, kwargs = Serialize.deserialize_inputs(item)
487
493
 
@@ -38,8 +38,8 @@ module Bitfab
38
38
  # @param trace_function_key [String] the trace function key
39
39
  # @param name [String, nil] explicit span name (defaults to method name)
40
40
  # @param type [String] span type: llm, agent, function, guardrail, handoff, custom
41
- # @param mock_on_replay [Boolean] mark this span for the "marked" mock strategy.
42
- # When true, `client.replay(... mock: "marked")` returns this span's
41
+ # @param mock_on_replay [Boolean] mark this span for the default "marked" mock strategy.
42
+ # When true, `client.replay(...)` returns this span's
43
43
  # historical output instead of executing the wrapped method.
44
44
  # @param client [Bitfab::Client, nil] route spans through this specific client
45
45
  # instead of the global `Bitfab.client`. When nil (default), the wrapper
@@ -132,8 +132,8 @@ module Bitfab
132
132
  # @param trace_function_key [String, nil] trace function key (overrides class-level bitfab_function)
133
133
  # @param name [String, nil] explicit span name (defaults to method name)
134
134
  # @param type [String] span type: llm, agent, function, guardrail, handoff, custom
135
- # @param mock_on_replay [Boolean] mark this span for the "marked" mock strategy.
136
- # When true, `client.replay(... mock: "marked")` returns this span's
135
+ # @param mock_on_replay [Boolean] mark this span for the default "marked" mock strategy.
136
+ # When true, `client.replay(...)` returns this span's
137
137
  # historical output instead of executing the wrapped method.
138
138
  def bitfab_span(method_name, trace_function_key: nil, name: nil, type: "custom", mock_on_replay: false)
139
139
  trace_function_key ||= @bitfab_function_key
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bitfab
4
- VERSION = "0.23.2"
4
+ VERSION = "0.23.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.2
4
+ version: 0.23.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harvest Team