super-agent-sdk 1.0.11 → 1.0.13
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 +15 -1
- package/dist/index.cjs +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +73 -72
- package/dist/{mammoth.browser-Czw2m8xL.js → mammoth.browser-CmEXxaIp.js} +1 -1
- package/dist/{nosUploader-C94D61NK.js → nosUploader-BkBtdrMs.js} +2 -2
- package/dist/widget.cjs +134 -48
- package/dist/widget.d.ts +6 -4
- package/dist/widget.mjs +10714 -2025
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@ Super Agent Web SDK —— 为 `super-agent-service` 提供的一站式浏览器
|
|
|
34
34
|
- **纯 API 模式**:`createSuperAgent()` 返回轻量 SDK 实例,提供流式聊天、会话列表、历史消息、Token 刷新等能力。
|
|
35
35
|
- **嵌入式组件**:`mount()` 挂载 React 聊天组件。
|
|
36
36
|
- **两种展示模式**:`floating`(右下角气泡 + 弹窗面板)与 `fullpage`(整页 DeepSeek 风格布局)。
|
|
37
|
+
- **Markdown 渲染**:内置 `react-markdown` + GFM(表格 / 任务列表 / 删除线),Claude 风格排版,默认转义防 XSS(见 [6.3](#63-markdown-渲染ai-消息))。
|
|
37
38
|
- **会话持久化**:自动加载会话列表、`localStorage` 记住最近会话、刷新后自动恢复。
|
|
38
39
|
- **附件上传(NOS 直传)**:内置 NOS 直传(分片 + 断点续传 + 进度),📎 选文件随消息发送,沙箱 Agent 可读取文件内容(详见 [5.12](#512-createnosuploader) / [6.1](#61-mount))。
|
|
39
40
|
|
|
@@ -542,7 +543,7 @@ mount("#chat-root", {
|
|
|
542
543
|
});
|
|
543
544
|
```
|
|
544
545
|
|
|
545
|
-
内置行为:📎
|
|
546
|
+
内置行为:📎 按钮(输入框左下角,绝对定位)选文件(≤10 个)→ 待发送附件以 chip 托盘显示在**输入框上方**(不占输入框内部空间),实时显示上传百分比 → 上传完成显示文件大小(可点击下载)→ 随消息发送 → 沙箱 Agent 读取(仅沙箱模式 Agent 支持,其他模式后端 400)。上传中禁止发送,失败 chip 红标可移除重选;regenerate 会连同附件一起重发。
|
|
546
547
|
|
|
547
548
|
### 6.2 源码接入(monorepo alias)注意事项
|
|
548
549
|
|
|
@@ -566,6 +567,17 @@ export default {
|
|
|
566
567
|
|
|
567
568
|
2. 无需在宿主 config 中镜像 SDK 的 `important: '[data-super-agent-widget]'`(那会把宿主自己的 utility 也锁进 widget 容器内);宿主管线生成的 utility 为普通类,widget DOM 照常命中,动画/自定义类由 SDK 自带的 `tailwind.css`(运行时注入)保证。
|
|
568
569
|
|
|
570
|
+
### 6.3 Markdown 渲染(AI 消息)
|
|
571
|
+
|
|
572
|
+
AI 文本消息(`text` part)按 Markdown 渲染,内置 `react-markdown` + `remark-gfm`(**随 SDK 打包,宿主无需额外安装**):
|
|
573
|
+
|
|
574
|
+
- **语法**:CommonMark 全集 + GFM 扩展(表格、任务列表 `- [ ]`、删除线 `~~x~~`、自动链接)
|
|
575
|
+
- **排版**:Claude 风格,色值对齐前端设计 tokens(`frontend/src/theme/tokens.ts`)——链接品牌橙 `#d97757`(hover 加深)、行内代码 `parchment #e8e6dc` 底、代码块 `card #efede6` 底 + `border #e3e1d8` hairline 边框(浅色暖调、横向滚动)、引用块 `clay` 左点缀、表头 `parchment` 底
|
|
576
|
+
- **安全**:默认 HTML 转义 + URL 清洗(`urlTransform`),Markdown 注入不会产生 XSS
|
|
577
|
+
- **流式友好**:未闭合语法(输出中的代码块 / 表格)渐进渲染不跳版
|
|
578
|
+
|
|
579
|
+
如需完全自定义渲染,通过 `slots.TextPart` 替换(见 [8.3 组件插槽](#83-组件插槽slots));`renderMode === "html"` 的工具结果不受影响,仍走 DOMPurify 内联渲染。
|
|
580
|
+
|
|
569
581
|
---
|
|
570
582
|
|
|
571
583
|
## 7. 展示模式
|
|
@@ -1601,6 +1613,8 @@ mount("#chat", { sdk }).open();
|
|
|
1601
1613
|
// 遇到 interrupt 时:自动渲染卡片 → 用户点击 → 自动 respondInterrupt → Agent 继续
|
|
1602
1614
|
```
|
|
1603
1615
|
|
|
1616
|
+
> interrupt 帧是流的**暂停点**(后端不发 `done`),`respondInterrupt()` 后的续事件在同一 SSE 流上返回;续流结束(或嵌套 interrupt 再次暂停)后,输入框均可正常继续发送——挂起/续流状态由 Widget 自动管理。
|
|
1617
|
+
|
|
1604
1618
|
也可通过插槽自定义中断卡片:
|
|
1605
1619
|
|
|
1606
1620
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("./nosUploader-KkzFK5EW.cjs");function h(r){if(Array.isArray(r))return r.map(e=>h(e));if(r&&typeof r=="object"&&r.constructor===Object){const e={};for(const[t,n]of Object.entries(r)){const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("./nosUploader-KkzFK5EW.cjs");function h(r){if(Array.isArray(r))return r.map(e=>h(e));if(r&&typeof r=="object"&&r.constructor===Object){const e={};for(const[t,n]of Object.entries(r)){const o=t.replace(/_([a-z])/g,(a,s)=>s.toUpperCase());e[o]=h(n)}return e}return r}const T="/api/agent/runtime/v1";class k{constructor(e){this.refreshing=null;const t=e.baseUrl??T;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 a=h(o.data);return this.token=a.token,a.appId&&!this.appId&&(this.appId=a.appId),a.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 c=new URLSearchParams;for(const[d,l]of Object.entries(n.params))l!=null&&c.set(d,String(l));const i=c.toString();i&&(o+=`?${i}`)}const a=await fetch(o,{method:e,headers:this.headers(),body:n!=null&&n.body?JSON.stringify(n.body):void 0});if(a.status===401&&!(n!=null&&n.retry)&&await this.handleTokenRefresh())return this.request(e,t,{...n,retry:!0});if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);const s=await a.json();if(s.code!=="200")throw new Error(s.message||`API error: ${s.code}`);return h(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}`,a=await fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:n});return a.status===401&&await this.handleTokenRefresh()?fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify(t),signal:n}):a}}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 I(r){const e=r.split(`
|
|
2
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:u(t.content)};case"thinking":return{type:"thinking",content:u(t.content)};case"ai":return{type:"ai",content:u(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:u(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:u(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id};case"stop":return{type:"stop",content:u(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 p(r,e,t){if(!r.body){t(new Error("Response body is null"));return}const n=r.body.getReader(),
|
|
3
|
+
`))}catch{return null}switch(t.type){case"user":return{type:"user",content:u(t.content)};case"thinking":return{type:"thinking",content:u(t.content)};case"ai":return{type:"ai",content:u(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:u(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:u(t.content),sessionId:t.sessionId??t.session_id??"",messageId:t.messageId??t.message_id};case"stop":return{type:"stop",content:u(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 p(r,e,t){if(!r.body){t(new Error("Response body is null"));return}const n=r.body.getReader(),o=new TextDecoder;let a="";try{for(;;){const{value:s,done:c}=await n.read();if(c)break;a+=o.decode(s,{stream:!0});let i;for(;(i=a.indexOf(`
|
|
4
4
|
|
|
5
|
-
`))!==-1;){const d=a.slice(0,
|
|
5
|
+
`))!==-1;){const d=a.slice(0,i);a=a.slice(i+2);const l=I(d);l&&e(l)}}if(a.trim()){const s=I(a);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 b(r,e){var a;const t=new AbortController,n=e.signal?S(e.signal,t.signal):t.signal,o={botId:r.getBotId(),message:e.message,sessionId:e.sessionId,stream:e.stream!==!1,...(a=e.attachments)!=null&&a.length?{attachments:e.attachments.map(({url:s,...c})=>c)}:{}};return o.stream?r.streamPost("/chat",o,n).then(s=>{var c;if(!s.ok){(c=e.onError)==null||c.call(e,new Error(`HTTP ${s.status}`));return}return p(s,i=>{var d,l,f,g,y,m;i.type==="done"&&i.sessionId?(d=e.onDone)==null||d.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==="stop"?((f=e.onMessage)==null||f.call(e,i),(g=e.onDone)==null||g.call(e,{sessionId:i.sessionId??"",content:i.content,messageId:i.messageId})):i.type==="error"?(y=e.onError)==null||y.call(e,new Error(i.content)):(m=e.onMessage)==null||m.call(e,i)},i=>{var d;return(d=e.onError)==null?void 0:d.call(e,i)})}).catch(s=>{var c;(s==null?void 0:s.name)!=="AbortError"&&((c=e.onError)==null||c.call(e,s instanceof Error?s:new Error(String(s))))}):r.post("/chat",o).then(s=>{var c;(c=e.onDone)==null||c.call(e,{sessionId:s.sessionId,content:s.content??"",messageId:s.messageId})}).catch(s=>{var c;(c=e.onError)==null||c.call(e,s instanceof Error?s:new Error(String(s)))}),t}function S(r,e){const t=new AbortController,n=()=>t.abort();return r.addEventListener("abort",n,{once:!0}),e.addEventListener("abort",n,{once:!0}),(r.aborted||e.aborted)&&t.abort(),t.signal}async function $(r){return(await r.post("/chat/sessions",{botId:r.getBotId()})).sessionId}function A(r){return{sessionId:r.threadId??r.sessionId,botId:r.botId,title:r.title,createTime:r.createTime,updateTime:r.updateTime}}async function C(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(A)}}async function _(r,e,t){await r.patch(`/chat/conversations/${e}`,{title:t})}async function O(r,e){await r.del(`/chat/conversations/${e}`)}async function P(r,e){const t=await r.get(`/chat/conversations/${e}/messages`);return E(t)}function E(r){const e=[...r].sort((s,c)=>{const i=new Date(s.createTime??0).getTime()||0,d=new Date(c.createTime??0).getTime()||0;return i!==d?i-d:(s.seq??0)-(c.seq??0)}),t=new Map;for(const s of e)s.role==="tool"&&s.toolCallId&&t.set(s.toolCallId,s.content||"");const n=new Set,o=[],a=(s,c,i)=>{const d=o[o.length-1];(d==null?void 0:d.role)==="assistant"?(d.parts.push(...s),d.id=c):o.push({id:c,role:"assistant",parts:[...s],timestamp:i})};for(const s of e){if(s.role==="system")continue;const c=String(s.id??s.messageId??`msg_${Date.now()}`),i=new Date(s.createTime??"").getTime()||Date.now();if(s.role==="human"){const d=(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}}));o.push({id:c,role:"user",parts:[...d,{type:"text",content:u(s.content)}],timestamp:i});continue}if(s.role==="ai"){const d=U(s,t,n);d.length>0&&a(d,c,i);continue}if(s.role==="tool"){if(s.toolCallId&&n.has(s.toolCallId))continue;a([N(s)],c,i)}}return o}function U(r,e,t){const n=[];r.reasoning&&n.push({type:"thinking",content:r.reasoning}),r.content&&n.push({type:"text",content:u(r.content)});for(const o of r.toolCalls??[])o.is_interrupt?(t.add(o.id),n.push(x(o,e))):n.push(v(o));return n}function x(r,e){const t=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:t,response:t?{action:"submit",value:q(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 N(r){var t,n,o;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:((t=r.metadata)==null?void 0:t.renderMode)??((n=r.metadata)==null?void 0:n.render_mode),html:(o=r.metadata)==null?void 0:o.html}}function q(r){if(r!=null)try{return JSON.parse(r)}catch{return r}}async function D(r,e,t,n,o,a,s){const c=await r.streamPost(`/chat/interrupt/${e}/respond`,{sessionId:t,action:n.action,value:n.value},s);if(!c.ok){const i=new Error(`HTTP ${c.status}`);throw a==null||a(i),i}o&&await p(c,i=>{i.type==="error"?a==null||a(new Error(i.content)):o(i)},i=>a==null?void 0:a(i))}async function L(r){return r.get(`/chat/bots/${r.getBotId()}/skills`)}async function G(r,e){await r.post("/chat/stop",{sessionId:e})}function M(r){const e=new k(r);return{botId:e.getBotId(),getToken:()=>e.fetchToken(),createSession:()=>$(e),chat:n=>b(e,n),listConversations:n=>C(e,n),renameConversation:(n,o)=>_(e,n,o),deleteConversation:n=>O(e,n),getMessages:n=>P(e,n),respondInterrupt:(n,o,a,s,c,i)=>D(e,n,o,a,s,c,i),setToken:n=>e.setToken(n),feedback:async(n,o,a)=>{const s={type:o};o==="dislike"&&((a==null?void 0:a.reason)!=null&&(s.reason=a.reason),a!=null&&a.remark&&(s.remark=a.remark)),await e.post(`/chat/messages/${n}/feedback`,s)},cancelFeedback:async n=>{await e.del(`/chat/messages/${n}/feedback`)},listSkills:()=>L(e),stopGeneration:n=>G(e,n)}}exports.createNosUploader=w.createNosUploader;exports.createSuperAgent=M;
|
package/dist/index.d.ts
CHANGED
|
@@ -199,8 +199,8 @@ export declare interface SuperAgentSDK {
|
|
|
199
199
|
renameConversation(sessionId: string, title: string): Promise<void>;
|
|
200
200
|
deleteConversation(sessionId: string): Promise<void>;
|
|
201
201
|
getMessages(sessionId: string): Promise<UIMessage[]>;
|
|
202
|
-
/** 响应中断事件(返回 SSE
|
|
203
|
-
respondInterrupt(interruptId: string, sessionId: string, response: InterruptResponse, onMessage?: (event: ChatEvent) => void, onError?: (error: Error) => void): Promise<void>;
|
|
202
|
+
/** 响应中断事件(返回 SSE 流,后端继续推送后续事件);signal 供调用方中断续流 */
|
|
203
|
+
respondInterrupt(interruptId: string, sessionId: string, response: InterruptResponse, onMessage?: (event: ChatEvent) => void, onError?: (error: Error) => void, signal?: AbortSignal): Promise<void>;
|
|
204
204
|
setToken(token: string): void;
|
|
205
205
|
/** 消息反馈(赞/踩),POST /chat/messages/{messageId}/feedback */
|
|
206
206
|
feedback(messageId: string, type: "like" | "dislike", options?: {
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { c as J } from "./nosUploader-
|
|
1
|
+
import { c as J } from "./nosUploader-BkBtdrMs.js";
|
|
2
2
|
function h(r) {
|
|
3
3
|
if (Array.isArray(r)) return r.map((e) => h(e));
|
|
4
4
|
if (r && typeof r == "object" && r.constructor === Object) {
|
|
5
5
|
const e = {};
|
|
6
6
|
for (const [t, n] of Object.entries(r)) {
|
|
7
|
-
const
|
|
8
|
-
e[
|
|
7
|
+
const o = t.replace(/_([a-z])/g, (a, s) => s.toUpperCase());
|
|
8
|
+
e[o] = h(n);
|
|
9
9
|
}
|
|
10
10
|
return e;
|
|
11
11
|
}
|
|
@@ -40,10 +40,10 @@ class T {
|
|
|
40
40
|
});
|
|
41
41
|
if (!n.ok)
|
|
42
42
|
throw new Error(`HTTP ${n.status}: ${n.statusText}`);
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
throw new Error(
|
|
46
|
-
const a = h(
|
|
43
|
+
const o = await n.json();
|
|
44
|
+
if (o.code !== "200")
|
|
45
|
+
throw new Error(o.message || `API error: ${o.code}`);
|
|
46
|
+
const a = h(o.data);
|
|
47
47
|
return this.token = a.token, a.appId && !this.appId && (this.appId = a.appId), a.token;
|
|
48
48
|
}
|
|
49
49
|
headers(e) {
|
|
@@ -70,15 +70,15 @@ class T {
|
|
|
70
70
|
async request(e, t, n) {
|
|
71
71
|
if (!this.token && !await this.handleTokenRefresh())
|
|
72
72
|
throw new Error("SDK token not available: POST /token failed");
|
|
73
|
-
let
|
|
73
|
+
let o = this.isAbsoluteUrl ? `${this.baseUrl}${t}` : `${this.getOrigin()}${this.baseUrl}${t}`;
|
|
74
74
|
if (n != null && n.params) {
|
|
75
|
-
const
|
|
75
|
+
const c = new URLSearchParams();
|
|
76
76
|
for (const [d, l] of Object.entries(n.params))
|
|
77
|
-
l != null &&
|
|
78
|
-
const
|
|
79
|
-
|
|
77
|
+
l != null && c.set(d, String(l));
|
|
78
|
+
const i = c.toString();
|
|
79
|
+
i && (o += `?${i}`);
|
|
80
80
|
}
|
|
81
|
-
const a = await fetch(
|
|
81
|
+
const a = await fetch(o, {
|
|
82
82
|
method: e,
|
|
83
83
|
headers: this.headers(),
|
|
84
84
|
body: n != null && n.body ? JSON.stringify(n.body) : void 0
|
|
@@ -108,13 +108,13 @@ class T {
|
|
|
108
108
|
async streamPost(e, t, n) {
|
|
109
109
|
if (!this.token && !await this.handleTokenRefresh())
|
|
110
110
|
throw new Error("SDK token not available: POST /token failed");
|
|
111
|
-
const
|
|
111
|
+
const o = this.isAbsoluteUrl ? `${this.baseUrl}${e}` : `${this.getOrigin()}${this.baseUrl}${e}`, a = await fetch(o, {
|
|
112
112
|
method: "POST",
|
|
113
113
|
headers: this.headers(),
|
|
114
114
|
body: JSON.stringify(t),
|
|
115
115
|
signal: n
|
|
116
116
|
});
|
|
117
|
-
return a.status === 401 && await this.handleTokenRefresh() ? fetch(
|
|
117
|
+
return a.status === 401 && await this.handleTokenRefresh() ? fetch(o, {
|
|
118
118
|
method: "POST",
|
|
119
119
|
headers: this.headers(),
|
|
120
120
|
body: JSON.stringify(t),
|
|
@@ -212,19 +212,19 @@ async function p(r, e, t) {
|
|
|
212
212
|
t(new Error("Response body is null"));
|
|
213
213
|
return;
|
|
214
214
|
}
|
|
215
|
-
const n = r.body.getReader(),
|
|
215
|
+
const n = r.body.getReader(), o = new TextDecoder();
|
|
216
216
|
let a = "";
|
|
217
217
|
try {
|
|
218
218
|
for (; ; ) {
|
|
219
|
-
const { value: s, done:
|
|
220
|
-
if (
|
|
221
|
-
a +=
|
|
222
|
-
let
|
|
223
|
-
for (; (
|
|
219
|
+
const { value: s, done: c } = await n.read();
|
|
220
|
+
if (c) break;
|
|
221
|
+
a += o.decode(s, { stream: !0 });
|
|
222
|
+
let i;
|
|
223
|
+
for (; (i = a.indexOf(`
|
|
224
224
|
|
|
225
225
|
`)) !== -1; ) {
|
|
226
|
-
const d = a.slice(0,
|
|
227
|
-
a = a.slice(
|
|
226
|
+
const d = a.slice(0, i);
|
|
227
|
+
a = a.slice(i + 2);
|
|
228
228
|
const l = I(d);
|
|
229
229
|
l && e(l);
|
|
230
230
|
}
|
|
@@ -244,46 +244,46 @@ async function p(r, e, t) {
|
|
|
244
244
|
}
|
|
245
245
|
function k(r, e) {
|
|
246
246
|
var a;
|
|
247
|
-
const t = new AbortController(), n = e.signal ? b(e.signal, t.signal) : t.signal,
|
|
247
|
+
const t = new AbortController(), n = e.signal ? b(e.signal, t.signal) : t.signal, o = {
|
|
248
248
|
botId: r.getBotId(),
|
|
249
249
|
message: e.message,
|
|
250
250
|
sessionId: e.sessionId,
|
|
251
251
|
stream: e.stream !== !1,
|
|
252
252
|
// url 仅前端回显(下载/预览),剥离后发送——签名 URL 不进后端
|
|
253
253
|
...(a = e.attachments) != null && a.length ? {
|
|
254
|
-
attachments: e.attachments.map(({ url: s, ...
|
|
254
|
+
attachments: e.attachments.map(({ url: s, ...c }) => c)
|
|
255
255
|
} : {}
|
|
256
256
|
};
|
|
257
|
-
return
|
|
258
|
-
var
|
|
257
|
+
return o.stream ? r.streamPost("/chat", o, n).then((s) => {
|
|
258
|
+
var c;
|
|
259
259
|
if (!s.ok) {
|
|
260
|
-
(
|
|
260
|
+
(c = e.onError) == null || c.call(e, new Error(`HTTP ${s.status}`));
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
263
|
return p(
|
|
264
264
|
s,
|
|
265
|
-
(
|
|
265
|
+
(i) => {
|
|
266
266
|
var d, l, f, g, y, m;
|
|
267
|
-
|
|
267
|
+
i.type === "done" && i.sessionId ? (d = e.onDone) == null || d.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 === "stop" ? ((f = e.onMessage) == null || f.call(e, i), (g = e.onDone) == null || g.call(e, { sessionId: i.sessionId ?? "", content: i.content, messageId: i.messageId })) : i.type === "error" ? (y = e.onError) == null || y.call(e, new Error(i.content)) : (m = e.onMessage) == null || m.call(e, i);
|
|
268
268
|
},
|
|
269
|
-
(
|
|
269
|
+
(i) => {
|
|
270
270
|
var d;
|
|
271
|
-
return (d = e.onError) == null ? void 0 : d.call(e,
|
|
271
|
+
return (d = e.onError) == null ? void 0 : d.call(e, i);
|
|
272
272
|
}
|
|
273
273
|
);
|
|
274
274
|
}).catch((s) => {
|
|
275
|
-
var
|
|
276
|
-
(s == null ? void 0 : s.name) !== "AbortError" && ((
|
|
277
|
-
}) : r.post("/chat",
|
|
278
|
-
var
|
|
279
|
-
(
|
|
275
|
+
var c;
|
|
276
|
+
(s == null ? void 0 : s.name) !== "AbortError" && ((c = e.onError) == null || c.call(e, s instanceof Error ? s : new Error(String(s))));
|
|
277
|
+
}) : r.post("/chat", o).then((s) => {
|
|
278
|
+
var c;
|
|
279
|
+
(c = e.onDone) == null || c.call(e, {
|
|
280
280
|
sessionId: s.sessionId,
|
|
281
281
|
content: s.content ?? "",
|
|
282
282
|
messageId: s.messageId
|
|
283
283
|
});
|
|
284
284
|
}).catch((s) => {
|
|
285
|
-
var
|
|
286
|
-
(
|
|
285
|
+
var c;
|
|
286
|
+
(c = e.onError) == null || c.call(e, s instanceof Error ? s : new Error(String(s)));
|
|
287
287
|
}), t;
|
|
288
288
|
}
|
|
289
289
|
function b(r, e) {
|
|
@@ -327,19 +327,19 @@ async function O(r, e) {
|
|
|
327
327
|
return P(t);
|
|
328
328
|
}
|
|
329
329
|
function P(r) {
|
|
330
|
-
const e = [...r].sort((s,
|
|
331
|
-
const
|
|
332
|
-
return
|
|
330
|
+
const e = [...r].sort((s, c) => {
|
|
331
|
+
const i = new Date(s.createTime ?? 0).getTime() || 0, d = new Date(c.createTime ?? 0).getTime() || 0;
|
|
332
|
+
return i !== d ? i - d : (s.seq ?? 0) - (c.seq ?? 0);
|
|
333
333
|
}), t = /* @__PURE__ */ new Map();
|
|
334
334
|
for (const s of e)
|
|
335
335
|
s.role === "tool" && s.toolCallId && t.set(s.toolCallId, s.content || "");
|
|
336
|
-
const n = /* @__PURE__ */ new Set(),
|
|
337
|
-
const d =
|
|
338
|
-
(d == null ? void 0 : d.role) === "assistant" ? (d.parts.push(...s), d.id =
|
|
336
|
+
const n = /* @__PURE__ */ new Set(), o = [], a = (s, c, i) => {
|
|
337
|
+
const d = o[o.length - 1];
|
|
338
|
+
(d == null ? void 0 : d.role) === "assistant" ? (d.parts.push(...s), d.id = c) : o.push({ id: c, role: "assistant", parts: [...s], timestamp: i });
|
|
339
339
|
};
|
|
340
340
|
for (const s of e) {
|
|
341
341
|
if (s.role === "system") continue;
|
|
342
|
-
const
|
|
342
|
+
const c = String(s.id ?? s.messageId ?? `msg_${Date.now()}`), i = new Date(s.createTime ?? "").getTime() || Date.now();
|
|
343
343
|
if (s.role === "human") {
|
|
344
344
|
const d = (s.attachments ?? []).map((l) => ({
|
|
345
345
|
type: "attachment",
|
|
@@ -353,31 +353,31 @@ function P(r) {
|
|
|
353
353
|
// 公开读桶下载链接(有则 chip 可点击下载)
|
|
354
354
|
}
|
|
355
355
|
}));
|
|
356
|
-
|
|
357
|
-
id:
|
|
356
|
+
o.push({
|
|
357
|
+
id: c,
|
|
358
358
|
role: "user",
|
|
359
359
|
parts: [...d, { type: "text", content: u(s.content) }],
|
|
360
|
-
timestamp:
|
|
360
|
+
timestamp: i
|
|
361
361
|
});
|
|
362
362
|
continue;
|
|
363
363
|
}
|
|
364
364
|
if (s.role === "ai") {
|
|
365
365
|
const d = x(s, t, n);
|
|
366
|
-
d.length > 0 && a(d,
|
|
366
|
+
d.length > 0 && a(d, c, i);
|
|
367
367
|
continue;
|
|
368
368
|
}
|
|
369
369
|
if (s.role === "tool") {
|
|
370
370
|
if (s.toolCallId && n.has(s.toolCallId)) continue;
|
|
371
|
-
a([v(s)],
|
|
371
|
+
a([v(s)], c, i);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
-
return
|
|
374
|
+
return o;
|
|
375
375
|
}
|
|
376
376
|
function x(r, e, t) {
|
|
377
377
|
const n = [];
|
|
378
378
|
r.reasoning && n.push({ type: "thinking", content: r.reasoning }), r.content && n.push({ type: "text", content: u(r.content) });
|
|
379
|
-
for (const
|
|
380
|
-
|
|
379
|
+
for (const o of r.toolCalls ?? [])
|
|
380
|
+
o.is_interrupt ? (t.add(o.id), n.push(E(o, e))) : n.push(U(o));
|
|
381
381
|
return n;
|
|
382
382
|
}
|
|
383
383
|
function E(r, e) {
|
|
@@ -410,7 +410,7 @@ function U(r) {
|
|
|
410
410
|
return { type: "tool_call", toolName: r.name ?? "", toolCallId: r.id ?? "", args: e };
|
|
411
411
|
}
|
|
412
412
|
function v(r) {
|
|
413
|
-
var t, n,
|
|
413
|
+
var t, n, o;
|
|
414
414
|
const e = Array.isArray(r.artifacts) ? r.artifacts : void 0;
|
|
415
415
|
return {
|
|
416
416
|
type: "tool_result",
|
|
@@ -419,7 +419,7 @@ function v(r) {
|
|
|
419
419
|
content: u(r.content),
|
|
420
420
|
artifacts: e,
|
|
421
421
|
renderMode: ((t = r.metadata) == null ? void 0 : t.renderMode) ?? ((n = r.metadata) == null ? void 0 : n.render_mode),
|
|
422
|
-
html: (
|
|
422
|
+
html: (o = r.metadata) == null ? void 0 : o.html
|
|
423
423
|
};
|
|
424
424
|
}
|
|
425
425
|
function D(r) {
|
|
@@ -430,25 +430,26 @@ function D(r) {
|
|
|
430
430
|
return r;
|
|
431
431
|
}
|
|
432
432
|
}
|
|
433
|
-
async function N(r, e, t, n,
|
|
434
|
-
const
|
|
433
|
+
async function N(r, e, t, n, o, a, s) {
|
|
434
|
+
const c = await r.streamPost(
|
|
435
435
|
`/chat/interrupt/${e}/respond`,
|
|
436
436
|
{
|
|
437
437
|
sessionId: t,
|
|
438
438
|
action: n.action,
|
|
439
439
|
value: n.value
|
|
440
|
-
}
|
|
440
|
+
},
|
|
441
|
+
s
|
|
441
442
|
);
|
|
442
|
-
if (!
|
|
443
|
-
const
|
|
444
|
-
throw a == null || a(
|
|
443
|
+
if (!c.ok) {
|
|
444
|
+
const i = new Error(`HTTP ${c.status}`);
|
|
445
|
+
throw a == null || a(i), i;
|
|
445
446
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
(
|
|
449
|
-
|
|
447
|
+
o && await p(
|
|
448
|
+
c,
|
|
449
|
+
(i) => {
|
|
450
|
+
i.type === "error" ? a == null || a(new Error(i.content)) : o(i);
|
|
450
451
|
},
|
|
451
|
-
(
|
|
452
|
+
(i) => a == null ? void 0 : a(i)
|
|
452
453
|
);
|
|
453
454
|
}
|
|
454
455
|
async function q(r) {
|
|
@@ -465,14 +466,14 @@ function G(r) {
|
|
|
465
466
|
createSession: () => S(e),
|
|
466
467
|
chat: (n) => k(e, n),
|
|
467
468
|
listConversations: (n) => A(e, n),
|
|
468
|
-
renameConversation: (n,
|
|
469
|
+
renameConversation: (n, o) => C(e, n, o),
|
|
469
470
|
deleteConversation: (n) => _(e, n),
|
|
470
471
|
getMessages: (n) => O(e, n),
|
|
471
|
-
respondInterrupt: (n,
|
|
472
|
+
respondInterrupt: (n, o, a, s, c, i) => N(e, n, o, a, s, c, i),
|
|
472
473
|
setToken: (n) => e.setToken(n),
|
|
473
|
-
feedback: async (n,
|
|
474
|
-
const s = { type:
|
|
475
|
-
|
|
474
|
+
feedback: async (n, o, a) => {
|
|
475
|
+
const s = { type: o };
|
|
476
|
+
o === "dislike" && ((a == null ? void 0 : a.reason) != null && (s.reason = a.reason), a != null && a.remark && (s.remark = a.remark)), await e.post(`/chat/messages/${n}/feedback`, s);
|
|
476
477
|
},
|
|
477
478
|
cancelFeedback: async (n) => {
|
|
478
479
|
await e.del(`/chat/messages/${n}/feedback`);
|