@epam/statgpt-dial-toolkit 0.2.0-rc.0 → 0.2.0-rc.10

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.
@@ -1,5 +1,5 @@
1
- import { CustomFields, MessageStreamResponse, RequestStreamBody } from '../models/chat-stream';
2
1
  import { Message } from '../models/message';
2
+ import { CustomFields, MessageStreamResponse, RequestStreamBody } from '../models/chat-stream';
3
3
  import { ModelInfo } from '../models/model';
4
4
  interface SSEOptions {
5
5
  signal?: AbortSignal;
package/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m="v1",R=`/${m}/ops/resource/share`,u={VERSION:`/${m}`,BUCKET:`/${m}/bucket`,CONVERSATIONS:`/${m}/metadata/conversations`,CONVERSATION_BY_ID:s=>`/${m}/metadata/conversations/${s}`,CHAT:s=>`/openai/deployments/${s}/chat/completions`,MODELS:"/openai/models",CONFIGURATION:s=>`/${m}/deployments/${s}/configuration`,SHARE_CONVERSATION:`${R}/create`,SHARE_CONVERSATION_ACCEPT:s=>`/${m}/invitations/${s}?accept=true`,SHARE_CONVERSATION_DETAILS:s=>`/${m}/invitations/${s}`,SHARE_CONVERSATION_LIST:`${R}/list`,SHARE_CONVERSATION_DISCARD:`${R}/discard`,SHARE_CONVERSATION_REVOKE:`${R}/revoke`,RATE:`/${m}/rate`,RENAME:`/${m}/ops/resource/move`};var T=(s=>(s.CONVERSATION="CONVERSATION",s))(T||{}),_=(s=>(s.ME="me",s.OTHERS="others",s))(_||{}),O=(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))(O||{}),I=(s=>(s.LINK="link",s))(I||{});const b=s=>{var t,r,e,n,o,a;return s.content?(console.info(`Using direct content format: ${s.content}`),s.content):(e=(r=(t=s.choices)==null?void 0:t[0])==null?void 0:r.delta)!=null&&e.content?(console.info(`Using OpenAI delta format: ${s.choices[0].delta.content}`),s.choices[0].delta.content):(a=(o=(n=s.choices)==null?void 0:n[0])==null?void 0:o.message)!=null&&a.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)},p=(s,t,r)=>{if(t==null||t(s),r){const e=b(s);e&&r(e)}},$=(s,t)=>s.error||s.message||`${t.status} ${t.statusText}`,P=(s,t)=>{const r=s==null?void 0:s.reduce((e,n)=>(e[n.index]=n,e),{});return t.forEach(e=>{r[e.index]?(e.attachments&&(r[e.index].attachments=(r[e.index].attachments||[]).concat(e.attachments)),e.content&&(r[e.index].content=(r[e.index].content||"")+e.content),e.name&&(r[e.index].name=(r[e.index].name||"")+e.name),e.status&&(r[e.index].status=e.status)):r[e.index]=e}),Object.values(r)},x=(s,t)=>{const r=structuredClone(s);return t.forEach(e=>{e.errorMessage&&(r.errorMessage=e.errorMessage),e.role&&(r.role=e.role),e.responseId&&(r.responseId=e.responseId),e.content&&(r.content=`${r.content||""}${e.content}`),e.custom_content&&(r.custom_content||(r.custom_content={}),e.custom_content.attachments&&(r.custom_content.attachments||(r.custom_content.attachments=[]),r.custom_content.attachments=r.custom_content.attachments.concat(e.custom_content.attachments)),e.custom_content.stages&&(r.custom_content.stages||(r.custom_content.stages=[]),r.custom_content.stages=P(r.custom_content.stages,e.custom_content.stages)),e.custom_content.state&&(r.custom_content.state=e.custom_content.state),e.custom_content.form_schema&&(r.custom_content.form_schema=e.custom_content.form_schema),e.custom_content.form_value&&(r.custom_content.form_value=e.custom_content.form_value))}),r},H={CHAT:"/api/chat"},V="application/json",D="Content-Type",A="Api-Key",L="X-CONVERSATION-ID",U=s=>(s==null?void 0:s.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/g,"").replace(/-/g," "))||"",C=(s,t,r)=>{const e={[D]:(t==null?void 0:t.contentType)||V};return t!=null&&t.jwt?e.Authorization=`Bearer ${t.jwt}`:s&&(e[A]=s),t!=null&&t.chatReference&&(e[L]=t.chatReference),{...e,...r}},j=s=>{const t={...s};return t[A]&&(t[A]=t[A].substring(0,8)+"...[REDACTED]"),t.Authorization&&(t.Authorization="Bearer [REDACTED]"),t},M=s=>({"Content-Type":`multipart/form-data; boundary=${s}`}),g=s=>{var n;const t=((n=s.name)==null?void 0:n.split("__"))||[],r=t.length>1?t.slice(1).join("__"):s.name;return{modelId:t[0],conversationName:r}},N=s=>{const t=Date.now(),r=U(s.name);return`${s.folderId}/${r}-${t}`},k=s=>({resourceTypes:[T.CONVERSATION],with:s}),E=async(s,t,r)=>await fetch(s,{method:r.method||"GET",headers:t,body:r!=null&&r.isFormData&&typeof(r==null?void 0:r.body)=="string"?r.body:JSON.stringify(r.body),signal:r==null?void 0:r.signal});function f(s){return s.split("/").map(t=>encodeURIComponent(t)).join("/")}function F(s){return s.split("/").map(t=>decodeURIComponent(t)).join("/")}class w{constructor(){this.decoder=new TextDecoder}async streamChat(t,r,e={},n){const{onMessage:o,onError:a,onComplete:c,signal:d}=e;try{const i=await this.initializeStreamRequest(t,r,d,n);await this.processStreamData(i,o),c==null||c()}catch(i){this.handleStreamError(i,a)}}async initializeStreamRequest(t,r,e,n){const o=C(void 0,{jwt:n}),a=await E(t,{Accept:"text/event-stream",...o},{method:"POST",body:r,signal:e});if(!a.ok){const c=await a.text();throw new Error(`HTTP ${a.status}: ${c}`)}if(!a.body)throw new Error("No response body");return a.body.getReader()}async processStreamData(t,r){let e="";try{for(;;){const{done:n,value:o}=await t.read();if(n){e.trim()&&this.parseSSEDataLine(e,r);break}const a=this.decoder.decode(o,{stream:!0});e+=a;const c=e.split(`
2
- `);e=c.pop()||"";for(const d of c)this.parseSSEDataLine(d,r)}}finally{t.releaseLock()}}handleStreamError(t,r){const e=t instanceof Error?t:new Error(String(t));throw r==null||r(e),e}parseSSEDataLine(t,r){const e=t.trim();if(!(!e||e.startsWith(":"))&&e.startsWith("data: ")){const n=e.slice(6);if(n==="[DONE]"){console.info("SSE: Stream completed");return}try{const o=JSON.parse(n);console.info(`SSE: Parsed data: ${o}`),r==null||r(o)}catch(o){console.error(`Failed to parse SSE data: ${n} ${o}`)}}}}const q=new w,K=async(s,t,r,e,n)=>{const{onMessage:o,onToken:a,onComplete:c,onError:d,model:i,signal:l}=r,y={conversationId:s,messages:t,model:i,custom_fields:n};await q.streamChat(H.CHAT,y,{onMessage:v=>p(v,o,a),onComplete:c,onError:d,signal:l},e)},h=s=>s instanceof Error&&s.message.includes("404"),S=s=>`/v1/conversations/${f(s)}`;class B{constructor(t){this.client=t}async getConversations(t,r,e){const n=`${r?e?`${r}/${e}`:`${r}`:""}`,o=`${u.CONVERSATIONS}/${n}`;try{return(await this.client.getRequest(o+"/?limit=1000&recursive=false",t).then(c=>c.items||[])).map(c=>{var l;const{conversationName:d,modelId:i}=g(c);return{id:((l=c.url)==null?void 0:l.replace("conversations/",""))||c.name,name:d,folderId:n,createdAt:c.createdAt,updatedAt:c.updatedAt,model:{id:i,name:i}}})}catch(a){if(h(a))return[];throw a}}async getConversation(t,r){try{return await this.client.getRequest(S(t),r)}catch(e){if(h(e))return null;throw e}}async getFile(t,r){try{const e=`${u.VERSION}/${f(t)}`;return await this.client.getRequest(e,r)}catch(e){if(h(e))return null;throw e}}async putOnboardingFile(t,r,e,n){try{const o=`${u.VERSION}/${f(r)}`,a="----NodeMultipartBoundary",d=[`--${a}`,`Content-Disposition: form-data; name="file"; filename="${t}"`,"Content-Type: application/json","",JSON.stringify(e),`--${a}--`,""].join(`\r
3
- `);return await this.client.request(o,n,{method:"PUT",body:d,headers:M(a),isFormData:!0})}catch(o){if(h(o))return null;throw o}}async getOnboardingFile(t,r){try{const e=`${u.VERSION}/${f(t)}`;return await this.client.getRequest(e,r)}catch(e){if(h(e))return null;throw e}}async getFileBlob(t,r){try{const e=`${u.VERSION}/${f(t)}`;return await this.client.requestBlob(e,r,{method:"GET"})}catch(e){if(h(e))return null;throw e}}async createConversation(t,r){const e=(t==null?void 0:t.id)||N(t),{name:n,folderId:o,model:a,messages:c,custom_fields:d}=t,i={id:e,name:n,folderId:o,model:a,messages:c||[],selectedAddons:t.selectedAddons||[],prompt:t.prompt||"",temperature:t.temperature||.7,createdAt:Date.now(),updatedAt:Date.now(),custom_fields:d};return await this.client.request(S(e),r,{method:"PUT",body:i}),{id:e,name:n,folderId:o,model:a,createdAt:i.createdAt,updatedAt:i.updatedAt}}async generateConversationLink(t,r){return await this.client.postRequest(u.SHARE_CONVERSATION,t,{body:r})}async getSharedConversations(t,r){return await this.client.postRequest(u.SHARE_CONVERSATION_LIST,t,{body:r})}async revokeSharedConversations(t,r){await this.client.postRequest(u.SHARE_CONVERSATION_REVOKE,t,{body:r})}async updateConversation(t,r,e){const n=await this.getConversation(t,e);if(!n)throw new Error(`Conversation with id ${t} not found`);const o={...n,...r,updatedAt:Date.now()};return await this.client.request(S(t),e,{method:"PUT",body:o})}async deleteConversation(t,r){t!=null&&t.isShared?await this.client.postRequest(u.SHARE_CONVERSATION_DISCARD,r,{body:{resources:[{url:t==null?void 0:t.url}]}}):await this.client.request(S(decodeURI(t==null?void 0:t.id)),r,{method:"DELETE"})}async streamChat(t,r){const e=t.model.id,n=encodeURIComponent(e),o=`${u.CHAT(n)}?api-version=${this.client.config.version}`,a={messages:t.messages,stream:!0,temperature:.7,max_tokens:4096,custom_fields:t.custom_fields};return await this.client.stream(o,r,{method:"POST",body:a,chatReference:t.conversationId})}async rateResponse(t,r,e){return await this.client.postRequest(u.RATE,e,{body:{responseId:t,rate:r}})}async renameConversation(t,r,e){return await this.client.postRequest(u.RENAME,e,{body:{sourceUrl:t,destinationUrl:r,overwrite:!0}})}}class z{constructor(t){this.config=t,console.info("DialApiClient initialized",{host:t.host||"NOT SET",hasApiKey:!!t.apiKey,version:t.version})}async getRequest(t,r,e){return this.request(t,r,{...e,method:"GET"})}async postRequest(t,r,e){return this.request(t,r,{...e,method:"POST"})}async requestBlob(t,r,e){const n=`${this.config.host}${t}`,o={...C(this.config.apiKey,{jwt:r,chatReference:e.chatReference}),...e.headers};try{return(await E(n,o,e)).blob()}catch(a){throw console.error("API Request Exception",{method:e.method,url:n,error:a instanceof Error?a.message:String(a)}),a}}async request(t,r,e){const n=Date.now(),o=`${this.config.host}${t}`,a={...C(this.config.apiKey,{jwt:r,chatReference:e.chatReference}),...e.headers};this.addInfoRequestLog("API Request",o,e,a);try{const c=await E(o,a,e),d=Date.now()-n;let i;const l=await c.text();try{i=l?JSON.parse(l):{}}catch{if(this.addErrorRequestParsing(o,e,c,d,l),!c.ok)throw new Error(`API request failed: ${c.status} ${c.statusText} - ${l.substring(0,100)}`);i={data:l}}if(!c.ok){this.addErrorRequestLog(o,e,c,d,i);const y=$(i,c);throw new Error(`API request failed: ${y}`)}return i}catch(c){const d=Date.now()-n;throw console.error("API Request Exception",{method:e.method,url:o,duration:`${d}ms`,error:c instanceof Error?c.message:String(c)}),c}}async stream(t,r,e){const n=`${this.config.host}${t}`,o=C(this.config.apiKey,{jwt:r,chatReference:e.chatReference},e.headers);this.addInfoRequestLog("Stream Request",n,e,o);const a=await E(n,o,e);if(!a.ok)throw console.error("Stream Request Failed",{method:e.method||"POST",url:n,status:a.status,statusText:a.statusText}),new Error(`Stream request failed: ${a.status} ${a.statusText}`);if(!a.body)throw new Error("No response body for stream");return a.body}addInfoRequestLog(t,r,e,n){const o={method:e.method||"GET",url:r,headers:j(n)};e.body&&(o.body=e.body),console.info(t,o)}addErrorRequestLog(t,r,e,n,o){console.error("API Request Failed",{method:r.method,url:t,status:e.status,statusText:e.statusText,duration:`${n}ms`,response:o})}addErrorRequestParsing(t,r,e,n,o){console.error("API Response Parse Error",{method:r.method,url:t,status:e.status,statusText:e.statusText,duration:`${n}ms`,responseText:o.substring(0,200),error:"Response is not valid JSON"})}}exports.AttachmentType=O;exports.ChatStreamSSEClient=w;exports.ConversationApi=B;exports.DIAL_API_ROUTES=u;exports.DialApiClient=z;exports.InvitationType=I;exports.ResourceTypes=T;exports.ShareTarget=_;exports.chatStreamSSEClient=q;exports.decodeApiUrl=F;exports.encodeApiUrl=f;exports.generateConversationId=N;exports.getErrorMessage=$;exports.getSharedConversationsRequest=k;exports.handleStreamMessage=p;exports.mergeMessages=x;exports.parseConversationName=g;exports.sendRequest=E;exports.streamChatResponse=K;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m="v1",R=`/${m}/ops/resource/share`,u={VERSION:`/${m}`,BUCKET:`/${m}/bucket`,CONVERSATIONS:`/${m}/metadata/conversations`,CONVERSATION_BY_ID:s=>`/${m}/metadata/conversations/${s}`,CHAT:s=>`/openai/deployments/${s}/chat/completions`,MODELS:"/openai/models",CONFIGURATION:s=>`/${m}/deployments/${s}/configuration`,SHARE_CONVERSATION:`${R}/create`,SHARE_CONVERSATION_ACCEPT:s=>`/${m}/invitations/${s}?accept=true`,SHARE_CONVERSATION_DETAILS:s=>`/${m}/invitations/${s}`,SHARE_CONVERSATION_LIST:`${R}/list`,SHARE_CONVERSATION_DISCARD:`${R}/discard`,SHARE_CONVERSATION_REVOKE:`${R}/revoke`,RATE:`/${m}/rate`,RENAME:`/${m}/ops/resource/move`};var O=(s=>(s.CONVERSATION="CONVERSATION",s))(O||{}),I=(s=>(s.ME="me",s.OTHERS="others",s))(I||{}),T=(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))(T||{}),p=(s=>(s.LINK="link",s))(p||{});const P=s=>{var t,r,e,n,o,a;return s.content?(console.info(`Using direct content format: ${s.content}`),s.content):(e=(r=(t=s.choices)==null?void 0:t[0])==null?void 0:r.delta)!=null&&e.content?(console.info(`Using OpenAI delta format: ${s.choices[0].delta.content}`),s.choices[0].delta.content):(a=(o=(n=s.choices)==null?void 0:n[0])==null?void 0:o.message)!=null&&a.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)},g=(s,t,r)=>{if(t==null||t(s),r){const e=P(s);e&&r(e)}},N=(s,t)=>s.error||s.message||`${t.status} ${t.statusText}`,x=(s,t)=>{const r=s==null?void 0:s.reduce((e,n)=>(e[n.index]=n,e),{});return t.forEach(e=>{r[e.index]?(e.attachments&&(r[e.index].attachments=(r[e.index].attachments||[]).concat(e.attachments)),e.content&&(r[e.index].content=(r[e.index].content||"")+e.content),e.name&&(r[e.index].name=(r[e.index].name||"")+e.name),e.status&&(r[e.index].status=e.status)):r[e.index]=e}),Object.values(r)},D=(s,t)=>{const r=structuredClone(s);return t.forEach(e=>{e.errorMessage&&(r.errorMessage=e.errorMessage),e.role&&(r.role=e.role),e.responseId&&(r.responseId=e.responseId),e.content&&(r.content=`${r.content||""}${e.content}`),e.custom_content&&(r.custom_content||(r.custom_content={}),e.custom_content.attachments&&(r.custom_content.attachments||(r.custom_content.attachments=[]),r.custom_content.attachments=r.custom_content.attachments.concat(e.custom_content.attachments)),e.custom_content.stages&&(r.custom_content.stages||(r.custom_content.stages=[]),r.custom_content.stages=x(r.custom_content.stages,e.custom_content.stages)),e.custom_content.state&&(r.custom_content.state=e.custom_content.state),e.custom_content.form_schema&&(r.custom_content.form_schema=e.custom_content.form_schema),e.custom_content.form_value&&(r.custom_content.form_value=e.custom_content.form_value))}),r},H={CHAT:"/api/chat"},V="application/json",L="Content-Type",A="Api-Key",U="X-CONVERSATION-ID",_="Ocp-Apim-Subscription-Key",j=s=>(s==null?void 0:s.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/g,"").replace(/-/g," "))||"",C=(s,t,r)=>{const e={[L]:(t==null?void 0:t.contentType)||V};return t!=null&&t.jwt?e.Authorization=`Bearer ${t.jwt}`:s&&(e[A]=s),t!=null&&t.chatReference&&(e[U]=t.chatReference),{...e,...r}},M=s=>{const t={...s};return t[A]&&(t[A]=t[A].substring(0,8)+"...[REDACTED]"),t.Authorization&&(t.Authorization="Bearer [REDACTED]"),t[_]&&(t[_]=t[_].substring(0,8)+"...[REDACTED]"),t},k=s=>({"Content-Type":`multipart/form-data; boundary=${s}`}),$=s=>{var n;const t=((n=s.name)==null?void 0:n.split("__"))||[],r=t.length>1?t.slice(1).join("__"):s.name;return{modelId:t[0],conversationName:r}},w=s=>{const t=Date.now(),r=j(s.name);return`${s.folderId}/${r}-${t}`},K=s=>({resourceTypes:[O.CONVERSATION],with:s}),f=async(s,t,r)=>await fetch(s,{method:r.method||"GET",headers:t,body:r!=null&&r.isFormData&&typeof(r==null?void 0:r.body)=="string"?r.body:JSON.stringify(r.body),signal:r==null?void 0:r.signal});function E(s){return s.split("/").map(t=>encodeURIComponent(t)).join("/")}function B(s){return s.split("/").map(t=>decodeURIComponent(t)).join("/")}class q{constructor(){this.decoder=new TextDecoder}async streamChat(t,r,e={},n){const{onMessage:o,onError:a,onComplete:c,signal:d}=e;try{const i=await this.initializeStreamRequest(t,r,d,n);await this.processStreamData(i,o),c==null||c()}catch(i){this.handleStreamError(i,a)}}async initializeStreamRequest(t,r,e,n){const o=C(void 0,{jwt:n}),a=await f(t,{Accept:"text/event-stream",...o},{method:"POST",body:r,signal:e});if(!a.ok){const c=await a.text();throw new Error(JSON.stringify({status:a.status,message:c}))}if(!a.body)throw new Error("No response body");return a.body.getReader()}async processStreamData(t,r){let e="";try{for(;;){const{done:n,value:o}=await t.read();if(n){e.trim()&&this.parseSSEDataLine(e,r);break}const a=this.decoder.decode(o,{stream:!0});e+=a;const c=e.split(`
2
+ `);e=c.pop()||"";for(const d of c)this.parseSSEDataLine(d,r)}}finally{t.releaseLock()}}handleStreamError(t,r){const e=t instanceof Error?t:new Error(String(t));throw r==null||r(e),e}parseSSEDataLine(t,r){const e=t.trim();if(!(!e||e.startsWith(":"))&&e.startsWith("data: ")){const n=e.slice(6);if(n==="[DONE]"){console.info("SSE: Stream completed");return}try{const o=JSON.parse(n);r==null||r(o)}catch(o){console.error(`Failed to parse SSE data: ${n} ${o}`)}}}}const b=new q,F=async(s,t,r,e,n)=>{const{onMessage:o,onToken:a,onComplete:c,onError:d,model:i,signal:l}=r,y={conversationId:s,messages:t,model:i,custom_fields:n};await b.streamChat(H.CHAT,y,{onMessage:v=>g(v,o,a),onComplete:c,onError:d,signal:l},e)},h=s=>s instanceof Error&&s.message.includes("404"),S=s=>`/v1/conversations/${E(s)}`;class J{constructor(t){this.client=t}async getConversations(t,r,e){const n=`${r?e?`${r}/${e}`:`${r}`:""}`,o=`${u.CONVERSATIONS}/${n}`;try{return(await this.client.getRequest(o+"/?limit=1000&recursive=false",t).then(c=>c.items||[])).map(c=>{var l;const{conversationName:d,modelId:i}=$(c);return{id:((l=c.url)==null?void 0:l.replace("conversations/",""))||c.name,name:d,folderId:n,createdAt:c.createdAt,updatedAt:c.updatedAt,model:{id:i,name:i}}})}catch(a){if(h(a))return[];throw a}}async getConversation(t,r){try{return await this.client.getRequest(S(t),r)}catch(e){if(h(e))return null;throw e}}async getFile(t,r){try{const e=`${u.VERSION}/${E(t)}`;return await this.client.getRequest(e,r)}catch(e){if(h(e))return null;throw e}}async putOnboardingFile(t,r,e,n){try{const o=`${u.VERSION}/${E(r)}`,a="----NodeMultipartBoundary",d=[`--${a}`,`Content-Disposition: form-data; name="file"; filename="${t}"`,"Content-Type: application/json","",JSON.stringify(e),`--${a}--`,""].join(`\r
3
+ `);return await this.client.request(o,n,{method:"PUT",body:d,headers:k(a),isFormData:!0})}catch(o){if(h(o))return null;throw o}}async getOnboardingFile(t,r){try{const e=`${u.VERSION}/${E(t)}`;return await this.client.getRequest(e,r)}catch(e){if(h(e))return null;throw e}}async getFileBlob(t,r){try{const e=`${u.VERSION}/${E(t)}`;return await this.client.requestBlob(e,r,{method:"GET"})}catch(e){if(h(e))return null;throw e}}async createConversation(t,r){const e=(t==null?void 0:t.id)||w(t),{name:n,folderId:o,model:a,messages:c,custom_fields:d}=t,i={id:e,name:n,folderId:o,model:a,messages:c||[],selectedAddons:t.selectedAddons||[],prompt:t.prompt||"",temperature:t.temperature||.7,createdAt:Date.now(),updatedAt:Date.now(),custom_fields:d};return await this.client.request(S(e),r,{method:"PUT",body:i}),{id:e,name:n,folderId:o,model:a,createdAt:i.createdAt,updatedAt:i.updatedAt}}async generateConversationLink(t,r){return await this.client.postRequest(u.SHARE_CONVERSATION,t,{body:r})}async getSharedConversations(t,r){return await this.client.postRequest(u.SHARE_CONVERSATION_LIST,t,{body:r})}async revokeSharedConversations(t,r){await this.client.postRequest(u.SHARE_CONVERSATION_REVOKE,t,{body:r})}async updateConversation(t,r,e){const n=await this.getConversation(t,e);if(!n)throw new Error(`Conversation with id ${t} not found`);const o={...n,...r,updatedAt:Date.now()};return await this.client.request(S(t),e,{method:"PUT",body:o})}async deleteConversation(t,r){t!=null&&t.isShared?await this.client.postRequest(u.SHARE_CONVERSATION_DISCARD,r,{body:{resources:[{url:t==null?void 0:t.url}]}}):await this.client.request(S(decodeURI(t==null?void 0:t.id)),r,{method:"DELETE"})}async streamChat(t,r){const e=t.model.id,n=encodeURIComponent(e),o=`${u.CHAT(n)}?api-version=${this.client.config.version}`,a={messages:t.messages,stream:!0,temperature:.7,max_tokens:4096,custom_fields:t.custom_fields};return await this.client.stream(o,r,{method:"POST",body:a,chatReference:t.conversationId})}async rateResponse(t,r,e){return await this.client.postRequest(u.RATE,e,{body:{responseId:t,rate:r}})}async renameConversation(t,r,e){return await this.client.postRequest(u.RENAME,e,{body:{sourceUrl:t,destinationUrl:r,overwrite:!0}})}}class z{constructor(t){this.config=t,console.info("DialApiClient initialized",{host:t.host||"NOT SET",hasApiKey:!!t.apiKey,version:t.version})}async getRequest(t,r,e){return this.request(t,r,{...e,method:"GET"})}async postRequest(t,r,e){return this.request(t,r,{...e,method:"POST"})}async requestBlob(t,r,e){const n=`${this.config.host}${t}`,o={...C(this.config.apiKey,{jwt:r,chatReference:e.chatReference}),...e.headers};try{return(await f(n,o,e)).blob()}catch(a){throw console.error("API Request Exception",{method:e.method,url:n,error:a instanceof Error?a.message:String(a)}),a}}async request(t,r,e){const n=Date.now(),o=`${this.config.host}${t}`,a={...C(this.config.apiKey,{jwt:r,chatReference:e.chatReference}),...e.headers};this.addInfoRequestLog("API Request",o,e,a);try{const c=await f(o,a,e),d=Date.now()-n;let i;const l=await c.text();try{i=l?JSON.parse(l):{}}catch{if(this.addErrorRequestParsing(o,e,c,d,l),!c.ok)throw new Error(`API request failed: ${c.status} ${c.statusText} - ${l.substring(0,100)}`);i={data:l}}if(!c.ok){this.addErrorRequestLog(o,e,c,d,i);const y=N(i,c);throw new Error(`API request failed: ${y}`)}return i}catch(c){const d=Date.now()-n;throw console.error("API Request Exception",{method:e.method,url:o,duration:`${d}ms`,error:c instanceof Error?c.message:String(c)}),c}}async stream(t,r,e){const n=`${this.config.host}${t}`,o=C(this.config.apiKey,{jwt:r,chatReference:e.chatReference},e.headers);this.addInfoRequestLog("Stream Request",n,e,o);const a=await f(n,o,e);if(!a.ok)throw console.error("Stream Request Failed",{method:e.method||"POST",url:n,status:a.status,statusText:a.statusText}),new Error(`Stream request failed: ${a.status} ${a.statusText}`);if(!a.body)throw new Error("No response body for stream");return a.body}addInfoRequestLog(t,r,e,n){const o={method:e.method||"GET",url:r,headers:M(n)};e.body&&(o.body=e.body),console.info(t,o)}addErrorRequestLog(t,r,e,n,o){console.error("API Request Failed",{method:r.method,url:t,status:e.status,statusText:e.statusText,duration:`${n}ms`,response:o})}addErrorRequestParsing(t,r,e,n,o){console.error("API Response Parse Error",{method:r.method,url:t,status:e.status,statusText:e.statusText,duration:`${n}ms`,responseText:o.substring(0,200),error:"Response is not valid JSON"})}}exports.AttachmentType=T;exports.ChatStreamSSEClient=q;exports.ConversationApi=J;exports.DIAL_API_ROUTES=u;exports.DialApiClient=z;exports.InvitationType=p;exports.ResourceTypes=O;exports.ShareTarget=I;exports.chatStreamSSEClient=b;exports.decodeApiUrl=B;exports.encodeApiUrl=E;exports.generateConversationId=w;exports.getErrorMessage=N;exports.getSharedConversationsRequest=K;exports.handleStreamMessage=g;exports.mergeMessages=D;exports.parseConversationName=$;exports.sendRequest=f;exports.streamChatResponse=F;
package/index.mjs CHANGED
@@ -15,18 +15,18 @@ const E = "/v1/ops/resource/share", u = {
15
15
  RATE: "/v1/rate",
16
16
  RENAME: "/v1/ops/resource/move"
17
17
  };
