The canonical openai_codex SDK can complete a turn successfully without emitting any `message.delta` events: the final assistant text arrives only as an `ItemCompletedNotification` whose item is an `agentMessage`. Before this change `_stream_thread_run` would loop through the stream, see no delta text, return, and Studio would emit only the empty usage + stop + `[DONE]` frames -- the user sees a blank reply for what was actually a complete answer. Track agent-message texts collected during the stream loop and, if no streamed deltas came through, yield the last one before returning. The buffered `thread.run()` fallback is still gated by the existing `emitted_any` flag so it never replays a turn that already executed side effects (file writes, shell commands). `_completed_agent_message_text` accepts both the upstream object shape (`ItemCompletedNotification(item.root.text=...)`) and the dict shape pre-release builds and tests use, so it works across SDK revs without an explicit version gate. Tests: new regression `test_empty_stream_falls_back_to_completed_agent_message` exercises a fake SDK whose `turn().stream()` yields only an `item.completed` event with an `agentMessage`; the test asserts the final text reaches the visible chat output and that the buffered `run()` path is NOT re-executed. |
||
|---|---|---|
| .. | ||
| backend | ||
| frontend | ||
| src-tauri | ||
| __init__.py | ||
| install_llama_prebuilt.py | ||
| install_python_stack.py | ||
| LICENSE.AGPL-3.0 | ||
| package-lock.json | ||
| package.json | ||
| setup.bat | ||
| setup.ps1 | ||
| setup.sh | ||
| Unsloth_Studio_Colab.ipynb | ||