ask-decisions 0.2.3 → 0.2.4
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 +11 -0
- data/lib/ask/decisions/compactor.rb +17 -5
- data/lib/ask/decisions/version.rb +1 -1
- data/lib/ask-decisions.rb +12 -6
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e64f40bca45e7b9bc9a11f33fabe1e178c30cfd9e61f4460395b77eb8092cc5a
|
|
4
|
+
data.tar.gz: 4e32792a9c4bdc411731beb94d9a078e98d92f3135aaa4da779090fd6c4f96c9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e6338ccd1b049f19612e7b33d4e7dbedce5192d4789c29ac62bf6fa075107fa7184764b71c3df9e0edc6284e8d9ed0013225d5ee84a6be9858b5d3ca49d2b874
|
|
7
|
+
data.tar.gz: f9c69aca54eaae484d182ab78c7265de776fafff15e5b4813908028dac1857e8df4f85428fc9474282dd54b4418a6c9981e8cb5e76673f028593daff8be3102b
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [0.2.4] - 2026-09-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`resolve_provider` memoizes the provider instance.** Every call to
|
|
12
|
+
`resolve_provider` previously created a new `Typesafe` (or other provider)
|
|
13
|
+
object. In a pipeline with 10+ decision calls per cycle, this meant 10+
|
|
14
|
+
redundant allocations with identical configuration. The provider is now
|
|
15
|
+
cached for the lifetime of the process — it holds only read-only state
|
|
16
|
+
(API key, base URL, model, timeout) set once at boot.
|
|
17
|
+
|
|
7
18
|
## [0.2.3] - 2026-09-18
|
|
8
19
|
|
|
9
20
|
### Added
|
|
@@ -145,6 +145,8 @@ module Ask
|
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
# First message and the most recent +preserve_recent+ messages are pinned.
|
|
148
|
+
# Pinned messages are never removed, but their tool calls are still
|
|
149
|
+
# evaluated by Jev — a recent tool result can still be irrelevant.
|
|
148
150
|
def compute_pinned(messages)
|
|
149
151
|
pinned = Set.new([0])
|
|
150
152
|
start = [messages.size - @preserve_recent, 1].max
|
|
@@ -152,6 +154,11 @@ module Ask
|
|
|
152
154
|
pinned
|
|
153
155
|
end
|
|
154
156
|
|
|
157
|
+
# Whether a message index is safe to remove (not pinned).
|
|
158
|
+
def removable?(idx, pinned)
|
|
159
|
+
!pinned.include?(idx)
|
|
160
|
+
end
|
|
161
|
+
|
|
155
162
|
# ── State ────────────────────────────────────────────────────────
|
|
156
163
|
|
|
157
164
|
# Build the state Jev sees: full conversation with tool results replaced
|
|
@@ -162,7 +169,6 @@ module Ask
|
|
|
162
169
|
pairs.each { |p| result_index[p[:result_msg_idx]] = p }
|
|
163
170
|
|
|
164
171
|
lines = messages.each_with_index.map do |msg, idx|
|
|
165
|
-
role = msg[:role] || "unknown"
|
|
166
172
|
content = msg[:content].to_s
|
|
167
173
|
|
|
168
174
|
if result_index[idx]
|
|
@@ -180,7 +186,6 @@ module Ask
|
|
|
180
186
|
end
|
|
181
187
|
end
|
|
182
188
|
|
|
183
|
-
goal_section = @goal ? "\n\nGoal: #{@goal}" : ""
|
|
184
189
|
{ conversation: lines, goal: @goal }.compact
|
|
185
190
|
end
|
|
186
191
|
|
|
@@ -195,6 +200,8 @@ module Ask
|
|
|
195
200
|
def build_questions(pairs, pinned)
|
|
196
201
|
questions = {}
|
|
197
202
|
pairs.each do |pair|
|
|
203
|
+
# Skip pairs where both the call and result live in pinned messages.
|
|
204
|
+
# Pinned messages are never touched — Jev does not score them.
|
|
198
205
|
next if pinned.include?(pair[:call_msg_idx]) && pinned.include?(pair[:result_msg_idx])
|
|
199
206
|
|
|
200
207
|
call_id = pair[:call_id]
|
|
@@ -312,8 +319,13 @@ module Ask
|
|
|
312
319
|
|
|
313
320
|
case decision[:action]
|
|
314
321
|
when :drop
|
|
315
|
-
|
|
316
|
-
|
|
322
|
+
# Only remove messages that are not pinned.
|
|
323
|
+
if removable?(pair[:call_msg_idx], pinned)
|
|
324
|
+
remove_indices.add(pair[:call_msg_idx])
|
|
325
|
+
end
|
|
326
|
+
if removable?(pair[:result_msg_idx], pinned)
|
|
327
|
+
remove_indices.add(pair[:result_msg_idx])
|
|
328
|
+
end
|
|
317
329
|
when :truncate
|
|
318
330
|
truncate_indices[pair[:result_msg_idx]] = pair[:call]
|
|
319
331
|
end
|
|
@@ -342,7 +354,7 @@ module Ask
|
|
|
342
354
|
# ── Stats ────────────────────────────────────────────────────────
|
|
343
355
|
|
|
344
356
|
def compute_stats(original, pruned, decisions)
|
|
345
|
-
action_counts = decisions.values.
|
|
357
|
+
action_counts = decisions.values.map { |d| d[:action] }.tally
|
|
346
358
|
original_chars = original.sum { |m| m[:content].to_s.length }
|
|
347
359
|
pruned_chars = pruned.sum { |m| m[:content].to_s.length }
|
|
348
360
|
|
data/lib/ask-decisions.rb
CHANGED
|
@@ -122,13 +122,19 @@ module Ask
|
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
# Resolve a provider by name, raising on unknown.
|
|
125
|
+
# Memoized: the provider is stateless after boot (API key,
|
|
126
|
+
# base URL, model, timeout are all read-only), so one instance
|
|
127
|
+
# per configuration lifetime is safe and avoids redundant
|
|
128
|
+
# allocations across the pipeline.
|
|
125
129
|
def resolve_provider(name)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
@resolved_provider ||= begin
|
|
131
|
+
klass = Ask::DecisionProvider.resolve(name)
|
|
132
|
+
|
|
133
|
+
if configuration.provider_options.any?
|
|
134
|
+
klass.new(**configuration.provider_options)
|
|
135
|
+
else
|
|
136
|
+
klass.new
|
|
137
|
+
end
|
|
132
138
|
end
|
|
133
139
|
end
|
|
134
140
|
end
|