@nameless26/widget 0.1.0 → 0.1.1

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/dist/index.cjs.js CHANGED
@@ -1,22 +1,22 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react");function R(t){return`nexus_widget_session_${t}`}function H(t){const r=sessionStorage.getItem(R(t));if(r)return r;const n=crypto.randomUUID();return sessionStorage.setItem(R(t),n),n}async function*W(t,r){const n=new TextDecoder;let u="";try{for(;;){if(r.aborted)return;const{done:a,value:x}=await t.read();if(a)return;u+=n.decode(x,{stream:!0});const c=u.split(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("react");function I(t){return`nexus_widget_session_${t}`}function H(t){const n=sessionStorage.getItem(I(t));if(n)return n;const s=crypto.randomUUID();return sessionStorage.setItem(I(t),s),s}async function*_(t,n){const s=new TextDecoder;let l="";try{for(;;){if(n.aborted)return;const{done:d,value:o}=await t.read();if(d)return;l+=s.decode(o,{stream:!0});const u=l.split(`
2
2
 
3
- `);u=c.pop()??"";for(const y of c)for(const b of y.split(`
4
- `)){if(!b.startsWith("data: "))continue;const d=b.slice(6).trim();try{yield JSON.parse(d)}catch{}}}}finally{t.releaseLock()}}function D({agentId:t,baseUrl:r="http://localhost:8000/api",endUserId:n}){const[u,a]=o.useState([]),[x,c]=o.useState(!1),[y,b]=o.useState(!0),[d,h]=o.useState(null),[v,p]=o.useState(null),[m,k]=o.useState(null),s=o.useRef(H(t)),w=o.useRef(null),T=o.useCallback(async()=>{var N;(N=w.current)==null||N.abort(),b(!0),h(null);const i=new AbortController;w.current=i;try{const f=await fetch(`${r}/widget/session`,{method:"POST",signal:i.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:t,sessionId:s.current})});if(!f.ok)throw new Error(`HTTP ${f.status}`);const j=await f.json();k(j.token);const S=await fetch(`${r}/chat/history`,{method:"POST",signal:i.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${j.token}`},body:JSON.stringify({agentId:t,sessionId:s.current})});if(!S.ok)throw new Error(`HTTP ${S.status}`);const l=await S.json();a(l.messages??[]),p(l.conversationId??null)}catch(f){(f==null?void 0:f.name)!=="AbortError"&&h("Unable to initialize widget session.")}finally{b(!1)}},[t]);o.useEffect(()=>(T(),()=>{var i;(i=w.current)==null||i.abort()}),[T]);const O=o.useCallback(()=>{var i;(i=w.current)==null||i.abort(),c(!1)},[]),P=o.useCallback(()=>{var i;(i=w.current)==null||i.abort(),a([]),p(null),h(null),c(!1),s.current=crypto.randomUUID(),k(null),T()},[T]),E=o.useCallback(async i=>{var S;if(!i.trim()||x||!m)return;(S=w.current)==null||S.abort();const N=new AbortController;w.current=N,h(null);const f=`u_${Date.now()}`,j=`a_${Date.now()}`;a(l=>[...l,{id:f,role:"user",content:i.trim()}]),c(!0);try{const l=await fetch(`${r}/chat`,{method:"POST",signal:N.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${m}`},body:JSON.stringify({agent_id:t,message:i.trim(),session_id:s.current,end_user_id:n})});if(!l.ok||!l.body)throw new Error(`HTTP ${l.status}`);a(g=>[...g,{id:j,role:"assistant",content:""}]);const $=l.body.getReader();for await(const g of W($,N.signal))switch(g.type){case"start":p(g.conversationId);break;case"token":a(I=>I.map(C=>C.id===j?{...C,content:C.content+g.content}:C));break;case"done":break;case"error":h(g.message),a(I=>I.filter(C=>C.id!==j));break}}catch(l){if((l==null?void 0:l.name)==="AbortError")return;h("Something went wrong. Please try again."),a($=>$.filter(g=>g.id!==f&&g.id!==j))}finally{c(!1)}},[t,n,x,m]);return{messages:u,isLoading:x,historyLoading:y,error:d,conversationId:v,send:E,reset:P,cancel:O}}function _({color:t}){return e.jsx("div",{className:`flex items-end gap-1 px-3 py-2.5 rounded-2xl rounded-bl-sm w-fit\r
5
- bg-[rgba(255,255,255,0.06)]`,children:[0,1,2].map(r=>e.jsx("span",{style:{width:6,height:6,borderRadius:"50%",background:t,opacity:.6,animation:`nexusBounce 1.2s ease-in-out ${r*.2}s infinite`}},r))})}function z({msg:t,primaryColor:r}){const n=t.role==="user";return e.jsx("div",{className:`flex ${n?"justify-end":"justify-start"}`,children:e.jsx("div",{style:n?{background:r}:void 0,className:`max-w-[82%] px-3 py-2.5 rounded-2xl text-sm leading-relaxed
6
- ${n?"text-white rounded-br-sm":"bg-[rgba(255,255,255,0.06)] text-[rgba(255,255,255,0.8)] rounded-bl-sm"}`,children:t.content})})}function B({agentName:t,messages:r,isLoading:n,error:u,primaryColor:a,welcomeMessage:x,onSend:c,onReset:y,onClose:b}){const[d,h]=o.useState(""),v=o.useRef(null),p=o.useRef(null);o.useEffect(()=>{var s;(s=v.current)==null||s.scrollIntoView({behavior:"smooth"})},[r,n]),o.useEffect(()=>{var s;(s=p.current)==null||s.focus()},[]);const m=()=>{!d.trim()||n||(c(d),h(""))},k=s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),m())};return e.jsxs(e.Fragment,{children:[e.jsx("style",{children:`
3
+ `);l=u.pop()??"";for(const h of u)for(const g of h.split(`
4
+ `)){if(!g.startsWith("data: "))continue;const i=g.slice(6).trim();try{yield JSON.parse(i)}catch{}}}}finally{t.releaseLock()}}function D({agentId:t,baseUrl:n,agentCoreUrl:s,endUserId:l}){const[d,o]=r.useState([]),[u,h]=r.useState(!1),[g,i]=r.useState(!0),[v,f]=r.useState(null),[k,y]=r.useState(null),[p,a]=r.useState(null),N=r.useRef(H(t)),w=r.useRef(null),T=r.useCallback(async()=>{w.current?.abort(),i(!0),f(null);const j=new AbortController;w.current=j;try{const x=await fetch(`${n}/widget/session`,{method:"POST",signal:j.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:t,sessionId:N.current})});if(!x.ok)throw new Error(`HTTP ${x.status}`);const C=await x.json();a(C.token);const m=await fetch(`${n}/chat/history`,{method:"POST",signal:j.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${C.token}`},body:JSON.stringify({agentId:t,sessionId:N.current})});if(!m.ok)throw new Error(`HTTP ${m.status}`);const c=await m.json();o(c.messages??[]),y(c.conversationId??null)}catch(x){x?.name!=="AbortError"&&f("Unable to initialize widget session.")}finally{i(!1)}},[t]);r.useEffect(()=>(T(),()=>{w.current?.abort()}),[T]);const E=r.useCallback(()=>{w.current?.abort(),h(!1)},[]),O=r.useCallback(()=>{w.current?.abort(),o([]),y(null),f(null),h(!1),N.current=crypto.randomUUID(),a(null),T()},[T]),P=r.useCallback(async j=>{if(!j.trim()||u||!p)return;w.current?.abort();const x=new AbortController;w.current=x,f(null);const C=`u_${Date.now()}`,m=`a_${Date.now()}`;o(c=>[...c,{id:C,role:"user",content:j.trim()}]),h(!0);try{const c=await fetch(`${s}/chat`,{method:"POST",signal:x.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${p}`},body:JSON.stringify({agent_id:t,message:j.trim(),session_id:N.current,end_user_id:l})});if(!c.ok||!c.body)throw new Error(`HTTP ${c.status}`);o(b=>[...b,{id:m,role:"assistant",content:""}]);const $=c.body.getReader();for await(const b of _($,x.signal))switch(b.type){case"start":y(b.conversationId);break;case"token":o(R=>R.map(S=>S.id===m?{...S,content:S.content+b.content}:S));break;case"done":break;case"error":f(b.message),o(R=>R.filter(S=>S.id!==m));break}}catch(c){if(c?.name==="AbortError")return;f("Something went wrong. Please try again."),o($=>$.filter(b=>b.id!==C&&b.id!==m))}finally{h(!1)}},[t,l,u,p]);return{messages:d,isLoading:u,historyLoading:g,error:v,conversationId:k,send:P,reset:O,cancel:E}}function B({color:t}){return e.jsx("div",{className:`flex items-end gap-1 px-3 py-2.5 rounded-2xl rounded-bl-sm w-fit\r
5
+ bg-[rgba(255,255,255,0.06)]`,children:[0,1,2].map(n=>e.jsx("span",{style:{width:6,height:6,borderRadius:"50%",background:t,opacity:.6,animation:`nexusBounce 1.2s ease-in-out ${n*.2}s infinite`}},n))})}function W({msg:t,primaryColor:n}){const s=t.role==="user";return e.jsx("div",{className:`flex ${s?"justify-end":"justify-start"}`,children:e.jsx("div",{style:s?{background:n}:void 0,className:`max-w-[82%] px-3 py-2.5 rounded-2xl text-sm leading-relaxed
6
+ ${s?"text-white rounded-br-sm":"bg-[rgba(255,255,255,0.06)] text-[rgba(255,255,255,0.8)] rounded-bl-sm"}`,children:t.content})})}function z({agentName:t,messages:n,isLoading:s,error:l,primaryColor:d,welcomeMessage:o,onSend:u,onReset:h,onClose:g}){const[i,v]=r.useState(""),f=r.useRef(null),k=r.useRef(null);r.useEffect(()=>{f.current?.scrollIntoView({behavior:"smooth"})},[n,s]),r.useEffect(()=>{k.current?.focus()},[]);const y=()=>{!i.trim()||s||(u(i),v(""))},p=a=>{a.key==="Enter"&&!a.shiftKey&&(a.preventDefault(),y())};return e.jsxs(e.Fragment,{children:[e.jsx("style",{children:`
7
7
  @keyframes nexusBounce {
8
8
  0%, 80%, 100% { transform: translateY(0); }
9
9
  40% { transform: translateY(-5px); }
10
10
  }
11
11
  `}),e.jsxs("div",{style:{fontFamily:"system-ui, -apple-system, sans-serif"},className:`flex flex-col overflow-hidden rounded-2xl shadow-2xl\r
12
- border border-[rgba(255,255,255,0.08)]`,role:"dialog","aria-label":`${t} chat`,children:[e.jsxs("div",{style:{background:a},className:"flex items-center justify-between px-4 py-3 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"w-2 h-2 rounded-full bg-white/40"}),e.jsx("span",{className:"text-white text-sm font-medium",children:t})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("button",{onClick:y,"aria-label":"Start new conversation",className:`p-1.5 rounded-full text-white/60 hover:text-white\r
13
- hover:bg-white/15 transition-colors`,children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[e.jsx("path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}),e.jsx("path",{d:"M3 3v5h5"})]})}),e.jsx("button",{onClick:b,"aria-label":"Close chat",className:`p-1.5 rounded-full text-white/60 hover:text-white\r
14
- hover:bg-white/15 transition-colors`,children:e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:e.jsx("path",{d:"M18 6 6 18M6 6l12 12"})})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-[#0d0d1a]",style:{minHeight:0},children:[r.length===0&&e.jsx("div",{className:"flex justify-start",children:e.jsx("div",{className:`max-w-[82%] px-3 py-2.5 rounded-2xl rounded-bl-sm\r
12
+ border border-[rgba(255,255,255,0.08)]`,role:"dialog","aria-label":`${t} chat`,children:[e.jsxs("div",{style:{background:d},className:"flex items-center justify-between px-4 py-3 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"w-2 h-2 rounded-full bg-white/40"}),e.jsx("span",{className:"text-white text-sm font-medium",children:t})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("button",{onClick:h,"aria-label":"Start new conversation",className:`p-1.5 rounded-full text-white/60 hover:text-white\r
13
+ hover:bg-white/15 transition-colors`,children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[e.jsx("path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}),e.jsx("path",{d:"M3 3v5h5"})]})}),e.jsx("button",{onClick:g,"aria-label":"Close chat",className:`p-1.5 rounded-full text-white/60 hover:text-white\r
14
+ hover:bg-white/15 transition-colors`,children:e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:e.jsx("path",{d:"M18 6 6 18M6 6l12 12"})})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-[#0d0d1a]",style:{minHeight:0},children:[n.length===0&&e.jsx("div",{className:"flex justify-start",children:e.jsx("div",{className:`max-w-[82%] px-3 py-2.5 rounded-2xl rounded-bl-sm\r
15
15
  bg-[rgba(255,255,255,0.06)] text-sm\r
16
- text-[rgba(255,255,255,0.8)] leading-relaxed`,children:x})}),r.map(s=>e.jsx(z,{msg:s,primaryColor:a},s.id)),n&&e.jsx("div",{className:"flex justify-start",children:e.jsx(_,{color:a})}),u&&e.jsx("div",{className:"text-center text-xs text-red-400/70 py-1",children:u}),e.jsx("div",{ref:v})]}),e.jsxs("div",{className:`px-3 py-3 bg-[#0d0d1a] border-t border-[rgba(255,255,255,0.06)]\r
17
- flex items-end gap-2 shrink-0`,children:[e.jsx("textarea",{ref:p,rows:1,value:d,onChange:s=>h(s.target.value),onKeyDown:k,placeholder:"Type a message…",disabled:n,style:{resize:"none",maxHeight:100,overflowY:"auto"},className:`flex-1 bg-[rgba(255,255,255,0.05)] border border-[rgba(255,255,255,0.08)]\r
16
+ text-[rgba(255,255,255,0.8)] leading-relaxed`,children:o})}),n.map(a=>e.jsx(W,{msg:a,primaryColor:d},a.id)),s&&e.jsx("div",{className:"flex justify-start",children:e.jsx(B,{color:d})}),l&&e.jsx("div",{className:"text-center text-xs text-red-400/70 py-1",children:l}),e.jsx("div",{ref:f})]}),e.jsxs("div",{className:`px-3 py-3 bg-[#0d0d1a] border-t border-[rgba(255,255,255,0.06)]\r
17
+ flex items-end gap-2 shrink-0`,children:[e.jsx("textarea",{ref:k,rows:1,value:i,onChange:a=>v(a.target.value),onKeyDown:p,placeholder:"Type a message…",disabled:s,style:{resize:"none",maxHeight:100,overflowY:"auto"},className:`flex-1 bg-[rgba(255,255,255,0.05)] border border-[rgba(255,255,255,0.08)]\r
18
18
  rounded-xl px-3 py-2.5 text-sm text-white/80 placeholder-white/25\r
19
19
  focus:outline-none focus:border-[rgba(255,255,255,0.18)]\r
20
- transition-colors disabled:opacity-40`}),e.jsx("button",{onClick:m,disabled:!d.trim()||n,"aria-label":"Send message",style:{background:d.trim()&&!n?a:void 0},className:`shrink-0 w-9 h-9 rounded-xl flex items-center justify-center\r
20
+ transition-colors disabled:opacity-40`}),e.jsx("button",{onClick:y,disabled:!i.trim()||s,"aria-label":"Send message",style:{background:i.trim()&&!s?d:void 0},className:`shrink-0 w-9 h-9 rounded-xl flex items-center justify-center\r
21
21
  bg-[rgba(255,255,255,0.08)] transition-colors\r
22
- disabled:opacity-40 disabled:cursor-not-allowed`,children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"2",strokeLinecap:"round",children:[e.jsx("path",{d:"m22 2-7 20-4-9-9-4Z"}),e.jsx("path",{d:"M22 2 11 13"})]})})]})]})]})}const M=o.forwardRef(({agentId:t,baseUrl:r,primaryColor:n="#6366f1",position:u="bottom-right",welcomeMessage:a="Hi! How can I help you today?",agentName:x="Assistant",endUserId:c},y)=>{const{messages:b,isLoading:d,historyLoading:h,error:v,conversationId:p,send:m,reset:k,cancel:s}=D({agentId:t,baseUrl:r,endUserId:c});return e.jsx("div",{ref:y,style:{position:"fixed",[u==="bottom-left"?"left":"right"]:"20px",bottom:"20px",zIndex:9999,fontFamily:"system-ui, -apple-system, sans-serif"},children:e.jsx(B,{agentName:x,messages:b,isLoading:d,error:v,primaryColor:n,welcomeMessage:a,onSend:m,onReset:k,onClose:s})})});M.displayName="NexusWidget";exports.NexusWidget=M;exports.useChat=D;
22
+ disabled:opacity-40 disabled:cursor-not-allowed`,children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"2",strokeLinecap:"round",children:[e.jsx("path",{d:"m22 2-7 20-4-9-9-4Z"}),e.jsx("path",{d:"M22 2 11 13"})]})})]})]})]})}const M=r.forwardRef(({agentId:t,baseUrl:n,agentCoreUrl:s,primaryColor:l="#6366f1",position:d="bottom-right",welcomeMessage:o="Hi! How can I help you today?",agentName:u="Assistant",endUserId:h},g)=>{const{messages:i,isLoading:v,historyLoading:f,error:k,conversationId:y,send:p,reset:a,cancel:N}=D({agentId:t,baseUrl:n,agentCoreUrl:s,endUserId:h});return e.jsx("div",{ref:g,style:{position:"fixed",[d==="bottom-left"?"left":"right"]:"20px",bottom:"20px",zIndex:9999,fontFamily:"system-ui, -apple-system, sans-serif"},children:e.jsx(z,{agentName:u,messages:i,isLoading:v,error:k,primaryColor:l,welcomeMessage:o,onSend:p,onReset:a,onClose:N})})});M.displayName="NexusWidget";exports.NexusWidget=M;exports.useChat=D;
package/dist/index.es.js CHANGED
@@ -1,34 +1,34 @@
1
- import { jsxs as p, Fragment as B, jsx as e } from "react/jsx-runtime";
2
- import { useState as k, useRef as D, useCallback as I, useEffect as H, forwardRef as E } from "react";
1
+ import { jsxs as m, Fragment as E, jsx as e } from "react/jsx-runtime";
2
+ import { useState as k, useRef as D, useCallback as I, useEffect as H, forwardRef as z } from "react";
3
3
  function O(t) {
4
4
  return `nexus_widget_session_${t}`;
5
5
  }
