palbase 0.5.2 → 0.7.0

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.
Files changed (66) hide show
  1. package/dist/ai/index.js +2 -14
  2. package/dist/backend/engine.js +2 -2
  3. package/dist/backend/env.js +1 -1
  4. package/dist/backend/index.js +7 -7
  5. package/dist/backend/stack.js +1 -1
  6. package/dist/backend/test.js +2 -2
  7. package/dist/chunks/3ALGILOX.js +2 -0
  8. package/dist/chunks/{6I6CETZY.js → 5ZJCEQV5.js} +3 -3
  9. package/dist/chunks/AIIKXCWN.js +2 -0
  10. package/dist/chunks/{LHLMCQKI.js → BKVU4I5R.js} +2 -2
  11. package/dist/chunks/ELEE7XO2.js +18 -0
  12. package/dist/chunks/{ZJOO2XZ2.js → G3BK7L3J.js} +2 -2
  13. package/dist/chunks/G7E26S3Y.js +13 -0
  14. package/dist/chunks/H2EPK74V.js +20 -0
  15. package/dist/chunks/{EDVRVUCJ.js → HEXIIGWS.js} +2 -2
  16. package/dist/chunks/{HLYQRT7O.js → JS3TTUHS.js} +2 -2
  17. package/dist/chunks/{NQA7ZLGD.js → KDSWK3XW.js} +1 -1
  18. package/dist/chunks/{XRW7YOUQ.js → L3NTI4AZ.js} +2 -2
  19. package/dist/chunks/LEBVOSG6.js +4 -0
  20. package/dist/chunks/OIA7KLRW.js +2 -0
  21. package/dist/chunks/{4ZVJ62A3.js → PJVWGUIT.js} +1 -1
  22. package/dist/chunks/{MYNCDAKM.js → SU7BP6VF.js} +1 -1
  23. package/dist/chunks/{TPBWIRHS.js → X3MTLJRV.js} +1 -1
  24. package/dist/chunks/{5G3URQAW.js → ZBOJEH7K.js} +2 -2
  25. package/dist/cli.js +133 -133
  26. package/dist/refuse/ai.js +1 -1
  27. package/dist/refuse/backend.js +1 -1
  28. package/dist/refuse/server.js +1 -1
  29. package/dist/server/index.js +2 -2
  30. package/dist/server/testing.js +2 -2
  31. package/dist/web/index.js +2 -2
  32. package/dist/web/palbe.js +2 -2
  33. package/dist/web/paywall.js +2 -2
  34. package/dist/web/ssr.js +2 -0
  35. package/dist/web/vite.js +2 -2
  36. package/package.json +6 -2
  37. package/types/ai/src/ai.d.ts +2 -4
  38. package/types/ai/src/chats.d.ts +40 -10
  39. package/types/ai/src/index.d.ts +2 -2
  40. package/types/ai/src/tools.d.ts +3 -8
  41. package/types/backend/src/container.d.ts +2 -2
  42. package/types/backend/src/engine.d.ts +1 -4
  43. package/types/backend/src/gateways.d.ts +250 -0
  44. package/types/backend/src/index.d.ts +2 -2
  45. package/types/backend/src/openapi.d.ts +3 -6
  46. package/types/backend/src/runtime.d.ts +39 -2
  47. package/types/internal/src/chat.d.ts +7 -39
  48. package/types/internal/src/modules/ai.d.ts +68 -35
  49. package/types/internal/src/modules/realtime.d.ts +9 -1
  50. package/types/web/src/backends.d.ts +19 -12
  51. package/types/web/src/chat.d.ts +118 -0
  52. package/types/web/src/client.d.ts +3 -4
  53. package/types/web/src/gateways.d.ts +89 -0
  54. package/types/web/src/index.d.ts +4 -4
  55. package/types/web/src/session.d.ts +11 -0
  56. package/types/web/src/socket.d.ts +18 -2
  57. package/types/web/src/ssr.d.ts +86 -0
  58. package/dist/chunks/FNUO6DSY.js +0 -4
  59. package/dist/chunks/JHQDWDV3.js +0 -13
  60. package/dist/chunks/K2LVOEW3.js +0 -20
  61. package/dist/chunks/QHJ4OPPI.js +0 -2
  62. package/dist/chunks/QHPZF7VM.js +0 -6
  63. package/types/backend/src/channels.d.ts +0 -81
  64. package/types/backend/src/rooms.d.ts +0 -178
  65. package/types/web/src/ai.d.ts +0 -224
  66. package/types/web/src/rooms.d.ts +0 -61
