@lzy6755/ai-chat-opencode

Vue 2 AI chat panel (OpenCode SSE)
1,438
Install
npm install @lzy6755/ai-chat-opencode
Latest Version:0.1.6
Vue:2
License:Proprietary
Last Updated:May 11, 2026
Links: Repository  ·  npm
Maintainer: lzy6755

ai-chat-opencode

Vue 2 单文件组件:OpenCode 对话面板(源码包,由宿主 webpack 编译)。

安装

npm install @lzy6755/ai-chat-opencode --save

使用

方案1 直接导入组件

用户直接导入AiChatPanel组件,并传入配置参数即可使用。

参数列表
参数名 类型 默认值 是否必填 说明
visible Boolean false 是 控制面板显示/隐藏,通常配合 :visible.sync 使用
opencodeUrl String https://opencodedev.pyamc.com 是 OpenCode 服务地址
opencodeDirectory String /work/crm-agent 是 服务端会话目录参数
opencodeSystem String '' 是 传给opencode进行身份校验的信息
source String crm 是 传入系统名称作为本地存储 key 的来源隔离标识
userId String '' 是 用于区分用户会话存储;不传会影响会话列表按用户隔离
opencodeAgent String build 否 使用的 agent
opencodeModelID String GLM-5 否 模型 ID
opencodeProviderID String jdprovider 否 模型提供商 ID
title String 智能助手 否 顶部主标题
subtitle String 随时提问,一键生成建议 否 顶部副标题
placeholder String 请输入你想让 AI 帮你处理的问题... 否 输入框占位文案
initialMessages Array [] 否 初始消息列表
toast Function undefined 否 自定义轻提示函数
confirm Function undefined 否 自定义确认框函数,返回 Promise<boolean>
maxSessionCount Number 10 否 本地最多保留会话数
示例
<template>
  <AiChatPanel
    :visible.sync="show"
    title="智能助手"
    subtitle="随时提问,一键生成建议"
    placeholder="请输入你想让 AI 帮你处理的问题..."
    :initial-messages="initialMessages"
    :opencode-url="opencodeUrl"
    opencode-directory="/work/crm-agent"
    :opencode-system="opencodeSystem"
    opencode-agent="build"
    opencode-model-i-d="GLM-5"
    opencode-provider-i-d="jdprovider"
    :toast="customToast"
    :confirm="customConfirm"
    source="crm"
    :user-id="userId"
    :max-session-count="10"
  />
</template>

<script>
import { AiChatPanel } from '@lzy6755/ai-chat-opencode'

export default {
  components: { AiChatPanel },
  data () {
    return {
      show: false,
      userId: 'u_10001',
      opencodeUrl: 'https://opencodedev.pyamc.com',
      opencodeSystem: `{
        "PY-CRM-TOKEN":"LOGIN_TOKEN_e71ef7c7-b982-40e5-85e1-8d34039256c1",
        "PY-CRM-DEVICE":"string"
      }`,
      initialMessages: [
        { role: 'assistant', content: '你好,我可以帮你生成跟进话术和工单建议。' }
      ]
    }
  },
  methods: {
    customToast ({ message, position = 'bottom' }) {
      // 可接你们自己的 UI 提示组件
      console.log('[toast]', position, message)
    },
    customConfirm ({ message, title }) {
      // 需要返回 Promise<boolean>
      return Promise.resolve(window.confirm(`${title ? `${title}\n` : ''}${message}`))
    }
  }
}
</script>

方案2 Headless 模式(v2):自建 UI

包内提供 **createAiChatController**:由本包维护会话列表、消息、流式状态与 OpenCode SSE;宿主只负责用自有组件渲染 ctrl 上的响应式数据并调用方法。

环境要求
  • Vue 2.5+。
引入
import { createAiChatController } from '@lzy6755/ai-chat-opencode'
最小示例
export default {
  data () {
    return {
      input: '',
      chat: createAiChatController({
        opencodeUrl: 'https://opencodedev.pyamc.com',
        opencodeDirectory: '/work/crm-agent',
        opencodeSystem: '',
        source: 'crm',
        userId: 'u_10001',
        confirm: async ({ message, title }) =>
          window.confirm(`${title ? title + '\n' : ''}${message}`)
      })
    }
  },
  async mounted () {
    await this.chat.init()
  },
  beforeDestroy () {
    this.chat.dispose()
  },
  methods: {
    async onSend () {
      const text = this.input.trim()
      if (!text) return
      try {
        await this.chat.sendMessage(text)
        this.input = ''
      } catch (e) {
        // 空消息、正在生成、建会话失败、prompt 请求失败等
      }
    }
  }
}

模板中把 chat 当作根状态对象绑定即可,例如:

<ul>
  <li v-for="s in chat.sessionList" :key="s.id" @click="chat.selectSession(s.id)">
    {{ chat.getSessionTitle(s) }}
    <span v-if="chat.isSessionGenerating(s.id)">生成中</span>
  </li>
</ul>
<div v-for="(m, i) in chat.messages" :key="i">
  <template v-if="m.role === 'assistant'">
    <div v-if="m.reasoning" v-html="chat.renderMarkdownHtml(m.reasoning)" />
    <div v-html="chat.renderMarkdownHtml(m.content)" />
  </template>
  <template v-else>{{ m.content }}</template>
