simforge 0.6.0 → 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 +4 -4
- data/lib/simforge/client.rb +21 -4
- data/lib/simforge/http_client.rb +10 -3
- data/lib/simforge/span_context.rb +13 -0
- data/lib/simforge/version.rb +1 -1
- data/lib/simforge.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 73a5e6deba272d1145d6403c0101d8f32a694f236ac4a976d02eb11b79b17c25
|
|
4
|
+
data.tar.gz: 89481b2c5f3e7a00946aba1e438c21df60b9c8138a04720b1a22701a35095c73
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2626a260759ff51764a1b6497b29ac1493acbc86ea9a0e347a39bd5b02987c5bc4012d7b5e7839887f634da72643370c75b6835a92da59c6b7768ae525fae6e2
|
|
7
|
+
data.tar.gz: 45b37048fc7d7338135f5b2d9cd8d6a4a111034587d055aeb9b58e9cd44ac562a1e00e19b9833293f68afc81ff5b47e184e31e410e5c7a795739ef2bdea17e5f
|
data/lib/simforge/client.rb
CHANGED
|
@@ -23,6 +23,8 @@ module Simforge
|
|
|
23
23
|
@enabled = false
|
|
24
24
|
end
|
|
25
25
|
@http_client = HttpClient.new(api_key:, service_url: @service_url)
|
|
26
|
+
@pending_span_threads = {}
|
|
27
|
+
@pending_span_mutex = Mutex.new
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
# Execute a block inside a span context, sending trace data on completion.
|
|
@@ -42,9 +44,14 @@ module Simforge
|
|
|
42
44
|
TraceState.create(trace_id)
|
|
43
45
|
end
|
|
44
46
|
|
|
47
|
+
if is_root_span
|
|
48
|
+
@pending_span_mutex.synchronize { @pending_span_threads[trace_id] = [] }
|
|
49
|
+
end
|
|
50
|
+
|
|
45
51
|
result = nil
|
|
46
52
|
error = nil
|
|
47
53
|
span_contexts = nil
|
|
54
|
+
span_prompt = nil
|
|
48
55
|
|
|
49
56
|
begin
|
|
50
57
|
SpanContext.with_span(trace_id:, span_id:) do
|
|
@@ -52,6 +59,7 @@ module Simforge
|
|
|
52
59
|
ensure
|
|
53
60
|
# Capture contexts before the span context is popped
|
|
54
61
|
span_contexts = SpanContext.current&.dig(:contexts)
|
|
62
|
+
span_prompt = SpanContext.current&.dig(:prompt)
|
|
55
63
|
end
|
|
56
64
|
rescue => e
|
|
57
65
|
error = e.message
|
|
@@ -61,7 +69,7 @@ module Simforge
|
|
|
61
69
|
begin
|
|
62
70
|
ended_at = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ")
|
|
63
71
|
|
|
64
|
-
send_span(
|
|
72
|
+
span_thread = send_span(
|
|
65
73
|
trace_function_key:,
|
|
66
74
|
trace_id:,
|
|
67
75
|
span_id:,
|
|
@@ -70,6 +78,7 @@ module Simforge
|
|
|
70
78
|
span_type:,
|
|
71
79
|
function_name:,
|
|
72
80
|
contexts: span_contexts,
|
|
81
|
+
prompt: span_prompt,
|
|
73
82
|
args:,
|
|
74
83
|
kwargs:,
|
|
75
84
|
result:,
|
|
@@ -78,14 +87,21 @@ module Simforge
|
|
|
78
87
|
ended_at:
|
|
79
88
|
)
|
|
80
89
|
|
|
81
|
-
# For root spans, also send trace completion
|
|
82
90
|
if is_root_span
|
|
91
|
+
pending = @pending_span_mutex.synchronize { @pending_span_threads.delete(trace_id) || [] }
|
|
92
|
+
pending << span_thread if span_thread
|
|
93
|
+
pending.each { |t| t.join(5) }
|
|
94
|
+
|
|
83
95
|
send_trace_completion(
|
|
84
96
|
trace_function_key:,
|
|
85
97
|
trace_id:,
|
|
86
98
|
started_at:,
|
|
87
99
|
ended_at:
|
|
88
100
|
)
|
|
101
|
+
else
|
|
102
|
+
@pending_span_mutex.synchronize do
|
|
103
|
+
@pending_span_threads[trace_id] << span_thread if span_thread && @pending_span_threads.key?(trace_id)
|
|
104
|
+
end
|
|
89
105
|
end
|
|
90
106
|
rescue Exception # rubocop:disable Lint/RescueException
|
|
91
107
|
# Silently ignore — user's result/exception takes priority
|
|
@@ -141,7 +157,7 @@ module Simforge
|
|
|
141
157
|
end
|
|
142
158
|
|
|
143
159
|
def send_span(trace_function_key:, trace_id:, span_id:, parent_span_id:,
|
|
144
|
-
span_name:, span_type:, function_name:, contexts:, args:, kwargs:, result:, error:,
|
|
160
|
+
span_name:, span_type:, function_name:, contexts:, prompt:, args:, kwargs:, result:, error:,
|
|
145
161
|
started_at:, ended_at:)
|
|
146
162
|
# Human-readable JSON (input/output fields)
|
|
147
163
|
human_inputs = Serialize.serialize_inputs(args, kwargs)
|
|
@@ -163,6 +179,7 @@ module Simforge
|
|
|
163
179
|
span_data["output_serialized"] = marshalled_output if marshalled_output
|
|
164
180
|
span_data["error"] = error if error
|
|
165
181
|
span_data["contexts"] = contexts if contexts&.any?
|
|
182
|
+
span_data["prompt"] = prompt if prompt
|
|
166
183
|
|
|
167
184
|
raw_span = {
|
|
168
185
|
"id" => span_id,
|
|
@@ -179,7 +196,7 @@ module Simforge
|
|
|
179
196
|
"sourceTraceId" => trace_id,
|
|
180
197
|
"traceFunctionKey" => trace_function_key,
|
|
181
198
|
"rawSpan" => raw_span
|
|
182
|
-
)
|
|
199
|
+
) # Returns the background thread
|
|
183
200
|
end
|
|
184
201
|
end
|
|
185
202
|
end
|
data/lib/simforge/http_client.rb
CHANGED
|
@@ -57,7 +57,8 @@ module Simforge
|
|
|
57
57
|
raise last_error
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
# Send an external span
|
|
60
|
+
# Send an external span in a background thread.
|
|
61
|
+
# Returns the thread for callers that need to await completion.
|
|
61
62
|
def send_external_span(payload)
|
|
62
63
|
merged = payload.merge("sdkVersion" => VERSION)
|
|
63
64
|
|
|
@@ -92,16 +93,22 @@ module Simforge
|
|
|
92
93
|
|
|
93
94
|
class << self
|
|
94
95
|
# Run a block in a background thread with tracking.
|
|
96
|
+
# Returns the thread for callers that need to join on it.
|
|
95
97
|
def _run_in_background(&block)
|
|
96
98
|
thread = Thread.new do
|
|
97
99
|
block.call
|
|
98
|
-
rescue
|
|
99
|
-
|
|
100
|
+
rescue => e
|
|
101
|
+
begin
|
|
102
|
+
warn "Simforge: Failed to send request: #{e.message}"
|
|
103
|
+
rescue
|
|
104
|
+
# Never crash the host app
|
|
105
|
+
end
|
|
100
106
|
ensure
|
|
101
107
|
@pending_threads_mutex.synchronize { @pending_threads.delete(Thread.current) }
|
|
102
108
|
end
|
|
103
109
|
|
|
104
110
|
@pending_threads_mutex.synchronize { @pending_threads << thread }
|
|
111
|
+
thread
|
|
105
112
|
end
|
|
106
113
|
|
|
107
114
|
# Wait for all pending background threads to complete.
|
|
@@ -25,6 +25,19 @@ module Simforge
|
|
|
25
25
|
rescue
|
|
26
26
|
# Silently ignore - never crash the host app
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
# Set the prompt for this span.
|
|
30
|
+
# The prompt is stored in span_data.prompt. Calling multiple times
|
|
31
|
+
# overwrites the previous value.
|
|
32
|
+
#
|
|
33
|
+
# @param prompt [String] the prompt string to store
|
|
34
|
+
def set_prompt(prompt)
|
|
35
|
+
return unless prompt.is_a?(String)
|
|
36
|
+
|
|
37
|
+
@span_state[:prompt] = prompt
|
|
38
|
+
rescue
|
|
39
|
+
# Silently ignore - never crash the host app
|
|
40
|
+
end
|
|
28
41
|
end
|
|
29
42
|
|
|
30
43
|
# Handle to the current active trace, allowing trace-level context to be set.
|
data/lib/simforge/version.rb
CHANGED
data/lib/simforge.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simforge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Harvest Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|