@egova/egovis-sdk
v0.1.1
Published
Egovis 嵌入式智能助手 SDK
Downloads
0
Maintainers
Keywords
Readme
Egovis 智能助手 SDK
@egova/egovis-sdk 用于在业务系统中接入 Egovis 智能助手,支持抽屉和页面嵌入两种布局,并可向助手提供当前页面的业务数据和快捷提问。
SDK 仅在浏览器环境中运行。Nuxt、Next.js 等服务端渲染项目应在客户端生命周期内加载 SDK。
安装
pnpm add @egova/egovis-sdk也可以使用 npm:
npm install @egova/egovis-sdk快速开始
import { create, type BusinessPageContext } from '@egova/egovis-sdk'
const assistant = create({
assistantUrl: 'https://ai.example.com/assistant.html',
projectId: 'project-100',
contextProvider: (): BusinessPageContext => ({
source: {
systemCode: 'case-center',
pageCode: 'case-list',
},
page: {
title: '案件统计',
path: location.pathname,
},
content: {
filters: { status: 'pending' },
selectedCaseIds: ['case-1'],
},
summary: [
{ key: 'total', label: '案件数', value: '12' },
],
questions: [
{ title: '分析趋势', content: '分析当前案件变化趋势' },
],
}),
})
assistant.on('error', error => console.error('智能助手异常', error))默认使用 drawer 布局,并在页面右下角显示系统 AI 图标。首次点击图标时打开智能助手。
初始化选项
| 选项 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| assistantUrl | string | - | 必填,助手 assistant.html 的绝对 HTTP(S) 地址。 |
| projectId | string | - | 必填,当前 Egovis 项目 ID。 |
| mountTarget | string \| HTMLElement | document.body | SDK 挂载节点。 |
| layout | 'drawer' \| 'embedded' | 'drawer' | 助手布局方式。 |
| trigger.label | string | - | AI 按钮文案;未配置时只显示系统 AI 图标。 |
| trigger.placement | 'left' \| 'right' | 'right' | AI 按钮位于页面左下角或右下角。 |
| trigger.hidden | boolean | false | 是否隐藏 SDK 内置 AI 按钮。 |
| drawer.width | number | 480 | 抽屉宽度,取值限制为 360~960 px。 |
| drawer.placement | 'left' \| 'right' | 'right' | 抽屉从页面左侧或右侧打开。 |
| contextProvider | () => BusinessPageContext \| Promise<BusinessPageContext> | - | 返回当前页面最新业务上下文。 |
| handshakeTimeoutMs | number | 5000 | 助手加载就绪超时时间,单位为 ms。 |
| ackTimeoutMs | number | 3000 | 上下文同步超时时间,单位为 ms。 |
业务上下文
字段说明
| 字段 | 必填 | 限制 |
| --- | --- | --- |
| source.systemCode | 是 | 非空字符串,最长 128 个字符。 |
| source.pageCode | 是 | 非空字符串,最长 128 个字符。 |
| page.title | 是 | 非空字符串,最长 256 个字符。 |
| page.path | 否 | 最长 1024 个字符,必须以 / 开头,不能包含 query(?)或 hash(#)。 |
| subject.type | 否 | 非空字符串,最长 128 个字符。 |
| subject.title | 否 | 最长 256 个字符。 |
| summary | 否 | 最多 8 项,各项 key 必须唯一。 |
| summary[].key | 是 | 非空字符串,最长 128 个字符。 |
| summary[].label | 是 | 非空字符串,最长 256 个字符。 |
| summary[].value | 是 | 最长 2048 个字符。 |
| content | 是 | 根必须是普通 JSON 对象(允许 null 原型),属性值只能包含标准 JSON 值,最大嵌套深度为 16 层。 |
| questions | 否 | 最多 20 项,仅用于 iframe 快捷提问,不提交后端。 |
| questions[].title | 是 | 非空字符串,最长 256 个字符。 |
| questions[].content | 是 | 非空字符串,单个字符串最长 16 KB。 |
summary 中每一项包含 key、label 和 value;questions 中每一项包含 title 和 content。
单个上下文序列化后最多 64 KB,questions 也参与该 iframe 协议大小校验。所有对象键最长 128 个字符,所有未设置更小字段上限的单个字符串最长 16 KB。content 从根容器开始计数,数组和对象容器最大嵌套深度为 16 层,基础值不增加深度。上下文使用严格字段校验,数组必须是无空洞的密集数组;不支持循环引用、访问器属性、数组额外自有属性、函数、undefined、日期对象和其他非 JSON 值。
对象键按大小写不敏感方式检查,禁止使用 token、accessToken、refreshToken、idToken、authorization、cookie、setCookie、password、secret、clientSecret、privateKey 等敏感键。业务系统仍应按白名单组装数据并主动脱敏。
上下文 Hash
上下文 Hash 只包含 source、page、subject、summary 和 content。questions 排除在 Hash 输入之外,也不会提交后端,只通过 iframe 协议提供快捷提问。SDK 先递归排序对象键并生成稳定 JSON,再按 UTF-8 字节执行 FNV-1a 32 位计算,输出 8 位小写十六进制字符串。
以下固定向量用于跨语言实现校验:
{"content":{"area":"东城区","icon":"🚀"},"page":{"path":"/statistics/cases","title":"案件统计"},"source":{"pageCode":"case-overview","systemCode":"statistics"},"summary":[{"key":"total","label":"案件数","value":"12"}]}对应 Hash 为 4c456b2a。
更新上下文
页面路由、查询条件、表格数据或选中项发生变化后,调用 refreshContext() 重新获取当前页面数据:
async function handleSearch() {
await loadTableData()
await assistant.refreshContext()
}refreshContext() 会重新执行初始化时传入的 contextProvider。建议先完成业务页面的数据更新,再调用该方法。
如果业务系统已经持有完整的新上下文,也可以直接更新:
assistant.setContext(nextContext)每次更新都应提供完整上下文。summary、content 和 questions 会整体替换,不会与上一次数据合并。
发送与后端流转
- 用户每次发送消息时,iframe 会冻结发送瞬间的完整业务上下文快照,并随
/api/v1/conversation-orchestrator/stream请求提交。 contextHash相同也不会省略快照;后端仍会为当前 user 行保存完整业务上下文,保证后续 Agent 每轮都能从持久化消息恢复。questions只用于前端快捷提问,不进入请求、数据库或模型输入。- 用户点击“移除页面数据”后,下一轮请求不携带业务上下文;后端不会从历史轮次恢复旧快照。
- 确认续接、同轮重试和 SSE 重连必须复用首次持久化的快照;重连请求不允许携带新的
businessContext。 - 当前只支持主助手和 Builder ReAct 子 Agent 使用业务上下文;工作流、专家团和 Plan-Execute 默认不接收完整业务上下文。
- 后端会再次校验 Schema、64 KB 大小、Hash、项目归属和内部 Part 伪造,业务系统不能绕过 SDK 直接写入内部消息结构;
token、accessToken、refreshToken、idToken、authorization、cookie、setCookie、password、secret、clientSecret、privateKey等敏感字段会被拒绝。 - 业务上下文保存于
mate_message.content_parts的两个内部 Part:结构化egovis_business_context_v1与回放egovis_part_v2,不写入 task、conversation 或 message 普通文本字段。
抽屉布局
const assistant = create({
assistantUrl: 'https://ai.example.com/assistant.html',
projectId: 'project-100',
layout: 'drawer',
trigger: {
label: 'AI 助手',
placement: 'right',
},
drawer: {
width: 440,
placement: 'right',
},
contextProvider: () => currentPageContext,
})抽屉首次打开时加载助手;关闭后保留当前助手页面和对话状态,再次打开时会重新获取当前页面上下文。
使用业务系统自己的按钮
隐藏 SDK 内置按钮,由业务系统调用实例方法打开或关闭助手:
const assistant = create({
assistantUrl: 'https://ai.example.com/assistant.html',
projectId: 'project-100',
trigger: { hidden: true },
contextProvider: () => currentPageContext,
})
document.querySelector('#ai-button')?.addEventListener('click', () => {
void assistant.toggle()
})页面嵌入布局
<div id="assistant-panel"></div>#assistant-panel {
width: 420px;
height: 100vh;
}const assistant = create({
assistantUrl: 'https://ai.example.com/assistant.html',
projectId: 'project-100',
mountTarget: '#assistant-panel',
layout: 'embedded',
contextProvider: () => currentPageContext,
})embedded 布局会填满挂载节点,因此挂载节点必须具有明确的宽度和高度。该布局始终显示,调用 close() 不会隐藏助手。
实例方法
| 方法 | 说明 |
| --- | --- |
| open() | 打开抽屉并重新获取当前页面上下文。 |
| close() | 关闭抽屉;对 embedded 布局无效。 |
| toggle() | 切换抽屉的打开状态。 |
| refreshContext() | 重新执行 contextProvider。 |
| setContext(context) | 使用完整快照更新业务上下文。 |
| clearContext() | 清除当前业务上下文。 |
| setProjectId(projectId) | 切换 Egovis 项目。 |
| on(event, handler) | 监听 SDK 事件,返回取消监听函数。 |
| destroy() | 销毁 SDK 实例并移除页面元素。 |
业务页面卸载或微前端应用销毁时,必须销毁 SDK 实例:
assistant.destroy()事件
const offReady = assistant.on('ready', () => {
console.info('智能助手已就绪')
})
const offError = assistant.on('error', error => {
console.error('智能助手异常', error)
})
// 不再需要监听时取消订阅
offReady()
offError()支持的事件包括 open、close、ready、context-ack、context-rejected 和 error。
切换项目
业务系统切换项目后,应同步更新 SDK 的 projectId:
await assistant.setProjectId(nextProjectId)调用前应先完成业务系统自身的项目状态切换,确保 contextProvider 能返回新项目的数据。
样式调整
按钮位置、抽屉方向和宽度优先通过初始化选项配置。颜色和层级可以通过 CSS 变量覆盖:
egovis-ai-assistant {
--egovis-assistant-trigger-bg: #1677ff;
--egovis-assistant-trigger-color: #ffffff;
--egovis-assistant-z-index: 2000;
}IIFE/CDN 接入
<script src="https://cdn.example.com/egovis-sdk.iife.js"></script>
<script>
const assistant = EgovisSDK.create({
assistantUrl: 'https://ai.example.com/assistant.html',
projectId: 'project-100',
contextProvider: () => ({
source: { systemCode: 'case-center', pageCode: 'case-detail' },
page: { title: '案件详情', path: location.pathname },
content: { caseId: 'case-1', status: 'pending' }
})
})
</script>数据安全
contextProvider 应按白名单组装数据,并在返回前完成脱敏:
contextProvider: () => ({
source: { systemCode: 'case-center', pageCode: 'case-detail' },
page: { title: '案件详情', path: location.pathname },
content: {
caseId: currentCase.id,
category: currentCase.category,
reporterPhone: maskPhone(currentCase.reporterPhone),
},
})不要提供 Token、Cookie、密码、身份证明、完整手机号或其他认证凭证。assistantUrl 也不应携带 Token 或其他敏感信息。
跨域配置
业务系统与智能助手跨域部署时,需要完成以下配置:
- 在实际托管
assistant.html的服务端响应中配置 CSPframe-ancestors,允许业务系统 Origin。 - 为智能助手前端配置允许接入的业务系统 Origin,例如
VITE_ASSISTANT_HOST_ORIGINS=https://business.example.com。
只填写规范的 HTTP(S) Origin,不要使用 *、路径、查询参数或片段。生产环境应使用 HTTPS。
