Conversation
Add two new UI configuration options for controlling Chain of Thought step rendering: - `cot_display`: "list" (default, current behavior) or "compact" (collapses all steps into a single summary accordion line like "Using search_web" / "Used 5 tools") - `show_step_details`: boolean (default true). When false, steps render as flat labels without expandable input/output details. New CompactSteps component groups step-type children under one accordion with an animated "Using X" label while running and a "Used N steps/tools" summary when complete. Includes translations for all 23 supported languages.
- Add countVisibleSteps helper that walks the full step subtree, fixing compact mode not activating when tools are nested under intermediate agent/run steps (e.g. LangGraph, LangChain). - In CompactSteps, use collectVisible for recursive count/naming and pass all step-type children to <Messages> so existing skip logic drills through intermediates to reach tools. - Switch showUsing signal from isRunning to !hasAnswer (presence of assistant_message in subtree), preventing both the flash between sequential tools and the stale "Using" label during answer streaming.
There was a problem hiding this comment.
2 issues found across 32 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…middelen' feat(ReadOnlyThread): add support for latex and dataPersistence features
|
This PR is stale because it has been open for 14 days with no activity. |
|
This looks nice! |
|
This PR is stale because it has been open for 14 days with no activity. |
Co-Authored-By: GitHub Copilot <noreply@github.com>
dokterbob
left a comment
There was a problem hiding this comment.
Nice job, very comprehensive, cool/useful new feature!
However, to be able to maintain it, we really kinda need ... E2E tests.
Any chance you could add a substantial/comprehensive E2E test for this feature? 🥺 🙏🏼
Add Cypress coverage for the compact chain-of-thought display: - collapses multiple steps into a single summary and expands on click - leaves a single step uncollapsed - counts nested steps recursively to trigger compact mode Adds data-testid hooks to CompactSteps for stable selection. Co-Authored-By: GitHub Copilot <noreply@github.com>
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Thanks! 🙏 Just pushed a comprehensive E2E test (compact_steps) covering:
I also added |
|
@codex review |
|
This PR is stale because it has been open for 14 days with no activity. |
…lat CoT Two behavioral asymmetries reported on the compact CoT display: - Compact mode only lifted direct message children of a run to the root, so an assistant message emitted inside a nested step stayed trapped in the collapsed summary. Collect messages recursively and strip them from the accordion body. - show_step_details=false dropped a step's whole subtree. Now it only hides the input/output payload: steps with sub-steps stay collapsible, leaves render as flat labels, preserving the (collapsible) hierarchy. Adds E2E coverage: a nested-message case in compact_steps and a new step_details spec. Co-Authored-By: GitHub Copilot <noreply@github.com>
There was a problem hiding this comment.
All reported issues were addressed across 9 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
… assertion - Step: a step whose children are all messages is no longer 'expandable' into an empty accordion — hasSubSteps now matches what the body renders (non-message children), consistent with nestedSteps. - E2E: assert the nested message is absent from the compact summary after expanding it (Radix unmounts closed content, so the collapsed check was vacuous). Co-Authored-By: GitHub Copilot <noreply@github.com>
|
@lamylio nice catches, thank you 🙏 both repros were spot on. Fixed in For the nested message one — the issue was compact mode only pulled the run's top-level messages out to the root, but your message was For Added E2E for both (nested-message case in @dokterbob lmk if that |
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
The non-message sub-step filter must only gate flat-mode expandability. Applying it to hasContent regressed default mode: a step whose children are all messages (e.g. a run wrapping assistant messages) flattened and dropped its accordion body, including MessageButtons. Keep hasContent based on any children; use the non-message filter solely for the show_step_details=false branch. Co-Authored-By: GitHub Copilot <noreply@github.com>
dokterbob
left a comment
There was a problem hiding this comment.
Happy to merge this once (minor) merge conflicts are solved.
…splay # Conflicts: # backend/chainlit/translations/pt-PT.json
…eat/compact-cot-display
Conflict resolved and merged latest main in, so it should be clean now. 🙏 |
|
Thanks @dokterbob. auto-merge seems blocked on your earlier "Requested changes" review |
|
Hey, actually I've implemented this PR in a private fork, and upon testing it a bit more I came across another issue. It might be a personal taste, but the displayed parent step does not properly use the latest step's avatarName/iconName. I personally simply fixed it like this: # frontend/src/components/chat/Messages/CompactSteps.tsx
- <MessageAvatar author={lastStep?.name || 'Assistant'} />
+ <MessageAvatar
+ author={lastStep?.name || 'Assistant'}
+ avatarName={lastStep?.metadata?.avatarName}
+ iconName={lastStep?.metadata?.icon}
+ />
# could be extended to isError also?just so you know :) |
Compact mode hardcoded the summary avatar to the step name, so custom step icons/avatars and error state were dropped (they showed in list mode only). Pass avatarName/icon/isError from the last step, mirroring the normal message path. Adds an E2E covering the icon case. Co-Authored-By: GitHub Copilot <noreply@github.com>
Head branch was pushed to by a user without write access
Good catch, thanks @lamylio 🙏 Fixed in Also added an E2E covering the icon in the compact summary. |
|
This PR is stale because it has been open for 14 days with no activity. |
Co-Authored-By: GitHub Copilot <noreply@github.com>
There was a problem hiding this comment.
4 issues found across 39 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="backend/chainlit/translations/el-GR.json">
<violation number="1" location="backend/chainlit/translations/el-GR.json:104">
P2: The completed compact summary uses `Χρησιμοποίησε`, which reads as an instruction or an incomplete active clause rather than “Used N steps/tools.” Use the passive plural forms so the Greek status accurately describes the completed run.</violation>
</file>
<file name="frontend/src/components/chat/Messages/CompactSteps.tsx">
<violation number="1" location="frontend/src/components/chat/Messages/CompactSteps.tsx:72">
P2: When an assistant message is emitted before its parent run finishes, `showUsing` becomes false while `isRunning` is true, so the compact summary says “Used” during active work. Keep the running label until the parent run ends.</violation>
</file>
<file name="backend/chainlit/translations/ar-SA.json">
<violation number="1" location="backend/chainlit/translations/ar-SA.json:103">
P3: The Arabic strings hardcode the plural noun “خطوات/أدوات” for every count, but Arabic number–noun agreement depends on the value of {{count}}. Compact mode activates at 2+ visible steps, so count=2 (the most common case) renders “استُخدمت 2 خطوات”, which is ungrammatical — two takes the dual “خطوتان”, and numbers 11+ take the singular “خطوة”. Since `Translator` substitutes whatever count is passed, this wrong form shows for real users whenever 2 (or ≥11) steps/tools are used. Reword the string so it stays grammatical for any count (e.g. “الخطوات المستخدمة: {{count}}”), or add i18next plural variants (`usedSteps_two`/`usedSteps_few`/`usedSteps_many`) for this locale.</violation>
</file>
<file name="frontend/src/components/chat/MessagesContainer/index.tsx">
<violation number="1" location="frontend/src/components/chat/MessagesContainer/index.tsx:180">
P3: The new context fields were correctly added to the useMemo dependency array, but the same array still omits other values the memo body reads: `latex` (`config?.features?.latex`), `editable` (`config?.features.edit_message`), `onFeedbackDeleted`, and `uploadFile`. While the diff is extending this dependency array anyway, closing those gaps keeps all context fields in sync; as written, `latex`/`editable`/`onFeedbackDeleted` can serve stale values if the config or callbacks change (e.g., the initial `useConfig` load completing after a partial render). Compare with `ReadOnlyThread.tsx`, where the same change also added the previously missing `config?.features?.latex` and `config?.dataPersistence`.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| "usedSteps": "Χρησιμοποίησε {{count}} βήματα", | ||
| "usedTools": "Χρησιμοποίησε {{count}} εργαλεία" |
There was a problem hiding this comment.
P2: The completed compact summary uses Χρησιμοποίησε, which reads as an instruction or an incomplete active clause rather than “Used N steps/tools.” Use the passive plural forms so the Greek status accurately describes the completed run.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/chainlit/translations/el-GR.json, line 104:
<comment>The completed compact summary uses `Χρησιμοποίησε`, which reads as an instruction or an incomplete active clause rather than “Used N steps/tools.” Use the passive plural forms so the Greek status accurately describes the completed run.</comment>
<file context>
@@ -100,7 +100,9 @@
"using": "Με τη χρήση",
- "used": "Χρησιμοποιήθηκε"
+ "used": "Χρησιμοποιήθηκε",
+ "usedSteps": "Χρησιμοποίησε {{count}} βήματα",
+ "usedTools": "Χρησιμοποίησε {{count}} εργαλεία"
},
</file context>
| "usedSteps": "Χρησιμοποίησε {{count}} βήματα", | |
| "usedTools": "Χρησιμοποίησε {{count}} εργαλεία" | |
| "usedSteps": "Χρησιμοποιήθηκαν {{count}} βήματα", | |
| "usedTools": "Χρησιμοποιήθηκαν {{count}} εργαλεία" |
| return check(steps); | ||
| }, [steps]); | ||
|
|
||
| const showUsing = !!isRunning && !hasAnswer; |
There was a problem hiding this comment.
P2: When an assistant message is emitted before its parent run finishes, showUsing becomes false while isRunning is true, so the compact summary says “Used” during active work. Keep the running label until the parent run ends.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/chat/Messages/CompactSteps.tsx, line 72:
<comment>When an assistant message is emitted before its parent run finishes, `showUsing` becomes false while `isRunning` is true, so the compact summary says “Used” during active work. Keep the running label until the parent run ends.</comment>
<file context>
@@ -0,0 +1,151 @@
+ return check(steps);
+ }, [steps]);
+
+ const showUsing = !!isRunning && !hasAnswer;
+
+ // Get the last visible step name for the "Using X" label
</file context>
| "usedSteps": "استُخدمت {{count}} خطوات", | ||
| "usedTools": "استُخدمت {{count}} أدوات" |
There was a problem hiding this comment.
P3: The Arabic strings hardcode the plural noun “خطوات/أدوات” for every count, but Arabic number–noun agreement depends on the value of {{count}}. Compact mode activates at 2+ visible steps, so count=2 (the most common case) renders “استُخدمت 2 خطوات”, which is ungrammatical — two takes the dual “خطوتان”, and numbers 11+ take the singular “خطوة”. Since Translator substitutes whatever count is passed, this wrong form shows for real users whenever 2 (or ≥11) steps/tools are used. Reword the string so it stays grammatical for any count (e.g. “الخطوات المستخدمة: {{count}}”), or add i18next plural variants (usedSteps_two/usedSteps_few/usedSteps_many) for this locale.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/chainlit/translations/ar-SA.json, line 103:
<comment>The Arabic strings hardcode the plural noun “خطوات/أدوات” for every count, but Arabic number–noun agreement depends on the value of {{count}}. Compact mode activates at 2+ visible steps, so count=2 (the most common case) renders “استُخدمت 2 خطوات”, which is ungrammatical — two takes the dual “خطوتان”, and numbers 11+ take the singular “خطوة”. Since `Translator` substitutes whatever count is passed, this wrong form shows for real users whenever 2 (or ≥11) steps/tools are used. Reword the string so it stays grammatical for any count (e.g. “الخطوات المستخدمة: {{count}}”), or add i18next plural variants (`usedSteps_two`/`usedSteps_few`/`usedSteps_many`) for this locale.</comment>
<file context>
@@ -99,7 +99,9 @@
"using": "يستخدم",
- "used": "مستخدم"
+ "used": "مستخدم",
+ "usedSteps": "استُخدمت {{count}} خطوات",
+ "usedTools": "استُخدمت {{count}} أدوات"
},
</file context>
| "usedSteps": "استُخدمت {{count}} خطوات", | |
| "usedTools": "استُخدمت {{count}} أدوات" | |
| "usedSteps": "الخطوات المستخدمة: {{count}}", | |
| "usedTools": "الأدوات المستخدمة: {{count}}" |
| loading, | ||
| config?.ui?.name, | ||
| config?.ui?.cot, | ||
| config?.ui?.cot_display, |
There was a problem hiding this comment.
P3: The new context fields were correctly added to the useMemo dependency array, but the same array still omits other values the memo body reads: latex (config?.features?.latex), editable (config?.features.edit_message), onFeedbackDeleted, and uploadFile. While the diff is extending this dependency array anyway, closing those gaps keeps all context fields in sync; as written, latex/editable/onFeedbackDeleted can serve stale values if the config or callbacks change (e.g., the initial useConfig load completing after a partial render). Compare with ReadOnlyThread.tsx, where the same change also added the previously missing config?.features?.latex and config?.dataPersistence.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/chat/MessagesContainer/index.tsx, line 180:
<comment>The new context fields were correctly added to the useMemo dependency array, but the same array still omits other values the memo body reads: `latex` (`config?.features?.latex`), `editable` (`config?.features.edit_message`), `onFeedbackDeleted`, and `uploadFile`. While the diff is extending this dependency array anyway, closing those gaps keeps all context fields in sync; as written, `latex`/`editable`/`onFeedbackDeleted` can serve stale values if the config or callbacks change (e.g., the initial `useConfig` load completing after a partial render). Compare with `ReadOnlyThread.tsx`, where the same change also added the previously missing `config?.features?.latex` and `config?.dataPersistence`.</comment>
<file context>
@@ -175,6 +177,8 @@ const MessagesContainer = ({ navigate }: Props) => {
loading,
config?.ui?.name,
config?.ui?.cot,
+ config?.ui?.cot_display,
+ config?.ui?.show_step_details,
config?.features?.unsafe_allow_html,
</file context>



Summary
Adds two new
[UI]config options (cot_displayandshow_step_details) that give app developers control over how Chain of Thought steps are displayed in the chat interface.Motivation
When an agent uses many tools sequentially, the default "list" display creates a long vertical stack of individual step accordions. This can overwhelm users who only care about the final result. The new
compactmode provides a ChatGPT-style collapsible summary.New Config Options
Added to
.chainlit/config.tomlunder[UI]:cot_display"list"|"compact""list"list= current behavior (each step as its own accordion).compact= all steps collapsed into one summary line.show_step_detailstrue|falsetruefalse, steps render as flat labels without expandable input/output.Compact Mode Behavior
tool_callcot mode) when completeChanges
Backend:
config.py— Addedcot_displayandshow_step_detailstoUISettingsmodel + TOML templatetranslations/*.json— AddedusedStepsandusedToolskeys to all 23 language filesFrontend:
messageContext.ts/MessageContext.tsx— AddedcotDisplayandshowStepDetailsto contextMessagesContainer/index.tsx/ReadOnlyThread.tsx— Wire config values into contextMessages/index.tsx— Compact mode branching logic for CL_RUN_NAMES handlerMessages/CompactSteps.tsx— New component for compact step summaryMessages/Message/Step.tsx— RespectshowStepDetailsto render flat labelTypes:
libs/react-client/src/types/config.ts— Added TS types for new config fieldsTesting
listandcompactmodesBackward Compatibility
Both options default to the existing behavior (
list/true). No breaking changes — apps without these config keys behave identically to before..chainlit/translations/files will see lint warnings for the newusedSteps/usedToolskeys on startup. This only affects users who opt intocot_display = "compact". To pick up the new keys, delete the local.chainlit/translations/folder and restart — Chainlit will regenerate it from the updated source. This follows the same pattern as all prior translation additions in this project.Summary by cubic
Adds two
[UI]config options that give app developers control over how Chain of Thought steps render:cot_display="compact"collapses multiple steps into one summary line instead of a vertical stack of accordions, andshow_step_details=falsepreserves the collapsible step hierarchy while hiding input/output payloads. Both default to the existing behavior, so backward compatible.show_step_details=falserenders leaf steps as flat labels while keeping the hierarchy expandable; in default list mode, message-only steps remain expandable.CompactStepscomponent;MessageContextgainscotDisplay/showStepDetails; read-only threads respectfeatures.latexanddataPersistence;usedSteps/usedToolsadded to all locales.Migration
[UI] cot_display = "compact"and/orshow_step_details = falsein.chainlit/config.toml..chainlit/translations/, delete the folder to regenerate and pick upusedSteps/usedTools.Written for commit 4b15775. Summary will update on new commits.