logo
0
0
WeChat Login
fix: fix openai compatible

docs-ai-helper

面向 VuePress 和 VitePress 文档站的轻量级悬浮 AI 助手组件。

docs-ai-helper 会在文档站中提供一个聊天面板,支持流式回答、Markdown 渲染、Shiki 代码高亮、携带页面上下文、展示 reasoning、处理站内文档链接,并可通过 CSS 变量融入现有主题。

English README

特性

  • 通过 vue-demi 同时支持 Vue 2.7+ 和 Vue 3
  • 内置 VitePress / VuePress 路由跳转辅助函数
  • 支持普通文本流、JSON Lines、SSE 风格 data: 事件
  • 内置基于 markdown-it 和 Shiki 的 Markdown fallback 渲染器
  • 支持 reasoning 展示和用户侧开关
  • 支持推荐问题、欢迎状态、头像、名称和初始消息
  • 可自定义请求体、流解析器、尺寸、样式类和 CSS 变量
  • 支持固定悬浮按钮、内联按钮、工具栏样式和朴素样式
  • 聊天面板可拖拽调整大小,并内置亮色 / 暗色主题变量

安装

npm install docs-ai-helper vue-demi

如果没有传入自己的 renderMarkdown,组件的 fallback renderer 会动态加载 shiki

npm install shiki

Vue 2.7 以下项目还需要安装并注册 @vue/composition-api

快速使用

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
        }),
        assistant: { name: '文档助手' },
        welcome: {
          title: '需要我帮你查文档吗?',
          description: '可以问概念、配置、错误排查,或让 AI 带你跳到相关页面。'
        },
        suggestedQuestions: [
          { label: '如何快速开始?' },
          { label: '这个配置项怎么用?' },
          { label: '帮我总结当前页面' }
        ]
      })
    });
  }
};

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
        })
      });
    }
  });
};

后端协议

组件向 endpoint 发送 POST 请求,请求体遵循 OpenAI Chat Completions 规范:

{
  "context": {},
  "messages": [
    { "role": "user", "content": "用户问题" }
  ]
}

如果你的后端协议不同,可以通过 requestBody prop 自定义请求体(添加额外字段、改变结构等)。

默认解析器支持普通文本流和 SSE 风格数据:

data: {"content":"回答片段","reasoning":"思考片段"}
data: [DONE]

它也能解析常见 OpenAI 兼容格式中的 choices[0].delta.content。如果你的后端协议不同,可以传入 requestBodyparseStream

Markdown 与 Shiki

优先推荐传入文档站自己的 Markdown 渲染函数,这样代码高亮、主题和插件效果会与文档站保持一致:

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

如果没有传 renderMarkdown,组件会使用 markdown-it 解析 Markdown,并动态 import('shiki') 处理代码高亮:

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

h(DocsAiHelper, {
  endpoint: '/api/docs-chat',
  renderMarkdown: createShikiMarkdownRenderer({
    theme: { light: 'github-light', dark: 'github-dark' },
    fallbackLang: 'text'
  })
});
常用配置
h(DocsAiHelper, {
  endpoint: '/api/docs-chat',
  headers: { Authorization: 'Bearer ...' },
  assistant: { name: '文档助手', avatar: '/bot.png' },
  user: { name: '我', 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: '当前页面讲了什么?' },
    {
      label: '给一个 TypeScript 示例',
      question: '请基于当前页面给一个 TypeScript 示例'
    }
  ],
  welcome: {
    title: '你好,我是文档助手',
    description: '开始前可以直接选择一个推荐问题。'
  },
  context: () => ({
    path: location.pathname,
    title: document.title
  })
});
导出内容
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 变量
: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;
}

也可以直接覆盖 .dah-* 类名。

npm 发布清单

  1. 更新 package.json 中的 version
  2. 运行 npm run typecheck
  3. 运行 npm run build
  4. 使用 npm pack --dry-run 预览发布内容。
  5. 使用 npm publish --access public 发布。

当前包会发布 distREADME.mdREADME_ZH.mdLICENSEprepublishOnly 会在发布前自动执行类型检查和构建。

协议

MIT License. Copyright (c) ZhaiSoul.