Skip to content

fix(core): wrap split render parts as messages#976

Merged
dingyi222666 merged 1 commit into
v1-devfrom
fix/core-markdown-split
Jul 13, 2026
Merged

fix(core): wrap split render parts as messages#976
dingyi222666 merged 1 commit into
v1-devfrom
fix/core-markdown-split

Conversation

@dingyi222666

Copy link
Copy Markdown
Member

This pr fixes split markdown/element rendering so each split part is sent as a separate message.

New Features

  • None

Bug Fixes

  • Wrap non-message elements in h('message') when split mode is enabled for text and koishi-element renderers
  • Send stream reply content as a message array so split parts dispatch correctly

Other Changes

  • Bump koishi-plugin-chatluna to 1.4.0-alpha.41 and sync peer dependency ranges

Validation

  • yarn lint-fix (0 errors, 2 existing warnings)

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@dingyi222666
dingyi222666 merged commit f91c291 into v1-dev Jul 13, 2026
2 of 3 checks passed
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 76a34f32-698e-4e74-b653-2da9aaf1e73f

📥 Commits

Reviewing files that changed from the base of the PR and between 42df541 and 8236112.

⛔ Files ignored due to path filters (27)
  • packages/adapter-azure-openai/package.json is excluded by !**/*.json
  • packages/adapter-claude/package.json is excluded by !**/*.json
  • packages/adapter-deepseek/package.json is excluded by !**/*.json
  • packages/adapter-dify/package.json is excluded by !**/*.json
  • packages/adapter-doubao/package.json is excluded by !**/*.json
  • packages/adapter-gemini/package.json is excluded by !**/*.json
  • packages/adapter-hunyuan/package.json is excluded by !**/*.json
  • packages/adapter-ollama/package.json is excluded by !**/*.json
  • packages/adapter-openai-like/package.json is excluded by !**/*.json
  • packages/adapter-openai/package.json is excluded by !**/*.json
  • packages/adapter-qwen/package.json is excluded by !**/*.json
  • packages/adapter-rwkv/package.json is excluded by !**/*.json
  • packages/adapter-spark/package.json is excluded by !**/*.json
  • packages/adapter-wenxin/package.json is excluded by !**/*.json
  • packages/adapter-zhipu/package.json is excluded by !**/*.json
  • packages/core/package.json is excluded by !**/*.json
  • packages/extension-agent/package.json is excluded by !**/*.json
  • packages/extension-long-memory/package.json is excluded by !**/*.json
  • packages/extension-tools/package.json is excluded by !**/*.json
  • packages/extension-usage/package.json is excluded by !**/*.json
  • packages/extension-variable/package.json is excluded by !**/*.json
  • packages/renderer-image/package.json is excluded by !**/*.json
  • packages/service-embeddings/package.json is excluded by !**/*.json
  • packages/service-multimodal/package.json is excluded by !**/*.json
  • packages/service-search/package.json is excluded by !**/*.json
  • packages/service-vector-store/package.json is excluded by !**/*.json
  • packages/shared-adapter/package.json is excluded by !**/*.json
📒 Files selected for processing (3)
  • packages/core/src/render/base.ts
  • packages/core/src/render/koishi-element.ts
  • packages/core/src/render/stream.ts

Walkthrough

本次变更统一 split 模式下流式渲染元素的包装形式,并将 ReplyStream 默认发送路径的参数改为数组包装。

Changes

流式渲染输出

Layer / File(s) Summary
统一 split 元素包装
packages/core/src/render/base.ts, packages/core/src/render/koishi-element.ts
启用 split 时,renderPartswriteflush 会将非 message 元素包装为 h('message', el)
调整默认发送参数
packages/core/src/render/stream.ts
默认发送路径将审查后的 processed 包装为数组后传入 context.send

Estimated code review effort: 3 (Moderate) | ~15–30 minutes

Possibly related PRs

Poem

小兔挥笔改渲染,
分片元素裹成 message。
流水发送添新匣,
一层数组稳稳接。
蹦蹦跳过代码林,
月光下兔耳笑盈盈。

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/core-markdown-split

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dingyi222666
dingyi222666 deleted the fix/core-markdown-split branch July 13, 2026 19:32

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request bumps the version of koishi-plugin-chatluna to 1.4.0-alpha.41 across multiple packages and updates the core rendering logic to support message splitting. The review feedback correctly identifies a critical issue where mapping individual elements to separate message elements when splitting is enabled will break rendering for inline formatting (such as bold text, links, or images) by fragmenting them into multiple messages. The reviewer's suggestions to wrap the entire array of elements in a single message element instead are highly appropriate and should be implemented to preserve message integrity.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +111 to +117
result.push(
...(this.options.split && this.options.split !== 'none'
? elements.map((el) =>
el.type === 'message' ? el : h('message', el)
)
: elements)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When split mode is enabled, mapping each individual element to a message element causes formatting elements (such as bold text, links, or images) within a single sentence/paragraph to be split into separate messages. This results in broken rendering and multiple fragmented messages in the chat client.

Instead, the entire array of elements for a single part should be wrapped in a single message element (unless it already contains message elements).

            if (elements.length > 0) {
                result.push(
                    ...(this.options.split && this.options.split !== 'none'
                        ? elements.some((el) => el.type === 'message')
                            ? elements
                            : [h('message', ...elements)]
                        : elements)
                )
            }

Comment on lines +77 to +82
let elements = this.splitter.writeText(text)
if (this.options.split && this.options.split !== 'none') {
elements = elements.map((el) =>
el.type === 'message' ? el : h('message', el)
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When split mode is enabled, mapping each individual element to a message element causes elements that are part of the same text block to be split into separate messages. Wrapping the entire array of elements in a single message element (unless it already contains message elements) preserves the integrity of the message structure.

Suggested change
let elements = this.splitter.writeText(text)
if (this.options.split && this.options.split !== 'none') {
elements = elements.map((el) =>
el.type === 'message' ? el : h('message', el)
)
}
let elements = this.splitter.writeText(text)
if (this.options.split && this.options.split !== 'none' && elements.length > 0) {
elements = elements.some((el) => el.type === 'message')
? elements
: [h('message', ...elements)]
}

Comment on lines +92 to +97
let elements = this.splitter.flush()
if (this.options.split && this.options.split !== 'none') {
elements = elements.map((el) =>
el.type === 'message' ? el : h('message', el)
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When split mode is enabled, mapping each individual element to a message element causes elements that are part of the same text block to be split into separate messages. Wrapping the entire array of elements in a single message element (unless it already contains message elements) preserves the integrity of the message structure.

Suggested change
let elements = this.splitter.flush()
if (this.options.split && this.options.split !== 'none') {
elements = elements.map((el) =>
el.type === 'message' ? el : h('message', el)
)
}
let elements = this.splitter.flush()
if (this.options.split && this.options.split !== 'none' && elements.length > 0) {
elements = elements.some((el) => el.type === 'message')
? elements
: [h('message', ...elements)]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant