@epam/statgpt-dial-toolkit 0.3.0-rc.2 → 0.3.0-rc.21

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.
@@ -19,6 +19,8 @@ export declare class ConversationApi {
19
19
  putOnboardingFile(fileName: string, filePath: string, fileData: OnboardingFileSchema, token: string): Promise<Entity | null>;
20
20
  getOnboardingFile(filePath: string, token: string): Promise<OnboardingFileSchema | null>;
21
21
  getFileBlob(filePath: string, token: string): Promise<Blob | null>;
22
+ deleteFile(filePath: string, token: string): Promise<void>;
23
+ putFile(filePath: string, file: Blob, token: string): Promise<void>;
22
24
  createConversation(data: CreateConversationRequest, token: string): Promise<ConversationInfo>;
23
25
  generateConversationLink(token: string, conversationData?: ConversationData): Promise<GeneratedLinkResponse>;
24
26
  getSharedConversations(token: string, requestData?: SharedConversationsRequest): Promise<SharedConversations>;
package/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m="v1",f=`/${m}/ops/resource/share`,d={VERSION:`/${m}`,BUCKET:`/${m}/bucket`,CONVERSATIONS:`/${m}/metadata/conversations`,CONVERSATION_BY_ID:n=>`/${m}/metadata/conversations/${n}`,CHAT:n=>`/openai/deployments/${n}/chat/completions`,MODELS:"/openai/models",CONFIGURATION:n=>`/${m}/deployments/${n}/configuration`,DATASETS_METADATA:n=>`/v1/deployments/${n}/route/metadata/datasets`,SHARE_CONVERSATION:`${f}/create`,SHARE_CONVERSATION_ACCEPT:n=>`/${m}/invitations/${n}?accept=true`,SHARE_CONVERSATION_DETAILS:n=>`/${m}/invitations/${n}`,SHARE_CONVERSATION_LIST:`${f}/list`,SHARE_CONVERSATION_DISCARD:`${f}/discard`,SHARE_CONVERSATION_REVOKE:`${f}/revoke`,RATE:n=>`/${m}/${n}/rate`,RENAME:`/${m}/ops/resource/move`},H={LENGTH:"length",STOP:"stop"},R={MINUTE:"minute",DAILY:"daily",WEEKLY:"weekly",MONTHLY:"monthly"},U={CONTENT_FILTER:"content_filter",500:"500"},x={RUNTIME_ERROR:"runtime_error",RATE_LIMIT_EXCEEDED:"rate_limit_exceeded"},V=[R.MINUTE,R.DAILY,R.WEEKLY,R.MONTHLY],K="statgpt",g={RATE_LIMIT:"rate_limit",UNKNOWN:"unknown"};var O=(n=>(n.CONVERSATION="CONVERSATION",n))(O||{}),N=(n=>(n.ME="me",n.OTHERS="others",n))(N||{}),y=(n=>(n.CSV="text/csv",n.TABLE="application/dial-ttyd-table",n.PLOTLY="application/vnd.plotly.v1+json",n.MARKDOWN="text/markdown",n.JSON="application/json",n.JPEG="image/jpeg",n.PNG="image/png",n.CUSTOM_DATA_GRID="custom_data_grid",n.CUSTOM_CHART="custom_chart",n.CUSTOM_CODE_SAMPLE="custom_code_sample",n))(y||{}),$=(n=>(n.LINK="link",n))($||{});const j=n=>n.content?(console.info(`Using direct content format: ${n.content}`),n.content):n.choices?.[0]?.delta?.content?(console.info(`Using OpenAI delta format: ${n.choices[0].delta.content}`),n.choices[0].delta.content):n.choices?.[0]?.message?.content?(console.info(`Using complete message format: ${n.choices[0].message.content}`),n.choices[0].message.content):(console.info("Unknown SSE data format:",n),null),v=(n,t,s)=>{if(t?.(n),s){const e=j(n);e&&s(e)}},D=(n,t)=>n.error||n.message||`${t.status} ${t.statusText}`,k=(n,t)=>{const s=n?.reduce((e,r)=>(e[r.index]=r,e),{});return t.forEach(e=>{s[e.index]?(e.attachments&&(s[e.index].attachments=(s[e.index].attachments||[]).concat(e.attachments)),e.content&&(s[e.index].content=(s[e.index].content||"")+e.content),e.name&&(s[e.index].name=(s[e.index].name||"")+e.name),e.status&&(s[e.index].status=e.status)):s[e.index]=e}),Object.values(s)},F=(n,t)=>{const s=structuredClone(n);return t.forEach(e=>{e.errorMessage&&(s.errorMessage=e.errorMessage),e.role&&(s.role=e.role),e.responseId&&(s.responseId=e.responseId),e.content&&Y(s,e),e.custom_content&&(s.custom_content||(s.custom_content={}),e.custom_content.attachments&&(s.custom_content.attachments||(s.custom_content.attachments=[]),s.custom_content.attachments=s.custom_content.attachments.concat(e.custom_content.attachments)),e.custom_content.stages&&(s.custom_content.stages||(s.custom_content.stages=[]),s.custom_content.stages=k(s.custom_content.stages,e.custom_content.stages)),e.custom_content.state&&(s.custom_content.state=e.custom_content.state),e.custom_content.form_schema&&(s.custom_content.form_schema=e.custom_content.form_schema),e.custom_content.form_value&&(s.custom_content.form_value=e.custom_content.form_value))}),s};function Y(n,t){if(t.content){const s=B(t.content);s!=null?n.content=n.content.slice(0,-s):n.content=`${n.content||""}${t.content}`}}function B(n){const t=n.match(/delete_chars\((\d+)\)/);return t!=null?parseInt(t[1],10):null}const G={CHAT:"/api/chat"},J="application/json",X="Content-Type",T="Api-Key",z="X-CONVERSATION-ID",I="Ocp-Apim-Subscription-Key";class C extends Error{constructor(t){super(t.message),this.isHttpError=!0,this.name="HttpError",this.code=t.code,this.status=t.status,this.details=t.details,this.displayMessage=t.displayMessage}}const W=n=>n?.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/g,"").replace(/-/g," ")||"",A=(n,t,s)=>{const e={[X]:t?.contentType||J};return t?.jwt?e.Authorization=`Bearer ${t.jwt}`:n&&(e[T]=n),t?.chatReference&&(e[z]=t.chatReference),{...e,...s}},Q=n=>{const t={...n};return t[T]&&(t[T]=t[T].substring(0,8)+"...[REDACTED]"),t.Authorization&&(t.Authorization="Bearer [REDACTED]"),t[I]&&(t[I]=t[I].substring(0,8)+"...[REDACTED]"),t},Z=n=>({"Content-Type":`multipart/form-data; boundary=${n}`}),w=n=>{const t=n.name?.split("__")||[],s=t.length>1?t.slice(1).join("__"):n.name;return{modelId:t[0],conversationName:s}},L=n=>{const t=Date.now(),s=W(n.name);return`${n.folderId}/${s}-${t}`},ee=n=>({resourceTypes:[O.CONVERSATION],with:n}),S=async(n,t,s)=>await fetch(n,{method:s.method||"GET",headers:t,body:s?.isFormData&&typeof s?.body=="string"?s.body:JSON.stringify(s.body),signal:s?.signal});function h(n){return n.split("/").map(t=>encodeURIComponent(t)).join("/")}function te(n){return n.split("/").map(t=>decodeURIComponent(t)).join("/")}function b(n){if(n?.kind!==g.RATE_LIMIT||typeof n.retryAfterSeconds!="number")return null;const t=new Date(n.occurredAt).getTime();return Number.isNaN(t)?null:new Date(t+n.retryAfterSeconds*1e3)}function se(n,t=Date.now()){const s=b(n);return s?s.getTime()>t:!1}function ne(n,t="en-GB"){return{date:n.toLocaleDateString(t),time:n.toLocaleTimeString(t,{hour:"2-digit",minute:"2-digit"})}}class q{constructor(){this.decoder=new TextDecoder}async streamChat(t,s,e={},r){const{onMessage:a,onError:o,onComplete:i,signal:c}=e;try{const u=await this.initializeStreamRequest(t,s,c,r);await this.processStreamData(u,a),i?.()}catch(u){this.handleStreamError(u,o)}}async initializeStreamRequest(t,s,e,r){const a=A(void 0,{jwt:r}),o=await S(t,{Accept:"text/event-stream",...a},{method:"POST",body:s,signal:e});if(!o.ok){const i=await o.text();let c={};try{c=JSON.parse(i)}catch{c.error="Failed to parse error body"}throw new C({status:o.status,message:c.error??"No response body"})}if(!o.body)throw new C({message:"No response body",status:o.status});return o.body.getReader()}async processStreamData(t,s){let e="";try{for(;;){const{done:r,value:a}=await t.read();if(r){e.trim()&&this.parseSSEDataLine(e,s);break}const o=this.decoder.decode(a,{stream:!0});e+=o;const i=e.split(`
2
- `);e=i.pop()||"";for(const c of i)this.parseSSEDataLine(c,s)}}finally{t.releaseLock()}}handleStreamError(t,s){const e=t instanceof Error?t:new Error(String(t));throw s?.(e),e}parseSSEDataLine(t,s){const e=t.trim();if(!(!e||e.startsWith(":"))&&e.startsWith("data: ")){const r=e.slice(6);if(r==="[DONE]"){console.info("SSE: Stream completed");return}let a;try{a=JSON.parse(r)}catch(o){console.error(`Failed to parse SSE data: ${r} ${o}`)}s?.(a)}}}const M=new q,re=async(n,t,s,e,r)=>{const{onMessage:a,onToken:o,onComplete:i,onError:c,model:u,signal:l}=s,p={conversationId:n,messages:t,model:u,custom_fields:r};await M.streamChat(G.CHAT,p,{onMessage:P=>v(P,a,o),onComplete:i,onError:c,signal:l},e)},E=n=>n instanceof Error&&n.message.includes("404"),_=n=>`/v1/conversations/${h(n)}`;class oe{constructor(t){this.client=t}async getConversations(t,s,e){const r=`${s?e?`${s}/${e}`:`${s}`:""}`,a=`${d.CONVERSATIONS}/${r}`;try{return(await this.client.getRequest(a+"/?limit=1000&recursive=false",t).then(i=>i.items||[])).map(i=>{const{conversationName:c,modelId:u}=w(i);return{id:i.url?.replace("conversations/","")||i.name,name:c,folderId:r,createdAt:i.createdAt,updatedAt:i.updatedAt,model:{id:u,name:u}}})}catch(o){if(E(o))return[];throw o}}async getConversation(t,s){try{return await this.client.getRequest(_(t),s)}catch(e){if(E(e))return null;throw e}}async getFile(t,s){try{const e=`${d.VERSION}/${h(t)}`;return await this.client.getRequest(e,s)}catch(e){if(E(e))return null;throw e}}async putOnboardingFile(t,s,e,r){try{const a=`${d.VERSION}/${h(s)}`,o="----NodeMultipartBoundary",c=[`--${o}`,`Content-Disposition: form-data; name="file"; filename="${t}"`,"Content-Type: application/json","",JSON.stringify(e),`--${o}--`,""].join(`\r
3
- `);return await this.client.request(a,r,{method:"PUT",body:c,headers:Z(o),isFormData:!0})}catch(a){if(E(a))return null;throw a}}async getOnboardingFile(t,s){try{const e=`${d.VERSION}/${h(t)}`;return await this.client.getRequest(e,s)}catch(e){if(E(e))return null;throw e}}async getFileBlob(t,s){try{const e=`${d.VERSION}/${h(t)}`;return await this.client.requestBlob(e,s,{method:"GET"})}catch(e){if(E(e))return null;throw e}}async createConversation(t,s){const e=t?.id||L(t),{name:r,folderId:a,model:o,messages:i,custom_fields:c}=t,u={id:e,name:r,folderId:a,model:o,messages:i||[],selectedAddons:t.selectedAddons||[],prompt:t.prompt||"",temperature:t.temperature||.7,createdAt:Date.now(),updatedAt:Date.now(),custom_fields:c};return await this.client.request(_(e),s,{method:"PUT",body:u}),{id:e,name:r,folderId:a,model:o,createdAt:u.createdAt,updatedAt:u.updatedAt}}async generateConversationLink(t,s){return await this.client.postRequest(d.SHARE_CONVERSATION,t,{body:s})}async getSharedConversations(t,s){return await this.client.postRequest(d.SHARE_CONVERSATION_LIST,t,{body:s})}async revokeSharedConversations(t,s){await this.client.postRequest(d.SHARE_CONVERSATION_REVOKE,t,{body:s})}async updateConversation(t,s,e){const r=await this.getConversation(t,e);if(!r)throw new Error(`Conversation with id ${t} not found`);const a={...r,...s,updatedAt:Date.now()};return await this.client.request(_(t),e,{method:"PUT",body:a})}async deleteConversation(t,s,e){s?.isShared?await this.client.postRequest(d.SHARE_CONVERSATION_DISCARD,e,{body:{resources:[{url:s?.url}]}}):await this.client.request(_(decodeURI(t)),e,{method:"DELETE"})}async streamChat(t,s){const e=t.model.id,r=encodeURIComponent(e),a=`${d.CHAT(r)}?api-version=${this.client.config.version}`,o={messages:t.messages,stream:!0,temperature:.7,max_tokens:4096,custom_fields:t.custom_fields};return await this.client.stream(a,s,{method:"POST",body:o,chatReference:t.conversationId})}async rateResponse(t,s,e,r){return await this.client.postRequest(d.RATE(t),r,{body:{responseId:s,rate:e}})}async renameConversation(t,s,e){return await this.client.postRequest(d.RENAME,e,{body:{sourceUrl:t,destinationUrl:s,overwrite:!0}})}}class ae{constructor(t){this.config=t,console.info("DialApiClient initialized",{host:t.host||"NOT SET",hasApiKey:!!t.apiKey,version:t.version})}async getRequest(t,s,e){return this.request(t,s,{...e,method:"GET"})}async postRequest(t,s,e){return this.request(t,s,{...e,method:"POST"})}async requestBlob(t,s,e){const r=`${this.config.host}${t}`,a={...A(this.config.apiKey,{jwt:s,chatReference:e.chatReference}),...e.headers};try{return(await S(r,a,e)).blob()}catch(o){throw console.error("API Request Exception",{method:e.method,url:r,error:o instanceof Error?o.message:String(o)}),o}}async request(t,s,e){const r=Date.now(),a=`${this.config.host}${t}`,o={...A(this.config.apiKey,{jwt:s,chatReference:e.chatReference}),...e.headers};this.addInfoRequestLog("API Request",a,e,o);try{const i=await S(a,o,e),c=Date.now()-r;let u;const l=await i.text();try{u=l?JSON.parse(l):{}}catch{if(this.addErrorRequestParsing(a,e,i,c,l),!i.ok)throw new Error(`API request failed: ${i.status} ${i.statusText} - ${l.substring(0,100)}`);u={data:l}}if(!i.ok){this.addErrorRequestLog(a,e,i,c,u);const p=D(u,i);throw new Error(`API request failed: ${p}`)}return u}catch(i){const c=Date.now()-r;throw console.error("API Request Exception",{method:e.method,url:a,duration:`${c}ms`,error:i instanceof Error?i.message:String(i)}),i}}async stream(t,s,e){const r=`${this.config.host}${t}`,a=A(this.config.apiKey,{jwt:s,chatReference:e.chatReference},e.headers);this.addInfoRequestLog("Stream Request",r,e,a);const o=await S(r,a,e);if(!o.ok)throw console.error("Stream Request Failed",{method:e.method||"POST",url:r,status:o.status,statusText:o.statusText}),new Error(`Stream request failed: ${o.status} ${o.statusText}`);if(!o.body)throw new Error("No response body for stream");return o.body}addInfoRequestLog(t,s,e,r){const a={method:e.method||"GET",url:s,headers:Q(r)};e.body&&(a.body=e.body),console.info(t,a)}addErrorRequestLog(t,s,e,r,a){console.error("API Request Failed",{method:s.method,url:t,status:e.status,statusText:e.statusText,duration:`${r}ms`,response:a})}addErrorRequestParsing(t,s,e,r,a){console.error("API Response Parse Error",{method:s.method,url:t,status:e.status,statusText:e.statusText,duration:`${r}ms`,responseText:a.substring(0,200),error:"Response is not valid JSON"})}}exports.AttachmentType=y;exports.COMPLETION_FINISH_REASON=H;exports.CUSTOM_VIEW_STATE_KEY=K;exports.ChatStreamSSEClient=q;exports.ConversationApi=oe;exports.DIAL_API_ROUTES=d;exports.DIAL_ERROR_CODES=U;exports.DIAL_ERROR_TYPES=x;exports.DialApiClient=ae;exports.ERROR_CONTEXT_KIND=g;exports.EXCEEDED_LIMIT=R;exports.EXCEEDED_LIMIT_ORDER=V;exports.InvitationType=$;exports.ResourceTypes=O;exports.ShareTarget=N;exports.chatStreamSSEClient=M;exports.decodeApiUrl=te;exports.encodeApiUrl=h;exports.formatDateTime=ne;exports.generateConversationId=L;exports.getErrorMessage=D;exports.getRateLimitRestoreDate=b;exports.getSharedConversationsRequest=ee;exports.handleStreamMessage=v;exports.isRateLimitStillActive=se;exports.mergeMessages=F;exports.parseConversationName=w;exports.sendRequest=S;exports.streamChatResponse=re;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l="v1",f=`/${l}/ops/resource/share`,u={VERSION:`/${l}`,BUCKET:`/${l}/bucket`,CONVERSATIONS:`/${l}/metadata/conversations`,CONVERSATION_BY_ID:s=>`/${l}/metadata/conversations/${s}`,CHAT:s=>`/openai/deployments/${s}/chat/completions`,MODELS:"/openai/models",CONFIGURATION:s=>`/${l}/deployments/${s}/configuration`,DATASETS_METADATA:s=>`/v1/deployments/${s}/route/metadata/datasets`,SHARE_CONVERSATION:`${f}/create`,SHARE_CONVERSATION_ACCEPT:s=>`/${l}/invitations/${s}?accept=true`,SHARE_CONVERSATION_DETAILS:s=>`/${l}/invitations/${s}`,SHARE_CONVERSATION_LIST:`${f}/list`,SHARE_CONVERSATION_DISCARD:`${f}/discard`,SHARE_CONVERSATION_REVOKE:`${f}/revoke`,RATE:s=>`/${l}/${s}/rate`,RENAME:`/${l}/ops/resource/move`},H={LENGTH:"length",STOP:"stop"},R={MINUTE:"minute",DAILY:"daily",WEEKLY:"weekly",MONTHLY:"monthly"},U={CONTENT_FILTER:"content_filter",500:"500"},V={RUNTIME_ERROR:"runtime_error",RATE_LIMIT_EXCEEDED:"rate_limit_exceeded"},x=[R.MINUTE,R.DAILY,R.WEEKLY,R.MONTHLY],F="statgpt",N={RATE_LIMIT:"rate_limit",UNKNOWN:"unknown"};var O=(s=>(s.CONVERSATION="CONVERSATION",s))(O||{}),g=(s=>(s.ME="me",s.OTHERS="others",s))(g||{}),y=(s=>(s.CSV="text/csv",s.TABLE="application/dial-ttyd-table",s.PLOTLY="application/vnd.plotly.v1+json",s.MARKDOWN="text/markdown",s.JSON="application/json",s.JPEG="image/jpeg",s.PNG="image/png",s.CROSS_DATASET_GRID="cross_dataset_grid",s.CUSTOM_DATA_GRID="custom_data_grid",s.CUSTOM_CHART="custom_chart",s.CUSTOM_CODE_SAMPLE="custom_code_sample",s))(y||{}),$=(s=>(s.LINK="link",s))($||{});const K=s=>s.content?(console.info(`Using direct content format: ${s.content}`),s.content):s.choices?.[0]?.delta?.content?(console.info(`Using OpenAI delta format: ${s.choices[0].delta.content}`),s.choices[0].delta.content):s.choices?.[0]?.message?.content?(console.info(`Using complete message format: ${s.choices[0].message.content}`),s.choices[0].message.content):(console.info("Unknown SSE data format:",s),null),D=(s,t,n)=>{if(t?.(s),n){const e=K(s);e&&n(e)}},v=(s,t)=>s.error||s.message||`${t.status} ${t.statusText}`,j=(s,t)=>{const n=s?.reduce((e,r)=>(e[r.index]=r,e),{});return t.forEach(e=>{n[e.index]?(e.attachments&&(n[e.index].attachments=(n[e.index].attachments||[]).concat(e.attachments)),e.content&&(n[e.index].content=(n[e.index].content||"")+e.content),e.name&&(n[e.index].name=(n[e.index].name||"")+e.name),e.status&&(n[e.index].status=e.status)):n[e.index]=e}),Object.values(n)},k=(s,t)=>{const n=structuredClone(s);return t.forEach(e=>{e.errorMessage&&(n.errorMessage=e.errorMessage),e.role&&(n.role=e.role),e.responseId&&(n.responseId=e.responseId),e.content&&Y(n,e),e.custom_content&&(n.custom_content||(n.custom_content={}),e.custom_content.attachments&&(n.custom_content.attachments||(n.custom_content.attachments=[]),n.custom_content.attachments=n.custom_content.attachments.concat(e.custom_content.attachments)),e.custom_content.stages&&(n.custom_content.stages||(n.custom_content.stages=[]),n.custom_content.stages=j(n.custom_content.stages,e.custom_content.stages)),e.custom_content.state&&(n.custom_content.state=e.custom_content.state),e.custom_content.form_schema&&(n.custom_content.form_schema=e.custom_content.form_schema),e.custom_content.form_value&&(n.custom_content.form_value=e.custom_content.form_value))}),n};function Y(s,t){if(t.content){const n=B(t.content);n!=null?s.content=s.content.slice(0,-n):s.content=`${s.content||""}${t.content}`}}function B(s){const t=s.match(/delete_chars\((\d+)\)/);return t!=null?parseInt(t[1],10):null}const G={CHAT:"/api/chat"},J="application/json",X="Content-Type",T="Api-Key",z="X-CONVERSATION-ID",I="Ocp-Apim-Subscription-Key";class C extends Error{constructor(t){super(t.message),this.isHttpError=!0,this.name="HttpError",this.code=t.code,this.status=t.status,this.details=t.details,this.displayMessage=t.displayMessage}}const W=s=>s?.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/g,"").replace(/-/g," ")||"",p=(s,t,n)=>{const e={};return t?.contentType!==null&&(e[X]=t?.contentType||J),t?.jwt?e.Authorization=`Bearer ${t.jwt}`:s&&(e[T]=s),t?.chatReference&&(e[z]=t.chatReference),{...e,...n}},Q=s=>{const t={...s};return t[T]&&(t[T]=t[T].substring(0,8)+"...[REDACTED]"),t.Authorization&&(t.Authorization="Bearer [REDACTED]"),t[I]&&(t[I]=t[I].substring(0,8)+"...[REDACTED]"),t},Z=s=>({"Content-Type":`multipart/form-data; boundary=${s}`}),w=s=>{const t=s.name?.split("__")||[],n=t.length>1?t.slice(1).join("__"):s.name;return{modelId:t[0],conversationName:n}},L=s=>{const t=Date.now(),n=W(s.name);return`${s.folderId}/${n}-${t}`},ee=s=>({resourceTypes:[O.CONVERSATION],with:s}),S=async(s,t,n)=>{const e=n?.body===void 0?void 0:n?.isFormData?n.body:JSON.stringify(n.body);return await fetch(s,{method:n.method||"GET",headers:t,body:e,signal:n?.signal})};function E(s){return s.split("/").map(t=>encodeURIComponent(t)).join("/")}function te(s){return s.split("/").map(t=>decodeURIComponent(t)).join("/")}function b(s){if(s?.kind!==N.RATE_LIMIT||typeof s.retryAfterSeconds!="number")return null;const t=new Date(s.occurredAt).getTime();return Number.isNaN(t)?null:new Date(t+s.retryAfterSeconds*1e3)}function ne(s,t=Date.now()){const n=b(s);return n?n.getTime()>t:!1}function se(s,t="en-GB"){return{date:s.toLocaleDateString(t),time:s.toLocaleTimeString(t,{hour:"2-digit",minute:"2-digit"})}}class q{constructor(){this.decoder=new TextDecoder}async streamChat(t,n,e={},r){const{onMessage:a,onError:o,onComplete:i,signal:c}=e;try{const d=await this.initializeStreamRequest(t,n,c,r);await this.processStreamData(d,a),i?.()}catch(d){this.handleStreamError(d,o)}}async initializeStreamRequest(t,n,e,r){const a=p(void 0,{jwt:r}),o=await S(t,{Accept:"text/event-stream",...a},{method:"POST",body:n,signal:e});if(!o.ok){const i=await o.text();let c={};try{c=JSON.parse(i)}catch{c.error="Failed to parse error body"}throw new C({status:o.status,message:c.error??"No response body"})}if(!o.body)throw new C({message:"No response body",status:o.status});return o.body.getReader()}async processStreamData(t,n){let e="";try{for(;;){const{done:r,value:a}=await t.read();if(r){e.trim()&&this.parseSSEDataLine(e,n);break}const o=this.decoder.decode(a,{stream:!0});e+=o;const i=e.split(`
2
+ `);e=i.pop()||"";for(const c of i)this.parseSSEDataLine(c,n)}}finally{t.releaseLock()}}handleStreamError(t,n){const e=t instanceof Error?t:new Error(String(t));throw n?.(e),e}parseSSEDataLine(t,n){const e=t.trim();if(!(!e||e.startsWith(":"))&&e.startsWith("data: ")){const r=e.slice(6);if(r==="[DONE]"){console.info("SSE: Stream completed");return}let a;try{a=JSON.parse(r)}catch(o){console.error(`Failed to parse SSE data: ${r} ${o}`)}n?.(a)}}}const M=new q,re=async(s,t,n,e,r)=>{const{onMessage:a,onToken:o,onComplete:i,onError:c,model:d,signal:h}=n,A={conversationId:s,messages:t,model:d,custom_fields:r};await M.streamChat(G.CHAT,A,{onMessage:P=>D(P,a,o),onComplete:i,onError:c,signal:h},e)},m=s=>s instanceof Error&&s.message.includes("404"),_=s=>`/v1/conversations/${E(s)}`;class oe{constructor(t){this.client=t}async getConversations(t,n,e){const r=`${n?e?`${n}/${e}`:`${n}`:""}`,a=`${u.CONVERSATIONS}/${r}`;try{return(await this.client.getRequest(a+"/?limit=1000&recursive=false",t).then(i=>i.items||[])).map(i=>{const{conversationName:c,modelId:d}=w(i);return{id:i.url?.replace("conversations/","")||i.name,name:c,folderId:r,createdAt:i.createdAt,updatedAt:i.updatedAt,model:{id:d,name:d}}})}catch(o){if(m(o))return[];throw o}}async getConversation(t,n){try{return await this.client.getRequest(_(t),n)}catch(e){if(m(e))return null;throw e}}async getFile(t,n){try{const e=`${u.VERSION}/${E(t)}`;return await this.client.getRequest(e,n)}catch(e){if(m(e))return null;throw e}}async putOnboardingFile(t,n,e,r){try{const a=`${u.VERSION}/${E(n)}`,o="----NodeMultipartBoundary",c=[`--${o}`,`Content-Disposition: form-data; name="file"; filename="${t}"`,"Content-Type: application/json","",JSON.stringify(e),`--${o}--`,""].join(`\r
3
+ `);return await this.client.request(a,r,{method:"PUT",body:c,headers:Z(o),isFormData:!0})}catch(a){if(m(a))return null;throw a}}async getOnboardingFile(t,n){try{const e=`${u.VERSION}/${E(t)}`;return await this.client.getRequest(e,n)}catch(e){if(m(e))return null;throw e}}async getFileBlob(t,n){try{const e=`${u.VERSION}/${E(t)}`;return await this.client.requestBlob(e,n,{method:"GET"})}catch(e){if(m(e))return null;throw e}}async deleteFile(t,n){try{const e=`${u.VERSION}/${E(t)}`;await this.client.request(e,n,{method:"DELETE"})}catch(e){if(m(e))return;throw e}}async putFile(t,n,e){try{const r=`${u.VERSION}/${E(t)}`,a=new FormData,o=decodeURIComponent(t.split("/").at(-1)??"file");a.append("attachment",n,o),await this.client.request(r,e,{method:"PUT",body:a,isFormData:!0})}catch(r){if(m(r))return;throw r}}async createConversation(t,n){const e=t?.id||L(t),{name:r,folderId:a,model:o,messages:i,custom_fields:c}=t,d={id:e,name:r,folderId:a,model:o,messages:i||[],selectedAddons:t.selectedAddons||[],prompt:t.prompt||"",temperature:t.temperature||.7,createdAt:Date.now(),updatedAt:Date.now(),custom_fields:c};return await this.client.request(_(e),n,{method:"PUT",body:d}),{id:e,name:r,folderId:a,model:o,createdAt:d.createdAt,updatedAt:d.updatedAt}}async generateConversationLink(t,n){return await this.client.postRequest(u.SHARE_CONVERSATION,t,{body:n})}async getSharedConversations(t,n){return await this.client.postRequest(u.SHARE_CONVERSATION_LIST,t,{body:n})}async revokeSharedConversations(t,n){await this.client.postRequest(u.SHARE_CONVERSATION_REVOKE,t,{body:n})}async updateConversation(t,n,e){const r=await this.getConversation(t,e);if(!r)throw new Error(`Conversation with id ${t} not found`);const a={...r,...n,updatedAt:Date.now()};return await this.client.request(_(t),e,{method:"PUT",body:a})}async deleteConversation(t,n,e){n?.isShared?await this.client.postRequest(u.SHARE_CONVERSATION_DISCARD,e,{body:{resources:[{url:n?.url}]}}):await this.client.request(_(decodeURI(t)),e,{method:"DELETE"})}async streamChat(t,n){const e=t.model.id,r=encodeURIComponent(e),a=`${u.CHAT(r)}?api-version=${this.client.config.version}`,o={messages:t.messages,stream:!0,temperature:.7,max_tokens:4096,custom_fields:t.custom_fields};return await this.client.stream(a,n,{method:"POST",body:o,chatReference:t.conversationId})}async rateResponse(t,n,e,r){return await this.client.postRequest(u.RATE(t),r,{body:{responseId:n,rate:e}})}async renameConversation(t,n,e){return await this.client.postRequest(u.RENAME,e,{body:{sourceUrl:t,destinationUrl:n,overwrite:!0}})}}class ae{constructor(t){this.config=t,console.info("DialApiClient initialized",{host:t.host||"NOT SET",hasApiKey:!!t.apiKey,version:t.version})}async getRequest(t,n,e){return this.request(t,n,{...e,method:"GET"})}async postRequest(t,n,e){return this.request(t,n,{...e,method:"POST"})}async requestBlob(t,n,e){const r=`${this.config.host}${t}`,a={...p(this.config.apiKey,{jwt:n,chatReference:e.chatReference,contentType:e.isFormData?null:void 0}),...e.headers};try{return(await S(r,a,e)).blob()}catch(o){throw console.error("API Request Exception",{method:e.method,url:r,error:o instanceof Error?o.message:String(o)}),o}}async request(t,n,e){const r=Date.now(),a=`${this.config.host}${t}`,o={...p(this.config.apiKey,{jwt:n,chatReference:e.chatReference,contentType:e.isFormData?null:void 0}),...e.headers};this.addInfoRequestLog("API Request",a,e,o);try{const i=await S(a,o,e),c=Date.now()-r;let d;const h=await i.text();try{d=h?JSON.parse(h):{}}catch{if(this.addErrorRequestParsing(a,e,i,c,h),!i.ok)throw new Error(`API request failed: ${i.status} ${i.statusText} - ${h.substring(0,100)}`);d={data:h}}if(!i.ok){this.addErrorRequestLog(a,e,i,c,d);const A=v(d,i);throw new Error(`API request failed: ${A}`)}return d}catch(i){const c=Date.now()-r;throw console.error("API Request Exception",{method:e.method,url:a,duration:`${c}ms`,error:i instanceof Error?i.message:String(i)}),i}}async stream(t,n,e){const r=`${this.config.host}${t}`,a=p(this.config.apiKey,{jwt:n,chatReference:e.chatReference,contentType:e.isFormData?null:void 0},e.headers);this.addInfoRequestLog("Stream Request",r,e,a);const o=await S(r,a,e);if(!o.ok)throw console.error("Stream Request Failed",{method:e.method||"POST",url:r,status:o.status,statusText:o.statusText}),new Error(`Stream request failed: ${o.status} ${o.statusText}`);if(!o.body)throw new Error("No response body for stream");return o.body}addInfoRequestLog(t,n,e,r){const a={method:e.method||"GET",url:n,headers:Q(r)};e.body&&(a.body=e.body),console.info(t,a)}addErrorRequestLog(t,n,e,r,a){console.error("API Request Failed",{method:n.method,url:t,status:e.status,statusText:e.statusText,duration:`${r}ms`,response:a})}addErrorRequestParsing(t,n,e,r,a){console.error("API Response Parse Error",{method:n.method,url:t,status:e.status,statusText:e.statusText,duration:`${r}ms`,responseText:a.substring(0,200),error:"Response is not valid JSON"})}}exports.AttachmentType=y;exports.COMPLETION_FINISH_REASON=H;exports.CUSTOM_VIEW_STATE_KEY=F;exports.ChatStreamSSEClient=q;exports.ConversationApi=oe;exports.DIAL_API_ROUTES=u;exports.DIAL_ERROR_CODES=U;exports.DIAL_ERROR_TYPES=V;exports.DialApiClient=ae;exports.ERROR_CONTEXT_KIND=N;exports.EXCEEDED_LIMIT=R;exports.EXCEEDED_LIMIT_ORDER=x;exports.InvitationType=$;exports.ResourceTypes=O;exports.ShareTarget=g;exports.chatStreamSSEClient=M;exports.decodeApiUrl=te;exports.encodeApiUrl=E;exports.formatDateTime=se;exports.generateConversationId=L;exports.getErrorMessage=v;exports.getRateLimitRestoreDate=b;exports.getSharedConversationsRequest=ee;exports.handleStreamMessage=D;exports.isRateLimitStillActive=ne;exports.mergeMessages=k;exports.parseConversationName=w;exports.sendRequest=S;exports.streamChatResponse=re;
package/index.mjs CHANGED
@@ -38,7 +38,7 @@ const h = "/v1/ops/resource/share", d = {
38
38
  RATE_LIMIT: "rate_limit",
39
39
  UNKNOWN: "unknown"
40
40
  };
41
- var T = /* @__PURE__ */ ((s) => (s.CONVERSATION = "CONVERSATION", s))(T || {}), g = /* @__PURE__ */ ((s) => (s.ME = "me", s.OTHERS = "others", s))(g || {}), y = /* @__PURE__ */ ((s) => (s.CSV = "text/csv", s.TABLE = "application/dial-ttyd-table", s.PLOTLY = "application/vnd.plotly.v1+json", s.MARKDOWN = "text/markdown", s.JSON = "application/json", s.JPEG = "image/jpeg", s.PNG = "image/png", s.CUSTOM_DATA_GRID = "custom_data_grid", s.CUSTOM_CHART = "custom_chart", s.CUSTOM_CODE_SAMPLE = "custom_code_sample", s))(y || {}), $ = /* @__PURE__ */ ((s) => (s.LINK = "link", s))($ || {});
41
+ var A = /* @__PURE__ */ ((s) => (s.CONVERSATION = "CONVERSATION", s))(A || {}), y = /* @__PURE__ */ ((s) => (s.ME = "me", s.OTHERS = "others", s))(y || {}), g = /* @__PURE__ */ ((s) => (s.CSV = "text/csv", s.TABLE = "application/dial-ttyd-table", s.PLOTLY = "application/vnd.plotly.v1+json", s.MARKDOWN = "text/markdown", s.JSON = "application/json", s.JPEG = "image/jpeg", s.PNG = "image/png", s.CROSS_DATASET_GRID = "cross_dataset_grid", s.CUSTOM_DATA_GRID = "custom_data_grid", s.CUSTOM_CHART = "custom_chart", s.CUSTOM_CODE_SAMPLE = "custom_code_sample", s))(g || {}), $ = /* @__PURE__ */ ((s) => (s.LINK = "link", s))($ || {});
42
42
  const w = (s) => s.content ? (console.info(`Using direct content format: ${s.content}`), s.content) : s.choices?.[0]?.delta?.content ? (console.info(`Using OpenAI delta format: ${s.choices[0].delta.content}`), s.choices[0].delta.content) : s.choices?.[0]?.message?.content ? (console.info(
43
43
  `Using complete message format: ${s.choices[0].message.content}`
44
44
  ), s.choices[0].message.content) : (console.info("Unknown SSE data format:", s), null), v = (s, t, n) => {
@@ -77,48 +77,49 @@ function L(s) {
77
77
  }
78
78
  const V = {
79
79
  CHAT: "/api/chat"
80
- }, M = "application/json", P = "Content-Type", S = "Api-Key", H = "X-CONVERSATION-ID", p = "Ocp-Apim-Subscription-Key";
81
- class A extends Error {
80
+ }, M = "application/json", P = "Content-Type", S = "Api-Key", H = "X-CONVERSATION-ID", T = "Ocp-Apim-Subscription-Key";
81
+ class p extends Error {
82
82
  constructor(t) {
83
83
  super(t.message), this.isHttpError = !0, this.name = "HttpError", this.code = t.code, this.status = t.status, this.details = t.details, this.displayMessage = t.displayMessage;
84
84
  }
85
85
  }
86
86
  const x = (s) => s?.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-+|-+$/g, "").replace(/-/g, " ") || "", _ = (s, t, n) => {
87
- const e = {
88
- [P]: t?.contentType || M
89
- };
90
- return t?.jwt ? e.Authorization = `Bearer ${t.jwt}` : s && (e[S] = s), t?.chatReference && (e[H] = t.chatReference), { ...e, ...n };
87
+ const e = {};
88
+ return t?.contentType !== null && (e[P] = t?.contentType || M), t?.jwt ? e.Authorization = `Bearer ${t.jwt}` : s && (e[S] = s), t?.chatReference && (e[H] = t.chatReference), { ...e, ...n };
91
89
  }, U = (s) => {
92
90
  const t = { ...s };
93
- return t[S] && (t[S] = t[S].substring(0, 8) + "...[REDACTED]"), t.Authorization && (t.Authorization = "Bearer [REDACTED]"), t[p] && (t[p] = t[p].substring(0, 8) + "...[REDACTED]"), t;
94
- }, K = (s) => ({
91
+ return t[S] && (t[S] = t[S].substring(0, 8) + "...[REDACTED]"), t.Authorization && (t.Authorization = "Bearer [REDACTED]"), t[T] && (t[T] = t[T].substring(0, 8) + "...[REDACTED]"), t;
92
+ }, F = (s) => ({
95
93
  "Content-Type": `multipart/form-data; boundary=${s}`
96
- }), j = (s) => {
94
+ }), K = (s) => {
97
95
  const t = s.name?.split("__") || [], n = t.length > 1 ? t.slice(1).join("__") : s.name;
98
96
  return { modelId: t[0], conversationName: n };
99
- }, k = (s) => {
97
+ }, j = (s) => {
100
98
  const t = Date.now(), n = x(s.name);
101
99
  return `${s.folderId}/${n}-${t}`;
102
- }, Z = (s) => ({ resourceTypes: [T.CONVERSATION], with: s }), I = async (s, t, n) => await fetch(s, {
103
- method: n.method || "GET",
104
- headers: t,
105
- body: n?.isFormData && typeof n?.body == "string" ? n.body : JSON.stringify(n.body),
106
- signal: n?.signal
107
- });
100
+ }, Z = (s) => ({ resourceTypes: [A.CONVERSATION], with: s }), I = async (s, t, n) => {
101
+ const e = n?.body === void 0 ? void 0 : n?.isFormData ? n.body : JSON.stringify(n.body);
102
+ return await fetch(s, {
103
+ method: n.method || "GET",
104
+ headers: t,
105
+ body: e,
106
+ signal: n?.signal
107
+ });
108
+ };
108
109
  function E(s) {
109
110
  return s.split("/").map((t) => encodeURIComponent(t)).join("/");
110
111
  }
