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

@egova/egovis-sdk

v0.1.5

Published

Egovis 嵌入式智能助手 SDK

Readme

Egovis 智能助手 SDK

@egova/egovis-sdk 用于在业务系统中接入 Egovis 智能助手,支持抽屉、页面内 Modal 和页面嵌入三种布局,并可向助手提供当前页面的业务上下文、快捷提问和宿主动作。

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',
  display: {
    theme: 'light',
    starterTitle: '案件办理助手',
    starterSubtitle: '分析当前案件并生成处置建议。',
    conversationWidthPercent: 120,
    themeToggleVisible: true,
    fontSize: 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 图标。首次点击图标时加载并打开智能助手。

SDK 写入 iframe URL 的业务参数只有 projectId,其他配置通过 iframe 桥接发送。iframe 内独立完成登录;登录跳转不会销毁 SDK 创建的 iframe,登录成功后会继续完成桥接初始化。

使用新增展示字段前应先部署支持对应 Bridge 字段的新版 assistant.html,再升级业务系统中的 SDK。新版助手仍兼容旧 SDK 未携带新增展示字段的初始化消息。

初始化选项

| 选项 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | assistantUrl | string | - | 必填,助手 assistant.html 的绝对 HTTP(S) 地址。 | | projectId | string | - | 必填,当前 Egovis 项目 ID。 | | mountTarget | string \| HTMLElement | document.body | SDK 挂载节点。 | | layout | 'drawer' \| 'modal' \| 'embedded' | 'drawer' | 助手布局方式。 | | trigger.label | string | - | AI 按钮文案;未配置时只显示系统 AI 图标。 | | trigger.placement | 'left' \| 'right' | 'right' | AI 按钮位于页面左下角或右下角。 | | trigger.hidden | boolean | false | 是否隐藏 SDK 内置 AI 按钮。 | | trigger.draggable | boolean | true | 是否允许拖动 SDK 内置 AI 按钮。 | | drawer.width | number \| px \| vw | 480 | 抽屉宽度,最小 360 px,最大为当前视口宽度。 | | drawer.placement | 'left' \| 'right' | 'right' | 抽屉打开方向。 | | drawer.resizable | boolean | true | 是否允许调整抽屉宽度。 | | modal.width | number \| px \| vw | 90vw | Modal 默认宽度,数字按 px 处理。 | | modal.height | number \| px \| vh | 90vh | Modal 默认高度,数字按 px 处理。 | | modal.draggable | boolean | true | 是否允许拖动 Modal。 | | modal.resizable | boolean | true | 是否允许调整 Modal 尺寸。 | | modal.backdropVisible | boolean | true | 是否显示半透明遮罩;隐藏后仍会阻断宿主交互。 | | interaction.snap | boolean | true | 是否为 Trigger、Drawer 和 Modal 启用吸附。 | | interaction.showSnapIndicators | boolean | true | 是否显示吸附视觉反馈;不影响实际吸附。 | | persistenceScope | 'origin' \| 'project' | 'origin' | 交互位置和尺寸按当前 Origin 或项目持久化。 | | display.contextVisible | boolean | true | 是否在助手中显示页面数据卡片。 | | display.starterTitle | string | 把想法变成成果,用 AI 高效完成工作 | 助手新对话欢迎区标题,最长 256 个字符;空白值回退默认文案。 | | display.starterSubtitle | string | 您好,我是您的智能助手,可以帮您梳理思路、拆解任务、生成内容,让工作推进更简单。 | 助手新对话欢迎区副标题,最长 512 个字符;空白值回退默认文案。 | | display.conversationWidthPercent | number | 100 | 对话内容和输入框共享宽度百分比,范围 80–140,步长 10。 | | display.theme | 'light' \| 'dark' \| 'system' | 'light' | 助手初始主题;system 会在当前 iframe 会话内实时跟随操作系统主题变化。 | | display.themeToggleVisible | boolean | true | 是否显示 assistant 页面右上角的主题切换按钮,宽屏和紧凑布局同时生效。 | | display.fontSize | number | 跟随 iframe 宽度 | assistant.html 的 HTML 根字号,单位为 px,范围 80–120;显式配置固定覆盖,缺省时按 iframe width 自动计算。 | | contextProvider | (scope: EgovisProjectScope) => BusinessPageContext \| Promise<BusinessPageContext> | - | 返回当前项目的最新业务上下文。 | | actions | EgovisHostActionDefinition[] | [] | 注册宿主动作,供助手生成固定动作卡片。 | | timeouts.loadMs | number | 10000 | iframe 文档首次加载超时时间,单位为 ms。 | | timeouts.contextAckMs | number | 10000 | 上下文同步确认超时时间,单位为 ms。 | | timeouts.actionExecutionMs | number | 10000 | 宿主动作 Handler 执行超时时间,单位为 ms。 |

三项超时仅接受有限正数;无效值统一回退到 10000 ms。

展示配置通过 Bridge 应用于当前 SDK iframe。宿主配置的对话宽度是每次加载的初始值;用户仍可在页面配置中临时调整当前会话宽度。display.theme 缺省为浅色主题,配置为 system 时会跟随操作系统主题实时变化;用户在助手内手动切换后仅影响当前 iframe 会话。fontSize 会直接写入 iframe 文档的 document.documentElement.style.fontSize,只影响 assistant.html,不会修改宿主页面字号。

业务上下文

字段说明

| 字段 | 必填 | 说明 | | --- | --- | --- | | source.systemCode | 是 | 来源系统编码,最长 128 个字符。 | | source.pageCode | 是 | 来源页面编码,最长 128 个字符。 | | page.title | 是 | 页面标题,最长 256 个字符。 | | page.path | 否 | 以 / 开头且不包含 query 或 hash,最长 1024 个字符。 | | subject | 否 | 当前业务主体,包含 type 和 title。 | | summary | 否 | 页面摘要,最多 8 项,key 必须唯一。 | | content | 是 | 提供给助手的结构化页面数据,根节点必须是 JSON 对象。 | | questions | 否 | 快捷提问,最多 20 项,仅用于助手界面。 |

单个上下文序列化后最多 64 KB,最大嵌套深度为 16 层。上下文只能包含标准 JSON 值,不支持循环引用、函数、undefined、日期对象、访问器属性或稀疏数组。

对象键禁止包含 Token、Cookie、密码、密钥等敏感字段。业务系统应按白名单组装数据,并在传给 SDK 前完成脱敏。

更新上下文

页面路由、查询条件、表格数据或选中项发生变化后,重新获取当前页面数据:

async function handleSearch() {
  await loadTableData()
  await assistant.refreshContext()
}

contextProvider 接收 { projectId, signal }。后续刷新、Provider 替换、项目切换或实例销毁会中止旧信号,并丢弃旧 Provider 的迟到结果。

如果业务系统已经持有完整的新上下文,也可以直接更新:

assistant.setContext(nextContext)

每次更新都应提供完整上下文;summary、content 和 questions 会整体替换,不与上一次数据合并。用户发送消息时,助手会使用发送瞬间的上下文快照;questions 只用于快捷提问,不提交后端。

display.contextVisible: false 只隐藏页面数据卡片,不会清除或停止同步上下文。需要停止携带上下文时,应调用 clearContext()。

宿主动作

宿主动作让对话能够触发业务系统中的固定操作:

  1. SDK 将已注册动作的名称、描述、参数 Schema 和默认参数提供给助手。
  2. 当用户对话符合某个业务操作场景时,助手生成固定动作卡片。
  3. 用户点击卡片后,iframe 向 SDK 发起动作请求,SDK 调用对应 Handler 并回传结果。

助手不会获得 Handler 实现,也不会绕过用户点击直接执行宿主操作。

动作字段

| 字段 | 必填 | 说明 | | --- | --- | --- | | call | 是 | 动作唯一名称,必须符合 EGOVIS_XXX_XXX 格式。 | | label | 是 | 动作卡片按钮文案。 | | description | 是 | 描述适用场景,供助手选择动作。 | | parameterSchema | 否 | 约束助手生成的卡片参数;省略时表示无参数。 | | defaultArgs | 否 | 卡片默认参数;助手生成的同名参数会覆盖默认值。 | | defaultButtonType | 是 | 默认按钮类型。 | | allowedButtonTypes | 是 | 助手可选择的按钮类型范围。 | | interaction | 否 | 配置点击后的终态和结果消息策略;省略时使用默认行为。 | | handler | 是 | 用户点击卡片后执行的宿主函数。 |

import { create, type EgovisHostActionDefinition } from '@egova/egovis-sdk'

const actions: EgovisHostActionDefinition[] = [
  {
    call: 'EGOVIS_OPEN_CASE_LEDGER',
    label: '打开案件台账',
    description: '打开当前区域的案件台账页。',
    parameterSchema: {
      type: 'object',
      properties: {
        regionId: { type: 'string' },
      },
      required: ['regionId'],
      additionalProperties: false,
    },
    defaultArgs: {
      regionId: 'all',
    },
    defaultButtonType: 'info',
    allowedButtonTypes: ['primary', 'info'],
    interaction: {
      disableAfterSuccess: true,
      resultMessage: {
        success: true,
        failure: '案件台账打开失败,请稍后重试。',
      },
    },
    handler: async (args, { projectId, signal }) => {
      const response = await fetch(
        `/api/projects/${encodeURIComponent(projectId)}/case-ledger`,
        { signal },
      )
      if (!response.ok) {
        return {
          status: 'failed',
          errorCode: 'LOAD_CASE_LEDGER_FAILED',
          message: '案件台账接口暂不可用。',
        }
      }
      location.assign(`/case-ledger?regionId=${encodeURIComponent(String(args.regionId))}`)
      return { status: 'success', message: '案件台账已打开。' }
    },
  },
]

const assistant = create({
  assistantUrl: 'https://ai.example.com/assistant.html',
  projectId: 'project-100',
  actions,
})

assistant.on('action-result', result => {
  console.log('宿主动作执行结果', result)
})

assistant.on('action-execution', telemetry => {
  console.log('宿主动作监控', telemetry)
})

按钮类型支持 Element Plus 的 default、primary、success、warning、danger 和 info。

interaction.disableAfterSuccess 控制动作成功后是否将当前卡片按钮置为“已完成”并禁用;默认 false。该状态只影响当前消息卡片中的当前动作,不会禁用同名动作的其他卡片或其他布局实例。

interaction.resultMessage.success 和 interaction.resultMessage.failure 控制结果提示策略:false 表示不提示,true 表示使用 Handler 返回的 message,没有动态消息时回退为 SDK 默认文案,字符串表示固定覆盖文案。默认值为 { success: false, failure: true }。rejected、failed 和 timeout 均使用 failure 策略,unsupported 不展示结果消息。

parameterSchema 用于约束助手生成的动作卡片。SDK 执行时只校验参数是否为标准 JSON 对象且不超过 16 KB,Handler 必须自行校验最终参数、用户权限和当前项目状态。未知动作返回 unsupported,参数格式或大小不合法返回 rejected,Handler 抛错返回 failed,超过动作超时返回 timeout。

每次 Handler 执行都会收到独立的 { projectId, signal }。调用 replaceActions()、切换项目、执行超时或销毁实例会中止信号;unregisterAction() 和同名 Handler 替换不会取消已经开始的执行。

Handler 返回的 message 只用于当前动作结果提示,最大 240 个字符;空白字符串、控制字符、HTML 标签和非字符串值会被忽略。message 不会进入动作注册描述、请求参数或 action-execution 监控事件。

action-execution 事件只提供 projectId、call、status 和 durationMs,不包含参数、Handler 返回内容或异常对象。action-result 事件会携带基础结果字段;当 Handler 返回了有效动态消息时,事件载荷会额外包含 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', resizable: true },
  contextProvider: () => currentPageContext,
})

