super-agent-sdk 1.0.17 → 1.0.19

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
@@ -86,7 +86,7 @@ function createSuperAgent(config: SDKConfig): SuperAgentSDK;
86
86
  ```ts
87
87
  export interface SDKConfig {
88
88
  botId: number; // Bot ID(必填)
89
- tokenGateway: string; // Token 网关前缀(必填,不带 host),如 "/api/gateway";token URL = {origin}{tokenGateway}/v1/token
89
+ tokenGateway: string; // Token 网关前缀(必填,不带 host),如 "/api/gateway";token URL = {origin}{tokenGateway}/v2/token/generate
90
90
  baseUrl?: string; // 业务接口前缀(可选,默认 "/api/agent/runtime/v1"),不带 host
91
91
  appId?: string; // 可选,不传则从 token 接口响应自动获取
92
92
  token?: string; // 可选,不传则自动调 token 接口获取
@@ -109,7 +109,7 @@ createSuperAgent({ botId, tokenGateway })
109
109
  ↓
110
110
  Widget 挂载时自动调用 sdk.getToken()
111
111
  ↓
112
- POST {origin}{tokenGateway}/v1/token(body: { botId })
112
+ POST {origin}{tokenGateway}/v2/token/generate(body: { botId })
113
113
  ↓
114
114
  后端返回 { token, appId }
115
115
  ↓
@@ -323,7 +323,7 @@ sdk.getToken(): Promise<string>
323
323
 
324
324
  自动获取并保存访问 token:
325
325
 
326
- - SDK 调用 `POST {origin}{tokenGateway}/v1/token`,请求体 `{ botId }`
326
+ - SDK 调用 `POST {origin}{tokenGateway}/v2/token/generate`,请求体 `{ botId }`
327
327
  - 后端返回 `{ token, appId }`
328
328
  - SDK 自动将 token + appId 保存在内部
329
329
  - Widget 在挂载时自动调用此方法 —— 通常无需手动调用
@@ -433,7 +433,7 @@ SDK 方法 → 后端接口的完整映射:
433
433
 
434
434
  | SDK 方法 | HTTP 请求 | 请求体 | 后端返回 |
435
435
  | --------------------- | -------------------------------------------- | --------------------------------------- | ----------------------------------------------- |
436
- | `getToken()` | `POST {gateway}/v1/token` | `{ botId }` | `{ token, appId }` |
436
+ | `getToken()` | `POST {gateway}/v2/token/generate` | `{ botId }` | `{ token, appId }` |
437
437
  | `createSession()` | `POST /chat/sessions` | `{ botId }` | `{ sessionId }` |
438
438
  | `chat()` | `POST /chat` | `{ botId, sessionId, message, stream, attachments? }` | SSE 流,`done`/`stop` 事件含 `sessionId` |
439
439
  | `listConversations()` | `GET /chat/conversations` | 查询参数 `botId`、`page`、`size` | `{ items: [{ sessionId, botId, ... }], total }` |
@@ -757,7 +757,7 @@ function MyTrigger({ isOpen, onClick, unreadCount }: TriggerProps) {
757
757
 
758
758
  floating 与 fullpage 模式均支持替换;`onToggleThreadList` 在 floating 下切换内嵌会话侧边栏、在 fullpage 下切换左侧边栏;开启 `artifactPreview` 后额外提供产物入口字段。
759
759
 
760
- > 注:fullpage 内置 Header 只有标题与产物入口(无关闭按钮);需要关闭入口时通过自定义 Header 的 `onClose` 自行渲染。floating 内置 Header 含历史/回首页/大窗/关闭按钮。
760
+ > 注:fullpage 内置 Header 有标题与产物入口(无关闭按钮);整屏容器态标题换成面板 `title`、并出现 home 返回入口,需要关闭入口时通过自定义 Header 的 `onClose` 自行渲染。floating 内置 Header 含历史/回首页/大窗/关闭按钮。
761
761
 
762
762
  ```ts
