@dypai-ai/client-sdk 1.10.5 → 1.10.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to `@dypai-ai/client-sdk` will be documented in this file.
4
4
 
5
+ ## [1.10.6] - 2026-05-12
6
+
7
+ ### Fixed
8
+
9
+ - `useChat` now supports the Vercel AI SDK UI Message Stream protocol (`x-vercel-ai-ui-message-stream: v1`) used by DYPAI agent streaming endpoints.
10
+ - Preserved compatibility with legacy Vercel data streams and the previous DYPAI plain-text stream fallback.
11
+
12
+ ### Changed
13
+
14
+ - `useChat` now keeps streamed tool calls and tool results in `message.parts` while still accumulating assistant text in `message.content`.
15
+
5
16
  ## [1.10.5] - 2026-05-10
6
17
 
7
18
  ### Fixed
package/README.md CHANGED
@@ -602,6 +602,42 @@ await patchSettings({ theme: 'dark' });
602
602
  await deleteItem({ id: '123' });
603
603
  ```
604
604
 
605
+ ### useChat
606
+
607
+ ```tsx
608
+ import { useChat } from '@dypai-ai/client-sdk/react';
609
+
610
+ function SupportChat() {
611
+ const { messages, input, setInput, sendMessage, isLoading, stop } = useChat('support_agent');
612
+
613
+ return (
614
+ <section>
615
+ {messages.map(message => (
616
+ <article key={message.id}>
617
+ <strong>{message.role}</strong>
618
+ <p>{message.content}</p>
619
+ {message.parts?.map((part, index) => {
620
+ if (part.type === 'tool-call') {
621
+ return <small key={index}>Calling {part.toolName}...</small>;
622
+ }
623
+ if (part.type === 'tool-result') {
624
+ return <small key={index}>{part.toolName} finished</small>;
625
+ }
626
+ return null;
627
+ })}
628
+ </article>
629
+ ))}
630
+
631
+ <input value={input} onChange={event => setInput(event.target.value)} />
632
+ <button onClick={() => sendMessage()} disabled={isLoading}>Send</button>
633
+ {isLoading && <button onClick={stop}>Stop</button>}
634
+ </section>
635
+ );
636
+ }
637
+ ```
638
+
639
+ `useChat` supports DYPAI agent streams that use the Vercel AI SDK UI Message Stream protocol, plus legacy DYPAI text streams for older engines. Assistant text is accumulated in `message.content`; streamed tool calls and tool results are exposed in `message.parts`.
640
+
605
641
  ### useUpload
606
642
 
607
643
  ```tsx
