feat(channels): support multi-message sending via split marker#2008
Merged
alexhoshina merged 8 commits intosipeed:mainfrom Mar 25, 2026
Merged
feat(channels): support multi-message sending via split marker#2008alexhoshina merged 8 commits intosipeed:mainfrom
alexhoshina merged 8 commits intosipeed:mainfrom
Conversation
Tests that SplitByMarker and SplitMessage work together correctly, and that code block boundaries are preserved during marker splitting.
alexhoshina
reviewed
Mar 25, 2026
yinwm
reviewed
Mar 25, 2026
Collaborator
yinwm
left a comment
There was a problem hiding this comment.
Code Review: Avoid goto in manager.go
The use of goto lengthSplit in the message processing logic is unnecessary and reduces readability. Go community best practices recommend avoiding goto except for specific cases like unified error handling.
Current approach:
- Uses
gototo jump to fallback logic when marker is not found or disabled - Creates non-linear control flow that's harder to follow
Suggested refactoring:
Let the marker splitting try first, then naturally fallback based on result:
var chunks []string
// Step 1: Try marker-based splitting if enabled
if m.config != nil && m.config.Agents.Defaults.SplitOnMarker {
if markerChunks := SplitByMarker(msg.Content); len(markerChunks) > 1 {
for _, chunk := range markerChunks {
chunks = append(chunks, splitByLength(chunk, maxLen)...)
}
}
}
// Step 2: Fallback to length-based splitting if no chunks from marker
if len(chunks) == 0 {
chunks = splitByLength(msg.Content, maxLen)
}Helper function:
func splitByLength(content string, maxLen int) []string {
if maxLen > 0 && len([]rune(content)) > maxLen {
return SplitMessage(content, maxLen)
}
return []string{content}
}Benefits:
- Linear, easy-to-follow control flow
- Less nesting, fewer lines
splitByLengthis independently testable
This is a minor issue but worth addressing for code maintainability.
Extract splitByLength helper function and remove goto-based control flow. The logic now flows more naturally - try marker splitting first, then fall back to length-based splitting.
alexhoshina
approved these changes
Mar 25, 2026
samueltuyizere
added a commit
to samueltuyizere/picoclaw
that referenced
this pull request
Mar 25, 2026
* update security migration documents * feat(config): add command pattern detection tool in exec settings (sipeed#1971) * Add command pattern testing endpoint and UI tool Adds a new API endpoint `/api/config/test-command-patterns` that tests a command against configured whitelist and blacklist patterns, along with a frontend UI component to interactively test patterns. * Only process deny patterns when enableDenyPatterns is true * feat(models): add extra_body config field in model add/edit UI (sipeed#1969) * Add extraBody field to model configuration forms This adds a new field allowing users to specify additional JSON fields to inject into the request body when configuring models. * Handle ExtraBody clearing when frontend sends empty object The backend now interprets an empty object sent from the frontend as a signal to clear the ExtraBody field, while nil/undefined preserves the existing value. Frontend changed to send {} instead of undefined when the field is empty. * refactor(web): clean up systray platform build files Separate embedded tray icons into platform-specific files, rename the no-cgo systray stub for consistency, and add the app version to the launcher startup log. * fix(agent): suppress heartbeat tool feedback (sipeed#1937) * fix(lint): remove CGO_ENABLED=0 for lint and fix (sipeed#1989) * fix(lint): remove CGO_ENABLED=0 for lint and fix * fix makefile * config: add baidu_search example to config.example.json (sipeed#1990) Add Baidu Qianfan AI Search configuration block after glm_search, matching the BaiduSearchConfig struct defaults (enabled: false, max_results: 10). Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * Fix security config precedence during migration (sipeed#1984) * Fix security config precedence during migration * add doc * fix ci * add baidu search * feat(web): add WeCom QR binding flow to channel settings (sipeed#1994) - add backend WeCom QR flow endpoints and in-memory flow state management - add frontend WeCom binding UI with QR polling and channel enable toggle - update channel config behavior and i18n strings for WeCom and WeChat - apply minor formatting cleanup in model-related components * chore(tui): add build target for picoclaw-launcher TUI and create README for TUI launcher (sipeed#1995) * fix(build): disable Matrix gateway import on freebsd/arm Exclude the Matrix gateway shim from freebsd/arm builds because modernc.org/libc currently fails to compile on that target. Document the upstream 32-bit FreeBSD codegen mismatch as well. * fix(release): ignore nightly tags in goreleaser changelog (sipeed#1999) GoReleaser was picking nightly tags as the "previous tag" when generating changelogs, causing release changelogs to be incomplete. Add git.ignore_tags to skip nightly tags. * feat(tools): add exec tool enhancement with background execution and PTY support (sipeed#1752) - Unified exec tool with actions: run/list/poll/read/write/send-keys/kill - PTY support using creack/pty library - Process session management with background execution - Process group kill for cleaning up child processes - Session cleanup: 30-minute TTL for old sessions - Output buffer: 100MB limit with truncation Actions: - run: execute command (sync or background) - list: list all sessions - poll: check session status - read: read session output - write: send input to session stdin - send-keys: send special keys (up, down, ctrl-c, enter, etc.) - kill: terminate session Tests: - PTY: allowed commands, write/read, poll, kill, process group kill - Non-PTY: background execution, list, read, write, poll, kill, process group kill - Session management: add/get/remove/list/cleanup * docs: update WeChat community QR code (sipeed#2003) Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat(logger): add PICOCLAW_LOG_FILE env var for file-only logging * Feature/add mimo provider (sipeed#1987) * feat: add Xiaomi MiMo provider support - Add 'mimo' protocol prefix support in factory_provider.go - Add default API base URL for MiMo: https://api.xiaomimimo.com/v1 - Update provider-label.ts to include Xiaomi MiMo label - Add MiMo to provider tables in both English and Chinese documentation - Add comprehensive unit tests for MiMo provider MiMo API is compatible with OpenAI API format, making it easy to integrate with the existing HTTPProvider infrastructure. Users can now use MiMo by configuring: { "model_name": "mimo", "model": "mimo/mimo-v2-pro", "api_key": "your-mimo-api-key" } * hassas dosyaları kaldırma * Add .security.yml and onboard to .gitignore * build(deps): upgrade pty and reorganize sqlite dependencies (sipeed#2012) - Upgrade github.com/creack/pty from v1.1.9 to v1.1.24 - Move github.com/mattn/go-sqlite3 to indirect dependency - Move rsc.io/qr from indirect to direct dependency * feat(channels): support multi-message sending via split marker (sipeed#2008) * Add multi-message sending via split marker * Add marker and length split integration tests Tests that SplitByMarker and SplitMessage work together correctly, and that code block boundaries are preserved during marker splitting. * Simplify message chunking logic in channel worker Extract splitByLength helper function and remove goto-based control flow. The logic now flows more naturally - try marker splitting first, then fall back to length-based splitting. * Update multi-message output instructions in agent context * Add split_on_marker to config defaults * Add split_on_marker config option * Rename 'Multi-Message Sending' setting to 'Chatty Mode' * Add SplitOnMarker config option --------- Co-authored-by: Cytown <cytown@gmail.com> Co-authored-by: 柚子 <40852301+uiYzzi@users.noreply.github.com> Co-authored-by: wenjie <meetwenjie@gmail.com> Co-authored-by: daming大铭 <yinwm@outlook.com> Co-authored-by: xiwuqi <64734786+xiwuqi@users.noreply.github.com> Co-authored-by: taorye <taorye@outlook.com> Co-authored-by: Luo Peng <luopeng.he@gmail.com> Co-authored-by: BeaconCat <111232138+BeaconCat@users.noreply.github.com> Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: lxowalle <83055338+lxowalle@users.noreply.github.com> Co-authored-by: Guoguo <16666742+imguoguo@users.noreply.github.com> Co-authored-by: Liu Yuan <namei.unix@gmail.com> Co-authored-by: 肆月 <2835601846@qq.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.
📝 Description
Support LLM to proactively send multiple messages via the
<|[SPLIT]|>split marker. WhenSplitOnMarkeris enabled in config, the LLM can use this marker in responses to split a single message into multiple independent outbound messages.Key changes:
pkg/channels/marker.gohandles split marker logicAgents.Defaults.SplitOnMarkercontrols the toggle, disabled by defaultMaxMessageLengthwill be further split by length🗣️ Type of Change
🤖 AI Code Generation
🔗 Related Issue
📚 Technical Context (Skip for Docs)
<|[SPLIT]|>is hardcoded inmarker.go, not configurable; the toggle is atAgentDefaults.SplitOnMarkerlevel☑️ Checklist