package/dist/refuse/ai.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
2
  throw new Error("palbase/ai is for servers: it speaks with the project secret key, which never goes into a browser or a mobile app \u2014 call your backend, and let it ask the model");
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
2
  throw new Error("palbase/backend is a server framework: it runs on your backend, never in a browser or a mobile app \u2014 apps use palbase/web (or the native SDKs)");
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
2
  throw new Error("palbase/server is for servers: its secret key never goes into a browser or a mobile app \u2014 apps use palbase/web (or the native SDKs) with the publishable key");
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
2
- import{a as c,b as d,c as e,d as f,e as g,f as h,g as i,h as j,i as k,j as l,k as m,l as n,m as o,n as p,o as q,p as r,q as s,r as t}from"../chunks/XRW7YOUQ.js";import"../chunks/NQA7ZLGD.js";import{m as b}from"../chunks/QHJ4OPPI.js";import"../chunks/5G3URQAW.js";import{b as a}from"../chunks/HLYQRT7O.js";import"../chunks/TPBWIRHS.js";import"../chunks/MYNCDAKM.js";export{j as AuthUnavailable,b as EVENT_TYPES,a as PalbaseError,o as ReservationSettled,i as TokenError,l as TokenVerifier,d as WebhookSignatureError,c as createServer,n as isEntitled,t as loadSecrets,q as pages,s as platformOwn,r as processOwn,m as requestAddress,k as sessionStanding,g as signatureHeader,f as verifySignature,e as verifyWebhook,h as verifyWebhookRequest,p as withReservation};
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import{a as c,b as d,c as e,d as f,e as g,f as h,g as i,h as j,i as k,j as l,k as m,l as n,m as o,n as p,o as q,p as r,q as s,r as t}from"../chunks/L3NTI4AZ.js";import"../chunks/KDSWK3XW.js";import{m as b}from"../chunks/AIIKXCWN.js";import"../chunks/ZBOJEH7K.js";import{b as a}from"../chunks/JS3TTUHS.js";import"../chunks/X3MTLJRV.js";import"../chunks/SU7BP6VF.js";export{j as AuthUnavailable,b as EVENT_TYPES,a as PalbaseError,o as ReservationSettled,i as TokenError,l as TokenVerifier,d as WebhookSignatureError,c as createServer,n as isEntitled,t as loadSecrets,q as pages,s as platformOwn,r as processOwn,m as requestAddress,k as sessionStanding,g as signatureHeader,f as verifySignature,e as verifyWebhook,h as verifyWebhookRequest,p as withReservation};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
2
- import{a,b,c,d}from"../chunks/ZJOO2XZ2.js";import"../chunks/TPBWIRHS.js";import"../chunks/MYNCDAKM.js";export{a as TestApiError,d as api,b as createTestApi,c as testRun};
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import{a,b,c,d}from"../chunks/G3BK7L3J.js";import"../chunks/X3MTLJRV.js";import"../chunks/SU7BP6VF.js";export{a as TestApiError,d as api,b as createTestApi,c as testRun};
package/dist/web/index.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
2
- import{a as de,b as he,e as ue,f as Y,g as z}from"../chunks/JHQDWDV3.js";import{u as Q}from"../chunks/6I6CETZY.js";import{c as E,e as q,f as p,g as Z,h as K}from"../chunks/QHPZF7VM.js";import{a as G,b as D,c as m,h as J}from"../chunks/QHJ4OPPI.js";import{a as W,b as P,c as X}from"../chunks/5G3URQAW.js";import{b as f,d as _}from"../chunks/HLYQRT7O.js";import"../chunks/TPBWIRHS.js";import"../chunks/MYNCDAKM.js";var I=class{api;open;session;credentials;mfa;passkey;magicLink;phone;password;email;sessions;constructor(e,t,s,n){this.api=m.client(e),this.open=m.client(t),this.session=s,this.credentials=n;let r=this.api,o=this.open;this.mfa={challenge:async(a,l,c)=>this.signedIn((await o.mfaChallenge({body:{mfa_token:a,type:l,code:c}})).data),recovery:async(a,l)=>this.signedIn((await o.mfaRecovery({body:{mfa_token:a,code:l}})).data),sendSmsCode:async a=>{await o.mfaSmsChallenge({body:{mfa_token:a}})},sendEmailCode:async a=>{await o.mfaEmailChallenge({body:{mfa_token:a}})},enrollTotp:async()=>{let a=(await r.mfaEnroll({body:{type:"totp"}})).data;return{enrollmentId:a.enrollment_id,secret:a.secret,otpUrl:a.otp_url,qrCode:a.qr_code,recoveryCodes:a.recovery_codes}},verifyTotp:async a=>{await r.mfaVerifyEnrollment({body:{code:a}})},enrollSms:async a=>(await r.mfaSmsEnroll({body:{phone:a}})).data,verifySms:async a=>{await r.mfaSmsVerifyEnrollment({body:{code:a}})},enrollEmail:async()=>{await r.mfaEmailEnroll()},factors:async()=>(await r.mfaListFactors()).data,removeFactor:async(a,l)=>{await r.mfaRemoveFactor({path:{id:a},body:{current_password:l}})},regenerateRecoveryCodes:async()=>(await r.mfaRegenerateRecoveryCodes()).data},this.passkey={register:async a=>{let l=(await r.webauthnRegisterBegin({body:{name:a}})).data,c=await this.authenticator().create({publicKey:ee(l.options.publicKey)});return(await r.webauthnRegisterFinish({body:se(c)})).data},signIn:async(a={})=>{let l=(await o.webauthnLoginBegin({body:a.userId?{user_id:a.userId}:{}})).data,c=await this.authenticator().get({publicKey:te(l.options.publicKey)}),d=await o.webauthnLoginFinish({query:a.userId?{user_id:a.userId}:void 0,body:ne(c)});return this.signedIn(d.data)},signUp:async(a,l)=>{let c=(await o.webauthnSignupBegin({body:{identifier:a,user_name:l}})).data,d=await this.authenticator().create({publicKey:ee(c.options.publicKey)});await o.webauthnSignupFinish({query:{user_id:c.user_id},body:se(d)});let u=(await o.webauthnLoginBegin({body:{user_id:c.user_id}})).data,k=await this.authenticator().get({publicKey:te(u.options.publicKey)});return this.signedIn((await o.webauthnLoginFinish({query:{user_id:c.user_id},body:ne(k)})).data)},list:async()=>(await r.webauthnListCredentials()).data,remove:async a=>{await r.webauthnDeleteCredential({path:{id:a}})}},this.magicLink={send:async a=>{await o.magicLinkRequest({body:{email:a}})},verify:async a=>this.signedIn((await o.magicLinkVerify({body:{token:a}})).data)},this.phone={sendCode:async a=>(await o.requestPhoneOtp({body:{phone:a,channel:"sms"}})).data,verifyCode:async(a,l)=>this.signInResult((await o.verifyPhoneOtp({body:{phone:a,token:l}})).data)},this.password={requestReset:async a=>{await o.passwordResetRequest({body:{email:a}})},confirmReset:async(a,l)=>{await o.passwordResetConfirm({body:{token:a,new_password:l}})},change:async a=>(await r.passwordChange({body:a})).data,set:async a=>(await r.setPassword({body:a})).data},this.email={verify:async a=>{await o.verifyEmail({body:a})},resendVerification:async a=>(await o.resendVerification({body:{email:a}})).data},this.sessions={list:async()=>(await r.listSessions()).data,revoke:async a=>{await r.revokeSession({path:{id:a}})},revokeAll:async()=>{await r.revokeAllSessions()}}}onAuthStateChange(e){return this.session.onChange(e)}currentSession(){return this.session.session()}async signUp(e){let t=(await this.open.signup({body:e})).data;return t.access_token&&t.refresh_token&&t.expires_in!==void 0&&await this.session.set({access_token:t.access_token,refresh_token:t.refresh_token,expires_in:t.expires_in},"SIGNED_IN",t.user),t}async signIn(e,t){return this.signInResult((await this.open.login({body:{email:e,password:t}})).data)}async signOut(){try{await this.session.session()&&await this.api.logout()}finally{await this.session.clear("SIGNED_OUT")}}async getUser(){let e=this.session.snapshot(),t=(await this.api.getMe()).data;return await this.session.setUser(t,e),t}async refreshSession(){return this.session.refresh()}async deleteAccount(e){await this.api.deleteAccount(e===void 0?void 0:{body:{password:e}}),await this.session.clear("SIGNED_OUT")}async signInResult(e){return"mfa_required"in e&&e.mfa_required?{mfaRequired:{mfaToken:e.mfa_token,factors:e.factors}}:{user:await this.signedIn(e)}}async setSession(e){return this.signedIn(e)}async signedIn(e){let t=await this.session.set({access_token:e.access_token,refresh_token:e.refresh_token,expires_in:e.expires_in},"SIGNED_IN",e.user);if(e.user)return e.user;let s=(await this.api.verifyTokenUser()).data;return await this.session.setUser(s,t),s}authenticator(){if(!this.credentials)throw new Error("passkeys need navigator.credentials (or createClient({ webauthn }))");return this.credentials}},C=i=>{let e=atob(i.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(i.length/4)*4,"=")),t=new Uint8Array(e.length);for(let s=0;s<e.length;s++)t[s]=e.charCodeAt(s);return t.buffer},g=i=>{if(!i)return;let e=i instanceof ArrayBuffer?new Uint8Array(i):new Uint8Array(i.buffer,i.byteOffset,i.byteLength),t="";for(let s of e)t+=String.fromCharCode(s);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},ie=i=>Array.isArray(i)?i.map(e=>({...e,id:C(String(e.id))})):void 0;function ee(i){let e=i.user;return{...i,challenge:C(String(i.challenge)),user:{...e,id:C(String(e.id))},excludeCredentials:ie(i.excludeCredentials)}}function te(i){return{...i,challenge:C(String(i.challenge)),allowCredentials:ie(i.allowCredentials)}}function se(i){let e=i,t=e.response;return{id:e.id,rawId:g(e.rawId),type:"public-key",authenticatorAttachment:e.authenticatorAttachment??void 0,clientExtensionResults:e.getClientExtensionResults?.()??{},response:{clientDataJSON:g(t.clientDataJSON),attestationObject:g(t.attestationObject),transports:t.getTransports?.()}}}function ne(i){let e=i,t=e.response;return{id:e.id,rawId:g(e.rawId),type:"public-key",authenticatorAttachment:e.authenticatorAttachment??void 0,clientExtensionResults:e.getClientExtensionResults?.()??{},response:{clientDataJSON:g(t.clientDataJSON),authenticatorData:g(t.authenticatorData),signature:g(t.signature),userHandle:g(t.userHandle)}}}var y=class extends Error{code="session_changed";constructor(e){super(e),this.name="SessionChangedError"}};function V(){let i=null;return{load:()=>i,save:e=>{i=e},clear:()=>{i=null},shared:!1}}function F(i){let e=null,t=!0,s=()=>{try{return globalThis.localStorage}catch{return}};return{shared:!0,load(){try{let n=s()?.getItem(i);return n==null?t?null:e:JSON.parse(n)}catch{return e}},save(n){e=n;try{let r=s();if(!r)throw new Error("no storage");r.setItem(i,JSON.stringify(n)),t=!0}catch{t=!1}},clear(){e=null,t=!0;try{s()?.removeItem(i)}catch{}},watch(n){let r=globalThis;if(typeof r.addEventListener!="function")return()=>{};let o=a=>{(a.key===i||a.key===null)&&n()};return r.addEventListener("storage",o),()=>r.removeEventListener?.("storage",o)}}}function pe(i){try{let e=i.split(".")[1]??"",t=atob(e.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(e.length/4)*4,"=")),s=JSON.parse(t).sub;return typeof s=="string"?s:""}catch{return""}}var fe=6e4,ge=15e3;function ye(i,e,t){let s=i?globalThis.navigator?.locks:void 0;return s?s.request(e,t):t()}var R=class{current=null;loaded;inflight=null;listeners=new Set;store;refresher;isRejected;now;lockName;refreshTimeoutMs;constructor(e,t,s,n={}){this.store=e,this.refresher=t,this.isRejected=s,this.now=n.now??Date.now,this.lockName=n.lockName??"palbase.session.refresh",this.refreshTimeoutMs=n.refreshTimeoutMs??ge,this.loaded=Promise.resolve(e.load()).then(r=>{this.current=r}),e.watch?.(()=>{this.reconcile()})}async session(){return await this.loaded,this.current}snapshot(){return this.current}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async set(e,t,s){await this.loaded;let n=t==="TOKEN_REFRESHED"?this.current:null,r={accessToken:e.access_token,refreshToken:e.refresh_token,expiresAt:this.now()+e.expires_in*1e3,userId:s?.id??n?.userId??pe(e.access_token),user:s??n?.user};return this.current=r,await this.store.save(r),this.emit(t,r),r}async setUser(e,t){await this.loaded,!(!this.current||!t||this.current.userId!==t.userId)&&(this.current={...this.current,user:e},await this.store.save(this.current),this.emit("USER_UPDATED",this.current))}async clear(e){await this.loaded;let t=this.current;this.current=null,this.inflight=null;let s=await this.store.load();(!s||!t||s.userId===t.userId)&&await this.store.clear(),t&&this.emit(e,null)}async accessToken(){await this.loaded;let e=this.current;if(!e)return;let t=e.expiresAt-this.now();return t>fe?e.accessToken:t>0?(this.refresh().catch(()=>{}),e.accessToken):(await this.refresh()).accessToken}refresh(){if(this.inflight)return this.inflight;let e=ye(this.store.shared===!0,this.lockName,async()=>{await this.loaded;let t=this.current;if(!t)throw new y("no session to refresh");let s=await this.adoptStored(t);if(s)return s;try{let n=await this.withTimeout(this.refresher(t.refreshToken));if(this.current?.refreshToken!==t.refreshToken)throw new y("the session changed while it was refreshed");return await this.set(n,"TOKEN_REFRESHED")}catch(n){throw this.isRejected(n)&&this.current?.refreshToken===t.refreshToken&&await this.clear("SESSION_EXPIRED"),n}});return this.inflight=e,e.finally(()=>{this.inflight===e&&(this.inflight=null)}).catch(()=>{}),e}async adoptStored(e){let t=await this.store.load();if(!t)throw this.current=null,this.emit("SIGNED_OUT",null),new y("signed out in another tab");if(t.userId!==e.userId)throw this.current=t,this.emit("SIGNED_OUT",null),this.emit("SIGNED_IN",t),new y("another user signed in in another tab");if(t.refreshToken!==e.refreshToken&&t.expiresAt>=e.expiresAt)return this.current=t,this.emit("TOKEN_REFRESHED",t),t}async reconcile(){await this.loaded;let e=this.current,t=await this.store.load();if(!e){t&&(this.current=t,this.emit("SIGNED_IN",t));return}await this.adoptStored(e).catch(()=>{})}withTimeout(e){let t,s=new Promise((n,r)=>{t=setTimeout(()=>r(new Error(`the refresh did not answer within ${this.refreshTimeoutMs/1e3} s`)),this.refreshTimeoutMs)});return Promise.race([e,s]).finally(()=>clearTimeout(t))}emit(e,t){for(let s of this.listeners)try{s(e,t)}catch{}}};var M=class{state="closed";refusal;joinRef=null;listeners=new Map;closers=new Set;joinWaiters=[];name;socket;constructor(e,t){this.name=e,this.socket=t}get topic(){return`realtime:${this.name}`}join(){if(this.state==="joined")return Promise.resolve();let e=new Promise((t,s)=>this.joinWaiters.push({resolve:t,reject:s}));return this.state!=="joining"&&this.socket.join(this),e}leave(){this.socket.leave(this)}push(e,t){return this.socket.request(this,e,t)}on(e,t){let s=this.listeners.get(e);return s||this.listeners.set(e,s=new Set),s.add(t),()=>s.delete(t)}onClosed(e){return this.closers.add(e),()=>this.closers.delete(e)}deliver(e,t){for(let s of this.listeners.get(e)??[])try{s(t)}catch{}}settled(e,t){this.state=e?"joined":"refused",this.refusal=e?void 0:t;let s=this.joinWaiters.splice(0);for(let n of s)e?n.resolve():n.reject(new Error(`join ${this.name} refused: ${JSON.stringify(t)}`))}closed(e){this.state="closed",this.joinRef=null;let t=this.joinWaiters.splice(0);for(let s of t)s.reject(new Error(`join ${this.name}: ${e}`));for(let s of[...this.closers])try{s()}catch{}}},v=class{ws=null;opening=null;ref=0;channels=new Map;replies=new Map;heartbeat=null;heartbeatRef=null;reconnectTimer=null;attempts=0;closedByUs=!1;reconnects=0;opts;constructor(e){this.opts=e}channel(e){let t=this.channels.get(e);return t||this.channels.set(e,t=new M(e,this)),t}disconnect(){this.closedByUs=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.stopHeartbeat();let e=this.ws;this.ws=null,this.opening=null,e?.close(1e3);for(let[,t]of this.replies)t("error",{reason:"socket closed"});this.replies.clear();for(let t of this.channels.values())t.closed("the socket was closed")}async tokenChanged(){if(!this.ws||this.ws.readyState!==1)return;let e=await this.opts.accessToken();if(e)for(let t of this.channels.values())t.state==="joined"&&this.push(t.joinRef,t.topic,"access_token",{access_token:e})}join(e){e.state="joining",this.open().then(()=>this.sendJoin(e)).catch(t=>e.settled(!1,{reason:t instanceof Error?t.message:String(t)}))}leave(e){e.state==="joined"&&this.ws?.readyState===1&&this.push(e.joinRef,e.topic,"phx_leave",{}),e.state="closed",this.channels.delete(e.name)}async request(e,t,s){let n=this.ws;if(this.channels.get(e.name)!==e||e.state!=="joined"||n?.readyState!==1)return{status:"error",response:{reason:"not joined"}};let r=this.nextRef(),o=JSON.stringify([e.joinRef,r,e.topic,t,s]),a=this.awaitReply(r);return n.send(o),a}open(){if(this.ws?.readyState===1)return Promise.resolve();if(this.opening)return this.opening;this.closedByUs=!1;let e=this.opts.webSocket??globalThis.WebSocket,t=`${this.opts.baseUrl.replace(/^http/,"ws")}/realtime/v1/websocket?vsn=2.0.0&apikey=${encodeURIComponent(this.opts.publishableKey)}`,s=new Promise((n,r)=>{let o=new e(t);this.ws=o,o.onopen=()=>{this.attempts=0,this.startHeartbeat(),n()},o.onmessage=a=>this.receive(String(a.data)),o.onerror=()=>r(new Error("the realtime socket could not be opened")),o.onclose=()=>this.dropped(o)});return this.opening=s,s.finally(()=>{this.opening===s&&(this.opening=null)}).catch(()=>{}),s}dropped(e){if(this.ws!==e)return;this.ws=null,this.stopHeartbeat();for(let[,n]of this.replies)n("error",{reason:"socket closed"});this.replies.clear();for(let n of this.channels.values())n.state==="joined"&&(n.state="joining");if(this.closedByUs||![...this.channels.values()].some(n=>n.state==="joining"))return;let t=this.opts.backoff??[500,1e3,2e3,5e3,1e4,3e4],s=t[Math.min(this.attempts,t.length-1)]*(.8+Math.random()*.4);this.attempts++,this.reconnectTimer=x(setTimeout(()=>{this.reconnectTimer=null,this.reconnects++;let n=[...this.channels.values()].filter(r=>r.state==="joining");this.open().then(()=>Promise.all(n.map(r=>this.sendJoin(r)))).catch(()=>{})},s))}async sendJoin(e){let t=await this.opts.accessToken(),s=this.nextRef();e.joinRef=s;let n=this.awaitReply(s);this.push(s,e.topic,"phx_join",{access_token:t,config:{broadcast:{self:!1}}},s);let{status:r,response:o}=await n;if(this.channels.get(e.name)!==e||e.state!=="joining"){r==="ok"&&this.ws?.readyState===1&&this.push(s,e.topic,"phx_leave",{});return}e.settled(r==="ok",o)}awaitReply(e){return new Promise(t=>{let s=x(setTimeout(()=>{this.replies.delete(e),t({status:"timeout",response:{reason:"no reply"}})},this.opts.replyTimeoutMs??1e4));this.replies.set(e,(n,r)=>{clearTimeout(s),this.replies.delete(e),t({status:n,response:r})})})}receive(e){let t;try{t=JSON.parse(e)}catch{return}if(!Array.isArray(t)||t.length!==5||typeof t[2]!="string"||typeof t[3]!="string")return;let[,s,n,r,o]=t,a=typeof o=="object"&&o!==null?o:{};if(r==="phx_reply"&&typeof s=="string"){if(s===this.heartbeatRef){this.heartbeatRef=null;return}this.replies.get(s)?.(String(a.status),a.response??{});return}let l=[...this.channels.values()].find(c=>c.topic===n);if(l){if(r==="phx_close"){l.state="closed";return}if(r==="phx_error"){l.state="joining",x(setTimeout(()=>this.channels.get(l.name)===l&&l.state==="joining"&&this.ws?.readyState===1&&void this.sendJoin(l),1e3));return}l.deliver(r,a)}}push(e,t,s,n,r=this.nextRef()){this.ws?.send(JSON.stringify([e,r,t,s,n]))}nextRef(){return String(++this.ref)}startHeartbeat(){this.stopHeartbeat(),this.heartbeat=x(setInterval(()=>{if(this.heartbeatRef!==null){this.heartbeatRef=null,this.ws?.close(4e3);return}this.heartbeatRef=this.nextRef(),this.push(null,"phoenix","heartbeat",{},this.heartbeatRef)},this.opts.heartbeatMs??25e3))}stopHeartbeat(){this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null,this.heartbeatRef=null}};function x(i){return i.unref?.(),i}var ve=30*6e4,re=1e3,we=100,be=60*1024,A=()=>globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;function O(){try{return globalThis.localStorage}catch{return}}var w=class{api;closingApi;flushMs;flushAt;now;anonKey;sessionKey;events=[];samples=[];timer;memoryAnon;memorySession;appVersion;stopAuto;session;identifyPending=!1;constructor(e,t,s,n={}){this.session=t,this.api=D.client(e),this.closingApi=D.client({send:r=>e.send({...r,keepalive:!0})}),this.flushMs=n.flushMs??5e3,this.flushAt=n.flushAt??20,this.now=n.now??Date.now,this.anonKey=`palbase.analytics.anonymous.${s}`,this.sessionKey=`palbase.analytics.session.${s}`,t.onChange(r=>{r==="SIGNED_IN"?(this.identifyPending=!0,this.soon()):r==="SIGNED_OUT"&&(this.identifyPending=!1,this.reset())})}capture(e,t){let s=this.now();this.hold({event:e,distinct_id:this.distinctId(),properties:t,timestamp:s,session_id:this.sessionId(s),...this.appVersion?{app_version:this.appVersion}:{}})}page(e={}){let t=globalThis.location,s=globalThis.document,n=e.url??(t?`${t.origin}${t.pathname}`:"");if(!n)return;let r=e.referrer??Pe(s?.referrer);this.capture("$pageview",{...e.properties,url:n,...e.title??s?.title?{title:e.title??s?.title}:{},...r?{referrer:r}:{}})}async identify(e){this.identifyPending=!1;let t=this.session.snapshot()?.userId;t&&(await this.flush(),await this.sendIdentify(this.api,t,e))}async sendIdentify(e,t,s){try{await e.identify({body:{distinct_id:t,anonymous_id:this.anonymousId(),traits:s,timestamp:this.now(),sent_at:this.now()}})}catch{}}reset(){this.memoryAnon=void 0,this.memorySession=void 0;try{O()?.removeItem(this.anonKey),O()?.removeItem(this.sessionKey)}catch{}}async flush(e=!1){this.timer&&clearTimeout(this.timer),this.timer=void 0;let t=e?this.closingApi:this.api,s=this.now(),n=this.session.snapshot()?.userId;for(this.identifyPending&&n&&(this.identifyPending=!1,await this.sendIdentify(t,n));this.events.length>0;){let r=this.take(this.events,e);try{await t.batch({body:{events:r.map(o=>({...o,sent_at:s}))}})}catch{}}for(;this.samples.length>0;){let r=this.take(this.samples,e);try{await t.sendPerf({body:{items:r}})}catch{}}}start(e={}){this.stopAuto?.(),this.appVersion=e.appVersion;let t=globalThis;if(typeof t.addEventListener!="function"||typeof globalThis.document>"u")return()=>{};let s=[];e.pageViews!==!1&&s.push(this.watchPages(t)),e.webVitals!==!1&&s.push(Te((o,a)=>this.sample("web_vital",o,a))),e.network!==!1&&s.push(this.watchFetch(t));let n=()=>{document.visibilityState==="hidden"&&this.flush(!0)},r=()=>{this.flush(!0)};return document.addEventListener("visibilitychange",n),t.addEventListener("pagehide",r),s.push(()=>{document.removeEventListener("visibilitychange",n),t.removeEventListener("pagehide",r)}),this.stopAuto=()=>{for(let o of s.splice(0))o();this.stopAuto=void 0},this.stopAuto}hold(e){this.events.length>=re&&this.events.shift(),this.events.push(e),this.soon()}sample(e,t,s,n={}){this.samples.length>=re&&this.samples.shift(),this.samples.push({row_id:A(),trace_type:e,name:t,value:Math.max(0,s),timestamp:this.now(),distinct_id:this.distinctId(),...n}),this.soon()}soon(){if(this.events.length+this.samples.length>=this.flushAt){this.flush();return}this.timer||(this.timer=setTimeout(()=>{this.flush()},this.flushMs),this.timer.unref?.())}take(e,t){let s=e.splice(0,we);if(!t)return s;for(;s.length>1&&JSON.stringify(s).length>be;)e.unshift(s.pop());return s}distinctId(){return this.session.snapshot()?.userId??this.anonymousId()}anonymousId(){let e=O();try{let t=e?.getItem(this.anonKey);if(t)return t;let s=`anon_${A()}`;if(e?.setItem(this.anonKey,s),e?.getItem(this.anonKey)===s)return s}catch{}return this.memoryAnon??=`anon_${A()}`,this.memoryAnon}sessionId(e){let t=O(),s=this.memorySession;try{let r=t?.getItem(this.sessionKey);r&&(s=JSON.parse(r))}catch{}let n=s&&e-s.last<ve?{id:s.id,last:e}:{id:`ses_${A()}`,last:e};this.memorySession=n;try{t?.setItem(this.sessionKey,JSON.stringify(n))}catch{}return n.id}watchPages(e){let t="",s=()=>{let a=`${e.location.origin}${e.location.pathname}`;a!==t&&(t=a,setTimeout(()=>this.page({url:a}),0))},n=e.history,r=n.pushState.bind(n),o=n.replaceState.bind(n);return n.pushState=(...a)=>{r(...a),s()},n.replaceState=(...a)=>{o(...a),s()},e.addEventListener("popstate",s),s(),()=>{n.pushState=r,n.replaceState=o,e.removeEventListener("popstate",s)}}watchFetch(e){let t=e.fetch;if(typeof t!="function")return()=>{};let s=async(n,r)=>{let o=performance.now(),a=n instanceof Request?n:void 0,l=(r?.method??a?.method??"GET").toUpperCase(),c;try{c=new URL(a?.url??String(n),e.location.href)}catch{c=void 0}let d=!!c&&c.pathname.startsWith("/analytics/")||_e(r?.headers??a?.headers);try{let u=await t(n,r);return c&&!d&&this.sample("network",`${l} ${c.origin}${c.pathname}`,performance.now()-o,{attrs:{status:String(u.status)},...u.headers.get("x-request-id")?{request_id:u.headers.get("x-request-id")}:{}}),u}catch(u){throw c&&!d&&this.sample("network",`${l} ${c.origin}${c.pathname}`,performance.now()-o,{attrs:{status:"0"}}),u}};return e.fetch=s,()=>{e.fetch===s&&(e.fetch=t)}}},Se=i=>i.entryType==="layout-shift"&&"value"in i&&"hadRecentInput"in i,ke=i=>i.entryType==="event"||i.entryType==="first-input";function N(i,e){if(!(typeof PerformanceObserver>"u"))try{let t=new PerformanceObserver(s=>e(s.getEntries()));return t.observe({type:i,buffered:!0}),t}catch{return}}function Te(i){if(typeof document>"u"||typeof performance>"u"||typeof performance.getEntriesByType!="function")return()=>{};let e=0,t=0,s=0,n=[N("largest-contentful-paint",c=>{for(let d of c)e=Math.max(e,d.startTime)}),N("layout-shift",c=>{for(let d of c)Se(d)&&!d.hadRecentInput&&(t+=d.value)}),N("event",c=>{for(let d of c)ke(d)&&(s=Math.max(s,d.duration))}),N("paint",c=>{for(let d of c)d.name==="first-contentful-paint"&&i("FCP",d.startTime)})],r=performance.getEntriesByType("navigation")[0];r&&r.responseStart>0&&i("TTFB",r.responseStart);let o=!1,a=()=>{o||(o=!0,e>0&&i("LCP",e),i("CLS",t),s>0&&i("INP",s))},l=()=>{document.visibilityState==="hidden"&&a()};return document.addEventListener("visibilitychange",l),()=>{a(),document.removeEventListener("visibilitychange",l);for(let c of n)c?.disconnect()}}function _e(i){if(!i)return!1;try{return new Headers(i).has("next-router-prefetch")}catch{return!1}}function Pe(i){if(!i)return"";try{let e=new URL(i);return`${e.origin}${e.pathname}`}catch{return i.split(/[?#]/,1)[0]??""}}var b=class{api;session;socket;ref;fetch;appVersion;app;listeners=new Set;watch;following;last;constructor(e,t,s,n,r,o,a){this.api=J.client(e),this.session=t,this.socket=s,this.ref=n,this.fetch=r,this.appVersion=o,this.app=a}async me(){let e=this.session.snapshot()?.userId,t=(await this.api.getMyCustomerInfo()).data;return this.watch&&this.watch.userId===e&&this.offer(this.watch,t),t}async offerings(e="web"){return(await this.api.getOfferings({query:{channel:e}})).data}async paywall(e,t={}){return Q(this.api,this.ref,e,s=>this.checkout(s),{signal:t.signal,fetch:this.fetch,attributes:t.attributes,locale:t.locale,appVersion:this.appVersion,app:this.app})}async checkout(e){let t={product:e.product,plan:e.plan,success_url:e.successUrl,cancel_url:e.cancelUrl};return(await this.api.createCheckout({body:t})).data.url}async portal(e){return(await this.api.createPortalSession({body:{return_url:e}})).data.url}async mergeGrant(){return(await this.api.createMergeGrant()).data}async merge(e){let t=this.session.snapshot()?.userId,s=(await this.api.mergeGuest({body:{grant:typeof e=="string"?e:e.grant}})).data;return this.watch&&this.watch.userId===t&&this.offer(this.watch,s),s}onCustomerInfo(e){if(this.listeners.add(e),this.listeners.size===1)this.start();else if(this.last!==void 0){let t=this.last;queueMicrotask(()=>this.listeners.has(e)&&ae(e,t))}return()=>{this.listeners.delete(e)&&this.listeners.size===0&&this.stop()}}start(){this.following=this.session.onChange((e,t)=>{(e==="SIGNED_IN"||e==="SIGNED_OUT"||e==="SESSION_EXPIRED")&&this.follow(t)}),this.session.session().then(e=>{this.following&&!this.watch&&this.last===void 0&&this.follow(e)})}stop(){this.following?.(),this.following=void 0,this.unfollow(),this.last=void 0}follow(e){if(this.unfollow(),!e){this.tell(null);return}let t=this.socket.channel(`purchases:${this.ref}:${e.userId}`),s={userId:e.userId,channel:t,off:()=>{},revision:-1,reading:!1,wanted:Number.NEGATIVE_INFINITY},n=[t.on("broadcast",r=>{r.event==="changed"&&this.changed(s,B(r.payload))}),t.on("state_snapshot",r=>this.held(s,B(oe(r.entries)))),t.on("state_diff",r=>this.held(s,B(oe(r.set))))];s.off=()=>n.forEach(r=>r()),this.watch=s,t.join().catch(()=>{}),this.read(s)}unfollow(){let e=this.watch;e&&(this.watch=void 0,e.off(),e.channel.leave())}changed(e,t){this.watch!==e||t!==void 0&&t<=e.revision||(e.reading?e.wanted=Math.max(e.wanted,t??Number.POSITIVE_INFINITY):this.read(e))}held(e,t){t!==void 0&&this.changed(e,t)}async read(e){e.reading=!0;try{for(;;){e.wanted=Number.NEGATIVE_INFINITY;try{let t=(await this.api.getMyCustomerInfo()).data;if(this.watch!==e)return;this.offer(e,t)}catch{}if(this.watch!==e||e.wanted<=e.revision)return}}finally{e.reading=!1}}offer(e,t){this.watch!==e||t.revision<=e.revision||(e.revision=t.revision,this.tell(t))}tell(e){if(!(this.last===null&&e===null)){this.last=e;for(let t of[...this.listeners])ae(t,e)}}};function ae(i,e){try{i(e)}catch{}}function oe(i){let e=typeof i=="object"&&i!==null?i.revision:void 0;return typeof e=="object"&&e!==null?e.v:void 0}function B(i){let e=typeof i=="object"&&i!==null?i.revision:void 0;return typeof e=="number"&&Number.isFinite(e)?e:void 0}function le(){return"cm_"+crypto.randomUUID()}async function L(i,e=4){for(let t=1;;t++)try{return await i()}catch(s){if(t>=e||!(s instanceof f)||s.status===429)throw q(s);let n=X(s,t,30);if(n===void 0)throw q(s);await new Promise(r=>setTimeout(r,n*1e3))}}var U=class{id;api;session;options;status="idle";error=null;messages=new Map;responses=new Map;order=[];turn=null;calls=new Map;voiceParts=[];handlers=new Map;answering=new Set;listeners=new Set;following;position;snapshot;told=!1;constructor(e,t,s={},n){this.api=e,this.id=t,this.options=s,this.session=n,this.position={after:s.after??0}}get state(){return this.snapshot??=this.build()}subscribe(e){return this.listeners.add(e),this.follow(),()=>{this.listeners.delete(e)}}async*[Symbol.asyncIterator](){let e,t,s=this.subscribe(()=>e?.());try{for(;;){let n=this.state;if(n!==t){t=n,yield n;continue}if(this.status==="closed"||this.status==="failed")return;await new Promise(r=>e=r)}}finally{s()}}async send(e,t={}){let s=t.clientId??le(),n=this.messages.get(s),r=n?{...n,status:"pending",error:null}:{clientId:s,id:null,text:e,author:this.session?.snapshot()?.userId??null,authorName:"",delivery:t.delivery??"next",status:"pending",error:null,responseId:null,createdAt:new Date().toISOString(),mine:!0};this.messages.set(s,r),n||this.order.push({type:"message",key:s}),this.changed(),this.follow();let o={client_id:s,text:r.text};t.delivery!==void 0&&(o.delivery=t.delivery);try{let a=await L(async()=>(await this.api.sendChatMessage({path:{chat_id:this.id},body:o})).data);this.heard(a,!0)}catch(a){let l=this.messages.get(s);throw l.status==="pending"&&(this.messages.set(s,{...l,status:"failed",error:a instanceof f?a.code:"send_failed"}),this.changed()),a}return this.messages.get(s)}tools(e){for(let[t,s]of Object.entries(e))this.handlers.set(t,s);this.follow();for(let t of this.calls.values())this.autoAnswer(t);return()=>{for(let[t,s]of Object.entries(e))this.handlers.get(t)===s&&this.handlers.delete(t)}}async answer(e,t,s={}){let n={output:K(t),is_error:s.isError===!0};this.answering.add(e);try{return await L(()=>this.api.answerChatToolCall({path:{chat_id:this.id,call_id:e},body:n})),!0}catch(r){if(r instanceof f&&r.status===409)return!1;throw this.answering.delete(e),r}}async approve(e,t){await p(this.api.decideChatApproval({path:{chat_id:this.id,approval_id:e},body:t===void 0?{approve:!0}:{approve:!0,reason:t}}))}async deny(e,t){await p(this.api.decideChatApproval({path:{chat_id:this.id,approval_id:e},body:t===void 0?{approve:!1}:{approve:!1,reason:t}}))}async stop(){return(await p(this.api.stopChat({path:{chat_id:this.id}}))).data.stopped}async startVoice(e){let t=new RTCPeerConnection,s=e.audio??(typeof Audio=="function"?new Audio:void 0);s&&(s.autoplay=!0),t.ontrack=n=>{s&&(s.srcObject=n.streams[0]??new MediaStream([n.track]))};for(let n of e.stream.getAudioTracks())t.addTrack(n,e.stream);try{let n=await t.createOffer();await t.setLocalDescription(n);let r=e.voice===void 0?{sdp:n.sdp??""}:{sdp:n.sdp??"",voice:e.voice},o=(await p(this.api.startChatVoice({path:{chat_id:this.id},body:r}))).data;await t.setRemoteDescription({type:"answer",sdp:o.sdp??""}),this.follow();let a=o.id;return{id:a,peer:t,stop:async()=>(t.close(),(await p(this.api.closeChatVoice({path:{chat_id:this.id,voice_id:a}}))).data.seconds)}}catch(n){throw t.close(),n}}async sendToSubagent(e,t){let s={client_id:le(),text:t};await L(()=>this.api.sendSubagentMessage({path:{chat_id:this.id,run_id:e},body:s}))}close(){this.following?.abort(),this.following=void 0,this.status="closed",this.changed()}follow(){if(this.following||this.status==="closed")return;let e=new AbortController;this.following=e,this.status="connecting",this.error=null,this.changed();let t=Z(async(s,n)=>{this.status!=="connecting"&&(this.status="connecting",this.changed());let r=(await this.api.followChat({path:{chat_id:this.id},query:s,signal:n})).data;return this.status="live",this.changed(),r},{...this.position,resumeFor:this.options.resumeFor,signal:e.signal});(async()=>{try{for await(let s of t)this.take(s)}catch(s){if(this.position=t.position,e.signal.aborted)return;this.status="failed",this.error=s,this.following=void 0,this.changed()}})()}take(e){switch(e.type){case"message":this.heard(e.message,!1);return;case"turn":{let t=this.response(e.response_id);t.status=e.status,t.waiting=e.waiting,t.error=e.error,e.user_id!==void 0&&(t.startedBy=e.user_id),typeof e.solo=="boolean"&&(t.solo=e.solo),this.turn=e;for(let s of this.calls.values())s.response_id===e.response_id&&this.autoAnswer(s);break}case"text":{let t=this.response(e.response_id);t.text=t.text.slice(0,E(t.text,e.offset))+e.text;break}case"reset":{let t=this.response(e.response_id);t.text=t.text.slice(0,E(t.text,e.offset));break}case"tool":{this.response(typeof e.agent_response_id=="string"&&e.agent_response_id!==""?e.agent_response_id:e.response_id).marks.set(`tool:${e.call_id}`,e),this.calls.set(e.call_id,e),this.autoAnswer(e);break}case"voice":this.voiceParts.push(e);break;case"agent":{if(this.response(e.parent_response_id).marks.set(e.run_id?`agent:${e.run_id}`:`agent:seq:${e.seq}`,e),!e.response_id)break;let t=this.response(e.response_id);if(t.runId=e.run_id,t.agent=e.name,t.parentId===null){t.parentId=e.parent_response_id;let s=this.order.findIndex(n=>n.type==="response"&&n.key===e.response_id);s>=0&&this.order.splice(s,1)}break}}this.changed()}heard(e,t){let s=this.messages.get(e.client_id),n=e.status==="delivered"||e.status==="failed"?e.status:"pending",r={clientId:e.client_id,id:e.id,text:e.text,author:e.author,authorName:e.author_name,delivery:e.delivery,status:s&&s.status==="delivered"&&t?"delivered":n,error:e.error,responseId:e.response_id??s?.responseId??null,createdAt:e.created_at,mine:s?.mine??!1};this.messages.set(e.client_id,r),s||this.order.push({type:"message",key:e.client_id}),this.changed()}response(e){let t=this.responses.get(e);return t||(t={id:e,status:null,waiting:null,error:null,text:"",marks:new Map,runId:null,agent:null,parentId:null,startedBy:void 0,solo:void 0},this.responses.set(e,t),this.order.push({type:"response",key:e})),t}autoAnswer(e){if(e.status!=="awaiting_output"||this.answering.has(e.call_id)||!this.mine(e.response_id)||this.responses.get(e.response_id)?.solo!==!0)return;let t=this.handlers.get(e.name);t&&(this.answering.add(e.call_id),(async()=>{let s;try{s={output:K(await t(e.input,e)),is_error:!1}}catch(n){s={output:[{type:"text",text:n instanceof Error?n.message||n.name:String(n)}],is_error:!0}}try{await L(()=>this.api.answerChatToolCall({path:{chat_id:this.id,call_id:e.call_id},body:s}))}catch(n){n instanceof f&&(n.status===409||n.status===403)||this.answering.delete(e.call_id)}})())}mine(e){let t=this.session?.snapshot()?.userId;return t!==void 0&&this.responses.get(e)?.startedBy===t}changed(){this.snapshot=void 0,!this.told&&(this.told=!0,queueMicrotask(()=>{this.told=!1;let e=this.state;for(let t of[...this.listeners])try{t(e)}catch{}}))}build(){let e=new Map;for(let n of this.responses.values()){let r=n.parentId!==null?this.responses.get(n.parentId)??n:n;e.set(n.id,Ee(n,r.startedBy??null,this.mine(r.id),r.solo??null))}let t=[];for(let n of this.order)n.type==="message"?t.push({type:"message",message:this.messages.get(n.key)}):this.responses.get(n.key).parentId===null&&t.push({type:"response",response:e.get(n.key)});let s=[...this.calls.values()].filter(n=>this.mine(n.response_id));return{status:this.status,error:this.error,items:t,messages:[...this.messages.values()],responses:[...e.values()],turn:this.turn,waiting:{approvals:s.filter(n=>n.status==="awaiting_approval"),outputs:s.filter(n=>n.status==="awaiting_output")},voice:[...this.voiceParts]}}};function Ee(i,e,t,s){let n=[...i.marks.values()].map((a,l)=>({m:a,i:l,at:E(i.text,Math.max(0,Number(a.text_offset)||0))}));n.sort((a,l)=>a.at-l.at||a.i-l.i);let r=[],o=0;for(let{m:a,at:l}of n)l>o&&r.push({type:"text",text:i.text.slice(o,l)}),o=Math.max(o,l),r.push(a.type==="tool"?{type:"tool",tool:a}:{type:"agent",agent:a});return o<i.text.length&&r.push({type:"text",text:i.text.slice(o)}),{id:i.id,status:i.status,waiting:i.waiting,error:i.error,text:i.text,parts:r,runId:i.runId,agent:i.agent,parentId:i.parentId,startedBy:e,mine:t,solo:s}}var S=class{api;session;chats;constructor(e,t){let s=G.client(e);this.api=s,this.session=t,this.chats={async create(n){let r={agent:n.agent};return n.name!==void 0&&(r.name=n.name),n.title!==void 0&&(r.title=n.title),(await p(s.createChat({body:r}))).data},async list(){return(await p(s.listChats({}))).data.chats},async get(n){return(await p(s.getChat({path:{chat_id:n}}))).data},async delete(n){await p(s.deleteChat({path:{chat_id:n}}))}}}chat(e,t={}){if(typeof e!="string"||e==="")throw new TypeError("pb.ai.chat(id): id is the chat's");return new U(this.api,e,t,this.session)}};var Ie=/^pb_[a-z0-9]+_s/,Ce=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Re=new Set(["invalid_token","token_expired","session_expired","session_revoked","missing_token"]),xe=new Set(["invalid_token","token_reuse","token_expired","session_revoked","session_expired","session_device_changed"]);function Me(i){return i.status===400&&i.code==="invalid_request"}function Ae(i){if(Ie.test(i.publishableKey)||"secretKey"in i)throw new TypeError("a secret key never goes into a client app: palbase/web takes the publishable key (pb_<ref>_c\u2026); servers use palbase/server");let e=/^pb_([a-z0-9]+)_c/.exec(i.publishableKey)?.[1];if(e===void 0)throw new TypeError("publishableKey is the project publishable key (pb_<ref>_c\u2026)");if(i.appId!==void 0&&!Ce.test(i.appId))throw new TypeError("appId is the registered app's id, a UUID (settings.appId of palbase apps:sync), not its slug");let t=new URL(i.url).origin,s=i.storage??(Oe()?F(`palbase.session.${t}`):V()),n=i.retry??W,r=P(_({baseUrl:i.url,credentials:{publishableKey:i.publishableKey},fetch:i.fetch}),n),o=m.client(r),a=new R(s,async h=>(await o.refreshToken({body:{refresh_token:h}})).data,h=>h instanceof f&&(h.status===401&&xe.has(h.code)||Me(h)),{lockName:`palbase.session.refresh.${t}`}),l=_({baseUrl:i.url,credentials:{publishableKey:i.publishableKey,accessToken:()=>a.accessToken()},fetch:i.fetch,xmlHttpRequest:i.xmlHttpRequest??(i.fetch===void 0?globalThis.XMLHttpRequest:void 0)}),c=P($(l,a),n),d=new v({baseUrl:i.url,publishableKey:i.publishableKey,accessToken:()=>a.accessToken(),webSocket:i.webSocket});a.onChange(h=>{h==="SIGNED_OUT"||h==="SESSION_EXPIRED"||h==="SIGNED_IN"?d.disconnect():h==="TOKEN_REFRESHED"&&d.tokenChanged()});let u=new w($(l,a),a,t);i.analytics&&u.start(i.analytics===!0?{}:i.analytics);let k=new Map,ce=h=>{let j=new URL(h).origin,T=k.get(j);return T||(T=P($(_({baseUrl:j,credentials:{accessToken:()=>a.accessToken()},fetch:i.fetch}),a),n),k.set(j,T)),T},H=Object.assign(Object.create(Y),{auth:new I(c,r,a,i.webauthn??globalThis.navigator?.credentials),socket:d,transport:c,analytics:u,purchases:new b(c,a,d,e,i.fetch,i.appVersion,i.appId),ai:new S(c,a)});return z(H,t,ce,c,d),H}function Oe(){try{return typeof globalThis.localStorage<"u"}catch{return!1}}function $(i,e){return{async send(t){let s=await e.session();try{return await i.send(t)}catch(n){let r=t.auth.some(o=>o.includes("userJWT"));if(!(n instanceof f)||n.status!==401||!Re.has(n.code)||!r||!s)throw n;try{e.snapshot()?.refreshToken===s.refreshToken&&await e.refresh()}catch{throw n}if(e.snapshot()?.userId!==s.userId)throw n;return i.send(t)}}}}export{S as AI,w as Analytics,de as BackendError,M as Channel,U as ChatSession,f as PalbaseError,b as Purchases,v as RealtimeSocket,ue as RoomError,y as SessionChangedError,Ae as createClient,he as isBackendError,F as localStore,V as memoryStore};
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import{a as t,b as r,c as a,d as o,e as p,f as n,g as i,h as m}from"../chunks/3ALGILOX.js";import{a as y,b as s,e as l}from"../chunks/G7E26S3Y.js";import"../chunks/5ZJCEQV5.js";import"../chunks/OIA7KLRW.js";import"../chunks/AIIKXCWN.js";import"../chunks/ZBOJEH7K.js";import{b as e}from"../chunks/JS3TTUHS.js";import"../chunks/X3MTLJRV.js";import"../chunks/SU7BP6VF.js";export{n as Analytics,y as BackendError,o as Channel,l as GatewayError,e as PalbaseError,i as Purchases,p as RealtimeSocket,t as SessionChangedError,m as createClient,s as isBackendError,a as localStore,r as memoryStore};
package/dist/web/palbe.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
2
- import{c as e,d as r,h as t}from"../chunks/JHQDWDV3.js";import"../chunks/5G3URQAW.js";import"../chunks/HLYQRT7O.js";import"../chunks/TPBWIRHS.js";import"../chunks/MYNCDAKM.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import{c as e,d as r,h as t}from"../chunks/G7E26S3Y.js";import"../chunks/OIA7KLRW.js";import"../chunks/ZBOJEH7K.js";import"../chunks/JS3TTUHS.js";import"../chunks/X3MTLJRV.js";import"../chunks/SU7BP6VF.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
2
- import{a as e,b as a,c as t,d as l,e as o,f as p,g as r,h as y,i as s,j as P,k as i,l as n,m as w,n as f,o as d,p as m,q as u,r as A,s as c,t as v}from"../chunks/6I6CETZY.js";import"../chunks/HLYQRT7O.js";import"../chunks/TPBWIRHS.js";import"../chunks/MYNCDAKM.js";export{w as PAYWALL_COMPONENTS,i as PAYWALL_ICONS,n as PAYWALL_SCHEMA,c as Paywall,a as assetId,p as attributesHeader,f as countdownValues,v as defaultPaywall,e as fontFamily,s as formatPeriod,y as formatPrice,o as htmlDocument,P as packageValues,d as packagesOf,r as parseDuration,t as prepareAssets,A as renderPaywall,m as resolvePaywall,u as resolvePaywallWithPaths,l as unzip};
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import{a as e,b as a,c as t,d as l,e as o,f as p,g as r,h as y,i as s,j as P,k as i,l as n,m as w,n as f,o as d,p as m,q as u,r as A,s as c,t as v}from"../chunks/5ZJCEQV5.js";import"../chunks/JS3TTUHS.js";import"../chunks/X3MTLJRV.js";import"../chunks/SU7BP6VF.js";export{w as PAYWALL_COMPONENTS,i as PAYWALL_ICONS,n as PAYWALL_SCHEMA,c as Paywall,a as assetId,p as attributesHeader,f as countdownValues,v as defaultPaywall,e as fontFamily,s as formatPeriod,y as formatPrice,o as htmlDocument,P as packageValues,d as packagesOf,r as parseDuration,t as prepareAssets,A as renderPaywall,m as resolvePaywall,u as resolvePaywallWithPaths,l as unzip};
@@ -0,0 +1,2 @@
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import{h as f}from"../chunks/3ALGILOX.js";import"../chunks/G7E26S3Y.js";import"../chunks/5ZJCEQV5.js";import"../chunks/OIA7KLRW.js";import"../chunks/AIIKXCWN.js";import"../chunks/ZBOJEH7K.js";import"../chunks/JS3TTUHS.js";import"../chunks/X3MTLJRV.js";import"../chunks/SU7BP6VF.js";var C=Object.freeze({"Cache-Control":"private, no-cache, no-store, must-revalidate, max-age=0",Expires:"0",Pragma:"no-cache"}),x={path:"/",sameSite:"lax",secure:!0,httpOnly:!1,maxAge:400*24*60*60},u=3180,k=5*6e4;function d(t){let e=/^pb_([a-z0-9]+)_c/.exec(t)?.[1];if(e===void 0)throw new TypeError("publishableKey is the project publishable key (pb_<ref>_c\u2026)");return`pb-${e}-session`}var y=t=>{let e=new TextEncoder().encode(JSON.stringify(t)),o="";for(let s of e)o+=String.fromCharCode(s);return btoa(o).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},b=t=>{try{let e=atob(t.replace(/-/g,"+").replace(/_/g,"/")),o=JSON.parse(new TextDecoder().decode(Uint8Array.from(e,s=>s.charCodeAt(0))));return typeof o.accessToken!="string"||typeof o.refreshToken!="string"||typeof o.expiresAt!="number"||typeof o.userId!="string"?null:o}catch{return null}};function m(t,e,o={},s=!1){let c={...x,...o},g=async()=>new Map((await e.getAll()).map(n=>[n.name,n.value])),S=n=>n===t||n.startsWith(`${t}.`)&&/^\d+$/.test(n.slice(t.length+1)),h=async n=>{if(!e.setAll)return;let i=n===null?[]:n.length<=u?[[t,n]]:Array.from({length:Math.ceil(n.length/u)},(r,l)=>[`${t}.${l}`,n.slice(l*u,(l+1)*u)]),p=new Set(i.map(([r])=>r)),a=i.map(([r,l])=>({name:r,value:l,options:c}));for(let r of(await g()).keys())S(r)&&!p.has(r)&&a.push({name:r,value:"",options:{...c,maxAge:0}});a.length>0&&await e.setAll(a,{...C})};return{async load(){let n=await g(),i=n.get(t);if(i===void 0){let p="";for(let a=0;n.has(`${t}.${a}`);a++)p+=n.get(`${t}.${a}`);i=p}return i?b(i):null},save:n=>h(y(n)),clear:()=>h(null),shared:s}}function A(t){let{cookies:e,cookieOptions:o,...s}=t,c=t.refresh??(e.setAll?"before":"never");return f({...s,refresh:c,storage:m(d(t.publishableKey),e,o)})}function O(){let t=()=>{let e=globalThis.document;if(!e)throw new Error("documentCookies: there is no document here \u2014 a server gives its request's cookies to createServerClient");return e};return{getAll:()=>t().cookie.split(";").map(e=>e.trim()).filter(e=>e.includes("=")).map(e=>{let o=e.indexOf("=");return{name:e.slice(0,o),value:e.slice(o+1)}}),setAll(e){for(let o of e){let s=o.options,c=[`Path=${s.path??"/"}`,s.domain?`Domain=${s.domain}`:"",s.maxAge!==void 0?`Max-Age=${s.maxAge}`:"",s.expires?`Expires=${s.expires.toUTCString()}`:"",s.sameSite?`SameSite=${s.sameSite.charAt(0).toUpperCase()}${s.sameSite.slice(1)}`:"",s.secure?"Secure":""].filter(Boolean);t().cookie=[`${o.name}=${o.value}`,...c].join("; ")}}}}function $(t){let{cookieOptions:e,...o}=t,s=globalThis.location?.protocol==="https:";return f({...o,storage:m(d(t.publishableKey),O(),{secure:s,...e},!0)})}async function v(t){let e=await t.auth.currentSession();if(!e||(e.expiresAt-Date.now()<=k&&await t.auth.refreshSession().catch(()=>{}),!await t.auth.currentSession()))return null;try{return(await t.auth.api.verifyTokenUser()).data}catch(o){if(o.status===401)return null;throw o}}export{C as NO_STORE_HEADERS,x as SESSION_COOKIE_OPTIONS,m as cookieSessionStore,$ as createBrowserClient,A as createServerClient,O as documentCookies,v as keepSession,d as sessionCookieName};
package/dist/web/vite.js CHANGED
@@ -1,3 +1,3 @@
1
- /*! palbase 0.5.2 — Palbase SDK License (see LICENSE) */
2
- import"../chunks/MYNCDAKM.js";import{execFile as $}from"node:child_process";import{existsSync as y,mkdtempSync as k,readFileSync as S,rmSync as x,writeFileSync as P}from"node:fs";import{createRequire as O}from"node:module";import{tmpdir as W}from"node:os";import{dirname as g,join as o,relative as u,resolve as v,sep as d}from"node:path";var E=/\.(?:ts|js|mts|mjs)$/;function F(n){if(!/^[a-z][a-z0-9-]*$/.test(n.app))throw new TypeError(`palbase({ app }): ${JSON.stringify(n.app)} is an app's slug (palbase apps:list)`);let c=process.cwd(),p="",i="",f=()=>v(c,n.dir??"palbase"),m=()=>{let e=n.environments[p];if(!e)throw new Error(`palbase: the mode "${p}" is not built against any environment \u2014 say which in vite.config: palbase({ environments: { ${JSON.stringify(p)}: '<environment slug>' } })`);return e};return{name:"palbase",enforce:"pre",config(e,s){p=s.mode,i=s.command??"";let r=e.build?.rollupOptions?.onwarn;return{build:{rollupOptions:{onwarn(t,a){let l=String(t.exporter??t.id??"");if(t.code==="MISSING_EXPORT"&&l.includes(`${d}environments${d}`))throw new Error(`palbase: ${t.message} \u2014 ${m()}'s backend has no such route (palbase apps:sync brings what it has)`);r?r(t,a):a(t)}}}}},configResolved(e){c=e.root,p=e.mode,i=e.command??i},async buildStart(){i!=="build"||n.typecheck===!1||await j(c,m(),n.tsconfig)},resolveId(e,s){if(!s)return null;let r=f();if(e==="palbase"||e.startsWith("palbase/")){let w=u(r,s);return w.startsWith("..")||w===""?null:this.resolve(e,o(c,"index.html"),{skipSelf:!0})}if(!(e.startsWith(".")||e.startsWith("/")))return null;let t=v(g(s),e);if(E.test(t)||(t+=".ts"),g(t)!==r&&g(t)!==o(r,"palbe"))return null;let a=u(r,t),l=`${n.app}.ts`;if(a!==l&&!a.startsWith(`palbe${d}`))return null;let h=m(),b=o(r,"environments",h,a===l?l:o("palbe",a.slice(`palbe${d}`.length)));if(!y(b))throw new Error(`palbase: ${u(c,b)} is not there \u2014 palbase apps:sync writes it (is ${n.app} set in ${h}, and has ${h} that machine?)`);return b}}}async function j(n,c,p){let i=p?v(n,p):["tsconfig.app.json","tsconfig.json"].map(e=>o(n,e)).find(y);if(!i)return;if(!y(i))throw new Error(`palbase({ tsconfig }): ${u(n,i)} is not there`);let f;try{let e=O(o(n,"package.json")).resolve("typescript/package.json"),s=JSON.parse(S(e,"utf8")).bin?.tsc;if(!s)throw new Error("no tsc");f=o(g(e),s)}catch{throw new Error("palbase: the build type-checks the app against its environment with the app's TypeScript, and the app has none (npm i -D typescript) \u2014 or say palbase({ typecheck: false })")}let m=k(o(W(),"palbase-typecheck-"));try{let e=o(m,"tsconfig.json");P(e,JSON.stringify({extends:i,compilerOptions:{noEmit:!0,composite:!1,incremental:!1,moduleSuffixes:[`.${c}`,""]}}));let s=await new Promise(r=>$(process.execPath,[f,"-p",e,"--pretty","false"],{cwd:n,maxBuffer:16<<20},(t,a,l)=>r({code:t?typeof t.code=="number"?t.code:1:0,text:`${a}${l}`.trim()})));if(s.code!==0)throw new Error(`palbase: the app does not type-check against ${c}, the environment this build is made for \u2014 a route its backend does not have, or a call that does not fit it:
1
+ /*! palbase 0.7.0 — Palbase SDK License (see LICENSE) */
2
+ import"../chunks/SU7BP6VF.js";import{execFile as $}from"node:child_process";import{existsSync as y,mkdtempSync as k,readFileSync as S,rmSync as x,writeFileSync as P}from"node:fs";import{createRequire as O}from"node:module";import{tmpdir as W}from"node:os";import{dirname as g,join as o,relative as u,resolve as v,sep as d}from"node:path";var E=/\.(?:ts|js|mts|mjs)$/;function F(n){if(!/^[a-z][a-z0-9-]*$/.test(n.app))throw new TypeError(`palbase({ app }): ${JSON.stringify(n.app)} is an app's slug (palbase apps:list)`);let c=process.cwd(),p="",i="",f=()=>v(c,n.dir??"palbase"),m=()=>{let e=n.environments[p];if(!e)throw new Error(`palbase: the mode "${p}" is not built against any environment \u2014 say which in vite.config: palbase({ environments: { ${JSON.stringify(p)}: '<environment slug>' } })`);return e};return{name:"palbase",enforce:"pre",config(e,s){p=s.mode,i=s.command??"";let r=e.build?.rollupOptions?.onwarn;return{build:{rollupOptions:{onwarn(t,a){let l=String(t.exporter??t.id??"");if(t.code==="MISSING_EXPORT"&&l.includes(`${d}environments${d}`))throw new Error(`palbase: ${t.message} \u2014 ${m()}'s backend has no such route (palbase apps:sync brings what it has)`);r?r(t,a):a(t)}}}}},configResolved(e){c=e.root,p=e.mode,i=e.command??i},async buildStart(){i!=="build"||n.typecheck===!1||await j(c,m(),n.tsconfig)},resolveId(e,s){if(!s)return null;let r=f();if(e==="palbase"||e.startsWith("palbase/")){let w=u(r,s);return w.startsWith("..")||w===""?null:this.resolve(e,o(c,"index.html"),{skipSelf:!0})}if(!(e.startsWith(".")||e.startsWith("/")))return null;let t=v(g(s),e);if(E.test(t)||(t+=".ts"),g(t)!==r&&g(t)!==o(r,"palbe"))return null;let a=u(r,t),l=`${n.app}.ts`;if(a!==l&&!a.startsWith(`palbe${d}`))return null;let h=m(),b=o(r,"environments",h,a===l?l:o("palbe",a.slice(`palbe${d}`.length)));if(!y(b))throw new Error(`palbase: ${u(c,b)} is not there \u2014 palbase apps:sync writes it (is ${n.app} set in ${h}, and has ${h} that machine?)`);return b}}}async function j(n,c,p){let i=p?v(n,p):["tsconfig.app.json","tsconfig.json"].map(e=>o(n,e)).find(y);if(!i)return;if(!y(i))throw new Error(`palbase({ tsconfig }): ${u(n,i)} is not there`);let f;try{let e=O(o(n,"package.json")).resolve("typescript/package.json"),s=JSON.parse(S(e,"utf8")).bin?.tsc;if(!s)throw new Error("no tsc");f=o(g(e),s)}catch{throw new Error("palbase: the build type-checks the app against its environment with the app's TypeScript, and the app has none (npm i -D typescript) \u2014 or say palbase({ typecheck: false })")}let m=k(o(W(),"palbase-typecheck-"));try{let e=o(m,"tsconfig.json");P(e,JSON.stringify({extends:i,compilerOptions:{noEmit:!0,composite:!1,incremental:!1,moduleSuffixes:[`.${c}`,""]}}));let s=await new Promise(r=>$(process.execPath,[f,"-p",e,"--pretty","false"],{cwd:n,maxBuffer:16<<20},(t,a,l)=>r({code:t?typeof t.code=="number"?t.code:1:0,text:`${a}${l}`.trim()})));if(s.code!==0)throw new Error(`palbase: the app does not type-check against ${c}, the environment this build is made for \u2014 a route its backend does not have, or a call that does not fit it:
3
3
  ${s.text}`)}finally{x(m,{recursive:!0,force:!0})}}export{F as palbase};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "palbase",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "description": "Palbase for JavaScript: the web client (palbase/web), the server SDK (palbase/server), the backend framework (palbase/backend), AI (palbase/ai) and the CLI (npx palbase).",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://palbase.studio",
@@ -26,6 +26,10 @@
26
26
  "types": "./types/web/src/paywall/index.d.ts",
27
27
  "default": "./dist/web/paywall.js"
28
28
  },
29
+ "./web/ssr": {
30
+ "types": "./types/web/src/ssr.d.ts",
31
+ "default": "./dist/web/ssr.js"
32
+ },
29
33
  "./web/vite": {
30
34
  "types": "./types/web/src/vite.d.ts",
31
35
  "default": "./dist/web/vite.js"
@@ -105,7 +109,7 @@
105
109
  "README.md"
106
110
  ],
107
111
  "dependencies": {
108
- "palgres": "0.5.2",
112
+ "palgres": "0.7.0",
109
113
  "reflect-metadata": "^0.2.2",
110
114
  "typescript": "~6.0.3",
111
115
  "zod": "^4.6.5"
@@ -213,17 +213,15 @@ export interface AI {
213
213
  * Made once, at a module's top level.
214
214
  */
215
215
  tool<S extends StandardSchema>(tool: BackendToolOptions<S>): BackendTool<S>;
216
- /** A tool the app's code answers (pb.ai.chat(id).tools({ name: fn })): the turn waits for it. */
216
+ /** A tool the app answers — through its gateway, whose backend gives the answer (chats.answer): the turn waits for it. */
217
217
  clientTool<S extends StandardSchema>(tool: ClientToolOptions<S>): ClientTool;
218
218
  /**
219
219
  * An agent the backend defines at each turn's start, from the turn's
220
220
  * context: put it with ai.agents.put(agent), and its chats' turns ask the
221
- * machine for it — clients: true, and the app's users start chats with it
222
- * themselves. Made once, at a module's top level.
221
+ * machine for it. Made once, at a module's top level.
223
222
  */
224
223
  agent(name: string, define: (ctx: AgentContext) => TurnDefinition | Promise<TurnDefinition>, options?: {
225
224
  machine?: string;
226
- clients?: boolean;
227
225
  }): BackendAgent;
228
226
  /**
229
227
  * A GitHub repository a chat's workspace works in, whose tokens this
@@ -1,4 +1,3 @@
1
- import { type ChatStream, type FollowChatOptions } from '../../internal/src/chat.js';
2
1
  import type * as modules from '../../internal/src/modules/index.js';
3
2
  import { type ToolResult } from '../../internal/src/tool-output.js';
4
3
  import { type AgentDefinitionInput, type BackendAgent, type BackendRepo } from './tools.js';
@@ -10,7 +9,7 @@ export type Endpoint = modules.ai.Endpoint;
10
9
  export type Decision = modules.ai.Decision;
11
10
  /** What the project allows its chats. */
12
11
  export interface AISettings {
13
- /** The app's users talk to the project's agents with their own session: start a chat with a named agent, write to the chats they are in. */
12
+ /** The app's users reach the chats they are members of with their own session (the server starts every chat). */
14
13
  clients: boolean;
15
14
  /** How many messages one user sends a minute. */
16
15
  userMessagesPerMinute: number;
@@ -163,28 +162,59 @@ export interface Chats {
163
162
  messages: ChatMessage[];
164
163
  nextCursor?: string;
165
164
  }>;
166
- /** What happens in the chat as typed parts, as it happens, followed again after a cut from where the reader is: read with for await, stopped with break or signal. */
167
- stream(id: string, options?: FollowChatOptions): ChatStream;
165
+ /**
166
+ * What happens in the chat — its messages, its turns, the answer as it is written, the tools and subagents — as a
167
+ * source a gateway pipes into its channel: `ctx.pipe(Palbase.ai.chats.events(id))`. The platform writes the chat
168
+ * into the channel itself from then on; the backend is not in the stream, and the gateway's members hear it.
169
+ */
170
+ events(id: string): ChatEvents;
168
171
  /** Stops the turn it is working on: what it wrote stays. Its response's id, or null when none ran. */
169
172
  stop(id: string): Promise<string | null>;
170
- /** A tool call that waits for a person's yes (a tool event's approval_id): made. */
171
- approve(id: string, approvalId: string, reason?: string): Promise<Decision>;
173
+ /**
174
+ * A tool call that waits for a person's yes (a tool event's approval_id): made. As a member (as), the server is held to
175
+ * their rules — a turn another member began is not theirs to decide (403 not_your_turn); without it, the server decides any.
176
+ */
177
+ approve(id: string, approvalId: string, options?: {
178
+ reason?: string;
179
+ as?: string;
180
+ }): Promise<Decision>;
172
181
  /** Not made: the agent is told, with the reason, and goes on. */
173
- deny(id: string, approvalId: string, reason?: string): Promise<Decision>;
174
- /** The answer of a client tool's call (a tool event's call_id): true when it is the one taken, false when another came first. */
182
+ deny(id: string, approvalId: string, options?: {
183
+ reason?: string;
184
+ as?: string;
185
+ }): Promise<Decision>;
186
+ /**
187
+ * The answer of a client tool's call (a tool event's call_id): true when it is the one taken, false when another came
188
+ * first. As a member (as): the app of the member whose turn it is answers it (403 not_your_turn otherwise).
189
+ */
175
190
  answer(id: string, callId: string, output: ToolResult, options?: {
176
191
  isError?: boolean;
192
+ as?: string;
177
193
  }): Promise<boolean>;
178
- /** A message for one of the agent's subagents at work (an agent event's run_id), at its next step. */
194
+ /** A message for one of the agent's subagents at work (an agent event's run_id), at its next step — as a member, held to their rules. */
179
195
  sendToSubagent(id: string, runId: string, text: string, options?: {
180
196
  clientId?: string;
197
+ as?: string;
181
198
  }): Promise<{
182
199
  runId: string;
183
200
  clientId: string;
184
201
  }>;
185
202
  }
203
+ /** A chat's stream as a gateway pipes it into its channel (gateways' PipeSource). */
204
+ export interface ChatEvents {
205
+ readonly kind: 'ai.chat';
206
+ readonly chatId: string;
207
+ /** Writes the chat into the channel from now on — from its start, for a channel that had not been its own. */
208
+ pipe(topic: string, options?: {
209
+ signal?: AbortSignal;
210
+ }): Promise<void>;
211
+ /** Writes it nowhere from now on. */
212
+ unpipe(options?: {
213
+ signal?: AbortSignal;
214
+ }): Promise<void>;
215
+ }
186
216
  export interface Agents {
187
- /** Names an agent: its definition, or a backend's ai.agent (its chats' turns ask the backend's machine); clients: true lets the app's users start chats with it. */
217
+ /** Names an agent: its definition, or a backend's ai.agent (its chats' turns ask the backend's machine). */
188
218
  put(name: string, definition: AgentDefinitionInput | BackendAgent): Promise<Agent>;
189
219
  put(agent: BackendAgent): Promise<Agent>;
190
220
  list(): Promise<Agent[]>;
@@ -4,7 +4,7 @@ export { AISchemaError, prepare } from './schema.js';
4
4
  export { ToolError } from './tools.js';
5
5
  export type { Infer, StandardSchema } from './schema.js';
6
6
  export { partial } from './partial.js';
7
- export type { AISettings, Agent, Agents, Chat, ChatMessage, Chats, CreateChat, Decision, Endpoint, EndpointInput, Endpoints, MemberInput, Repo, Repos, SendMessage, Settings, TurnArtifact, TurnCost } from './chats.js';
7
+ export type { AISettings, Agent, Agents, Chat, ChatEvents, ChatMessage, Chats, CreateChat, Decision, Endpoint, EndpointInput, Endpoints, MemberInput, Repo, Repos, SendMessage, Settings, TurnArtifact, TurnCost } from './chats.js';
8
8
  export type { AgentContext, AgentDefinitionInput, BackendAgent, BackendRepo, BackendTool, BackendToolOptions, ChatContext, ClientTool, ClientToolOptions, HttpsToolRef, McpToolRef, SubagentDefinition, Tool, ToolContext, TurnDefinition, } from './tools.js';
9
- export type { AgentEvent, ChatEvent, ChatPosition, ChatStream, MessageEvent, ResetEvent, TextEvent, ToolEvent, ToolStatus, TurnEvent, TurnStatus, WaitingReason } from '../../internal/src/chat.js';
9
+ export type { AgentEvent, ChatEvent, MessageEvent, ResetEvent, TextEvent, ToolEvent, ToolStatus, TurnEvent, TurnStatus, WaitingReason } from '../../internal/src/chat.js';
10
10
  export type { ToolPart, ToolResult } from '../../internal/src/tool-output.js';
@@ -73,7 +73,7 @@ export interface ClientToolOptions<S extends StandardSchema> {
73
73
  input?: S;
74
74
  approval?: boolean;
75
75
  }
76
- /** A tool the app's code answers (pb.ai.chat(id).tools({ name: fn })): the turn waits for its answer. */
76
+ /** A tool the app answers — through its gateway, whose backend gives the answer (chats.answer): the turn waits for it. */
77
77
  export interface ClientTool {
78
78
  readonly source: 'client';
79
79
  readonly name: string;
@@ -116,19 +116,15 @@ export interface AgentDefinitionInput {
116
116
  subagents?: SubagentDefinition[];
117
117
  /** How many tool calls a turn makes at most (1–200): past it the agent is told it has no tools left and answers. */
118
118
  maxToolCalls?: number;
119
- /** A named agent's: the app's users start chats with it themselves (when the project lets them). Left out, the server's alone. */
120
- clients?: boolean;
121
119
  }
122
- /** What a backend's agent is for one turn: whether users reach it is the named agent's, said when it is put. */
123
- export type TurnDefinition = Omit<AgentDefinitionInput, 'clients'>;
120
+ /** What a backend's agent is for one turn. */
121
+ export type TurnDefinition = AgentDefinitionInput;
124
122
  /** An agent the backend defines at each turn's start: put with ai.agents.put(agent), its chats' turns ask its machine. */
125
123
  export interface BackendAgent {
126
124
  readonly kind: 'agent';
127
125
  readonly name: string;
128
126
  /** The project's machine that defines it (default backend). */
129
127
  readonly machine?: string;
130
- /** The app's users start chats with it themselves (put with it). */
131
- readonly clients: boolean;
132
128
  /** The definition for a turn, said as the platform takes it, with the backend tools it hands out. */
133
129
  resolve(ctx: AgentContext): Promise<{
134
130
  definition: AgentDefinition;
@@ -193,7 +189,6 @@ export declare function backendRepo(options: {
193
189
  }): BackendRepo;
194
190
  export declare function backendAgent(name: string, define: (ctx: AgentContext) => TurnDefinition | Promise<TurnDefinition>, options?: {
195
191
  machine?: string;
196
- clients?: boolean;
197
192
  }): BackendAgent;
198
193
  /** A tool as the platform takes it (ToolRef). */
199
194
  export declare function toolRef(t: Tool, what: string): ToolRef;
@@ -28,8 +28,8 @@ export declare class Container {
28
28
  readonly cronProviders: Ctor[];
29
29
  /** The providers that are @Task classes: the platform runs them as their tasks come due. */
30
30
  readonly taskProviders: Ctor[];
31
- /** The providers that are @Room classes. */
32
- readonly rooms: Ctor[];
31
+ /** The providers that are @Gateway classes. */
32
+ readonly gateways: Ctor[];
33
33
  constructor(modules: Function[]);
34
34
  private collect;
35
35
  private validate;
@@ -1,7 +1,6 @@
1
1
  import { type PalbaseServer, type TokenUser, type TokenVerifier, type WebhookEvent } from '../../server/src/index.js';
2
2
  import { type AuthSpec, type RateLimitConfig } from './decorators.js';
3
3
  import { type ContractOptions } from './openapi.js';
4
- import { type ChannelsDef } from './channels.js';
5
4
  import { type StringsTable } from './i18n.js';
6
5
  import type { RequestTelemetry } from './requests.js';
7
6
  /** The signed-in user, as @User() gives it. */
@@ -63,8 +62,6 @@ export interface AppOptions {
63
62
  cors?: CorsOptions;
64
63
  /** The framework's own handlers of the platform's events (user.deleted → forget), run before the app's @On. */
65
64
  events?: Record<string, ((event: WebhookEvent) => Promise<unknown>)[]>;
66
- /** The app's channels; the ones defineChannels declared in this process unless given (a test's own). */
67
- channels?: ChannelsDef;
68
65
  /** The app's database: each request (and each delivery) one transaction, as its caller or as the service role. */
69
66
  database?: {
70
67
  app: RequestDatabases;
@@ -104,7 +101,7 @@ export interface AppOptions {
104
101
  * never to be done (TaskFailure, or a payload its schema refuses), or the
105
102
  * failure the platform tries again;
106
103
  * - its @Upload routes' two steps, from storage (upload.ts), and its
107
- * @Room classes' joins, messages and moments, from realtime (rooms.ts):
104
+ * @Gateway classes' joins, messages and moments, from realtime (gateways.ts):
108
105
  * platform-calls.ts;
109
106
  * - its ai tools and agents (@palbase/ai's ai.tool and ai.agent), from the
110
107
  * ai module: POST /_palbase/ai/tools runs the tool an agent called (its