@@ -1 +1 @@
1
- import{jsx as t,Fragment as e}from"react/jsx-runtime";import{createContext as n,useState as r,useEffect as a,useContext as o,useCallback as s,useRef as i}from"react";const c=n(null);function l({client:e,children:n}){const[o,s]=r(null),[i,l]=r(null),[u,d]=r(!0),[h,f]=r(null);a(()=>{const{data:{subscription:t}}=e.auth.onAuthStateChange((t,e)=>{f(t),"SIGNED_IN"===t||"TOKEN_REFRESHED"===t||"INITIAL_SESSION"===t?(l(e??null),s(e?.user??null),d(!1)):"SIGNED_OUT"===t?(l(null),s(null),d(!1)):"PASSWORD_RECOVERY"===t?(l(e??null),s(e?.user??null),d(!1)):"AUTH_ERROR"===t?d(!1):"USER_UPDATED"===t&&e&&(l(e),s(e.user??null))});return()=>{t?.unsubscribe()}},[e]);const p={client:e,user:o,session:i,isLoading:u,isAuthenticated:!!o,authEvent:h};return t(c.Provider,{value:p,children:n})}function u(){const t=o(c);if(!t)throw new Error('useDypai must be used within a <DypaiProvider>. Wrap your app with <DypaiProvider url="...">.');return t}function d(){return u().client}function h(){const{client:t,user:e,isLoading:n,isAuthenticated:r,authEvent:a}=u(),o=s(async(e,n)=>{const{error:r}=await t.auth.signInWithPassword({email:e,password:n});return{error:r}},[t]),i=s(async(e,n,r)=>{const{data:a,error:o}=await t.auth.signUp({email:e,password:n,...r});return{error:o,confirmationRequired:a?.confirmationRequired}},[t]),c=s(async()=>{await t.auth.signOut()},[t]),l=s(async(e,n)=>{const{error:r}=await t.auth.resetPasswordForEmail(e,n);return{error:r}},[t]),d=s(async e=>{const{error:n}=await t.auth.setPassword(e);return{error:n}},[t]),h=s(async e=>{await t.auth.signInWithOAuth(e)},[t]),f=s(async e=>{const{error:n}=await t.auth.signInWithOtp({email:e});return{error:n}},[t]),p=s(async e=>{const{error:n}=await t.auth.signInWithMagicLink(e);return{error:n}},[t]),w=s(async()=>{const{data:e,error:n}=await t.auth.enableTwoFactor();return{data:e,error:n}},[t]),y=s(async e=>{const{error:n}=await t.auth.verifyTwoFactor(e);return{error:n}},[t]),m=s(async()=>{const{error:e}=await t.auth.disableTwoFactor();return{error:e}},[t]),b=s(async(e,n)=>{const{data:r,error:a}=await t.auth.createOrganization(e,n);return{data:r,error:a}},[t]),T=s(async()=>{const{data:e,error:n}=await t.auth.listOrganizations();return{data:e,error:n}},[t]),E=s(async(e,n,r)=>{const{error:a}=await t.auth.inviteMember(e,n,r);return{error:a}},[t]);return{user:e,isLoading:n,isAuthenticated:r,authEvent:a,lastError:t.auth.lastError,isPasswordRecovery:t.auth.isPasswordRecoveryCallback||t.auth.hasPasswordRecoveryToken,signIn:o,signUp:i,signOut:c,resetPassword:l,setPassword:d,signInWithOAuth:h,signInWithOtp:f,signInWithMagicLink:p,enableTwoFactor:w,verifyTwoFactor:y,disableTwoFactor:m,createOrganization:b,listOrganizations:T,inviteMember:E}}function f(t,e={}){const n=d(),{params:o,enabled:c=!0,refetchInterval:l=0}=e,[u,h]=r(null),[f,p]=r(null),[w,y]=r(!0),[m,b]=r(!1),T=i(!0),E=JSON.stringify(o||{}),g=s(async(e=!1)=>{if(!c)return void y(!1);e?b(!0):y(!0),p(null);const{data:r,error:a}=await n.api.get(t,{params:o});T.current&&(a?(p(a),h(null)):h(r),y(!1),b(!1))},[n,t,E,c]);return a(()=>(T.current=!0,g(),()=>{T.current=!1}),[g]),a(()=>{if(!l||!c)return;const t=setInterval(()=>g(!0),l);return()=>clearInterval(t)},[g,l,c]),{data:u,error:f,isLoading:w,isRefetching:m,refetch:s(async()=>{await g(!0)},[g])}}function p(t,e={}){const n=d(),{method:a="POST",onSuccess:o,onError:i}=e,[c,l]=r(null),[u,h]=r(null),[f,p]=r(!1);return{mutate:s(async e=>{let r;switch(p(!0),h(null),a){case"PUT":r=await n.api.put(t,e);break;case"PATCH":r=await n.api.patch(t,e);break;case"DELETE":r=await n.api.delete(t,{params:e});break;default:r=await n.api.post(t,e)}return p(!1),r.error?(h(r.error),i?.(r.error),{data:null,error:r.error}):(l(r.data),o?.(r.data),{data:r.data,error:null})},[n,t,a,o,i]),data:c,error:u,isLoading:f,reset:s(()=>{l(null),h(null),p(!1)},[])}}function w(t,e={}){const n=d(),{onSuccess:a,onError:o}=e,[i,c]=r(0),[l,u]=r(!1),[h,f]=r(null),[p,w]=r(null);return{upload:s(async(e,r)=>{u(!0),c(0),f(null);const{data:s,error:i}=await n.api.upload(t,e,{params:r,onProgress:c});return u(!1),i?(f(i),o?.(i),{data:null,error:i}):(w(s),a?.(s),{data:s,error:null})},[n,t,a,o]),progress:i,isUploading:l,error:h,data:p,reset:s(()=>{c(0),u(!1),f(null),w(null)},[])}}function y(){return crypto.randomUUID?.()||`${Date.now()}-${Math.random().toString(36).slice(2)}`}function m(t){return t.parts?.length?t.parts.filter(t=>"text"===t.type).map(t=>t.text||"").join(""):t.content||""}function b(t){return t.parts?.length?t.parts.filter(t=>"tool-call"===t.type).map(t=>({toolName:t.toolName||"unknown",args:t.args})):[]}function T(){return y()}function E(t,e={}){const n=d(),[o,c]=r(e.id||T),[l,u]=r(e.initialMessages||[]),[h,f]=r("ready"),[p,w]=r(""),[y,m]=r(null),b=i(null);a(()=>{if(!1===e.loadHistory)return;if(!e.id)return;let t=!1;return(async()=>{try{const e=n.baseUrl,r=n.getAuthToken()||"",a=await fetch(`${e}/api/v0/chats/${o}/messages?limit=50`,{headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"}});if(!a.ok||t)return;const s=await a.json();if(s.messages&&!t){const t=s.messages.map(t=>({id:t.id,role:t.role,content:(t.parts||[]).filter(t=>"text"===t.type).map(t=>t.text).join(""),parts:t.parts,metadata:t.metadata,createdAt:new Date(t.created_at)}));u(t)}}catch{}})(),()=>{t=!0}},[o,e.id,e.loadHistory]);const E=s(async r=>{const a=r||p;if(!a.trim())return;r||w(""),m(null);const s={id:T(),role:"user",content:a,parts:[{type:"text",text:a}],createdAt:new Date},i=[...l,s];u(i),f("submitted");const c={id:T(),role:"assistant",content:"",parts:[],createdAt:new Date};try{const r=n.baseUrl,s=n.getAuthToken()||"",l=new AbortController;b.current=l;const d={session_id:o,messages:[{role:"user",content:a}],...e.body||{}},h=await fetch(`${r}/api/v0/${t}`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",Accept:"text/event-stream",...e.headers||{}},body:JSON.stringify(d),signal:l.signal});if(!h.ok){const t=await h.json().catch(()=>({error:h.statusText}));throw new Error(t.error||`HTTP ${h.status}`)}if((h.headers.get("content-type")||"").includes("application/json")){const t=await h.json(),n=t.content||t.text||JSON.stringify(t);c.content=n,c.parts=[{type:"text",text:n}];const r=[...i,{...c}];return u(r),f("ready"),void e.onFinish?.(c,r)}f("streaming"),u([...i,c]);const p=h.body?.getReader();if(!p)throw new Error("No response body");const w=new TextDecoder;let y="";for(;;){const{done:t,value:e}=await p.read();if(t)break;const n=w.decode(e,{stream:!0}).split("\n").filter(t=>!/^[A-Z][a-zA-Z-]+:\s/.test(t)).join("\n");n&&(y+=n,c.content=y,c.parts=[{type:"text",text:y}],u([...i,{...c}]))}const m={...c,content:y,parts:[{type:"text",text:y}]},T=[...i,m];u(T),f("ready"),e.onFinish?.(m,T)}catch(t){if("AbortError"===t.name)return void f("ready");m(t),f("error"),e.onError?.(t)}finally{b.current=null}},[p,l,o,t,n,e]),g=s(()=>{b.current?.abort(),b.current=null,f("ready")},[]),S=s(()=>{g(),u([]),m(null),f("ready"),w(""),c(T())},[g]);return{messages:l,status:h,input:p,setInput:w,sendMessage:E,setMessages:u,stop:g,newChat:S,isLoading:"submitted"===h||"streaming"===h,error:y,chatId:o}}function g(t={}){const e=d(),{endpointId:n,limit:o=20,enabled:i=!0}=t,[c,l]=r([]),[u,h]=r(!1),[f,p]=r(null),w=s(async()=>{h(!0),p(null);try{const t=e.baseUrl,r=e.getAuthToken()||"",a=new URLSearchParams({limit:String(o)});n&&a.set("endpoint_id",n);const s=await fetch(`${t}/api/v0/chats?${a}`,{headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"}});if(!s.ok){const t=await s.json().catch(()=>({}));throw new Error(t.error||`HTTP ${s.status}`)}const i=((await s.json()).chats||[]).map(t=>({id:t.id,title:t.title,visibility:t.visibility,messageCount:parseInt(t.message_count||"0"),createdAt:t.created_at,updatedAt:t.updated_at}));l(i)}catch(t){p(t)}finally{h(!1)}},[e,n,o]),y=s(async t=>{const n=e.baseUrl,r=e.getAuthToken()||"",a=await fetch(`${n}/api/v0/chats/${t}`,{method:"DELETE",headers:{Authorization:`Bearer ${r}`}});if(!a.ok){const t=await a.json().catch(()=>({}));throw new Error(t.error||`HTTP ${a.status}`)}l(e=>e.filter(e=>e.id!==t))},[e]),m=s(async(t,n)=>{const r=e.baseUrl,a=e.getAuthToken()||"",o=await fetch(`${r}/api/v0/chats/${t}`,{method:"PATCH",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({title:n})});if(!o.ok){const t=await o.json().catch(()=>({}));throw new Error(t.error||`HTTP ${o.status}`)}l(e=>e.map(e=>e.id===t?{...e,title:n}:e))},[e]);return a(()=>{i&&w()},[i,w]),{chats:c,isLoading:u,error:f,refetch:w,deleteChat:y,renameChat:m}}let S=null,v="disconnected",$=null,A=null,O=0,I="",P="";const C=[1e3,2e3,5e3,1e4,3e4],N=new Set,D=[],L=[];function R(t,e){if(S&&(S.readyState===WebSocket.OPEN||S.readyState===WebSocket.CONNECTING))return S;I=t,P=e;const n=t.replace(/^http/,"ws")+`/realtime?token=${encodeURIComponent(e)}`,r=new WebSocket(n);return S=r,v="connecting",r.onopen=()=>{v="connected",O=0;for(const t of D)r.send(JSON.stringify({type:"subscribe",...t}));for(const t of L)r.send(JSON.stringify({type:"join",...t}));A&&clearInterval(A),A=setInterval(()=>{r.readyState===WebSocket.OPEN&&r.send(JSON.stringify({type:"heartbeat"}))},25e3)},r.onmessage=t=>{try{const e=JSON.parse("string"==typeof t.data?t.data:"");for(const t of N)t(e)}catch{}},r.onclose=()=>{if(v="disconnected",S=null,A&&clearInterval(A),N.size>0&&!$){const t=C[Math.min(O,C.length-1)];O++,$=setTimeout(()=>{$=null,N.size>0&&I&&P&&R(I,P)},t)}},r.onerror=()=>{v="error"},r}function k(t){return N.add(t),()=>{N.delete(t),0===N.size&&S&&(S.close(),S=null)}}function j(t){return!(!S||S.readyState!==WebSocket.OPEN||(S.send(JSON.stringify(t)),0))}function x(t,e={}){const n=d(),{event:o="*",filter:s,enabled:c=!0}=e,[l,u]=r([]),[h,f]=r("disconnected"),[p,w]=r(null),y=i(e);return y.current=e,a(()=>{if(!c)return;const e=n.baseUrl,r=n.getAuthToken()||"";if(!r)return void w(new Error("Authentication required for realtime"));const a=R(e,r);f(v),function(t){const e=D.findIndex(e=>e.table===t.table);e>=0&&D.splice(e,1),D.push(t)}({table:t,event:o,filter:s});const i=()=>{a.readyState===WebSocket.OPEN&&(a.send(JSON.stringify({type:"subscribe",table:t,event:o,filter:s})),f("connected"))};a.readyState===WebSocket.OPEN?i():a.addEventListener("open",i,{once:!0});const l=k(e=>{if("connected"!==e.type&&"subscribe"!==e.type||f("connected"),"change"!==e.type||e.table!==t)return;if("*"!==o&&e.event!==o)return;const n={table:e.table,event:e.event,record:e.record??null,old_record:e.old_record??null,timestamp:e.timestamp,truncated:e.truncated};u(t=>[...t.slice(-99),n]),y.current.onChange?.(n),e.truncated?("INSERT"===e.event&&y.current.onInsert?.(null),"UPDATE"===e.event&&y.current.onUpdate?.(null,null),"DELETE"===e.event&&y.current.onDelete?.(null)):("INSERT"===e.event&&e.record&&y.current.onInsert?.(e.record),"UPDATE"===e.event&&e.record&&y.current.onUpdate?.(e.record,e.old_record),"DELETE"===e.event&&e.old_record&&y.current.onDelete?.(e.old_record))});return()=>{l(),function(t){const e=D.findIndex(e=>e.table===t);e>=0&&D.splice(e,1)}(t),j({type:"unsubscribe",table:t})}},[t,o,c,n]),{changes:l,isConnected:"connected"===h,status:h,error:p}}function W(t,e={}){const n=d(),{presence:o,enabled:c=!0}=e,[l,u]=r({}),[h,f]=r(!1),p=i(e);return p.current=e,a(()=>{if(!c||!t)return;const e=n.baseUrl,r=n.getAuthToken()||"";if(!r)return;const a=R(e,r);!function(t){const e=L.findIndex(e=>e.channel===t.channel);e>=0&&L.splice(e,1),L.push(t)}({channel:t,presence:o||void 0});const s=()=>{a.readyState===WebSocket.OPEN&&a.send(JSON.stringify({type:"join",channel:t,presence:o||void 0}))};a.readyState===WebSocket.OPEN?s():a.addEventListener("open",s,{once:!0});const i=k(e=>{"connected"!==e.type&&"join"!==e.type||f(!0),"broadcast"===e.type&&e.channel===t&&p.current.onBroadcast?.({event:e.event,payload:e.payload,sender:e.sender,timestamp:e.timestamp}),"presence_state"===e.type&&e.channel===t&&u(e.presences||{}),"presence_diff"===e.type&&e.channel===t&&u(t=>{const n={...t};if(e.joins)for(const[t,r]of Object.entries(e.joins))n[t]=r,p.current.onJoin?.(t,r);if(e.leaves)for(const[t,r]of Object.entries(e.leaves))delete n[t],p.current.onLeave?.(t,r);return n})});return()=>{i(),function(t){const e=L.findIndex(e=>e.channel===t);e>=0&&L.splice(e,1)}(t),j({type:"leave",channel:t}),f(!1)}},[t,c,n]),{broadcast:s((e,n)=>{j({type:"broadcast",channel:t,event:e,payload:n})},[t]),presences:l,isConnected:h,memberCount:Object.keys(l).length}}function _(t,e={}){const n=d(),{loadHistory:o=!0,limit:c=50}=e,[l,u]=r([]),[h,f]=r(!1),[p,w]=r(null),y=i(new Set);a(()=>{if(!o||!t)return;let e=!1;return(async()=>{f(!0);try{const r=n.baseUrl,a=n.getAuthToken()||"",o=await fetch(`${r}/api/v0/channels/${t}/messages?limit=${c}`,{headers:{Authorization:`Bearer ${a}`}});if(!o.ok)throw new Error(`HTTP ${o.status}`);const s=await o.json();if(!e&&s.messages){const t=s.messages;t.forEach(t=>y.current.add(t.id)),u(t)}}catch(t){e||w(t)}finally{e||f(!1)}})(),()=>{e=!0}},[t,o,c,n]);const{isConnected:m}=x("channel_messages",{event:"INSERT",filter:{channel_id:t},onInsert:t=>{t&&(y.current.has(t.id)||(y.current.add(t.id),u(e=>[...e,t])))}});return{messages:l,send:s(async(e,r)=>{try{const a=n.baseUrl,o=n.getAuthToken()||"",s=await fetch(`${a}/api/v0/channels/${t}/messages`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({content:e,metadata:r})});if(!s.ok){const t=await s.json().catch(()=>({}));throw new Error(t.error||`HTTP ${s.status}`)}const i=await s.json();i.message&&(y.current.add(i.message.id),u(t=>[...t,i.message]))}catch(t){throw w(t),t}},[t,n]),isLoading:h,isConnected:m,error:p}}function z(){const t=d(),[e,n]=r([]),[o,i]=r(!1),[c,l]=r(null),u=s(async()=>{i(!0);try{const e=t.baseUrl,r=t.getAuthToken()||"",a=await fetch(`${e}/api/v0/channels`,{headers:{Authorization:`Bearer ${r}`}});if(!a.ok)throw new Error(`HTTP ${a.status}`);const o=await a.json();n(o.channels||[])}catch(t){l(t)}finally{i(!1)}},[t]);return a(()=>{u()},[u]),{channels:e,isLoading:o,error:c,createChannel:s(async(e,r=[],a="group")=>{const o=t.baseUrl,s=t.getAuthToken()||"",i=await fetch(`${o}/api/v0/channels`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({name:e,type:a,members:r})});if(!i.ok){const t=await i.json().catch(()=>({}));throw new Error(t.error||`HTTP ${i.status}`)}const c=await i.json();return n(t=>[c,...t]),c},[t]),refetch:u}}function H({children:n,redirectTo:r,roles:a,loadingComponent:o,unauthorizedComponent:s,unauthenticatedComponent:i}){const{user:c,isLoading:l,isAuthenticated:d}=u();if(l)return t(e,{children:o||null});if(!d)return r&&"undefined"!=typeof window?(window.location.replace(r),null):t(e,{children:i||null});if(a&&a.length>0){const n=c?.role;if(!n||!a.includes(n))return t(e,{children:s||null})}return t(e,{children:n})}export{l as DypaiProvider,H as ProtectedRoute,y as generateChatId,m as getMessageText,b as getToolCalls,p as useAction,h as useAuth,W as useChannel,_ as useChannelMessages,z as useChannels,E as useChat,g as useChatList,u as useDypai,d as useDypaiClient,f as useEndpoint,x as useRealtime,w as useUpload};
1
+ import{jsx as t,Fragment as e}from"react/jsx-runtime";import{createContext as n,useState as r,useEffect as o,useContext as a,useCallback as s,useRef as i}from"react";const c=n(null);function l({client:e,children:n}){const[a,s]=r(null),[i,l]=r(null),[u,d]=r(!0),[f,p]=r(null);o(()=>{const{data:{subscription:t}}=e.auth.onAuthStateChange((t,e)=>{p(t),"SIGNED_IN"===t||"TOKEN_REFRESHED"===t||"INITIAL_SESSION"===t?(l(e??null),s(e?.user??null),d(!1)):"SIGNED_OUT"===t?(l(null),s(null),d(!1)):"PASSWORD_RECOVERY"===t?(l(e??null),s(e?.user??null),d(!1)):"AUTH_ERROR"===t?d(!1):"USER_UPDATED"===t&&e&&(l(e),s(e.user??null))});return()=>{t?.unsubscribe()}},[e]);const h={client:e,user:a,session:i,isLoading:u,isAuthenticated:!!a,authEvent:f};return t(c.Provider,{value:h,children:n})}function u(){const t=a(c);if(!t)throw new Error('useDypai must be used within a <DypaiProvider>. Wrap your app with <DypaiProvider url="...">.');return t}function d(){return u().client}function f(){const{client:t,user:e,isLoading:n,isAuthenticated:r,authEvent:o}=u(),a=s(async(e,n)=>{const{error:r}=await t.auth.signInWithPassword({email:e,password:n});return{error:r}},[t]),i=s(async(e,n,r)=>{const{data:o,error:a}=await t.auth.signUp({email:e,password:n,...r});return{error:a,confirmationRequired:o?.confirmationRequired}},[t]),c=s(async()=>{await t.auth.signOut()},[t]),l=s(async(e,n)=>{const{error:r}=await t.auth.resetPasswordForEmail(e,n);return{error:r}},[t]),d=s(async e=>{const{error:n}=await t.auth.setPassword(e);return{error:n}},[t]),f=s(async e=>{await t.auth.signInWithOAuth(e)},[t]),p=s(async e=>{const{error:n}=await t.auth.signInWithOtp({email:e});return{error:n}},[t]),h=s(async e=>{const{error:n}=await t.auth.signInWithMagicLink(e);return{error:n}},[t]),y=s(async()=>{const{data:e,error:n}=await t.auth.enableTwoFactor();return{data:e,error:n}},[t]),w=s(async e=>{const{error:n}=await t.auth.verifyTwoFactor(e);return{error:n}},[t]),m=s(async()=>{const{error:e}=await t.auth.disableTwoFactor();return{error:e}},[t]),g=s(async(e,n)=>{const{data:r,error:o}=await t.auth.createOrganization(e,n);return{data:r,error:o}},[t]),b=s(async()=>{const{data:e,error:n}=await t.auth.listOrganizations();return{data:e,error:n}},[t]),v=s(async(e,n,r)=>{const{error:o}=await t.auth.inviteMember(e,n,r);return{error:o}},[t]);return{user:e,isLoading:n,isAuthenticated:r,authEvent:o,lastError:t.auth.lastError,isPasswordRecovery:t.auth.isPasswordRecoveryCallback||t.auth.hasPasswordRecoveryToken,signIn:a,signUp:i,signOut:c,resetPassword:l,setPassword:d,signInWithOAuth:f,signInWithOtp:p,signInWithMagicLink:h,enableTwoFactor:y,verifyTwoFactor:w,disableTwoFactor:m,createOrganization:g,listOrganizations:b,inviteMember:v}}function p(t,e={}){const n=d(),{params:a,enabled:c=!0,refetchInterval:l=0}=e,[u,f]=r(null),[p,h]=r(null),[y,w]=r(!0),[m,g]=r(!1),b=i(!0),v=JSON.stringify(a||{}),S=s(async(e=!1)=>{if(!c)return void w(!1);e?g(!0):w(!0),h(null);const{data:r,error:o}=await n.api.get(t,{params:a});b.current&&(o?(h(o),f(null)):f(r),w(!1),g(!1))},[n,t,v,c]);return o(()=>(b.current=!0,S(),()=>{b.current=!1}),[S]),o(()=>{if(!l||!c)return;const t=setInterval(()=>S(!0),l);return()=>clearInterval(t)},[S,l,c]),{data:u,error:p,isLoading:y,isRefetching:m,refetch:s(async()=>{await S(!0)},[S])}}function h(t,e={}){const n=d(),{method:o="POST",onSuccess:a,onError:i}=e,[c,l]=r(null),[u,f]=r(null),[p,h]=r(!1);return{mutate:s(async e=>{let r;switch(h(!0),f(null),o){case"PUT":r=await n.api.put(t,e);break;case"PATCH":r=await n.api.patch(t,e);break;case"DELETE":r=await n.api.delete(t,{params:e});break;default:r=await n.api.post(t,e)}return h(!1),r.error?(f(r.error),i?.(r.error),{data:null,error:r.error}):(l(r.data),a?.(r.data),{data:r.data,error:null})},[n,t,o,a,i]),data:c,error:u,isLoading:p,reset:s(()=>{l(null),f(null),h(!1)},[])}}function y(t,e={}){const n=d(),{onSuccess:o,onError:a}=e,[i,c]=r(0),[l,u]=r(!1),[f,p]=r(null),[h,y]=r(null);return{upload:s(async(e,r)=>{u(!0),c(0),p(null);const{data:s,error:i}=await n.api.upload(t,e,{params:r,onProgress:c});return u(!1),i?(p(i),a?.(i),{data:null,error:i}):(y(s),o?.(s),{data:s,error:null})},[n,t,o,a]),progress:i,isUploading:l,error:f,data:h,reset:s(()=>{c(0),u(!1),p(null),y(null)},[])}}function w(){return crypto.randomUUID?.()||`${Date.now()}-${Math.random().toString(36).slice(2)}`}function m(t){return t.parts?.length?t.parts.filter(t=>"text"===t.type).map(t=>t.text||"").join(""):t.content||""}function g(t){return t.parts?.length?t.parts.filter(t=>"tool-call"===t.type).map(t=>({toolName:t.toolName||"unknown",args:t.args})):[]}function b(){return w()}function v(t){const e=t.trim();if(!e||"[DONE]"===e)return null;if(/^[a-z0-9]:/.test(e)){const t=e[0],n=e.slice(2);if("0"===t){const t=JSON.parse(n);return"string"==typeof t?{type:"text-delta",delta:t}:null}if("9"===t){const t=JSON.parse(n);return{type:"tool-call",toolName:String(t?.toolName||t?.function?.name||"tool"),args:t?.args??t?.arguments??t?.input??{}}}if("e"===t){const t=JSON.parse(n);throw new Error(t?.errorText||t?.message||"AI stream error")}return null}const n=JSON.parse(e);switch(n?.type){case"text-delta":return"string"==typeof n.delta?{type:"text-delta",delta:n.delta}:null;case"text":return"string"==typeof n.text?{type:"text-delta",delta:n.text}:null;case"tool-input-available":return{type:"tool-call",toolName:String(n.toolName||"tool"),args:n.input??{}};case"tool-output-available":return{type:"tool-result",toolName:String(n.toolName||n.toolCallId||"tool"),result:n.output};case"error":throw new Error(n.errorText||n.message||"AI stream error");default:return null}}function S(t){const e=t.split(/\r?\n/).filter(t=>t.startsWith("data:")).map(t=>t.slice(5).trimStart());return e.length>0?[e.join("\n")]:[]}function E(t){const e=t.split(/\r?\n/),n=e.pop()||"";return{payloads:e.map(t=>t.trim()).filter(Boolean),rest:n}}function T(t,e={}){const n=d(),[a,c]=r(e.id||b),[l,u]=r(e.initialMessages||[]),[f,p]=r("ready"),[h,y]=r(""),[w,m]=r(null),g=i(null);o(()=>{if(!1===e.loadHistory)return;if(!e.id)return;let t=!1;return(async()=>{try{const e=n.baseUrl,r=n.getAuthToken()||"",o=await fetch(`${e}/api/v0/chats/${a}/messages?limit=50`,{headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"}});if(!o.ok||t)return;const s=await o.json();if(s.messages&&!t){const t=s.messages.map(t=>({id:t.id,role:t.role,content:(t.parts||[]).filter(t=>"text"===t.type).map(t=>t.text).join(""),parts:t.parts,metadata:t.metadata,createdAt:new Date(t.created_at)}));u(t)}}catch{}})(),()=>{t=!0}},[a,e.id,e.loadHistory]);const T=s(async r=>{const o=r||h;if(!o.trim())return;r||y(""),m(null);const s={id:b(),role:"user",content:o,parts:[{type:"text",text:o}],createdAt:new Date},i=[...l,s];u(i),p("submitted");const c={id:b(),role:"assistant",content:"",parts:[],createdAt:new Date};try{const r=n.baseUrl,s=n.getAuthToken()||"",l=new AbortController;g.current=l;const f={session_id:a,messages:[{role:"user",content:o}],...e.body||{}},h=await fetch(`${r}/api/v0/${t}`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",Accept:"text/event-stream",...e.headers||{}},body:JSON.stringify(f),signal:l.signal});if(!h.ok){const t=await h.json().catch(()=>({error:h.statusText}));throw new Error(t.error||`HTTP ${h.status}`)}if((h.headers.get("content-type")||"").includes("application/json")){const t=function(t){if("string"==typeof t?.content)return t.content;if("string"==typeof t?.text)return t.text;const e=Array.isArray(t?.messages)?t.messages:[],n=e[e.length-1],r=n?.content;if("string"==typeof r)return r;if(Array.isArray(r)){const t=r.filter(t=>"text"===t?.type).map(t=>t.text||"").join("");if(t)return t}return JSON.stringify(t)}(await h.json());c.content=t,c.parts=[{type:"text",text:t}];const n=[...i,{...c}];return u(n),p("ready"),void e.onFinish?.(c,n)}p("streaming"),u([...i,c]);const y=h.body?.getReader();if(!y)throw new Error("No response body");const w=new TextDecoder;let m="",b="";const T=[],A="v1"===(d=h.headers).get("x-vercel-ai-ui-message-stream")?"ui-message":"v1"===d.get("x-vercel-ai-data-stream")?"legacy-data":null,$=()=>{c.content=m,c.parts=[...m?[{type:"text",text:m}]:[],...T],u([...i,{...c}])},O=t=>{if(t)return"text-delta"===t.type?(m+=t.delta,void $()):"tool-call"===t.type?(T.push({type:"tool-call",toolName:t.toolName,args:t.args}),e.onToolCall?.({toolName:t.toolName,args:t.args}),void $()):void("tool-result"===t.type&&(T.push({type:"tool-result",toolName:t.toolName,result:t.result}),$()))};for(;;){const{done:t,value:e}=await y.read();if(t)break;const n=w.decode(e,{stream:!0});if("ui-message"===A){b+=n;const t=b.split(/\r?\n\r?\n/);b=t.pop()||"";for(const e of t)for(const t of S(e))O(v(t));continue}if("legacy-data"===A){b+=n;const{payloads:t,rest:e}=E(b);b=e;for(const e of t)O(v(e));continue}const r=n.split("\n").filter(t=>!/^[A-Z][a-zA-Z-]+:\s/.test(t)).join("\n");r&&(m+=r,$())}if("ui-message"===A&&b.trim())for(const t of S(b))O(v(t));else if("legacy-data"===A&&b.trim())for(const t of[b.trim()])O(v(t));const N={...c,content:m,parts:c.parts?.length?c.parts:[{type:"text",text:m}]},I=[...i,N];u(I),p("ready"),e.onFinish?.(N,I)}catch(t){if("AbortError"===t.name)return void p("ready");m(t),p("error"),e.onError?.(t)}finally{g.current=null}var d},[h,l,a,t,n,e]),A=s(()=>{g.current?.abort(),g.current=null,p("ready")},[]),$=s(()=>{A(),u([]),m(null),p("ready"),y(""),c(b())},[A]);return{messages:l,status:f,input:h,setInput:y,sendMessage:T,setMessages:u,stop:A,newChat:$,isLoading:"submitted"===f||"streaming"===f,error:w,chatId:a}}function A(t={}){const e=d(),{endpointId:n,limit:a=20,enabled:i=!0}=t,[c,l]=r([]),[u,f]=r(!1),[p,h]=r(null),y=s(async()=>{f(!0),h(null);try{const t=e.baseUrl,r=e.getAuthToken()||"",o=new URLSearchParams({limit:String(a)});n&&o.set("endpoint_id",n);const s=await fetch(`${t}/api/v0/chats?${o}`,{headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"}});if(!s.ok){const t=await s.json().catch(()=>({}));throw new Error(t.error||`HTTP ${s.status}`)}const i=((await s.json()).chats||[]).map(t=>({id:t.id,title:t.title,visibility:t.visibility,messageCount:parseInt(t.message_count||"0"),createdAt:t.created_at,updatedAt:t.updated_at}));l(i)}catch(t){h(t)}finally{f(!1)}},[e,n,a]),w=s(async t=>{const n=e.baseUrl,r=e.getAuthToken()||"",o=await fetch(`${n}/api/v0/chats/${t}`,{method:"DELETE",headers:{Authorization:`Bearer ${r}`}});if(!o.ok){const t=await o.json().catch(()=>({}));throw new Error(t.error||`HTTP ${o.status}`)}l(e=>e.filter(e=>e.id!==t))},[e]),m=s(async(t,n)=>{const r=e.baseUrl,o=e.getAuthToken()||"",a=await fetch(`${r}/api/v0/chats/${t}`,{method:"PATCH",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({title:n})});if(!a.ok){const t=await a.json().catch(()=>({}));throw new Error(t.error||`HTTP ${a.status}`)}l(e=>e.map(e=>e.id===t?{...e,title:n}:e))},[e]);return o(()=>{i&&y()},[i,y]),{chats:c,isLoading:u,error:p,refetch:y,deleteChat:w,renameChat:m}}let $=null,O="disconnected",N=null,I=null,P=0,C="",x="";const D=[1e3,2e3,5e3,1e4,3e4],J=new Set,L=[],R=[];function k(t,e){if($&&($.readyState===WebSocket.OPEN||$.readyState===WebSocket.CONNECTING))return $;C=t,x=e;const n=t.replace(/^http/,"ws")+`/realtime?token=${encodeURIComponent(e)}`,r=new WebSocket(n);return $=r,O="connecting",r.onopen=()=>{O="connected",P=0;for(const t of L)r.send(JSON.stringify({type:"subscribe",...t}));for(const t of R)r.send(JSON.stringify({type:"join",...t}));I&&clearInterval(I),I=setInterval(()=>{r.readyState===WebSocket.OPEN&&r.send(JSON.stringify({type:"heartbeat"}))},25e3)},r.onmessage=t=>{try{const e=JSON.parse("string"==typeof t.data?t.data:"");for(const t of J)t(e)}catch{}},r.onclose=()=>{if(O="disconnected",$=null,I&&clearInterval(I),J.size>0&&!N){const t=D[Math.min(P,D.length-1)];P++,N=setTimeout(()=>{N=null,J.size>0&&C&&x&&k(C,x)},t)}},r.onerror=()=>{O="error"},r}function j(t){return J.add(t),()=>{J.delete(t),0===J.size&&$&&($.close(),$=null)}}function z(t){return!(!$||$.readyState!==WebSocket.OPEN||($.send(JSON.stringify(t)),0))}function W(t,e={}){const n=d(),{event:a="*",filter:s,enabled:c=!0}=e,[l,u]=r([]),[f,p]=r("disconnected"),[h,y]=r(null),w=i(e);return w.current=e,o(()=>{if(!c)return;const e=n.baseUrl,r=n.getAuthToken()||"";if(!r)return void y(new Error("Authentication required for realtime"));const o=k(e,r);p(O),function(t){const e=L.findIndex(e=>e.table===t.table);e>=0&&L.splice(e,1),L.push(t)}({table:t,event:a,filter:s});const i=()=>{o.readyState===WebSocket.OPEN&&(o.send(JSON.stringify({type:"subscribe",table:t,event:a,filter:s})),p("connected"))};o.readyState===WebSocket.OPEN?i():o.addEventListener("open",i,{once:!0});const l=j(e=>{if("connected"!==e.type&&"subscribe"!==e.type||p("connected"),"change"!==e.type||e.table!==t)return;if("*"!==a&&e.event!==a)return;const n={table:e.table,event:e.event,record:e.record??null,old_record:e.old_record??null,timestamp:e.timestamp,truncated:e.truncated};u(t=>[...t.slice(-99),n]),w.current.onChange?.(n),e.truncated?("INSERT"===e.event&&w.current.onInsert?.(null),"UPDATE"===e.event&&w.current.onUpdate?.(null,null),"DELETE"===e.event&&w.current.onDelete?.(null)):("INSERT"===e.event&&e.record&&w.current.onInsert?.(e.record),"UPDATE"===e.event&&e.record&&w.current.onUpdate?.(e.record,e.old_record),"DELETE"===e.event&&e.old_record&&w.current.onDelete?.(e.old_record))});return()=>{l(),function(t){const e=L.findIndex(e=>e.table===t);e>=0&&L.splice(e,1)}(t),z({type:"unsubscribe",table:t})}},[t,a,c,n]),{changes:l,isConnected:"connected"===f,status:f,error:h}}function _(t,e={}){const n=d(),{presence:a,enabled:c=!0}=e,[l,u]=r({}),[f,p]=r(!1),h=i(e);return h.current=e,o(()=>{if(!c||!t)return;const e=n.baseUrl,r=n.getAuthToken()||"";if(!r)return;const o=k(e,r);!function(t){const e=R.findIndex(e=>e.channel===t.channel);e>=0&&R.splice(e,1),R.push(t)}({channel:t,presence:a||void 0});const s=()=>{o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({type:"join",channel:t,presence:a||void 0}))};o.readyState===WebSocket.OPEN?s():o.addEventListener("open",s,{once:!0});const i=j(e=>{"connected"!==e.type&&"join"!==e.type||p(!0),"broadcast"===e.type&&e.channel===t&&h.current.onBroadcast?.({event:e.event,payload:e.payload,sender:e.sender,timestamp:e.timestamp}),"presence_state"===e.type&&e.channel===t&&u(e.presences||{}),"presence_diff"===e.type&&e.channel===t&&u(t=>{const n={...t};if(e.joins)for(const[t,r]of Object.entries(e.joins))n[t]=r,h.current.onJoin?.(t,r);if(e.leaves)for(const[t,r]of Object.entries(e.leaves))delete n[t],h.current.onLeave?.(t,r);return n})});return()=>{i(),function(t){const e=R.findIndex(e=>e.channel===t);e>=0&&R.splice(e,1)}(t),z({type:"leave",channel:t}),p(!1)}},[t,c,n]),{broadcast:s((e,n)=>{z({type:"broadcast",channel:t,event:e,payload:n})},[t]),presences:l,isConnected:f,memberCount:Object.keys(l).length}}function H(t,e={}){const n=d(),{loadHistory:a=!0,limit:c=50}=e,[l,u]=r([]),[f,p]=r(!1),[h,y]=r(null),w=i(new Set);o(()=>{if(!a||!t)return;let e=!1;return(async()=>{p(!0);try{const r=n.baseUrl,o=n.getAuthToken()||"",a=await fetch(`${r}/api/v0/channels/${t}/messages?limit=${c}`,{headers:{Authorization:`Bearer ${o}`}});if(!a.ok)throw new Error(`HTTP ${a.status}`);const s=await a.json();if(!e&&s.messages){const t=s.messages;t.forEach(t=>w.current.add(t.id)),u(t)}}catch(t){e||y(t)}finally{e||p(!1)}})(),()=>{e=!0}},[t,a,c,n]);const{isConnected:m}=W("channel_messages",{event:"INSERT",filter:{channel_id:t},onInsert:t=>{t&&(w.current.has(t.id)||(w.current.add(t.id),u(e=>[...e,t])))}});return{messages:l,send:s(async(e,r)=>{try{const o=n.baseUrl,a=n.getAuthToken()||"",s=await fetch(`${o}/api/v0/channels/${t}/messages`,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({content:e,metadata:r})});if(!s.ok){const t=await s.json().catch(()=>({}));throw new Error(t.error||`HTTP ${s.status}`)}const i=await s.json();i.message&&(w.current.add(i.message.id),u(t=>[...t,i.message]))}catch(t){throw y(t),t}},[t,n]),isLoading:f,isConnected:m,error:h}}function U(){const t=d(),[e,n]=r([]),[a,i]=r(!1),[c,l]=r(null),u=s(async()=>{i(!0);try{const e=t.baseUrl,r=t.getAuthToken()||"",o=await fetch(`${e}/api/v0/channels`,{headers:{Authorization:`Bearer ${r}`}});if(!o.ok)throw new Error(`HTTP ${o.status}`);const a=await o.json();n(a.channels||[])}catch(t){l(t)}finally{i(!1)}},[t]);return o(()=>{u()},[u]),{channels:e,isLoading:a,error:c,createChannel:s(async(e,r=[],o="group")=>{const a=t.baseUrl,s=t.getAuthToken()||"",i=await fetch(`${a}/api/v0/channels`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({name:e,type:o,members:r})});if(!i.ok){const t=await i.json().catch(()=>({}));throw new Error(t.error||`HTTP ${i.status}`)}const c=await i.json();return n(t=>[c,...t]),c},[t]),refetch:u}}function B({children:n,redirectTo:r,roles:o,loadingComponent:a,unauthorizedComponent:s,unauthenticatedComponent:i}){const{user:c,isLoading:l,isAuthenticated:d}=u();if(l)return t(e,{children:a||null});if(!d)return r&&"undefined"!=typeof window?(window.location.replace(r),null):t(e,{children:i||null});if(o&&o.length>0){const n=c?.role;if(!n||!o.includes(n))return t(e,{children:s||null})}return t(e,{children:n})}export{l as DypaiProvider,B as ProtectedRoute,w as generateChatId,m as getMessageText,g as getToolCalls,h as useAction,f as useAuth,_ as useChannel,H as useChannelMessages,U as useChannels,T as useChat,A as useChatList,u as useDypai,d as useDypaiClient,p as useEndpoint,W as useRealtime,y as useUpload};
@@ -1 +1 @@
1
- "use strict";var jsxRuntime=require("react/jsx-runtime"),react=require("react");const DypaiContext=react.createContext(null);function useDypai(){const e=react.useContext(DypaiContext);if(!e)throw new Error('useDypai must be used within a <DypaiProvider>. Wrap your app with <DypaiProvider url="...">.');return e}function useDypaiClient(){return useDypai().client}function generateChatId(){return crypto.randomUUID?.()||`${Date.now()}-${Math.random().toString(36).slice(2)}`}function generateId(){return generateChatId()}let sharedWs=null,sharedWsStatus="disconnected",reconnectTimer=null,heartbeatTimer=null,reconnectAttempt=0,currentBaseUrl="",currentToken="";const RECONNECT_INTERVALS=[1e3,2e3,5e3,1e4,3e4],messageHandlers=new Set,pendingSubscriptions=[],pendingChannelJoins=[];function getOrCreateSharedWs(e,t){if(sharedWs&&(sharedWs.readyState===WebSocket.OPEN||sharedWs.readyState===WebSocket.CONNECTING))return sharedWs;currentBaseUrl=e,currentToken=t;const r=e.replace(/^http/,"ws")+`/realtime?token=${encodeURIComponent(t)}`,n=new WebSocket(r);return sharedWs=n,sharedWsStatus="connecting",n.onopen=()=>{sharedWsStatus="connected",reconnectAttempt=0;for(const e of pendingSubscriptions)n.send(JSON.stringify({type:"subscribe",...e}));for(const e of pendingChannelJoins)n.send(JSON.stringify({type:"join",...e}));heartbeatTimer&&clearInterval(heartbeatTimer),heartbeatTimer=setInterval(()=>{n.readyState===WebSocket.OPEN&&n.send(JSON.stringify({type:"heartbeat"}))},25e3)},n.onmessage=e=>{try{const t=JSON.parse("string"==typeof e.data?e.data:"");for(const e of messageHandlers)e(t)}catch{}},n.onclose=()=>{if(sharedWsStatus="disconnected",sharedWs=null,heartbeatTimer&&clearInterval(heartbeatTimer),messageHandlers.size>0&&!reconnectTimer){const e=RECONNECT_INTERVALS[Math.min(reconnectAttempt,RECONNECT_INTERVALS.length-1)];reconnectAttempt++,reconnectTimer=setTimeout(()=>{reconnectTimer=null,messageHandlers.size>0&&currentBaseUrl&&currentToken&&getOrCreateSharedWs(currentBaseUrl,currentToken)},e)}},n.onerror=()=>{sharedWsStatus="error"},n}function addMessageHandler(e){return messageHandlers.add(e),()=>{messageHandlers.delete(e),0===messageHandlers.size&&sharedWs&&(sharedWs.close(),sharedWs=null)}}function sendMessage(e){return!(!sharedWs||sharedWs.readyState!==WebSocket.OPEN||(sharedWs.send(JSON.stringify(e)),0))}function useRealtime(e,t={}){const r=useDypaiClient(),{event:n="*",filter:a,enabled:s=!0}=t,[o,c]=react.useState([]),[i,u]=react.useState("disconnected"),[l,d]=react.useState(null),p=react.useRef(t);return p.current=t,react.useEffect(()=>{if(!s)return;const t=r.baseUrl,o=r.getAuthToken()||"";if(!o)return void d(new Error("Authentication required for realtime"));const i=getOrCreateSharedWs(t,o);u(sharedWsStatus),function(e){const t=pendingSubscriptions.findIndex(t=>t.table===e.table);t>=0&&pendingSubscriptions.splice(t,1),pendingSubscriptions.push(e)}({table:e,event:n,filter:a});const l=()=>{i.readyState===WebSocket.OPEN&&(i.send(JSON.stringify({type:"subscribe",table:e,event:n,filter:a})),u("connected"))};i.readyState===WebSocket.OPEN?l():i.addEventListener("open",l,{once:!0});const h=addMessageHandler(t=>{if("connected"!==t.type&&"subscribe"!==t.type||u("connected"),"change"!==t.type||t.table!==e)return;if("*"!==n&&t.event!==n)return;const r={table:t.table,event:t.event,record:t.record??null,old_record:t.old_record??null,timestamp:t.timestamp,truncated:t.truncated};c(e=>[...e.slice(-99),r]),p.current.onChange?.(r),t.truncated?("INSERT"===t.event&&p.current.onInsert?.(null),"UPDATE"===t.event&&p.current.onUpdate?.(null,null),"DELETE"===t.event&&p.current.onDelete?.(null)):("INSERT"===t.event&&t.record&&p.current.onInsert?.(t.record),"UPDATE"===t.event&&t.record&&p.current.onUpdate?.(t.record,t.old_record),"DELETE"===t.event&&t.old_record&&p.current.onDelete?.(t.old_record))});return()=>{h(),function(e){const t=pendingSubscriptions.findIndex(t=>t.table===e);t>=0&&pendingSubscriptions.splice(t,1)}(e),sendMessage({type:"unsubscribe",table:e})}},[e,n,s,r]),{changes:o,isConnected:"connected"===i,status:i,error:l}}exports.DypaiProvider=function({client:e,children:t}){const[r,n]=react.useState(null),[a,s]=react.useState(null),[o,c]=react.useState(!0),[i,u]=react.useState(null);react.useEffect(()=>{const{data:{subscription:t}}=e.auth.onAuthStateChange((e,t)=>{u(e),"SIGNED_IN"===e||"TOKEN_REFRESHED"===e||"INITIAL_SESSION"===e?(s(t??null),n(t?.user??null),c(!1)):"SIGNED_OUT"===e?(s(null),n(null),c(!1)):"PASSWORD_RECOVERY"===e?(s(t??null),n(t?.user??null),c(!1)):"AUTH_ERROR"===e?c(!1):"USER_UPDATED"===e&&t&&(s(t),n(t.user??null))});return()=>{t?.unsubscribe()}},[e]);const l={client:e,user:r,session:a,isLoading:o,isAuthenticated:!!r,authEvent:i};return jsxRuntime.jsx(DypaiContext.Provider,{value:l,children:t})},exports.ProtectedRoute=function({children:e,redirectTo:t,roles:r,loadingComponent:n,unauthorizedComponent:a,unauthenticatedComponent:s}){const{user:o,isLoading:c,isAuthenticated:i}=useDypai();if(c)return jsxRuntime.jsx(jsxRuntime.Fragment,{children:n||null});if(!i)return t&&"undefined"!=typeof window?(window.location.replace(t),null):jsxRuntime.jsx(jsxRuntime.Fragment,{children:s||null});if(r&&r.length>0){const e=o?.role;if(!e||!r.includes(e))return jsxRuntime.jsx(jsxRuntime.Fragment,{children:a||null})}return jsxRuntime.jsx(jsxRuntime.Fragment,{children:e})},exports.generateChatId=generateChatId,exports.getMessageText=function(e){return e.parts?.length?e.parts.filter(e=>"text"===e.type).map(e=>e.text||"").join(""):e.content||""},exports.getToolCalls=function(e){return e.parts?.length?e.parts.filter(e=>"tool-call"===e.type).map(e=>({toolName:e.toolName||"unknown",args:e.args})):[]},exports.useAction=function(e,t={}){const r=useDypaiClient(),{method:n="POST",onSuccess:a,onError:s}=t,[o,c]=react.useState(null),[i,u]=react.useState(null),[l,d]=react.useState(!1);return{mutate:react.useCallback(async t=>{let o;switch(d(!0),u(null),n){case"PUT":o=await r.api.put(e,t);break;case"PATCH":o=await r.api.patch(e,t);break;case"DELETE":o=await r.api.delete(e,{params:t});break;default:o=await r.api.post(e,t)}return d(!1),o.error?(u(o.error),s?.(o.error),{data:null,error:o.error}):(c(o.data),a?.(o.data),{data:o.data,error:null})},[r,e,n,a,s]),data:o,error:i,isLoading:l,reset:react.useCallback(()=>{c(null),u(null),d(!1)},[])}},exports.useAuth=function(){const{client:e,user:t,isLoading:r,isAuthenticated:n,authEvent:a}=useDypai(),s=react.useCallback(async(t,r)=>{const{error:n}=await e.auth.signInWithPassword({email:t,password:r});return{error:n}},[e]),o=react.useCallback(async(t,r,n)=>{const{data:a,error:s}=await e.auth.signUp({email:t,password:r,...n});return{error:s,confirmationRequired:a?.confirmationRequired}},[e]),c=react.useCallback(async()=>{await e.auth.signOut()},[e]),i=react.useCallback(async(t,r)=>{const{error:n}=await e.auth.resetPasswordForEmail(t,r);return{error:n}},[e]),u=react.useCallback(async t=>{const{error:r}=await e.auth.setPassword(t);return{error:r}},[e]),l=react.useCallback(async t=>{await e.auth.signInWithOAuth(t)},[e]),d=react.useCallback(async t=>{const{error:r}=await e.auth.signInWithOtp({email:t});return{error:r}},[e]),p=react.useCallback(async t=>{const{error:r}=await e.auth.signInWithMagicLink(t);return{error:r}},[e]),h=react.useCallback(async()=>{const{data:t,error:r}=await e.auth.enableTwoFactor();return{data:t,error:r}},[e]),f=react.useCallback(async t=>{const{error:r}=await e.auth.verifyTwoFactor(t);return{error:r}},[e]),y=react.useCallback(async()=>{const{error:t}=await e.auth.disableTwoFactor();return{error:t}},[e]),w=react.useCallback(async(t,r)=>{const{data:n,error:a}=await e.auth.createOrganization(t,r);return{data:n,error:a}},[e]),m=react.useCallback(async()=>{const{data:t,error:r}=await e.auth.listOrganizations();return{data:t,error:r}},[e]),g=react.useCallback(async(t,r,n)=>{const{error:a}=await e.auth.inviteMember(t,r,n);return{error:a}},[e]);return{user:t,isLoading:r,isAuthenticated:n,authEvent:a,lastError:e.auth.lastError,isPasswordRecovery:e.auth.isPasswordRecoveryCallback||e.auth.hasPasswordRecoveryToken,signIn:s,signUp:o,signOut:c,resetPassword:i,setPassword:u,signInWithOAuth:l,signInWithOtp:d,signInWithMagicLink:p,enableTwoFactor:h,verifyTwoFactor:f,disableTwoFactor:y,createOrganization:w,listOrganizations:m,inviteMember:g}},exports.useChannel=function(e,t={}){const r=useDypaiClient(),{presence:n,enabled:a=!0}=t,[s,o]=react.useState({}),[c,i]=react.useState(!1),u=react.useRef(t);return u.current=t,react.useEffect(()=>{if(!a||!e)return;const t=r.baseUrl,s=r.getAuthToken()||"";if(!s)return;const c=getOrCreateSharedWs(t,s);!function(e){const t=pendingChannelJoins.findIndex(t=>t.channel===e.channel);t>=0&&pendingChannelJoins.splice(t,1),pendingChannelJoins.push(e)}({channel:e,presence:n||void 0});const l=()=>{c.readyState===WebSocket.OPEN&&c.send(JSON.stringify({type:"join",channel:e,presence:n||void 0}))};c.readyState===WebSocket.OPEN?l():c.addEventListener("open",l,{once:!0});const d=addMessageHandler(t=>{"connected"!==t.type&&"join"!==t.type||i(!0),"broadcast"===t.type&&t.channel===e&&u.current.onBroadcast?.({event:t.event,payload:t.payload,sender:t.sender,timestamp:t.timestamp}),"presence_state"===t.type&&t.channel===e&&o(t.presences||{}),"presence_diff"===t.type&&t.channel===e&&o(e=>{const r={...e};if(t.joins)for(const[e,n]of Object.entries(t.joins))r[e]=n,u.current.onJoin?.(e,n);if(t.leaves)for(const[e,n]of Object.entries(t.leaves))delete r[e],u.current.onLeave?.(e,n);return r})});return()=>{d(),function(e){const t=pendingChannelJoins.findIndex(t=>t.channel===e);t>=0&&pendingChannelJoins.splice(t,1)}(e),sendMessage({type:"leave",channel:e}),i(!1)}},[e,a,r]),{broadcast:react.useCallback((t,r)=>{sendMessage({type:"broadcast",channel:e,event:t,payload:r})},[e]),presences:s,isConnected:c,memberCount:Object.keys(s).length}},exports.useChannelMessages=function(e,t={}){const r=useDypaiClient(),{loadHistory:n=!0,limit:a=50}=t,[s,o]=react.useState([]),[c,i]=react.useState(!1),[u,l]=react.useState(null),d=react.useRef(new Set);react.useEffect(()=>{if(!n||!e)return;let t=!1;return(async()=>{i(!0);try{const n=r.baseUrl,s=r.getAuthToken()||"",c=await fetch(`${n}/api/v0/channels/${e}/messages?limit=${a}`,{headers:{Authorization:`Bearer ${s}`}});if(!c.ok)throw new Error(`HTTP ${c.status}`);const i=await c.json();if(!t&&i.messages){const e=i.messages;e.forEach(e=>d.current.add(e.id)),o(e)}}catch(e){t||l(e)}finally{t||i(!1)}})(),()=>{t=!0}},[e,n,a,r]);const{isConnected:p}=useRealtime("channel_messages",{event:"INSERT",filter:{channel_id:e},onInsert:e=>{e&&(d.current.has(e.id)||(d.current.add(e.id),o(t=>[...t,e])))}});return{messages:s,send:react.useCallback(async(t,n)=>{try{const a=r.baseUrl,s=r.getAuthToken()||"",c=await fetch(`${a}/api/v0/channels/${e}/messages`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({content:t,metadata:n})});if(!c.ok){const e=await c.json().catch(()=>({}));throw new Error(e.error||`HTTP ${c.status}`)}const i=await c.json();i.message&&(d.current.add(i.message.id),o(e=>[...e,i.message]))}catch(e){throw l(e),e}},[e,r]),isLoading:c,isConnected:p,error:u}},exports.useChannels=function(){const e=useDypaiClient(),[t,r]=react.useState([]),[n,a]=react.useState(!1),[s,o]=react.useState(null),c=react.useCallback(async()=>{a(!0);try{const t=e.baseUrl,n=e.getAuthToken()||"",a=await fetch(`${t}/api/v0/channels`,{headers:{Authorization:`Bearer ${n}`}});if(!a.ok)throw new Error(`HTTP ${a.status}`);const s=await a.json();r(s.channels||[])}catch(e){o(e)}finally{a(!1)}},[e]);return react.useEffect(()=>{c()},[c]),{channels:t,isLoading:n,error:s,createChannel:react.useCallback(async(t,n=[],a="group")=>{const s=e.baseUrl,o=e.getAuthToken()||"",c=await fetch(`${s}/api/v0/channels`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({name:t,type:a,members:n})});if(!c.ok){const e=await c.json().catch(()=>({}));throw new Error(e.error||`HTTP ${c.status}`)}const i=await c.json();return r(e=>[i,...e]),i},[e]),refetch:c}},exports.useChat=function(e,t={}){const r=useDypaiClient(),[n,a]=react.useState(t.id||generateId),[s,o]=react.useState(t.initialMessages||[]),[c,i]=react.useState("ready"),[u,l]=react.useState(""),[d,p]=react.useState(null),h=react.useRef(null);react.useEffect(()=>{if(!1===t.loadHistory)return;if(!t.id)return;let e=!1;return(async()=>{try{const t=r.baseUrl,a=r.getAuthToken()||"",s=await fetch(`${t}/api/v0/chats/${n}/messages?limit=50`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"}});if(!s.ok||e)return;const c=await s.json();if(c.messages&&!e){const e=c.messages.map(e=>({id:e.id,role:e.role,content:(e.parts||[]).filter(e=>"text"===e.type).map(e=>e.text).join(""),parts:e.parts,metadata:e.metadata,createdAt:new Date(e.created_at)}));o(e)}}catch{}})(),()=>{e=!0}},[n,t.id,t.loadHistory]);const f=react.useCallback(async a=>{const c=a||u;if(!c.trim())return;a||l(""),p(null);const d={id:generateId(),role:"user",content:c,parts:[{type:"text",text:c}],createdAt:new Date},f=[...s,d];o(f),i("submitted");const y={id:generateId(),role:"assistant",content:"",parts:[],createdAt:new Date};try{const a=r.baseUrl,s=r.getAuthToken()||"",u=new AbortController;h.current=u;const l={session_id:n,messages:[{role:"user",content:c}],...t.body||{}},d=await fetch(`${a}/api/v0/${e}`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",Accept:"text/event-stream",...t.headers||{}},body:JSON.stringify(l),signal:u.signal});if(!d.ok){const e=await d.json().catch(()=>({error:d.statusText}));throw new Error(e.error||`HTTP ${d.status}`)}if((d.headers.get("content-type")||"").includes("application/json")){const e=await d.json(),r=e.content||e.text||JSON.stringify(e);y.content=r,y.parts=[{type:"text",text:r}];const n=[...f,{...y}];return o(n),i("ready"),void t.onFinish?.(y,n)}i("streaming"),o([...f,y]);const p=d.body?.getReader();if(!p)throw new Error("No response body");const w=new TextDecoder;let m="";for(;;){const{done:e,value:t}=await p.read();if(e)break;const r=w.decode(t,{stream:!0}).split("\n").filter(e=>!/^[A-Z][a-zA-Z-]+:\s/.test(e)).join("\n");r&&(m+=r,y.content=m,y.parts=[{type:"text",text:m}],o([...f,{...y}]))}const g={...y,content:m,parts:[{type:"text",text:m}]},T=[...f,g];o(T),i("ready"),t.onFinish?.(g,T)}catch(e){if("AbortError"===e.name)return void i("ready");p(e),i("error"),t.onError?.(e)}finally{h.current=null}},[u,s,n,e,r,t]),y=react.useCallback(()=>{h.current?.abort(),h.current=null,i("ready")},[]),w=react.useCallback(()=>{y(),o([]),p(null),i("ready"),l(""),a(generateId())},[y]);return{messages:s,status:c,input:u,setInput:l,sendMessage:f,setMessages:o,stop:y,newChat:w,isLoading:"submitted"===c||"streaming"===c,error:d,chatId:n}},exports.useChatList=function(e={}){const t=useDypaiClient(),{endpointId:r,limit:n=20,enabled:a=!0}=e,[s,o]=react.useState([]),[c,i]=react.useState(!1),[u,l]=react.useState(null),d=react.useCallback(async()=>{i(!0),l(null);try{const e=t.baseUrl,a=t.getAuthToken()||"",s=new URLSearchParams({limit:String(n)});r&&s.set("endpoint_id",r);const c=await fetch(`${e}/api/v0/chats?${s}`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"}});if(!c.ok){const e=await c.json().catch(()=>({}));throw new Error(e.error||`HTTP ${c.status}`)}const i=((await c.json()).chats||[]).map(e=>({id:e.id,title:e.title,visibility:e.visibility,messageCount:parseInt(e.message_count||"0"),createdAt:e.created_at,updatedAt:e.updated_at}));o(i)}catch(e){l(e)}finally{i(!1)}},[t,r,n]),p=react.useCallback(async e=>{const r=t.baseUrl,n=t.getAuthToken()||"",a=await fetch(`${r}/api/v0/chats/${e}`,{method:"DELETE",headers:{Authorization:`Bearer ${n}`}});if(!a.ok){const e=await a.json().catch(()=>({}));throw new Error(e.error||`HTTP ${a.status}`)}o(t=>t.filter(t=>t.id!==e))},[t]),h=react.useCallback(async(e,r)=>{const n=t.baseUrl,a=t.getAuthToken()||"",s=await fetch(`${n}/api/v0/chats/${e}`,{method:"PATCH",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({title:r})});if(!s.ok){const e=await s.json().catch(()=>({}));throw new Error(e.error||`HTTP ${s.status}`)}o(t=>t.map(t=>t.id===e?{...t,title:r}:t))},[t]);return react.useEffect(()=>{a&&d()},[a,d]),{chats:s,isLoading:c,error:u,refetch:d,deleteChat:p,renameChat:h}},exports.useDypai=useDypai,exports.useDypaiClient=useDypaiClient,exports.useEndpoint=function(e,t={}){const r=useDypaiClient(),{params:n,enabled:a=!0,refetchInterval:s=0}=t,[o,c]=react.useState(null),[i,u]=react.useState(null),[l,d]=react.useState(!0),[p,h]=react.useState(!1),f=react.useRef(!0),y=JSON.stringify(n||{}),w=react.useCallback(async(t=!1)=>{if(!a)return void d(!1);t?h(!0):d(!0),u(null);const{data:s,error:o}=await r.api.get(e,{params:n});f.current&&(o?(u(o),c(null)):c(s),d(!1),h(!1))},[r,e,y,a]);return react.useEffect(()=>(f.current=!0,w(),()=>{f.current=!1}),[w]),react.useEffect(()=>{if(!s||!a)return;const e=setInterval(()=>w(!0),s);return()=>clearInterval(e)},[w,s,a]),{data:o,error:i,isLoading:l,isRefetching:p,refetch:react.useCallback(async()=>{await w(!0)},[w])}},exports.useRealtime=useRealtime,exports.useUpload=function(e,t={}){const r=useDypaiClient(),{onSuccess:n,onError:a}=t,[s,o]=react.useState(0),[c,i]=react.useState(!1),[u,l]=react.useState(null),[d,p]=react.useState(null);return{upload:react.useCallback(async(t,s)=>{i(!0),o(0),l(null);const{data:c,error:u}=await r.api.upload(e,t,{params:s,onProgress:o});return i(!1),u?(l(u),a?.(u),{data:null,error:u}):(p(c),n?.(c),{data:c,error:null})},[r,e,n,a]),progress:s,isUploading:c,error:u,data:d,reset:react.useCallback(()=>{o(0),i(!1),l(null),p(null)},[])}};
1
+ "use strict";var jsxRuntime=require("react/jsx-runtime"),react=require("react");const DypaiContext=react.createContext(null);function useDypai(){const e=react.useContext(DypaiContext);if(!e)throw new Error('useDypai must be used within a <DypaiProvider>. Wrap your app with <DypaiProvider url="...">.');return e}function useDypaiClient(){return useDypai().client}function generateChatId(){return crypto.randomUUID?.()||`${Date.now()}-${Math.random().toString(36).slice(2)}`}function generateId(){return generateChatId()}function parseAIStreamEvent(e){const t=e.trim();if(!t||"[DONE]"===t)return null;if(/^[a-z0-9]:/.test(t)){const e=t[0],r=t.slice(2);if("0"===e){const e=JSON.parse(r);return"string"==typeof e?{type:"text-delta",delta:e}:null}if("9"===e){const e=JSON.parse(r);return{type:"tool-call",toolName:String(e?.toolName||e?.function?.name||"tool"),args:e?.args??e?.arguments??e?.input??{}}}if("e"===e){const e=JSON.parse(r);throw new Error(e?.errorText||e?.message||"AI stream error")}return null}const r=JSON.parse(t);switch(r?.type){case"text-delta":return"string"==typeof r.delta?{type:"text-delta",delta:r.delta}:null;case"text":return"string"==typeof r.text?{type:"text-delta",delta:r.text}:null;case"tool-input-available":return{type:"tool-call",toolName:String(r.toolName||"tool"),args:r.input??{}};case"tool-output-available":return{type:"tool-result",toolName:String(r.toolName||r.toolCallId||"tool"),result:r.output};case"error":throw new Error(r.errorText||r.message||"AI stream error");default:return null}}function readSSEDataPayloads(e){const t=e.split(/\r?\n/).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trimStart());return t.length>0?[t.join("\n")]:[]}function readLegacyDataPayloads(e){const t=e.split(/\r?\n/),r=t.pop()||"";return{payloads:t.map(e=>e.trim()).filter(Boolean),rest:r}}let sharedWs=null,sharedWsStatus="disconnected",reconnectTimer=null,heartbeatTimer=null,reconnectAttempt=0,currentBaseUrl="",currentToken="";const RECONNECT_INTERVALS=[1e3,2e3,5e3,1e4,3e4],messageHandlers=new Set,pendingSubscriptions=[],pendingChannelJoins=[];function getOrCreateSharedWs(e,t){if(sharedWs&&(sharedWs.readyState===WebSocket.OPEN||sharedWs.readyState===WebSocket.CONNECTING))return sharedWs;currentBaseUrl=e,currentToken=t;const r=e.replace(/^http/,"ws")+`/realtime?token=${encodeURIComponent(t)}`,n=new WebSocket(r);return sharedWs=n,sharedWsStatus="connecting",n.onopen=()=>{sharedWsStatus="connected",reconnectAttempt=0;for(const e of pendingSubscriptions)n.send(JSON.stringify({type:"subscribe",...e}));for(const e of pendingChannelJoins)n.send(JSON.stringify({type:"join",...e}));heartbeatTimer&&clearInterval(heartbeatTimer),heartbeatTimer=setInterval(()=>{n.readyState===WebSocket.OPEN&&n.send(JSON.stringify({type:"heartbeat"}))},25e3)},n.onmessage=e=>{try{const t=JSON.parse("string"==typeof e.data?e.data:"");for(const e of messageHandlers)e(t)}catch{}},n.onclose=()=>{if(sharedWsStatus="disconnected",sharedWs=null,heartbeatTimer&&clearInterval(heartbeatTimer),messageHandlers.size>0&&!reconnectTimer){const e=RECONNECT_INTERVALS[Math.min(reconnectAttempt,RECONNECT_INTERVALS.length-1)];reconnectAttempt++,reconnectTimer=setTimeout(()=>{reconnectTimer=null,messageHandlers.size>0&&currentBaseUrl&&currentToken&&getOrCreateSharedWs(currentBaseUrl,currentToken)},e)}},n.onerror=()=>{sharedWsStatus="error"},n}function addMessageHandler(e){return messageHandlers.add(e),()=>{messageHandlers.delete(e),0===messageHandlers.size&&sharedWs&&(sharedWs.close(),sharedWs=null)}}function sendMessage(e){return!(!sharedWs||sharedWs.readyState!==WebSocket.OPEN||(sharedWs.send(JSON.stringify(e)),0))}function useRealtime(e,t={}){const r=useDypaiClient(),{event:n="*",filter:a,enabled:s=!0}=t,[o,c]=react.useState([]),[i,l]=react.useState("disconnected"),[u,d]=react.useState(null),p=react.useRef(t);return p.current=t,react.useEffect(()=>{if(!s)return;const t=r.baseUrl,o=r.getAuthToken()||"";if(!o)return void d(new Error("Authentication required for realtime"));const i=getOrCreateSharedWs(t,o);l(sharedWsStatus),function(e){const t=pendingSubscriptions.findIndex(t=>t.table===e.table);t>=0&&pendingSubscriptions.splice(t,1),pendingSubscriptions.push(e)}({table:e,event:n,filter:a});const u=()=>{i.readyState===WebSocket.OPEN&&(i.send(JSON.stringify({type:"subscribe",table:e,event:n,filter:a})),l("connected"))};i.readyState===WebSocket.OPEN?u():i.addEventListener("open",u,{once:!0});const h=addMessageHandler(t=>{if("connected"!==t.type&&"subscribe"!==t.type||l("connected"),"change"!==t.type||t.table!==e)return;if("*"!==n&&t.event!==n)return;const r={table:t.table,event:t.event,record:t.record??null,old_record:t.old_record??null,timestamp:t.timestamp,truncated:t.truncated};c(e=>[...e.slice(-99),r]),p.current.onChange?.(r),t.truncated?("INSERT"===t.event&&p.current.onInsert?.(null),"UPDATE"===t.event&&p.current.onUpdate?.(null,null),"DELETE"===t.event&&p.current.onDelete?.(null)):("INSERT"===t.event&&t.record&&p.current.onInsert?.(t.record),"UPDATE"===t.event&&t.record&&p.current.onUpdate?.(t.record,t.old_record),"DELETE"===t.event&&t.old_record&&p.current.onDelete?.(t.old_record))});return()=>{h(),function(e){const t=pendingSubscriptions.findIndex(t=>t.table===e);t>=0&&pendingSubscriptions.splice(t,1)}(e),sendMessage({type:"unsubscribe",table:e})}},[e,n,s,r]),{changes:o,isConnected:"connected"===i,status:i,error:u}}exports.DypaiProvider=function({client:e,children:t}){const[r,n]=react.useState(null),[a,s]=react.useState(null),[o,c]=react.useState(!0),[i,l]=react.useState(null);react.useEffect(()=>{const{data:{subscription:t}}=e.auth.onAuthStateChange((e,t)=>{l(e),"SIGNED_IN"===e||"TOKEN_REFRESHED"===e||"INITIAL_SESSION"===e?(s(t??null),n(t?.user??null),c(!1)):"SIGNED_OUT"===e?(s(null),n(null),c(!1)):"PASSWORD_RECOVERY"===e?(s(t??null),n(t?.user??null),c(!1)):"AUTH_ERROR"===e?c(!1):"USER_UPDATED"===e&&t&&(s(t),n(t.user??null))});return()=>{t?.unsubscribe()}},[e]);const u={client:e,user:r,session:a,isLoading:o,isAuthenticated:!!r,authEvent:i};return jsxRuntime.jsx(DypaiContext.Provider,{value:u,children:t})},exports.ProtectedRoute=function({children:e,redirectTo:t,roles:r,loadingComponent:n,unauthorizedComponent:a,unauthenticatedComponent:s}){const{user:o,isLoading:c,isAuthenticated:i}=useDypai();if(c)return jsxRuntime.jsx(jsxRuntime.Fragment,{children:n||null});if(!i)return t&&"undefined"!=typeof window?(window.location.replace(t),null):jsxRuntime.jsx(jsxRuntime.Fragment,{children:s||null});if(r&&r.length>0){const e=o?.role;if(!e||!r.includes(e))return jsxRuntime.jsx(jsxRuntime.Fragment,{children:a||null})}return jsxRuntime.jsx(jsxRuntime.Fragment,{children:e})},exports.generateChatId=generateChatId,exports.getMessageText=function(e){return e.parts?.length?e.parts.filter(e=>"text"===e.type).map(e=>e.text||"").join(""):e.content||""},exports.getToolCalls=function(e){return e.parts?.length?e.parts.filter(e=>"tool-call"===e.type).map(e=>({toolName:e.toolName||"unknown",args:e.args})):[]},exports.useAction=function(e,t={}){const r=useDypaiClient(),{method:n="POST",onSuccess:a,onError:s}=t,[o,c]=react.useState(null),[i,l]=react.useState(null),[u,d]=react.useState(!1);return{mutate:react.useCallback(async t=>{let o;switch(d(!0),l(null),n){case"PUT":o=await r.api.put(e,t);break;case"PATCH":o=await r.api.patch(e,t);break;case"DELETE":o=await r.api.delete(e,{params:t});break;default:o=await r.api.post(e,t)}return d(!1),o.error?(l(o.error),s?.(o.error),{data:null,error:o.error}):(c(o.data),a?.(o.data),{data:o.data,error:null})},[r,e,n,a,s]),data:o,error:i,isLoading:u,reset:react.useCallback(()=>{c(null),l(null),d(!1)},[])}},exports.useAuth=function(){const{client:e,user:t,isLoading:r,isAuthenticated:n,authEvent:a}=useDypai(),s=react.useCallback(async(t,r)=>{const{error:n}=await e.auth.signInWithPassword({email:t,password:r});return{error:n}},[e]),o=react.useCallback(async(t,r,n)=>{const{data:a,error:s}=await e.auth.signUp({email:t,password:r,...n});return{error:s,confirmationRequired:a?.confirmationRequired}},[e]),c=react.useCallback(async()=>{await e.auth.signOut()},[e]),i=react.useCallback(async(t,r)=>{const{error:n}=await e.auth.resetPasswordForEmail(t,r);return{error:n}},[e]),l=react.useCallback(async t=>{const{error:r}=await e.auth.setPassword(t);return{error:r}},[e]),u=react.useCallback(async t=>{await e.auth.signInWithOAuth(t)},[e]),d=react.useCallback(async t=>{const{error:r}=await e.auth.signInWithOtp({email:t});return{error:r}},[e]),p=react.useCallback(async t=>{const{error:r}=await e.auth.signInWithMagicLink(t);return{error:r}},[e]),h=react.useCallback(async()=>{const{data:t,error:r}=await e.auth.enableTwoFactor();return{data:t,error:r}},[e]),f=react.useCallback(async t=>{const{error:r}=await e.auth.verifyTwoFactor(t);return{error:r}},[e]),y=react.useCallback(async()=>{const{error:t}=await e.auth.disableTwoFactor();return{error:t}},[e]),m=react.useCallback(async(t,r)=>{const{data:n,error:a}=await e.auth.createOrganization(t,r);return{data:n,error:a}},[e]),g=react.useCallback(async()=>{const{data:t,error:r}=await e.auth.listOrganizations();return{data:t,error:r}},[e]),w=react.useCallback(async(t,r,n)=>{const{error:a}=await e.auth.inviteMember(t,r,n);return{error:a}},[e]);return{user:t,isLoading:r,isAuthenticated:n,authEvent:a,lastError:e.auth.lastError,isPasswordRecovery:e.auth.isPasswordRecoveryCallback||e.auth.hasPasswordRecoveryToken,signIn:s,signUp:o,signOut:c,resetPassword:i,setPassword:l,signInWithOAuth:u,signInWithOtp:d,signInWithMagicLink:p,enableTwoFactor:h,verifyTwoFactor:f,disableTwoFactor:y,createOrganization:m,listOrganizations:g,inviteMember:w}},exports.useChannel=function(e,t={}){const r=useDypaiClient(),{presence:n,enabled:a=!0}=t,[s,o]=react.useState({}),[c,i]=react.useState(!1),l=react.useRef(t);return l.current=t,react.useEffect(()=>{if(!a||!e)return;const t=r.baseUrl,s=r.getAuthToken()||"";if(!s)return;const c=getOrCreateSharedWs(t,s);!function(e){const t=pendingChannelJoins.findIndex(t=>t.channel===e.channel);t>=0&&pendingChannelJoins.splice(t,1),pendingChannelJoins.push(e)}({channel:e,presence:n||void 0});const u=()=>{c.readyState===WebSocket.OPEN&&c.send(JSON.stringify({type:"join",channel:e,presence:n||void 0}))};c.readyState===WebSocket.OPEN?u():c.addEventListener("open",u,{once:!0});const d=addMessageHandler(t=>{"connected"!==t.type&&"join"!==t.type||i(!0),"broadcast"===t.type&&t.channel===e&&l.current.onBroadcast?.({event:t.event,payload:t.payload,sender:t.sender,timestamp:t.timestamp}),"presence_state"===t.type&&t.channel===e&&o(t.presences||{}),"presence_diff"===t.type&&t.channel===e&&o(e=>{const r={...e};if(t.joins)for(const[e,n]of Object.entries(t.joins))r[e]=n,l.current.onJoin?.(e,n);if(t.leaves)for(const[e,n]of Object.entries(t.leaves))delete r[e],l.current.onLeave?.(e,n);return r})});return()=>{d(),function(e){const t=pendingChannelJoins.findIndex(t=>t.channel===e);t>=0&&pendingChannelJoins.splice(t,1)}(e),sendMessage({type:"leave",channel:e}),i(!1)}},[e,a,r]),{broadcast:react.useCallback((t,r)=>{sendMessage({type:"broadcast",channel:e,event:t,payload:r})},[e]),presences:s,isConnected:c,memberCount:Object.keys(s).length}},exports.useChannelMessages=function(e,t={}){const r=useDypaiClient(),{loadHistory:n=!0,limit:a=50}=t,[s,o]=react.useState([]),[c,i]=react.useState(!1),[l,u]=react.useState(null),d=react.useRef(new Set);react.useEffect(()=>{if(!n||!e)return;let t=!1;return(async()=>{i(!0);try{const n=r.baseUrl,s=r.getAuthToken()||"",c=await fetch(`${n}/api/v0/channels/${e}/messages?limit=${a}`,{headers:{Authorization:`Bearer ${s}`}});if(!c.ok)throw new Error(`HTTP ${c.status}`);const i=await c.json();if(!t&&i.messages){const e=i.messages;e.forEach(e=>d.current.add(e.id)),o(e)}}catch(e){t||u(e)}finally{t||i(!1)}})(),()=>{t=!0}},[e,n,a,r]);const{isConnected:p}=useRealtime("channel_messages",{event:"INSERT",filter:{channel_id:e},onInsert:e=>{e&&(d.current.has(e.id)||(d.current.add(e.id),o(t=>[...t,e])))}});return{messages:s,send:react.useCallback(async(t,n)=>{try{const a=r.baseUrl,s=r.getAuthToken()||"",c=await fetch(`${a}/api/v0/channels/${e}/messages`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({content:t,metadata:n})});if(!c.ok){const e=await c.json().catch(()=>({}));throw new Error(e.error||`HTTP ${c.status}`)}const i=await c.json();i.message&&(d.current.add(i.message.id),o(e=>[...e,i.message]))}catch(e){throw u(e),e}},[e,r]),isLoading:c,isConnected:p,error:l}},exports.useChannels=function(){const e=useDypaiClient(),[t,r]=react.useState([]),[n,a]=react.useState(!1),[s,o]=react.useState(null),c=react.useCallback(async()=>{a(!0);try{const t=e.baseUrl,n=e.getAuthToken()||"",a=await fetch(`${t}/api/v0/channels`,{headers:{Authorization:`Bearer ${n}`}});if(!a.ok)throw new Error(`HTTP ${a.status}`);const s=await a.json();r(s.channels||[])}catch(e){o(e)}finally{a(!1)}},[e]);return react.useEffect(()=>{c()},[c]),{channels:t,isLoading:n,error:s,createChannel:react.useCallback(async(t,n=[],a="group")=>{const s=e.baseUrl,o=e.getAuthToken()||"",c=await fetch(`${s}/api/v0/channels`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({name:t,type:a,members:n})});if(!c.ok){const e=await c.json().catch(()=>({}));throw new Error(e.error||`HTTP ${c.status}`)}const i=await c.json();return r(e=>[i,...e]),i},[e]),refetch:c}},exports.useChat=function(e,t={}){const r=useDypaiClient(),[n,a]=react.useState(t.id||generateId),[s,o]=react.useState(t.initialMessages||[]),[c,i]=react.useState("ready"),[l,u]=react.useState(""),[d,p]=react.useState(null),h=react.useRef(null);react.useEffect(()=>{if(!1===t.loadHistory)return;if(!t.id)return;let e=!1;return(async()=>{try{const t=r.baseUrl,a=r.getAuthToken()||"",s=await fetch(`${t}/api/v0/chats/${n}/messages?limit=50`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"}});if(!s.ok||e)return;const c=await s.json();if(c.messages&&!e){const e=c.messages.map(e=>({id:e.id,role:e.role,content:(e.parts||[]).filter(e=>"text"===e.type).map(e=>e.text).join(""),parts:e.parts,metadata:e.metadata,createdAt:new Date(e.created_at)}));o(e)}}catch{}})(),()=>{e=!0}},[n,t.id,t.loadHistory]);const f=react.useCallback(async a=>{const c=a||l;if(!c.trim())return;a||u(""),p(null);const d={id:generateId(),role:"user",content:c,parts:[{type:"text",text:c}],createdAt:new Date},f=[...s,d];o(f),i("submitted");const y={id:generateId(),role:"assistant",content:"",parts:[],createdAt:new Date};try{const a=r.baseUrl,s=r.getAuthToken()||"",l=new AbortController;h.current=l;const u={session_id:n,messages:[{role:"user",content:c}],...t.body||{}},d=await fetch(`${a}/api/v0/${e}`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",Accept:"text/event-stream",...t.headers||{}},body:JSON.stringify(u),signal:l.signal});if(!d.ok){const e=await d.json().catch(()=>({error:d.statusText}));throw new Error(e.error||`HTTP ${d.status}`)}if((d.headers.get("content-type")||"").includes("application/json")){const e=function(e){if("string"==typeof e?.content)return e.content;if("string"==typeof e?.text)return e.text;const t=Array.isArray(e?.messages)?e.messages:[],r=t[t.length-1],n=r?.content;if("string"==typeof n)return n;if(Array.isArray(n)){const e=n.filter(e=>"text"===e?.type).map(e=>e.text||"").join("");if(e)return e}return JSON.stringify(e)}(await d.json());y.content=e,y.parts=[{type:"text",text:e}];const r=[...f,{...y}];return o(r),i("ready"),void t.onFinish?.(y,r)}i("streaming"),o([...f,y]);const p=d.body?.getReader();if(!p)throw new Error("No response body");const g=new TextDecoder;let w="",S="";const T=[],b="v1"===(m=d.headers).get("x-vercel-ai-ui-message-stream")?"ui-message":"v1"===m.get("x-vercel-ai-data-stream")?"legacy-data":null,E=()=>{y.content=w,y.parts=[...w?[{type:"text",text:w}]:[],...T],o([...f,{...y}])},C=e=>{if(e)return"text-delta"===e.type?(w+=e.delta,void E()):"tool-call"===e.type?(T.push({type:"tool-call",toolName:e.toolName,args:e.args}),t.onToolCall?.({toolName:e.toolName,args:e.args}),void E()):void("tool-result"===e.type&&(T.push({type:"tool-result",toolName:e.toolName,result:e.result}),E()))};for(;;){const{done:e,value:t}=await p.read();if(e)break;const r=g.decode(t,{stream:!0});if("ui-message"===b){S+=r;const e=S.split(/\r?\n\r?\n/);S=e.pop()||"";for(const t of e)for(const e of readSSEDataPayloads(t))C(parseAIStreamEvent(e));continue}if("legacy-data"===b){S+=r;const{payloads:e,rest:t}=readLegacyDataPayloads(S);S=t;for(const t of e)C(parseAIStreamEvent(t));continue}const n=r.split("\n").filter(e=>!/^[A-Z][a-zA-Z-]+:\s/.test(e)).join("\n");n&&(w+=n,E())}if("ui-message"===b&&S.trim())for(const e of readSSEDataPayloads(S))C(parseAIStreamEvent(e));else if("legacy-data"===b&&S.trim())for(const e of[S.trim()])C(parseAIStreamEvent(e));const v={...y,content:w,parts:y.parts?.length?y.parts:[{type:"text",text:w}]},x=[...f,v];o(x),i("ready"),t.onFinish?.(v,x)}catch(e){if("AbortError"===e.name)return void i("ready");p(e),i("error"),t.onError?.(e)}finally{h.current=null}var m},[l,s,n,e,r,t]),y=react.useCallback(()=>{h.current?.abort(),h.current=null,i("ready")},[]),m=react.useCallback(()=>{y(),o([]),p(null),i("ready"),u(""),a(generateId())},[y]);return{messages:s,status:c,input:l,setInput:u,sendMessage:f,setMessages:o,stop:y,newChat:m,isLoading:"submitted"===c||"streaming"===c,error:d,chatId:n}},exports.useChatList=function(e={}){const t=useDypaiClient(),{endpointId:r,limit:n=20,enabled:a=!0}=e,[s,o]=react.useState([]),[c,i]=react.useState(!1),[l,u]=react.useState(null),d=react.useCallback(async()=>{i(!0),u(null);try{const e=t.baseUrl,a=t.getAuthToken()||"",s=new URLSearchParams({limit:String(n)});r&&s.set("endpoint_id",r);const c=await fetch(`${e}/api/v0/chats?${s}`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"}});if(!c.ok){const e=await c.json().catch(()=>({}));throw new Error(e.error||`HTTP ${c.status}`)}const i=((await c.json()).chats||[]).map(e=>({id:e.id,title:e.title,visibility:e.visibility,messageCount:parseInt(e.message_count||"0"),createdAt:e.created_at,updatedAt:e.updated_at}));o(i)}catch(e){u(e)}finally{i(!1)}},[t,r,n]),p=react.useCallback(async e=>{const r=t.baseUrl,n=t.getAuthToken()||"",a=await fetch(`${r}/api/v0/chats/${e}`,{method:"DELETE",headers:{Authorization:`Bearer ${n}`}});if(!a.ok){const e=await a.json().catch(()=>({}));throw new Error(e.error||`HTTP ${a.status}`)}o(t=>t.filter(t=>t.id!==e))},[t]),h=react.useCallback(async(e,r)=>{const n=t.baseUrl,a=t.getAuthToken()||"",s=await fetch(`${n}/api/v0/chats/${e}`,{method:"PATCH",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({title:r})});if(!s.ok){const e=await s.json().catch(()=>({}));throw new Error(e.error||`HTTP ${s.status}`)}o(t=>t.map(t=>t.id===e?{...t,title:r}:t))},[t]);return react.useEffect(()=>{a&&d()},[a,d]),{chats:s,isLoading:c,error:l,refetch:d,deleteChat:p,renameChat:h}},exports.useDypai=useDypai,exports.useDypaiClient=useDypaiClient,exports.useEndpoint=function(e,t={}){const r=useDypaiClient(),{params:n,enabled:a=!0,refetchInterval:s=0}=t,[o,c]=react.useState(null),[i,l]=react.useState(null),[u,d]=react.useState(!0),[p,h]=react.useState(!1),f=react.useRef(!0),y=JSON.stringify(n||{}),m=react.useCallback(async(t=!1)=>{if(!a)return void d(!1);t?h(!0):d(!0),l(null);const{data:s,error:o}=await r.api.get(e,{params:n});f.current&&(o?(l(o),c(null)):c(s),d(!1),h(!1))},[r,e,y,a]);return react.useEffect(()=>(f.current=!0,m(),()=>{f.current=!1}),[m]),react.useEffect(()=>{if(!s||!a)return;const e=setInterval(()=>m(!0),s);return()=>clearInterval(e)},[m,s,a]),{data:o,error:i,isLoading:u,isRefetching:p,refetch:react.useCallback(async()=>{await m(!0)},[m])}},exports.useRealtime=useRealtime,exports.useUpload=function(e,t={}){const r=useDypaiClient(),{onSuccess:n,onError:a}=t,[s,o]=react.useState(0),[c,i]=react.useState(!1),[l,u]=react.useState(null),[d,p]=react.useState(null);return{upload:react.useCallback(async(t,s)=>{i(!0),o(0),u(null);const{data:c,error:l}=await r.api.upload(e,t,{params:s,onProgress:o});return i(!1),l?(u(l),a?.(l),{data:null,error:l}):(p(c),n?.(c),{data:c,error:null})},[r,e,n,a]),progress:s,isUploading:c,error:l,data:d,reset:react.useCallback(()=>{o(0),i(!1),u(null),p(null)},[])}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dypai-ai/client-sdk",
3
- "version": "1.10.5",
3
+ "version": "1.10.6",
4
4
  "description": "Official JavaScript/TypeScript SDK for DYPAI — backend-as-a-service with visual workflows, AI agents, and MCP.",
5
5
  "type": "module",
6
6
  "private": false,