super-agent-sdk 1.0.5 → 1.0.7

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 CHANGED
@@ -63,9 +63,8 @@ import { createSuperAgent } from "super-agent-sdk";
63
63
  import { mount } from "super-agent-sdk/widget";
64
64
 
65
65
  const sdk = createSuperAgent({
66
- baseUrl: "/api/v1",
67
66
  botId: 1,
68
- appId: "your_app_id",
67
+ tokenGateway: "/api/gateway",
69
68
  });
70
69
  // Token 自动获取,无需手动设置
71
70
  const widget = mount("#chat", { sdk });
@@ -84,39 +83,40 @@ function createSuperAgent(config: SDKConfig): SuperAgentSDK;
84
83
 
85
84
  ```ts
86
85
  export interface SDKConfig {
87
- baseUrl: string; // e.g. "https://agent.example.com/api/v1"
88
- botId: number; // bot ID
89
- appId: string; // 应用密钥,用于换取 token
86
+ botId: number; // Bot ID(必填)
87
+ tokenGateway: string; // Token 网关前缀(必填,不带 host),如 "/api/gateway";token URL = {origin}{tokenGateway}/v1/token
88
+ baseUrl?: string; // 业务接口前缀(可选,默认 "/api/agent/runtime/v1"),不带 host
89
+ appId?: string; // 可选,不传则从 token 接口响应自动获取
90
+ token?: string; // 可选,不传则自动调 token 接口获取
90
91
  }
91
92
  ```
92
93
 
93
- 只需提供 `baseUrl`、`botId` 与 `appId` 即可。SDK 不要求在创建时传入 `token`——组件挂载后会自动调用 `sdk.getToken()` 获取 token 并内部保存,无需手动设置。
94
+ 只需提供 `botId` 与 `tokenGateway` 即可。`baseUrl` 默认为 `/api/agent/runtime/v1`,`appId` 从 token 接口响应中自动获取。SDK 不要求在创建时传入 `token`——组件挂载后会自动调用 `sdk.getToken()` 获取 token 并内部保存,无需手动设置。
94
95
 
95
96
  ```ts
96
97
  const sdk = createSuperAgent({
97
- baseUrl: "https://agent.example.com/api/v1",
98
98
  botId: 1,
99
- appId: "your_app_id",
99
+ tokenGateway: "/api/gateway",
100
100
  });
101
101
  ```
102
102
 
103
103
  凭证获取流程:
104
104
 
105
105
  ```
106
- createSuperAgent({ baseUrl, botId, appId })
106
+ createSuperAgent({ botId, tokenGateway })
107
107
 
108
108
  Widget 挂载时自动调用 sdk.getToken()
109
109
 
110
- POST /api/token(无参数)
110
+ POST {origin}{tokenGateway}/v1/token(body: { botId })
111
111
 
112
- 后端返回 { token }
112
+ 后端返回 { token, appId }
113
113
 
114
- SDK 内部自动保存 token
114
+ SDK 内部自动保存 token + appId
115
115
 
116
116
  ready
117
117
  ```
118
118
 
119
- `appId` 用于换取访问 token,浏览器端后续请求只持有短时有效的 token。
119
+ `tokenGateway` 用于拼接 token 接口路径,`appId` 自动从 token 响应获取(也可手动传入覆盖)。
120
120
 
121
121
  ---
122
122
 
@@ -143,6 +143,9 @@ export interface SuperAgentSDK {
143
143
  setToken(token: string): void;
144
144
  feedback(messageId: string, type: "like" | "dislike", options?: { reason?: number; remark?: string }): Promise<void>;
145
145
  cancelFeedback(messageId: string): Promise<void>;
146
+ respondInterrupt(interruptId: string, sessionId: string, response: InterruptResponse): Promise<void>;
147
+ listSkills(): Promise<SkillInfo[]>;
148
+ stopGeneration(sessionId: string): Promise<void>;
146
149
  }
