Files
boos e0a5f57793 feat(desktop): embed BoosAPI Desktop client as a subproject
Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
2026-06-22 11:32:57 +08:00

209 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# markstream-vue — Agent Context (`/llms`)
This file is a **compact, agent-focused** map of `markstream-vue`: where things live, how to answer common questions, and what to check first when users report issues.
For human-facing prompts and reusable rollout templates, also see `/guide/ai-workflows`.
## Answering guidelines
- Prefer **user-facing behavior** from `docs/guide/*` (and `docs/zh/guide/*`) and **export surface** from `src/exports.ts`.
- Ask **at most one** clarifying question if the request is ambiguous.
- When debugging, ask for a **minimal repro** (there’s a shareable test page) and walk the user through the checklist below.
- Avoid raw HTML tags like `<thinking>` in Markdown docs pages; escape them (VitePress compiles Markdown as Vue SFC).
---
## Setup commands
- Install deps: `pnpm install`
- Playground dev: `pnpm dev`
- Docs dev/build/serve: `pnpm docs:dev`, `pnpm docs:build`, `pnpm docs:serve`
- Tests: `pnpm test`
- Typecheck: `pnpm typecheck`
- Lint: `pnpm lint`
---
## Repo structure
- Library source: `src/`
- Public exports: `src/exports.ts`
- Components: `src/components/*/`
- Workers: `src/workers/`
- Utilities: `src/utils/`, `src/composables/`, `src/types/`
- Parser-only package: `packages/markdown-parser/` (published as `stream-markdown-parser`)
- Docs site (VitePress): `docs/` (Chinese under `docs/zh/`)
- Demos: `playground/` (Vite), `playground-nuxt/` (Nuxt SSR)
- Tests: `test/` (Vitest)
---
## Core mental model
There are two layers:
1) **Parser layer** (`stream-markdown-parser`)
- `getMarkdown()` creates a configured `markdown-it-ts` instance
- `parseMarkdownToStructure(content, md)` turns Markdown into a node tree (`ParsedNode[]`)
- Streaming mid-states reduce flicker (unclosed fences / `$$` / partial inline HTML)
2) **Renderer layer** (`markstream-vue`)
- Default component: `MarkdownRender` (also referred to as `NodeRenderer`)
- Takes either `content: string` (parses internally) or `nodes: ParsedNode[]` (recommended for streaming)
- Performance tools:
- Virtualization window (`maxLiveNodes`, `liveNodeBuffer`)
- Batch rendering (steady “typewriter” feel)
- Defer heavy nodes until visible (`viewportPriority`, `deferNodesUntilVisible`)
---
## Public API (safe to suggest)
From `markstream-vue` (`src/exports.ts`):
- Component: `MarkdownRender` (default export)
- Parser helpers (re-exported): `getMarkdown()`, `parseMarkdownToStructure(content, md)`, `setDefaultMathOptions()`
- Custom node renderers: `setCustomComponents()`, `removeCustomComponents()`, `clearGlobalCustomComponents()`
- Feature toggles: `enableMermaid()`, `disableMermaid()`, `enableKatex()`, `disableKatex()`
- Worker injection:
- KaTeX: `createKaTeXWorkerFromCDN()`, `setKaTeXWorker()`
- Mermaid: `createMermaidWorkerFromCDN()`, `setMermaidWorker()`
From `stream-markdown-parser` (`packages/markdown-parser/src/index.ts`):
- `getMarkdown()`, `parseMarkdownToStructure(content, md)`, `ParseOptions` hooks
- Streaming mid-state behavior and `final: true` end-of-stream mode
---
## Troubleshooting checklist (high signal)
When “it doesn’t render” or “looks wrong”, check these in order:
1) **CSS order/reset**: reset first, then `markstream-vue/index.css` (Tailwind usually inside `@layer components`).
2) **Optional peer installed** (Mermaid/KaTeX/Monaco/Shiki).
3) **Loader enabled** if you disabled or override it: `enableMermaid()` / `enableKatex()`.
4) **Peer CSS imported** where required: `katex/dist/katex.min.css` (Mermaid does not require extra CSS).
5) **Standalone node wrapper**: standalone node components need a `.markstream-vue` wrapper for scoped styles/vars.
6) **SSR**: in Nuxt, wrap with `<client-only>` when using browser-only peers/workers.
Docs: `docs/guide/troubleshooting.md`, `docs/guide/tailwind.md`, `docs/nuxt-ssr.md`
---
## Common intents (router)
Use these as “answer skeletons”: quick steps + minimal repro questions + where to read next.
### Install + first render
- Signals: “how to use”, “minimal example”
- Steps:
- Import CSS: `markstream-vue/index.css`
- Render: `<MarkdownRender :content="md" />`
- Ask: “Vite or Nuxt? Show your CSS import order (reset + Tailwind layers).”
- Docs: `docs/guide/quick-start.md`, `docs/guide/installation.md`
### CSS missing / Tailwind overrides
- Signals: “unstyled”, “Tailwind overrides”, “looks wrong”
- Steps:
- Ensure reset loads before `markstream-vue/index.css`
- Tailwind: import library CSS inside `@layer components`
- If using standalone node components, wrap `.markstream-vue`
- Ask: “Paste `main.css` (Tailwind layers) + where you import `markstream-vue/index.css`.”
- Docs: `docs/guide/tailwind.md`, `docs/guide/troubleshooting.md`
### Streaming: “loading forever” at end
- Signals: “stuck loading”, “final chunk”
- Steps:
- On end-of-stream set `final: true` (ParseOptions or component prop) so mid-states don’t stick
- Ask: “Do you set `final` when the stream ends? What are the last ~40 chars (often ends with ``` or $$)?”
- Docs: `docs/guide/parser-api.md`, `docs/guide/parser.md`
### Streaming: smooth typewriter feel
- Signals: “bursty”, “jumpy”, “not smooth”
- Steps:
- Enable/tune batching (`renderBatchSize` / `renderBatchDelay`)
- Keep heavy nodes deferred (`viewportPriority`, `deferNodesUntilVisible`)
- Ask: “How often do you update `content/nodes` (per token? per chunk?) and what batch props are set?”
- Docs: `docs/guide/performance.md`, `docs/guide/props.md`
### Large documents: perf/memory
- Signals: “huge markdown”, “scroll lag”, “memory high”
- Steps:
- Tune virtualization (`maxLiveNodes`, `liveNodeBuffer`)
- Keep heavy nodes deferred
- Ask: “Approx size (KB/lines)? Many code blocks/diagrams?”
- Docs: `docs/guide/performance.md`
### Mermaid not rendering
- Signals: “mermaid blank”
- Steps:
- Install peer `mermaid`
- If you disabled/overrode the loader, call `enableMermaid()` on the client (or set a custom loader)
- Re-check CSS order/reset
- Ask: “Did you disable the loader? Any SSR? Is the fence ```mermaid?”
- Docs: `docs/guide/mermaid.md`, `docs/guide/troubleshooting.md`
- Code: `src/components/MermaidBlockNode/mermaid.ts`
### KaTeX not rendering
- Signals: “math not shown”
- Steps:
- Install peer `katex`
- Import `katex/dist/katex.min.css`
- If you disabled/overrode the loader, call `enableKatex()` on the client (or set a custom loader)
- Ask: “Is KaTeX CSS imported? `$...$` or `$$...$$`? Any SSR? Did you disable the loader?”
- Docs: `docs/guide/math.md`, `docs/guide/installation.md`
- Code: `src/components/MathInlineNode/katex.ts`
### Monaco code blocks missing features / blank
- Signals: “toolbar missing”, “blank editor”
- Steps:
- Install peer `stream-monaco`
- Ensure Monaco workers are bundled (Vite plugin) and you’re on the client
- For app-level preloading, call `preloadCodeBlockRuntime()` from `markstream-vue`; do not import `stream-monaco` directly just to warm workers
- Ask: “Any worker-related console errors? Are Monaco workers bundled in production?”
- Docs: `docs/guide/monaco.md`, `docs/guide/components.md`
### Prefer lightweight code blocks (no Monaco)
- Signals: “SSR friendly”, “reduce bundle”
- Steps:
- Use `MarkdownCodeBlockNode` (Shiki) or `render-code-blocks-as-pre`
- If using Shiki, install `stream-markdown`
- Ask: “Need highlighting or just plain code?”
- Docs: `docs/guide/code-blocks.md`, `docs/guide/components.md`
### Custom components in Markdown (`<thinking>`)
- Signals: “custom tag”, “embed component”
- Steps:
- Allow custom tags via `customHtmlTags` / `custom-html-tags` (unknown tags render as raw HTML when closed; incomplete or malformed fragments stay as text)
- Map via `setCustomComponents(customId, mapping)`
- Ask: “What tag names? Do you want HTML passthrough or a custom node type?”
- Docs: `docs/guide/advanced.md`, `docs/guide/parser-api.md`
### Nuxt SSR errors
- Signals: “window is not defined”, “SSR crash”
- Steps:
- Wrap renderer in `<client-only>`
- Ensure heavy peers/workers initialize only in browser
- Ask: “Nuxt version? Error during build or runtime? Which peers are installed/enabled?”
- Docs: `docs/nuxt-ssr.md`
### “What does the package export?”
- Signals: “is X exported”, “how to import Y”
- Steps:
- Check `src/exports.ts` and `package.json#exports`
- Ask: “Which symbol and what import path did you try?”
- Docs: `docs/guide/components.md`, `docs/guide/api.md`