@baoyog/agent-vue2
| Install | |
|---|---|
npm install @baoyog/agent-vue2 |
|
| Latest Version: | 1.6.1 |
| Vue: | 2 |
| License: | MIT |
| Last Updated: | Aug 21, 2026 |
| Links: | npm |
宝遥智能体 Vue2 插件 (@baoyog/agent-vue2)
可嵌入任意 Vue2 系统的智能体对话组件,支持 SSE 流式通信、工具调用展示、Markdown 渲染。组件使用原生 HTML、内置 SVG 图标和隔离样式,不依赖 Element UI、Ant Design Vue 或其他第三方 UI 框架。
从 1.2.0 开始提供 AiFormAssistant 和 createFormAdapter,用于把表单快照、字段白名单、类型转换、最终确认和补丁回填标准化。1.3.0 起内置统一智能体客户端,支持一致的认证、会话、SSE、停止生成和标准错误信息。
鉴权、会话、AG-UI SSE、停止生成和标准错误统一使用 @baoyog/agent-core。业务系统推荐通过 getAccessToken 从自己的服务端取得短期 Token,禁止在浏览器中配置 Client Secret。
getAccessToken: function (context) {
return businessApi.getAiToken({ force: context.force }).then(function (res) { return res.token })
}
安装
npm install @baoyog/agent-vue2
只有
vue是 peerDependency。Vue 2.6、Vue 2.7 项目均可使用。
使用
标准表单助手(推荐)
<template>
<AiFormAssistant
scene-code="purchase.order"
biz-type="采购订单"
title="采购单填报助手"
:base-url="agent.baseUrl"
:chat-key="agent.chatKey"
:agent-id="agent.agentId"
:agent-code="agent.agentCode"
:record-id="orderId"
:adapter="formAdapter"
:context-params="{ token, tenantId, userId }"
@save-request="handleSave"
/>
</template>
<script>
import { AiFormAssistant, createFormAdapter, formConverters } from '@baoyog/agent-vue2'
import '@baoyog/agent-vue2/dist/style.css'
export default {
components: { AiFormAssistant },
computed: {
formAdapter() {
return createFormAdapter({
getValues: () => this.form,
setValue: (key, value) => this.$set(this.form, key, value),
fields: {
name: { label: '订单名称' },
amount: {
label: '订单金额',
fromForm: formConverters.minorToMajor,
toForm: formConverters.majorToMinor,
},
signDate: { label: '签订日期', fromForm: formConverters.date },
},
})
},
},
}
</script>
一轮对话中多次调用 propose_form_patch 时,AgentChat 只在运行结束后输出最后一份补丁;AiFormAssistant 再统一展示一次确认。只有用户点击“应用到表单”后才调用适配器,save-request 也只表示保存意图,最终仍由宿主系统执行原有校验和保存方法。
约定式通用适配器
多个业务页面接入时,推荐使用 createConventionFormAdapter。页面只声明子组件、字段来源、转换预设、选择器配对和表格方法名,不再重复实现 getValues、setValue、金额转换及组件定位。
import { createConventionFormAdapter } from '@baoyog/agent-vue2'
createConventionFormAdapter({
page: this,
defaultSection: 'info',
sections: {
info: { ref: 'OrderInfo', model: 'formItem' },
detail: { ref: 'OrderDetail', model: 'formItem' },
},
fields: {
name: { label: '订单名称', required: true },
amount: { label: '订单金额', converter: 'money' },
customerId: {
label: '客户 ID',
pair: { labelKey: 'customerName', method: 'setAgentCustomer' },
},
customerName: { label: '客户名称', writable: false },
},
tables: {
detailList: {
section: 'detail',
source: 'detailList',
label: '订单明细',
component: 'table',
rowKey: 'agentRowId',
ensureMethod: 'ensureAgentRowIds',
addMethod: 'addAgentRow',
setCellMethod: 'setAgentCell',
removeMethod: 'removeAgentRow',
columns: {
productName: { label: '产品', required: true },
price: { label: '单价', converter: 'money' },
quantity: { label: '数量', converter: 'number' },
},
},
},
actions: {
openCustomerSelector: {
label: '打开客户选择器',
section: 'info',
ref: 'customerSelect',
method: 'handleCcClick',
args: [],
},
},
validateForm: () => this.validatePage(),
})
内置转换预设包括 money、percent、number、date、stringArray。pair 用于统一处理 ID 与显示名称;表格列同样支持转换预设。无法通用化的联动计算继续放在宿主组件方法或 afterApply 钩子中。
动态表单与字段联动
字段存在依赖关系时,通过 dependsOn 声明顺序,并用 isReady 或 waitFor 告诉运行时下游字段何时完成加载。确认回填后,组件会逐字段执行:先设置上游字段,触发宿主页面原有 change 逻辑,等待下游选项就绪,再校验并设置下游字段。
formAdapter() {
return createFormAdapter({
getValues: () => this.form,
setValue: async (key, value) => {
this.$set(this.form, key, value)
if (key === 'categoryId') await this.loadProducts(value)
},
fields: {
categoryId: {
label: '产品分类',
component: 'select',
valueType: 'string',
required: true,
options: this.categoryOptions,
},
productId: {
label: '产品',
component: 'select',
valueType: 'string',
required: true,
dependsOn: ['categoryId'],
optionsSource: { type: 'api', trigger: 'categoryId' },
getOptions: () => this.productOptions,
isReady: () => !this.productLoading,
validate: (value) => this.productOptions.some((item) => item.value === value)
|| '所选产品不属于当前分类',
},
},
})
}
动态适配器同时提供:
getSchema():返回可序列化字段结构、依赖和选项来源。getState():返回字段当前值、显隐、禁用和加载状态。getOptions(field):读取字段最新选项。waitForField(field):等待异步联动完成。setField(field, value):通过宿主页面赋值逻辑修改单字段。executePatch(values):按依赖顺序执行整份补丁。
AiFormAssistant 会把 formSchema、formState 和 currentFormData 放入每次对话的上下文。旧版只实现基础 getSnapshot/applyPatch 的适配器仍然兼容。
动态明细表格
数组字段声明为 component: 'table' 后,运行时可以按行标识更新已有行、添加新行,并处理行内字段联动:
productLines: {
label: '产品明细',
component: 'table',
rowKey: 'id',
// 默认 false:补丁中未出现的已有行不会被删除。
replaceRows: false,
getRows: () => this.form.productLines,
addRow: row => this.addProductRow(row), // 返回新行对象或行 ID
updateRow: (rowId, patch) => this.updateProductRow(rowId, patch),
removeRow: rowId => this.removeProductRow(rowId),
setCell: (rowId, column, value) => this.setProductCell(rowId, column, value),
waitForCell: (rowId, column) => this.waitProductCellReady(rowId, column),
columns: {
categoryId: { label: '分类', component: 'select' },
productId: {
label: '产品',
component: 'select',
dependsOn: ['categoryId'],
toForm: (value, context) => this.resolveProductId(context.rowKey, value),
validate: (value, context) => this.isValidProduct(context.rowKey, value)
|| '产品不属于当前分类',
},
quantity: { label: '数量', valueType: 'number', required: true },
unitPrice: { label: '单价', valueType: 'number', required: true },
},
}
对应补丁仍使用普通数组,便于智能体生成和用户确认:
{
"productLines": [
{ "id": "LINE-1", "quantity": 10 },
{ "categoryId": "CAT-1", "productId": "产品一", "quantity": 2, "unitPrice": 100 }
]
}
运行规则:
- 包含行 ID:更新该行中补丁明确给出的单元格。
- 不包含行 ID:调用
addRow创建新行,宿主必须返回新行对象或行 ID。 - 行内字段根据
columns.*.dependsOn排序并等待联动。 replaceRows默认为false,不会因为模型漏写某行而删除已有数据。- 只有业务明确要求“数组即完整明细”时才开启
replaceRows: true;开启后补丁中缺失的已有行会调用removeRow。
适配器还公开 getTableRows、addTableRow、updateTableRow 和 removeTableRow,宿主页面可以用于调试或自定义确认流程。
复杂业务动作
附件选择、客户选择器、保存草稿等操作不能表示成普通字段值时,在适配器中注册白名单动作:
createFormAdapter({
getValues: () => this.form,
fields: { /* 字段协议 */ },
validateForm: () => this.$refs.form.validate()
.then(() => ({ valid: true }))
.catch(() => ({ valid: false, message: '请先完善必填项' })),
actions: {
openCustomerSelector: {
label: '打开客户选择器',
description: '打开页面已有的客户选择弹窗',
execute: payload => this.openCustomerSelector(payload.keyword),
},
requestAttachmentUpload: {
label: '选择合同附件',
description: '打开文件选择器,文件仍由用户选择',
execute: () => this.$refs.attachmentUploader.open(),
},
saveDraft: {
label: '保存草稿',
execute: () => this.saveDraft(),
},
},
})
平台智能体需要启用内置工具 propose_form_actions。工具只返回动作计划,不执行页面操作。插件在一轮运行结束后展示统一确认框,用户确认后才调用 executeActions。
支持的标准动作类型:
| 类型 | 参数 | 作用 |
|---|---|---|
set_field |
field, value |
修改一个白名单字段 |
set_fields |
values |
按联动协议批量回填 |
add_table_row |
field, value |
新增明细行 |
update_table_row |
field, rowKey, values |
更新指定明细行 |
remove_table_row |
field, rowKey |
删除指定明细行 |
trigger_action |
name, payload |
调用宿主注册的白名单业务动作 |
validate |
fields |
调用宿主表单校验 |
request_submit |
- | 产生 save-request,不会直接提交 |
trigger_action 的 name 不在 actions 注册表中时会被拒绝。上传动作只能打开宿主文件选择器,智能体不能代替用户读取或选择本地文件。
方式一:全局注册
// main.js
import Vue from 'vue'
import BaoyogAgent from '@baoyog/agent-vue2'
import '@baoyog/agent-vue2/dist/style.css'
Vue.use(BaoyogAgent, {
baseUrl: 'https://ai.example.com/web/api',
devBaseUrl: 'http://127.0.0.1:13060/web/api',
chatKey: '从智能体发布配置中获取',
agentId: '2079080349952217090',
agentCode: 'form_agent_001',
})
<!-- 任意组件 -->
<template>
<AgentChat
agent-code="form_agent_001"
biz-type="采购合同"
:context-params="{ token: shortLivedBusinessToken }"
@form-patch="applyPatch"
@submit-request="confirmSubmit"
/>
</template>
方式二:按需引入
<script>
import { AgentChat } from '@baoyog/agent-vue2'
import '@baoyog/agent-vue2/dist/style.css'
export default {
components: { AgentChat },
}
</script>
<template>
<AgentChat
:api-base-url="apiUrl"
:agent-code="code"
:token="token"
:biz-type="bizType"
/>
</template>
方式三:CDN
<link rel="stylesheet" href="https://unpkg.com/@baoyog/agent-vue2/dist/style.css">
<script src="https://unpkg.com/vue@2.7"></script>
<script src="https://unpkg.com/@baoyog/agent-vue2"></script>
<script>
// 自动注册 AgentChat 组件
new Vue({ el: '#app' })
</script>
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
baseUrl |
String |
- | 生产环境后端 API 地址(包含 /web/api) |
devBaseUrl |
String |
- | 本地后端 API 地址(包含 /web/api) |
chatKey |
String |
必填 | 静默换取平台运行 Token |
agentId |
String |
必填 | 创建持久会话所需的智能体数据库 ID |
agentCode |
String |
必填 | 智能体编码 |
bizType |
String |
'' |
业务类型,自动生成初始消息 |
contextParams |
Object |
{} |
请求级业务上下文,仅建议传短期凭证 |
title |
String |
'AI 助手' |
面板标题 |
placeholder |
String |
'输入消息,Enter 发送...' |
输入框提示 |
emptyHint |
String |
'有什么可以帮你?' |
空状态提示 |
defaultCollapsed |
Boolean |
true |
是否默认折叠为悬浮按钮 |
AiFormAssistant Props
除 AgentChat 的连接与界面属性外,标准表单助手还支持:
| 属性 | 类型 | 说明 |
|---|---|---|
sceneCode |
String |
业务场景编码,例如 contract.sales |
recordId |
String/Number |
当前业务记录 ID;为空表示新增 |
operation |
String |
可选,默认根据 recordId 推断 CREATE/UPDATE |
adapter |
Object |
createFormAdapter 返回的表单适配器 |
disabled |
Boolean |
是否禁用助手 |
contextProvider |
Function |
每次发送前补充动态业务上下文 |
事件:patch-proposed、patch-applied、actions-proposed、actions-applied、patch-rejected、save-request、error。
本地开发
cd baoyog-ai-vue2-plugin
npm install
npm run dev # 启动 demo(端口 3201)
npm run build # 构建到 dist/
form-patch 只表示回填建议,submit-request 只表示用户表达了提交意图。插件不会直接调用业务提交接口,宿主页面必须展示确认并再次执行本地校验。
通信协议
通过 POST /api/runtime/agui/run/{agentCode} 发起 SSE 流式请求,响应遵循 AgentScope SSE 事件协议:
TEXT_MESSAGE_START / TEXT_MESSAGE_CONTENT— AI 回复文本TOOL_CALL_START / TOOL_CALL_ARGS / TOOL_CALL_RESULT— 工具调用RUN_FINISHED— 执行完成RUN_ERROR— 执行失败
目录结构
baoyog-ai-vue2-plugin/
├── src/
│ ├── index.js # 插件入口,install + 导出
│ ├── AgentChat.vue # 主组件
│ ├── AiFormAssistant.vue # 标准表单助手
│ ├── formAdapter.js # 表单适配器与转换器
│ └── ai-agent.js # Markdown 渲染 + SSE 处理
├── demo/ # 本地调试
├── package.json
└── vite.config.js
Related Packages
Tnzi AI components - chat, agent visualization, and workflow builder for AI-powe...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.6.1 | ^2.6.0 || | MIT | |
| 1.6.0 | ^2.6.0 || | MIT | |
| 1.5.0 | ^2.6.0 || | MIT | |
| 1.4.0 | ^2.6.0 || | MIT | |
| 1.3.2 | ^2.6.0 || | MIT | |
| 1.3.1 | ^2.6.0 || | MIT | |
| 1.3.0 | ^2.6.0 || | MIT | |
| 1.2.0 | ^2.6.0 || | MIT | |
| 1.1.0 | ^2.6.0 || | MIT |