> 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/dong-tai-shang-xia-wen.md).

# 动态上下文

### 连接时的动态上下文

通过以下方式连接时传递初始上下文 `dynamicInfo`:

```ts
client.connect({
  apiKey: '...',
  characterId: '...',
  dynamicInfo: '玩家：Aria，等级：5，当前区域：Eldenmere Forest',
});
```

默认情况下，此上下文是可变的，并且可在会话期间被替换。若要将其锁定为静态系统提示：

```ts
{
  dynamicInfo: '游戏规则：已禁用 PvP。经济：通胀模式。',
  keepInContext: true, // 作为会话中的固定提示持久保留
}
```

***

### `updateContext`

用于会话中途更新上下文的主要方法。支持追加、替换和重置模式。

```ts
client.updateContext(options: ContextUpdateOptions)
```

#### 选项

| 字段                         | 类型                                 | 默认         | 描述                                            |
| -------------------------- | ---------------------------------- | ---------- | --------------------------------------------- |
| `文本`                       | `string`                           | —          | 要注入的上下文文本。除非以下情况，否则必填 `mode` 是 `"reset"`      |
| `mode`                     | `"append" \| "replace" \| "reset"` | `"append"` | 如何应用上下文                                       |
| `run_llm`                  | `"true" \| "false" \| "auto"`      | `"auto"`   | 是否触发机器人回复                                     |
| `current_attention_object` | `string`                           | —          | 机器人应关注的对象（必须匹配 `actionConfig.objects[].name`) |

#### 模式

**`append`** — 添加到现有的临时上下文：

```ts
client.updateContext({
  text: '用户刚刚捡起了魔法剑。',
  mode: 'append',
  run_llm: 'false', // 静默更新，不触发机器人回复
});
```

**`replace`** — 替换整个临时上下文：

```ts
client.updateContext({
  text: '游戏状态：等级 10，Boss 战已开始。',
  mode: 'replace',
  run_llm: 'auto', // 让服务器决定是否回复
});
```

**`reset`** — 完全清除临时上下文：

```ts
client.updateContext({ mode: 'reset' });
```

#### 触发机器人回复

```ts
// 始终回复
client.updateContext({
  text: '一位新的挑战者出现了。',
  run_llm: 'true',
});

// 从不回复（静默上下文更新）
client.updateContext({
  text: '用户生命值：10/100',
  run_llm: 'false',
});

// 由服务器决定（默认）
client.updateContext({
  text: '天气变为暴风雨。',
  run_llm: 'auto',
});
```

#### 通过以下方式监控 token 使用量 `serverResponse`

服务器会在每次之后返回 token 数量 `context-update`:

```ts
client.on('serverResponse', (response) => {
  if (response.event_type === 'context-update' && response.status === 'success') {
    const { remaining_tokens, max_tokens } = response.extras ?? {};
    console.log(`上下文 token：${max_tokens - remaining_tokens} / ${max_tokens}`);
  }
});
```

***

### `updateDynamicInfo`

一个更简单的版本， `updateContext` — 始终追加，且从不触发机器人回复。

```ts
client.updateDynamicInfo('玩家生命值降至 30%。');
```

等同于：

```ts
client.updateContext({ text: '...', mode: 'append', run_llm: 'false' });
```

使用 `updateContext` 用于完全控制； `updateDynamicInfo` 用于快速静默更新。

***

### 模板键

模板键会替换角色系统提示中的占位符。适合个性化在 Convai 仪表板中配置的提示。

如果仪表板提示中包含 `{{player_name}}`:

```ts
client.updateTemplateKeys({
  player_name: 'Aria',
  current_quest: '寻找失落的遗物',
});
```

角色将在其回复中使用 `Aria` 和 `寻找失落的遗物` 。

***

### 文件上传

在活动会话期间，使用以下方式直接向角色发送文件 `uploadFile`。角色会将该文件作为对话上下文的一部分接收，并能根据其内容进行回复。

```ts
await client.uploadFile(file, {
  onProgress: (pct) => console.log(`${pct}% 已上传`),
});
```

#### React

```tsx
const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
  const file = e.target.files?.[0];
  if (!file) return;

  await client.uploadFile(file, {
    onProgress: (pct) => setProgress(pct),
  });
};
```