147
150
  ```
148
151
 
@@ -275,9 +278,9 @@ sdk.getToken(): Promise<string>
275
278
 
276
279
  自动获取并保存访问 token:
277
280
 
278
- - SDK 调用 `POST /api/token`(固定路径,不拼接 `baseUrl`),无需请求参数
279
- - 后端返回 `{ token }`
280
- - SDK 自动将 token 保存在内部
281
+ - SDK 调用 `POST {origin}{tokenGateway}/v1/token`,请求体 `{ botId }`
282
+ - 后端返回 `{ token, appId }`
283
+ - SDK 自动将 token + appId 保存在内部
281
284
  - Widget 在挂载时自动调用此方法 —— 通常无需手动调用
282
285
 
283
286
  ```ts
@@ -329,10 +332,12 @@ SDK 方法 → 后端接口的完整映射:
329
332
  | --------------------- | ------------------------- | --------------------------------------- | ----------------------------------------------- |
330
333
  | `getToken()` | `POST {gateway}/v1/token` | `{ botId }` | `{ token, appId }` |
331
334
  | `createSession()` | `POST /chat/sessions` | `{ botId }` | `{ sessionId }` |
332
- | `chat()` | `POST /chat` | `{ botId, sessionId, message, stream }` | SSE 流,`done` 事件含 `sessionId` |
335
+ | `chat()` | `POST /chat` | `{ botId, sessionId, message, stream }` | SSE 流,`done`/`stop` 事件含 `sessionId` |
333
336
  | `listConversations()` | `GET /chat/conversations` | 查询参数 `botId`、`page`、`size` | `{ items: [{ sessionId, botId, ... }], total }` |
334
337
  | `feedback()` | `POST /chat/messages/{messageId}/feedback` | `{ type, reason?, remark? }` | `null` |
335
338
  | `cancelFeedback()` | `DELETE /chat/messages/{messageId}/feedback` | 无 body | `null` |
339
+ | `stopGeneration()` | `POST /chat/stop` | `{ sessionId }` | `{ stopped: "pending", sessionId }` |
340
+ | `listSkills()` | `GET /chat/bots/{botId}/skills` | — | `[{ code, name, displayName, description }]` |
336
341
 
337
342
  ---
338
343
 
@@ -373,9 +378,8 @@ import { createSuperAgent } from "super-agent-sdk";
373
378
  import { mount } from "super-agent-sdk/widget";
374
379
 
375
380
  const sdk = createSuperAgent({
376
- baseUrl: "/api/v1",
377
381
  botId: 1,
378
- appId: "your_app_id",
382
+ tokenGateway: "/api/gateway",
379
383
  });
380
384
 
