> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript.md).

# 开始使用原生 TypeScript

在没有 UI 框架的项目中安装 Convai Web SDK，将客户端连接到角色，并添加可选的聊天小组件。

使用纯 TypeScript 或 JavaScript 连接到 Convai 角色，无需 React 或其他 UI 框架。当你首次在无框架项目中设置 SDK 时，请使用此页面。最后，你的页面会持有一个已连接的客户端，以及可选的预构建聊天小部件。

### 先决条件

* 一个带有包管理器和可解析 npm 包的打包器的项目。
* 一个 Convai 账户、来自 <code class="expression">space.vars.dashboard\_url</code>的 API 密钥，以及一个角色 ID。

### 安装该包

原生 API 是单个 `@convai/web-sdk` 包的一部分。无需单独安装其他包。

{% tabs %}
{% tab title="npm" %}

```bash
npm install @convai/web-sdk @convai/web-widget
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm add @convai/web-sdk @convai/web-widget
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add @convai/web-sdk @convai/web-widget
```

{% endtab %}
{% endtabs %}

从 `@convai/web-sdk/vanilla`导入。它导出 `ConvaiClient`，SDK 自带的 `AudioRenderer` 类，以及所有核心类型。预构建的聊天 UI， `createConvaiWidget` 并且 `destroyConvaiWidget`，位于 `@convai/web-widget/vanilla`. `ConvaiClient` 也可从 `@convai/web-sdk/core`.

### 创建并连接客户端

将配置传递给构造函数，订阅事件，然后调用 `connect()`。等待 `botReady` 后再发送第一条消息。

{% code title="src/main.ts" %}

```typescript
import { ConvaiClient } from '@convai/web-sdk/vanilla';

const client = new ConvaiClient({
  apiKey: 'YOUR_API_KEY',
  characterId: 'YOUR_CHARACTER_ID',
  endUserId: 'user-uuid', // 可选：启用长期记忆和按用户分析
});

client.on('stateChange', (state) => {
  console.log('Agent state:', state.agentState);
});

client.on('message', (message) => {
  console.log(message.type, message.content);
});

client.on('botReady', () => {
  client.sendUserTextMessage('Hello!');
});

try {
  await client.connect();
} catch (error) {
  console.error('Connect failed:', error);
}
```

{% endcode %}

`connect()` 需要 `characterId` 以及二者之一 `apiKey` 或 `authToken`。没有它们会抛出 `apiKey 或 authToken 至少需要其一，且 characterId 是必需的`。你也可以省略构造函数参数，并将配置传递给 `connect(config)` 改为。

设置 `enableVideo: true` 以打开支持摄像头和屏幕共享的视频连接。使用默认 `false`时，连接仅为音频。

{% hint style="danger" %}
客户端代码中的 API 密钥对任何打开该页面的人都是可读的。对于公开页面，请在服务器上创建一个短期有效的认证令牌，并传递 `authToken` 而不是。参见 [使用认证令牌连接](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/auth-tokens.md).
{% endhint %}

### 播放角色的音频

聊天小部件会替你播放角色的声音。如果你在默认 WebRTC 传输上构建自己的 UI，请创建一个 `AudioRenderer` 用于客户端房间的对象。没有它，角色的音频永远不会附加到页面。

```typescript
import { AudioRenderer } from '@convai/web-sdk/vanilla';

client.on('connect', () => {
  const audioRenderer = new AudioRenderer(client.room);
  // 在你拆除会话时调用 audioRenderer.destroy()。
});
```

参见 [在 TypeScript 中构建自定义 UI](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/building-a-custom-ui-typescript.md) 以获取完整模式，包括 WebSocket 传输。

### 添加聊天小部件

`createConvaiWidget(container, options)` 将现成的聊天和语音 UI 挂载到一个 DOM 元素中，并返回一个小部件句柄。小部件会在首次点击时连接客户端，并在断开连接后再次打开时使用 `reconnect()` 。

