agent-tool-chat
v1.1.6
Published
An agent-driven chat plugin with ToolPackage architecture and host-controlled execution
Readme
agent-tool-chat
基于 ToolPackage 架构的 AI 对话插件,工具由宿主控制执行。基于 Vue 3 + Element Plus。
版本: 1.0.1
安装
npm install agent-tool-chat需要同级依赖 vue (^3.4) 和 element-plus (^2.0)。
npm install vue@^3.4 element-plus@^2.0快速开始
<script setup>
import { useAgentChat, ChatPanel } from 'agent-tool-chat'
import 'agent-tool-chat/dist/style.css'
const chat = useAgentChat({
toolPackages: [myToolPackage],
onToolCall: async (call) => {
// 宿主执行工具并返回结果
return { success: true, data: { /* ... */ } }
},
suggestedCommands: [
// 可选:空状态快捷命令,点击即发送 text 指令
{ label: '查询订单', text: '查询今天的所有订单' },
{ label: '使用帮助', text: '你能做什么?介绍一下你的能力' },
],
})
</script>
<template>
<ChatPanel :chat="chat" />
</template>免 chat 使用(开箱即用)
ChatPanel 的 chat 属性可选。不传时组件内部自建聊天实例,仅启用内置工具(也可通过 options 传入 AgentChatOptions 配置):
<template>
<!-- 仅内置工具 -->
<ChatPanel />
<!-- 带 options 配置(如 provider、suggestedCommands 等) -->
<ChatPanel :options="{ suggestedCommands: [{ label: '现在几点', text: '现在几点?' }] }" />
</template>注意:未传入宿主
onToolCall时,仅内置工具(get_current_time等)可执行,宿主自定义工具需通过options.toolPackages传入。
默认快捷命令
不传 chat 且 options 未配置 suggestedCommands 时,空状态面板自动展示与内置工具对应的默认可点击命令(点击即发送对应指令):
| 命令 | 指令 | 对应内置工具 |
|---|---|---|
| 现在几点 | 现在几点了? | get_current_time |
| 帮我计算 | 帮我计算 (1+2)*3 | calculate_expression |
| 生成 UUID | 帮我生成一个 UUID | generate_uuid |
| 客户端信息 | 获取我的客户端信息 | get_client_info |
规则:
options.suggestedCommands已传(含空数组)→ 以宿主配置为准builtInTools: false→ 不展示默认命令builtInTools为名称数组 → 只展示数组内启用工具对应的命令
内置工具
插件默认启用一组开箱即用的通用工具(BUILTIN_TOOL_PACKAGE),不依赖宿主 onToolCall:
| 工具 | 说明 |
|---|---|
| get_current_time | 获取当前时间、日期、时区与星期 |
| calculate_expression | 安全计算数学表达式(支持 + - * / % 和括号,白名单解析不用 eval) |
| generate_uuid | 生成 UUID v4 |
| get_client_info | 浏览器基本信息(UA、平台、语言、屏幕尺寸) |
通过 useAgentChat 的 builtInTools 配置:
useAgentChat({
toolPackages: [...],
builtInTools: true, // 默认:全部启用
// builtInTools: ['get_current_time', 'calculate_expression'], // 按需启用
// builtInTools: false, // 关闭
})宿主如在 toolPackages 中注册同名的工具,将覆盖内置工具的定义与执行。
自定义 systemPrompt 时内置工具仍可见
宿主通过 useAgentChat 传入自定义 systemPrompt 时,插件会在其末尾自动追加一段内置工具描述(复用 buildSystemPrompt 的包段格式,如 【内置工具】... + 工具列表),因此 LLM 询问"你能做什么"时也会列举开箱即用的内置工具。内置工具关闭(builtInTools: false 或过滤后为空)时不追加。
此外,无论是否自定义 systemPrompt、是否开启内置工具,插件都会在提示词末尾追加"重复指令处理规则":用户再次发送相同或类似指令(即使之前已执行过)时,LLM 必须重新调用对应工具再次执行,不得以"已经执行过"等理由拒绝,也不能用历史结果代替重新执行。
核心概念
ToolPackage(工具包)
由宿主注册,包含工具定义(ToolDefinition)和可选的 Vue 渲染组件:
import type { ToolPackage } from 'agent-tool-chat'
const myToolPackage: ToolPackage = {
id: 'demo',
name: '演示工具',
description: '演示用途',
components: { /* 可选:自定义渲染组件,按 componentName 查找 */ },
tools: [
{
name: 'query_order',
description: '按订单号查询订单信息',
parameters: { type: 'object', properties: { id: { type: 'string' } } },
displayHints: {
resultFormat: 'table',
previewFields: ['id', 'name', 'amount'], // 表格列字段(空/缺省 → 全量)
summaryTemplate: '查询到订单 {id}', // {占位符} 从工具 args 插值
selectable: true, // 允许行选择(出现"选择"操作列)
labelField: 'name', // 选中后"我选择 X"取值字段(缺省 → previewFields[0])
suggestedNext: '下一步可以查看该订单明细', // 快捷建议
},
},
],
}displayHints 完整字段:
| 字段 | 作用 |
|---|---|
| suggestComponent | 建议使用组件名(ToolPackage.components 中注册)渲染 |
| resultFormat | table / card / list / text / map,无组件时按此降级渲染 |
| previewFields | 表格列字段(→ RenderBlock.fields),空数组/缺省时全量显示 |
| summaryTemplate | 渲染块标题模板,{key} 从工具 args 插值 |
| selectable | 表格是否显示"选择"操作列(多行时) |
| labelField | 选中文案取值字段,缺省取第一个配置字段 |
| suggestedNext | 后续建议文本 |
| suggestedNextEvent | 延迟建议:等待该业务事件到达后再显示 |
表格行选择
当工具结果渲染为表格且 selectable: true 时,多行结果每行出现"选择"按钮,点击后向对话发送:
我选择 {labelField 对应的值}随后 LLM 可据此继续流程(例如"以黄壁庄水库为出口创建方案"的多候选出口站选择)。
业务事件(Business Events)
宿主通过 EventBus 把业务状态回灌给插件,EventEngine 按规则触发对话:
import { useAgentChat } from 'agent-tool-chat'
const chat = useAgentChat({
toolPackages: [myToolPackage],
onToolCall: async (call) => { /* ... */ },
businessEvents: {
rules: [
{
event: 'scheme:feedback:success',
action: 'suggest', // respond / suggest / notify / silent
prompt: '操作成功', // action=suggest 时发送给 LLM 的消息
autoPopup: true, // 事件到达时自动打开聊天面板
cooldown: 10000, // 冷却时间 ms
},
],
},
})
// 宿主在页面操作完成后派发事件
chat.eventBus.dispatch({ type: 'scheme:feedback:success', timestamp: Date.now(), payload: {} }, true)dispatch(event, checkChatOpen)— 第二个参数为true时,若聊天面板未打开则事件被丢弃action: 'suggest'→ 调用sendMessage(prompt),把该消息作为用户消息发送并触发 LLM 回复- 与
displayHints.suggestedNextEvent结合可实现:工具打开页面 → 用户操作完成派发事件 → 聊天窗口出现"操作成功"并显示下一步建议
文件上传
- 文件通过
ChatInput选择,以fileId间接引用存入fileStore - 默认
sendFileToLLM: false,LLM 只能看到文件名/类型,看不到文件内容 - 工具通过
fileId从fileStore取回数据(如open_mapview_file展示空间数据)
FileAttachment 与 Blob
FileAttachment 新增可选字段 blob?: Blob,保存原始文件的 Blob 引用(所有文件都会存,File 本身即是 Blob,零额外内存开销):
interface FileAttachment {
id: string
name: string
size: number
type: string
data: string // 文本=原始内容;二进制=base64 data URL
blob?: Blob // 原始文件 Blob 引用(仅运行时有效)
}.tif/.tiff优化:不生成 base64data(data为空字符串),仅保留blob引用,避免大栅格文件的内存开销- 持久化限制:Blob 无法被
JSON.stringify(会变成{})。同会话内f.blob完好;刷新/换端后需回退data - 获取 Blob:使用
blobFromAttachment(f)工具——优先返回f.blob,否则把 base64data转成 Blob(覆盖刷新场景),两者都无则返回null:import { blobFromAttachment, isTifFile } from 'agent-tool-chat' const blob = blobFromAttachment(file) // Blob | null if (blob) await blob.arrayBuffer() // 如 geotiff.js 解析 - 消费方约定:拿到
.tif文件对象后优先用blobFromAttachment(f);返回null说明刷新后数据丢失,提示用户重新上传
Markdown 渲染
- AI 回复按 Markdown 渲染(
markdown-it实现,经DOMPurify清洗,禁用原始 HTML) - 支持标题、列表、代码块、表格、引用、链接、分割线等,样式跟随 Element Plus 主题变量
使用说明
- 定义工具包 — 创建
ToolPackage,包含工具定义(displayHints)和可选渲染组件。 - 创建
useAgentChat— 传入工具包、宿主onToolCall回调,可选businessEvents、systemPrompt、provider、suggestedCommands。 - 渲染
ChatPanel— 将返回的AgentChatAPI绑定到chatprop;也可不传chat,仅传可选options(或不传,直接开箱即用内置工具)。 - 文件上传 —
ChatInput支持文件选择,工具通过fileId引用。 - 业务联动 — 页面操作完成后
eventBus.dispatch回灌,驱动 LLM 回复或延迟建议。 - 持久化 — 消息与设置自动保存(direct 模式 localStorage;proxy 模式 POST
/api/messages,按 device_id 区分)。
数据持久化
| providerMode | 消息存储 | 说明 |
|---|---|---|
| direct | localStorage | 键 {storagePrefix}messages |
| proxy | 服务端 /api/messages | 按 device_id 标识,防抖 400ms 批量提交 |
API 概览
useAgentChat(options) // 核心组合式函数,返回 AgentChatAPI
ChatPanel // 对话面板(chat / options prop,chat 可选)
buildSystemPrompt(packages) // 构建系统提示词
createDeepSeekProvider() // 直连 DeepSeek LLM 提供者
createProxyProvider() // 代理模式 LLM 提供者
createEventBus() // 创建独立 EventBus
Agent, ToolRegistry // 底层 Agent 多轮循环器 / 工具注册表详细文档
- DESIGN.md — 完整架构设计(事件系统、渲染流程、SuggestedNext 延迟显示逻辑等)
- 宿主集成示例参考仓库
src/agent-chat-demo/(含bridge/页面联动、modules/工具包与业务事件)
