legion-llm 0.14.15 → 0.14.16
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 +10 -0
- data/lib/legion/llm/api/client_translators/anthropic_messages.rb +2 -6
- data/lib/legion/llm/api/client_translators/openai_responses.rb +12 -5
- data/lib/legion/llm/inference/executor/context_window.rb +5 -0
- data/lib/legion/llm/inference/executor/escalation.rb +2 -2
- data/lib/legion/llm/version.rb +1 -1
- 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: 3eec433896cf314b65ac64111f414a55dc7e9639db3d54cc76359c9fb01ed567
|
|
4
|
+
data.tar.gz: 659857c6aa71573f6fbb795a655b7a59f2936672b0538db0bc14c18ae06ecfbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 648b2bd80386141477bf5b77b387814f768d5f64447a921d34ef828dde6d9469a15e63211e63c4173e7188e0a61c5d60eb366415ccb68c43c031a23cd4889ac3
|
|
7
|
+
data.tar.gz: 22f1a949a48470e5a6b543a683e2de4f9c86f44d1c21d706e704bb4a5f58672311ba632b03710647beb071987abed2947e6299e0ad69c06b73c72484398fb238
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Legion LLM Changelog
|
|
2
2
|
|
|
3
|
+
## [0.14.16] - 2026-07-14
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Server tool results are now visible to Claude and Codex streaming clients.** When the daemon executes a LegionIO tool server-side during the streaming tool loop, the result must reach the client in a format its SDK can parse. Two bugs prevented this:
|
|
8
|
+
- **Anthropic Messages (`/v1/messages`):** The `server_tool_result` SSE emitted `content: []` in `content_block_start` and put the actual result in a `content_block_delta` with `delta.type = "content_block_delta"` — a type the Anthropic TypeScript/Python SDK does not process. The client saw an empty result block. Fixed: result content is now placed directly in the `content_block_start` event; no unrecognized delta needed.
|
|
9
|
+
- **OpenAI Responses (`/v1/responses`):** The `on_server_tool_result` emitter was a no-op — tool results were silently discarded. Codex saw `function_call` items with no matching `function_call_output`. Fixed: emits a proper `response.output_item.added` + `response.output_item.done` pair with `type: "function_call_output"`, `call_id`, and the result text.
|
|
10
|
+
|
|
11
|
+
- **Empty assistant messages left after thinking extraction are now stripped.** `strip_thinking_from_history` can leave behind assistant messages with no content and no tool_calls (the thinking was their only payload). These empty messages confused some providers. A second `empty_assistant_message?` pass now runs after thinking stripping.
|
|
12
|
+
|
|
3
13
|
## [0.14.15] - 2026-07-09
|
|
4
14
|
|
|
5
15
|
### Fixed
|
|
@@ -292,12 +292,8 @@ module Legion
|
|
|
292
292
|
emit('content_block_start', {
|
|
293
293
|
type: 'content_block_start',
|
|
294
294
|
index: block_index,
|
|
295
|
-
content_block: { type: 'server_tool_result', id: tool_call_id,
|
|
296
|
-
|
|
297
|
-
emit('content_block_delta', {
|
|
298
|
-
type: 'content_block_delta',
|
|
299
|
-
index: block_index,
|
|
300
|
-
delta: { type: 'content_block_delta', content: [{ type: 'text', text: result_text }] }
|
|
295
|
+
content_block: { type: 'server_tool_result', id: tool_call_id,
|
|
296
|
+
content: [{ type: 'text', text: result_text }] }
|
|
301
297
|
})
|
|
302
298
|
emit('content_block_stop', { type: 'content_block_stop', index: block_index })
|
|
303
299
|
end
|
|
@@ -401,11 +401,18 @@ module Legion
|
|
|
401
401
|
|
|
402
402
|
def on_server_tool_result(block_index:, tool_call_id:, result_text:)
|
|
403
403
|
_ = block_index
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
404
|
+
idx = @output_items.length
|
|
405
|
+
item = { id: "fco_#{tool_call_id}", type: 'function_call_output',
|
|
406
|
+
call_id: tool_call_id, output: result_text.to_s, status: 'completed' }
|
|
407
|
+
@output_items << item
|
|
408
|
+
emit('response.output_item.added', {
|
|
409
|
+
type: 'response.output_item.added', sequence_number: next_seq,
|
|
410
|
+
output_index: idx, item: item
|
|
411
|
+
})
|
|
412
|
+
emit('response.output_item.done', {
|
|
413
|
+
type: 'response.output_item.done', sequence_number: next_seq,
|
|
414
|
+
output_index: idx, item: item
|
|
415
|
+
})
|
|
409
416
|
end
|
|
410
417
|
|
|
411
418
|
def on_keep_alive
|
|
@@ -17,6 +17,11 @@ module Legion
|
|
|
17
17
|
messages = messages.reject { |m| empty_assistant_message?(m) }
|
|
18
18
|
end
|
|
19
19
|
messages = strip_thinking_from_history(messages)
|
|
20
|
+
post_thinking_rejected = messages.count { |m| empty_assistant_message?(m) }
|
|
21
|
+
if post_thinking_rejected.positive?
|
|
22
|
+
log.warn "[llm][executor] action=strip_empty_assistants_post_thinking request_id=#{@request.id} removed=#{post_thinking_rejected}"
|
|
23
|
+
messages = messages.reject { |m| empty_assistant_message?(m) }
|
|
24
|
+
end
|
|
20
25
|
messages = trim_oversized_tool_results(messages)
|
|
21
26
|
enforce_context_window(messages)
|
|
22
27
|
end
|
|
@@ -170,12 +170,12 @@ module Legion
|
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
def pipeline_escalation_enabled?
|
|
173
|
-
esc = Legion::Settings[:llm]
|
|
173
|
+
esc = Legion::Settings[:llm][:routing][:escalation]
|
|
174
174
|
esc[:enabled] == true && esc[:pipeline_enabled] == true
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
def pipeline_escalation_max_attempts
|
|
178
|
-
esc = Legion::Settings[:llm]
|
|
178
|
+
esc = Legion::Settings[:llm][:routing][:escalation]
|
|
179
179
|
esc[:max_attempts] || 3
|
|
180
180
|
end
|
|
181
181
|
|
data/lib/legion/llm/version.rb
CHANGED