π SoloEngine v0.3.0 Release β Checkpoint Mechanism & Message Queue #6
Sh4r1ock
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
[v0.3.0] - 2026-06-29
π Added
ReActCoreintroduces three checkpoints during streaming:content_ended(after text content),before_tool_calls(before tool calls), andafter_tool_calls(after tool calls), enabling precise interception and state synchronization of the execution flow.MessageQueueclass inrun.py, supporting async enqueue, drain, and remove operations. Users can now queue messages while the LLM is running; queued messages are sent automatically after the current task completes. The frontend introduces aQueueBarcomponent to display queued messages, with CSS spinning animation, single-line ellipsis, and hover-to-delete functionality.MessageQueue.drain_all()now merges consecutive messages with the samenameinto a single message, preventing fragmented user input when multiple queue entries share the same sender.message_queued,queue_drained, andqueue_returned(useRunWebSocket.ts). The frontend processes queue state updates in real time.queue_returned. Checkpoint stops cleanly clear the queue and automatically start the next message.SystemMessagetype (withnotificationrole) to separate error messages from assistant content. Errors are now rendered as independent notification bubbles, no longer embedded within assistant message cards.ReActCoreinitializes atiktokenencoder on startup for real-time token counting during streaming. Unknown models fall back too200k_base.π§ Improved
ModelManagerhas been upgraded fromSelecttoAutoComplete, allowing users to type custom model names not in the predefined list.ToolCallsBlocktype (message_block.py), unifying the internal tool-call format to an OpenAI-styletool_callslist, replacing the legacyToolUseBlock._get_valid_token_valueto uniformly handleNone/0/empty values from the API, preventing placeholder values from overwriting accumulated values.react_core.pyrefactored: eachChatResponsenow contains only a single block type (SoloTextBlockorSoloThinkingBlock), replacing the previous pattern of accumulating multiple blocks before yielding. This enables the frontend to precisely handle each type of incremental content.LLMMessage[]toMessage[](LLMMessage | SystemMessage).convertToLLMMessagesnow splits system messages such aserrorinto independentSystemMessageentries rather than reusingLLMMessage. UpdatedMessageListandRunPanelto renderSystemMessageentries.save_assistant_messagenow follow the same code path.erroris saved as an independent field and no longer written into the data block.on_execution_donenow detects empty-collector scenarios (wherestream_callbackwas never triggered) and automatically sets the status toerrorwith detailed LLM failure output. This prevents false "completed" status during silent failures.createNewSessioninrunPanelStorenow immediately inserts the new session into thesessionsarray, ensuring the UI reflects the new session without requiring a refresh.isRunningorisWaitingReplyis true. The ENTER key now triggers send (queue) as long as the input has content, no longer blocked byisRunningstate.execution_startnow generates a newmsg_asst_${Date.now()}ID, preventing React key conflicts when the queue drain triggers a new assistant message that would otherwise duplicate the previous message ID.websocket_handler.pyhas been significantly simplified, removing complex grace period and takeover logic.RunContextnow owns its own event loop, and the WebSocket only acts as a transport layer with injected callbacks.aclose()closing the stream inReActCoreno longer raisesCancelledError; it is treated as a normal end (breaking out of the loop), avoiding misinterpreting expected stream closure as a cancellation error.ToolCallEventManagernow uniformly sends tool-call events to the frontend throughtool_callsblocks, removing the legacytool_useblock handling logic.TruncatedFormatterBaseremovedtoken_counterandmax_tokensparameters along with dead code such as_truncateand_count; the constructor is simplified to a no-arg empty implementation.OpenAIChatFormatterremoved theOpenAIMultiAgentFormattersubclass.anthropic_model.pycapturesinput_tokensin themessage_startevent and accumulatedoutput_tokensin themessage_deltaevent, resolving inaccurate token counts in Anthropic streaming responses._convert_openai_to_anthropic_messagesstatic method that converts OpenAI-format messages (tool_calls,reasoning_content) to Anthropic format (tool_use,thinking).anthropic_model.pyandqwen_model.pynow yield a separateChatResponsefor eachtool_call, enabling precise handling on the frontend.ποΈ Removed
backend/SoloAgent/token_counter/directory, including__init__.py,openai_token_counter.py, andtoken_base.py. The original functionality has been merged intoReActCoreinline accumulation.backend/SoloAgent/formatter/truncated_formatter_base.pyβ removed from the exports in__init__.py; the file is preserved but is no longer public API.OpenAIMultiAgentFormatterfromopenai_formatter.py.ToolUseBlockβ the message block type was unified fromtool_usetotool_calls; the legacytool_usetype is no longer used._convert_anthropic_message_to_solo_formatfunction β removed a 99-line AnthropicβSolo format conversion function inanthropic_model.py, replaced by the new OpenAIβAnthropic conversion method.reasoning_contentfrom content inOpenAIChatFormatter, and removed the compatibility code (with DEBUG logs) that forcibly added an emptyreasoning_contentto messages carryingtool_calls.TruncatedFormatterBase._group_messagesnow only checkstool_callsandtool_resulttypes, removingtool_usecompatibility code.π Fixed
agent.replycaught an exception and returned an error string, but_execute_agenttreated the run ascompletedbecause the collector was empty.on_execution_donenow checkscollector.get_chunk_count() > 0and forcesstatus="error"with the actual LLM error output.contentblocks; they are rendered as independentnotification-role messages with proper styling and status indicators.tool_useblocks in streaming responses, unifying to thetool_callsformat.OpenAIChatFormatteradds filtering logic: when an assistant message has emptycontentand notool_calls, it is skipped. This fixes the LLM API error "Input is a zero-length, empty document".ChunkCollector._extract_raw_typeinrun.pyremoved recognition of the'tool_use'type string, unifying the mapping to'tool_calls'.aclose()closing the stream inreact_core.pyno longer raisesCancelledError; it breaks out of the loop and is treated as a normal end, avoiding misinterpreting expected stream closure as a cancellation error.acloseinreact_core.py, it is no longer converted toasyncio.CancelledError; it breaks out of the loop and is treated as a normal end, avoiding misinterpreting expected stream closure as a cancellation error.flow_compiler.pyadds new logic: immediately after creating the flow, check whethercancel_eventis already set, and if so, cancel the flow right away, avoiding wasted HTTP connections.flow_compiler.pyfixed a bug where an interrupted Agent incorrectly returned"completed"; it now returns"stop"status. Theoutputfield is no longer filled witherror, preventing error pollution of the output.MessageList.tsxunifies on the W3C Clipboard API, ensuring that Windows clipboard history (Win+V) is correctly captured; fixed the issue where clipboard history could not be triggered on Windows.π€ Join Us
We're looking for like-minded contributors who share our passion for SoloEngine and Agentic AI. Every contribution β from a typo fix to a full feature β makes SoloEngine better.
π Contributing Guide Β· π¬ Discussions Β· π§ Contact Us
Beta Was this translation helpful? Give feedback.
All reactions