npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ai-chat-sidebar

v1.0.17

Published

基于 Vue 3 的 AI 对话侧边栏组件,用于连接已部署的 LangGraph 服务

Readme

AI Chat Sidebar

基于 Vue 3 的 AI 对话侧边栏组件,用于连接已部署的 LangGraph 服务,可轻松集成到现有项目中。

注意: 这是一个纯前端组件,需要连接到已部署的 LangGraph 后端服务。

🏗️ 组件架构设计

本项目采用分层架构设计,实现了UI与业务逻辑的完全分离,提供了高度的可复用性和可维护性。

架构层级

┌─────────────────────────────────────────┐
│                UI 层                    │
├─────────────────────────────────────────┤
│  ChatBox.vue (纯UI组件)                 │
│  ChatSidebar.vue (侧边栏容器)           │
│  AIChat.vue (开箱即用组件)              │
├─────────────────────────────────────────┤
│              业务逻辑层                  │
├─────────────────────────────────────────┤
│  ChatService.ts (聊天服务)              │
│  useChat.ts (组合式函数)                │
├─────────────────────────────────────────┤
│               数据层                    │
├─────────────────────────────────────────┤
│  LangGraphService.ts (WebSocket服务)    │
│  remoteConfig.ts (配置管理)             │
└─────────────────────────────────────────┘

设计原则

  1. 职责分离

    • UI层:只负责界面展示,通过 props 和 events 通信
    • 业务逻辑层:封装聊天相关业务逻辑
    • 数据层:处理WebSocket连接和数据管理
  2. 高度可复用

    • ChatBox.vue:纯UI组件,可在任何地方使用
    • ChatService.ts:独立的服务类,可被多个组件使用
    • useChat.ts:组合式函数,提供响应式状态管理
  3. 灵活的使用方式

    • 开箱即用<AIChat /> 一行代码搞定
    • 自定义UI:使用 ChatBox + useChat
    • 完全自定义:直接使用 ChatService

✨ 特性

  • 🎨 现代化 UI - 基于 Element Plus 的美观界面
  • 📱 响应式设计 - 支持移动端和桌面端
  • 🔄 实时流式对话 - 支持 LangGraph 的流式响应
  • 🎛️ 高度可配置 - 丰富的配置选项
  • 📦 npm 包 - 可直接安装使用
  • 🔌 TypeScript 支持 - 完整的类型定义
  • 🎯 多实例支持 - 可在同一页面使用多个对话组件
  • 🎨 丰富组件支持 - 代码块、表格、图表、文档、文件预览等
  • 🔧 LangGraph 集成 - 连接已部署的 LangGraph 服务
  • 🌐 远程服务器支持 - 支持连接多个远程 LangGraph 服务
  • ⚙️ 服务器管理 - 可视化的服务器配置和管理界面

🏗️ 项目架构

你的项目 (前端组件)
    ↓ WebSocket/HTTP
已部署的 LangGraph 服务 (后端)

这是一个纯前端组件库,通过 WebSocket 连接到已部署的 LangGraph 服务。详细架构说明请查看 ARCHITECTURE.md

📦 安装

npm install ai-chat-sidebar

样式引入

安装后需要引入样式文件:

// 在 main.js 或 main.ts 中引入样式
import 'ai-chat-sidebar/dist/style.css'

或者在使用组件的文件中引入:

<style>
@import 'ai-chat-sidebar/dist/style.css';
</style>

🎮 在线演示

体验重新设计的聊天组件:

# 运行组件设计演示
npm run example:chat-component

演示包含:

  • 开箱即用组件
  • 组合式函数使用
  • 自定义UI组件
  • 服务层直接使用

🚀 使用方式

方式1: 开箱即用 (推荐)

最简单的使用方式,适合快速集成:

<template>
  <AIChat 
    :config="chatConfig"
    :trigger-size="60"
  />
</template>

<script setup>
import AIChat from 'ai-chat-sidebar'
import 'ai-chat-sidebar/dist/style.css'

const chatConfig = {
  title: '智能助手',
  placeholder: '请输入您的问题...',
  assistantName: 'AI',
  assistantAvatar: '@/assets/avatar.svg'  // 支持静态资源路径
}
</script>

