{"slug": "soloengine-v0-3-0-release-checkpoint-mechanism-message-queue", "title": "SoloEngine v0.3.0 Release — Checkpoint Mechanism & Message Queue", "summary": "SoloEngine v0.3.0 introduces a checkpoint mechanism with three streaming checkpoints and a MessageQueue class for async message handling. The release also upgrades ModelManager to AutoComplete, refactors ReActCore for single-block responses, and improves error handling with SystemMessage type.", "body_md": "`ReActCore`\n\nintroduces three checkpoints during streaming: `content_ended`\n\n(after text content), `before_tool_calls`\n\n(before tool calls), and `after_tool_calls`\n\n(after tool calls), enabling precise interception and state synchronization of the execution flow.`MessageQueue`\n\nclass in `run.py`\n\n, 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 a `QueueBar`\n\ncomponent to display queued messages, with CSS spinning animation, single-line ellipsis, and hover-to-delete functionality.`MessageQueue.drain_all()`\n\nnow merges consecutive messages with the same `name`\n\ninto a single message, preventing fragmented user input when multiple queue entries share the same sender.`message_queued`\n\n, `queue_drained`\n\n, and `queue_returned`\n\n(`useRunWebSocket.ts`\n\n). The frontend processes queue state updates in real time.`queue_returned`\n\n. Checkpoint stops cleanly clear the queue and automatically start the next message.`SystemMessage`\n\ntype (with `notification`\n\nrole) to separate error messages from assistant content. Errors are now rendered as independent notification bubbles, no longer embedded within assistant message cards.`ReActCore`\n\ninitializes a `tiktoken`\n\nencoder on startup for real-time token counting during streaming. Unknown models fall back to `o200k_base`\n\n.`ModelManager`\n\nhas been upgraded from `Select`\n\nto `AutoComplete`\n\n, allowing users to type custom model names not in the predefined list.`ToolCallsBlock`\n\ntype (`message_block.py`\n\n), unifying the internal tool-call format to an OpenAI-style `tool_calls`\n\nlist, replacing the legacy `ToolUseBlock`\n\n.`_get_valid_token_value`\n\nto uniformly handle `None`\n\n/0/empty values from the API, preventing placeholder values from overwriting accumulated values.`react_core.py`\n\nrefactored: each `ChatResponse`\n\nnow contains only a single block type (`SoloTextBlock`\n\nor `SoloThinkingBlock`\n\n), replacing the previous pattern of accumulating multiple blocks before yielding. This enables the frontend to precisely handle each type of incremental content.`LLMMessage[]`\n\nto `Message[]`\n\n(`LLMMessage | SystemMessage`\n\n). `convertToLLMMessages`\n\nnow splits system messages such as `error`\n\ninto independent `SystemMessage`\n\nentries rather than reusing `LLMMessage`\n\n. Updated `MessageList`\n\nand `RunPanel`\n\nto render `SystemMessage`\n\nentries.`save_assistant_message`\n\nnow follow the same code path. `error`\n\nis saved as an independent field and no longer written into the data block.`on_execution_done`\n\nnow detects empty-collector scenarios (where `stream_callback`\n\nwas never triggered) and automatically sets the status to `error`\n\nwith detailed LLM failure output. This prevents false \"completed\" status during silent failures.`createNewSession`\n\nin `runPanelStore`\n\nnow immediately inserts the new session into the `sessions`\n\narray, ensuring the UI reflects the new session without requiring a refresh.`isRunning`\n\nor `isWaitingReply`\n\nis true. The ENTER key now triggers send (queue) as long as the input has content, no longer blocked by `isRunning`\n\nstate.`execution_start`\n\nnow generates a new `msg_asst_${Date.now()}`\n\nID, preventing React key conflicts when the queue drain triggers a new assistant message that would otherwise duplicate the previous message ID.`websocket_handler.py`\n\nhas been significantly simplified, removing complex grace period and takeover logic. `RunContext`\n\nnow owns its own event loop, and the WebSocket only acts as a transport layer with injected callbacks.`aclose()`\n\nclosing the stream in `ReActCore`\n\nno longer raises `CancelledError`\n\n; it is treated as a normal end (breaking out of the loop), avoiding misinterpreting expected stream closure as a cancellation error.`ToolCallEventManager`\n\nnow uniformly sends tool-call events to the frontend through `tool_calls`\n\nblocks, removing the legacy `tool_use`\n\nblock handling logic.`TruncatedFormatterBase`\n\nremoved `token_counter`\n\nand `max_tokens`\n\nparameters along with dead code such as `_truncate`\n\nand `_count`\n\n; the constructor is simplified to a no-arg empty implementation. `OpenAIChatFormatter`\n\nremoved the `OpenAIMultiAgentFormatter`\n\nsubclass.`anthropic_model.py`\n\ncaptures `input_tokens`\n\nin the `message_start`\n\nevent and accumulated `output_tokens`\n\nin the `message_delta`\n\nevent, resolving inaccurate token counts in Anthropic streaming responses.`_convert_openai_to_anthropic_messages`\n\nstatic method that converts OpenAI-format messages (`tool_calls`\n\n, `reasoning_content`\n\n) to Anthropic format (`tool_use`\n\n, `thinking`\n\n).`anthropic_model.py`\n\nand `qwen_model.py`\n\nnow yield a separate `ChatResponse`\n\nfor each `tool_call`\n\n, enabling precise handling on the frontend.`backend/SoloAgent/token_counter/`\n\ndirectory, including `__init__.py`\n\n, `openai_token_counter.py`\n\n, and `token_base.py`\n\n. The original functionality has been merged into `ReActCore`\n\ninline accumulation.`backend/SoloAgent/formatter/truncated_formatter_base.py`\n\n— removed from the exports in `__init__.py`\n\n; the file is preserved but is no longer public API.`OpenAIMultiAgentFormatter`\n\nfrom `openai_formatter.py`\n\n.`ToolUseBlock`\n\n— the message block type was unified from `tool_use`\n\nto `tool_calls`\n\n; the legacy `tool_use`\n\ntype is no longer used.`_convert_anthropic_message_to_solo_format`\n\nfunction — removed a 99-line Anthropic→Solo format conversion function in `anthropic_model.py`\n\n, replaced by the new OpenAI→Anthropic conversion method.`reasoning_content`\n\nfrom content in `OpenAIChatFormatter`\n\n, and removed the compatibility code (with DEBUG logs) that forcibly added an empty `reasoning_content`\n\nto messages carrying `tool_calls`\n\n.`TruncatedFormatterBase._group_messages`\n\nnow only checks `tool_calls`\n\nand `tool_result`\n\ntypes, removing `tool_use`\n\ncompatibility code.`agent.reply`\n\ncaught an exception and returned an error string, but `_execute_agent`\n\ntreated the run as `completed`\n\nbecause the collector was empty. `on_execution_done`\n\nnow checks `collector.get_chunk_count() > 0`\n\nand forces `status=\"error\"`\n\nwith the actual LLM error output.`content`\n\nblocks; they are rendered as independent `notification`\n\n-role messages with proper styling and status indicators.`tool_use`\n\nblocks in streaming responses, unifying to the `tool_calls`\n\nformat.`OpenAIChatFormatter`\n\nadds filtering logic: when an assistant message has empty `content`\n\nand no `tool_calls`\n\n, it is skipped. This fixes the LLM API error \"Input is a zero-length, empty document\".`ChunkCollector._extract_raw_type`\n\nin `run.py`\n\nremoved recognition of the `'tool_use'`\n\ntype string, unifying the mapping to `'tool_calls'`\n\n.`aclose()`\n\nclosing the stream in `react_core.py`\n\nno longer raises `CancelledError`\n\n; it breaks out of the loop and is treated as a normal end, avoiding misinterpreting expected stream closure as a cancellation error.`aclose`\n\nin `react_core.py`\n\n, it is no longer converted to `asyncio.CancelledError`\n\n; it breaks out of the loop and is treated as a normal end, avoiding misinterpreting expected stream closure as a cancellation error.`flow_compiler.py`\n\nadds new logic: immediately after creating the flow, check whether `cancel_event`\n\nis already set, and if so, cancel the flow right away, avoiding wasted HTTP connections.`flow_compiler.py`\n\nfixed a bug where an interrupted Agent incorrectly returned `\"completed\"`\n\n; it now returns `\"stop\"`\n\nstatus. The `output`\n\nfield is no longer filled with `error`\n\n, preventing error pollution of the output.`MessageList.tsx`\n\nunifies 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.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.\n\n📝 [Contributing Guide](https://github.com/Sh4r1ock/SoloEngine/blob/main/CONTRIBUTING.md) · 💬 [Discussions](https://github.com/Sh4r1ock/SoloEngine/discussions) · 📧 [Contact Us](mailto:sh4r1ock@qq.com)", "url": "https://wpnews.pro/news/soloengine-v0-3-0-release-checkpoint-mechanism-message-queue", "canonical_source": "https://dev.to/sh4rlock/soloengine-v030-release-checkpoint-mechanism-message-queue-2i2l", "published_at": "2026-06-29 15:35:44+00:00", "updated_at": "2026-06-29 15:49:04.525106+00:00", "lang": "en", "topics": ["developer-tools", "large-language-models", "ai-agents"], "entities": ["SoloEngine", "ReActCore", "MessageQueue", "ModelManager", "ToolCallsBlock", "SystemMessage", "tiktoken", "OpenAI"], "alternates": {"html": "https://wpnews.pro/news/soloengine-v0-3-0-release-checkpoint-mechanism-message-queue", "markdown": "https://wpnews.pro/news/soloengine-v0-3-0-release-checkpoint-mechanism-message-queue.md", "text": "https://wpnews.pro/news/soloengine-v0-3-0-release-checkpoint-mechanism-message-queue.txt", "jsonld": "https://wpnews.pro/news/soloengine-v0-3-0-release-checkpoint-mechanism-message-queue.jsonld"}}