```typescript
import { ConvaiClient } from '@convai/web-sdk/vanilla';
import { createConvaiWidget } from '@convai/web-widget/vanilla';

const client = new ConvaiClient({
  apiKey: 'YOUR_API_KEY',
  characterId: 'YOUR_CHARACTER_ID',
  enableVideo: true,
});

const widget = createConvaiWidget(document.body, {
  convaiClient: client,
  showVideo: true,
  showScreenShare: true,
});

// 当你移除小部件时：
widget.destroy(); // 或 destroyConvaiWidget(widget)
```

传入一个现有的 `convaiClient`，或传入凭据和角色 ID，以便小部件自行创建客户端。两者都没有时， `createConvaiWidget` 会抛出 `必须提供 convaiClient，或提供 (apiKey 或 authToken) 和 characterId`.

| 选项                                   | 类型                               | 默认值     | 描述                                |
| ------------------------------------ | -------------------------------- | ------- | --------------------------------- |
| `convaiClient`                       | `ConvaiClient`                   | 无       | 小部件所驱动的客户端。                       |
| `apiKey`, `authToken`, `characterId` | `string`                         | 无       | 仅在 `convaiClient` 被省略时使用，用于创建客户端。 |
| `enableVideo`, `startWithVideoOn`    | `boolean`                        | `false` | 传递给小部件创建的客户端。                     |
| `enableLipsync`, `enableEmotion`     | `boolean`                        | `false` | 传递给小部件创建的客户端。                     |
| `blendshapeConfig`                   | `对象`                             | 无       | 传递给小部件创建的客户端。                     |
| `showVideo`                          | `boolean`                        | `true`  | 在设置中显示摄像头切换。仅适用于视频连接。             |
| `showScreenShare`                    | `boolean`                        | `true`  | 在设置中显示屏幕共享切换。仅适用于视频连接。            |
| `defaultVoiceMode`                   | `boolean`                        | `true`  | 以语音模式打开小部件。                       |
| `onConnect`                          | `() => void`                     | 无       | 在客户端连接后调用。                        |
| `onDisconnect`                       | `() => void`                     | 无       | 在客户端断开连接后调用。                      |
| `onMessage`                          | `(message: ChatMessage) => void` | 无       | 随最新聊天消息一起调用。                      |

当小部件自行创建客户端时，只会转发表中的选项。要设置任何其他 `ConvaiConfig` 字段，请自行创建客户端并将其传入为 `convaiClient`.

返回的句柄公开 `element` （小部件的根元素）， `client`，以及 `destroy()`.

### 验证连接

加载页面，然后打开小部件或调用 `connect()`。该 `stateChange` 处理程序日志 `已连接` 一旦会话建立，角色会在 `botReady` 触发时。

### 后续步骤

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>ConvaiClient 参考文档</strong><br>客户端的每个属性、方法和控制接口。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/convaiclient-core-api.md">ConvaiClient 参考</a></td></tr><tr><td><strong>在 TypeScript 中处理事件和消息</strong><br>订阅状态、消息和转录，并渲染对话。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/events-and-message-handling.md">在 TypeScript 中处理事件和消息</a></td></tr><tr><td><strong>在原生 TypeScript 中添加口型同步</strong><br>在 three.js 角色上播放流式 blendshape 帧。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/real-time-lipsync.md">在原生 TypeScript 中添加口型同步</a></td></tr><tr><td><strong>在 TypeScript 中构建自定义 UI</strong><br>连接你自己的聊天界面、音频播放和媒体控制。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/building-a-custom-ui-typescript.md">在 TypeScript 中构建自定义 UI</a></td></tr><tr><td><strong>配置与类型参考</strong><br>每个配置字段、状态字段以及导出的入口点。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/best-practices-and-type-definitions.md">配置和类型参考</a></td></tr><tr><td><strong>Blendshape 通道顺序参考</strong><br>ARKit 和 MetaHuman blendshape 帧的通道顺序。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/mappings-reference.md">Blendshape 声道顺序参考</a></td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