763
763
  export interface HeaderProps {
@@ -766,10 +766,11 @@ export interface HeaderProps {
766
766
  onToggleThreadList: () => void;
767
767
  isMaximized?: boolean; // floating:大窗状态
768
768
  onToggleMaximize?: () => void; // floating:大窗/小窗切换
769
- showHome?: boolean; // floating:聊天态显示回到首页
770
- onHome?: () => void; // floating:回到首页(新会话)
769
+ showHome?: boolean; // floating:聊天态显示回到首页;整屏容器态显示「返回聊天」
770
+ onHome?: () => void; // 回到首页(新会话);整屏容器态为 closePanel 返回聊天
771
771
  artifactCount?: number; // 会话产物数量(artifactPreview 开启时提供)
772
772
  onToggleArtifactDrawer?: () => void; // 打开/关闭产物预览抽屉
773
+ panelTitle?: string; // 整屏容器态:面板标题(内置 Header 居中显示;自定义 Header 据此自行渲染)
773
774
  }
774
775
  ```
775
776
 
@@ -1138,9 +1139,9 @@ mount("#app", {
1138
1139
  | 项 | 表现 |
1139
1140
  | --- | --- |
1140
1141
  | 呈现 | 替换「内容区 + 输入区」,Header 保留(小窗仍可拖拽);`link` 走 `window.open`,不占状态 |
1141
- | 标题栏 | 返回箭头 + `title`(可选);`Esc` 等价返回 |
1142
+ | 标题 | 无独立标题栏(纯白背景);`title` 传入时显示在 **Header 居中**(floating 内置 Header / fullpage 均适用,自定义 `slots.Header` 收 `panelTitle` 自行渲染) |
1143
+ | 退出 | Header 的 home 图标(tooltip「返回聊天」)/ 业务组件 `close()` / `Esc`;关闭聊天面板时一并清掉 |
1142
1144
  | 窗口几何 | 保持打开前窗态,小窗不自动升大窗;内容在容器内滚动(业务页不写滚动容器) |
1143
- | 关闭 | 返回 / `close()` / `Esc`;关闭聊天面板时一并清掉 |
1144
1145
  | 栈 | 单层不叠栈,容器内部导航由业务组件自己管 |
1145
1146
 
1146
1147
  注意:浮层组件渲染在 SDK 自己的 `createRoot` 树内,拿不到宿主的 React Context / Router。组件引用直接给,不需要注册表——类型即校验。
@@ -1795,7 +1796,7 @@ function MyChat({ sdk }: { sdk: SuperAgentSDK }) {
1795
1796
 
1796
1797
  ### 13.3 Token 续期
1797
1798
 
1798
- 请求返回 `401` 时,SDK 自动重新调用 `POST {tokenGateway}/v1/token` 获取新 token。
1799
+ 请求返回 `401` 时,SDK 自动重新调用 `POST {tokenGateway}/v2/token/generate` 获取新 token。
1799
1800
 
1800
1801
  ### 13.4 停止与取消请求
1801
1802
 
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("./nosUploader-CgVOa1Lz.cjs");function f(r){if(Array.isArray(r))return r.map(e=>f(e));if(r&&typeof r=="object"&&r.constructor===Object){const e={};for(const[i,n]of Object.entries(r)){const d=i.replace(/_([a-z])/g,(t,s)=>s.toUpperCase());e[d]=f(n)}return e}return r}const S="/api/agent/runtime/v1";class A{constructor(e){this.refreshing=null;const i=e.baseUrl??S;this.baseUrl=i.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),this.loginUrl=e.loginUrl,this.onAuthExpired=e.onAuthExpired}getBotId(){return this.botId}getAppKey(){return this.appId}setToken(e){this.token=e}getOrigin(){return typeof window<"u"?window.location.origin:""}async fetchToken(){const i=`${this.isAbsoluteGateway?this.tokenGateway:`${this.getOrigin()}${this.tokenGateway}`}/v1/token`,n=await fetch(i,{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 d=await n.json();if(d.code!=="200")throw new Error(d.message||`API error: ${d.code}`);const t=f(d.data);return this.token=t.token,t.appId&&!this.appId&&(this.appId=t.appId),t.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,i,n){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");let d=this.isAbsoluteUrl?`${this.baseUrl}${i}`:`${this.getOrigin()}${this.baseUrl}${i}`;if(n!=null&&n.params){const o=new URLSearchParams;for(const[c,l]of Object.entries(n.params))l!=null&&o.set(c,String(l));const a=o.toString();a&&(d+=`?${a}`)}const t=await fetch(d,{method:e,headers:this.headers(),body:n!=null&&n.body?JSON.stringify(n.body):void 0});if(t.status===401&&!(n!=null&&n.retry)&&await this.handleTokenRefresh())return this.request(e,i,{...n,retry:!0});if(!t.ok){let o=`HTTP ${t.status}: ${t.statusText}`;try{const a=await t.json();a!=null&&a.message&&(o=a.message)}catch{}throw new Error(o)}const s=await t.json();if(s.code!=="200")throw new Error(s.message||`API error: ${s.code}`);return f(s.data)}get(e,i){return this.request("GET",e,{params:i})}post(e,i){return this.request("POST",e,{body:i})}patch(e,i){return this.request("PATCH",e,{body:i})}del(e){return this.request("DELETE",e)}async streamPost(e,i,n){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");const d=this.isAbsoluteUrl?`${this.baseUrl}${e}`:`${this.getOrigin()}${this.baseUrl}${e}`,t=await fetch(d,{method:"POST",headers:this.headers(),body:JSON.stringify(i),signal:n});if(t.status===401){const s=await h.peekCookieExpired(t.clone());if(s.isCookieExpired&&typeof(i==null?void 0:i.message)=="string"){h.stashPendingChat({botId:this.botId,message:i.message,sessionId:i.sessionId??""});const a=s.loginUrl??this.loginUrl;return this.onAuthExpired?this.onAuthExpired({loginUrl:a,sessionId:s.sessionId,botId:this.botId}):a&&window.location.replace(a),t}if(await this.handleTokenRefresh())return fetch(d,{method:"POST",headers:this.headers(),body:JSON.stringify(i),signal:n})}return t}}function u(r){return typeof r=="string"?r:Array.isArray(r)?r.map(e=>{if(typeof e=="string")return e;if(e&&typeof e=="object"){if(typeof e.text=="string")return e.text;if(e.type)return`[${e.type}${e.mime_type?": "+e.mime_type:""}]`}return""}).join(""):r==null?"":String(r)}function k(r){const e=r.split(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("./nosUploader-CgVOa1Lz.cjs");function f(r){if(Array.isArray(r))return r.map(e=>f(e));if(r&&typeof r=="object"&&r.constructor===Object){const e={};for(const[i,n]of Object.entries(r)){const d=i.replace(/_([a-z])/g,(t,s)=>s.toUpperCase());e[d]=f(n)}return e}return r}const S="/api/agent/runtime/v1";class A{constructor(e){this.refreshing=null,this.tokenPromise=null;const i=e.baseUrl??S;this.baseUrl=i.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),this.loginUrl=e.loginUrl,this.onAuthExpired=e.onAuthExpired}getBotId(){return this.botId}getAppKey(){return this.appId}setToken(e){this.token=e}getOrigin(){return typeof window<"u"?window.location.origin:""}async fetchToken(){if(this.token)return this.token;if(this.tokenPromise)return this.tokenPromise;this.tokenPromise=(async()=>{const i=`${this.isAbsoluteGateway?this.tokenGateway:`${this.getOrigin()}${this.tokenGateway}`}/v2/token/generate`,n=await fetch(i,{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 d=await n.json();if(d.code!=="200")throw new Error(d.message||`API error: ${d.code}`);const t=f(d.data);return this.token=t.token,t.appId&&!this.appId&&(this.appId=t.appId),t.token})();try{return await this.tokenPromise}finally{this.tokenPromise=null}}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.token="",this.refreshing=(async()=>{await this.fetchToken()})(),await this.refreshing,!0}catch{return!1}finally{this.refreshing=null}}async request(e,i,n){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");let d=this.isAbsoluteUrl?`${this.baseUrl}${i}`:`${this.getOrigin()}${this.baseUrl}${i}`;if(n!=null&&n.params){const o=new URLSearchParams;for(const[c,l]of Object.entries(n.params))l!=null&&o.set(c,String(l));const a=o.toString();a&&(d+=`?${a}`)}const t=await fetch(d,{method:e,headers:this.headers(),body:n!=null&&n.body?JSON.stringify(n.body):void 0});if(t.status===401&&!(n!=null&&n.retry)&&await this.handleTokenRefresh())return this.request(e,i,{...n,retry:!0});if(!t.ok){let o=`HTTP ${t.status}: ${t.statusText}`;try{const a=await t.json();a!=null&&a.message&&(o=a.message)}catch{}throw new Error(o)}const s=await t.json();if(s.code!=="200")throw new Error(s.message||`API error: ${s.code}`);return f(s.data)}get(e,i){return this.request("GET",e,{params:i})}post(e,i){return this.request("POST",e,{body:i})}patch(e,i){return this.request("PATCH",e,{body:i})}del(e){return this.request("DELETE",e)}async streamPost(e,i,n){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");const d=this.isAbsoluteUrl?`${this.baseUrl}${e}`:`${this.getOrigin()}${this.baseUrl}${e}`,t=await fetch(d,{method:"POST",headers:this.headers(),body:JSON.stringify(i),signal:n});if(t.status===401){const s=await h.peekCookieExpired(t.clone());if(s.isCookieExpired&&typeof(i==null?void 0:i.message)=="string"){h.stashPendingChat({botId:this.botId,message:i.message,sessionId:i.sessionId??""});const a=s.loginUrl??this.loginUrl;return this.onAuthExpired?this.onAuthExpired({loginUrl:a,sessionId:s.sessionId,botId:this.botId}):a&&window.location.replace(a),t}if(await this.handleTokenRefresh())return fetch(d,{method:"POST",headers:this.headers(),body:JSON.stringify(i),signal:n})}return t}}function u(r){return typeof r=="string"?r:Array.isArray(r)?r.map(e=>{if(typeof e=="string")return e;if(e&&typeof e=="object"){if(typeof e.text=="string")return e.text;if(e.type)return`[${e.type}${e.mime_type?": "+e.mime_type:""}]`}return""}).join(""):r==null?"":String(r)}function k(r){const e=r.split(`
2
2
  `).map(o=>o.trim()).filter(o=>o.length>0);let i,n,d;for(const o of e)if(o.startsWith("id:"))i=o.slice(3).trim();else if(o.startsWith("event:"))n=o.slice(6).trim();else if(o.startsWith("data:")){const a=o.slice(5).trim();d=d?`${d}
3
- ${a}`:a}if(d===void 0)return null;let t;try{t=JSON.parse(d)}catch{return null}const s=t.type==="tool_result"&&typeof t.content=="object"&&t.content?t.content:void 0;switch(t.type){case"session.start":return{type:"session.start",content:"",sessionId:t.sessionId??t.session_id??"",roundId:t.roundId??t.round_id,event:n,id:i};case"user":return{type:"user",content:u(t.content),event:n,id:i};case"thinking":return{type:"thinking",content:u(t.content),event:n,id:i};case"ai":return{type:"ai",content:u(t.content),event:n,id:i};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??{}),event:n,id:i};case"tool_result":{const o=s==null?void 0:s.result;let a;return typeof o=="string"?a=o:o!=null&&typeof o=="object"?a=JSON.stringify(o):s&&typeof s=="object"&&Object.keys(s).length>0?a=JSON.stringify(s):a=u(t.output??""),{type:"tool_result",content:a,toolName:t.name,toolCallId:t.id,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,renderMode:(s==null?void 0:s.render_mode)??t.render_mode??t.renderMode,html:(s==null?void 0:s.html)??t.html,markdown:(s==null?void 0:s.markdown)??t.markdown,event:n,id:i}}case"done":return{type:"done",content:u(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id,roundId:t.roundId??t.round_id,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,event:n,id:i};case"stop":return{type:"stop",content:u(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id,roundId:t.roundId??t.round_id,event:n,id:i};case"error":return{type:"error",content:t.message??"Unknown error",event:n,id:i};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},event:n,id:i};default:return null}}async function b(r,e,i){if(!r.body){i(new Error("Response body is null"));return}const n=r.body.getReader(),d=new TextDecoder;let t="";try{for(;;){const{value:s,done:o}=await n.read();if(o)break;t+=d.decode(s,{stream:!0});let a;for(;(a=t.indexOf(`
3
+ ${a}`:a}if(d===void 0)return null;let t;try{t=JSON.parse(d)}catch{return null}const s=t.type==="tool_result"&&typeof t.content=="object"&&t.content?t.content:void 0;switch(t.type){case"session.start":return{type:"session.start",content:"",sessionId:t.sessionId??t.session_id??"",roundId:t.roundId??t.round_id,event:n,id:i};case"user":return{type:"user",content:u(t.content),event:n,id:i};case"thinking":return{type:"thinking",content:u(t.content),event:n,id:i};case"ai":return{type:"ai",content:u(t.content),event:n,id:i};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??{}),event:n,id:i};case"tool_delta":return{type:"tool_delta",content:typeof t.content=="string"?t.content:"",toolCallId:t.tool_call_id??t.toolCallId??"",event:n,id:i};case"tool_result":{const o=s==null?void 0:s.result;let a;return typeof o=="string"?a=o:o!=null&&typeof o=="object"?a=JSON.stringify(o):s&&typeof s=="object"&&Object.keys(s).length>0?a=JSON.stringify(s):a=u(t.output??""),{type:"tool_result",content:a,toolName:t.name,toolCallId:t.id,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,renderMode:(s==null?void 0:s.render_mode)??t.render_mode??t.renderMode,html:(s==null?void 0:s.html)??t.html,markdown:(s==null?void 0:s.markdown)??t.markdown,event:n,id:i}}case"done":return{type:"done",content:u(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id,roundId:t.roundId??t.round_id,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,event:n,id:i};case"stop":return{type:"stop",content:u(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id,roundId:t.roundId??t.round_id,event:n,id:i};case"error":return{type:"error",content:t.message??"Unknown error",event:n,id:i};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},event:n,id:i};default:return null}}async function b(r,e,i){if(!r.body){i(new Error("Response body is null"));return}const n=r.body.getReader(),d=new TextDecoder;let t="";try{for(;;){const{value:s,done:o}=await n.read();if(o)break;t+=d.decode(s,{stream:!0});let a;for(;(a=t.indexOf(`
4
4
 
5
- `))!==-1;){const c=t.slice(0,a);t=t.slice(a+2);const l=k(c);l&&e(l)}}if(t.trim()){const s=k(t);s&&e(s)}}catch(s){(s==null?void 0:s.name)!=="AbortError"&&i(s instanceof Error?s:new Error(String(s)))}finally{try{n.releaseLock()}catch{}}}function $(r,e){var t;const i=new AbortController,n=e.signal?_(e.signal,i.signal):i.signal,d={botId:r.getBotId(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1,...(t=e.attachments)!=null&&t.length?{attachments:e.attachments.map(({url:s,...o})=>o)}:{}};return d.stream?r.streamPost("/chat",d,n).then(async s=>{var o;if(!s.ok){let a=`HTTP ${s.status}`;try{const c=await s.json();c!=null&&c.message&&(a=c.message)}catch{}(o=e.onError)==null||o.call(e,new Error(a));return}return b(s,a=>{var c,l,g,m,y,I,p,w;a.type==="done"&&a.sessionId?((c=e.onMessage)==null||c.call(e,a),(l=e.onDone)==null||l.call(e,{sessionId:a.sessionId,content:a.content,messageId:a.messageId,roundId:a.roundId,artifacts:a.artifacts})):a.type==="done"?((g=e.onMessage)==null||g.call(e,a),(m=e.onDone)==null||m.call(e,{sessionId:"",content:a.content,messageId:a.messageId,roundId:a.roundId,artifacts:a.artifacts})):a.type==="stop"?((y=e.onMessage)==null||y.call(e,a),(I=e.onDone)==null||I.call(e,{sessionId:a.sessionId??"",content:a.content,messageId:a.messageId,roundId:a.roundId})):a.type==="error"?(p=e.onError)==null||p.call(e,new Error(a.content)):(w=e.onMessage)==null||w.call(e,a)},a=>{var c;return(c=e.onError)==null?void 0:c.call(e,a)})}).catch(s=>{var o;(s==null?void 0:s.name)!=="AbortError"&&((o=e.onError)==null||o.call(e,s instanceof Error?s:new Error(String(s))))}):r.post("/chat",d).then(s=>{var o;(o=e.onDone)==null||o.call(e,{sessionId:s.sessionId,content:s.content??"",messageId:s.messageId})}).catch(s=>{var o;(o=e.onError)==null||o.call(e,s instanceof Error?s:new Error(String(s)))}),i}function _(r,e){const i=new AbortController,n=()=>i.abort();return r.addEventListener("abort",n,{once:!0}),e.addEventListener("abort",n,{once:!0}),(r.aborted||e.aborted)&&i.abort(),i.signal}async function E(r){return(await r.post("/chat/sessions",{botId:r.getBotId()})).sessionId}function O(r){return{sessionId:r.threadId??r.sessionId,botId:r.botId,title:r.title,createTime:r.createTime,updateTime:r.updateTime}}async function v(r,e){const i=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{...i,items:i.items.map(O)}}async function x(r,e,i){await r.patch(`/chat/conversations/${e}`,{title:i})}async function P(r,e){await r.del(`/chat/conversations/${e}`)}async function C(r,e){const i=await r.get(`/chat/conversations/${e}/messages`);return U(i)}function T(){return`r_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}function U(r){var d;const e=r.length>0&&Array.isArray((d=r[0])==null?void 0:d.data),i=[];if(e)for(const t of r)i.push({roundId:t.roundId??T(),artifacts:Array.isArray(t.artifacts)&&t.artifacts.length?t.artifacts:void 0,items:Array.isArray(t.data)?t.data:[]});else i.push({roundId:T(),items:r});const n=[];for(const t of i){const s=N(t.items);for(const o of s)o.roundId=t.roundId;if(t.artifacts){const o=s.findLast(a=>a.role==="assistant");o&&(o.artifacts=t.artifacts)}n.push(...s)}return n}function N(r){const e=[...r].sort((s,o)=>{const a=new Date(s.createTime??0).getTime()||0,c=new Date(o.createTime??0).getTime()||0;return a!==c?a-c:(s.seq??0)-(o.seq??0)}),i=new Map;for(const s of e)s.role==="tool"&&s.toolCallId&&i.set(s.toolCallId,s.content||"");const n=new Set,d=[],t=(s,o,a)=>{const c=d[d.length-1];(c==null?void 0:c.role)==="assistant"?(c.parts.push(...s),c.id=o):d.push({id:o,role:"assistant",parts:[...s],timestamp:a})};for(const s of e){if(s.role==="system")continue;const o=String(s.id??s.messageId??`msg_${Date.now()}`),a=new Date(s.createTime??"").getTime()||Date.now();if(s.role==="human"){const c=(s.attachments??[]).map(l=>({type:"attachment",attachment:{nosKey:l.nosKey??l.attachmentId??"",filename:l.filename??"file",size:l.size??void 0,mime:l.mime??void 0,url:l.url??void 0}}));d.push({id:o,role:"user",parts:[...c,{type:"text",content:u(s.content)}],timestamp:a});continue}if(s.role==="ai"){const c=M(s,i,n);c.length>0&&t(c,o,a);continue}if(s.role==="tool"){if(s.toolCallId&&n.has(s.toolCallId))continue;t([j(s)],o,a)}}return d}function M(r,e,i){const n=[];r.reasoning&&n.push({type:"thinking",content:r.reasoning}),r.content&&n.push({type:"text",content:u(r.content)});for(const d of r.toolCalls??[])d.is_interrupt??d.isInterrupt?(i.add(d.id),n.push(D(d,e))):n.push(q(d));return n}function D(r,e){const i=e.has(r.id),n=typeof r.args=="object"?r.args:{};return{type:"interrupt",interrupt:{interruptId:r.id??"",interruptType:n.interruptType??"input",content:n.content??"",options:n.options,placeholder:n.placeholder,inputType:n.inputType,maxLength:n.maxLength,required:n.required,fields:n.fields,metadata:n.metadata},resolved:i,response:i?{action:"submit",value:J(e.get(r.id))}:void 0}}function q(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 j(r){var i,n,d,t;const e=Array.isArray(r.artifacts)?r.artifacts:void 0;return{type:"tool_result",toolName:r.toolName??"",toolCallId:r.toolCallId??"",content:u(r.content),artifacts:e,renderMode:r.renderMode??((i=r.metadata)==null?void 0:i.renderMode)??((n=r.metadata)==null?void 0:n.render_mode),html:r.html??((d=r.metadata)==null?void 0:d.html),markdown:r.markdown??((t=r.metadata)==null?void 0:t.markdown)}}function J(r){if(r!=null)try{return JSON.parse(r)}catch{return r}}async function L(r,e,i,n,d,t,s){const o=await r.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:i,action:n.action,value:n.value},s);if(!o.ok){const a=new Error(`HTTP ${o.status}`);throw t==null||t(a),a}d&&await b(o,a=>{a.type==="error"?t==null||t(new Error(a.content)):d(a)},a=>t==null?void 0:t(a))}async function G(r){return r.get(`/chat/bots/${r.getBotId()}/skills`)}async function R(r,e){await r.post("/chat/stop",{sessionId:e})}function B(r){const e=new A(r);return{botId:e.getBotId(),getToken:()=>e.fetchToken(),createSession:()=>E(e),chat:n=>$(e,n),listConversations:n=>v(e,n),renameConversation:(n,d)=>x(e,n,d),deleteConversation:n=>P(e,n),getMessages:n=>C(e,n),respondInterrupt:(n,d,t,s,o,a)=>L(e,n,d,t,s,o,a),setToken:n=>e.setToken(n),feedback:async(n,d,t)=>{const s={type:d};d==="dislike"&&((t==null?void 0:t.reason)!=null&&(s.reason=t.reason),t!=null&&t.remark&&(s.remark=t.remark)),await e.post(`/chat/messages/${n}/feedback`,s)},cancelFeedback:async n=>{await e.del(`/chat/messages/${n}/feedback`)},listSkills:()=>G(e),stopGeneration:n=>R(e,n)}}exports.createNosUploader=h.createNosUploader;exports.createSuperAgent=B;
5
+ `))!==-1;){const c=t.slice(0,a);t=t.slice(a+2);const l=k(c);l&&e(l)}}if(t.trim()){const s=k(t);s&&e(s)}}catch(s){(s==null?void 0:s.name)!=="AbortError"&&i(s instanceof Error?s:new Error(String(s)))}finally{try{n.releaseLock()}catch{}}}function $(r,e){var t;const i=new AbortController,n=e.signal?_(e.signal,i.signal):i.signal,d={botId:r.getBotId(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1,...(t=e.attachments)!=null&&t.length?{attachments:e.attachments.map(({url:s,...o})=>o)}:{}};return d.stream?r.streamPost("/chat",d,n).then(async s=>{var o;if(!s.ok){let a=`HTTP ${s.status}`;try{const c=await s.json();c!=null&&c.message&&(a=c.message)}catch{}(o=e.onError)==null||o.call(e,new Error(a));return}return b(s,a=>{var c,l,g,m,y,I,p,w;a.type==="done"&&a.sessionId?((c=e.onMessage)==null||c.call(e,a),(l=e.onDone)==null||l.call(e,{sessionId:a.sessionId,content:a.content,messageId:a.messageId,roundId:a.roundId,artifacts:a.artifacts})):a.type==="done"?((g=e.onMessage)==null||g.call(e,a),(m=e.onDone)==null||m.call(e,{sessionId:"",content:a.content,messageId:a.messageId,roundId:a.roundId,artifacts:a.artifacts})):a.type==="stop"?((y=e.onMessage)==null||y.call(e,a),(I=e.onDone)==null||I.call(e,{sessionId:a.sessionId??"",content:a.content,messageId:a.messageId,roundId:a.roundId})):a.type==="error"?(p=e.onError)==null||p.call(e,new Error(a.content)):(w=e.onMessage)==null||w.call(e,a)},a=>{var c;return(c=e.onError)==null?void 0:c.call(e,a)})}).catch(s=>{var o;(s==null?void 0:s.name)!=="AbortError"&&((o=e.onError)==null||o.call(e,s instanceof Error?s:new Error(String(s))))}):r.post("/chat",d).then(s=>{var o;(o=e.onDone)==null||o.call(e,{sessionId:s.sessionId,content:s.content??"",messageId:s.messageId})}).catch(s=>{var o;(o=e.onError)==null||o.call(e,s instanceof Error?s:new Error(String(s)))}),i}function _(r,e){const i=new AbortController,n=()=>i.abort();return r.addEventListener("abort",n,{once:!0}),e.addEventListener("abort",n,{once:!0}),(r.aborted||e.aborted)&&i.abort(),i.signal}async function P(r){return(await r.post("/chat/sessions",{botId:r.getBotId()})).sessionId}function v(r){return{sessionId:r.threadId??r.sessionId,botId:r.botId,title:r.title,createTime:r.createTime,updateTime:r.updateTime}}async function E(r,e){const i=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{...i,items:i.items.map(v)}}async function O(r,e,i){await r.patch(`/chat/conversations/${e}`,{title:i})}async function C(r,e){await r.del(`/chat/conversations/${e}`)}async function x(r,e){const i=await r.get(`/chat/conversations/${e}/messages`);return U(i)}function T(){return`r_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}function U(r){var d;const e=r.length>0&&Array.isArray((d=r[0])==null?void 0:d.data),i=[];if(e)for(const t of r)i.push({roundId:t.roundId??T(),artifacts:Array.isArray(t.artifacts)&&t.artifacts.length?t.artifacts:void 0,items:Array.isArray(t.data)?t.data:[]});else i.push({roundId:T(),items:r});const n=[];for(const t of i){const s=N(t.items);for(const o of s)o.roundId=t.roundId;if(t.artifacts){const o=s.findLast(a=>a.role==="assistant");o&&(o.artifacts=t.artifacts)}n.push(...s)}return n}function N(r){const e=[...r].sort((s,o)=>{const a=new Date(s.createTime??0).getTime()||0,c=new Date(o.createTime??0).getTime()||0;return a!==c?a-c:(s.seq??0)-(o.seq??0)}),i=new Map;for(const s of e)s.role==="tool"&&s.toolCallId&&i.set(s.toolCallId,s.content||"");const n=new Set,d=[],t=(s,o,a)=>{const c=d[d.length-1];(c==null?void 0:c.role)==="assistant"?(c.parts.push(...s),c.id=o):d.push({id:o,role:"assistant",parts:[...s],timestamp:a})};for(const s of e){if(s.role==="system")continue;const o=String(s.id??s.messageId??`msg_${Date.now()}`),a=new Date(s.createTime??"").getTime()||Date.now();if(s.role==="human"){const c=(s.attachments??[]).map(l=>({type:"attachment",attachment:{nosKey:l.nosKey??l.attachmentId??"",filename:l.filename??"file",size:l.size??void 0,mime:l.mime??void 0,url:l.url??void 0}}));d.push({id:o,role:"user",parts:[...c,{type:"text",content:u(s.content)}],timestamp:a});continue}if(s.role==="ai"){const c=M(s,i,n);c.length>0&&t(c,o,a);continue}if(s.role==="tool"){if(s.toolCallId&&n.has(s.toolCallId))continue;t([j(s)],o,a)}}return d}function M(r,e,i){const n=[];r.reasoning&&n.push({type:"thinking",content:r.reasoning}),r.content&&n.push({type:"text",content:u(r.content)});for(const d of r.toolCalls??[])d.is_interrupt??d.isInterrupt?(i.add(d.id),n.push(D(d,e))):n.push(q(d));return n}function D(r,e){const i=e.has(r.id),n=typeof r.args=="object"?r.args:{};return{type:"interrupt",interrupt:{interruptId:r.id??"",interruptType:n.interruptType??"input",content:n.content??"",options:n.options,placeholder:n.placeholder,inputType:n.inputType,maxLength:n.maxLength,required:n.required,fields:n.fields,metadata:n.metadata},resolved:i,response:i?{action:"submit",value:J(e.get(r.id))}:void 0}}function q(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 j(r){var i,n,d,t;const e=Array.isArray(r.artifacts)?r.artifacts:void 0;return{type:"tool_result",toolName:r.toolName??"",toolCallId:r.toolCallId??"",content:u(r.content),artifacts:e,renderMode:r.renderMode??((i=r.metadata)==null?void 0:i.renderMode)??((n=r.metadata)==null?void 0:n.render_mode),html:r.html??((d=r.metadata)==null?void 0:d.html),markdown:r.markdown??((t=r.metadata)==null?void 0:t.markdown)}}function J(r){if(r!=null)try{return JSON.parse(r)}catch{return r}}async function L(r,e,i,n,d,t,s){const o=await r.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:i,action:n.action,value:n.value},s);if(!o.ok){const a=new Error(`HTTP ${o.status}`);throw t==null||t(a),a}d&&await b(o,a=>{a.type==="error"?t==null||t(new Error(a.content)):d(a)},a=>t==null?void 0:t(a))}async function G(r){return r.get(`/chat/bots/${r.getBotId()}/skills`)}async function R(r,e){await r.post("/chat/stop",{sessionId:e})}function B(r){const e=new A(r);return{botId:e.getBotId(),getToken:()=>e.fetchToken(),createSession:()=>P(e),chat:n=>$(e,n),listConversations:n=>E(e,n),renameConversation:(n,d)=>O(e,n,d),deleteConversation:n=>C(e,n),getMessages:n=>x(e,n),respondInterrupt:(n,d,t,s,o,a)=>L(e,n,d,t,s,o,a),setToken:n=>e.setToken(n),feedback:async(n,d,t)=>{const s={type:d};d==="dislike"&&((t==null?void 0:t.reason)!=null&&(s.reason=t.reason),t!=null&&t.remark&&(s.remark=t.remark)),await e.post(`/chat/messages/${n}/feedback`,s)},cancelFeedback:async n=>{await e.del(`/chat/messages/${n}/feedback`)},listSkills:()=>G(e),stopGeneration:n=>R(e,n)}}exports.createNosUploader=h.createNosUploader;exports.createSuperAgent=B;
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export declare interface ChatAttachment {
24
24
  }
