logo
0
0
WeChat Login

docs-ai-helper

A lightweight floating AI assistant for VuePress and VitePress documentation sites.

docs-ai-helper gives your docs a chat panel that can stream answers, render Markdown, highlight code with Shiki, carry page context to your backend, show reasoning blocks, follow internal documentation links, and fit into existing themes with CSS variables.

Chinese README

Features

  • Vue 2.7+ and Vue 3 support through vue-demi
  • VitePress and VuePress navigation helpers
  • Streaming responses from plain text, JSON lines, or SSE-style data: events
  • Markdown rendering with a Shiki-powered fallback
  • Optional reasoning display with a user-facing toggle
  • Suggested questions and configurable welcome state
  • Custom request payloads, stream parsers, identities, avatars, sizes, and CSS variables
  • Fixed or inline launcher modes, including compact toolbar and plain variants
  • Resizable chat panel with light and dark theme variables

Install

npm install docs-ai-helper vue-demi

If you do not pass your own renderMarkdown function, the fallback renderer dynamically imports shiki:

npm install shiki

For Vue 2 projects below Vue 2.7, also install and register @vue/composition-api.

Quick Start

VitePress

// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme';
import { h } from 'vue';
import { useRouter } from 'vitepress';
import { DocsAiHelper, createVitePressNavigator } from 'docs-ai-helper';
import 'docs-ai-helper/style.css';

export default {
  extends: DefaultTheme,
  enhanceApp({ app }) {
    app.component('DocsAiHelper', DocsAiHelper);
  },
  Layout() {
    const router = useRouter();

    return h(DefaultTheme.Layout, null, {
      'layout-bottom': () => h(DocsAiHelper, {
        endpoint: '/api/docs-chat',
        navigate: createVitePressNavigator(router),
        context: () => ({
          path: window.location.pathname,
          title: document.title
        }),
        suggestedQuestions: [
          { label: 'How do I get started?' },
          { label: 'Explain this page' },
          { label: 'Show me a TypeScript example' }
        ]
      })
    });
  }
};

VuePress

// client.ts / enhanceApp.ts
import { h } from 'vue';
import { DocsAiHelper, createVuePressNavigator } from 'docs-ai-helper';
import 'docs-ai-helper/style.css';

export default ({ app, router }) => {
  app.component('DocsAiHelperHost', {
    render() {
      return h(DocsAiHelper, {
        endpoint: '/api/docs-chat',
        navigate: createVuePressNavigator(router),
        context: () => ({
          path: window.location.pathname,
          title: document.title
        })
      });
    }
  });
};

Backend Contract

By default, the component sends POST requests to endpoint with this JSON body:

{
  "question": "User question",
  "context": {},
  "messages": [{ "role": "user", "content": "..." }]
}

The default stream parser accepts plain text chunks and SSE-style events:

data: {"content":"Answer chunk","reasoning":"Reasoning chunk"}
data: [DONE]

It also understands common OpenAI-compatible choices[0].delta.content payloads. Use requestBody or parseStream when your backend has a different protocol.

Markdown and Shiki

For the best visual match, pass the same Markdown renderer your docs site already uses:

h(DocsAiHelper, {
  endpoint: '/api/docs-chat',
  renderMarkdown: (markdown, message) => docsMarkdownRenderer.render(markdown)
});

Without renderMarkdown, the built-in fallback uses markdown-it and dynamically imports shiki for fenced code blocks:

import { createShikiMarkdownRenderer } from 'docs-ai-helper';

h(DocsAiHelper, {
  endpoint: '/api/docs-chat',
  renderMarkdown: createShikiMarkdownRenderer({
    theme: { light: 'github-light', dark: 'github-dark' },
    fallbackLang: 'text'
  })
});
Common configuration
h(DocsAiHelper, {
  endpoint: '/api/docs-chat',
  headers: { Authorization: 'Bearer ...' },
  assistant: { name: 'Docs Assistant', avatar: '/bot.png' },
  user: { name: 'You', avatar: '/me.png' },
  defaultOpen: false,
  showReasoningDefault: true,
  allowReasoningToggle: true,
  launcherText: 'AI',
  launcherMode: 'fixed',
  launcherVariant: 'primary',
  size: { width: 460, height: 660 },
  maxWidth: 960,
  maxHeight: 900,
  closeOnClear: false,
  cssVars: {
    '--dah-accent': '#0f766e',
    '--dah-radius': '6px'
  },
  panelClass: 'my-docs-ai-panel',
  launcherClass: 'my-docs-ai-launcher',
  suggestedQuestions: [
    { label: 'What is this page about?' },
    {
      label: 'Give me a TypeScript example',
      question: 'Give me a TypeScript example based on the current page.'
    }
  ],
  welcome: {
    title: 'Hi, I am your docs assistant',
    description: 'Choose a suggestion or ask your own question.'
  },
  context: () => ({
    path: location.pathname,
    title: document.title
  })
});
Exports
import DocsAiHelperPlugin, {
  DocsAiHelper,
  createShikiMarkdownRenderer,
  createVitePressNavigator,
  createVuePressNavigator,
  defaultMarkdownRenderer,
  defaultNavigate,
  defaultStreamParser
} from 'docs-ai-helper';

import type {
  ChatMessage,
  ChatRequestContext,
  MarkdownRenderer,
  NavigateHandler,
  RequestBodyBuilder,
  StreamParser
} from 'docs-ai-helper';
CSS variables
:root {
  --dah-font-family: Inter, ui-sans-serif, system-ui, sans-serif;
  --dah-z-index: 2147481000;
  --dah-accent: #2563eb;
  --dah-accent-strong: #1d4ed8;
  --dah-bg: #ffffff;
  --dah-surface: #f8fafc;
  --dah-border: #d9e2ec;
  --dah-text: #172033;
  --dah-muted: #64748b;
  --dah-shadow: 0 18px 50px rgba(15, 23, 42, 0.18);
  --dah-radius: 8px;
}

You can also override .dah-* classes directly for deeper styling.

npm Publishing Checklist

  1. Update version in package.json.
  2. Run npm run typecheck.
  3. Run npm run build.
  4. Preview the package with npm pack --dry-run.
  5. Publish with npm publish --access public.

The package includes dist, README.md, README_ZH.md, and LICENSE. The prepublishOnly script runs type checking and a production build before publishing.

License

MIT License. Copyright (c) ZhaiSoul.

About

No description, topics, or website provided.
456.00 KiB
0 forks0 stars1 branches8 TagREADMEMIT license
Language
TypeScript77.4%
CSS22.6%