super-agent-sdk 1.0.20 → 1.0.22

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
@@ -201,7 +201,7 @@ export interface ChatOptions {
201
201
  messageId?: string;
202
202
  roundId?: string; // 本轮对话 id(session.start/session.done 携带)
203
203
  artifacts?: Artifact[]; // done 汇总的本轮文件产物(generate_file 等交付产物)
204
- }) => void; // messageId:后端在 done 事件返回的消息标识(存在时 SDK Widget 用其启用消息反馈,若返回可据此判断该消息可 feedback)
204
+ }) => void; // messageId:done/stop 事件带回的后端消息标识(= conversation_messages.message_id,feedback 按它定位;未带回时 SDK 回查历史兜底)
205
205
  signal?: AbortSignal;
206
206
  }
207
207
 
@@ -352,23 +352,23 @@ sdk.setToken("<TOKEN>");
352
352
 
353
353
  消息反馈(赞/踩)。调用 `sdk.feedback()` 发送 `POST /chat/messages/{messageId}/feedback`;调用 `sdk.cancelFeedback()` 发送 `DELETE` 取消反馈。
354
354
 
355
- > **messageId 说明**:即消息历史返回的表主键 `id`(数字),不是 `messageId`(UUID)。纯 API 模式从 `getMessages()` 结果取 `UIMessage.id`。
355
+ > **messageId 说明**:即消息列表里的 `messageId`(后端 `conversation_messages.message_id`,langchain 原始消息 id,UUID 字符串),**不是** `UIMessage.id`(历史加载为表主键、流式为客户端临时 id,仅作渲染 key)。纯 API 模式从 `getMessages()` 结果取 `UIMessage.messageId`;流式消息由 `done`/`stop` 事件(`onDone` 的 `messageId`)带回,两者都有时以帧内为准。
356
356
 
357
357
  ```ts
358
358
  const messages = await sdk.getMessages(sessionId);
359
359
  const aiMsg = messages.findLast((m) => m.role === "assistant");
360
360
 
361
361
  // 点赞
362
- await sdk.feedback(aiMsg.id, "like");
362
+ await sdk.feedback(aiMsg.messageId!, "like");
363
363
 
364
364
  // 踩(可附原因 + 备注)
365
- await sdk.feedback(aiMsg.id, "dislike", {
365
+ await sdk.feedback(aiMsg.messageId!, "dislike", {
366
366
  reason: 1, // 1=事实错误 2=逻辑问题 3=不相关 4=信息过时 5=冗长啰嗦 6=难以理解
367
367
  remark: "时间描述有误",
368
368
  });
369
369
 
370
370
  // 取消反馈
371
- await sdk.cancelFeedback(aiMsg.id);
371
+ await sdk.cancelFeedback(aiMsg.messageId!);
372
372
  ```
373
373
 
374
374
  组件内置的点赞/踩按钮已自动调用 `feedback()`/`cancelFeedback()`:
@@ -376,7 +376,7 @@ await sdk.cancelFeedback(aiMsg.id);
376
376
  - 点击已选中的按钮 → 取消(DELETE)
377
377
  - 点击另一个按钮 → 切换(POST)
378
378
  - 点踩时弹出原因选择面板(可选填原因 + 备注后提交)
379
- - 流式渲染期间消息尚无后端 ID(临时占位),此时点击反馈 SDK 会自动拉取一次历史消息解析真实 ID 再发送,业务方无感知
379
+ - 消息本身没带 `messageId` 时(如后端 done/stop 帧未回传),SDK 自动拉取一次历史消息,按该消息的 `roundId` 定位到它并取 `messageId` 再发送,业务方无感知
380
380
 
381
381
  ### 5.10 respondInterrupt()
382
382
 
