@tbox-dev-js/sdk
v0.1.33
Published
百宝箱平台 JavaScript SDK — 知识库、插件、会话等服务的统一客户端
Maintainers
Readme
@tbox-dev-js/sdk
百宝箱(Tbox)平台 JavaScript/TypeScript SDK,为商户提供一站式 AI 应用服务接入能力。
特性
- 🔐 双鉴权链路 — B端(API Key)和 C端(Session 授权码)两种鉴权模式
- 🤖 LLM 对话 — OpenAI 兼容的 Chat Completions,支持流式输出
- 📚 知识库检索 — 语义检索 + 配置文件驱动的多知识库管理
- 🗄️ 数据库访问 — 基于 Superbase 数据链路的轻量 CRUD 客户端,配置文件驱动
- 🔌 插件工具 — TTS、ASR、网络搜索、自定义插件执行
- 💬 会话管理 — 会话创建、消息保存与查询
- 🗺️ 高德地图 — 天气、地理编码、路线规划等 13 项地图服务
- 🎙️ C端多媒体 — TTS 语音合成(WebSocket)、ASR 语音识别、文件上传、消息反馈
- 📦 双格式输出 — ESM + CJS 双格式,完整 TypeScript 类型
- 🌐 多端适配 — 支持 H5、小程序(Taro/uni-app/原生 wx)、Node.js,通过
setFetcher注入自定义请求实现
安装
npm install @tbox-dev-js/sdk鉴权说明
SDK 涉及三个角色:
| 角色 | 说明 | 持有凭证 | |------|------|---------| | 商户 Server | 后端服务 | API Key(从百宝箱平台开发网关后台获取) | | 商户 Client | 前端应用 | C端授权码(sessionId + channel) | | 百宝箱平台 | Tbox 网关 | 颁发凭证 |
B端鉴权(商户 Server → 百宝箱平台)
商户 Server 通过 API Key 直接调用百宝箱平台,请求头携带 Authorization: <apiKey>。
适用客户端:TboxPluginClient、TboxConversationClient、TboxAppClient、LlmClient、AmapClient、TboxKnowledgeClient
C端鉴权(商户 Client → 商户 Server → 百宝箱平台)
商户 Client 先通过商户 Server 获取百宝箱平台颁发的授权码,再直接调用百宝箱平台。
商户 Client → 商户 Server → TboxAppClient.generateSession(apiKey)
↓
百宝箱平台颁发 sessionId + channel
↓
商户 Client ← 返回授权码 ← 商户 Server
↓
商户 Client → 百宝箱平台(TBOXSESSIONID + X-Tbox-Channel + X-Tbox-AppId)适用客户端:TboxHomepageClient
⚠️ API Key 仅在商户 Server 侧使用,禁止暴露给前端。
多端适配
SDK 的 C 端客户端(TboxHomepageClient、TboxFeedbackClient、TboxUploadClient、TboxAsrClient)默认使用浏览器原生 fetch 发起请求。在小程序环境中没有全局 fetch,需要通过 setFetcher 注入自定义请求实现。
H5 / Node.js: 无需任何配置,自动使用原生 fetch。
小程序环境: 在使用任何 C 端客户端之前,调用 setFetcher 注册请求函数:
import Taro from '@tarojs/taro';
import { setFetcher } from '@tbox-dev-js/sdk';
setFetcher((url, init) => {
return new Promise((resolve, reject) => {
Taro.request({
url,
method: (init?.method as any) || 'GET',
header: init?.headers,
data: init?.body,
success: (res) => {
resolve({
ok: res.statusCode >= 200 && res.statusCode < 300,
status: res.statusCode,
statusText: String(res.statusCode),
headers: { get: (name) => res.header?.[name] ?? null },
json: async () => res.data,
text: async () =>
typeof res.data === 'string' ? res.data : JSON.stringify(res.data),
arrayBuffer: async () => res.data as ArrayBuffer,
});
},
fail: (err) => reject(new Error(err.errMsg)),
});
});
});只需实现 SDK 实际使用的接口子集(
FetcherInit/FetcherResponse),无需完整模拟浏览器fetch。小程序环境若缺少AbortController,SDK 会自动降级为无超时控制,不会报错。
适配范围: 仅 C 端客户端(基于 HttpClient)。B 端客户端(TboxPluginClient、KnowledgeClient 等基于 APIClient)仅在 Server 层使用,不需要适配。
快速开始
LLM 大模型对话
当前支持的模型:qwen3.6-plus、qwen3.5-plus、MiniMax-M2.5、glm-5.1、glm-5v-turbo、glm-5-turbo、glm-5、kimi-k2.5
import { LlmClient, SUPPORTED_MODELS } from '@tbox-dev-js/sdk';
const llm = new LlmClient({ apiKey: 'your-api-key' });
// 简化调用
const answer = await llm.chat('kimi-k2.5', [
{ role: 'user', content: '你好,请介绍一下你自己' },
]);
console.log(answer);
// 流式调用
const stream = await llm.chatCompletions({
model: 'kimi-k2.5',
messages: [{ role: 'user', content: '你好' }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
}知识库检索
import { TboxKnowledgeClient } from '@tbox-dev-js/sdk';
// 自动从【项目根目录】下的 config/knowledge.json 加载配置
const knowledge = new TboxKnowledgeClient({ apiKey: 'your-api-key' });
// 按名称检索
const result = await knowledge.retrieveByName('alipay-doc', '福州有哪些景点?');
if (result.success) {
for (const item of result.data) {
console.log(`[${item.score.toFixed(2)}] ${item.content}`);
}
}
// 查看知识库 schema
const schema = knowledge.getSchema('alipay-doc');
console.log(schema?.columns.map(c => `${c.name}: ${c.description}`));
// 直接指定 datasetId 检索
const knowledge2 = new TboxKnowledgeClient({
apiKey: 'your-api-key',
datasetId: 'your-dataset-id',
});
const result2 = await knowledge2.retrieve('退款政策是什么?');数据库访问(Nexbase)
基于百宝箱 BFF 代理 + Superbase 数据链路的轻量数据库访问客户端,提供 insert / select / update / delete 四个语义化 CRUD 方法以及原始 SQL 执行能力。请求统一通过 https://o.tbox.cn/openapi/v1/integration/bff/nexbase/api/v1/zdas/executeSql 转发,仅需 X-Superbase-Auth-Token 鉴权。详细文档参见 docs/nexbase-client.md。
import { NexbaseClient } from '@tbox-dev-js/sdk';
// 自动从【项目根目录】下的 config/nexbase.json 加载配置
const db = new NexbaseClient();
// 插入
await db.insert('users', { name: 'Alice', age: 20 });
// 查询
const list = await db.select('users', {
columns: ['id', 'name'],
where: { age: 20 },
orderBy: 'id DESC',
limit: 10,
});
// 更新(强制要求 where,避免误全表更新)
await db.update('users', { age: 21 }, { id: 1 });
// 删除(强制要求 where,避免误全表删除)
await db.delete('users', { id: 1 });
// 原始 SQL(复杂查询场景)
const stats = await db.executeSql(
'SELECT status, COUNT(*) AS cnt FROM users GROUP BY status'
);插件工具执行
import { TboxPluginClient } from '@tbox-dev-js/sdk';
const plugin = new TboxPluginClient({ apiKey: 'your-api-key' });
// 按工具 ID 执行
const result = await plugin.run('tool-id-xxx', {
params: { city: '杭州' },
});
// 按工具名称执行(通过插件 ID + 工具名称定位)
const sqlResult = await plugin.runByToolName(
'202604290lNB08558454', // pluginId
'execute_sql', // toolName
{
project_id: 'project_3e2df4eb7b0b4f8b',
sql: 'SELECT * FROM users LIMIT 10',
user_identity: 'zhangsan',
},
);
// TTS 文字转语音
const tts = await plugin.doTts({ tts_text: '你好,世界' });
// ASR 语音转文字
const asr = await plugin.asrBase64({ base64_audio: '<base64-string>' });
// 网络搜索
const search = await plugin.webSearch({ q: '上海今天天气' });
if (search.success) {
for (const item of search.data?.items ?? []) {
console.log(item.title, item.url);
}
}会话管理
import { TboxConversationClient } from '@tbox-dev-js/sdk';
const conv = new TboxConversationClient({ apiKey: 'your-api-key' });
// 创建会话
const res = await conv.createConversation({
agentId: 'your-app-id',
userId: 'user-123',
});
const conversationId = res.data;
// 保存消息
await conv.saveMessage({
agentId: 'your-app-id',
conversationId,
query: '今天天气怎么样?',
answer: '今天杭州晴天,25°C。',
});
// 查询消息列表
const messages = await conv.listMessages({
agentId: 'your-app-id',
conversationId,
pageNo: 1,
pageSize: 20,
});高德地图
import { AmapClient } from '@tbox-dev-js/sdk';
const amap = new AmapClient({ apiKey: 'your-api-key' });
// 查询天气
const weather = await amap.weather({ city: '杭州市' });
if (weather.success) {
const w = weather.data?.lives?.[0];
console.log(`${w?.city} ${w?.weather} ${w?.temperature}℃`);
}
// 地址转经纬度
const geo = await amap.geocode({ address: '北京市朝阳区阜通东大街6号' });
// 步行路线规划
const route = await amap.walkingRoute({ origin: '116.481028,39.989643', destination: '116.434446,39.90816' });首页开场白(C端鉴权)
import { TboxHomepageClient } from '@tbox-dev-js/sdk';
// 方式一:便捷工厂(自动获取 session,仅限 Server 侧)
const client = await TboxHomepageClient.create({
apiKey: 'your-api-key',
appId: 'your-app-id',
userId: 'user-123',
});
// 方式二:手动传入 session(适用于前端)
const client2 = new TboxHomepageClient({
session: { sessionId: 'xxx', channel: 'alipay_mini_app', appId: 'your-app-id' },
});
const result = await client.get({ agentId: 'your-agent-id' });
if (result.success) {
console.log('开场白:', result.data?.prologue);
console.log('推荐问题:', result.data?.suggestQuestions);
}C端语音识别(ASR)
import { TboxAsrClient } from '@tbox-dev-js/sdk';
// 便捷工厂(自动获取 session)
const asr = await TboxAsrClient.create({
apiKey: 'your-api-key',
appId: 'your-app-id',
userId: 'user-123',
});
const result = await asr.recognize({ base64Audio: '<base64-string>' });
if (result.success) {
console.log('识别结果:', result.data?.text);
}C端文件上传
import { TboxUploadClient } from '@tbox-dev-js/sdk';
const upload = await TboxUploadClient.create({
apiKey: 'your-api-key',
appId: 'your-app-id',
userId: 'user-123',
});
const result = await upload.upload({
file: yourBlob,
fileType: 'image',
fileName: 'photo.jpg',
});
if (result.success) {
console.log('文件 ID:', result.data?.fileId);
}C端消息反馈(点赞/点踩)
import { TboxFeedbackClient } from '@tbox-dev-js/sdk';
const feedback = await TboxFeedbackClient.create({
apiKey: 'your-api-key',
appId: 'your-app-id',
userId: 'user-123',
});
await feedback.addTag({
requestId: 'message-request-id',
feedback: 'LIKE', // 'LIKE' | 'DISLIKE' | 'CANCEL'
});C端 TTS 语音合成(WebSocket)
import { TboxTtsClient } from '@tbox-dev-js/sdk';
// 便捷工厂
const tts = await TboxTtsClient.create({
apiKey: 'your-api-key',
appId: 'your-app-id',
userId: 'user-123',
ttsAppkey: 'your-tts-appkey',
ttsAuthUrl: 'https://your-tts-auth-url',
});
// 获取鉴权信息
const auth = await tts.fetchAuth();
if (auth.success && auth.data) {
// 构建 WebSocket URL
const wsUrl = tts.buildUpstreamUrl(auth.data);
// 构建初始化 payload
const initPayload = TboxTtsClient.buildPayload();
// 构建文本 payload
const textPayload = TboxTtsClient.buildTextPayload('你好,世界');
// 构建停止 payload
const stopPayload = TboxTtsClient.buildStopPayload();
// 消费者自行管理 WebSocket 连接
// const ws = new WebSocket(wsUrl);
// ws.send(initPayload); ws.send(textPayload); ws.send(stopPayload);
}Session 生成(B→C 鉴权桥接)
import { TboxAppClient } from '@tbox-dev-js/sdk';
const app = new TboxAppClient({ apiKey: 'your-api-key' });
const result = await app.generateSession({
appId: 'your-app-id',
userId: 'user-123',
});
if (result.success) {
// 将 sessionId + channel 返回给前端
console.log('sessionId:', result.data?.sessionId);
console.log('channel:', result.data?.channel);
}配置文件
配置文件加载机制(统一规范)
SDK 中所有支持本地配置文件的客户端(目前为 TboxKnowledgeClient、NexbaseClient),都统一通过 src/node-utils.ts 提供的工具方法加载,以保证规则一致:
| 工具方法 | 说明 |
|---------|------|
| findProjectRoot(startDir?, marker?) | 定位代码库根目录。从 startDir(默认 process.cwd())向上遍历到文件系统根目录,返回最外层包含 marker(默认 package.json)的目录。与常见的 "find first" 实现不同,本方法返回最外层匹配,确保在 monorepo 子包中调用也能定位到真正的代码库根目录。 |
| loadJsonConfig<T>(filePath, rootDir?) | 读取并解析 JSON 配置文件。绝对路径直接使用;相对路径相对 rootDir(默认 findProjectRoot())解析。失败时静默返回 undefined,不抛异常。 |
| loadProjectConfig<T>(relativePath) | loadJsonConfig 的便捷封装,固定从代码库根目录加载。 |
统一规则:所有客户端的本地配置文件都从【项目根目录】下的 config/{clientName}.json 加载,例如:
TboxKnowledgeClient→<项目根目录>/config/knowledge.jsonNexbaseClient→<项目根目录>/config/nexbase.json- 后续新增的客户端也应遵循
<项目根目录>/config/{clientName}.json命名约定
默认行为:
- 配置文件不存在时静默跳过,不报错(不会影响客户端的构造,未传入必填字段时才会抛错)
- 在 monorepo 中,子包
cwd也会被解析到最外层package.json所在目录(即项目根目录)
自定义代码库根目录(按优先级从高到低):
- 构造参数
projectRoot:new NexbaseClient({ projectRoot: '/custom/path' }) - 环境变量
TBOX_PROJECT_ROOT:TBOX_PROJECT_ROOT=/workspace node app.js - 自动查找:从
process.cwd()向上找到最外层package.json所在目录
自定义配置文件路径(构造参数 config 字段):
// 字符串:相对于代码库根目录的路径
new TboxKnowledgeClient({ apiKey: 'xxx', config: 'configs/kb.json' });
// 字符串:绝对路径
new NexbaseClient({ config: '/etc/myapp/nexbase.json' });
// 对象:直接传入配置内容,跳过文件加载
new NexbaseClient({ config: { apiKey: 'xxx', projectId: 'yyy' } });新增需要本地配置的客户端时,请遵循同样规范:使用 loadJsonConfig / loadProjectConfig,避免自行实现 fs.readFileSync 逻辑。
知识库配置文件
TboxKnowledgeClient 自动从【项目根目录】下的 config/knowledge.json 加载知识库配置,格式如下:
{
"version": "1.0",
"defaults": {
"topK": 5,
"scoreThreshold": 0.5,
"updateMode": "UPSERT"
},
"knowledge_bases": {
"alipay-doc": {
"name": "alipay-doc",
"type": "STRUCTURED",
"datasetId": "your-dataset-id",
"documentId": "your-document-id",
"description": "景点数据知识库",
"schema": {
"name": "景点数据",
"description": "景点信息表",
"columns": [
{ "name": "title", "dataType": "STRING", "description": "景点名称", "primaryKey": true },
{ "name": "description", "dataType": "STRING", "description": "景点介绍" }
]
},
"retrieve_config": {
"topK": 3,
"scoreThreshold": 0.7
}
}
}
}参数优先级:方法参数 > 知识库 retrieve_config > 全局 defaults > 代码默认值
Nexbase 数据库配置文件
NexbaseClient 自动从【项目根目录】下的 config/nexbase.json 加载数据库访问配置,格式如下:
{
"version": "1.0",
"anonKey": "sb_your_anon_key",
"projectId": "your_project_id",
"databaseName": "your_database_name",
"baseUrl": "https://o.tbox.cn",
"timeout": 5000,
"debug": false,
"tables": {
"users": {
"name": "users",
"description": "用户表",
"primaryKey": "id",
"columns": [
{ "name": "id", "dataType": "BIGINT", "required": true },
{ "name": "name", "dataType": "VARCHAR(64)", "required": true },
{ "name": "age", "dataType": "INT" }
]
}
}
}字段说明:
| 字段 | 必填 | 说明 |
|------|------|------|
| anonKey | ✅ | Superbase anon_key,用于 X-Superbase-Auth-Token 鉴权。构造参数中对应字段为 apiKey |
| projectId | ✅ | 项目 ID(标识 Superbase 项目) |
| databaseName | — | 数据库名(作为请求体 dataBaseName 字段) |
| baseUrl | — | BFF 代理 base URL,默认 https://o.tbox.cn |
| timeout | — | 请求超时(毫秒,默认 5000) |
| debug | — | 调试日志开关 |
| tables | — | 表结构元信息(仅作上下文,运行时不强校验) |
优先级:构造参数 > 配置文件字段。完整文档参见 docs/nexbase-client.md。
API 参考
客户端一览
| 客户端 | 鉴权 | 说明 |
|--------|------|------|
| LlmClient | B端 | LLM 大模型对话(流式/非流式) |
| TboxKnowledgeClient | B端 | 知识库语义检索、列表查询、文档管理 |
| NexbaseClient | AnonKey(BFF 代理) | 数据库 CRUD(基于 Superbase 数据链路,走 BFF 代理 + AnonKey 鉴权) |
| TboxPluginClient | B端 | 插件工具执行、TTS、ASR、网络搜索 |
| TboxConversationClient | B端 | 会话创建、查询、消息保存 |
| TboxAppClient | B端 | Session 生成(B→C 鉴权桥接) |
| AmapClient | B端 | 高德地图(天气、地理编码、路线规划等) |
| TboxHomepageClient | C端 | 首页开场白获取 |
| TboxAsrClient | C端 | 语音识别(Base64 音频输入) |
| TboxUploadClient | C端 | 文件上传(图片/视频/音频) |
| TboxFeedbackClient | C端 | 消息反馈(点赞/点踩/取消) |
| TboxTtsClient | C端 | TTS 语音合成(WebSocket 模式) |
通用响应格式
所有 B端客户端方法返回统一的 SdkResponse<T> 结构:
interface SdkResponse<T> {
success: boolean;
data?: T;
errorCode?: string;
errorMsg?: string;
}LlmClient
支持的模型:
| 模型名称 | 说明 |
|---------|------|
| qwen3.6-plus | 通义千问 3.6 Plus |
| qwen3.5-plus | 通义千问 3.5 Plus |
| MiniMax-M2.5 | MiniMax M2.5 |
| glm-5.1 | 智谱 GLM 5.1 |
| glm-5v-turbo | 智谱 GLM 5V Turbo(多模态推理) |
| glm-5-turbo | 智谱 GLM 5 Turbo |
| glm-5 | 智谱 GLM 5 |
| kimi-k2.5 | Kimi K2.5 |
方法:
| 方法 | 说明 |
|------|------|
| chatCompletions(request) | Chat Completions(流式返回 AsyncIterable<ChatCompletionChunk>,非流式返回 ChatCompletionResponse) |
| chat(model, messages, options?) | 简化对话方法,自动处理流式输出,返回完整文本 |
导出常量:SUPPORTED_MODELS(模型名称数组)、SupportedModel(模型名称类型)
TboxKnowledgeClient
| 方法 | 说明 |
|------|------|
| retrieve(query, options?) | 语义检索(直接指定 datasetId) |
| retrieveByName(name, query, options?) | 按配置名称检索知识库 |
| list(request?) | 查询知识库列表 |
| create(request) | 创建知识库文档(上传文件) |
| update(request) | 更新知识库文档 |
| getSchema(name) | 获取知识库 schema |
| getKnowledgeBase(name) | 获取知识库配置条目 |
| listKnowledgeNames() | 列出所有已加载的知识库名称 |
| listKnowledgeSummaries() | 列出所有知识库摘要信息 |
NexbaseClient
基于百宝箱 BFF 代理 + Superbase 数据链路的数据库访问客户端,自动从【项目根目录】下的 config/nexbase.json 加载配置。仅需 X-Superbase-Auth-Token(即 AnonKey)鉴权,无需 Session。
| 方法 | 说明 |
|------|------|
| insert(table, data) | 插入一条记录 |
| select(table, options?) | 查询记录,支持 columns / where / orderBy / limit / offset |
| update(table, data, where) | 更新记录(强制 where 非空) |
| delete(table, where) | 删除记录(强制 where 非空) |
| executeSql(sql, traceId?) | 执行原始 SQL(用于 JOIN、聚合、子查询等复杂场景) |
| getTableSchema(name) | 获取配置文件中的表结构定义 |
| listTableNames() | 列出所有已配置的表名 |
安全特性:
- 表名/列名严格校验(
^[a-zA-Z_][a-zA-Z0-9_]*$),自动反引号包裹 - 字符串字面量自动转义单引号、反斜杠
update/delete强制要求where条件,避免误全表操作Date类型自动格式化为YYYY-MM-DD HH:mm:ss
返回格式:所有方法返回 NexbaseResult<T>,结构为 { success, code, data, message, traceId }。详见 docs/nexbase-client.md。
TboxPluginClient
| 方法 | 说明 |
|------|------|
| run(pluginToolId, request) | 按工具 ID 执行插件工具 |
| runByToolName(pluginId, toolName, params) | 按工具名称执行插件工具(在插件集合中按名称定位) |
| getPluginInfo(pluginId) | 查询插件配置信息(含工具集) |
| doTts(request) | 文字转语音 |
| asrBase64(request) | 语音转文字(Base64 音频输入) |
| webSearch(request) | 网络搜索(自动解包深层响应结构) |
TboxConversationClient
| 方法 | 说明 |
|------|------|
| createConversation(request) | 创建新会话 |
| listConversations(request) | 查询会话列表 |
| listMessages(request) | 查询消息列表 |
| saveMessage(request) | 保存消息 |
TboxAppClient
| 方法 | 说明 |
|------|------|
| generateSession(request) | 生成 C端授权码(sessionId + channel) |
AmapClient
| 方法 | 说明 |
|------|------|
| weather(request) | 天气查询(实况/预报) |
| geocode(request) | 地址转经纬度 |
| regeocode(request) | 经纬度转地址 |
| ipLocation(request) | IP 定位 |
| walkingRoute(request) | 步行路线规划 |
| cyclingRoute(request) | 骑行路线规划 |
| drivingRoute(request) | 驾车路线规划 |
| ebikeRoute(request) | 电动车路线规划 |
| transitRoute(request) | 公交路线规划 |
| peripheralSearch(request) | 周边搜索 |
| district(request) | 行政区域查询 |
| convert(request) | 坐标转换 |
| poiSearch(request) | POI 关键字搜索 |
TboxHomepageClient
| 方法 | 说明 |
|------|------|
| get(request) | 获取首页开场白 |
| static create(options) | 便捷工厂方法(自动获取 session) |
TboxAsrClient
| 方法 | 说明 |
|------|------|
| recognize(request) | C端语音识别(Base64 音频输入) |
| static create(options) | 便捷工厂方法(自动获取 session) |
TboxUploadClient
| 方法 | 说明 |
|------|------|
| upload(request) | C端文件上传(支持图片/视频/音频) |
| static create(options) | 便捷工厂方法(自动获取 session) |
TboxFeedbackClient
| 方法 | 说明 |
|------|------|
| addTag(request) | 消息反馈(LIKE / DISLIKE / CANCEL) |
| static create(options) | 便捷工厂方法(自动获取 session) |
TboxTtsClient
| 方法 | 说明 |
|------|------|
| fetchAuth() | 获取 TTS 鉴权信息(timestamp + digest) |
| buildUpstreamUrl(auth) | 构建上游 TTS WebSocket URL |
| static buildPayload(voiceConfig?) | 构建 WS 初始化 payload |
| static buildTextPayload(text) | 构建发送文本的 WS payload |
| static buildStopPayload() | 构建停止 TTS 流的 WS payload |
| static generateTaskId() | 生成 32 位十六进制任务 ID |
| static create(options) | 便捷工厂方法(自动获取 session) |
环境要求
- Node.js >= 16.0.0
- 浏览器:支持
fetchAPI 的现代浏览器 - 小程序:微信/支付宝等小程序环境(需通过
setFetcher注入请求实现) - 模块格式:ESM(
import)+ CJS(require)
License
See LEGAL.md
