---
url: /v6.2/copilot-sdk-js.md
---
# JS SDK 集成指南

如果你们希望保留自己的页面、入口和业务壳，但又不想自己从零实现数据问答界面和结果渲染，那么应该使用 JS SDK。

不过在看 SDK 之前，也建议先想清楚：当前这套能力会以 Agent 模式运行，还是以 Workflow 模式运行。

> \[!TIP] 建议先看总览
> 如果你们还没判断清楚运行方式和接入方式的关系，建议先读 [Data Agent 集成总览](copilot-sdk.md)。

## JS SDK 解决的是什么问题

JS SDK 解决的是：

* 你们想保留自己的页面壳
* 但希望把衡石现成的聊天能力或结果渲染能力嵌进去

它不解决的是：

* 把衡石返回结果转换成你们自己的图表协议
* 让你们完全不需要理解运行方式差异

## JS SDK 有两种常见嵌入形态

### 1. 完整聊天窗：`new Copilot(...)`

这种方式适合把一个完整聊天窗嵌进页面里。

它包含：

* 消息区
* 输入区
* 推荐问题
* 图表和结果展示
* 会话相关交互

适合：

* 希望在页面右侧或右下角挂一个 AI 助手
* 希望复用完整聊天体验
* 只想控制窗口开关、位置、大小和主题

### 2. 局部结果卡片：`Copilot.renderChat(...)`

这种方式适合把一条问答结果嵌在业务页面中。

适合：

* 已经有自己的页面结构
* 只想把答案和图表嵌到某个模块里
* 希望把“数据问答结果”作为业务页面中的一个组成部分来展示

## JS SDK 和 iframe 仪表盘一起使用

如果你们的父页面已经加载 Copilot JS SDK，同时页面里还通过 iframe 嵌入衡石仪表盘，可以让父页面 Copilot 接管 iframe 仪表盘里的智能助理能力。

推荐做法是在 iframe 仪表盘 URL 上增加：

```text
?agentHost=parent&parentOrigin={父页面 origin}
```

接管后：

* iframe 仪表盘不再显示自己的 Copilot 侧边栏
* 仪表盘里的“打开助手”“智能解读”“图表解读”等入口会打开父页面 Copilot
* Agent 读取和编辑 iframe 仪表盘时，会通过 iframe 代理出来的业务动作和业务对象完成

