Skip to content

Commit 86cd62f

Browse files
秦奇claude
andcommitted
feat(sdk/daemon-ui): render contract — markdown / HTML / plain text helpers (PR-D)
Closes the "render 契约只覆盖 terminal" gap surfaced in the PR QwenLM#4328 review: > PR ships `daemonUiEventToTerminalText` for terminal. Web/IDE/channel > adapters each roll their own projection. No shared contract → adapter > divergence is inevitable. ## New helpers ```ts daemonBlockToMarkdown(block, opts?): string // GFM-compatible daemonBlockToHtml(block, opts?): string // conservatively escaped HTML daemonBlockToPlainText(block, opts?): string // for copy-paste / logs daemonToolPreviewToMarkdown(preview, opts?): string ``` All three respect the same `kind` discrimination so adapters can switch between them without touching call sites. ## Per-kind projection For each `DaemonTranscriptBlock['kind']`: - `user` / `assistant` / `thought` — plain text with role labels - `tool` — header with toolName + structured preview + status badge - `shell` — fenced code block, stream-discriminated (stdout vs stderr) - `permission` — title + options list + resolved/pending indicator - `status` / `debug` / `error` — semantic class / role (error → role=alert) For each `DaemonToolPreview['kind']`: - `ask_user_question` — question + options as bullet list - `command` — fenced bash with optional cwd comment - `file_diff` — unified diff in fenced code block (oldText/newText OR patch) - `file_read` — `path (lines N-M)` line - `web_fetch` — `METHOD url` line - `mcp_invocation` — `serverId::toolName` with args summary - `key_value` — bullet list - `generic` — emphasized summary ## Security - Default HTML sanitizer escapes `<`, `>`, `&`, `"`, `'` and FIRST strips ANSI/control sequences via `sanitizeTerminalText` (defense against agent-emitted escape codes in HTML output). - Custom sanitizer hook for consumers wanting markdown→HTML pipelines (markdown-it + DOMPurify, etc.). - `sanitizeUrls` option strips token-like query params (`token=`, `key=`, `x-amz-`, etc.) from URLs in `web_fetch` previews. - `maxFieldLength` truncation defaults 8192, prevents pathological rendering on huge content. ## Adapter conformance (out of scope for this commit) The conformance test framework (fixture corpus + `runAdapterConformanceSuite`) mentioned in PR-D scope is deferred to a follow-up. The render helpers here are the precondition — once stable, the conformance framework can use them as the reference projection. ## Test coverage (77/77 pass) - All 9 block kinds render in markdown (verified for user/assistant/tool/ shell/permission/error specifically) - file_diff renders as unified diff with old/new lines - mcp_invocation renders as `server::tool` format - HTML escapes XSS (`<script>` → `&lt;script&gt;`) - HTML strips terminal escape sequences before escaping - Error blocks emit `role="alert"` for screen readers - plain text drops markdown delimiters - maxFieldLength truncates with ellipsis - sanitizeUrls strips token query params - Custom sanitizer hook works ## Roadmap PR-D of the unified follow-up to PR QwenLM#4328 — completes the 5-PR series (A: event coverage, B: time schema, E: state machine, C: tool preview + content extraction, D: render contract). Generated with AI Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent e6f5758 commit 86cd62f

3 files changed

Lines changed: 595 additions & 0 deletions

File tree

packages/sdk-typescript/src/daemon/ui/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ export {
2424
daemonUiEventToTerminalText,
2525
transcriptBlockToTerminalText,
2626
} from './terminal.js';
27+
export {
28+
daemonBlockToHtml,
29+
daemonBlockToMarkdown,
30+
daemonBlockToPlainText,
31+
daemonToolPreviewToMarkdown,
32+
} from './render.js';
33+
export type {
34+
DaemonHtmlRenderOptions,
35+
DaemonRenderOptions,
36+
} from './render.js';
2737
export {
2838
extractContentPart,
2939
getOutputText,

0 commit comments

Comments
 (0)