抽屉首次打开时加载助手;关闭后保留对话状态,再次打开时重新获取页面上下文。Trigger 位置和抽屉宽度会根据 persistenceScope 持久化。

隐藏 SDK 内置按钮后,可以使用业务系统自己的入口:

const assistant = create({
  assistantUrl: 'https://ai.example.com/assistant.html',
  projectId: 'project-100',
  trigger: { hidden: true },
})

document.querySelector('#ai-button')?.addEventListener('click', () => {
  void assistant.toggle()
})

Modal

const assistant = create({
  assistantUrl: 'https://ai.example.com/assistant.html',
  projectId: 'project-100',
  layout: 'modal',
  modal: {
    width: '80vw',
    height: '80vh',
    draggable: true,
    resizable: true,
    backdropVisible: true,
  },
  interaction: {
    snap: true,
    showSnapIndicators: true,
  },
})

Modal 支持拖动、八方向缩放、位置与尺寸持久化,并在窄屏下自动切换为近全屏模式。关闭按钮、遮罩点击和 Escape 均可关闭 Modal;打开期间会保持焦点循环并锁定页面滚动。

modal.backdropVisible: false 只隐藏遮罩颜色,透明遮罩仍会阻断宿主页面交互。

页面嵌入

<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() 不会隐藏助手;嵌入区域尺寸由业务系统管理。