381
385
  const widget = mount("#chat-root", {
@@ -728,6 +732,8 @@ export interface ThreadListProps {
728
732
  onNew: () => void;
729
733
  onDelete: (sessionId: string) => void;
730
734
  onRename: (sessionId: string, title: string) => void;
735
+ hasMore?: boolean;
736
+ onLoadMore?: () => void;
731
737
  }
732
738
  ```
733
739
 
@@ -867,7 +873,7 @@ mount("#chat-root", {
867
873
  });
868
874
  ```
869
875
 
870
- > 点赞 / 踩的反馈回调不在 `hooks` 中,而是在 `sdk.onFeedback`(见 [5.9](#59-feedback--onfeedback))。
876
+ > 点赞 / 踩由内置 `ActionBar` 组件通过 `ChatState.feedback()` / `cancelFeedback()` 自动处理,无需额外配置(见 [5.9](#59-feedback--cancelfeedback))。
871
877
 
872
878
  ### 8.5 定制示例
873
879
 
@@ -885,9 +891,8 @@ import type {
885
891
  } from "super-agent-sdk/widget";
886
892
 
887
893
  const sdk = createSuperAgent({
888
- baseUrl: "/api/v1",
889
894
  botId: 1,
890
- appId: "your_app_id",
895
+ tokenGateway: "/api/gateway",
891
896
  });
892
897
  sdk.setToken("demo_token");
893
898
 
@@ -1102,7 +1107,8 @@ await sdk.deleteConversation(items[0].sessionId);
1102
1107
 
1103
1108
  ### 9.2 组件内置能力
1104
1109
 
1105
- - **自动加载**:挂载后自动调用 `listConversations` 拉取会话列表。
1110
+ - **自动加载**:挂载后自动调用 `listConversations` 拉取会话列表(每页 20 条)。
1111
+ - **滚动加载**:会话列表滚动到底部时自动加载下一页,支持任意数量的会话。
1106
1112
  - **切换**:点击会话项加载该会话历史消息并展示。
1107
1113
  - **新建**:点击「新会话」清空当前消息,下次发送时自动调用 `createSession()` 创建新会话。
1108
1114
  - **重命名**:`fullpage` 侧边栏或自定义 `ThreadList` 中调用 `renameConversation`。
@@ -1113,7 +1119,47 @@ await sdk.deleteConversation(items[0].sessionId);
1113
1119
 
1114
1120
  ## 10. 中断恢复
1115
1121
 
1116
- ### 10.1 中断请求
1122
+ ### 10.1 停止生成
1123
+
1124
+ SDK 提供双信号停止机制,确保多实例部署下也能可靠停止生成:
1125
+
1126
+ 1. **`abort()`**:断开 SSE 连接,前端即时停止接收
1127
+ 2. **`POST /chat/stop`**:通过 Redis Pub/Sub 广播取消信号到实际执行的后端实例
1128
+
1129
+ Widget 内置的停止按钮已自动执行双信号(`abort()` + `stopGeneration()`),无需手动处理。
1130
+
1131
+ #### 纯 API 模式
1132
+
1133
+ ```ts
1134
+ const controller = sdk.chat({
1135
+ sessionId,
1136
+ message: "...",
1137
+ stream: true,
1138
+ onMessage: (event) => {
1139
+ if (event.type === 'stop') {
1140
+ // 用户主动停止,event.content 为已生成的半截回复全文
1141
+ console.log("已停止,半截回复:", event.content);
1142
+ }
1143
+ },
1144
+ onDone,
1145
+ });
1146
+
1147
+ // 停止生成:双信号并发
1148
+ controller.abort();
1149
+ await sdk.stopGeneration(sessionId);
1150
+ ```
1151
+
1152
+ #### stopGeneration()
1153
+
1154
+ ```ts
1155
+ sdk.stopGeneration(sessionId: string): Promise<void>
1156
+ ```
1157
+
1158
+ 调用 `POST /chat/stop`,广播取消信号。返回 `{ stopped: "pending" }` 表示已受理,实际停止异步发生。SDK 不应阻塞等待——以 SSE 流的 `stop`/`done` 事件或本地 `abort` 作为停止完成的判定。
1159
+
1160
+ 半截回复(含思考与正文)会保留:既写入数据库(刷新可回显),也写入 checkpoint(影响下一轮对话上下文)。
1161
+
1162
+ ### 10.2 中断请求
1117
1163
 
1118
1164
  `chat()` 返回 `AbortController`,可随时中断:
1119
1165
 
@@ -1135,7 +1181,7 @@ sdk.chat({ sessionId, message: "...", signal: ac.signal });
1135
1181
  ac.abort();
1136
1182
  ```
1137
1183
 
1138
- ### 10.2 会话恢复
1184
+ ### 10.3 会话恢复
1139
1185
 
1140
1186
  页面刷新或组件重新挂载时,会话状态自动恢复:
1141
1187
 
@@ -1195,6 +1241,7 @@ export interface ChatEvent {
1195
1241
  | "tool_call"
1196
1242
  | "tool_result"
1197
1243
  | "done"
1244
+ | "stop"
1198
1245
  | "error";
1199
1246
  content: string;
1200
1247
  toolName?: string;
@@ -1313,9 +1360,8 @@ sdk.chat({
1313
1360
  import { createSuperAgent } from "super-agent-sdk";
1314
1361
 
1315
1362
  const sdk = createSuperAgent({
1316
- baseUrl: "/api/v1",
1317
1363
  botId: 1,
1318
- appId: "your_app_id",
1364
+ tokenGateway: "/api/gateway",
1319
1365
  });
1320
1366
  sdk.setToken("<TOKEN>");
1321
1367
 
@@ -1407,11 +1453,13 @@ function MyChat({ sdk }: { sdk: SuperAgentSDK }) {
1407
1453
 
1408
1454
  ### 13.3 Token 续期
1409
1455
 
1410
- 请求返回 `401` 时,SDK 自动重新调用 `POST /api/token` 获取新 token。
1456
+ 请求返回 `401` 时,SDK 自动重新调用 `POST {tokenGateway}/v1/token` 获取新 token。
1411
1457
 
1412
- ### 13.4 取消请求
1458
+ ### 13.4 停止与取消请求
1413
1459
 
1414
- `chat()` 返回 `AbortController`;或传入外部 `AbortSignal`(SDK 会合并内部信号,任一触发即中断):
1460
+ `chat()` 返回 `AbortController`;或传入外部 `AbortSignal`(SDK 会合并内部信号,任一触发即中断)。
1461
+
1462
+ 推荐使用双信号机制停止生成(Widget 内置停止按钮已自动处理):
1415
1463
 
1416
1464
  ```ts
1417
1465
  const controller = sdk.chat({
@@ -1420,11 +1468,16 @@ const controller = sdk.chat({
1420
1468
  stream: true,
1421
1469
  onDone,
1422
1470
  });
1423
- // 稍后取消
1471
+ // 双信号停止:abort 断 SSE + POST /chat/stop 广播后端取消
1424
1472
  controller.abort();
1473
+ await sdk.stopGeneration(sessionId);
1425
1474
  ```
1426
1475
 
1476
+ 纯客户端取消(不通知后端):
1477
+
1427
1478
  ```ts
1479
+ controller.abort();
1480
+ // 或使用外部 signal
1428
1481
  const ac = new AbortController();
1429
1482
  sdk.chat({ sessionId, message: "...", signal: ac.signal });
1430
1483
  ac.abort();
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function f(a){if(Array.isArray(a))return a.map(e=>f(e));if(a&&typeof a=="object"&&a.constructor===Object){const e={};for(const[t,n]of Object.entries(a)){const o=t.replace(/_([a-z])/g,(r,s)=>s.toUpperCase());e[o]=f(n)}return e}return a}const w="/api/agent/runtime/v1";class I{constructor(e){this.refreshing=null;const t=e.baseUrl??w;this.baseUrl=t.replace(/\/$/,""),this.tokenGateway=e.tokenGateway.replace(/\/$/,""),this.appId=e.appId??"",this.token=e.token??"",this.botId=e.botId,this.isAbsoluteUrl=/^https?:\/\//.test(this.baseUrl),this.isAbsoluteGateway=/^https?:\/\//.test(this.tokenGateway)}getBotId(){return this.botId}getAppKey(){return this.appId}setToken(e){this.token=e}getOrigin(){return typeof window<"u"?window.location.origin:""}async fetchToken(){const t=`${this.isAbsoluteGateway?this.tokenGateway:`${this.getOrigin()}${this.tokenGateway}`}/v1/token`,n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({botId:this.botId})});if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);const o=await n.json();if(o.code!=="200")throw new Error(o.message||`API error: ${o.code}`);const r=f(o.data);return this.token=r.token,r.appId&&!this.appId&&(this.appId=r.appId),r.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,n){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");let o=this.isAbsoluteUrl?`${this.baseUrl}${t}`:`${this.getOrigin()}${this.baseUrl}${t}`;if(n!=null&&n.params){const i=new URLSearchParams;for(const[l,d]of Object.entries(n.params))d!=null&&i.set(l,String(d));const c=i.toString();c&&(o+=`?${c}`)}const r=await fetch(o,{method:e,headers:this.headers(),body:n!=null&&n.body?JSON.stringify(n.body):void 0});if(r.status===401&&!(n!=null&&n.retry)&&await this.handleTokenRefresh())return this.request(e,t,{...n,retry:!0});if(!r.ok)throw new Error(`HTTP ${r.status}: ${r.statusText}`);const s=await r.json();if(s.code!=="200")throw new Error(s.message||`API error: ${s.code}`);return f(s.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,n){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");const o=this.isAbsoluteUrl?`${this.baseUrl}${e}`:`${this.getOrigin()}${this.baseUrl}${e}`,r=await fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:n});return r.status===401&&await this.handleTokenRefresh()?fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:n}):r}}function y(a){const e=a.split(`
2
- `).map(n=>n.trim()).filter(n=>n.startsWith("data:")).map(n=>n.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,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,renderMode:t.render_mode??t.renderMode,html:t.html};case"done":return{type:"done",content:t.content??"",sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_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 m(a,e,t){if(!a.body){t(new Error("Response body is null"));return}const n=a.body.getReader(),o=new TextDecoder;let r="";try{for(;;){const{value:s,done:i}=await n.read();if(i)break;r+=o.decode(s,{stream:!0});let c;for(;(c=r.indexOf(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function u(r){if(Array.isArray(r))return r.map(e=>u(e));if(r&&typeof r=="object"&&r.constructor===Object){const e={};for(const[t,s]of Object.entries(r)){const o=t.replace(/_([a-z])/g,(n,a)=>a.toUpperCase());e[o]=u(s)}return e}return r}const I="/api/agent/runtime/v1";class w{constructor(e){this.refreshing=null;const t=e.baseUrl??I;this.baseUrl=t.replace(/\/$/,""),this.tokenGateway=e.tokenGateway.replace(/\/$/,""),this.appId=e.appId??"",this.token=e.token??"",this.botId=e.botId,this.isAbsoluteUrl=/^https?:\/\//.test(this.baseUrl),this.isAbsoluteGateway=/^https?:\/\//.test(this.tokenGateway)}getBotId(){return this.botId}getAppKey(){return this.appId}setToken(e){this.token=e}getOrigin(){return typeof window<"u"?window.location.origin:""}async fetchToken(){const t=`${this.isAbsoluteGateway?this.tokenGateway:`${this.getOrigin()}${this.tokenGateway}`}/v1/token`,s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({botId:this.botId})});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);const o=await s.json();if(o.code!=="200")throw new Error(o.message||`API error: ${o.code}`);const n=u(o.data);return this.token=n.token,n.appId&&!this.appId&&(this.appId=n.appId),n.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,s){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");let o=this.isAbsoluteUrl?`${this.baseUrl}${t}`:`${this.getOrigin()}${this.baseUrl}${t}`;if(s!=null&&s.params){const i=new URLSearchParams;for(const[d,l]of Object.entries(s.params))l!=null&&i.set(d,String(l));const c=i.toString();c&&(o+=`?${c}`)}const n=await fetch(o,{method:e,headers:this.headers(),body:s!=null&&s.body?JSON.stringify(s.body):void 0});if(n.status===401&&!(s!=null&&s.retry)&&await this.handleTokenRefresh())return this.request(e,t,{...s,retry:!0});if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);const a=await n.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,s){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");const o=this.isAbsoluteUrl?`${this.baseUrl}${e}`:`${this.getOrigin()}${this.baseUrl}${e}`,n=await fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:s});return n.status===401&&await this.handleTokenRefresh()?fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:s}):n}}function y(r){const e=r.split(`
2
+ `).map(s=>s.trim()).filter(s=>s.startsWith("data:")).map(s=>s.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,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,renderMode:t.render_mode??t.renderMode,html:t.html};case"done":return{type:"done",content:t.content??"",sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id};case"stop":return{type:"stop",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 m(r,e,t){if(!r.body){t(new Error("Response body is null"));return}const s=r.body.getReader(),o=new TextDecoder;let n="";try{for(;;){const{value:a,done:i}=await s.read();if(i)break;n+=o.decode(a,{stream:!0});let c;for(;(c=n.indexOf(`
4
4
 
5
- `))!==-1;){const l=r.slice(0,c);r=r.slice(c+2);const d=y(l);d&&e(d)}}if(r.trim()){const s=y(r);s&&e(s)}}catch(s){(s==null?void 0:s.name)!=="AbortError"&&t(s instanceof Error?s:new Error(String(s)))}finally{try{n.releaseLock()}catch{}}}function k(a,e){const t=new AbortController,n=e.signal?b(e.signal,t.signal):t.signal,o={botId:a.getBotId(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1};return o.stream?a.streamPost("/chat",o,n).then(r=>{var s;if(!r.ok){(s=e.onError)==null||s.call(e,new Error(`HTTP ${r.status}`));return}return m(r,i=>{var c,l,d,h;i.type==="done"&&i.sessionId?(c=e.onDone)==null||c.call(e,{sessionId:i.sessionId,content:i.content,messageId:i.messageId}):i.type==="done"?(l=e.onDone)==null||l.call(e,{sessionId:"",content:i.content,messageId:i.messageId}):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(r=>{var s;(r==null?void 0:r.name)!=="AbortError"&&((s=e.onError)==null||s.call(e,r instanceof Error?r:new Error(String(r))))}):a.post("/chat",o).then(r=>{var s;(s=e.onDone)==null||s.call(e,{sessionId:r.sessionId,content:r.content??""})}).catch(r=>{var s;(s=e.onError)==null||s.call(e,r instanceof Error?r:new Error(String(r)))}),t}function b(a,e){const t=new AbortController,n=()=>t.abort();return a.addEventListener("abort",n,{once:!0}),e.addEventListener("abort",n,{once:!0}),(a.aborted||e.aborted)&&t.abort(),t.signal}async function T(a){return(await a.post("/chat/sessions",{botId:a.getBotId()})).sessionId}function S(a){return{sessionId:a.threadId??a.sessionId,botId:a.botId,title:a.title,createTime:a.createTime,updateTime:a.updateTime}}async function p(a,e){const t=await a.get("/chat/conversations",{botId:a.getBotId(),page:(e==null?void 0:e.page)??1,size:(e==null?void 0:e.size)??20});return{...t,items:t.items.map(S)}}async function $(a,e,t){await a.patch(`/chat/conversations/${e}`,{title:t})}async function A(a,e){await a.del(`/chat/conversations/${e}`)}async function C(a,e){const t=await a.get(`/chat/conversations/${e}/messages`);return O(t)}function O(a){var n,o,r;const e=[],t=[...a].sort((s,i)=>(s.seq??0)-(i.seq??0));for(const s of t){const i=s.role;if(i==="system")continue;const c=s.messageId??`msg_${s.id}`,l=new Date(s.createTime??"").getTime()||Date.now();if(i==="human")e.push({id:c,role:"user",parts:[{type:"text",content:s.content??""}],timestamp:l});else if(i==="ai"){const d=[];s.reasoning&&d.push({type:"thinking",content:s.reasoning}),s.content&&d.push({type:"text",content:s.content});const h=s.toolCalls;if(h&&Array.isArray(h))for(const u of h){let g;try{g=typeof u.args=="string"?u.args:JSON.stringify(u.args??{})}catch{g=String(u.args??"{}")}d.push({type:"tool_call",toolName:u.name??"",toolCallId:u.id??"",args:g})}e.push({id:c,role:"assistant",parts:d,timestamp:l})}else if(i==="tool"){const d=Array.isArray(s.artifacts)?s.artifacts:void 0;e.push({id:c,role:"assistant",parts:[{type:"tool_result",toolName:s.toolName??"",toolCallId:s.toolCallId??"",content:s.content??"",artifacts:d,renderMode:((n=s.metadata)==null?void 0:n.renderMode)??((o=s.metadata)==null?void 0:o.render_mode),html:(r=s.metadata)==null?void 0:r.html}],timestamp:l})}}return e}async function _(a,e,t,n,o,r){const s=await a.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:t,action:n.action,value:n.value});if(!s.ok){const i=new Error(`HTTP ${s.status}`);throw r==null||r(i),i}o&&await m(s,i=>{i.type==="error"?r==null||r(new Error(i.content)):o(i)},i=>r==null?void 0:r(i))}function v(a){const e=new I(a);return{getToken:()=>e.fetchToken(),createSession:()=>T(e),chat:n=>k(e,n),listConversations:n=>p(e,n),renameConversation:(n,o)=>$(e,n,o),deleteConversation:n=>A(e,n),getMessages:n=>C(e,n),respondInterrupt:(n,o,r,s,i)=>_(e,n,o,r,s,i),setToken:n=>e.setToken(n),feedback:async(n,o,r)=>{const s={type:o};o==="dislike"&&((r==null?void 0:r.reason)!=null&&(s.reason=r.reason),r!=null&&r.remark&&(s.remark=r.remark)),await e.post(`/chat/messages/${n}/feedback`,s)},cancelFeedback:async n=>{await e.del(`/chat/messages/${n}/feedback`)}}}exports.createSuperAgent=v;
5
+ `))!==-1;){const d=n.slice(0,c);n=n.slice(c+2);const l=y(d);l&&e(l)}}if(n.trim()){const a=y(n);a&&e(a)}}catch(a){(a==null?void 0:a.name)!=="AbortError"&&t(a instanceof Error?a:new Error(String(a)))}finally{try{s.releaseLock()}catch{}}}function p(r,e){const t=new AbortController,s=e.signal?b(e.signal,t.signal):t.signal,o={botId:r.getBotId(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1};return o.stream?r.streamPost("/chat",o,s).then(n=>{var a;if(!n.ok){(a=e.onError)==null||a.call(e,new Error(`HTTP ${n.status}`));return}return m(n,i=>{var c,d,l,h,f,g;i.type==="done"&&i.sessionId?(c=e.onDone)==null||c.call(e,{sessionId:i.sessionId,content:i.content,messageId:i.messageId}):i.type==="done"?(d=e.onDone)==null||d.call(e,{sessionId:"",content:i.content,messageId:i.messageId}):i.type==="stop"?((l=e.onMessage)==null||l.call(e,i),(h=e.onDone)==null||h.call(e,{sessionId:i.sessionId??"",content:i.content})):i.type==="error"?(f=e.onError)==null||f.call(e,new Error(i.content)):(g=e.onMessage)==null||g.call(e,i)},i=>{var c;return(c=e.onError)==null?void 0:c.call(e,i)})}).catch(n=>{var a;(n==null?void 0:n.name)!=="AbortError"&&((a=e.onError)==null||a.call(e,n instanceof Error?n:new Error(String(n))))}):r.post("/chat",o).then(n=>{var a;(a=e.onDone)==null||a.call(e,{sessionId:n.sessionId,content:n.content??"",messageId:n.messageId})}).catch(n=>{var a;(a=e.onError)==null||a.call(e,n instanceof Error?n:new Error(String(n)))}),t}function b(r,e){const t=new AbortController,s=()=>t.abort();return r.addEventListener("abort",s,{once:!0}),e.addEventListener("abort",s,{once:!0}),(r.aborted||e.aborted)&&t.abort(),t.signal}async function k(r){return(await r.post("/chat/sessions",{botId:r.getBotId()})).sessionId}function T(r){return{sessionId:r.threadId??r.sessionId,botId:r.botId,title:r.title,createTime:r.createTime,updateTime:r.updateTime}}async function S(r,e){const t=await r.get("/chat/conversations",{botId:r.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 $(r,e,t){await r.patch(`/chat/conversations/${e}`,{title:t})}async function A(r,e){await r.del(`/chat/conversations/${e}`)}async function C(r,e){const t=await r.get(`/chat/conversations/${e}/messages`);return O(t)}function O(r){const e=[...r].sort((a,i)=>(a.seq??0)-(i.seq??0)),t=new Map;for(const a of e)a.role==="tool"&&a.toolCallId&&t.set(a.toolCallId,a.content||"");const s=new Set,o=[],n=(a,i,c)=>{const d=o[o.length-1];(d==null?void 0:d.role)==="assistant"?(d.parts.push(...a),d.id=i):o.push({id:i,role:"assistant",parts:[...a],timestamp:c})};for(const a of e){if(a.role==="system")continue;const i=a.messageId??`msg_${a.id}`,c=new Date(a.createTime??"").getTime()||Date.now();if(a.role==="human"){o.push({id:i,role:"user",parts:[{type:"text",content:a.content??""}],timestamp:c});continue}if(a.role==="ai"){const d=P(a,t,s);d.length>0&&n(d,i,c);continue}if(a.role==="tool"){if(a.toolCallId&&s.has(a.toolCallId))continue;n([E(a)],i,c)}}return o}function P(r,e,t){const s=[];r.reasoning&&s.push({type:"thinking",content:r.reasoning}),r.content&&s.push({type:"text",content:r.content});for(const o of r.toolCalls??[])o.is_interrupt?(t.add(o.id),s.push(_(o,e))):s.push(v(o));return s}function _(r,e){const t=e.has(r.id),s=typeof r.args=="object"?r.args:{};return{type:"interrupt",interrupt:{interruptId:r.id??"",interruptType:s.interruptType??"input",content:s.content??"",options:s.options,placeholder:s.placeholder,inputType:s.inputType,maxLength:s.maxLength,required:s.required,fields:s.fields,metadata:s.metadata},resolved:t,response:t?{action:"submit",value:U(e.get(r.id))}:void 0}}function v(r){let e;try{e=typeof r.args=="string"?r.args:JSON.stringify(r.args??{})}catch{e=String(r.args??"{}")}return{type:"tool_call",toolName:r.name??"",toolCallId:r.id??"",args:e}}function E(r){var t,s,o;const e=Array.isArray(r.artifacts)?r.artifacts:void 0;return{type:"tool_result",toolName:r.toolName??"",toolCallId:r.toolCallId??"",content:r.content??"",artifacts:e,renderMode:((t=r.metadata)==null?void 0:t.renderMode)??((s=r.metadata)==null?void 0:s.render_mode),html:(o=r.metadata)==null?void 0:o.html}}function U(r){if(r!=null)try{return JSON.parse(r)}catch{return r}}async function x(r,e,t,s,o,n){const a=await r.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:t,action:s.action,value:s.value});if(!a.ok){const i=new Error(`HTTP ${a.status}`);throw n==null||n(i),i}o&&await m(a,i=>{i.type==="error"?n==null||n(new Error(i.content)):o(i)},i=>n==null?void 0:n(i))}async function q(r){return r.get(`/chat/bots/${r.getBotId()}/skills`)}async function N(r,e){await r.post("/chat/stop",{sessionId:e})}function L(r){const e=new w(r);return{getToken:()=>e.fetchToken(),createSession:()=>k(e),chat:s=>p(e,s),listConversations:s=>S(e,s),renameConversation:(s,o)=>$(e,s,o),deleteConversation:s=>A(e,s),getMessages:s=>C(e,s),respondInterrupt:(s,o,n,a,i)=>x(e,s,o,n,a,i),setToken:s=>e.setToken(s),feedback:async(s,o,n)=>{const a={type:o};o==="dislike"&&((n==null?void 0:n.reason)!=null&&(a.reason=n.reason),n!=null&&n.remark&&(a.remark=n.remark)),await e.post(`/chat/messages/${s}/feedback`,a)},cancelFeedback:async s=>{await e.del(`/chat/messages/${s}/feedback`)},listSkills:()=>q(e),stopGeneration:s=>N(e,s)}}exports.createSuperAgent=L;
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export declare interface ArtifactFile {
15
15
  }
16
16
 
17
17
  export declare interface ChatEvent {
18
- type: "user" | "thinking" | "ai" | "tool_call" | "tool_result" | "done" | "error" | "interrupt";
18
+ type: "user" | "thinking" | "ai" | "tool_call" | "tool_result" | "done" | "stop" | "error" | "interrupt";
19
19
  content: string;
20
20
  toolName?: string;
21
21
  toolCallId?: string;
@@ -137,6 +137,13 @@ export declare interface SDKConfig {
137
137
  token?: string;
138
138
  }
139
139
 
140
+ declare interface SkillInfo {
141
+ code: string;
142
+ name: string;
143
+ displayName: string | null;
144
+ description: string | null;
145
+ }
146
+
140
147
  export declare interface SuperAgentSDK {
141
148
  /** 获取 token(调用 POST {tokenGateway}/v1/token),自动设置内部凭证 */
142
149
  getToken(): Promise<string>;
@@ -157,6 +164,10 @@ export declare interface SuperAgentSDK {
157
164
  }): Promise<void>;
158
165
  /** 取消消息反馈,DELETE /chat/messages/{messageId}/feedback */
159
166
  cancelFeedback(messageId: string): Promise<void>;
167
+ /** 获取当前 bot 绑定的 skill 列表,GET /chat/bots/{botId}/skills */
168
+ listSkills(): Promise<SkillInfo[]>;
169
+ /** 停止生成(双信号:POST /chat/stop 广播 + abort SSE),半截回复保留 */
170
+ stopGeneration(sessionId: string): Promise<void>;
160
171
  }
161
172
 
162
173
  export declare interface UIMessage {