111
112
  function ee(s) {
112
113
  return s.split("/").map((t) => decodeURIComponent(t)).join("/");
113
114
  }
114
- function F(s) {
115
+ function k(s) {
115
116
  if (s?.kind !== C.RATE_LIMIT || typeof s.retryAfterSeconds != "number")
116
117
  return null;
117
118
  const t = new Date(s.occurredAt).getTime();
118
119
  return Number.isNaN(t) ? null : new Date(t + s.retryAfterSeconds * 1e3);
119
120
  }
120
121
  function te(s, t = Date.now()) {
121
- const n = F(s);
122
+ const n = k(s);
122
123
  return n ? n.getTime() > t : !1;
123
124
  }
124
125
  function ne(s, t = "en-GB") {
@@ -171,13 +172,13 @@ class Y {
171
172
  } catch {
172
173
  i.error = "Failed to parse error body";
173
174
  }
174
- throw new A({
175
+ throw new p({
175
176
  status: o.status,
176
177
  message: i.error ?? "No response body"
177
178
  });
178
179
  }
179
180
  if (!o.body)
180
- throw new A({
181
+ throw new p({
181
182
  message: "No response body",
182
183
  status: o.status
183
184
  });
@@ -253,7 +254,7 @@ class re {
253
254
  const r = `${n ? e ? `${n}/${e}` : `${n}` : ""}`, a = `${d.CONVERSATIONS}/${r}`;
254
255
  try {
255
256
  return (await this.client.getRequest(a + "/?limit=1000&recursive=false", t).then((c) => c.items || [])).map((c) => {
256
- const { conversationName: i, modelId: u } = j(c);
257
+ const { conversationName: i, modelId: u } = K(c);
257
258
  return {
258
259
  id: c.url?.replace("conversations/", "") || c.name,
259
260
  name: i,
@@ -306,7 +307,7 @@ class re {
306
307
  return await this.client.request(a, r, {
307
308
  method: "PUT",
308
309
  body: i,
309
- headers: K(o),
310
+ headers: F(o),
310
311
  isFormData: !0
311
312
  });
312
313
  } catch (a) {
@@ -335,8 +336,32 @@ class re {
335
336
  throw e;
336
337
  }
337
338
  }
339
+ async deleteFile(t, n) {
340
+ try {
341
+ const e = `${d.VERSION}/${E(t)}`;
342
+ await this.client.request(e, n, { method: "DELETE" });
343
+ } catch (e) {
344
+ if (l(e))
345
+ return;
346
+ throw e;
347
+ }
348
+ }
349
+ async putFile(t, n, e) {
350
+ try {
351
+ const r = `${d.VERSION}/${E(t)}`, a = new FormData(), o = decodeURIComponent(t.split("/").at(-1) ?? "file");
352
+ a.append("attachment", n, o), await this.client.request(r, e, {
353
+ method: "PUT",
354
+ body: a,
355
+ isFormData: !0
356
+ });
357
+ } catch (r) {
358
+ if (l(r))
359
+ return;
360
+ throw r;
361
+ }
362
+ }
338
363
  async createConversation(t, n) {
339
- const e = t?.id || k(t), { name: r, folderId: a, model: o, messages: c, custom_fields: i } = t, u = {
364
+ const e = t?.id || j(t), { name: r, folderId: a, model: o, messages: c, custom_fields: i } = t, u = {
340
365
  id: e,
341
366
  name: r,
342
367
  folderId: a,
@@ -481,7 +506,8 @@ class oe {
481
506
  const r = `${this.config.host}${t}`, a = {
482
507
  ..._(this.config.apiKey, {
483
508
  jwt: n,
484
- chatReference: e.chatReference
509
+ chatReference: e.chatReference,
510
+ contentType: e.isFormData ? null : void 0
485
511
  }),
486
512
  ...e.headers
487
513
  };
@@ -499,7 +525,8 @@ class oe {
499
525
  const r = Date.now(), a = `${this.config.host}${t}`, o = {
500
526
  ..._(this.config.apiKey, {
501
527
  jwt: n,
502
- chatReference: e.chatReference
528
+ chatReference: e.chatReference,
529
+ contentType: e.isFormData ? null : void 0
503
530
  }),
504
531
  ...e.headers
505
532
  };
@@ -544,7 +571,8 @@ class oe {
544
571
  this.config.apiKey,
545
572
  {
546
573
  jwt: n,
547
- chatReference: e.chatReference
574
+ chatReference: e.chatReference,
575
+ contentType: e.isFormData ? null : void 0
548
576
  },
549
577
  e.headers
550
578
  );
@@ -595,7 +623,7 @@ class oe {
595
623
  }
596
624
  }
597
625
  export {
598
- y as AttachmentType,
626
+ g as AttachmentType,
599
627
  G as COMPLETION_FINISH_REASON,
600
628
  X as CUSTOM_VIEW_STATE_KEY,
601
629
  Y as ChatStreamSSEClient,
@@ -608,20 +636,20 @@ export {
608
636
  R as EXCEEDED_LIMIT,
609
637
  W as EXCEEDED_LIMIT_ORDER,
610
638
  $ as InvitationType,
611
- T as ResourceTypes,
612
- g as ShareTarget,
639
+ A as ResourceTypes,
640
+ y as ShareTarget,
613
641
  B as chatStreamSSEClient,
614
642
  ee as decodeApiUrl,
615
643
  E as encodeApiUrl,
616
644
  ne as formatDateTime,
617
- k as generateConversationId,
645
+ j as generateConversationId,
618
646
  D as getErrorMessage,
619
- F as getRateLimitRestoreDate,
647
+ k as getRateLimitRestoreDate,
620
648
  Z as getSharedConversationsRequest,
621
649
  v as handleStreamMessage,
622
650
  te as isRateLimitStillActive,
623
651
  Q as mergeMessages,
624
- j as parseConversationName,
652
+ K as parseConversationName,
625
653
  I as sendRequest,
626
654
  se as streamChatResponse
627
655
  };
@@ -17,6 +17,7 @@ export interface CreateConversationRequest {
17
17
  }
18
18
  export interface UpdateConversationRequest {
19
19
  name?: string;
20
+ id?: string;
20
21
  folderId?: string;
21
22
  model?: ModelInfo;
22
23
  prompt?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epam/statgpt-dial-toolkit",
3
- "version": "0.3.0-rc.2",
3
+ "version": "0.3.0-rc.21",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": {
@@ -14,7 +14,7 @@
14
14
  "module": "./index.mjs",
15
15
  "types": "./index.d.ts",
16
16
  "dependencies": {
17
- "@epam/statgpt-shared-toolkit": "0.3.0-rc.2",
17
+ "@epam/statgpt-shared-toolkit": "0.3.0-rc.21",
18
18
  "@epam/ai-dial-shared": "^0.43.3"
19
19
  }
20
20
  }
@@ -6,6 +6,7 @@ export declare enum AttachmentType {
6
6
  JSON = "application/json",
7
7
  JPEG = "image/jpeg",
8
8
  PNG = "image/png",
9
+ CROSS_DATASET_GRID = "cross_dataset_grid",
9
10
  CUSTOM_DATA_GRID = "custom_data_grid",
10
11
  CUSTOM_CHART = "custom_chart",
11
12
  CUSTOM_CODE_SAMPLE = "custom_code_sample"