</div>
<button type="button" :disabled="chat.isCurrentSessionLoading" @click="onSend">发送</button>
<button type="button" @click="chat.abort">停止</button>
<button type="button" @click="chat.startNewDraft">新草稿</button>

renderMarkdownHtml(text) 使用与本包面板一致的 Markdown 规则生成 HTML;若使用 v-html,请自行评估 XSS 风险(与自带组件相同策略:markdown-it,html: false)。

生命周期

调用时机 方法 说明
页面/模块挂载后 await chat.init() 创建 HTTP 客户端、启动全局 SSE、进入本地「空草稿」视图并刷新会话列表
页面卸载前 chat.dispose() 中止 SSE、清空内部 client,避免泄漏;再次使用可再调用 init()

工厂选项 createAiChatController(options)

与组件 props 对齐的字段如下(不传则用默认值)。

选项 类型 默认值 说明
opencodeUrl String https://opencodedev.pyamc.com OpenCode 服务根地址
opencodeDirectory String /work/crm-agent 服务端 directory 参数
opencodeSystem String '' 鉴权信息
opencodeAgent String build prompt 所用 agent
opencodeModelID String GLM-5 模型 ID
opencodeProviderID String jdprovider 提供商 ID
source String crm 本地存储命名空间(与会话列表、lastActive 隔离相关)
userId String '' 必填建议填写;会话列表按用户维度存 localStorage
maxSessionCount Number 10 本地会话列表上限
initialMessages Array [] 无远程会话或拉取历史为空时使用的初始消息快照
toast Function undefined ({ message, position?, ... }) => void,部分错误会调用
confirm Function undefined ({ message, title }) => Promise<boolean>,deleteSession 前确认
onSessionIdle Function undefined 收到 session.idle 后调用 ({ sessionId })
onError Function undefined 创建会话失败、流式失败、init 异常等
onTitleSynced Function undefined 首条消息后从服务端同步标题成功:({ sessionId, title })

对外状态(建议在模板中绑定,只读)

字段 说明
sessionList { id, title }[],侧栏列表
activeSessionId 当前查看的会话 id;仅本地草稿时为 null
messages 当前会话消息:role、content、reasoning(纯文本)、messageId、timestamp
isCurrentSessionLoading 当前会话是否在生成
hasCurrentSessionReplyContent 当前轮是否已有可见流式内容(区分「仅有 loading 点」与「已出字」)
activeGenerationBySession { [sessionId]: boolean },各会话是否仍在生成(含切走后该会话在后台仍返回时);可只读绑定侧栏「生成中」等角标;由 SSE 与包内逻辑维护,只读
hasReplyContentBySession { [sessionId]: boolean },各会话当前轮是否已出现可见流式正文或思考;可只读绑定「已出字」等角标;只读
streamPartTypesBySession { [sessionId]: { [partId]: 类型 } },非当前会话的 part 类型缓存,供后台 SSE 过滤 text/reasoning 与「已出字」判断配套;只读

切换会话、删除会话等请使用下方对外方法, 不要通过改写上述字段或 messages 代替流程。

内部流式中间状态: 同一 ctrl 对象上还有 streamPartIdTypes、assistantPartTextMap 等,由 SSE 驱动;不要在业务里手动赋值,否则易与流式不同步。

对外方法

方法 说明
init() 初始化客户端与 SSE,并进入空入口视图
dispose() 释放 SSE 与 client
sendMessage(text) 或 sendMessage({ text, system?, agent?, model? }) 发送消息;必要时会先创建远程会话;返回 Promise,校验失败或请求失败会 reject(并在内部更新消息/状态)
abort() 停止当前会话生成(对齐服务端 abort)
selectSession(id) / switchSession(id) 同一实现:切换会话并拉取历史
deleteSession(id) 先走 confirm,再删远程与本地列表;若删的是当前会话则自动切换或空白视图
startNewDraft() 等同组件侧栏「新建」:仅本地新草稿,清除 lastActive;首个远程 session 在第一次成功 sendMessage 时创建
refreshSessionList() 仅从 localStorage 刷新 sessionList
reloadMessages() 为当前 activeSessionId 重新请求历史
getSessionTitle(session) 展示用标题,缺省为「未命名会话」
isSessionGenerating(sessionId?) 是否正在生成;省略参数时看当前会话
renderMarkdownHtml(text) 将任意 Markdown 字符串转为 HTML(如正文 m.content、思考 m.reasoning)

Related Packages

@baoyog/agent-vue2

宝遥智能体 Vue2 通用插件 - 支持标准化表单助手且无第三方 UI 框架依赖

0
@huyooo/ai-chat-frontend-vue

AI Chat Frontend - Vue components with adapter pattern

12,303
punine-design

一个基于 Vue 3 的 AI 聊天插件,通过Langchain.js、DeepSeek API Key快速构建自定义...

3,987
ai-assistant-plugin

Vue2 AI 助手浮层插件:无 Element UI 依赖,支持主动唤起、多轮对话、部门数据透传

1,125
tax-ai

AI assistant component library for Vue 3

4,109

Version History

Version Released Vue License
0.1.6 ^2.5.0 Proprietary
0.1.5 ^2.5.0 Proprietary
0.1.4 ^2.5.0 Proprietary
0.1.3 ^2.5.0 Proprietary
0.1.2 ^2.5.0 Proprietary