ask-agent 0.2.1 → 0.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 +14 -0
- data/lib/ask/agent/chat.rb +98 -86
- data/lib/ask/agent/events.rb +2 -2
- data/lib/ask/agent/loop.rb +12 -2
- data/lib/ask/agent/session.rb +21 -2
- data/lib/ask/agent/version.rb +1 -1
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4812b86203eb5a12eb03138de1e50fe8f0a80532f545bb683dcf051f2729c088
|
|
4
|
+
data.tar.gz: ba9e999b2aedae3e9c0f55067a35e3d3f29f828717a8f7129c0e0037bd518a33
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5b049b05acf1a82334a2169a708d60a6511db2d790ec5db3f30b9b4775a561eb204b8fdb209b60d095edeba43bd27f1572a909d78118eba9f295943625da370
|
|
7
|
+
data.tar.gz: 54ba99bbacd6152c52196f276f28559d2a13e09b048338c4c5198e9ab01c8f2cc9e5eb57c2a957b1ba6dea4410726c3eba644104b66d767729e908a10c366133
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [0.3.0] — 2026-07-17
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- **Token and cost tracking** — `ResponseMessage` and `ChatChunk` now carry `input_tokens`, `output_tokens`, and `cost` fields. Token counts are extracted from provider responses and streaming chunks.
|
|
6
|
+
- **Instrumentation events** — `Chat#ask` emits `chat.ask` and `chat.stream.ask` events via `Ask::Instrumentation`, unlocking the full monitoring pipeline (ask-agent → ask-instrumentation → ask-monitoring).
|
|
7
|
+
- **Cost in agent events** — `SessionEnd` and `TurnEnd` events now include `input_tokens`, `output_tokens`, and `cost` fields, accumulated across all turns in the session.
|
|
8
|
+
- **Cumulative session costs** — `Session` tracks `total_input_tokens`, `total_output_tokens`, and `total_cost` across all turns and reflection rounds.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Dependency added** — `ask-instrumentation >= 0.1` added to gemspec. Instrumentation is optional (emission is wrapped in `defined?` check).
|
|
13
|
+
- **Gemfile** — now uses local path resolution for sibling ask-* gems during development.
|
|
14
|
+
|
|
1
15
|
## [0.2.1] - 2026-06-25
|
|
2
16
|
|
|
3
17
|
### Changed
|
data/lib/ask/agent/chat.rb
CHANGED
|
@@ -3,47 +3,30 @@
|
|
|
3
3
|
module Ask
|
|
4
4
|
module Agent
|
|
5
5
|
# Response message returned by {Chat#ask}.
|
|
6
|
-
#
|
|
7
|
-
ResponseMessage = Data.define(:content, :tool_calls, :thinking) do
|
|
6
|
+
# Includes token counts and cost when available from the provider.
|
|
7
|
+
ResponseMessage = Data.define(:content, :tool_calls, :thinking, :input_tokens, :output_tokens, :cost) do
|
|
8
8
|
def tool_call? = !tool_calls.empty?
|
|
9
9
|
def to_s = content.to_s
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
# Tool call data used in {ResponseMessage} and {ChatChunk}.
|
|
13
12
|
ToolCallInfo = Data.define(:id, :name, :arguments)
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
ChatChunk = Data.define(:content, :tool_calls, :thinking) do
|
|
14
|
+
ChatChunk = Data.define(:content, :tool_calls, :thinking, :input_tokens, :output_tokens) do
|
|
17
15
|
def tool_call? = !tool_calls.empty?
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
# Thin wrapper around {Ask::Provider} + an internal message array that
|
|
21
|
-
# presents a Chat-like API for ask-agent internal use.
|
|
22
|
-
#
|
|
23
|
-
# Manages conversation history, resolves the correct provider/model,
|
|
24
|
-
# handles streaming chunk accumulation, and normalises tool call
|
|
25
|
-
# formats between Ask::Provider (Array of Hashes) and ask-agent
|
|
26
|
-
# internal usage (Hash of { id => ToolCallInfo }).
|
|
27
18
|
class Chat
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# @return [String] model ID (e.g. "gpt-4o")
|
|
19
|
+
attr_reader :model_id
|
|
20
|
+
|
|
31
21
|
def model
|
|
32
22
|
@model_id
|
|
33
23
|
end
|
|
34
|
-
|
|
24
|
+
|
|
35
25
|
attr_reader :messages
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
# @param tools [Array<Ask::Tool>] tool instances available to the chat
|
|
39
|
-
# @param temperature [Float, nil] sampling temperature
|
|
40
|
-
# @param schema [Ask::Schema, Hash, nil] structured output schema
|
|
41
|
-
# @param assume_model_exists [Boolean] whether to skip model catalog lookup
|
|
42
|
-
# @param provider [String, Symbol, nil] provider slug to use (overrides model catalog)
|
|
43
|
-
def initialize(model:, tools: [], temperature: nil, schema: nil,
|
|
44
|
-
assume_model_exists: false, provider: nil, **)
|
|
27
|
+
def initialize(model:, tools: [], temperature: nil, schema: nil, provider: nil, **)
|
|
45
28
|
@model_id = model.respond_to?(:id) ? model.id : model.to_s
|
|
46
|
-
@model_info =
|
|
29
|
+
@model_info = Ask::ModelCatalog.find(@model_id)
|
|
47
30
|
@tools = tools
|
|
48
31
|
@temperature = temperature
|
|
49
32
|
@schema = schema
|
|
@@ -52,38 +35,39 @@ module Ask
|
|
|
52
35
|
@provider = nil
|
|
53
36
|
end
|
|
54
37
|
|
|
55
|
-
# Send a user message and get a completion response.
|
|
56
|
-
#
|
|
57
|
-
# @param message [String, nil] user message text
|
|
58
|
-
# @yield [ChatChunk] streaming chunks (only when a block is given)
|
|
59
|
-
# @return [ResponseMessage] the assistant's response
|
|
60
38
|
def ask(message = nil, &block)
|
|
61
39
|
@messages << Ask::Message.new(role: :user, content: message.to_s) if message
|
|
62
40
|
|
|
63
41
|
stream = block_given?
|
|
64
42
|
tool_defs = @tools.map { |t| Ask::ToolDef.from_tool(t) }
|
|
65
43
|
|
|
66
|
-
# Accumulator for tool calls during streaming (keyed by index)
|
|
67
44
|
calls_acc = {}
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
46
|
+
provider_model = @model_id
|
|
47
|
+
provider_tools = tool_defs
|
|
48
|
+
provider_temp = @temperature
|
|
49
|
+
provider_schema = @schema&.respond_to?(:to_json_schema) ? @schema.to_json_schema : @schema
|
|
50
|
+
provider_params = @extra_params || {}
|
|
51
|
+
|
|
52
|
+
result = provider.chat(
|
|
53
|
+
@messages.map(&:to_h),
|
|
54
|
+
model: provider_model,
|
|
55
|
+
tools: provider_tools,
|
|
56
|
+
temperature: provider_temp,
|
|
73
57
|
stream: stream,
|
|
74
|
-
schema:
|
|
75
|
-
**
|
|
58
|
+
schema: provider_schema,
|
|
59
|
+
**provider_params
|
|
76
60
|
) do |raw_chunk|
|
|
77
61
|
next unless block_given?
|
|
78
62
|
|
|
79
|
-
# Accumulate tool calls by index during streaming
|
|
80
63
|
accumulate_tool_calls(raw_chunk, calls_acc)
|
|
81
64
|
|
|
82
|
-
# Yield adapted chunk with current tool call state
|
|
83
65
|
yield ChatChunk.new(
|
|
84
66
|
content: raw_chunk.content,
|
|
85
67
|
tool_calls: build_current_tool_calls(calls_acc),
|
|
86
|
-
thinking: raw_chunk.respond_to?(:thinking) ? raw_chunk.thinking : nil
|
|
68
|
+
thinking: raw_chunk.respond_to?(:thinking) ? raw_chunk.thinking : nil,
|
|
69
|
+
input_tokens: nil,
|
|
70
|
+
output_tokens: nil
|
|
87
71
|
)
|
|
88
72
|
end
|
|
89
73
|
|
|
@@ -93,24 +77,24 @@ module Ask
|
|
|
93
77
|
build_response(result)
|
|
94
78
|
end
|
|
95
79
|
|
|
96
|
-
# Store assistant response in conversation history
|
|
97
80
|
@messages << Ask::Message.new(
|
|
98
81
|
role: :assistant,
|
|
99
82
|
content: response_msg.content,
|
|
100
83
|
tool_calls: response_msg.tool_calls&.values&.map { |tc|
|
|
101
84
|
{ id: tc.id, type: "function", name: tc.name, arguments: tc.arguments }
|
|
102
|
-
}
|
|
85
|
+
},
|
|
86
|
+
metadata: {
|
|
87
|
+
input_tokens: response_msg.input_tokens,
|
|
88
|
+
output_tokens: response_msg.output_tokens,
|
|
89
|
+
cost: response_msg.cost
|
|
90
|
+
}.compact
|
|
103
91
|
)
|
|
104
92
|
|
|
93
|
+
emit_instrumentation(stream, response_msg)
|
|
94
|
+
|
|
105
95
|
response_msg
|
|
106
96
|
end
|
|
107
97
|
|
|
108
|
-
# Add a message to the conversation history.
|
|
109
|
-
#
|
|
110
|
-
# @param role [Symbol] :system, :user, :assistant, :tool
|
|
111
|
-
# @param content [String, nil] message content
|
|
112
|
-
# @param tool_call_id [String, nil] tool call ID (for tool results)
|
|
113
|
-
# @param tool_calls [Array<Hash>, nil] tool call invocations
|
|
114
98
|
def add_message(role:, content: nil, tool_call_id: nil, tool_calls: nil)
|
|
115
99
|
@messages << Ask::Message.new(
|
|
116
100
|
role: role,
|
|
@@ -120,58 +104,34 @@ module Ask
|
|
|
120
104
|
)
|
|
121
105
|
end
|
|
122
106
|
|
|
123
|
-
# Set or replace the system prompt.
|
|
124
|
-
#
|
|
125
|
-
# @param prompt [String] system instructions
|
|
126
|
-
# @return [self]
|
|
127
107
|
def with_instructions(prompt)
|
|
128
108
|
@messages.reject! { |m| m.role == :system }
|
|
129
109
|
@messages.unshift(Ask::Message.new(role: :system, content: prompt))
|
|
130
110
|
self
|
|
131
111
|
end
|
|
132
112
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
# Set additional parameters for the provider call and return self.
|
|
138
|
-
#
|
|
139
|
-
# @param params [Hash] extra parameters passed to the provider
|
|
140
|
-
# @return [self]
|
|
141
|
-
def with_params(**params)
|
|
142
|
-
@extra_params = (@extra_params || {}).merge(params)
|
|
143
|
-
self
|
|
144
|
-
end
|
|
113
|
+
def with_params(**params)
|
|
114
|
+
@extra_params = (@extra_params || {}).merge(params)
|
|
115
|
+
self
|
|
116
|
+
end
|
|
145
117
|
|
|
146
|
-
|
|
147
|
-
# @param params [Hash] extra keyword arguments for the provider
|
|
148
|
-
# @return [self]
|
|
149
|
-
def with_schema(schema)
|
|
118
|
+
def with_schema(schema)
|
|
150
119
|
@schema = schema.respond_to?(:to_json_schema) ? schema.to_json_schema : schema
|
|
151
120
|
self
|
|
152
121
|
end
|
|
153
122
|
|
|
154
|
-
# Clear all messages from the conversation.
|
|
155
123
|
def reset_messages!
|
|
156
124
|
@messages.clear
|
|
157
125
|
end
|
|
158
126
|
|
|
159
127
|
private
|
|
160
128
|
|
|
161
|
-
# Resolve model info from the catalog.
|
|
162
|
-
def resolve_model(model_id)
|
|
163
|
-
Ask::ModelCatalog.find(model_id)
|
|
164
|
-
rescue Ask::ModelNotFound
|
|
165
|
-
nil
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
# Lazily resolve and instantiate the LLM provider.
|
|
169
129
|
def provider
|
|
170
130
|
@provider ||= build_provider
|
|
171
131
|
end
|
|
172
132
|
|
|
173
133
|
def build_provider
|
|
174
|
-
slug = @provider_override&.to_s || @model_info
|
|
134
|
+
slug = @provider_override&.to_s || @model_info.provider
|
|
175
135
|
klass = Ask::Provider.resolve(slug)
|
|
176
136
|
klass.new(provider_config(slug))
|
|
177
137
|
end
|
|
@@ -185,7 +145,6 @@ def with_schema(schema)
|
|
|
185
145
|
Ask::LLM::Config.new(config)
|
|
186
146
|
end
|
|
187
147
|
|
|
188
|
-
# Accumulate partial tool calls from streaming chunks.
|
|
189
148
|
def accumulate_tool_calls(raw_chunk, calls_acc)
|
|
190
149
|
return unless raw_chunk.tool_call?
|
|
191
150
|
|
|
@@ -198,7 +157,6 @@ def with_schema(schema)
|
|
|
198
157
|
end
|
|
199
158
|
end
|
|
200
159
|
|
|
201
|
-
# Build current snapshot of tool calls from accumulator.
|
|
202
160
|
def build_current_tool_calls(calls_acc)
|
|
203
161
|
hash = {}
|
|
204
162
|
calls_acc.each_value do |tc_data|
|
|
@@ -212,7 +170,6 @@ def with_schema(schema)
|
|
|
212
170
|
hash
|
|
213
171
|
end
|
|
214
172
|
|
|
215
|
-
# Convert Ask::Provider tool_calls (Array of Hashes) to Hash.
|
|
216
173
|
def build_tool_call_hash(raw_calls)
|
|
217
174
|
hash = {}
|
|
218
175
|
raw_calls.each do |tc|
|
|
@@ -227,21 +184,76 @@ def with_schema(schema)
|
|
|
227
184
|
hash
|
|
228
185
|
end
|
|
229
186
|
|
|
230
|
-
# Build response from streaming result.
|
|
231
187
|
def build_stream_response(stream, calls_acc)
|
|
232
|
-
|
|
188
|
+
tokens = accumulated_tokens(stream)
|
|
189
|
+
cost = calculate_cost(tokens[:input], tokens[:output])
|
|
233
190
|
ResponseMessage.new(
|
|
234
191
|
content: stream.accumulated_text,
|
|
235
192
|
tool_calls: build_current_tool_calls(calls_acc),
|
|
236
|
-
thinking: thinking
|
|
193
|
+
thinking: stream.chunks.filter_map(&:thinking).last,
|
|
194
|
+
input_tokens: tokens[:input],
|
|
195
|
+
output_tokens: tokens[:output],
|
|
196
|
+
cost: cost
|
|
237
197
|
)
|
|
238
198
|
end
|
|
239
199
|
|
|
240
|
-
# Build response from non-streaming result.
|
|
241
200
|
def build_response(msg)
|
|
242
201
|
tool_calls = msg.tool_calls ? build_tool_call_hash(msg.tool_calls) : {}
|
|
243
202
|
thinking = msg.respond_to?(:thinking) ? msg.thinking : nil
|
|
244
|
-
|
|
203
|
+
metadata = msg.metadata || {}
|
|
204
|
+
input_tokens = metadata[:input_tokens] || metadata["input_tokens"]
|
|
205
|
+
output_tokens = metadata[:output_tokens] || metadata["output_tokens"]
|
|
206
|
+
cost = calculate_cost(input_tokens, output_tokens)
|
|
207
|
+
ResponseMessage.new(
|
|
208
|
+
content: msg.content.to_s,
|
|
209
|
+
tool_calls: tool_calls,
|
|
210
|
+
thinking: thinking,
|
|
211
|
+
input_tokens: input_tokens,
|
|
212
|
+
output_tokens: output_tokens,
|
|
213
|
+
cost: cost
|
|
214
|
+
)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def accumulated_tokens(stream)
|
|
218
|
+
input = 0
|
|
219
|
+
output = 0
|
|
220
|
+
stream.chunks.each do |chunk|
|
|
221
|
+
if chunk.usage
|
|
222
|
+
input = chunk.usage[:input_tokens] || chunk.usage["input_tokens"] || input
|
|
223
|
+
output = chunk.usage[:output_tokens] || chunk.usage["output_tokens"] || output
|
|
224
|
+
end
|
|
225
|
+
output += 1 if chunk.content.to_s.length > 0
|
|
226
|
+
end
|
|
227
|
+
{ input: input, output: output }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def calculate_cost(input_tokens, output_tokens)
|
|
231
|
+
return nil unless input_tokens || output_tokens
|
|
232
|
+
Ask::LLM::CostCalculator.calculate(@model_info, input_tokens: input_tokens || 0, output_tokens: output_tokens || 0)
|
|
233
|
+
rescue StandardError
|
|
234
|
+
nil
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def emit_instrumentation(stream, response_msg)
|
|
238
|
+
return unless defined?(Ask::Instrumentation)
|
|
239
|
+
|
|
240
|
+
payload = {
|
|
241
|
+
model: @model_id,
|
|
242
|
+
provider: @model_info.provider,
|
|
243
|
+
input_tokens: response_msg.input_tokens,
|
|
244
|
+
output_tokens: response_msg.output_tokens,
|
|
245
|
+
cost: response_msg.cost,
|
|
246
|
+
tool_calls: response_msg.tool_call?,
|
|
247
|
+
stream: stream
|
|
248
|
+
}.compact
|
|
249
|
+
|
|
250
|
+
if stream
|
|
251
|
+
Ask::Instrumentation.instrument("chat.stream.ask", payload)
|
|
252
|
+
else
|
|
253
|
+
Ask::Instrumentation.instrument("chat.ask", payload)
|
|
254
|
+
end
|
|
255
|
+
rescue StandardError
|
|
256
|
+
nil
|
|
245
257
|
end
|
|
246
258
|
end
|
|
247
259
|
end
|
data/lib/ask/agent/events.rb
CHANGED
|
@@ -4,10 +4,10 @@ module Ask
|
|
|
4
4
|
module Agent
|
|
5
5
|
module Events
|
|
6
6
|
SessionStart = Data.define
|
|
7
|
-
SessionEnd = Data.define(:result, :turn_count, :tool_calls_made)
|
|
7
|
+
SessionEnd = Data.define(:result, :turn_count, :tool_calls_made, :input_tokens, :output_tokens, :cost)
|
|
8
8
|
|
|
9
9
|
TurnStart = Data.define
|
|
10
|
-
TurnEnd = Data.define(:tool_results, :turn_number)
|
|
10
|
+
TurnEnd = Data.define(:tool_results, :turn_number, :input_tokens, :output_tokens, :cost)
|
|
11
11
|
|
|
12
12
|
MessageStart = Data.define
|
|
13
13
|
TextDelta = Data.define(:content)
|
data/lib/ask/agent/loop.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Ask
|
|
|
6
6
|
LOOP_DETECTION_WINDOW = 3
|
|
7
7
|
@max_consecutive_tool_turns = 6
|
|
8
8
|
|
|
9
|
-
attr_reader :turn_count
|
|
9
|
+
attr_reader :turn_count, :last_input_tokens, :last_output_tokens, :last_cost
|
|
10
10
|
|
|
11
11
|
def initialize(max_turns: 25, max_consecutive_tool_turns: 6)
|
|
12
12
|
@max_turns = max_turns
|
|
@@ -36,6 +36,10 @@ module Ask
|
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
@last_input_tokens = response.input_tokens
|
|
40
|
+
@last_output_tokens = response.output_tokens
|
|
41
|
+
@last_cost = response.cost
|
|
42
|
+
|
|
39
43
|
event_emitter.emit(Events::MessageEnd.new(tool_calls: response.tool_call?))
|
|
40
44
|
@turn_count += 1
|
|
41
45
|
|
|
@@ -65,7 +69,13 @@ module Ask
|
|
|
65
69
|
return "Based on my investigation: #{summary}"
|
|
66
70
|
end
|
|
67
71
|
|
|
68
|
-
event_emitter.emit(Events::TurnEnd.new(
|
|
72
|
+
event_emitter.emit(Events::TurnEnd.new(
|
|
73
|
+
tool_results: tool_results,
|
|
74
|
+
turn_number: @turn_count,
|
|
75
|
+
input_tokens: @last_input_tokens,
|
|
76
|
+
output_tokens: @last_output_tokens,
|
|
77
|
+
cost: @last_cost
|
|
78
|
+
))
|
|
69
79
|
|
|
70
80
|
if compactor && compactor.should_compact?
|
|
71
81
|
compactor.run(event_emitter: event_emitter)
|
data/lib/ask/agent/session.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Ask
|
|
|
7
7
|
module Agent
|
|
8
8
|
class Session
|
|
9
9
|
attr_reader :id, :chat, :tools, :turn_count, :created_at, :messages
|
|
10
|
-
attr_reader :tool_calls_made
|
|
10
|
+
attr_reader :tool_calls_made, :total_input_tokens, :total_output_tokens, :total_cost
|
|
11
11
|
|
|
12
12
|
def reflection_count
|
|
13
13
|
@reflector&.reflection_count || 0
|
|
@@ -33,6 +33,10 @@ module Ask
|
|
|
33
33
|
@created_at = Time.now
|
|
34
34
|
@_no_tools_instructed = false
|
|
35
35
|
|
|
36
|
+
@total_input_tokens = 0
|
|
37
|
+
@total_output_tokens = 0
|
|
38
|
+
@total_cost = 0.0
|
|
39
|
+
|
|
36
40
|
@telemetry = telemetry.is_a?(Telemetry) ? telemetry : Telemetry.new(enabled: !!telemetry)
|
|
37
41
|
|
|
38
42
|
@chat = build_chat(model, system_prompt, tools, **chat_options)
|
|
@@ -99,6 +103,10 @@ module Ask
|
|
|
99
103
|
event_emitter: self,
|
|
100
104
|
session_id: @id
|
|
101
105
|
)
|
|
106
|
+
|
|
107
|
+
@total_input_tokens += @loop.last_input_tokens.to_i
|
|
108
|
+
@total_output_tokens += @loop.last_output_tokens.to_i
|
|
109
|
+
@total_cost += @loop.last_cost.to_f
|
|
102
110
|
rescue MaxTurnsExceeded => e
|
|
103
111
|
emit(Events::MaxTurnsExceeded.new(max_turns: @max_turns))
|
|
104
112
|
@telemetry.log(:max_turns_exceeded, session_id: @id, max_turns: @max_turns)
|
|
@@ -143,6 +151,10 @@ module Ask
|
|
|
143
151
|
event_emitter: self,
|
|
144
152
|
session_id: @id
|
|
145
153
|
)
|
|
154
|
+
|
|
155
|
+
@total_input_tokens += @loop.last_input_tokens.to_i
|
|
156
|
+
@total_output_tokens += @loop.last_output_tokens.to_i
|
|
157
|
+
@total_cost += @loop.last_cost.to_f
|
|
146
158
|
end
|
|
147
159
|
end
|
|
148
160
|
|
|
@@ -151,7 +163,14 @@ module Ask
|
|
|
151
163
|
try_auto_meta_agent
|
|
152
164
|
end
|
|
153
165
|
|
|
154
|
-
emit(Events::SessionEnd.new(
|
|
166
|
+
emit(Events::SessionEnd.new(
|
|
167
|
+
result: response,
|
|
168
|
+
turn_count: @turn_count,
|
|
169
|
+
tool_calls_made: @tool_calls_made,
|
|
170
|
+
input_tokens: @total_input_tokens,
|
|
171
|
+
output_tokens: @total_output_tokens,
|
|
172
|
+
cost: @total_cost
|
|
173
|
+
))
|
|
155
174
|
@messages = @chat.messages.dup
|
|
156
175
|
|
|
157
176
|
response
|
data/lib/ask/agent/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ask-agent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kaka Ruto
|
|
@@ -65,6 +65,20 @@ dependencies:
|
|
|
65
65
|
- - ">="
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '0.1'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: ask-instrumentation
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0.1'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0.1'
|
|
68
82
|
- !ruby/object:Gem::Dependency
|
|
69
83
|
name: minitest
|
|
70
84
|
requirement: !ruby/object:Gem::Requirement
|