super-agent-sdk 1.0.6 → 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
@@ -144,6 +144,8 @@ export interface SuperAgentSDK {
144
144
  feedback(messageId: string, type: "like" | "dislike", options?: { reason?: number; remark?: string }): Promise<void>;
145
145
  cancelFeedback(messageId: string): Promise<void>;
146
146
  respondInterrupt(interruptId: string, sessionId: string, response: InterruptResponse): Promise<void>;
147
+ listSkills(): Promise<SkillInfo[]>;
148
+ stopGeneration(sessionId: string): Promise<void>;
147
149
  }
148
150
  ```
149
151
 
@@ -330,10 +332,12 @@ SDK 方法 → 后端接口的完整映射:
330
332
  | --------------------- | ------------------------- | --------------------------------------- | ----------------------------------------------- |
331
333
  | `getToken()` | `POST {gateway}/v1/token` | `{ botId }` | `{ token, appId }` |
332
334
  | `createSession()` | `POST /chat/sessions` | `{ botId }` | `{ sessionId }` |
333
- | `chat()` | `POST /chat` | `{ botId, sessionId, message, stream }` | SSE 流,`done` 事件含 `sessionId` |
335
+ | `chat()` | `POST /chat` | `{ botId, sessionId, message, stream }` | SSE 流,`done`/`stop` 事件含 `sessionId` |
334
336
  | `listConversations()` | `GET /chat/conversations` | 查询参数 `botId`、`page`、`size` | `{ items: [{ sessionId, botId, ... }], total }` |
335
337
  | `feedback()` | `POST /chat/messages/{messageId}/feedback` | `{ type, reason?, remark? }` | `null` |
336
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 }]` |
337
341
 
338
342
  ---
339
343
 
@@ -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
 
@@ -1101,7 +1107,8 @@ await sdk.deleteConversation(items[0].sessionId);
1101
1107
 
1102
1108
  ### 9.2 组件内置能力
1103
1109
 
1104
- - **自动加载**:挂载后自动调用 `listConversations` 拉取会话列表。
1110
+ - **自动加载**:挂载后自动调用 `listConversations` 拉取会话列表(每页 20 条)。
1111
+ - **滚动加载**:会话列表滚动到底部时自动加载下一页,支持任意数量的会话。
1105
1112
  - **切换**:点击会话项加载该会话历史消息并展示。
1106
1113
  - **新建**:点击「新会话」清空当前消息,下次发送时自动调用 `createSession()` 创建新会话。
1107
1114
  - **重命名**:`fullpage` 侧边栏或自定义 `ThreadList` 中调用 `renameConversation`。
@@ -1112,7 +1119,47 @@ await sdk.deleteConversation(items[0].sessionId);
1112
1119
 
1113
1120
  ## 10. 中断恢复
1114
1121
 
1115
- ### 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 中断请求
1116
1163
 
1117
1164
  `chat()` 返回 `AbortController`,可随时中断:
1118
1165
 
@@ -1134,7 +1181,7 @@ sdk.chat({ sessionId, message: "...", signal: ac.signal });
1134
1181
  ac.abort();
1135
1182
  ```
1136
1183
 
1137
- ### 10.2 会话恢复
1184
+ ### 10.3 会话恢复
1138
1185
 
1139
1186
  页面刷新或组件重新挂载时,会话状态自动恢复:
1140
1187
 
@@ -1194,6 +1241,7 @@ export interface ChatEvent {
1194
1241
  | "tool_call"
1195
1242
  | "tool_result"
1196
1243
  | "done"
1244
+ | "stop"
1197
1245
  | "error";
1198
1246
  content: string;
1199
1247
  toolName?: string;
@@ -1407,9 +1455,11 @@ function MyChat({ sdk }: { sdk: SuperAgentSDK }) {
1407
1455
 
1408
1456
  请求返回 `401` 时,SDK 自动重新调用 `POST {tokenGateway}/v1/token` 获取新 token。
1409
1457
 
1410
- ### 13.4 取消请求
1458
+ ### 13.4 停止与取消请求
1411
1459
 
1412
- `chat()` 返回 `AbortController`;或传入外部 `AbortSignal`(SDK 会合并内部信号,任一触发即中断):
1460
+ `chat()` 返回 `AbortController`;或传入外部 `AbortSignal`(SDK 会合并内部信号,任一触发即中断)。
1461
+
1462
+ 推荐使用双信号机制停止生成(Widget 内置停止按钮已自动处理):
1413
1463
 
1414
1464
  ```ts
1415
1465
  const controller = sdk.chat({
@@ -1418,11 +1468,16 @@ const controller = sdk.chat({
1418
1468
  stream: true,
1419
1469
  onDone,
1420
1470
  });
1421
- // 稍后取消
1471
+ // 双信号停止:abort 断 SSE + POST /chat/stop 广播后端取消
1422
1472
  controller.abort();
1473
+ await sdk.stopGeneration(sessionId);
1423
1474
  ```
1424
1475
 
1476
+ 纯客户端取消(不通知后端):
1477
+
1425
1478
  ```ts
1479
+ controller.abort();
1480
+ // 或使用外部 signal
1426
1481
  const ac = new AbortController();
1427
1482
  sdk.chat({ sessionId, message: "...", signal: ac.signal });
1428
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??"",messageId:r.messageId})}).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 {