fix: streaming infrastructure — queue, loop condition, and timeout#260
Merged
moonpyt merged 5 commits intoXSpoonAi:mainfrom Feb 25, 2026
Merged
fix: streaming infrastructure — queue, loop condition, and timeout#260moonpyt merged 5 commits intoXSpoonAi:mainfrom
moonpyt merged 5 commits intoXSpoonAi:mainfrom
Conversation
1. ThreadSafeOutputQueue: add put_nowait() method
- ToolCallAgent.step() uses put_nowait() to push chunks into the
queue, but ThreadSafeOutputQueue only had an async put(). This
caused AttributeError at runtime when streaming was active.
2. BaseAgent.stream(): fix while-loop exit condition
- Old: `while not (done or empty)` → exited immediately when the
queue was initially empty, even though the producer hadn't
started yet.
- New: `while not (done and empty)` → continues until the task
is complete AND all queued items have been consumed.
3. SpoonReactSkill.run() / SpoonReactAI.run(): accept `timeout` kwarg
- BaseAgent._run_and_signal_done() passes timeout to run(), but
SpoonReactSkill and SpoonReactAI overrode run() without the
timeout parameter, causing TypeError.
Includes tests for all three fixes.
Co-authored-by: Cursor <cursoragent@cursor.com>
…ep() When an LLM response has no tool calls and a finish_reason, step() returned early without pushing content to output_queue. This caused streaming consumers to receive zero chunks for simple text responses. Also removes debug print() statements added during investigation. Co-authored-by: Cursor <cursoragent@cursor.com>
…er issues XSpoonAi#5 - MCPTool.expand_server_tools() discovers all real server tools and creates individual MCPTool instances per tool (e.g. read_file, write_file instead of single "filesystem" proxy) XSpoonAi#8 - SkillScript now accepts input_schema; ScriptTool derives structured parameters from it and serializes kwargs to JSON for stdin XSpoonAi#9 - SkillLoader uses utf-8-sig encoding (strips BOM), normalizes CRLF line endings, and deduplicates discovery via resolved paths Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ToolCallAgent.step()usesput_nowait()but the wrapper class only had asyncput(), causingAttributeErrorduring streaming.not (done or empty)exited immediately when the queue was initially empty. Fixed tonot (done and empty)so it waits for the producer to start._run_and_signal_done()passestimeouttorun(), but subclasses didn't accept it, causingTypeError.Test plan
tests/test_streaming_fixes.py— 5 tests covering all 3 fixespy_compileon all modified filesMade with Cursor