feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(session-ui): render Mermaid diagrams - #39818

Draft
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid
Draft

feat(session-ui): render Mermaid diagrams#39818
EugeneChan00 wants to merge 2 commits into
anomalyco:devfrom
EugeneChan00:aes29-mermaid

Conversation

@EugeneChan00

@EugeneChan00EugeneChan00 commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#39816

Linear surface: AES-29

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Renders completed Mermaid fences as strict, lazily loaded diagrams while retaining raw source for streaming, failure fallback, and copy. Theme changes rerender safely and stale asynchronous renders are ignored.

This restores the focused portion of #38175 and preserves its original commit authorship.

How did you verify your code works?

Ran the session-ui typecheck and focused Mermaid/stream tests (28 passing), plus the workspace typecheck (30 packages). In Storybook, verified the three-node diagram, surrounding prose, and the copy control changing from Copy to Copied.

Screenshots / recordings

Validated in the visible Browser against a real OpenCode web session and backend. The included Components/Markdown/Mermaid story remains as a focused reproduction surface.

Real OpenCode chat rendering Mermaid

Real OpenCode Mermaid rendering at 480px viewport

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Mermaid fenced code blocks now render as charts by default in the chat
markdown view (desktop and web), while the code block's copy button keeps
copying the original mermaid source.
- Split settled mermaid fences into standalone code blocks so both the
streaming and settled render paths route through one diagram handler.
- Render diagrams from a lazily imported, serialized mermaid instance and
fall back to the source while streaming, incomplete, or on parse errors.
- Track the app color scheme via a reactive signal on data-color-scheme so
diagrams re-render when the theme flips.
- Gate the settled-path mermaid split behind a fence regex so messages
without diagrams stay lexer-free.
- Collapse the mermaid/shiki resource branches into one block construction.
- Track only the last started render (source, scheme, request) per block;
failed parses no longer re-render on identical effect re-runs.
- Drop dead rejection handling from the serialized render queue.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

Related PR:

Why it's related: This PR also adds Mermaid diagram support for markdown, though it targets the app package rather than session-ui. It may have implemented similar diagram rendering functionality that could be worth reviewing for consistency or shared patterns.

However, the current PR (#39818) appears to be focused specifically on the session-ui component and is restoring work from #38175 with original authorship preserved, which suggests it's a distinct effort from the earlier app-level implementation.

Sign up for freeto 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.

Render Mermaid fences as diagrams in chat

2 participants

@EugeneChan00@ben-fornefeld