完整示例见 [iframe 集成：父页面 Copilot SDK 接管 iframe 仪表盘](copilot-sdk-iframe.md#parent-copilot-iframe-dashboard)。

## JS SDK 与运行方式的关系

### JS SDK + Workflow

如果当前使用的是 Workflow 模式：

* 执行过程主要由衡石后端工作流服务负责
* 你们的页面负责承载入口和业务壳
* JS SDK 负责把聊天界面或结果渲染能力嵌进页面

这种组合最容易理解成：

* 你们保留页面壳
* 衡石负责执行和渲染

### JS SDK + Agent

如果当前使用的是 Agent 模式：

* JS SDK 不只是一个“显示结果的组件”
* 它还会承接 Agent 模式在前端侧的运行过程
* 你们看到的不只是一个渲染层，而是一套嵌入式的智能问答前端能力

这种组合更适合：

* 希望在自有页面中直接保留 Agent 风格体验
* 希望用户在页面里看到更连续的执行过程和交互反馈

## 前后端职责怎么理解

| 组合 | 你们主要负责什么 | 衡石主要负责什么 |
|---|---|---|
| JS SDK + Workflow | 页面壳、入口、业务流程 | 后端执行推进 + 前端结果渲染 |
| JS SDK + Agent | 页面壳、入口、业务流程 | Agent 运行过程 + 前端聊天与结果能力 |

## 什么时候最适合选 JS SDK

* 你们明确要保留自己的页面壳
* 你们不想自己做完整的数据问答前端体验
* 你们希望结果卡片、图表和聊天能力能自然嵌进现有页面

## 什么时候不应该优先选 JS SDK

### 情况 1：你们只想接后端能力

这时应该先看 [API 集成](copilot-sdk-api.md)。

### 情况 2：你们想最快复用完整页面

这时通常 [iframe 集成](copilot-sdk-iframe.md) 更省事。

### 情况 3：你们想完全使用自己的前端协议和图表体系

那就要准备自己承担更多前端适配成本，JS SDK 并不是为“协议转码”设计的。

## 最小接法示意

### 完整聊天窗：`new Copilot(...)`

```html
<script src="https://your-hengshi-host/assets/hengshi-copilot@<version>.js"></script>
<div id="copilot-root"></div>
<script>
 const root = document.getElementById('copilot-root');
 const copilot = new Copilot(root, {
   locale: 'zh-CN',
   userConfig: {
     dataSources: [
       { dataAppId: 130870, datasetId: 1 },
     ],
   },
 });
</script>
```

### 局部结果卡片：`Copilot.renderChat(...)`

```html
<script src="https://your-hengshi-host/assets/hengshi-copilot@<version>.js"></script>
<div id="chat-result"></div>
<script>
 const container = document.getElementById('chat-result');
 window.Copilot.renderChat(container, {
   prompt: '华东区上月销售额是多少？',
   type: 'workflow',
 }, {
   userConfig: {
     dataSources: [
       { dataAppId: 130870, datasetId: 1 },
     ],
   },
 });
</script>
```

> \[!TIP] 提示
> `type` 用来指定这条问答按哪种运行方式执行，因此在集成前最好先确定你们选择的是 Agent 模式还是 Workflow 模式。

## 常用参数说明

这一节不是把所有内部实现细节都摊开，而是先把集成时最常用、最容易搞混的参数讲清楚。

### `new Copilot(container, config)` 的常用配置

#### `container`

* 类型：`HTMLElement`
* 含义：聊天窗挂载到哪个 DOM 节点
* 你们负责先在页面里准备这个容器

#### `locale`

* 类型：`string`
* 作用：指定界面语言，例如 `zh-CN`、`en-US`
* 用途：控制 SDK 内部文案和本地化资源加载

#### `userConfig`

* 类型：`object`
* 作用：指定当前问答可用的数据范围
* 最常见写法：

```js
userConfig: {
  dataSources: [
    { dataAppId: 130870, datasetId: 1 },
  ],
}
```

`dataSources` 支持两种模式，但同一次配置里不要混用：

1. 数据包 / 数据集模式
   * `dataAppId`
   * `datasetId`

2. 主题域模式
   * `subjectId`

示例：

```js
userConfig: {
  dataSources: [
    { subjectId: 1 },
    { subjectId: 2 },
  ],
}
```

#### `draggable`

* 类型：`object`
* 作用：把聊天窗做成可拖拽、可调整尺寸的浮层
* 常用字段：
  * `enable`: 是否启用拖拽
  * `bounds`: 拖拽边界，常见值为 `window` 或 `parent`
  * `minWidth` / `minHeight`: 最小尺寸
  * `position`: 初始位置，例如 `{ x, y }`
  * `size`: 初始宽高，例如 `{ width, height }`

示例：

```js
draggable: {
  enable: true,
  bounds: 'window',
  minWidth: 440,
  minHeight: 440,
  position: { x: window.innerWidth - 480, y: 20 },
  size: { width: 440, height: window.innerHeight * 0.8 },
}
```

#### `stylesheet`

* 类型：`string`
* 作用：向 SDK 的 shadow DOM 注入自定义样式
* 适合改主题色、间距、字体等表现层

例如：

```js
stylesheet: ':host > *, ::before, ::after { --brand: #4CAF50; }'
```

#### `i18n`

* 类型：`object`
* 作用：覆盖 SDK 内部部分文案
* 适合微调“问题理解 / 数据表现 / 取数逻辑”这类标题文案

例如：

```js
i18n: {
  'zh-CN': {
    'copilot.question-reasoning': '问题理解',
    'copilot.question-answer': '数据表现',
    'copilot.question-reasoning-logic': '取数逻辑',
  },
}
```

#### 其他常用项

| 参数 | 作用 |
|---|---|
| `closable` | 是否显示关闭按钮 |
| `headless` | 是否先以隐藏状态初始化 |
| `style` | 根容器样式 |
| `completionConfig` | 控制结果渲染阶段的行为 |
| `onReady` | SDK 初始化完成后的回调 |
| `onHide` | 调用 `hide()` 后触发的回调 |

### `completionConfig` 常用字段

这个配置会影响结果卡片和问答完成后的展示方式。

| 参数 | 作用 |
|---|---|
| `meta` | 指定要展示哪些内容，例如 `answer,chart,chartConfig` |
| `openChartConfig` | 是否默认展开取数逻辑面板 |
| `stylesheet` | 结果卡片阶段额外样式 |
| `i18n` | 结果卡片阶段额外文案覆盖 |
| `onCompletionDone` | 问答完成时的回调，参数为 `(conversationId, uid)` |

### `Copilot.renderChat(container, chatConfig, copilotConfig)` 的参数

`renderChat(...)` 接受 3 个参数：

#### 第 1 个参数：`container`

* 类型：`HTMLElement`
* 作用：结果卡片要渲染进哪个容器

#### 第 2 个参数：`chatConfig`

这是“这一条结果本身怎么来”的配置，常见两种用法：

1. 动态问答

```js
{
  prompt: '华东区上月销售额是多少？',
  type: 'workflow',
}
```

常用字段：

* `prompt`: 用户问题
* `type`: `agent` 或 `workflow`
* `conversationId`: 如果要在已有会话里继续问，可以显式传入
* `meta`: 控制最终展示哪些结果块
* `openChartConfig`: 是否展开取数逻辑面板
* `onCompletionDone`: 本次问答完成后的回调

2. 静态渲染已有结果

如果你已经拿到了完整的问答数据，也可以直接传：

* `conversationId`
* `uid`
* `prompt`
* `answer`
* `refineQuestion`
* `charts`
* 以及相关结果字段

这更适合“把一条现成结果重新渲染到另一个区域”。

#### 第 3 个参数：`copilotConfig`

这部分和 `new Copilot(...)` 的配置思路一致，最常见的是继续传 `userConfig`，让这条结果在明确的数据范围内运行：

```js
{
  userConfig: {
    dataSources: [
      { dataAppId: 130870, datasetId: 1 },
    ],
  },
}
```

## 部署和认证相关参数

### `window.__hs_sdk_base_url__`

如果 SDK 文件不是直接从衡石系统同域加载，而是放在 CDN 或其他静态资源域名下，应该在加载脚本前显式指定后端地址：

```html
<script>
  window.__hs_sdk_base_url__ = 'https://your-hengshi-host';
</script>
<script src="https://cdn.example.com/assets/hengshi-copilot@<version>.js"></script>
```

否则，SDK 默认会按当前脚本所在 host 去推断接口地址，容易把请求打错地方。

### 登录认证

SDK 页面最终是否能正常显示问答和图表，还取决于登录态是否已经准备好。

常见方式有两种：

1. 你们自己的系统已经和衡石打通 SSO
2. 通过 JWT 登录接口先完成认证

例如：

```js
fetch('https://your-hengshi-host/api/auth/login-info?activeAuth=jwt-param&jwtParam=<your-jwt-param>')
```

## 实例方法

`new Copilot(...)` 返回的是一个实例。最常用的方法是：

| 方法 | 作用 |
|---|---|
| `show()` | 显示聊天窗 |
| `hide()` | 隐藏聊天窗 |

所以在页面里，通常不需要反复销毁重建实例；直接控制显示 / 隐藏就够了。

## 一句话总结

JS SDK 适合“保留自己的页面，但复用衡石前端能力”。

它不是一种独立于 Agent / Workflow 之外的新模式，而是承载这两种运行方式的前端嵌入方式。