重要说明:

  • 点击头像图标时会自动连接到测试服务器
  • 确保 Element Plus 已正确安装和配置
  • 样式文件必须引入才能正常显示
  • 导入时使用 import AIChat from 'ai-chat-sidebar',不要使用子路径导入
  • 如需连接到其他服务器,可通过 :default-server-id 属性指定
  • HTTPS 支持:在 HTTPS 页面中会自动使用 WSS 连接,HTTP 页面使用 WS 连接

高级配置示例

<template>
  <AIChat 
    :config="chatConfig"
    :default-server-id="'local'"
    :trigger-size="60"
  />
</template>

<script setup>
import AIChat from 'ai-chat-sidebar'
import 'ai-chat-sidebar/dist/style.css'

const chatConfig = {
  title: '智能助手',
  placeholder: '请输入您的问题...',
  assistantName: 'AI',
  assistantAvatar: '@/assets/avatar.svg',
  // 其他配置...
}
</script>

方式2: 使用组合式函数

适合需要更多控制权的场景:

<template>
  <ChatSidebar
    :messages="messages"
    :loading="loading"
    :is-connected="isConnected"
    :is-open="isOpen"
    :width="500"
    :theme="'light'"
    @send="sendMessage"
    @close="close"
  />
</template>

<script setup>
import { useChat } from 'ai-chat-sidebar/composables/useChat'
import ChatSidebar from 'ai-chat-sidebar/components/ChatSidebar.vue'

const {
  messages,
  loading,
  isConnected,
  isOpen,
  sendMessage,
  close,
  open
} = useChat({
  autoConnect: true,
  defaultServerId: 'test',
  config: {
    title: '我的AI助手',
    placeholder: '请输入您的问题...'
  }
})

// 打开聊天
const openChat = () => {
  open()
}
</script>

方式3: 自定义UI

适合需要完全自定义界面的场景:

<template>
  <div class="my-chat-container">
    <ChatBox
      :messages="messages"
      :config="chatConfig"
      :loading="loading"
      :is-connected="isConnected"
      :theme="'dark'"
      @send="sendMessage"
    />
  </div>
</template>

<script setup>
import { useChat } from 'ai-chat-sidebar/composables/useChat'
import ChatBox from 'ai-chat-sidebar/components/ChatBox.vue'

const { messages, loading, isConnected, sendMessage } = useChat({
  config: {
    title: '自定义聊天',
    assistantName: 'AI助手',
    showTimestamp: true
  }
})
</script>

<style>
.my-chat-container {
  width: 100%;
  height: 600px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}
</style>

方式4: 直接使用服务层

适合需要完全控制业务逻辑的场景:

<template>
  <div>
    <div v-for="message in messages" :key="message.id">
      {{ message.message }}
    </div>
    <input v-model="inputMessage" @keyup.enter="sendMessage" />
  </div>
</template>

<script setup>
import { ChatService } from 'ai-chat-sidebar/services/ChatService'
import { ref, onMounted } from 'vue'

const chatService = new ChatService({
  config: {
    title: '服务层聊天'
  }
})

const messages = chatService.messages
const loading = chatService.loading
const isConnected = chatService.isConnected
const inputMessage = ref('')

const sendMessage = async () => {
  if (inputMessage.value.trim()) {
    await chatService.sendMessage(inputMessage.value)
    inputMessage.value = ''
  }
}

onMounted(async () => {
  await chatService.connect('test')
})
</script>

🚀 快速开始

基础使用 (旧版API,向后兼容)

<template>
  <div>
    <button @click="openChat">打开 AI 助手</button>
    
    <AIChatSidebar
      :is-open="isChatOpen"
      :messages="messages"
      :loading="loading"
      :config="chatConfig"
      @open="handleOpen"
      @close="handleClose"
      @send="handleSend"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { AIChatSidebar } from 'ai-chat-sidebar'
import type { Message, ChatConfig } from 'ai-chat-sidebar'

const isChatOpen = ref(false)
const loading = ref(false)
const messages = ref<Message[]>([])

const chatConfig: ChatConfig = {
  title: 'AI 助手',
  placeholder: '请输入您的问题...',
  showTimestamp: true,
  assistantName: 'AI',
  assistantAvatar: 'https://example.com/ai-avatar.png',
  userAvatar: 'https://example.com/user-avatar.png'
}

const openChat = () => {
  isChatOpen.value = true
}

const handleOpen = () => {
  console.log('聊天窗口已打开')
}