18
- var I = /* @__PURE__ */ ((s) => (s.CONVERSATION = "CONVERSATION", s))(I || {}), _ = /* @__PURE__ */ ((s) => (s.ME = "me", s.OTHERS = "others", s))(_ || {}), 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))(y || {}), C = /* @__PURE__ */ ((s) => (s.LINK = "link", s))(C || {});
19
- const T = (s) => {
18
+ var _ = /* @__PURE__ */ ((s) => (s.CONVERSATION = "CONVERSATION", s))(_ || {}), y = /* @__PURE__ */ ((s) => (s.ME = "me", s.OTHERS = "others", s))(y || {}), C = /* @__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))(C || {}), T = /* @__PURE__ */ ((s) => (s.LINK = "link", s))(T || {});
19
+ const $ = (s) => {
20
20
  var t, r, e, n, o, c;
21
21
  return s.content ? (console.info(`Using direct content format: ${s.content}`), s.content) : (e = (r = (t = s.choices) == null ? void 0 : t[0]) == null ? void 0 : r.delta) != null && e.content ? (console.info(`Using OpenAI delta format: ${s.choices[0].delta.content}`), s.choices[0].delta.content) : (c = (o = (n = s.choices) == null ? void 0 : n[0]) == null ? void 0 : o.message) != null && c.content ? (console.info(
22
22
  `Using complete message format: ${s.choices[0].message.content}`
23
23
  ), s.choices[0].message.content) : (console.info("Unknown SSE data format:", s), null);
24
- }, $ = (s, t, r) => {
24
+ }, p = (s, t, r) => {
25
25
  if (t == null || t(s), r) {
26
- const e = T(s);
26
+ const e = $(s);
27
27
  e && r(e);
28
28
  }
29
- }, p = (s, t) => s.error || s.message || `${t.status} ${t.statusText}`, g = (s, t) => {
29
+ }, g = (s, t) => s.error || s.message || `${t.status} ${t.statusText}`, w = (s, t) => {
30
30
  const r = s == null ? void 0 : s.reduce(
31
31
  (e, n) => (e[n.index] = n, e),
32
32
  {}
@@ -34,36 +34,36 @@ const T = (s) => {
34
34
  return t.forEach((e) => {
35
35
  r[e.index] ? (e.attachments && (r[e.index].attachments = (r[e.index].attachments || []).concat(e.attachments)), e.content && (r[e.index].content = (r[e.index].content || "") + e.content), e.name && (r[e.index].name = (r[e.index].name || "") + e.name), e.status && (r[e.index].status = e.status)) : r[e.index] = e;
36
36
  }), Object.values(r);
37
- }, j = (s, t) => {
37
+ }, k = (s, t) => {
38
38
  const r = structuredClone(s);
39
39
  return t.forEach((e) => {
40
40
  e.errorMessage && (r.errorMessage = e.errorMessage), e.role && (r.role = e.role), e.responseId && (r.responseId = e.responseId), e.content && (r.content = `${r.content || ""}${e.content}`), e.custom_content && (r.custom_content || (r.custom_content = {}), e.custom_content.attachments && (r.custom_content.attachments || (r.custom_content.attachments = []), r.custom_content.attachments = r.custom_content.attachments.concat(
41
41
  e.custom_content.attachments
42
- )), e.custom_content.stages && (r.custom_content.stages || (r.custom_content.stages = []), r.custom_content.stages = g(
42
+ )), e.custom_content.stages && (r.custom_content.stages || (r.custom_content.stages = []), r.custom_content.stages = w(
43
43
  r.custom_content.stages,
44
44
  e.custom_content.stages
45
45
  )), e.custom_content.state && (r.custom_content.state = e.custom_content.state), e.custom_content.form_schema && (r.custom_content.form_schema = e.custom_content.form_schema), e.custom_content.form_value && (r.custom_content.form_value = e.custom_content.form_value));
46
46
  }), r;
47
- }, w = {
47
+ }, q = {
48
48
  CHAT: "/api/chat"
49
- }, q = "application/json", b = "Content-Type", f = "Api-Key", V = "X-CONVERSATION-ID", v = (s) => (s == null ? void 0 : s.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-+|-+$/g, "").replace(/-/g, " ")) || "", S = (s, t, r) => {
49
+ }, b = "application/json", V = "Content-Type", f = "Api-Key", v = "X-CONVERSATION-ID", I = "Ocp-Apim-Subscription-Key", x = (s) => (s == null ? void 0 : s.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-+|-+$/g, "").replace(/-/g, " ")) || "", S = (s, t, r) => {
50
50
  const e = {
51
- [b]: (t == null ? void 0 : t.contentType) || q
51
+ [V]: (t == null ? void 0 : t.contentType) || b
52
52
  };
53
- return t != null && t.jwt ? e.Authorization = `Bearer ${t.jwt}` : s && (e[f] = s), t != null && t.chatReference && (e[V] = t.chatReference), { ...e, ...r };
54
- }, x = (s) => {
53
+ return t != null && t.jwt ? e.Authorization = `Bearer ${t.jwt}` : s && (e[f] = s), t != null && t.chatReference && (e[v] = t.chatReference), { ...e, ...r };
54
+ }, P = (s) => {
55
55
  const t = { ...s };
56
- return t[f] && (t[f] = t[f].substring(0, 8) + "...[REDACTED]"), t.Authorization && (t.Authorization = "Bearer [REDACTED]"), t;
57
- }, P = (s) => ({
56
+ return t[f] && (t[f] = t[f].substring(0, 8) + "...[REDACTED]"), t.Authorization && (t.Authorization = "Bearer [REDACTED]"), t[I] && (t[I] = t[I].substring(0, 8) + "...[REDACTED]"), t;
57
+ }, H = (s) => ({
58
58
  "Content-Type": `multipart/form-data; boundary=${s}`
59
- }), H = (s) => {
59
+ }), D = (s) => {
60
60
  var n;
61
61
  const t = ((n = s.name) == null ? void 0 : n.split("__")) || [], r = t.length > 1 ? t.slice(1).join("__") : s.name;
62
62
  return { modelId: t[0], conversationName: r };
63
63
  }, L = (s) => {
64
- const t = Date.now(), r = v(s.name);
64
+ const t = Date.now(), r = x(s.name);
65
65
  return `${s.folderId}/${r}-${t}`;
66
- }, k = (s) => ({ resourceTypes: [I.CONVERSATION], with: s }), O = async (s, t, r) => await fetch(s, {
66
+ }, K = (s) => ({ resourceTypes: [_.CONVERSATION], with: s }), O = async (s, t, r) => await fetch(s, {
67
67
  method: r.method || "GET",
68
68
  headers: t,
69
69
  body: r != null && r.isFormData && typeof (r == null ? void 0 : r.body) == "string" ? r.body : JSON.stringify(r.body),
@@ -72,10 +72,10 @@ const T = (s) => {
72
72
  function h(s) {
73
73
  return s.split("/").map((t) => encodeURIComponent(t)).join("/");
74
74
  }
75
- function F(s) {
75
+ function B(s) {
76
76
  return s.split("/").map((t) => decodeURIComponent(t)).join("/");
77
77
  }
78
- class D {
78
+ class U {
79
79
  constructor() {
80
80
  this.decoder = new TextDecoder();
81
81
  }
@@ -110,7 +110,9 @@ class D {
110
110
  );
111
111
  if (!c.ok) {
112
112
  const a = await c.text();
113
- throw new Error(`HTTP ${c.status}: ${a}`);
113
+ throw new Error(
114
+ JSON.stringify({ status: c.status, message: a })
115
+ );
114
116
  }
115
117
  if (!c.body)
116
118
  throw new Error("No response body");
@@ -151,33 +153,33 @@ class D {
151
153
  }
152
154
  try {
153
155
  const o = JSON.parse(n);
154
- console.info(`SSE: Parsed data: ${o}`), r == null || r(o);
156
+ r == null || r(o);
155
157
  } catch (o) {
156
158
  console.error(`Failed to parse SSE data: ${n} ${o}`);
157
159
  }
158
160
  }
159
161
  }
160
162
  }
161
- const U = new D(), K = async (s, t, r, e, n) => {
162
- const { onMessage: o, onToken: c, onComplete: a, onError: d, model: i, signal: l } = r, A = {
163
+ const j = new U(), F = async (s, t, r, e, n) => {
164
+ const { onMessage: o, onToken: c, onComplete: a, onError: d, model: i, signal: m } = r, A = {
163
165
  conversationId: s,
164
166
  messages: t,
165
167
  model: i,
166
168
  custom_fields: n
167
169
  };
168
- await U.streamChat(
169
- w.CHAT,
170
+ await j.streamChat(
171
+ q.CHAT,
170
172
  A,
171
173
  {
172
- onMessage: (N) => $(N, o, c),
174
+ onMessage: (N) => p(N, o, c),
173
175
  onComplete: a,
174
176
  onError: d,
175
- signal: l
177
+ signal: m
176
178
  },
177
179
  e
178
180
  );
179
- }, m = (s) => s instanceof Error && s.message.includes("404"), R = (s) => `/v1/conversations/${h(s)}`;
180
- class B {
181
+ }, l = (s) => s instanceof Error && s.message.includes("404"), R = (s) => `/v1/conversations/${h(s)}`;
182
+ class M {
181
183
  constructor(t) {
182
184
  this.client = t;
183
185
  }
@@ -185,10 +187,10 @@ class B {
185
187
  const n = `${r ? e ? `${r}/${e}` : `${r}` : ""}`, o = `${u.CONVERSATIONS}/${n}`;
186
188
  try {
187
189
  return (await this.client.getRequest(o + "/?limit=1000&recursive=false", t).then((a) => a.items || [])).map((a) => {
188
- var l;
189
- const { conversationName: d, modelId: i } = H(a);
190
+ var m;
191
+ const { conversationName: d, modelId: i } = D(a);
190
192
  return {
191
- id: ((l = a.url) == null ? void 0 : l.replace("conversations/", "")) || a.name,
193
+ id: ((m = a.url) == null ? void 0 : m.replace("conversations/", "")) || a.name,
192
194
  name: d,
193
195
  folderId: n,
194
196
  createdAt: a.createdAt,
@@ -197,7 +199,7 @@ class B {
197
199
  };
198
200
  });
199
201
  } catch (c) {
200
- if (m(c))
202
+ if (l(c))
201
203
  return [];
202
204
  throw c;
203
205
  }
@@ -209,7 +211,7 @@ class B {
209
211
  r
210
212
  );
211
213
  } catch (e) {
212
- if (m(e))
214
+ if (l(e))
213
215
  return null;
214
216
  throw e;
215
217
  }
@@ -219,7 +221,7 @@ class B {
219
221
  const e = `${u.VERSION}/${h(t)}`;
220
222
  return await this.client.getRequest(e, r);
221
223
  } catch (e) {
222
- if (m(e))
224
+ if (l(e))
223
225
  return null;
224
226
  throw e;
225
227
  }
@@ -239,11 +241,11 @@ class B {
239
241
  return await this.client.request(o, n, {
240
242
  method: "PUT",
241
243
  body: d,
242
- headers: P(c),
244
+ headers: H(c),
243
245
  isFormData: !0
244
246
  });
245
247
  } catch (o) {
246
- if (m(o))
248
+ if (l(o))
247
249
  return null;
248
250
  throw o;
249
251
  }
@@ -253,7 +255,7 @@ class B {
253
255
  const e = `${u.VERSION}/${h(t)}`;
254
256
  return await this.client.getRequest(e, r);
255
257
  } catch (e) {
256
- if (m(e))
258
+ if (l(e))
257
259
  return null;
258
260
  throw e;
259
261
  }
@@ -263,7 +265,7 @@ class B {
263
265
  const e = `${u.VERSION}/${h(t)}`;
264
266
  return await this.client.requestBlob(e, r, { method: "GET" });
265
267
  } catch (e) {
266
- if (m(e))
268
+ if (l(e))
267
269
  return null;
268
270
  throw e;
269
271
  }
@@ -396,7 +398,7 @@ class B {
396
398
  });
397
399
  }
398
400
  }
399
- class M {
401
+ class J {
400
402
  constructor(t) {
401
403
  this.config = t, console.info("DialApiClient initialized", {
402
404
  host: t.host || "NOT SET",
@@ -440,25 +442,25 @@ class M {
440
442
  try {
441
443
  const a = await O(o, c, e), d = Date.now() - n;
442
444
  let i;
443
- const l = await a.text();
445
+ const m = await a.text();
444
446
  try {
445
- i = l ? JSON.parse(l) : {};
447
+ i = m ? JSON.parse(m) : {};
446
448
  } catch {
447
449
  if (this.addErrorRequestParsing(
448
450
  o,
449
451
  e,
450
452
  a,
451
453
  d,
452
- l
454
+ m
453
455
  ), !a.ok)
454
456
  throw new Error(
455
- `API request failed: ${a.status} ${a.statusText} - ${l.substring(0, 100)}`
457
+ `API request failed: ${a.status} ${a.statusText} - ${m.substring(0, 100)}`
456
458
  );
457
- i = { data: l };
459
+ i = { data: m };
458
460
  }
459
461
  if (!a.ok) {
460
462
  this.addErrorRequestLog(o, e, a, d, i);
461
- const A = p(i, a);
463
+ const A = g(i, a);
462
464
  throw new Error(`API request failed: ${A}`);
463
465
  }
464
466
  return i;
@@ -500,7 +502,7 @@ class M {
500
502
  const o = {
501
503
  method: e.method || "GET",
502
504
  url: r,
503
- headers: x(n)
505
+ headers: P(n)
504
506
  };
505
507
  e.body && (o.body = e.body), console.info(t, o);
506
508
  }
@@ -528,23 +530,23 @@ class M {
528
530
  }
529
531
  }
530
532
  export {
531
- y as AttachmentType,
532
- D as ChatStreamSSEClient,
533
- B as ConversationApi,
533
+ C as AttachmentType,
534
+ U as ChatStreamSSEClient,
535
+ M as ConversationApi,
534
536
  u as DIAL_API_ROUTES,
535
- M as DialApiClient,
536
- C as InvitationType,
537
- I as ResourceTypes,
538
- _ as ShareTarget,
539
- U as chatStreamSSEClient,
540
- F as decodeApiUrl,
537
+ J as DialApiClient,
538
+ T as InvitationType,
539
+ _ as ResourceTypes,
540
+ y as ShareTarget,
541
+ j as chatStreamSSEClient,
542
+ B as decodeApiUrl,
541
543
  h as encodeApiUrl,
542
544
  L as generateConversationId,
543
- p as getErrorMessage,
544
- k as getSharedConversationsRequest,
545
- $ as handleStreamMessage,
546
- j as mergeMessages,
547
- H as parseConversationName,
545
+ g as getErrorMessage,
546
+ K as getSharedConversationsRequest,
547
+ p as handleStreamMessage,
548
+ k as mergeMessages,
549
+ D as parseConversationName,
548
550
  O as sendRequest,
549
- K as streamChatResponse
551
+ F as streamChatResponse
550
552
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epam/statgpt-dial-toolkit",
3
- "version": "0.2.0-rc.0",
3
+ "version": "0.2.0-rc.10",
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.2.0-rc.0",
17
+ "@epam/statgpt-shared-toolkit": "0.2.0-rc.10",
18
18
  "@epam/ai-dial-shared": "^0.34.0"
19
19
  }
20
20
  }