Drawer 和 Modal 使用 position: fixed。自定义 mountTarget 的祖先不应通过 transform、filter、perspective 或 contain 建立 Fixed Positioning Containing Block。

实例方法

| 方法 | 说明 | | --- | --- | | open() | 打开 Drawer 或 Modal,并重新获取当前页面上下文。 | | close() | 关闭 Drawer 或 Modal;对 embedded 布局无效。 | | toggle() | 切换 Drawer 或 Modal 的打开状态。 | | refreshContext() | 重新执行 contextProvider。 | | setContext(context) | 使用完整快照更新业务上下文。 | | clearContext() | 清除当前业务上下文。 | | setProjectId(projectId, options?) | 原子更新项目、上下文来源和宿主动作。 | | registerAction(action) | 注册单个宿主动作。 | | unregisterAction(call) | 按动作名注销宿主动作。 | | replaceActions(actions) | 原子替换全部宿主动作。 | | listActions() | 返回当前可公开的动作描述列表。 | | getState() | 返回实例当前状态的只读快照。 | | on(event, handler) | 监听 SDK 事件,返回取消监听函数。 | | destroy() | 销毁 SDK 实例并移除页面元素。 |

业务页面卸载或微前端应用销毁时,必须调用 destroy()。

事件

| 事件 | 载荷 | | --- | --- | | open、close、ready | { projectId } | | context-ack | ContextAckPayload | | context-rejected | ContextRejectedPayload | | action-ack、action-rejected | EgovisHostActionsAckPayload | | action-result | EgovisHostActionResultPayload & { message?: string } | | action-execution | { projectId, call, status, durationMs } | | error | { code, message, projectId } |