6
- function W(t) {
7
- const s = sessionStorage.getItem(O(t));
8
- if (s) return s;
6
+ function A(t) {
7
+ const n = sessionStorage.getItem(O(t));
8
+ if (n) return n;
9
9
  const r = crypto.randomUUID();
10
10
  return sessionStorage.setItem(O(t), r), r;
11
11
  }
12
- async function* A(t, s) {
12
+ async function* W(t, n) {
13
13
  const r = new TextDecoder();
14
- let d = "";
14
+ let i = "";
15
15
  try {
16
16
  for (; ; ) {
17
- if (s.aborted) return;
18
- const { done: o, value: f } = await t.read();
19
- if (o) return;
20
- d += r.decode(f, { stream: !0 });
21
- const l = d.split(`
17
+ if (n.aborted) return;
18
+ const { done: c, value: s } = await t.read();
19
+ if (c) return;
20
+ i += r.decode(s, { stream: !0 });
21
+ const d = i.split(`
22
22
 
23
23
  `);
24
- d = l.pop() ?? "";
25
- for (const y of l)
26
- for (const b of y.split(`
24
+ i = d.pop() ?? "";
25
+ for (const u of d)
26
+ for (const g of u.split(`
27
27
  `)) {
28
- if (!b.startsWith("data: ")) continue;
29
- const c = b.slice(6).trim();
28
+ if (!g.startsWith("data: ")) continue;
29
+ const a = g.slice(6).trim();
30
30
  try {
31
- yield JSON.parse(c);
31
+ yield JSON.parse(a);
32
32
  } catch {
33
33
  }
34
34
  }
@@ -37,139 +37,134 @@ async function* A(t, s) {
37
37
  t.releaseLock();
38
38
  }
39
39
  }
40
- function J({ agentId: t, baseUrl: s = "http://localhost:8000/api", endUserId: r }) {
41
- const [d, o] = k([]), [f, l] = k(!1), [y, b] = k(!0), [c, u] = k(null), [N, x] = k(null), [g, S] = k(null), n = D(W(t)), w = D(null), j = I(async () => {
42
- var T;
43
- (T = w.current) == null || T.abort(), b(!0), u(null);
44
- const a = new AbortController();
45
- w.current = a;
40
+ function L({ agentId: t, baseUrl: n, agentCoreUrl: r, endUserId: i }) {
41
+ const [c, s] = k([]), [d, u] = k(!1), [g, a] = k(!0), [N, h] = k(null), [S, y] = k(null), [x, o] = k(null), T = D(A(t)), w = D(null), j = I(async () => {
42
+ w.current?.abort(), a(!0), h(null);
43
+ const v = new AbortController();
44
+ w.current = v;
46
45
  try {
47
- const h = await fetch(`${s}/widget/session`, {
46
+ const f = await fetch(`${n}/widget/session`, {
48
47
  method: "POST",
49
- signal: a.signal,
48
+ signal: v.signal,
50
49
  headers: { "Content-Type": "application/json" },
51
50
  body: JSON.stringify({
52
51
  agentId: t,
53
- sessionId: n.current
52
+ sessionId: T.current
54
53
  })
55
54
  });
56
- if (!h.ok)
57
- throw new Error(`HTTP ${h.status}`);
58
- const v = await h.json();
59
- S(v.token);
60
- const C = await fetch(`${s}/chat/history`, {
55
+ if (!f.ok)
56
+ throw new Error(`HTTP ${f.status}`);
57
+ const $ = await f.json();
58
+ o($.token);
59
+ const p = await fetch(`${n}/chat/history`, {
61
60
  method: "POST",
62
- signal: a.signal,
61
+ signal: v.signal,
63
62
  headers: {
64
63
  "Content-Type": "application/json",
65
- Authorization: `Bearer ${v.token}`
64
+ Authorization: `Bearer ${$.token}`
66
65
  },
67
66
  body: JSON.stringify({
68
67
  agentId: t,
69
- sessionId: n.current
68
+ sessionId: T.current
70
69
  })
71
70
  });
72
- if (!C.ok)
73
- throw new Error(`HTTP ${C.status}`);
74
- const i = await C.json();
75
- o(i.messages ?? []), x(i.conversationId ?? null);
76
- } catch (h) {
77
- (h == null ? void 0 : h.name) !== "AbortError" && u("Unable to initialize widget session.");
71
+ if (!p.ok)
72
+ throw new Error(`HTTP ${p.status}`);
73
+ const l = await p.json();
74
+ s(l.messages ?? []), y(l.conversationId ?? null);
75
+ } catch (f) {
76
+ f?.name !== "AbortError" && h("Unable to initialize widget session.");
78
77
  } finally {
79
- b(!1);
78
+ a(!1);
80
79
  }
81
80
  }, [t]);
82
81
  H(() => (j(), () => {
83
- var a;
84
- (a = w.current) == null || a.abort();
82
+ w.current?.abort();
85
83
  }), [j]);
86
84
  const P = I(() => {
87
- var a;
88
- (a = w.current) == null || a.abort(), l(!1);
85
+ w.current?.abort(), u(!1);
89
86
  }, []), _ = I(() => {
90
- var a;
91
- (a = w.current) == null || a.abort(), o([]), x(null), u(null), l(!1), n.current = crypto.randomUUID(), S(null), j();
92
- }, [j]), z = I(
93
- async (a) => {
94
- var C;
95
- if (!a.trim() || f || !g) return;
96
- (C = w.current) == null || C.abort();
97
- const T = new AbortController();
98
- w.current = T, u(null);
99
- const h = `u_${Date.now()}`, v = `a_${Date.now()}`;
100
- o((i) => [
101
- ...i,
102
- { id: h, role: "user", content: a.trim() }
103
- ]), l(!0);
87
+ w.current?.abort(), s([]), y(null), h(null), u(!1), T.current = crypto.randomUUID(), o(null), j();
88
+ }, [j]), B = I(
89
+ async (v) => {
90
+ if (!v.trim() || d || !x) return;
91
+ w.current?.abort();
92
+ const f = new AbortController();
93
+ w.current = f, h(null);
94
+ const $ = `u_${Date.now()}`, p = `a_${Date.now()}`;
95
+ s((l) => [
96
+ ...l,
97
+ { id: $, role: "user", content: v.trim() }
98
+ ]), u(!0);
104
99
  try {
105
- const i = await fetch(`${s}/chat`, {
100
+ const l = await fetch(`${r}/chat`, {
106
101
  method: "POST",
107
- signal: T.signal,
102
+ signal: f.signal,
108
103
  headers: {
109
104
  "Content-Type": "application/json",
110
- Authorization: `Bearer ${g}`
105
+ Authorization: `Bearer ${x}`
111
106
  },
112
107
  body: JSON.stringify({
113
108
  agent_id: t,
114
- message: a.trim(),
115
- session_id: n.current,
116
- end_user_id: r
109
+ message: v.trim(),
110
+ session_id: T.current,
111
+ end_user_id: i
117
112
  })
118
113
  });
119
- if (!i.ok || !i.body)
120
- throw new Error(`HTTP ${i.status}`);
121
- o((m) => [
122
- ...m,
123
- { id: v, role: "assistant", content: "" }
114
+ if (!l.ok || !l.body)
115
+ throw new Error(`HTTP ${l.status}`);
116
+ s((b) => [
117
+ ...b,
118
+ { id: p, role: "assistant", content: "" }
124
119
  ]);
125
- const M = i.body.getReader();
126
- for await (const m of A(M, T.signal))
127
- switch (m.type) {
120
+ const R = l.body.getReader();
121
+ for await (const b of W(R, f.signal))
122
+ switch (b.type) {
128
123
  case "start":
129
- x(m.conversationId);
124
+ y(b.conversationId);
130
125
  break;
131
126
  case "token":
132
- o(
133
- (R) => R.map(
134
- ($) => $.id === v ? { ...$, content: $.content + m.content } : $
127
+ s(
128
+ (M) => M.map(
129
+ (C) => C.id === p ? { ...C, content: C.content + b.content } : C
135
130
  )
136
131
  );
137
132
  break;
138
133
  case "done":
139
134
  break;
140
135
  case "error":
141
- u(m.message), o(
142
- (R) => R.filter(($) => $.id !== v)
136
+ h(b.message), s(
137
+ (M) => M.filter((C) => C.id !== p)
143
138
  );
144
139
  break;
145
140
  }
146
- } catch (i) {
147
- if ((i == null ? void 0 : i.name) === "AbortError") return;
148
- u("Something went wrong. Please try again."), o(
149
- (M) => M.filter(
150
- (m) => m.id !== h && m.id !== v
141
+ } catch (l) {
142
+ if (l?.name === "AbortError") return;
143
+ h("Something went wrong. Please try again."), s(
144
+ (R) => R.filter(
145
+ (b) => b.id !== $ && b.id !== p
151
146
  )
152
147
  );
153
148
  } finally {
154
- l(!1);
149
+ u(!1);
155
150
  }
156
151
  },
157
- [t, r, f, g]
152
+ [t, i, d, x]
158
153
  );
159
154
  return {
160
- messages: d,
161
- isLoading: f,
162
- historyLoading: y,
163
- error: c,
164
- conversationId: N,
165
- send: z,
155
+ messages: c,
156
+ isLoading: d,
157
+ historyLoading: g,
158
+ error: N,
159
+ conversationId: S,
160
+ send: B,
166
161
  reset: _,
167
162
  cancel: P
168
163
  };
169
164
  }
170
- function K({ color: t }) {
165
+ function U({ color: t }) {
171
166
  return /* @__PURE__ */ e("div", { className: `flex items-end gap-1 px-3 py-2.5 rounded-2xl rounded-bl-sm w-fit\r
172
- bg-[rgba(255,255,255,0.06)]`, children: [0, 1, 2].map((s) => /* @__PURE__ */ e(
167
+ bg-[rgba(255,255,255,0.06)]`, children: [0, 1, 2].map((n) => /* @__PURE__ */ e(
173
168
  "span",
174
169
  {
175
170
  style: {
@@ -178,59 +173,57 @@ function K({ color: t }) {
178
173
  borderRadius: "50%",
179
174
  background: t,
180
175
  opacity: 0.6,
181
- animation: `nexusBounce 1.2s ease-in-out ${s * 0.2}s infinite`
176
+ animation: `nexusBounce 1.2s ease-in-out ${n * 0.2}s infinite`
182
177
  }
183
178
  },
184
- s
179
+ n
185
180
  )) });
186
181
  }
187
- function L({
182
+ function J({
188
183
  msg: t,
189
- primaryColor: s
184
+ primaryColor: n
190
185
  }) {
191
186
  const r = t.role === "user";
192
187
  return /* @__PURE__ */ e("div", { className: `flex ${r ? "justify-end" : "justify-start"}`, children: /* @__PURE__ */ e(
193
188
  "div",
194
189
  {
195
- style: r ? { background: s } : void 0,
190
+ style: r ? { background: n } : void 0,
196
191
  className: `max-w-[82%] px-3 py-2.5 rounded-2xl text-sm leading-relaxed
197
192
  ${r ? "text-white rounded-br-sm" : "bg-[rgba(255,255,255,0.06)] text-[rgba(255,255,255,0.8)] rounded-bl-sm"}`,
198
193
  children: t.content
199
194
  }
200
195
  ) });
201
196
  }
202
- function U({
197
+ function K({
203
198
  agentName: t,
204
- messages: s,
199
+ messages: n,
205
200
  isLoading: r,
206
- error: d,
207
- primaryColor: o,
208
- welcomeMessage: f,
209
- onSend: l,
210
- onReset: y,
211
- onClose: b
201
+ error: i,
202
+ primaryColor: c,
203
+ welcomeMessage: s,
204
+ onSend: d,
205
+ onReset: u,
206
+ onClose: g
212
207
  }) {
213
- const [c, u] = k(""), N = D(null), x = D(null);
208
+ const [a, N] = k(""), h = D(null), S = D(null);
214
209
  H(() => {
215
- var n;
216
- (n = N.current) == null || n.scrollIntoView({ behavior: "smooth" });
217
- }, [s, r]), H(() => {
218
- var n;
219
- (n = x.current) == null || n.focus();
210
+ h.current?.scrollIntoView({ behavior: "smooth" });
211
+ }, [n, r]), H(() => {
212
+ S.current?.focus();
220
213
  }, []);
221
- const g = () => {
222
- !c.trim() || r || (l(c), u(""));
223
- }, S = (n) => {
224
- n.key === "Enter" && !n.shiftKey && (n.preventDefault(), g());
214
+ const y = () => {
215
+ !a.trim() || r || (d(a), N(""));
216
+ }, x = (o) => {
217
+ o.key === "Enter" && !o.shiftKey && (o.preventDefault(), y());
225
218
  };
226
- return /* @__PURE__ */ p(B, { children: [
219
+ return /* @__PURE__ */ m(E, { children: [
227
220
  /* @__PURE__ */ e("style", { children: `
228
221
  @keyframes nexusBounce {
229
222
  0%, 80%, 100% { transform: translateY(0); }
230
223
  40% { transform: translateY(-5px); }
231
224
  }
232
225
  ` }),
233
- /* @__PURE__ */ p(
226
+ /* @__PURE__ */ m(
234
227
  "div",
235
228
  {
236
229
  style: { fontFamily: "system-ui, -apple-system, sans-serif" },
@@ -239,25 +232,25 @@ function U({
239
232
  role: "dialog",
240
233
  "aria-label": `${t} chat`,
241
234
  children: [
242
- /* @__PURE__ */ p(
235
+ /* @__PURE__ */ m(
243
236
  "div",
244
237
  {
245
- style: { background: o },
238
+ style: { background: c },
246
239
  className: "flex items-center justify-between px-4 py-3 shrink-0",
247
240
  children: [
248
- /* @__PURE__ */ p("div", { className: "flex items-center gap-2.5", children: [
241
+ /* @__PURE__ */ m("div", { className: "flex items-center gap-2.5", children: [
249
242
  /* @__PURE__ */ e("div", { className: "w-2 h-2 rounded-full bg-white/40" }),
250
243
  /* @__PURE__ */ e("span", { className: "text-white text-sm font-medium", children: t })
251
244
  ] }),
252
- /* @__PURE__ */ p("div", { className: "flex items-center gap-1", children: [
245
+ /* @__PURE__ */ m("div", { className: "flex items-center gap-1", children: [
253
246
  /* @__PURE__ */ e(
254
247
  "button",
255
248
  {
256
- onClick: y,
249
+ onClick: u,
257
250
  "aria-label": "Start new conversation",
258
251
  className: `p-1.5 rounded-full text-white/60 hover:text-white\r
259
252
  hover:bg-white/15 transition-colors`,
260
- children: /* @__PURE__ */ p(
253
+ children: /* @__PURE__ */ m(
261
254
  "svg",
262
255
  {
263
256
  width: "14",
@@ -278,7 +271,7 @@ function U({
278
271
  /* @__PURE__ */ e(
279
272
  "button",
280
273
  {
281
- onClick: b,
274
+ onClick: g,
282
275
  "aria-label": "Close chat",
283
276
  className: `p-1.5 rounded-full text-white/60 hover:text-white\r
284
277
  hover:bg-white/15 transition-colors`,
@@ -301,25 +294,25 @@ function U({
301
294
  ]
302
295
  }
303
296
  ),
304
- /* @__PURE__ */ p("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-[#0d0d1a]", style: { minHeight: 0 }, children: [
305
- s.length === 0 && /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e("div", { className: `max-w-[82%] px-3 py-2.5 rounded-2xl rounded-bl-sm\r
297
+ /* @__PURE__ */ m("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-[#0d0d1a]", style: { minHeight: 0 }, children: [
298
+ n.length === 0 && /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e("div", { className: `max-w-[82%] px-3 py-2.5 rounded-2xl rounded-bl-sm\r
306
299
  bg-[rgba(255,255,255,0.06)] text-sm\r
307
- text-[rgba(255,255,255,0.8)] leading-relaxed`, children: f }) }),
308
- s.map((n) => /* @__PURE__ */ e(L, { msg: n, primaryColor: o }, n.id)),
309
- r && /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e(K, { color: o }) }),
310
- d && /* @__PURE__ */ e("div", { className: "text-center text-xs text-red-400/70 py-1", children: d }),
311
- /* @__PURE__ */ e("div", { ref: N })
300
+ text-[rgba(255,255,255,0.8)] leading-relaxed`, children: s }) }),
301
+ n.map((o) => /* @__PURE__ */ e(J, { msg: o, primaryColor: c }, o.id)),
302
+ r && /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e(U, { color: c }) }),
303
+ i && /* @__PURE__ */ e("div", { className: "text-center text-xs text-red-400/70 py-1", children: i }),
304
+ /* @__PURE__ */ e("div", { ref: h })
312
305
  ] }),
313
- /* @__PURE__ */ p("div", { className: `px-3 py-3 bg-[#0d0d1a] border-t border-[rgba(255,255,255,0.06)]\r
306
+ /* @__PURE__ */ m("div", { className: `px-3 py-3 bg-[#0d0d1a] border-t border-[rgba(255,255,255,0.06)]\r
314
307
  flex items-end gap-2 shrink-0`, children: [
315
308
  /* @__PURE__ */ e(
316
309
  "textarea",
317
310
  {
318
- ref: x,
311
+ ref: S,
319
312
  rows: 1,
320
- value: c,
321
- onChange: (n) => u(n.target.value),
322
- onKeyDown: S,
313
+ value: a,
314
+ onChange: (o) => N(o.target.value),
315
+ onKeyDown: x,
323
316
  placeholder: "Type a message…",
324
317
  disabled: r,
325
318
  style: { resize: "none", maxHeight: 100, overflowY: "auto" },
@@ -332,14 +325,14 @@ function U({
332
325
  /* @__PURE__ */ e(
333
326
  "button",
334
327
  {
335
- onClick: g,
336
- disabled: !c.trim() || r,
328
+ onClick: y,
329
+ disabled: !a.trim() || r,
337
330
  "aria-label": "Send message",
338
- style: { background: c.trim() && !r ? o : void 0 },
331
+ style: { background: a.trim() && !r ? c : void 0 },
339
332
  className: `shrink-0 w-9 h-9 rounded-xl flex items-center justify-center\r
340
333
  bg-[rgba(255,255,255,0.08)] transition-colors\r
341
334
  disabled:opacity-40 disabled:cursor-not-allowed`,
342
- children: /* @__PURE__ */ p(
335
+ children: /* @__PURE__ */ m(
343
336
  "svg",
344
337
  {
345
338
  width: "14",
@@ -363,49 +356,50 @@ function U({
363
356
  )
364
357
  ] });
365
358
  }
366
- const F = E(
359
+ const F = z(
367
360
  ({
368
361
  agentId: t,
369
- baseUrl: s,
370
- primaryColor: r = "#6366f1",
371
- position: d = "bottom-right",
372
- welcomeMessage: o = "Hi! How can I help you today?",
373
- agentName: f = "Assistant",
374
- endUserId: l
375
- }, y) => {
362
+ baseUrl: n,
363
+ agentCoreUrl: r,
364
+ primaryColor: i = "#6366f1",
365
+ position: c = "bottom-right",
366
+ welcomeMessage: s = "Hi! How can I help you today?",
367
+ agentName: d = "Assistant",
368
+ endUserId: u
369
+ }, g) => {
376
370
  const {
377
- messages: b,
378
- isLoading: c,
379
- historyLoading: u,
380
- error: N,
381
- conversationId: x,
382
- send: g,
383
- reset: S,
384
- cancel: n
385
- } = J({ agentId: t, baseUrl: s, endUserId: l });
371
+ messages: a,
372
+ isLoading: N,
373
+ historyLoading: h,
374
+ error: S,
375
+ conversationId: y,
376
+ send: x,
377
+ reset: o,
378
+ cancel: T
379
+ } = L({ agentId: t, baseUrl: n, agentCoreUrl: r, endUserId: u });
386
380
  return /* @__PURE__ */ e(
387
381
  "div",
388
382
  {
389
- ref: y,
383
+ ref: g,
390
384
  style: {
391
385
  position: "fixed",
392
- [d === "bottom-left" ? "left" : "right"]: "20px",
386
+ [c === "bottom-left" ? "left" : "right"]: "20px",
393
387
  bottom: "20px",
394
388
  zIndex: 9999,
395
389
  fontFamily: "system-ui, -apple-system, sans-serif"
396
390
  },
397
391
  children: /* @__PURE__ */ e(
398
- U,
392
+ K,
399
393
  {
400
- agentName: f,
401
- messages: b,
402
- isLoading: c,
403
- error: N,
404
- primaryColor: r,
405
- welcomeMessage: o,
406
- onSend: g,
407
- onReset: S,
408
- onClose: n
394
+ agentName: d,
395
+ messages: a,
396
+ isLoading: N,
397
+ error: S,
398
+ primaryColor: i,
399
+ welcomeMessage: s,
400
+ onSend: x,
401
+ onReset: o,
402
+ onClose: T
409
403
  }
410
404
  )
411
405
  }
@@ -415,5 +409,5 @@ const F = E(
415
409
  F.displayName = "NexusWidget";
416
410
  export {
417
411
  F as NexusWidget,
418
- J as useChat
412
+ L as useChat
419
413
  };
package/dist/types.d.ts CHANGED
@@ -6,6 +6,7 @@ export interface ChatMessage {
6
6
  export interface UseChatOptions {
7
7
  agentId: string;
8
8
  baseUrl?: string;
9
+ agentCoreUrl?: string;
9
10
  endUserId?: string;
10
11
  }
11
12
  export type SseEvent = {
@@ -23,6 +24,7 @@ export type SseEvent = {
23
24
  export interface NexusWidgetProps {
24
25
  agentId: string;
25
26
  baseUrl?: string;
27
+ agentCoreUrl?: string;
26
28
  primaryColor?: string;
27
29
  position?: "bottom-right" | "bottom-left";
28
30
  welcomeMessage?: string;
package/dist/useChat.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ChatMessage, UseChatOptions } from './types';
2
- export declare function useChat({ agentId, baseUrl: BASE_URL, endUserId }: UseChatOptions): {
2
+ export declare function useChat({ agentId, baseUrl: BASE_URL, agentCoreUrl, endUserId }: UseChatOptions): {
3
3
  messages: ChatMessage[];
4
4
  isLoading: boolean;
5
5
  historyLoading: boolean;