docs/design/markdown-chart-skill-integration.md
Status: accepted
Qwen Code WebShell owns the rendering side of the contract:
@qwen-code/web-shell includes the markdown-chart renderer and ECharts
runtime.markdown-chart skill
so the model emits renderable chart blocks..qwen/skills/markdown-chart/SKILL.md; user-level skill installation is
also supported.For the normal data.kind="inline" output produced by the skill, the WebShell
host needs no chart-specific code:
import { WebShellWithProviders } from '@qwen-code/web-shell';
<WebShellWithProviders
baseUrl="http://127.0.0.1:4170"
token={token}
sessionId={sessionId}
/>;
If the host exposes real controlled datasets to the skill and allows
data.kind="ref", it provides resolveDataRef through a custom registry:
import {
createMarkdownChartRegistry,
WebShellWithProviders,
} from '@qwen-code/web-shell';
const chartRegistry = createMarkdownChartRegistry({
resolveDataRef: async (ref, context) =>
loadControlledChartDataset(ref, context),
});
const markdown = { chart: { registry: chartRegistry } };
<WebShellWithProviders
baseUrl="http://127.0.0.1:4170"
token={token}
sessionId={sessionId}
markdown={markdown}
/>;
The renderer never fetches a ref or reads a local path by itself.
resolveDataRef is the host-owned boundary from a model-visible reference to a
trusted dataset. The default registry accepts normalized artifact:// and
session-file:// refs, parses the block as JSON, validates the option, and then
passes the normalized ref plus declared format and dimensions to the resolver.
Resolver waits are bounded to 30 seconds. Keep markdown, chart, and
labels overrides referentially stable while charts are mounted.
The shared React adapter distinguishes a closed chart fence from the active unterminated tail fence:
markdown-chart block renders immediately and remains mounted while
later answer text streams, including when the fence is inside a blockquote.