25
25
 
26
26
  export declare interface ChatEvent {
27
- type: "session.start" | "user" | "thinking" | "ai" | "tool_call" | "tool_result" | "done" | "stop" | "error" | "interrupt";
27
+ type: "session.start" | "user" | "thinking" | "ai" | "tool_call" | "tool_delta" | "tool_result" | "done" | "stop" | "error" | "interrupt";
28
28
  content: string;
29
29
  toolName?: string;
30
30
  toolCallId?: string;
@@ -198,12 +198,23 @@ declare interface SkillInfo {
198
198
  name: string;
199
199
  displayName: string | null;
200
200
  description: string | null;
201
+ /** 归属:entry=入口 agent 自己的技能;member=Team 中某个成员的技能 */
202
+ owner: 'entry' | 'member';
203
+ /** owner=member 时该成员在 Team 内的 code(member_ref_code);entry 时为 null */
204
+ memberCode: string | null;
205
+ /** owner=member 时该成员的展示名;entry 时为 null */
206
+ memberName: string | null;
207
+ /** 能否通过斜杠命令点名(Pipeline 流水线模式下的成员技能为 false) */
208
+ selectable: boolean;
209
+ /** selectable=false 的原因,展示给用户;可选时为空 */
210
+ disabledReason: string | null;
201
211
  }
202
212
 
203
213
  export declare interface SuperAgentSDK {
204
214
  /** 当前 Bot ID(只读) */
205
215
  readonly botId: number;
206
- /** 获取 token(调用 POST {tokenGateway}/v1/token),自动设置内部凭证 */
216
+ /** 确保持有 token:已持直接返回缓存;否则 POST {tokenGateway}/v2/token/generate 签发
217
+ *(多 widget 并发挂载合并为一次请求),自动设置内部凭证。401 重签走重试链路 */
207
218
  getToken(): Promise<string>;
208
219
  /** 创建新会话,返回 sessionId */
209
220
  createSession(): Promise<string>;
@@ -222,7 +233,7 @@ export declare interface SuperAgentSDK {
222
233
  }): Promise<void>;
223
234
  /** 取消消息反馈,DELETE /chat/messages/{messageId}/feedback */
224
235
  cancelFeedback(messageId: string): Promise<void>;
225
- /** 获取当前 bot 绑定的 skill 列表,GET /chat/bots/{botId}/skills */
236
+ /** 获取当前 bot 绑定的 skill 列表,GET /chat/bots/{botId}/skills(含归属与可选性) */
226
237
  listSkills(): Promise<SkillInfo[]>;
227
238
  /** 停止生成(双信号:POST /chat/stop 广播 + abort SSE),半截回复保留 */
228
239
  stopGeneration(sessionId: string): Promise<void>;
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ function f(r) {
15
15
  const A = "/api/agent/runtime/v1";
16
16
  class $ {
17
17
  constructor(e) {
18
- this.refreshing = null;
18
+ this.refreshing = null, this.tokenPromise = null;
19
19
  const i = e.baseUrl ?? A;
20
20
  this.baseUrl = i.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), this.loginUrl = e.loginUrl, this.onAuthExpired = e.onAuthExpired;
21
21
  }
@@ -32,20 +32,34 @@ class $ {
32
32
  getOrigin() {
33
33
  return typeof window < "u" ? window.location.origin : "";
34
34
  }
35
- /** POST {origin}{tokenGateway}/v1/token — 获取 token + appId */
35
+ /** POST {origin}{tokenGateway}/v2/token/generate — 获取 token + appId。
36
+ *
37
+ * 已持 token 直接返回缓存;并发调用凭 in-flight promise 合并为一次请求
38
+ * (多 widget 共享同一 sdk 时,各自 ChatProvider 挂载只打一次签发端点)。
39
+ * 401 强刷前须先清 this.token(见 handleTokenRefresh)。
40
+ */
36
41
  async fetchToken() {
37
- const i = `${this.isAbsoluteGateway ? this.tokenGateway : `${this.getOrigin()}${this.tokenGateway}`}/v1/token`, n = await fetch(i, {
38
- method: "POST",
39
- headers: { "Content-Type": "application/json" },
40
- body: JSON.stringify({ botId: this.botId })
41
- });
42
- if (!n.ok)
43
- throw new Error(`HTTP ${n.status}: ${n.statusText}`);
44
- const d = await n.json();
45
- if (d.code !== "200")
46
- throw new Error(d.message || `API error: ${d.code}`);
47
- const t = f(d.data);
48
- return this.token = t.token, t.appId && !this.appId && (this.appId = t.appId), t.token;
42
+ if (this.token) return this.token;
43
+ if (this.tokenPromise) return this.tokenPromise;
44
+ this.tokenPromise = (async () => {
45
+ const i = `${this.isAbsoluteGateway ? this.tokenGateway : `${this.getOrigin()}${this.tokenGateway}`}/v2/token/generate`, n = await fetch(i, {
46
+ method: "POST",
47
+ headers: { "Content-Type": "application/json" },
48
+ body: JSON.stringify({ botId: this.botId })
49
+ });
50
+ if (!n.ok)
51
+ throw new Error(`HTTP ${n.status}: ${n.statusText}`);
52
+ const d = await n.json();
53
+ if (d.code !== "200")
54
+ throw new Error(d.message || `API error: ${d.code}`);
55
+ const t = f(d.data);
56
+ return this.token = t.token, t.appId && !this.appId && (this.appId = t.appId), t.token;
57
+ })();
58
+ try {
59
+ return await this.tokenPromise;
60
+ } finally {
61
+ this.tokenPromise = null;
62
+ }
49
63
  }
50
64
  headers(e) {
51
65
  return {
@@ -59,7 +73,7 @@ class $ {
59
73
  if (this.refreshing)
60
74
  return await this.refreshing, !0;
61
75
  try {
62
- return this.refreshing = (async () => {
76
+ return this.token = "", this.refreshing = (async () => {
63
77
  await this.fetchToken();
64
78
  })(), await this.refreshing, !0;
65
79
  } catch {
@@ -206,6 +220,14 @@ ${a}` : a;
206
220
  event: n,
207
221
  id: i
208
222
  };
223
+ case "tool_delta":
224
+ return {
225
+ type: "tool_delta",
226
+ content: typeof t.content == "string" ? t.content : "",
227
+ toolCallId: t.tool_call_id ?? t.toolCallId ?? "",
228
+ event: n,
229
+ id: i
230
+ };
209
231
  case "tool_result": {
210
232
  const o = s == null ? void 0 : s.result;
211
233
  let a;
@@ -305,7 +327,7 @@ async function T(r, e, i) {
305
327
  }
306
328
  function _(r, e) {
307
329
  var t;
308
- const i = new AbortController(), n = e.signal ? x(e.signal, i.signal) : i.signal, d = {
330
+ const i = new AbortController(), n = e.signal ? P(e.signal, i.signal) : i.signal, d = {
309
331
  botId: r.getBotId(),
310
332
  message: e.message,
311
333
  sessionId: e.sessionId,
@@ -353,16 +375,16 @@ function _(r, e) {
353
375
  (o = e.onError) == null || o.call(e, s instanceof Error ? s : new Error(String(s)));
354
376
  }), i;
355
377
  }
356
- function x(r, e) {
378
+ function P(r, e) {
357
379
  const i = new AbortController(), n = () => i.abort();
358
380
  return r.addEventListener("abort", n, { once: !0 }), e.addEventListener("abort", n, { once: !0 }), (r.aborted || e.aborted) && i.abort(), i.signal;
359
381
  }
360
- async function E(r) {
382
+ async function x(r) {
361
383
  return (await r.post("/chat/sessions", {
362
384
  botId: r.getBotId()
363
385
  })).sessionId;
364
386
  }
365
- function O(r) {
387
+ function E(r) {
366
388
  return {
367
389
  // 后端返回 thread_id,toCamelCase 转为 threadId,映射为 sessionId
368
390
  sessionId: r.threadId ?? r.sessionId,
@@ -380,13 +402,13 @@ async function v(r, e) {
380
402
  });
381
403
  return {
382
404
  ...i,
383
- items: i.items.map(O)
405
+ items: i.items.map(E)
384
406
  };
385
407
  }
386
408
  async function C(r, e, i) {
387
409
  await r.patch(`/chat/conversations/${e}`, { title: i });
388
410
  }
389
- async function P(r, e) {
411
+ async function O(r, e) {
390
412
  await r.del(`/chat/conversations/${e}`);
391
413
  }
392
414
  async function U(r, e) {
@@ -559,11 +581,11 @@ function z(r) {
559
581
  return {
560
582
  botId: e.getBotId(),
561
583
  getToken: () => e.fetchToken(),
562
- createSession: () => E(e),
584
+ createSession: () => x(e),
563
585
  chat: (n) => _(e, n),
564
586
  listConversations: (n) => v(e, n),
565
587
  renameConversation: (n, d) => C(e, n, d),
566
- deleteConversation: (n) => P(e, n),
588
+ deleteConversation: (n) => O(e, n),
567
589
  getMessages: (n) => U(e, n),
568
590
  respondInterrupt: (n, d, t, s, o, a) => G(e, n, d, t, s, o, a),
569
591
  setToken: (n) => e.setToken(n),