activeagent 1.2.0 → 1.3.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/CHANGELOG.md +125 -1
- data/README.md +34 -0
- data/lib/active_agent/base.rb +11 -2
- data/lib/active_agent/concerns/delegation.rb +385 -0
- data/lib/active_agent/delegation/backend.rb +109 -0
- data/lib/active_agent/delegation/budget.rb +138 -0
- data/lib/active_agent/delegation/contract.rb +117 -0
- data/lib/active_agent/delegation/definition.rb +95 -0
- data/lib/active_agent/delegation/ledger.rb +56 -0
- data/lib/active_agent/delegation/pricing.rb +106 -0
- data/lib/active_agent/delegation/runner.rb +283 -0
- data/lib/active_agent/delegation/schema.rb +220 -0
- data/lib/active_agent/providers/_base_provider.rb +97 -1
- data/lib/active_agent/providers/open_ai/chat_provider.rb +21 -2
- data/lib/active_agent/telemetry/instrumentation.rb +34 -1
- data/lib/active_agent/version.rb +1 -1
- data/lib/active_agent.rb +1 -0
- metadata +10 -1
|
@@ -26,6 +26,15 @@ module ActiveAgent
|
|
|
26
26
|
|
|
27
27
|
protected
|
|
28
28
|
|
|
29
|
+
# Chat Completions reports a streamed request's token usage on a final
|
|
30
|
+
# chunk, and only when the request opts in.
|
|
31
|
+
#
|
|
32
|
+
# @return [Hash]
|
|
33
|
+
# @see Base#api_stream_usage_parameters
|
|
34
|
+
def api_stream_usage_parameters
|
|
35
|
+
{ stream_options: { include_usage: true } }
|
|
36
|
+
end
|
|
37
|
+
|
|
29
38
|
# @return [OpenAI::Client::Completions] the API client for chat completions
|
|
30
39
|
# @see Base#api_prompt_executer
|
|
31
40
|
def api_prompt_executer
|
|
@@ -100,7 +109,12 @@ module ActiveAgent
|
|
|
100
109
|
# Called Multiple Times: [Chunk<T>, T]<Content, ToolsCall>
|
|
101
110
|
case api_response_event.type
|
|
102
111
|
when :chunk
|
|
112
|
+
# The usage chunk carries usage and an empty choices array, so it
|
|
113
|
+
# must be read before choices.first is dereferenced below.
|
|
114
|
+
record_stream_usage(api_response_event.chunk.try(:usage))
|
|
115
|
+
|
|
103
116
|
api_message = api_response_event.chunk.choices.first
|
|
117
|
+
return if api_message.nil?
|
|
104
118
|
|
|
105
119
|
# If we have a delta, we need to update a message in the stack
|
|
106
120
|
message = find_or_create_message(api_message.index)
|
|
@@ -118,8 +132,13 @@ module ActiveAgent
|
|
|
118
132
|
# Returns the full content when complete
|
|
119
133
|
# => {type: :"content.done", content: "Hi there! How can I help you today?", parsed: nil}
|
|
120
134
|
|
|
121
|
-
#
|
|
122
|
-
|
|
135
|
+
# Close out and run tooling callbacks (Recursive) — but not here.
|
|
136
|
+
# The usage chunk is emitted *after* content.done, and finishing
|
|
137
|
+
# at this point builds the response from a usage_stack that has
|
|
138
|
+
# not received it yet, so a streamed generation reports zero
|
|
139
|
+
# tokens. Deferred to stream_finished!, which the base provider
|
|
140
|
+
# calls once the stream has drained.
|
|
141
|
+
self.stream_completion_pending = true
|
|
123
142
|
when :"tool_calls.function.arguments.delta"
|
|
124
143
|
# => {type: :"tool_calls.function.arguments.delta", name: "get_current_weather", index: 0, arguments: "", parsed: nil, arguments_delta: ""}
|
|
125
144
|
when :"tool_calls.function.arguments.done"
|
|
@@ -94,12 +94,24 @@ module ActiveAgent
|
|
|
94
94
|
prompt_span.set_attribute("prompt.input.tools", JSON.generate(roster)) if roster.any?
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
# prompt_options[:messages] holds the turns a caller passed
|
|
98
|
+
# explicitly. An agent that renders its user turn from the
|
|
99
|
+
# action's template — the idiomatic form, `instructions:` plus
|
|
100
|
+
# `locals:` — has none at this point: the rendering happens
|
|
101
|
+
# later, in prepare_prompt_parameters. Falling back to it means
|
|
102
|
+
# the message the model actually received is on the trace either
|
|
103
|
+
# way, which is what an evaluation scores.
|
|
104
|
+
outbound = prompt_options[:messages]
|
|
105
|
+
outbound = rendered_prompt_messages if outbound.blank?
|
|
106
|
+
|
|
107
|
+
if outbound.present?
|
|
98
108
|
serialized = Array(outbound).map { |message|
|
|
99
109
|
if message.is_a?(Hash)
|
|
100
110
|
role = message[:role] || message["role"] || "user"
|
|
101
111
|
content = message[:content] || message["content"]
|
|
102
112
|
{ role: role.to_s, content: telemetry_truncate(content) }
|
|
113
|
+
elsif message.respond_to?(:content)
|
|
114
|
+
{ role: (message.try(:role) || "user").to_s, content: telemetry_truncate(message.content) }
|
|
103
115
|
else
|
|
104
116
|
{ role: "user", content: telemetry_truncate(message) }
|
|
105
117
|
end
|
|
@@ -257,6 +269,27 @@ module ActiveAgent
|
|
|
257
269
|
# tool loop) can't bloat the trace payload.
|
|
258
270
|
TELEMETRY_ATTRIBUTE_MAX_CHARS = 4_000
|
|
259
271
|
|
|
272
|
+
# The turns this generation will actually send, for an agent that
|
|
273
|
+
# renders its user message from the action's template rather than
|
|
274
|
+
# passing `messages:`. prepare_prompt_parameters is a pure function of
|
|
275
|
+
# prompt_options — it deep_dups its input and mutates no instance
|
|
276
|
+
# state — so calling it here is a read, not a side effect. It does
|
|
277
|
+
# re-render the templates, which is why it is only reached when there
|
|
278
|
+
# are no explicit messages to record.
|
|
279
|
+
#
|
|
280
|
+
# Never raises: a provider that builds parameters differently, or an
|
|
281
|
+
# agent whose templates need context this call does not have, must
|
|
282
|
+
# cost the generation nothing more than an absent attribute.
|
|
283
|
+
def rendered_prompt_messages
|
|
284
|
+
return unless respond_to?(:prepare_prompt_parameters, true)
|
|
285
|
+
|
|
286
|
+
parameters = prepare_prompt_parameters
|
|
287
|
+
parameters[:messages] || parameters["messages"]
|
|
288
|
+
rescue StandardError => e
|
|
289
|
+
logger&.debug { "[ActiveAgent::Telemetry] could not read rendered messages: #{e.class}: #{e.message}" }
|
|
290
|
+
nil
|
|
291
|
+
end
|
|
292
|
+
|
|
260
293
|
def telemetry_truncate(value)
|
|
261
294
|
text = value.to_s
|
|
262
295
|
return text if text.length <= TELEMETRY_ATTRIBUTE_MAX_CHARS
|
data/lib/active_agent/version.rb
CHANGED
data/lib/active_agent.rb
CHANGED
|
@@ -93,6 +93,7 @@ module ActiveAgent
|
|
|
93
93
|
# These components are loaded on-demand when first referenced.
|
|
94
94
|
autoload :Base
|
|
95
95
|
autoload :Callbacks, "active_agent/concerns/callbacks"
|
|
96
|
+
autoload :Delegation, "active_agent/concerns/delegation"
|
|
96
97
|
autoload :Streaming, "active_agent/concerns/streaming"
|
|
97
98
|
autoload :InlinePreviewInterceptor
|
|
98
99
|
autoload :Generation
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activeagent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Bowen
|
|
@@ -410,6 +410,7 @@ files:
|
|
|
410
410
|
- lib/active_agent/base.rb
|
|
411
411
|
- lib/active_agent/collector.rb
|
|
412
412
|
- lib/active_agent/concerns/callbacks.rb
|
|
413
|
+
- lib/active_agent/concerns/delegation.rb
|
|
413
414
|
- lib/active_agent/concerns/observers.rb
|
|
414
415
|
- lib/active_agent/concerns/parameterized.rb
|
|
415
416
|
- lib/active_agent/concerns/preview.rb
|
|
@@ -420,6 +421,14 @@ files:
|
|
|
420
421
|
- lib/active_agent/concerns/tooling.rb
|
|
421
422
|
- lib/active_agent/concerns/view.rb
|
|
422
423
|
- lib/active_agent/configuration.rb
|
|
424
|
+
- lib/active_agent/delegation/backend.rb
|
|
425
|
+
- lib/active_agent/delegation/budget.rb
|
|
426
|
+
- lib/active_agent/delegation/contract.rb
|
|
427
|
+
- lib/active_agent/delegation/definition.rb
|
|
428
|
+
- lib/active_agent/delegation/ledger.rb
|
|
429
|
+
- lib/active_agent/delegation/pricing.rb
|
|
430
|
+
- lib/active_agent/delegation/runner.rb
|
|
431
|
+
- lib/active_agent/delegation/schema.rb
|
|
423
432
|
- lib/active_agent/deprecator.rb
|
|
424
433
|
- lib/active_agent/generation.rb
|
|
425
434
|
- lib/active_agent/generation_job.rb
|