Add a minimal web chat UI served by ds4-server - #718
Open
phierru wants to merge 3 commits into
Open
Conversation
Co-authored-by: Francesco Lardieri <flardi@gmx.net> Co-authored-by: DwarfStar AI Agent <agent@dwarfstar.ai>
The UI previously rendered only bold/italic/code and showed raw Markdown and LaTeX for everything else, which is unreadable for models that emit headings, tables and equations. - Markdown: headings, nested lists, tables, blockquotes, links, rules, fenced and inline code. Code and math are pulled out before escaping so their contents are never mangled by the inline rules. - Math: KaTeX renders $$..$$ and \[..\] as display, $..$ and \(..\) inline. Inline $..$ requires non-space next to both delimiters so prose like "costs $5 and $7" is not swallowed. If KaTeX cannot load the source LaTeX is shown instead of being lost, and messages re-render on load. - Thinking toggle in the header sends reasoning_effort per request (off by default, persisted in localStorage). GLM emits visible reasoning otherwise, which is costly at streaming speeds. - Copy button per message copies the raw Markdown, not rendered HTML. - Stop button (and Esc) aborts generation, keeping text received so far as ordinary history; an empty response bubble is removed instead. The embedded copy in ds4_server.c is generated from chat-ui.html rather than hand-escaped, since the LaTeX regexes are backslash-heavy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The chat UI lives in two places: chat-ui.html, which is editable and can be opened from disk, and a string literal in ds4_server.c so the binary serves the page without external assets. Keeping those in sync by hand is a trap, because the Markdown and LaTeX regexes are backslash-heavy and a single missed escape yields a page that compiles but renders wrongly. - tools/gen_chat_ui.py regenerates the embedded copy from chat-ui.html. --check reports staleness without writing, for use before a release. - tools/test_chat_ui.js covers the renderer: Markdown blocks, HTML escaping, and the math delimiters. It accepts a path, so the same suite can run against a page fetched from a running ds4-server; that is what proves the C escaping survived the round trip, which compiling cannot tell you. Co-Authored-By: Claude Opus 5 <noreply@anthropic.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.
I added a minimal web chat interface, served directly by
ds4-serverat/, so amodel can be used from a browser without any extra tooling. There is no build step
and nothing to install: the page is embedded in the binary as a string literal, and
chat-ui.htmlis the same page as a standalone file if you prefer to open it fromdisk.
Trying it
Then open http://127.0.0.1:8000 — the UI is served by
ds4-serveritself on itsusual port, not by a separate process.
Two prompts that exercise the rendering:
Show me the Maxwell equationsExplain briefly how these equations imply electromagnetic wavesThe first comes back with headings, bold text and display equations; the follow-up
uses inline math inside bullet lists.
What it does
/v1/chat/completionsSSE endpoint.rules, fenced and inline code.
$$..$$and\[..\]as display math,$..$and\(..\)inline. Inline$..$requires a non-space character next to bothdelimiters, so ordinary prose like "costs $5 and $7" is not swallowed as math.
reasoning_effortper request, off bydefault. GLM 5.2 emits visible reasoning otherwise, which is tedious to read at
streaming speeds.
HTML, and a stop button (also bound to Esc) that aborts generation while keeping
whatever text already arrived.
Notes, and things you may want changed
of the fonts. If it fails to load, equations degrade to showing the raw LaTeX
instead of breaking, and re-render if it arrives late. I am happy to drop math
rendering altogether if you would rather the UI carry no external dependency.
ds4_server.cis generated fromchat-ui.htmlrather thanescaped by hand, since the LaTeX regexes are backslash-heavy and one missed escape
yields a page that compiles but renders wrongly.
tools/gen_chat_ui.pyregeneratesit;
tools/gen_chat_ui.py --checkreports staleness without writing, if you wantit in a pre-release check.
tools/test_chat_ui.jscovers the renderer (Markdown blocks, HTML escaping, mathdelimiters). It takes an optional path, so the same suite can be run against a page
fetched from a running
ds4-server— that is what verifies the C escaping survivedthe round trip, which compiling cannot tell you. Plain
node, no dependencies.streaming). The UI is model-agnostic and reads the model id from
/v1/models.answers
GET /, which was previously unhandled.