const offReady = assistant.on('ready', ({ projectId }) => {
  console.info('智能助手已就绪', projectId)
})

const offError = assistant.on('error', error => {
  console.error('智能助手异常', error)
})

// 不再需要监听时取消订阅
offReady()
offError()

iframe 首次触发 load 只表示文档已加载,不要求用户已经登录。ready 在助手登录并完成业务桥接后触发,表示助手业务已就绪。

切换项目

业务系统切换项目后,可以同时更新 SDK 的项目、上下文来源和动作:

await assistant.setProjectId(nextProjectId, {
  contextProvider: ({ projectId, signal }) => loadProjectContext(projectId, { signal }),
  actions: buildProjectActions(nextProjectId),
})

| 选项 | 行为 | | --- | --- | | 不传 options | 复用当前 Provider 和动作;项目变化时清除旧快照。 | | contextProvider | 替换 Provider;传 null 时移除 Provider 并清空上下文。 | | context | 切换为直接快照模式;传 null 时清空上下文。 | | actions | 原子替换动作;传 [] 时清空动作。 |

context 与 contextProvider 不能同时传入。SDK 会先完整校验本次更新,校验失败时保持原状态。setProjectId() 的 Promise 不等待 iframe 登录或桥接 ready,应通过 ready 事件确认远端业务就绪。

const state = assistant.getState()
// { projectId, open, ready, contextMode, actionRevision, destroyed }

样式调整

按钮位置、抽屉方向和尺寸优先通过初始化选项配置。字体、颜色和层级可以通过 CSS 变量覆盖:

egovis-ai-assistant {
  --egovis-assistant-font-family: var(--eg-font-sans);
  --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 应按白名单组装数据,并在返回前完成脱敏。
  • 不要提供 Token、Cookie、密码、身份证明、完整手机号或其他认证凭证。
  • assistantUrl 不应携带 Token 或其他敏感信息。
  • 宿主动作的 description、defaultArgs 和 Handler 返回 message 均会进入助手 iframe,应避免包含敏感数据、内部错误堆栈或可用于越权操作的信息。
  • 动作 Handler 必须在宿主侧重新校验参数、当前用户权限和项目归属;助手生成的卡片参数不能视为可信输入。
  • 跨域部署时,助手服务端必须通过 CSP frame-ancestors 允许业务系统 Origin。
  • 智能助手前端必须配置允许接入的业务系统 Origin,例如 VITE_ASSISTANT_HOST_ORIGINS=https://business.example.com。
  • 生产环境使用 HTTPS,Origin 配置不得使用 *、路径、查询参数或片段。