const handleClose = () => {
  isChatOpen.value = false
}

const handleSend = async (message: string) => {
  // 添加用户消息
  messages.value.push({
    id: Date.now().toString(),
    content: message,
    type: 'user',
    timestamp: new Date(),
    status: 'sent'
  })
  
  // 模拟 AI 响应
  loading.value = true
  setTimeout(() => {
    messages.value.push({
      id: (Date.now() + 1).toString(),
      content: `我收到了您的消息:"${message}"`,
      type: 'assistant',
      timestamp: new Date(),
      status: 'sent'
    })
    loading.value = false
  }, 1000)
}
</script>

与 LangGraph 集成

<template>
  <div>
    <button @click="openChat">打开 AI 助手</button>
    
    <AIChatSidebar
      :is-open="isChatOpen"
      :messages="chatStore.messages"
      :loading="chatStore.loading"
      :config="chatConfig"
      @open="handleOpen"
      @close="handleClose"
      @send="handleSend"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { AIChatSidebar, useChatStore } from 'ai-chat-sidebar'
import type { ChatConfig, LangGraphConfig } from 'ai-chat-sidebar'

const isChatOpen = ref(false)
const chatStore = useChatStore()

const chatConfig: ChatConfig = {
  title: 'LangGraph AI 助手',
  placeholder: '请输入您的问题...',
  showTimestamp: true
}

// LangGraph 配置
const langGraphConfig: LangGraphConfig = {
  baseUrl: 'ws://localhost:8000/ws',
  apiKey: 'your-api-key',
  timeout: 30000
}

onMounted(async () => {
  // 连接到 LangGraph 服务
  await chatStore.connect()
})

const openChat = () => {
  isChatOpen.value = true
}

const handleOpen = () => {
  console.log('聊天窗口已打开')
}

const handleClose = () => {
  isChatOpen.value = false
}

const handleSend = async (message: string) => {
  // 使用 store 发送消息,会自动处理 LangGraph 通信
  await chatStore.sendMessage(message)
}
</script>

丰富组件支持

组件支持多种丰富的内容类型,包括代码块、表格、图表、文档等:

<template>
  <AIChatSidebar
    :is-open="true"
    :messages="messages"
    :config="chatConfig"
    @send="handleSend"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { AIChatSidebar } from 'ai-chat-sidebar'
import type { Message } from 'ai-chat-sidebar'

const messages = ref<Message[]>([
  // 代码块消息
  {
    id: '1',
    content: 'console.log("Hello World")',
    type: 'assistant',
    messageType: 'code',
    metadata: {
      language: 'javascript',
      fileName: 'example.js'
    },
    timestamp: new Date(),
    status: 'sent'
  },
  // 表格消息
  {
    id: '2',
    content: '这是销售数据表格:',
    type: 'assistant',
    messageType: 'table',
    metadata: {
      data: [
        { name: '产品A', sales: 1200, growth: '+15%' },
        { name: '产品B', sales: 980, growth: '+8%' }
      ],
      columns: [
        { prop: 'name', label: '产品名称', width: 120 },
        { prop: 'sales', label: '销售额', width: 100 },
        { prop: 'growth', label: '增长率', width: 100 }
      ]
    },
    timestamp: new Date(),
    status: 'sent'
  },
  // 图表消息
  {
    id: '3',
    content: '这是销售趋势图表:',
    type: 'assistant',
    messageType: 'chart',
    metadata: {
      chartType: 'line',
      chartData: {
        categories: ['1月', '2月', '3月'],
        values: [1200, 1350, 1100]
      }
    },
    timestamp: new Date(),
    status: 'sent'
  }
])

const handleSend = (message: string) => {
  // 处理消息发送
  console.log('发送消息:', message)
}
</script>

📚 API 文档

AIChatSidebar Props

| 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | isOpen | boolean | false | 是否显示侧边栏 | | messages | Message[] | [] | 消息列表 | | loading | boolean | false | 是否正在加载 | | disabled | boolean | false | 是否禁用输入 | | config | ChatConfig | {} | 聊天配置 | | position | 'left' \| 'right' | 'right' | 侧边栏位置 | | width | string \| number | '400px' | 侧边栏宽度 | | theme | 'light' \| 'dark' | 'light' | 主题 |

ChatConfig