#### 原生 JS

```ts
document.querySelector('#file-input').addEventListener('change', async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (!file) return;

  await client.uploadFile(file, {
    onProgress: (pct) => progressBar.style.width = `${pct}%`,
  });
});
```

#### 选项

| 字段           | 类型                      | 默认              | 描述                   |
| ------------ | ----------------------- | --------------- | -------------------- |
| `主题`         | `string`                | `"file-upload"` | 上传通道的路由标识符           |
| `onProgress` | `(pct: number) => void` | —               | 上传进度回调，参数为 0–100 的整数 |

#### 支持的格式

| 格式   | MIME 类型      |
| ---- | ------------ |
| JPEG | `image/jpeg` |
| PNG  | `image/png`  |
| GIF  | `image/gif`  |
| WebP | `image/webp` |

最大文件大小： **10 MB**。文件以原始二进制形式发送——不是 base64 编码。

#### 错误处理

`uploadFile` 是异步的，且失败时会抛出异常——请始终将其包裹在 try/catch 中：

```ts
try {
  await client.uploadFile(file, { onProgress: setProgress });
} catch (err) {
  // 常见原因：
  // - 未连接（传输尚未就绪）
  // - 文件类型不受支持（仅支持 JPEG、PNG、GIF、WebP）
  // - 文件超过 10 MB
  // - 传输中途发生网络错误
  console.error('上传失败：', err);
}
```

在调用前验证类型和大小，以便为用户提供快速的本地错误，而不是等待传输失败：

```ts
const SUPPORTED = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

if (!SUPPORTED.includes(file.type)) throw new Error(`不支持的类型：${file.type}`);
if (file.size > 10 * 1024 * 1024) throw new Error('文件超过 10 MB');

await client.uploadFile(file, { onProgress: setProgress });
```

#### 备注

* 仅在使用 WebRTC 传输（`transport: "livekit"`，默认）连接时可用。不支持 WebSocket 传输。
* 如果在未连接时调用，该方法会抛出异常。先检查 `client.state.isConnected` 。

***

### 场景元数据

使用 `updateSceneMetadata` 用于描述环境变化。这不会 **不** 添加新的动作目标——它只为机器人提供叙事上下文。

```ts
client.updateSceneMetadata([
  { name: 'fog', description: '一层浓雾笼罩，能见度很低。' },
  { name: 'ambience', description: '远处的雷声和风声。' },
]);
```

如果机器人需要 *作用于* 场景中的对象，它们必须在 `actionConfig.objects` 连接时声明。参见 Actions。

***

### 会话管理

#### 重置对话

`resetSession()` 会清除消息历史并开始新的对话线程。角色会忘记当前交流，但会保留任何长期记忆（如果 `endUserId` 已设置）。

```ts
await client.disconnect();
client.resetSession();
await client.connect();
```

#### 空闲超时

服务器会在可配置的超时后断开空闲会话。可在 `resetIdleTimer()` 任意用户交互时调用，以保持会话存活。

```ts
// 在点击、按键或任何用户活动时调用
document.addEventListener('click', () => {
  if (client.state.isConnected) {
    client.resetIdleTimer();
  }
});

// 在断开连接前监听警告
client.on('idleWarning', ({ remainingSeconds }) => {
  showBanner(`会话将在 ${remainingSeconds} 秒后过期 — 点击继续`);
});
```

***

### 长期记忆

当 `endUserId` 提供时，角色会在不同会话之间构建持久记忆。可通过以下方式访问它们： `client.memoryManager`.

```ts
const client = useConvaiClient({
  apiKey: '...',
  characterId: '...',
  endUserId: 'user-uuid 或任意唯一用户 ID', // 启用记忆
});

// 连接后：
const memory = client.memoryManager;

if (memory) {
  // 列出记忆
  const { memories, total_count } = await memory.listMemories({ page: 1, pageSize: 20 });

  // 手动添加一条记忆
  await memory.addMemories(['用户是一名偏好 TypeScript 的软件工程师。']);

  // 删除特定记忆
  await memory.deleteMemory(memories[0].id);
}
```

完整参考请参见 Memory API。


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/dong-tai-shang-xia-wen.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
