super-agent-sdk 1.0.2 → 1.0.4
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/README.md +160 -54
- package/dist/index.cjs +4 -4
- package/dist/index.d.ts +53 -10
- package/dist/index.mjs +202 -172
- package/dist/widget.cjs +228 -29
- package/dist/widget.d.ts +65 -10
- package/dist/widget.mjs +1132 -667
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,8 @@ Super Agent Web SDK —— 为 `super-agent-service` 提供的一站式浏览器
|
|
|
15
15
|
9. [会话管理](#9-会话管理)
|
|
16
16
|
10. [中断恢复](#10-中断恢复)
|
|
17
17
|
11. [消息类型](#11-消息类型)
|
|
18
|
-
12. [
|
|
18
|
+
12. [Human-in-the-Loop](#12-human-in-the-loop)
|
|
19
|
+
13. [高级用法](#13-高级用法)
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
@@ -61,7 +62,11 @@ pnpm add react react-dom
|
|
|
61
62
|
import { createSuperAgent } from "super-agent-sdk";
|
|
62
63
|
import { mount } from "super-agent-sdk/widget";
|
|
63
64
|
|
|
64
|
-
const sdk = createSuperAgent({
|
|
65
|
+
const sdk = createSuperAgent({
|
|
66
|
+
baseUrl: "/api/v1",
|
|
67
|
+
botId: 1,
|
|
68
|
+
appId: "your_app_id",
|
|
69
|
+
});
|
|
65
70
|
// Token 自动获取,无需手动设置
|
|
66
71
|
const widget = mount("#chat", { sdk });
|
|
67
72
|
widget.open();
|
|
@@ -81,46 +86,46 @@ function createSuperAgent(config: SDKConfig): SuperAgentSDK;
|
|
|
81
86
|
export interface SDKConfig {
|
|
82
87
|
baseUrl: string; // e.g. "https://agent.example.com/api/v1"
|
|
83
88
|
botId: number; // bot ID
|
|
89
|
+
appId: string; // 应用密钥,用于换取 token
|
|
84
90
|
}
|
|
85
91
|
```
|
|
86
92
|
|
|
87
|
-
只需提供 `baseUrl` 与 `
|
|
93
|
+
只需提供 `baseUrl`、`botId` 与 `appId` 即可。SDK 不要求在创建时传入 `token`——组件挂载后会自动调用 `sdk.getToken()` 获取 token 并内部保存,无需手动设置。
|
|
88
94
|
|
|
89
95
|
```ts
|
|
90
96
|
const sdk = createSuperAgent({
|
|
91
97
|
baseUrl: "https://agent.example.com/api/v1",
|
|
92
98
|
botId: 1,
|
|
99
|
+
appId: "your_app_id",
|
|
93
100
|
});
|
|
94
101
|
```
|
|
95
102
|
|
|
96
103
|
凭证获取流程:
|
|
97
104
|
|
|
98
105
|
```
|
|
99
|
-
createSuperAgent({ baseUrl, botId })
|
|
106
|
+
createSuperAgent({ baseUrl, botId, appId })
|
|
100
107
|
↓
|
|
101
108
|
Widget 挂载时自动调用 sdk.getToken()
|
|
102
109
|
↓
|
|
103
|
-
POST /token
|
|
110
|
+
POST /api/token(无参数)
|
|
104
111
|
↓
|
|
105
|
-
后端返回 {
|
|
112
|
+
后端返回 { token }
|
|
106
113
|
↓
|
|
107
|
-
SDK
|
|
114
|
+
SDK 内部自动保存 token
|
|
108
115
|
↓
|
|
109
116
|
ready
|
|
110
117
|
```
|
|
111
118
|
|
|
112
|
-
|
|
119
|
+
`appId` 用于换取访问 token,浏览器端后续请求只持有短时有效的 token。
|
|
113
120
|
|
|
114
121
|
---
|
|
115
122
|
|
|
116
123
|
## 5. API 参考
|
|
117
124
|
|
|
118
|
-
>
|
|
125
|
+
> **字段命名**:后端接口返回 camelCase 字段,SDK 直接使用,无需转换。
|
|
119
126
|
>
|
|
120
|
-
> - 后端返回 `
|
|
121
|
-
> -
|
|
122
|
-
> - SDK 所有公开 API 均使用 camelCase(`sessionId`、`botId`)
|
|
123
|
-
> - SDK 发起请求时同样使用 camelCase(如 `{ botId, sessionId, message }`)
|
|
127
|
+
> - 后端返回 `sessionId`、`botId`、`createTime`、`updateTime`
|
|
128
|
+
> - SDK 所有公开 API 均使用 camelCase
|
|
124
129
|
|
|
125
130
|
### 5.1 SDK 实例
|
|
126
131
|
|
|
@@ -134,8 +139,8 @@ export interface SuperAgentSDK {
|
|
|
134
139
|
renameConversation(sessionId: string, title: string): Promise<void>;
|
|
135
140
|
deleteConversation(sessionId: string): Promise<void>;
|
|
136
141
|
getMessages(sessionId: string): Promise<UIMessage[]>;
|
|
137
|
-
getToken(): Promise<
|
|
138
|
-
setToken(
|
|
142
|
+
getToken(): Promise<string>;
|
|
143
|
+
setToken(token: string): void;
|
|
139
144
|
feedback(messageId: string, type: "like" | "dislike"): void;
|
|
140
145
|
onFeedback?: (messageId: string, type: "like" | "dislike") => void;
|
|
141
146
|
}
|
|
@@ -146,8 +151,8 @@ export interface SuperAgentSDK {
|
|
|
146
151
|
创建新会话,返回 `sessionId`。聊天前必须先创建会话。
|
|
147
152
|
|
|
148
153
|
- SDK 调用 `POST /chat/sessions`,请求体为 `{ botId }`
|
|
149
|
-
- 后端返回 `{
|
|
150
|
-
- SDK
|
|
154
|
+
- 后端返回 `{ sessionId: "..." }`
|
|
155
|
+
- SDK 直接返回 `sessionId` 字符串
|
|
151
156
|
|
|
152
157
|
```ts
|
|
153
158
|
const sessionId = await sdk.createSession();
|
|
@@ -158,7 +163,7 @@ const sessionId = await sdk.createSession();
|
|
|
158
163
|
流式聊天。**`sessionId` 为必填**,必须先调用 `createSession()` 获取。返回 `AbortController`,可随时中断。
|
|
159
164
|
|
|
160
165
|
- SDK 发送 `POST /chat`,请求体为 `{ botId, sessionId, message, stream }`
|
|
161
|
-
- 后端 SSE 在 `done` 事件中返回 `
|
|
166
|
+
- 后端 SSE 在 `done` 事件中返回 `sessionId`
|
|
162
167
|
|
|
163
168
|
```ts
|
|
164
169
|
export interface ChatOptions {
|
|
@@ -245,8 +250,7 @@ const { items, total } = await sdk.listConversations({ page: 1, size: 20 });
|
|
|
245
250
|
```
|
|
246
251
|
|
|
247
252
|
- SDK 调用 `GET /chat/conversations?botId=1&page=1&size=20`
|
|
248
|
-
-
|
|
249
|
-
- SDK 将其映射为 `Conversation { sessionId, botId, title, createTime, updateTime }`
|
|
253
|
+
- 后端返回的每一项为 `{ sessionId, botId, title, createTime, updateTime }`
|
|
250
254
|
|
|
251
255
|
### 5.5 getMessages()
|
|
252
256
|
|
|
@@ -266,30 +270,30 @@ await sdk.deleteConversation(sessionId);
|
|
|
266
270
|
### 5.7 getToken()
|
|
267
271
|
|
|
268
272
|
```typescript
|
|
269
|
-
sdk.getToken(): Promise<
|
|
273
|
+
sdk.getToken(): Promise<string>
|
|
270
274
|
```
|
|
271
275
|
|
|
272
|
-
|
|
276
|
+
自动获取并保存访问 token:
|
|
273
277
|
|
|
274
|
-
- SDK 调用 `POST /token
|
|
275
|
-
- 后端返回 `{
|
|
276
|
-
- SDK
|
|
278
|
+
- SDK 调用 `POST /api/token`(固定路径,不拼接 `baseUrl`),无需请求参数
|
|
279
|
+
- 后端返回 `{ token }`
|
|
280
|
+
- SDK 自动将 token 保存在内部
|
|
277
281
|
- Widget 在挂载时自动调用此方法 —— 通常无需手动调用
|
|
278
282
|
|
|
279
283
|
```ts
|
|
280
|
-
const
|
|
284
|
+
const token = await sdk.getToken();
|
|
281
285
|
```
|
|
282
286
|
|
|
283
287
|
### 5.8 setToken()
|
|
284
288
|
|
|
285
289
|
```typescript
|
|
286
|
-
sdk.setToken(
|
|
290
|
+
sdk.setToken(token: string): void
|
|
287
291
|
```
|
|
288
292
|
|
|
289
|
-
|
|
293
|
+
手动设置 token(用于 token 由外部获取、或测试等场景)。正常情况下无需调用,Widget 挂载时会自动通过 `getToken()` 获取 token。
|
|
290
294
|
|
|
291
295
|
```ts
|
|
292
|
-
sdk.setToken("<
|
|
296
|
+
sdk.setToken("<TOKEN>");
|
|
293
297
|
```
|
|
294
298
|
|
|
295
299
|
### 5.9 feedback() / onFeedback
|
|
@@ -312,21 +316,14 @@ sdk.feedback("msg_123", "like");
|
|
|
312
316
|
|
|
313
317
|
SDK 方法 → 后端接口的完整映射:
|
|
314
318
|
|
|
315
|
-
|
|
316
|
-
| --------------------- | ------------------------- | --------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------ |
|
|
317
|
-
| `getToken()` | `POST /token` | `{ botId }` | `{ app_id, token }` | `{ appId, token }` |
|
|
318
|
-
| `createSession()` | `POST /chat/sessions` | `{ botId }` | `{ session_id }` | `sessionId` 字符串 |
|
|
319
|
-
| `chat()` | `POST /chat` | `{ botId, sessionId, message, stream }` | SSE 流,`done` 事件含 `session_id` | `onDone` 中暴露 `sessionId` |
|
|
320
|
-
| `listConversations()` | `GET /chat/conversations` | 查询参数 `botId`、`page`、`size` | `{ thread_id, bot_id, create_time, update_time }[]` | `Conversation { sessionId, botId, title, createTime, updateTime }` |
|
|
321
|
-
|
|
322
|
-
字段命名转换规则:
|
|
319
|
+
> 除 `getToken()` 外,其余接口请求均携带 `X-App-Id` 与 `X-Token` 请求头进行鉴权。
|
|
323
320
|
|
|
324
|
-
|
|
|
325
|
-
|
|
|
326
|
-
| `
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `
|
|
321
|
+
| SDK 方法 | HTTP 请求 | 请求体 | 后端返回 |
|
|
322
|
+
| --------------------- | ------------------------- | --------------------------------------- | ----------------------------------------------- |
|
|
323
|
+
| `getToken()` | `POST /api/token` | 无参数 | `{ token }` |
|
|
324
|
+
| `createSession()` | `POST /chat/sessions` | `{ botId }` | `{ sessionId }` |
|
|
325
|
+
| `chat()` | `POST /chat` | `{ botId, sessionId, message, stream }` | SSE 流,`done` 事件含 `sessionId` |
|
|
326
|
+
| `listConversations()` | `GET /chat/conversations` | 查询参数 `botId`、`page`、`size` | `{ items: [{ sessionId, botId, ... }], total }` |
|
|
330
327
|
|
|
331
328
|
---
|
|
332
329
|
|
|
@@ -366,7 +363,11 @@ export interface WidgetInstance {
|
|
|
366
363
|
import { createSuperAgent } from "super-agent-sdk";
|
|
367
364
|
import { mount } from "super-agent-sdk/widget";
|
|
368
365
|
|
|
369
|
-
const sdk = createSuperAgent({
|
|
366
|
+
const sdk = createSuperAgent({
|
|
367
|
+
baseUrl: "/api/v1",
|
|
368
|
+
botId: 1,
|
|
369
|
+
appId: "your_app_id",
|
|
370
|
+
});
|
|
370
371
|
|
|
371
372
|
const widget = mount("#chat-root", {
|
|
372
373
|
sdk,
|
|
@@ -874,8 +875,12 @@ import type {
|
|
|
874
875
|
WelcomeScreenProps,
|
|
875
876
|
} from "super-agent-sdk/widget";
|
|
876
877
|
|
|
877
|
-
const sdk = createSuperAgent({
|
|
878
|
-
|
|
878
|
+
const sdk = createSuperAgent({
|
|
879
|
+
baseUrl: "/api/v1",
|
|
880
|
+
botId: 1,
|
|
881
|
+
appId: "your_app_id",
|
|
882
|
+
});
|
|
883
|
+
sdk.setToken("demo_token");
|
|
879
884
|
|
|
880
885
|
function CustomHeader({ title, onClose, onToggleThreadList }: HeaderProps) {
|
|
881
886
|
return (
|
|
@@ -1192,17 +1197,118 @@ export interface ChatEvent {
|
|
|
1192
1197
|
|
|
1193
1198
|
---
|
|
1194
1199
|
|
|
1195
|
-
## 12.
|
|
1200
|
+
## 12. Human-in-the-Loop
|
|
1201
|
+
|
|
1202
|
+
Agent 执行中需要人类介入时(确认敏感操作、选择方案、补充信息、审核内容等),SDK 提供统一的中断交互机制。
|
|
1203
|
+
|
|
1204
|
+
### 12.1 核心流程
|
|
1205
|
+
|
|
1206
|
+
```
|
|
1207
|
+
Agent 执行中
|
|
1208
|
+
→ 后端发送 SSE interrupt 事件
|
|
1209
|
+
→ SDK 渲染中断交互卡片(按 interruptType 分发)
|
|
1210
|
+
→ 用户完成操作
|
|
1211
|
+
→ SDK 调用 respondInterrupt() 回传响应
|
|
1212
|
+
→ Agent 基于响应继续执行
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
### 12.2 interrupt 事件
|
|
1216
|
+
|
|
1217
|
+
```json
|
|
1218
|
+
{
|
|
1219
|
+
"type": "interrupt",
|
|
1220
|
+
"interruptId": "int_001",
|
|
1221
|
+
"interruptType": "confirm",
|
|
1222
|
+
"content": "即将执行转账 ¥500,确认执行?",
|
|
1223
|
+
"options": ["确认", "取消"]
|
|
1224
|
+
}
|
|
1225
|
+
```
|
|
1226
|
+
|
|
1227
|
+
### 12.3 响应中断
|
|
1228
|
+
|
|
1229
|
+
```ts
|
|
1230
|
+
await sdk.respondInterrupt(interruptId, {
|
|
1231
|
+
action: "confirm",
|
|
1232
|
+
});
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
### 12.4 Widget 自动处理
|
|
1236
|
+
|
|
1237
|
+
Widget 内置中断卡片渲染,收到 `interrupt` 事件后自动展示对应交互卡片,用户操作后自动回传,无需业务方处理:
|
|
1238
|
+
|
|
1239
|
+
```ts
|
|
1240
|
+
mount("#chat", { sdk }).open();
|
|
1241
|
+
// 遇到 interrupt 时:自动渲染卡片 → 用户点击 → 自动 respondInterrupt → Agent 继续
|
|
1242
|
+
```
|
|
1243
|
+
|
|
1244
|
+
也可通过插槽自定义中断卡片:
|
|
1245
|
+
|
|
1246
|
+
```ts
|
|
1247
|
+
mount("#chat", {
|
|
1248
|
+
sdk,
|
|
1249
|
+
slots: {
|
|
1250
|
+
InterruptCard: MyInterruptCard, // 自定义全部类型
|
|
1251
|
+
},
|
|
1252
|
+
});
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
### 12.5 纯 API 模式手动处理
|
|
1256
|
+
|
|
1257
|
+
```ts
|
|
1258
|
+
sdk.chat({
|
|
1259
|
+
sessionId,
|
|
1260
|
+
message: "帮我转账 ¥500",
|
|
1261
|
+
onMessage: (e) => {
|
|
1262
|
+
if (e.type === "interrupt" && e.interrupt) {
|
|
1263
|
+
// 自定义 UI 处理
|
|
1264
|
+
const ok = window.confirm(e.interrupt.content);
|
|
1265
|
+
sdk.respondInterrupt(e.interrupt.interruptId, {
|
|
1266
|
+
action: ok ? "confirm" : "cancel",
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
},
|
|
1270
|
+
});
|
|
1271
|
+
```
|
|
1272
|
+
|
|
1273
|
+
### 12.6 interruptType 一览
|
|
1274
|
+
|
|
1275
|
+
| interruptType | 交互 | action | value 示例 |
|
|
1276
|
+
|---------------|------|--------|-----------|
|
|
1277
|
+
| `confirm` | 二次确认 | `confirm` / `cancel` | — |
|
|
1278
|
+
| `select` | 单选 | `select` | `"flight_a"` |
|
|
1279
|
+
| `multiSelect` | 多选 | `submit` | `["name", "phone"]` |
|
|
1280
|
+
| `input` | 文本输入 | `submit` | `"123456"` |
|
|
1281
|
+
| `form` | 表单 | `submit` | `{ name: "张三" }` |
|
|
1282
|
+
| `review` | 内容审阅 | `approve` / `reject` | 修改后内容 |
|
|
1283
|
+
| `approve` | 审批流 | `approve` / `reject` | 驳回原因 |
|
|
1284
|
+
| `upload` | 文件上传 | `submit` | `{ fileId, fileName }` |
|
|
1285
|
+
| `image` | 图片选择 | `select` / `reject` | 图片索引 |
|
|
1286
|
+
| `auth` | 授权请求 | `authorized` / `skip` | — |
|
|
1287
|
+
| `captcha` | 人机验证 | `verified` | `"captcha_token"` |
|
|
1288
|
+
| `decision` | 流程分支 | `decide` | `"retry"` 等 |
|
|
1289
|
+
| `rating` | 评分 | `rate` | `4` |
|
|
1290
|
+
| `date` | 日期选择 | `submit` | `"2026-08-21T14:00:00"` |
|
|
1291
|
+
| `location` | 位置选择 | `submit` | `{ address, lat, lng }` |
|
|
1292
|
+
|
|
1293
|
+
> 每个 `interruptType` 的完整字段定义见 [API 文档](./API.md) 与 [HITL 设计文档](../docs/superpowers/specs/2026-08-18-human-in-the-loop-design.md)。
|
|
1294
|
+
|
|
1295
|
+
---
|
|
1296
|
+
|
|
1297
|
+
## 13. 高级用法
|
|
1196
1298
|
|
|
1197
|
-
###
|
|
1299
|
+
### 13.1 纯 API 模式(不用 Widget)
|
|
1198
1300
|
|
|
1199
1301
|
不挂载组件,仅使用 API 层构建自己的 UI:
|
|
1200
1302
|
|
|
1201
1303
|
```ts
|
|
1202
1304
|
import { createSuperAgent } from "super-agent-sdk";
|
|
1203
1305
|
|
|
1204
|
-
const sdk = createSuperAgent({
|
|
1205
|
-
|
|
1306
|
+
const sdk = createSuperAgent({
|
|
1307
|
+
baseUrl: "/api/v1",
|
|
1308
|
+
botId: 1,
|
|
1309
|
+
appId: "your_app_id",
|
|
1310
|
+
});
|
|
1311
|
+
sdk.setToken("<TOKEN>");
|
|
1206
1312
|
|
|
1207
1313
|
const sessionId = await sdk.createSession();
|
|
1208
1314
|
|
|
@@ -1218,7 +1324,7 @@ sdk.chat({
|
|
|
1218
1324
|
});
|
|
1219
1325
|
```
|
|
1220
1326
|
|
|
1221
|
-
###
|
|
1327
|
+
### 13.2 使用 Hooks
|
|
1222
1328
|
|
|
1223
1329
|
从 `super-agent-sdk/widget` 导出 `useChat`、`useConversations`,可在自己的 React 应用中复用:
|
|
1224
1330
|
|
|
@@ -1290,11 +1396,11 @@ function MyChat({ sdk }: { sdk: SuperAgentSDK }) {
|
|
|
1290
1396
|
|
|
1291
1397
|
> `useChat` 在 `sessionId` 为空时会自动调用 `sdk.createSession()` 创建新会话,无需手动处理。
|
|
1292
1398
|
|
|
1293
|
-
###
|
|
1399
|
+
### 13.3 Token 续期
|
|
1294
1400
|
|
|
1295
|
-
请求返回 `401` 时,SDK
|
|
1401
|
+
请求返回 `401` 时,SDK 自动重新调用 `POST /api/token` 获取新 token。
|
|
1296
1402
|
|
|
1297
|
-
###
|
|
1403
|
+
### 13.4 取消请求
|
|
1298
1404
|
|
|
1299
1405
|
`chat()` 返回 `AbortController`;或传入外部 `AbortSignal`(SDK 会合并内部信号,任一触发即中断):
|
|
1300
1406
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function
|
|
2
|
-
`).map(
|
|
3
|
-
`))}catch{return null}switch(
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function u(n){if(Array.isArray(n))return n.map(e=>u(e));if(n&&typeof n=="object"&&n.constructor===Object){const e={};for(const[t,r]of Object.entries(n)){const o=t.replace(/_([a-z])/g,(s,a)=>a.toUpperCase());e[o]=u(r)}return e}return n}class g{constructor(e){this.refreshing=null,this.baseUrl=e.baseUrl.replace(/\/$/,""),this.appId=e.appId,this.token=e.token??"",this.botId=e.botId}getBotId(){return this.botId}getAppKey(){return this.appId}setToken(e){this.token=e}getOrigin(){try{return new URL(this.baseUrl).origin}catch{return""}}async fetchToken(){const e=`${this.getOrigin()}/api/token`,t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({appId:this.appId,botId:this.botId})});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);const r=await t.json();if(r.code!=="200")throw new Error(r.message||`API error: ${r.code}`);const o=u(r.data);return this.token=o.token,o.token}headers(e){return{"Content-Type":"application/json","X-App-Id":this.appId,"X-Token":this.token,...e}}async handleTokenRefresh(){if(this.refreshing)return await this.refreshing,!0;try{return this.refreshing=(async()=>{await this.fetchToken()})(),await this.refreshing,!0}catch{return!1}finally{this.refreshing=null}}async request(e,t,r){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");let o=`${this.baseUrl}${t}`;if(r!=null&&r.params){const i=new URLSearchParams;for(const[l,d]of Object.entries(r.params))d!=null&&i.set(l,String(d));const c=i.toString();c&&(o+=`?${c}`)}const s=await fetch(o,{method:e,headers:this.headers(),body:r!=null&&r.body?JSON.stringify(r.body):void 0});if(s.status===401&&!(r!=null&&r.retry)&&await this.handleTokenRefresh())return this.request(e,t,{...r,retry:!0});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);const a=await s.json();if(a.code!=="200")throw new Error(a.message||`API error: ${a.code}`);return u(a.data)}get(e,t){return this.request("GET",e,{params:t})}post(e,t){return this.request("POST",e,{body:t})}patch(e,t){return this.request("PATCH",e,{body:t})}del(e){return this.request("DELETE",e)}async streamPost(e,t,r){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");const o=`${this.baseUrl}${e}`,s=await fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:r});return s.status===401&&await this.handleTokenRefresh()?fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:r}):s}}function f(n){const e=n.split(`
|
|
2
|
+
`).map(r=>r.trim()).filter(r=>r.startsWith("data:")).map(r=>r.slice(5).trim());if(!e.length)return null;let t;try{t=JSON.parse(e.join(`
|
|
3
|
+
`))}catch{return null}switch(t.type){case"user":return{type:"user",content:t.content??""};case"thinking":return{type:"thinking",content:t.content??""};case"ai":return{type:"ai",content:t.content??""};case"tool_call":return{type:"tool_call",content:t.name??"",toolName:t.name,toolCallId:t.id,args:typeof t.args=="string"?t.args:JSON.stringify(t.args??{})};case"tool_result":return{type:"tool_result",content:t.output??"",toolName:t.name,toolCallId:t.id};case"done":return{type:"done",content:t.content??"",sessionId:t.sessionId??t.session_id??""};case"error":return{type:"error",content:t.message??"Unknown error"};case"interrupt":return{type:"interrupt",content:t.content??"",interrupt:{interruptId:t.interruptId??t.interrupt_id??"",interruptType:t.interruptType??t.interrupt_type??"confirm",content:t.content??"",options:t.options,placeholder:t.placeholder,inputType:t.inputType??t.input_type,maxLength:t.maxLength??t.max_length,required:t.required,fields:t.fields,metadata:t.metadata}};default:return null}}async function y(n,e,t){if(!n.body){t(new Error("Response body is null"));return}const r=n.body.getReader(),o=new TextDecoder;let s="";try{for(;;){const{value:a,done:i}=await r.read();if(i)break;s+=o.decode(a,{stream:!0});let c;for(;(c=s.indexOf(`
|
|
4
4
|
|
|
5
|
-
`))!==-1;){const l=
|
|
5
|
+
`))!==-1;){const l=s.slice(0,c);s=s.slice(c+2);const d=f(l);d&&e(d)}}if(s.trim()){const a=f(s);a&&e(a)}}catch(a){(a==null?void 0:a.name)!=="AbortError"&&t(a instanceof Error?a:new Error(String(a)))}finally{try{r.releaseLock()}catch{}}}function m(n,e){const t=new AbortController,r=e.signal?I(e.signal,t.signal):t.signal,o={botId:n.getBotId(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1};return o.stream?n.streamPost("/chat",o,r).then(s=>{var a;if(!s.ok){(a=e.onError)==null||a.call(e,new Error(`HTTP ${s.status}`));return}return y(s,i=>{var c,l,d,h;i.type==="done"&&i.sessionId?(c=e.onDone)==null||c.call(e,{sessionId:i.sessionId,content:i.content}):i.type==="done"?(l=e.onDone)==null||l.call(e,{sessionId:"",content:i.content}):i.type==="error"?(d=e.onError)==null||d.call(e,new Error(i.content)):(h=e.onMessage)==null||h.call(e,i)},i=>{var c;return(c=e.onError)==null?void 0:c.call(e,i)})}).catch(s=>{var a;(s==null?void 0:s.name)!=="AbortError"&&((a=e.onError)==null||a.call(e,s instanceof Error?s:new Error(String(s))))}):n.post("/chat",o).then(s=>{var a;(a=e.onDone)==null||a.call(e,{sessionId:s.sessionId,content:s.content??""})}).catch(s=>{var a;(a=e.onError)==null||a.call(e,s instanceof Error?s:new Error(String(s)))}),t}function I(n,e){const t=new AbortController,r=()=>t.abort();return n.addEventListener("abort",r,{once:!0}),e.addEventListener("abort",r,{once:!0}),(n.aborted||e.aborted)&&t.abort(),t.signal}async function w(n){return(await n.post("/chat/sessions",{botId:n.getBotId()})).sessionId}function T(n){return{sessionId:n.threadId??n.sessionId,botId:n.botId,title:n.title,createTime:n.createTime,updateTime:n.updateTime}}async function b(n,e){const t=await n.get("/chat/conversations",{botId:n.getBotId(),page:(e==null?void 0:e.page)??1,size:(e==null?void 0:e.size)??20});return{...t,items:t.items.map(T)}}async function k(n,e,t){await n.patch(`/chat/conversations/${e}`,{title:t})}async function S(n,e){await n.del(`/chat/conversations/${e}`)}async function p(n,e){const t=await n.get(`/chat/conversations/${e}/messages`);return E(t)}function E(n){const e=[],t=[...n].sort((r,o)=>(r.seq??0)-(o.seq??0));for(const r of t){const o=r.role;if(o==="system")continue;const s=r.messageId??`msg_${r.id}`,a=new Date(r.createTime??"").getTime()||Date.now();if(o==="human")e.push({id:s,role:"user",parts:[{type:"text",content:r.content??""}],timestamp:a});else if(o==="ai"){const i=[];r.reasoning&&i.push({type:"thinking",content:r.reasoning}),r.content&&i.push({type:"text",content:r.content});const c=r.toolCalls;if(c&&Array.isArray(c))for(const l of c){let d;try{d=typeof l.args=="string"?l.args:JSON.stringify(l.args??{})}catch{d=String(l.args??"{}")}i.push({type:"tool_call",toolName:l.name??"",toolCallId:l.id??"",args:d})}e.push({id:s,role:"assistant",parts:i,timestamp:a})}else o==="tool"&&e.push({id:s,role:"assistant",parts:[{type:"tool_result",toolName:r.toolName??"",toolCallId:r.toolCallId??"",content:r.content??""}],timestamp:a})}return e}async function C(n,e,t,r){await n.post(`/chat/interrupt/${e}/respond`,{sessionId:t,action:r.action,value:r.value})}function O(n){const e=new g(n),t={getToken:()=>e.fetchToken(),createSession:()=>w(e),chat:r=>m(e,r),listConversations:r=>b(e,r),renameConversation:(r,o)=>k(e,r,o),deleteConversation:r=>S(e,r),getMessages:r=>p(e,r),respondInterrupt:(r,o,s)=>C(e,r,o,s),setToken:r=>e.setToken(r),feedback:(r,o)=>{var s;(s=t.onFeedback)==null||s.call(t,r,o)}};return t}exports.createSuperAgent=O;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export declare interface ChatEvent {
|
|
2
|
-
type: "user" | "thinking" | "ai" | "tool_call" | "tool_result" | "done" | "error";
|
|
2
|
+
type: "user" | "thinking" | "ai" | "tool_call" | "tool_result" | "done" | "error" | "interrupt";
|
|
3
3
|
content: string;
|
|
4
4
|
toolName?: string;
|
|
5
5
|
toolCallId?: string;
|
|
6
6
|
args?: string;
|
|
7
7
|
sessionId?: string;
|
|
8
|
+
interrupt?: InterruptEvent;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export declare interface ChatOptions {
|
|
@@ -30,6 +31,44 @@ export declare interface Conversation {
|
|
|
30
31
|
|
|
31
32
|
export declare function createSuperAgent(config: SDKConfig): SuperAgentSDK;
|
|
32
33
|
|
|
34
|
+
export declare interface FormField {
|
|
35
|
+
name: string;
|
|
36
|
+
label: string;
|
|
37
|
+
type: 'text' | 'number' | 'password' | 'textarea' | 'select' | 'date';
|
|
38
|
+
required?: boolean;
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
defaultValue?: any;
|
|
41
|
+
options?: string[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare interface InterruptEvent {
|
|
45
|
+
interruptId: string;
|
|
46
|
+
interruptType: InterruptType;
|
|
47
|
+
content: string;
|
|
48
|
+
options?: (string | InterruptOption)[];
|
|
49
|
+
placeholder?: string;
|
|
50
|
+
inputType?: 'text' | 'number' | 'password' | 'textarea';
|
|
51
|
+
maxLength?: number;
|
|
52
|
+
required?: boolean;
|
|
53
|
+
fields?: FormField[];
|
|
54
|
+
metadata?: Record<string, any>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export declare interface InterruptOption {
|
|
58
|
+
value: string;
|
|
59
|
+
label: string;
|
|
60
|
+
description?: string;
|
|
61
|
+
icon?: string;
|
|
62
|
+
danger?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export declare interface InterruptResponse {
|
|
66
|
+
action: string;
|
|
67
|
+
value?: any;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export declare type InterruptType = 'confirm' | 'select' | 'multiSelect' | 'input' | 'form';
|
|
71
|
+
|
|
33
72
|
export declare interface ListConversationsParams {
|
|
34
73
|
page?: number;
|
|
35
74
|
size?: number;
|
|
@@ -59,21 +98,23 @@ export declare type MessagePart = {
|
|
|
59
98
|
} | {
|
|
60
99
|
type: "error";
|
|
61
100
|
content: string;
|
|
101
|
+
} | {
|
|
102
|
+
type: "interrupt";
|
|
103
|
+
interrupt: InterruptEvent;
|
|
104
|
+
resolved?: boolean;
|
|
105
|
+
response?: InterruptResponse;
|
|
62
106
|
};
|
|
63
107
|
|
|
64
108
|
export declare interface SDKConfig {
|
|
65
109
|
baseUrl: string;
|
|
66
110
|
botId: number;
|
|
67
|
-
appId
|
|
111
|
+
appId: string;
|
|
68
112
|
token?: string;
|
|
69
113
|
}
|
|
70
114
|
|
|
71
115
|
export declare interface SuperAgentSDK {
|
|
72
|
-
/** 获取 token(调用 POST /token),自动设置内部凭证 */
|
|
73
|
-
getToken(): Promise<
|
|
74
|
-
appId: string;
|
|
75
|
-
token: string;
|
|
76
|
-
}>;
|
|
116
|
+
/** 获取 token(调用 POST /api/token),自动设置内部凭证 */
|
|
117
|
+
getToken(): Promise<string>;
|
|
77
118
|
/** 创建新会话,返回 sessionId */
|
|
78
119
|
createSession(): Promise<string>;
|
|
79
120
|
chat(options: ChatOptions): AbortController;
|
|
@@ -81,9 +122,11 @@ export declare interface SuperAgentSDK {
|
|
|
81
122
|
renameConversation(sessionId: string, title: string): Promise<void>;
|
|
82
123
|
deleteConversation(sessionId: string): Promise<void>;
|
|
83
124
|
getMessages(sessionId: string): Promise<UIMessage[]>;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
125
|
+
/** 响应中断事件 */
|
|
126
|
+
respondInterrupt(interruptId: string, sessionId: string, response: InterruptResponse): Promise<void>;
|
|
127
|
+
setToken(token: string): void;
|
|
128
|
+
feedback(messageId: string, type: "like" | "dislike"): void;
|
|
129
|
+
onFeedback?: (messageId: string, type: "like" | "dislike") => void;
|
|
87
130
|
}
|
|
88
131
|
|
|
89
132
|
export declare interface UIMessage {
|