| 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | title | string | 'AI 助手' | 聊天窗口标题 | | placeholder | string | '请输入消息...' | 输入框占位符 | | maxLength | number | 1000 | 最大输入长度 | | autoFocus | boolean | true | 是否自动聚焦 | | showTimestamp | boolean | false | 是否显示时间戳 | | assistantName | string | 'AI' | 助手名称 | | assistantAvatar | string | - | 助手头像 | | userAvatar | string | - | 用户头像 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | open | - | 侧边栏打开时触发 | | close | - | 侧边栏关闭时触发 | | send | message: string | 发送消息时触发 | | typing | isTyping: boolean | 输入状态变化时触发 | | minimize | minimized: boolean | 最小化状态变化时触发 |

Store API

const chatStore = useChatStore()

// 状态
chatStore.messages        // 消息列表
chatStore.loading         // 加载状态
chatStore.isConnected     // 连接状态
chatStore.error          // 错误信息

// 方法
await chatStore.sendMessage(message)     // 发送消息
await chatStore.connect()                // 连接服务
await chatStore.disconnect()             // 断开连接
chatStore.clearMessages()                // 清空消息
chatStore.retryLastMessage()             // 重试最后一条消息

🎨 自定义样式

组件支持通过 CSS 变量进行主题定制:

.ai-chat-sidebar {
  --sidebar-bg: #ffffff;
  --sidebar-border: #e4e7ed;
  --message-bg: #ffffff;
  --message-user-bg: #409eff;
  --message-text-color: #303133;
  --message-user-text-color: #ffffff;
  --input-bg: #ffffff;
  --input-border: #dcdfe6;
  --input-focus-border: #409eff;
}

🌐 远程服务器连接

服务器管理组件

<template>
  <div>
    <!-- 服务器管理 -->
    <ServerManager />
    
    <!-- 聊天组件 -->
    <AIChatSidebar 
      :visible="showChat"
      @close="showChat = false"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { AIChatSidebar, ServerManager } from 'ai-chat-sidebar'
import 'ai-chat-sidebar/dist/style.css'

const showChat = ref(false)
</script>

编程式管理

import { remoteConfigManager, langGraphService } from 'ai-chat-sidebar'

// 添加远程服务器
remoteConfigManager.addServer('production', {
  name: '生产服务器',
  host: 'api.example.com',
  port: 443,
  protocol: 'wss',
  path: '/langgraph/ws',
  apiKey: 'your-api-key',
  timeout: 180000,
  retryAttempts: 3,
  description: '生产环境的 LangGraph 服务'
})

// 切换到远程服务器
await langGraphService.switchServer('production')

// 检查连接状态
const status = await langGraphService.checkServerStatus()
console.log('连接状态:', status)

服务器配置选项

interface RemoteServerConfig {
  name: string              // 服务器名称
  host: string              // 主机地址
  port: number              // 端口号
  protocol: 'ws' | 'wss'    // 协议类型
  path?: string             // WebSocket 路径
  apiKey?: string           // API 密钥
  timeout?: number          // 超时时间(ms)
  retryAttempts?: number    // 重试次数
  description?: string      // 服务器描述
}

演示页面

运行示例项目:

npm run example

这个演示页面展示如何:

  • 配置你的 LangGraph 服务连接
  • 连接到已部署的服务
  • 测试连接状态
  • 开始聊天对话
  • 管理多个服务器配置

🔧 开发

# 安装依赖
npm install

# 开发模式
npm run dev

# 运行示例
npm run example

# 构建
npm run build

# 类型检查
npm run type-check

# 代码检查
npm run lint

📚 组件API参考

AIChat 组件

开箱即用的聊天组件,提供完整的聊天功能。

Props

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | autoConnect | boolean | false | 是否自动连接 | | defaultServerId | string | - | 默认服务器ID | | triggerText | string | '开始对话' | 触发器文本 | | triggerType | string | 'primary' | 触发器类型 | | triggerSize | string | 'default' | 触发器大小 | | position | 'left' \| 'right' | 'right' | 侧边栏位置 | | width | string \| number | '400px' | 侧边栏宽度 | | theme | 'light' \| 'dark' | 'light' | 主题 | | config | ChatConfig | {} | 聊天配置 |

Events