@@ -482,6 +482,15 @@ export interface MountOptions {
482
482
  attachmentUploader?: (file: File) => Promise<ChatAttachment>;
483
483
  /** 内置 NOS 直传(推荐):配置即用,📎 按钮 + chip 进度 + 断点续传全内置 */
484
484
  nosUpload?: { baseURL: string; headers?: Record<string, string>; trunkSize?: number };
485
+ /**
486
+ * 折叠内容(思维链/工具调用)DeepSeek 式展示:流式期间自动展开、结束自动收起,
487
+ * 思维链收起条显示「已深度思考 · 用时 Ns」(仅 live 轮有耗时,历史回显无数据)。
488
+ * 对象出现(含 {})即整体开启;子项/子字段仅覆盖缺省(全 true)。结构可扩展。
489
+ */
490
+ collapse?: {
491
+ thinking?: { expandWhileStreaming?: boolean; showDuration?: boolean };
492
+ toolCall?: { expandWhileStreaming?: boolean };
493
+ };
485
494
  }
486
495
 
487
496
  export interface CapabilityItem {
@@ -919,8 +928,9 @@ export interface ActionBarProps {
919
928
  message: UIMessage;
920
929
  onCopy: () => void;
921
930
  onRegenerate?: () => void;
931
+ // 传整条 message(内置 ActionBar 的做法)或 messageId / 本地 id 字符串均可
922
932
  onFeedback?: (
923
- messageId: string,
933
+ message: UIMessage | string,
924
934
  feedback: "like" | "dislike",
925
935
  options?: { reason?: number; remark?: string },
926
936
  ) => void;
@@ -1508,10 +1518,11 @@ ac.abort();
1508
1518
 
1509
1519
  ```ts
1510
1520
  export interface UIMessage {
1511
- id: string;
1521
+ id: string; // 渲染 key:历史加载为表主键,流式为客户端临时 id(不用于 feedback)
1512
1522
  role: "user" | "assistant";
1513
1523
  parts: MessagePart[];
1514
1524
  timestamp: number;
1525
+ messageId?: string; // 后端消息标识(= conversation_messages.message_id),feedback/cancelFeedback 按它定位
1515
1526
  roundId?: string; // 本轮对话 id(历史分组 roundId;后端为 null 时 SDK 随机生成)
1516
1527
  artifacts?: Artifact[]; // done 汇总的本轮文件产物(历史取分组 artifacts),消息末尾渲染文件卡片
1517
1528
  }
@@ -1577,7 +1588,7 @@ export interface ChatEvent {
1577
1588
  toolCallId?: string;
1578
1589
  args?: string; // JSON.stringify 后的字符串
1579
1590
  sessionId?: string;
1580
- messageId?: string; // done 事件携带后端消息标识(后端返回时该消息可反馈/feedback)
1591
+ messageId?: string; // done/stop 事件携带的后端消息标识(= conversation_messages.message_id,feedback 按它定位消息)
1581
1592
  interrupt?: InterruptEvent; // interrupt 事件携带中断详情
1582
1593
  artifacts?: Artifact[]; // tool_result 顶层产物;done 事件汇总本轮产物(Widget 挂到消息级渲染文件卡片)
1583
1594
  renderMode?: string; // "html" 时工具结果为富文本
@@ -1634,6 +1645,8 @@ mount("#chat", { sdk }).open();
1634
1645
  ```
1635
1646
 
1636
1647
  > interrupt 帧是流的**暂停点**(后端不发 `done`),`respondInterrupt()` 后的续事件在同一 SSE 流上返回;续流结束(或嵌套 interrupt 再次暂停)后,输入框均可正常继续发送——挂起/续流状态由 Widget 自动管理。
1648
+ >
1649
+ > pending interrupt 期间在输入框直接发文本(不点卡片)也是"作答":Widget 自动路由到 `POST /chat/interrupt/{interruptId}/respond`(`action=submit` + 原文),而非新开 `/chat` 轮;答案回填到中断卡片,不另插用户气泡(与历史加载口径一致)。
1637
1650
 
1638
1651
  也可通过插槽自定义中断卡片:
1639
1652
 
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("./nosUploader-DLX7JsnR.cjs");function f(s){if(Array.isArray(s))return s.map(e=>f(e));if(s&&typeof s=="object"&&s.constructor===Object){const e={};for(const[i,n]of Object.entries(s)){const d=i.replace(/_([a-z])/g,(t,r)=>r.toUpperCase());e[d]=f(n)}return e}return s}const S="/api/agent/runtime/v1";class C{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.botCode=e.botCode,this.tenantId=e.tenantId,this.isAbsoluteUrl=/^https?:\/\//.test(this.baseUrl),this.isAbsoluteGateway=/^https?:\/\//.test(this.tokenGateway),this.loginUrl=e.loginUrl,this.onAuthExpired=e.onAuthExpired}getBotCode(){return this.botCode}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}`}/superagent/v2/token/generate`,n={"Content-Type":"application/json"};this.tenantId!=null&&(n["X-Tenant-Id"]=String(this.tenantId));const d=await fetch(i,{method:"POST",headers:n,body:JSON.stringify({botCode:this.botCode})});if(!d.ok)throw new Error(`HTTP ${d.status}: ${d.statusText}`);const t=await d.json();if(t.code!=="200")throw new Error(t.message||`API error: ${t.code}`);const r=f(t.data);return this.token=r.token,r.appId&&!this.appId&&(this.appId=r.appId),r.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 r=await t.json();if(r.code!=="200")throw new Error(r.message||`API error: ${r.code}`);return f(r.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 r=await h.peekCookieExpired(t.clone());if(r.isCookieExpired&&typeof(i==null?void 0:i.message)=="string"){h.stashPendingChat({botCode:this.botCode,message:i.message,sessionId:i.sessionId??""});const a=r.loginUrl??this.loginUrl;return this.onAuthExpired?this.onAuthExpired({loginUrl:a,sessionId:r.sessionId,botCode:this.botCode}):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(s){return typeof s=="string"?s:Array.isArray(s)?s.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(""):s==null?"":String(s)}function k(s){const e=s.split(`
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 r=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=r==null?void 0:r.result;let a;return typeof o=="string"?a=o:o!=null&&typeof o=="object"?a=JSON.stringify(o):r&&typeof r=="object"&&Object.keys(r).length>0?a=JSON.stringify(r):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:(r==null?void 0:r.render_mode)??t.render_mode??t.renderMode,html:(r==null?void 0:r.html)??t.html,markdown:(r==null?void 0:r.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(s,e,i){if(!s.body){i(new Error("Response body is null"));return}const n=s.body.getReader(),d=new TextDecoder;let t="";try{for(;;){const{value:r,done:o}=await n.read();if(o)break;t+=d.decode(r,{stream:!0});let a;for(;(a=t.indexOf(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("./nosUploader-Dk2GyRpT.cjs");function g(r){if(Array.isArray(r))return r.map(e=>g(e));if(r&&typeof r=="object"&&r.constructor===Object){const e={};for(const[o,s]of Object.entries(r)){const d=o.replace(/_([a-z])/g,(t,n)=>n.toUpperCase());e[d]=g(s)}return e}return r}const S="/api/agent/runtime/v1";class C{constructor(e){this.refreshing=null,this.tokenPromise=null;const o=e.baseUrl??S;this.baseUrl=o.replace(/\/$/,""),this.tokenGateway=e.tokenGateway.replace(/\/$/,""),this.appId=e.appId??"",this.token=e.token??"",this.botCode=e.botCode,this.tenantId=e.tenantId,this.isAbsoluteUrl=/^https?:\/\//.test(this.baseUrl),this.isAbsoluteGateway=/^https?:\/\//.test(this.tokenGateway),this.loginUrl=e.loginUrl,this.onAuthExpired=e.onAuthExpired}getBotCode(){return this.botCode}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 o=`${this.isAbsoluteGateway?this.tokenGateway:`${this.getOrigin()}${this.tokenGateway}`}/superagent/v2/token/generate`,s={"Content-Type":"application/json"};this.tenantId!=null&&(s["X-Tenant-Id"]=String(this.tenantId));const d=await fetch(o,{method:"POST",headers:s,body:JSON.stringify({botCode:this.botCode})});if(!d.ok)throw new Error(`HTTP ${d.status}: ${d.statusText}`);const t=await d.json();if(t.code!=="200")throw new Error(t.message||`API error: ${t.code}`);const n=g(t.data);return this.token=n.token,n.appId&&!this.appId&&(this.appId=n.appId),n.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,o,s){if(!this.token&&!await this.handleTokenRefresh())throw new Error("SDK token not available: POST /token failed");let d=this.isAbsoluteUrl?`${this.baseUrl}${o}`:`${this.getOrigin()}${this.baseUrl}${o}`;if(s!=null&&s.params){const a=new URLSearchParams;for(const[c,l]of Object.entries(s.params))l!=null&&a.set(c,String(l));const i=a.toString();i&&(d+=`?${i}`)}const t=await fetch(d,{method:e,headers:this.headers(),body:s!=null&&s.body?JSON.stringify(s.body):void 0});if(t.status===401&&!(s!=null&&s.retry)&&await this.handleTokenRefresh())return this.request(e,o,{...s,retry:!0});if(!t.ok){let a=`HTTP ${t.status}: ${t.statusText}`;try{const i=await t.json();i!=null&&i.message&&(a=i.message)}catch{}throw new Error(a)}const n=await t.json();if(n.code!=="200")throw new Error(n.message||`API error: ${n.code}`);return g(n.data)}get(e,o){return this.request("GET",e,{params:o})}post(e,o){return this.request("POST",e,{body:o})}patch(e,o){return this.request("PATCH",e,{body:o})}del(e){return this.request("DELETE",e)}async streamPost(e,o,s){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(o),signal:s});if(t.status===401){const n=await m.peekCookieExpired(t.clone());if(n.isCookieExpired&&typeof(o==null?void 0:o.message)=="string"){m.stashPendingChat({botCode:this.botCode,message:o.message,sessionId:o.sessionId??""});const i=n.loginUrl??this.loginUrl;return this.onAuthExpired?this.onAuthExpired({loginUrl:i,sessionId:n.sessionId,botCode:this.botCode}):i&&window.location.replace(i),t}if(await this.handleTokenRefresh())return fetch(d,{method:"POST",headers:this.headers(),body:JSON.stringify(o),signal:s})}return t}}function h(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
+ `).map(a=>a.trim()).filter(a=>a.length>0);let o,s,d;for(const a of e)if(a.startsWith("id:"))o=a.slice(3).trim();else if(a.startsWith("event:"))s=a.slice(6).trim();else if(a.startsWith("data:")){const i=a.slice(5).trim();d=d?`${d}
3
+ ${i}`:i}if(d===void 0)return null;let t;try{t=JSON.parse(d)}catch{return null}const n=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:s,id:o};case"user":return{type:"user",content:h(t.content),event:s,id:o};case"thinking":return{type:"thinking",content:h(t.content),event:s,id:o};case"ai":return{type:"ai",content:h(t.content),event:s,id:o};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:s,id:o};case"tool_delta":return{type:"tool_delta",content:typeof t.content=="string"?t.content:"",toolCallId:t.tool_call_id??t.toolCallId??"",event:s,id:o};case"tool_result":{const a=n==null?void 0:n.result;let i;return typeof a=="string"?i=a:a!=null&&typeof a=="object"?i=JSON.stringify(a):n&&typeof n=="object"&&Object.keys(n).length>0?i=JSON.stringify(n):i=h(t.output??""),{type:"tool_result",content:i,toolName:t.name,toolCallId:t.id,artifacts:Array.isArray(t.artifacts)?t.artifacts:void 0,renderMode:(n==null?void 0:n.render_mode)??t.render_mode??t.renderMode,html:(n==null?void 0:n.html)??t.html,markdown:(n==null?void 0:n.markdown)??t.markdown,event:s,id:o}}case"done":return{type:"done",content:h(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:s,id:o};case"stop":return{type:"stop",content:h(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id,roundId:t.roundId??t.round_id,event:s,id:o};case"error":return{type:"error",content:t.message??"Unknown error",event:s,id:o};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:s,id:o};default:return null}}async function b(r,e,o){if(!r.body){o(new Error("Response body is null"));return}const s=r.body.getReader(),d=new TextDecoder;let t="";try{for(;;){const{value:n,done:a}=await s.read();if(a)break;t+=d.decode(n,{stream:!0});let i;for(;(i=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 r=k(t);r&&e(r)}}catch(r){(r==null?void 0:r.name)!=="AbortError"&&i(r instanceof Error?r:new Error(String(r)))}finally{try{n.releaseLock()}catch{}}}function A(s,e){var t;const i=new AbortController,n=e.signal?$(e.signal,i.signal):i.signal,d={botCode:s.getBotCode(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1,...(t=e.attachments)!=null&&t.length?{attachments:e.attachments.map(({url:r,...o})=>o)}:{}};return d.stream?s.streamPost("/chat",d,n).then(async r=>{var o;if(!r.ok){let a=`HTTP ${r.status}`;try{const c=await r.json();c!=null&&c.message&&(a=c.message)}catch{}(o=e.onError)==null||o.call(e,new Error(a));return}return b(r,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(r=>{var o;(r==null?void 0:r.name)!=="AbortError"&&((o=e.onError)==null||o.call(e,r instanceof Error?r:new Error(String(r))))}):s.post("/chat",d).then(r=>{var o;(o=e.onDone)==null||o.call(e,{sessionId:r.sessionId,content:r.content??"",messageId:r.messageId})}).catch(r=>{var o;(o=e.onError)==null||o.call(e,r instanceof Error?r:new Error(String(r)))}),i}function $(s,e){const i=new AbortController,n=()=>i.abort();return s.addEventListener("abort",n,{once:!0}),e.addEventListener("abort",n,{once:!0}),(s.aborted||e.aborted)&&i.abort(),i.signal}async function _(s){return(await s.post("/chat/sessions",{botCode:s.getBotCode()})).sessionId}function P(s){return{sessionId:s.threadId??s.sessionId,title:s.title,createTime:s.createTime,updateTime:s.updateTime}}async function v(s,e){const i=await s.get("/chat/conversations",{botCode:s.getBotCode(),page:(e==null?void 0:e.page)??1,size:(e==null?void 0:e.size)??20});return{...i,items:i.items.map(P)}}async function E(s,e,i){await s.patch(`/chat/conversations/${e}`,{title:i})}async function O(s,e){await s.del(`/chat/conversations/${e}`)}async function x(s,e){const i=await s.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(s){var d;const e=s.length>0&&Array.isArray((d=s[0])==null?void 0:d.data),i=[];if(e)for(const t of s)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:s});const n=[];for(const t of i){const r=N(t.items);for(const o of r)o.roundId=t.roundId;if(t.artifacts){const o=r.findLast(a=>a.role==="assistant");o&&(o.artifacts=t.artifacts)}n.push(...r)}return n}function N(s){const e=[...s].sort((r,o)=>{const a=new Date(r.createTime??0).getTime()||0,c=new Date(o.createTime??0).getTime()||0;return a!==c?a-c:(r.seq??0)-(o.seq??0)}),i=new Map;for(const r of e)r.role==="tool"&&r.toolCallId&&i.set(r.toolCallId,r.content||"");const n=new Set,d=[],t=(r,o,a)=>{const c=d[d.length-1];(c==null?void 0:c.role)==="assistant"?(c.parts.push(...r),c.id=o):d.push({id:o,role:"assistant",parts:[...r],timestamp:a})};for(const r of e){if(r.role==="system")continue;const o=String(r.id??r.messageId??`msg_${Date.now()}`),a=new Date(r.createTime??"").getTime()||Date.now();if(r.role==="human"){const c=(r.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(r.content)}],timestamp:a});continue}if(r.role==="ai"){const c=M(r,i,n);c.length>0&&t(c,o,a);continue}if(r.role==="tool"){if(r.toolCallId&&n.has(r.toolCallId))continue;t([j(r)],o,a)}}return d}function M(s,e,i){const n=[];s.reasoning&&n.push({type:"thinking",content:s.reasoning}),s.content&&n.push({type:"text",content:u(s.content)});for(const d of s.toolCalls??[])d.is_interrupt??d.isInterrupt?(i.add(d.id),n.push(D(d,e))):n.push(q(d));return n}function D(s,e){const i=e.has(s.id),n=typeof s.args=="object"?s.args:{};return{type:"interrupt",interrupt:{interruptId:s.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(s.id))}:void 0}}function q(s){let e;try{e=typeof s.args=="string"?s.args:JSON.stringify(s.args??{})}catch{e=String(s.args??"{}")}return{type:"tool_call",toolName:s.name??"",toolCallId:s.id??"",args:e}}function j(s){var i,n,d,t;const e=Array.isArray(s.artifacts)?s.artifacts:void 0;return{type:"tool_result",toolName:s.toolName??"",toolCallId:s.toolCallId??"",content:u(s.content),artifacts:e,renderMode:s.renderMode??((i=s.metadata)==null?void 0:i.renderMode)??((n=s.metadata)==null?void 0:n.render_mode),html:s.html??((d=s.metadata)==null?void 0:d.html),markdown:s.markdown??((t=s.metadata)==null?void 0:t.markdown)}}function J(s){if(s!=null)try{return JSON.parse(s)}catch{return s}}async function L(s,e,i,n,d,t,r){const o=await s.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:i,action:n.action,value:n.value},r);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(s){return s.get(`/chat/bots/${s.getBotCode()}/skills`)}async function R(s,e){await s.post("/chat/stop",{sessionId:e})}function B(s){const e=new C(s);return{botCode:e.getBotCode(),getToken:()=>e.fetchToken(),createSession:()=>_(e),chat:n=>A(e,n),listConversations:n=>v(e,n),renameConversation:(n,d)=>E(e,n,d),deleteConversation:n=>O(e,n),getMessages:n=>x(e,n),respondInterrupt:(n,d,t,r,o,a)=>L(e,n,d,t,r,o,a),setToken:n=>e.setToken(n),feedback:async(n,d,t)=>{const r={type:d};d==="dislike"&&((t==null?void 0:t.reason)!=null&&(r.reason=t.reason),t!=null&&t.remark&&(r.remark=t.remark)),await e.post(`/chat/messages/${n}/feedback`,r)},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,i);t=t.slice(i+2);const l=k(c);l&&e(l)}}if(t.trim()){const n=k(t);n&&e(n)}}catch(n){(n==null?void 0:n.name)!=="AbortError"&&o(n instanceof Error?n:new Error(String(n)))}finally{try{s.releaseLock()}catch{}}}function A(r,e){var t;const o=new AbortController,s=e.signal?_(e.signal,o.signal):o.signal,d={botCode:r.getBotCode(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1,...(t=e.attachments)!=null&&t.length?{attachments:e.attachments.map(({url:n,...a})=>a)}:{}};return d.stream?r.streamPost("/chat",d,s).then(async n=>{var a;if(!n.ok){let i=`HTTP ${n.status}`;try{const c=await n.json();c!=null&&c.message&&(i=c.message)}catch{}(a=e.onError)==null||a.call(e,new Error(i));return}return b(n,i=>{var c,l,u,f,y,I,p,w;i.type==="done"&&i.sessionId?((c=e.onMessage)==null||c.call(e,i),(l=e.onDone)==null||l.call(e,{sessionId:i.sessionId,content:i.content,messageId:i.messageId,roundId:i.roundId,artifacts:i.artifacts})):i.type==="done"?((u=e.onMessage)==null||u.call(e,i),(f=e.onDone)==null||f.call(e,{sessionId:"",content:i.content,messageId:i.messageId,roundId:i.roundId,artifacts:i.artifacts})):i.type==="stop"?((y=e.onMessage)==null||y.call(e,i),(I=e.onDone)==null||I.call(e,{sessionId:i.sessionId??"",content:i.content,messageId:i.messageId,roundId:i.roundId})):i.type==="error"?(p=e.onError)==null||p.call(e,new Error(i.content)):(w=e.onMessage)==null||w.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",d).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)))}),o}function _(r,e){const o=new AbortController,s=()=>o.abort();return r.addEventListener("abort",s,{once:!0}),e.addEventListener("abort",s,{once:!0}),(r.aborted||e.aborted)&&o.abort(),o.signal}async function $(r){return(await r.post("/chat/sessions",{botCode:r.getBotCode()})).sessionId}function P(r){return{sessionId:r.threadId??r.sessionId,title:r.title,createTime:r.createTime,updateTime:r.updateTime}}async function v(r,e){const o=await r.get("/chat/conversations",{botCode:r.getBotCode(),page:(e==null?void 0:e.page)??1,size:(e==null?void 0:e.size)??20});return{...o,items:o.items.map(P)}}async function E(r,e,o){await r.patch(`/chat/conversations/${e}`,{title:o})}async function O(r,e){await r.del(`/chat/conversations/${e}`)}async function x(r,e){const o=await r.get(`/chat/conversations/${e}/messages`);return U(o)}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),o=[];if(e)for(const t of r)o.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 o.push({roundId:T(),items:r});const s=[];for(const t of o){const n=M(t.items);for(const a of n)a.roundId=t.roundId;if(t.artifacts){const a=n.findLast(i=>i.role==="assistant");a&&(a.artifacts=t.artifacts)}s.push(...n)}return s}function M(r){var n;const e=[...r].sort((a,i)=>{const c=new Date(a.createTime??0).getTime()||0,l=new Date(i.createTime??0).getTime()||0;return c!==l?c-l:(a.seq??0)-(i.seq??0)}),o=new Map;for(const a of e)a.role==="tool"&&a.toolCallId&&o.set(a.toolCallId,a.content||"");const s=new Set,d=[],t=(a,i,c,l)=>{const u=d[d.length-1];(u==null?void 0:u.role)==="assistant"?(u.parts.push(...a),u.id=i,l&&(u.messageId=l)):d.push({id:i,role:"assistant",parts:[...a],timestamp:c,messageId:l})};for(const a of e){if(a.role==="system")continue;const i=String(a.id??a.messageId??`msg_${Date.now()}`),c=new Date(a.createTime??"").getTime()||Date.now();if(a.role==="human"){const l=(a.attachments??[]).map(f=>({type:"attachment",attachment:{nosKey:f.nosKey??f.attachmentId??"",filename:f.filename??"file",size:f.size??void 0,mime:f.mime??void 0,url:f.url??void 0}})),u=(n=a.metadata)==null?void 0:n.raw_message;d.push({id:i,role:"user",parts:[...l,{type:"text",content:h(a.content)}],timestamp:c,messageId:a.messageId,rawContent:typeof u=="string"&&u?u:void 0});continue}if(a.role==="ai"){const l=N(a,o,s);l.length>0&&t(l,i,c,a.messageId);continue}if(a.role==="tool"){if(a.toolCallId&&s.has(a.toolCallId))continue;t([j(a)],i,c)}}return d}function N(r,e,o){const s=[];r.reasoning&&s.push({type:"thinking",content:r.reasoning}),r.content&&s.push({type:"text",content:h(r.content)});for(const d of r.toolCalls??[])d.is_interrupt??d.isInterrupt?(o.add(d.id),s.push(D(d,e))):s.push(q(d));return s}function D(r,e){const o=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:o,response:o?{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 o,s,d,t;const e=Array.isArray(r.artifacts)?r.artifacts:void 0;return{type:"tool_result",toolName:r.toolName??"",toolCallId:r.toolCallId??"",content:h(r.content),artifacts:e,renderMode:r.renderMode??((o=r.metadata)==null?void 0:o.renderMode)??((s=r.metadata)==null?void 0:s.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,o,s,d,t,n){const a=await r.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:o,action:s.action,value:s.value},n);if(!a.ok){const i=new Error(`HTTP ${a.status}`);throw t==null||t(i),i}d&&await b(a,i=>{i.type==="error"?t==null||t(new Error(i.content)):d(i)},i=>t==null?void 0:t(i))}async function G(r){return r.get(`/chat/bots/${r.getBotCode()}/skills`)}async function R(r,e){await r.post("/chat/stop",{sessionId:e})}function B(r){const e=new C(r);return{botCode:e.getBotCode(),getToken:()=>e.fetchToken(),createSession:()=>$(e),chat:s=>A(e,s),listConversations:s=>v(e,s),renameConversation:(s,d)=>E(e,s,d),deleteConversation:s=>O(e,s),getMessages:s=>x(e,s),respondInterrupt:(s,d,t,n,a,i)=>L(e,s,d,t,n,a,i),setToken:s=>e.setToken(s),feedback:async(s,d,t)=>{const n={type:d};d==="dislike"&&((t==null?void 0:t.reason)!=null&&(n.reason=t.reason),t!=null&&t.remark&&(n.remark=t.remark)),await e.post(`/chat/messages/${s}/feedback`,n)},cancelFeedback:async s=>{await e.del(`/chat/messages/${s}/feedback`)},listSkills:()=>G(e),stopGeneration:s=>R(e,s)}}exports.createNosUploader=m.createNosUploader;exports.createSuperAgent=B;
package/dist/index.d.ts CHANGED
@@ -134,6 +134,7 @@ export declare type MessagePart = {
134
134
  } | {
135
135
  type: "thinking";
136
136
  content: string;
137
+ durationMs?: number;
137
138
  } | {
138
139
  type: "tool_call";
139
140
  toolName: string;
@@ -226,12 +227,14 @@ export declare interface SuperAgentSDK {
226
227
  /** 响应中断事件(返回 SSE 流,后端继续推送后续事件);signal 供调用方中断续流 */
227
228
  respondInterrupt(interruptId: string, sessionId: string, response: InterruptResponse, onMessage?: (event: ChatEvent) => void, onError?: (error: Error) => void, signal?: AbortSignal): Promise<void>;
228
229
  setToken(token: string): void;
229
- /** 消息反馈(赞/踩),POST /chat/messages/{messageId}/feedback */
230
+ /** 消息反馈(赞/踩),POST /chat/messages/{messageId}/feedback。
231
+ * messageId = 消息列表的 UIMessage.messageId(后端 conversation_messages.message_id,
232
+ * langchain uuid),不是渲染 key id;流式消息取自 done/stop 事件的 messageId。 */
230
233
  feedback(messageId: string, type: "like" | "dislike", options?: {
231
234
  reason?: number;
232
235
  remark?: string;
233
236
  }): Promise<void>;
234
- /** 取消消息反馈,DELETE /chat/messages/{messageId}/feedback */
237
+ /** 取消消息反馈,DELETE /chat/messages/{messageId}/feedback(messageId 同上) */
235
238
  cancelFeedback(messageId: string): Promise<void>;
236
239
  /** 获取当前 bot 绑定的 skill 列表,GET /chat/bots/{botCode}/skills(含归属与可选性) */
237
240
  listSkills(): Promise<SkillInfo[]>;
@@ -244,8 +247,15 @@ export declare interface UIMessage {
244
247
  role: "user" | "assistant";
245
248
  parts: MessagePart[];
246
249
  timestamp: number;
250
+ /** 后端消息标识(conversation_messages.message_id,langchain 原始 message id uuid):
251
+ * feedback / cancelFeedback 按它定位消息(不是表主键 id)。来源二选一:
252
+ * 历史加载取消息列表的 messageId;流式消息取 done/stop 帧的 messageId。 */
253
+ messageId?: string;
247
254
  roundId?: string;
248
255
  artifacts?: Artifact[];
256
+ /** 用户消息原文(含技能 "/code" 前缀;parts 文本展示 "/技能名" 版本时两者不同)。
257
+ * regenerate 原样重发用;历史加载从后端 metadata.raw_message 还原。 */
258
+ rawContent?: string;
249
259
  }
250
260
 
251
261
  export { }