@tbox-dev-js/sdk 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1180,6 +1180,10 @@ let KnowledgeClient$1 = class KnowledgeClient {
1180
1180
 
1181
1181
  /**
1182
1182
  * 百宝箱插件服务 SDK - 底层 HTTP 请求封装
1183
+ *
1184
+ * 支持两种鉴权模式:
1185
+ * - B端:Authorization header(API Key)
1186
+ * - C端:TBOXSESSIONID + X-Tbox-Channel + X-Tbox-AppId headers
1183
1187
  */
1184
1188
  /** 默认调用域名 */
1185
1189
  const DEFAULT_BASE_URL = 'https://o.tbox.cn';
@@ -1199,25 +1203,53 @@ function normalizeResponse(raw) {
1199
1203
  }
1200
1204
  /**
1201
1205
  * 底层 HTTP 客户端
1206
+ *
1207
+ * 支持两种构造方式:
1208
+ * - 新版:传入 HttpClientConfig(含 AuthMode)
1209
+ * - 旧版:传入 LegacyHttpClientConfig(含 apiKey,向后兼容)
1202
1210
  */
1203
1211
  class HttpClient {
1204
1212
  constructor(config) {
1205
- this.baseUrl = config.baseUrl.replace(/\/$/, '');
1206
- this.apiKey = config.apiKey;
1213
+ this._baseUrl = config.baseUrl.replace(/\/$/, '');
1207
1214
  this.timeout = config.timeout;
1215
+ if ('auth' in config) {
1216
+ this.auth = config.auth;
1217
+ }
1218
+ else {
1219
+ this.auth = { type: 'apiKey', apiKey: config.apiKey };
1220
+ }
1221
+ }
1222
+ /** 获取 base URL */
1223
+ get baseUrl() {
1224
+ return this._baseUrl;
1225
+ }
1226
+ /** 获取鉴权请求头(供外部流式请求等场景使用) */
1227
+ getAuthHeaders() {
1228
+ return this.buildAuthHeaders();
1229
+ }
1230
+ /** 构建鉴权相关的请求头 */
1231
+ buildAuthHeaders() {
1232
+ if (this.auth.type === 'session') {
1233
+ return {
1234
+ TBOXSESSIONID: this.auth.session.sessionId,
1235
+ 'X-Tbox-Channel': this.auth.session.channel,
1236
+ 'X-Tbox-AppId': this.auth.session.appId,
1237
+ };
1238
+ }
1239
+ return { Authorization: this.auth.apiKey };
1208
1240
  }
1209
1241
  /** 构建通用请求头 */
1210
1242
  buildHeaders(extra) {
1211
1243
  return {
1212
1244
  'Content-Type': 'application/json;charset=UTF-8',
1213
- Authorization: this.apiKey,
1245
+ ...this.buildAuthHeaders(),
1214
1246
  ...extra,
1215
1247
  };
1216
1248
  }
1217
1249
  /** 构建 FormData 请求头(不设置 Content-Type,让浏览器自动处理 boundary) */
1218
1250
  buildHeadersForFormData(extra) {
1219
1251
  return {
1220
- Authorization: this.apiKey,
1252
+ ...this.buildAuthHeaders(),
1221
1253
  ...extra,
1222
1254
  };
1223
1255
  }
@@ -1309,7 +1341,7 @@ class HttpClient {
1309
1341
  base = path;
1310
1342
  }
1311
1343
  else {
1312
- base = `${this.baseUrl}${path}`;
1344
+ base = `${this._baseUrl}${path}`;
1313
1345
  }
1314
1346
  if (!queryParams || Object.keys(queryParams).length === 0) {
1315
1347
  return base;
@@ -1319,18 +1351,36 @@ class HttpClient {
1319
1351
  }
1320
1352
  /** 解析响应体 */
1321
1353
  async parseResponse(response) {
1322
- if (!response.ok) {
1354
+ let text;
1355
+ try {
1356
+ const buffer = await response.arrayBuffer();
1357
+ text = new TextDecoder('utf-8').decode(buffer);
1358
+ }
1359
+ catch {
1323
1360
  return {
1324
1361
  success: false,
1325
1362
  errorCode: `HTTP_${response.status}`,
1326
1363
  errorMsg: `HTTP error: ${response.status} ${response.statusText}`,
1327
1364
  };
1328
1365
  }
1366
+ // 非 200 时也尝试解析响应体,提取服务端返回的真实错误信息
1367
+ if (!response.ok) {
1368
+ try {
1369
+ const errorJson = JSON.parse(text);
1370
+ const errorCode = errorJson.errorCode ?? errorJson.code ?? errorJson.resultCode ?? `HTTP_${response.status}`;
1371
+ const errorMsg = errorJson.errorMsg ?? errorJson.msg ?? errorJson.resultDesc ?? `HTTP error: ${response.status} ${response.statusText}`;
1372
+ return { success: false, errorCode, errorMsg };
1373
+ }
1374
+ catch {
1375
+ return {
1376
+ success: false,
1377
+ errorCode: `HTTP_${response.status}`,
1378
+ errorMsg: `HTTP error: ${response.status} ${response.statusText}`,
1379
+ };
1380
+ }
1381
+ }
1329
1382
  let json;
1330
1383
  try {
1331
- // 使用 arrayBuffer + TextDecoder 确保多字节 UTF-8 字符(如中文)正确解码
1332
- const buffer = await response.arrayBuffer();
1333
- const text = new TextDecoder('utf-8').decode(buffer);
1334
1384
  json = JSON.parse(text);
1335
1385
  }
1336
1386
  catch {
@@ -1350,7 +1400,7 @@ class HttpClient {
1350
1400
  * 封装 /openapi/v1/plugin 下的全部接口
1351
1401
  */
1352
1402
  /** API 路径前缀 */
1353
- const API_PREFIX$4 = '/openapi/v1/plugin';
1403
+ const API_PREFIX$5 = '/openapi/v1/plugin';
1354
1404
  /**
1355
1405
  * 百宝箱插件服务客户端
1356
1406
  *
@@ -1392,7 +1442,7 @@ class TboxPluginClient {
1392
1442
  * ```
1393
1443
  */
1394
1444
  async doTts(request) {
1395
- return this.http.post(`${API_PREFIX$4}/doTts`, request);
1445
+ return this.http.post(`${API_PREFIX$5}/doTts`, request);
1396
1446
  }
1397
1447
  // ============================================================
1398
1448
  // ASR - 语音转文字
@@ -1414,7 +1464,7 @@ class TboxPluginClient {
1414
1464
  * ```
1415
1465
  */
1416
1466
  async asrBase64(request) {
1417
- return this.http.post(`${API_PREFIX$4}/asrBase64V2`, request);
1467
+ return this.http.post(`${API_PREFIX$5}/asrBase64V2`, request);
1418
1468
  }
1419
1469
  // ============================================================
1420
1470
  // 插件工具执行
@@ -1441,7 +1491,7 @@ class TboxPluginClient {
1441
1491
  * ```
1442
1492
  */
1443
1493
  async run(pluginToolId, request) {
1444
- return this.http.post(`${API_PREFIX$4}/run/${encodeURIComponent(pluginToolId)}`, request);
1494
+ return this.http.post(`${API_PREFIX$5}/run/${encodeURIComponent(pluginToolId)}`, request);
1445
1495
  }
1446
1496
  // ============================================================
1447
1497
  // 插件信息查询
@@ -1463,7 +1513,7 @@ class TboxPluginClient {
1463
1513
  * ```
1464
1514
  */
1465
1515
  async getPluginInfo(pluginId) {
1466
- return this.http.get(`${API_PREFIX$4}/info/${encodeURIComponent(pluginId)}`);
1516
+ return this.http.get(`${API_PREFIX$5}/info/${encodeURIComponent(pluginId)}`);
1467
1517
  }
1468
1518
  /**
1469
1519
  * 网络搜索
@@ -1522,7 +1572,7 @@ TboxPluginClient.WEB_SEARCH_TOOL_ID = '20240611204600000001';
1522
1572
  * 封装 /openapi/v1/conversation 下的全部接口
1523
1573
  */
1524
1574
  /** API 路径前缀 */
1525
- const API_PREFIX$3 = '/openapi/v1/conversation';
1575
+ const API_PREFIX$4 = '/openapi/v1/conversation';
1526
1576
  /**
1527
1577
  * 百宝箱会话管理客户端
1528
1578
  *
@@ -1570,7 +1620,7 @@ class TboxConversationClient {
1570
1620
  * ```
1571
1621
  */
1572
1622
  async createConversation(request) {
1573
- return this.http.post(`${API_PREFIX$3}/create`, request);
1623
+ return this.http.post(`${API_PREFIX$4}/create`, request);
1574
1624
  }
1575
1625
  /**
1576
1626
  * 查询会话列表(分页)
@@ -1594,7 +1644,7 @@ class TboxConversationClient {
1594
1644
  * ```
1595
1645
  */
1596
1646
  async listConversations(request) {
1597
- return this.http.post(`${API_PREFIX$3}/list`, request);
1647
+ return this.http.post(`${API_PREFIX$4}/list`, request);
1598
1648
  }
1599
1649
  // ============================================================
1600
1650
  // 消息管理
@@ -1620,7 +1670,7 @@ class TboxConversationClient {
1620
1670
  * ```
1621
1671
  */
1622
1672
  async listMessages(request) {
1623
- return this.http.post(`${API_PREFIX$3}/message/list`, request);
1673
+ return this.http.post(`${API_PREFIX$4}/message/list`, request);
1624
1674
  }
1625
1675
  /**
1626
1676
  * 新增会话消息
@@ -1645,7 +1695,7 @@ class TboxConversationClient {
1645
1695
  * ```
1646
1696
  */
1647
1697
  async saveMessage(request) {
1648
- return this.http.post(`${API_PREFIX$3}/message/save`, request);
1698
+ return this.http.post(`${API_PREFIX$4}/message/save`, request);
1649
1699
  }
1650
1700
  }
1651
1701
 
@@ -1703,6 +1753,116 @@ class TboxAppClient {
1703
1753
  }
1704
1754
  }
1705
1755
 
1756
+ /**
1757
+ * 百宝箱首页开场白 SDK - HomepageClient 核心类
1758
+ *
1759
+ * 封装 /agent/v1/homepage 下的接口。
1760
+ * 该接口走 C端鉴权(TBOXSESSIONID + X-Tbox-Channel + X-Tbox-AppId)。
1761
+ */
1762
+ /** API 路径前缀 */
1763
+ const API_PREFIX$3 = '/agent/v1/homepage';
1764
+ /**
1765
+ * 百宝箱首页开场白客户端(C端鉴权)
1766
+ *
1767
+ * @example
1768
+ * ```ts
1769
+ * import { TboxHomepageClient } from '@tbox-dev-js/sdk';
1770
+ *
1771
+ * // 方式一:自动获取 session(推荐)
1772
+ * const client = await TboxHomepageClient.create({
1773
+ * apiKey: 'your-api-key',
1774
+ * appId: '202508APhciU03604644',
1775
+ * userId: 'user-123',
1776
+ * });
1777
+ *
1778
+ * // 方式二:手动传入 session
1779
+ * const client = new TboxHomepageClient({
1780
+ * session: { sessionId: 'xxx', channel: 'alipay_mini_app', appId: '202508APhciU03604644' },
1781
+ * });
1782
+ *
1783
+ * const result = await client.get({ agentId: '202508APhciU03604644' });
1784
+ * if (result.success) {
1785
+ * console.log('开场白:', result.data?.prologue);
1786
+ * }
1787
+ * ```
1788
+ */
1789
+ class TboxHomepageClient {
1790
+ /**
1791
+ * 使用 C端 Session 鉴权构造
1792
+ */
1793
+ constructor(config) {
1794
+ this.http = new HttpClient({
1795
+ baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
1796
+ auth: { type: 'session', session: config.session },
1797
+ timeout: config.timeout,
1798
+ });
1799
+ }
1800
+ /**
1801
+ * 便捷工厂方法:通过 B端 apiKey 自动获取 session 并创建 C端客户端
1802
+ *
1803
+ * 内部流程:
1804
+ * 1. 使用 apiKey 调用 TboxAppClient.generateSession() 获取 sessionId + channel
1805
+ * 2. 用获取到的 session 信息创建 C端鉴权的 HomepageClient
1806
+ *
1807
+ * @param options - 创建参数(apiKey、appId、userId)
1808
+ * @returns 已鉴权的 TboxHomepageClient 实例
1809
+ *
1810
+ * @example
1811
+ * ```ts
1812
+ * const client = await TboxHomepageClient.create({
1813
+ * apiKey: 'your-api-key',
1814
+ * appId: '202508APhciU03604644',
1815
+ * userId: 'user-123',
1816
+ * });
1817
+ * ```
1818
+ */
1819
+ static async create(options) {
1820
+ const appClient = new TboxAppClient({
1821
+ apiKey: options.apiKey,
1822
+ baseUrl: options.baseUrl,
1823
+ timeout: options.timeout,
1824
+ });
1825
+ const sessionResult = await appClient.generateSession({
1826
+ appId: options.appId,
1827
+ userId: options.userId,
1828
+ });
1829
+ if (!sessionResult.success || !sessionResult.data?.sessionId || !sessionResult.data?.channel) {
1830
+ throw new Error(`Failed to generate session: ${sessionResult.errorCode ?? 'UNKNOWN'} - ${sessionResult.errorMsg ?? 'No session data returned'}`);
1831
+ }
1832
+ return new TboxHomepageClient({
1833
+ session: {
1834
+ sessionId: sessionResult.data.sessionId,
1835
+ channel: sessionResult.data.channel,
1836
+ appId: options.appId,
1837
+ },
1838
+ baseUrl: options.baseUrl,
1839
+ timeout: options.timeout,
1840
+ });
1841
+ }
1842
+ /**
1843
+ * 获取首页开场白
1844
+ *
1845
+ * POST /agent/v1/homepage/get
1846
+ *
1847
+ * @param request - 请求参数,agentId 为必填
1848
+ * @returns 开场白信息,包含开场白文本、推荐问题等
1849
+ *
1850
+ * @example
1851
+ * ```ts
1852
+ * const res = await client.get({
1853
+ * agentId: '202508APhciU03604644',
1854
+ * extInfo: '{}',
1855
+ * });
1856
+ * if (res.success) {
1857
+ * console.log(res.data?.prologue);
1858
+ * }
1859
+ * ```
1860
+ */
1861
+ async get(request) {
1862
+ return this.http.post(`${API_PREFIX$3}/get`, request);
1863
+ }
1864
+ }
1865
+
1706
1866
  /**
1707
1867
  * 高德地图 SDK - AmapClient 核心类
1708
1868
  *
@@ -2834,12 +2994,12 @@ class LlmClient {
2834
2994
  * 流式调用 Chat Completions
2835
2995
  */
2836
2996
  async *streamChatCompletions(request) {
2837
- const url = `${this.http['baseUrl']}${API_PREFIX}/chat/completions`;
2997
+ const url = `${this.http.baseUrl}${API_PREFIX}/chat/completions`;
2838
2998
  const response = await fetch(url, {
2839
2999
  method: 'POST',
2840
3000
  headers: {
2841
3001
  'Content-Type': 'application/json;charset=UTF-8',
2842
- Authorization: this.http['apiKey'],
3002
+ ...this.http.getAuthHeaders(),
2843
3003
  },
2844
3004
  body: JSON.stringify(request),
2845
3005
  });
@@ -2975,6 +3135,7 @@ exports.TboxAPI = TboxAPI;
2975
3135
  exports.TboxAppClient = TboxAppClient;
2976
3136
  exports.TboxConversationClient = TboxConversationClient;
2977
3137
  exports.TboxError = TboxError;
3138
+ exports.TboxHomepageClient = TboxHomepageClient;
2978
3139
  exports.TboxPluginClient = TboxPluginClient;
2979
3140
  exports.TimeoutError = TimeoutError;
2980
3141
  exports.knowledgeSchema = knowledgeSchema;