| 事件 | 参数 | 说明 | |------|------|------| | send | message: string | 发送消息 | | open | - | 打开聊天 | | close | - | 关闭聊天 | | minimize | minimized: boolean | 最小化状态变化 | | focus | - | 输入框聚焦 | | blur | - | 输入框失焦 | | connect | serverId: string | 连接服务器 | | disconnect | - | 断开连接 | | error | error: string | 错误事件 |

ChatBox 组件

纯UI聊天框组件,需要外部管理状态。

Props

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | messages | Message[] | [] | 消息列表 | | config | ChatConfig | {} | 聊天配置 | | loading | boolean | false | 加载状态 | | disabled | boolean | false | 禁用状态 | | minimized | boolean | false | 最小化状态 | | showMinimize | boolean | true | 显示最小化按钮 | | showClose | boolean | true | 显示关闭按钮 | | theme | 'light' \| 'dark' | 'light' | 主题 | | isConnected | boolean | false | 连接状态 |

Events

| 事件 | 参数 | 说明 | |------|------|------| | send | message: string | 发送消息 | | minimize | minimized: boolean | 最小化状态变化 | | close | - | 关闭聊天 | | focus | - | 输入框聚焦 | | blur | - | 输入框失焦 |

useChat 组合式函数

提供响应式聊天状态管理的组合式函数。

参数

interface UseChatOptions {
  autoConnect?: boolean
  defaultServerId?: string
  showConnectionStatus?: boolean
  config?: ChatConfig
  serverId?: string
}

返回值

| 属性 | 类型 | 说明 | |------|------|------| | isOpen | Ref<boolean> | 是否打开 | | minimized | Ref<boolean> | 是否最小化 | | messages | ComputedRef<Message[]> | 消息列表 | | loading | ComputedRef<boolean> | 加载状态 | | isConnected | ComputedRef<boolean> | 连接状态 | | error | ComputedRef<string \| null> | 错误信息 | | config | ComputedRef<ChatConfig> | 聊天配置 | | open | () => void | 打开聊天 | | close | () => void | 关闭聊天 | | minimize | (value?: boolean) => void | 最小化 | | connect | (serverId?: string) => Promise<void> | 连接服务器 | | disconnect | () => Promise<void> | 断开连接 | | switchServer | (serverId: string) => Promise<void> | 切换服务器 | | sendMessage | (message: string) => Promise<void> | 发送消息 | | clearMessages | () => void | 清空消息 | | retryLastMessage | () => void | 重试最后一条消息 | | updateConfig | (config: Partial<ChatConfig>) => void | 更新配置 |

ChatService 服务类

独立的聊天服务类,提供完整的聊天业务逻辑。

构造函数

new ChatService(options?: ChatServiceOptions)

主要方法

| 方法 | 参数 | 返回值 | 说明 | |------|------|--------|------| | connect | serverId?: string | Promise<void> | 连接服务器 | | disconnect | - | Promise<void> | 断开连接 | | switchServer | serverId: string | Promise<void> | 切换服务器 | | sendMessage | message: string | Promise<void> | 发送消息 | | addMessage | message: Omit<Message, 'id' \| 'timestamp'> | Message | 添加消息 | | updateMessage | id: string, updates: Partial<Message> | void | 更新消息 | | removeMessage | id: string | void | 移除消息 | | clearMessages | - | void | 清空消息 | | retryLastMessage | - | void | 重试最后一条消息 | | updateConfig | config: Partial<ChatConfig> | void | 更新配置 | | destroy | - | void | 销毁服务 |

🎯 最佳实践

1. 选择合适的组件

  • AIChat: 适合快速集成,需要完整聊天功能
  • ChatSidebar + useChat: 适合需要自定义布局的场景
  • ChatBox + useChat: 适合需要完全自定义UI的场景
  • ChatService: 适合需要完全控制业务逻辑的场景

2. 状态管理

  • 使用 useChat 组合式函数管理状态
  • 避免直接操作 ChatService 实例
  • 通过事件监听器处理状态变化

3. 性能优化

  • 使用 v-memo 优化消息列表渲染
  • 合理使用防抖更新避免频繁重渲染
  • 及时清理不需要的监听器

4. 错误处理

  • 监听 error 事件处理错误
  • 提供用户友好的错误提示
  • 实现重试机制

5. 主题定制

  • 使用 CSS 变量自定义主题
  • 支持深色/浅色模式切换
  • 保持与项目整体风格一致

📄 许可证

MIT License

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📞 支持

如有问题,请通过以下方式联系: