Note
Grok responding on behalf of Julius.
Thanks for the detailed report. I checked it against current main (30cc78897), and the Tab and Shift+Enter parts hold up.
What the code does (confirmed)
- Tab:
listIndentForTabalways inserts" "at the start of the line and leaves the marker alone, so2.stays2.. The existing test only checks a bullet (- foo→- foo). - Both modes use it: the Tiptap editor passes Tab to the composer's key handler in plain and rich mode, and Tiptap's own list Tab/Shift-Tab are turned off.
ChatComposerthen callslistIndentForTab. - Why rich mode looks nested: the rich-text parser treats any deeper indent prefix as a child list, with no content-column check. Serialization then writes the stored indent back as typed. So the editor draws
1. first\n 2. nestedas nested, but the prompt text that gets sent is exactly that string. I ran it throughmdast-util-from-markdownwith GFM (the same micromark stackreact-markdown/remark-gfmuse)."1. first\n 2. nested"comes out as one flat list with two items, and"1. first\n 1. nested"comes out nested.- a\n - bnests fine, as you said. - Plain-mode Shift+Enter on an empty item:
listContinuationForEnterremoves the marker no matter how deep the indent is. Rich mode handles list items throughsplitOrLiftListItem, which lifts an empty item one level. That's why the two modes behave differently. - Shift+Tab:
ChatComposertoggles plan mode, or returnsfalsewhen plan mode isn't available, which lets the browser move focus back. Nothing outdents a list item.
The user docs say Tab nests a list item and that what you type is what the agent receives. That makes the flat result a bug and not intended behavior.
Inferred / not verified
- I didn't check how the sent message bubble renders this in the app. With the parser above it would likely show as a flat list.
- How a given model reads
2. nestedis outside our control. The sent text is simply not a nested list in CommonMark.
Possible fix direction (untested)
- Tab on a list line should indent to the item above's content column (marker width plus its following space, so 3 for
1.and 4 for10.). For ordered items it should restart at1.or continue an existing sublist. Because rich mode serializes the stored indent, fixing the source edit would likely fix both modes. - Plain-mode Shift+Enter on an empty nested item could outdent to the parent's indent and continue the parent's numbering, matching what rich mode already does.
- Whether Shift+Tab should outdent nested list lines is a separate maintainer call, since it changes the plan-mode shortcut on those lines. It isn't needed for the Tab/Shift+Enter fix.
Related
- #14332 (open): renumbers following items when you insert into a numbered list. It edits the same
composer-list-continuation.tsfunctions and the sameChatComposercall site. It also adds a caret field toComposerListEdit. Your branch adds one too, so the two would need reconciling. GitHub already shows #14332 as conflicting withmain. - #14677 (merged): added block-level Markdown to the rich composer, where the current list parsing and serialization live.
- #8394 (open, different issue: numbers in a message turning into a list) and #12145 (closed, unmerged earlier list-continuation attempt).
On scope, your fork branch is one commit. It touches composer-list-continuation.ts and its tests, ChatComposer.tsx, and docs/user/composer.md, which covers the Tab nesting, the Shift+Enter outdent, and the Shift+Tab outdent. I haven't run it.