@sable-ai/sdk-core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +1 -1
- package/dist/sable.iife.js +1 -1
- package/dist/types/session/index.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/index.test.ts +2 -2
- package/src/version.ts +1 -1
package/dist/esm/index.js
CHANGED
package/dist/sable.iife.js
CHANGED
|
@@ -1483,4 +1483,4 @@ console.log(' await new Wireframe().toDataURL() — base64 for LLM');
|
|
|
1483
1483
|
});
|
|
1484
1484
|
${fs};
|
|
1485
1485
|
return Wireframe;
|
|
1486
|
-
})()`);return tr}var er=null;function fu(){if(!er)er=(0,eval)(`(${hs})`);return er}async function us(){let t=fu()();return{screenshot_jpeg_b64:(await new(Dl())(document.body,{}).toDataURL()).replace(/^data:[^,]+,/,""),elements:t,viewport:{width:window.innerWidth,height:window.innerHeight},url:window.location.href}}async function ds(){let t=()=>new Promise((e)=>requestAnimationFrame(()=>requestAnimationFrame(()=>e())));await t(),await new Promise((e)=>{let r=performance.now(),o=performance.now(),s=new MutationObserver(()=>{o=performance.now()});s.observe(document.documentElement,{subtree:!0,childList:!0,attributes:!0,characterData:!0});let c=()=>{let i=performance.now();if(i-o>=30){s.disconnect(),e();return}if(i-r>=30){s.disconnect(),e();return}requestAnimationFrame(c)};requestAnimationFrame(c)}),await t()}function Qe(t,e){return async(l)=>{let n={};try{n=l.payload?JSON.parse(l.payload):{}}catch(r){console.warn(`[Sable] ${t}: bad JSON payload`,r)}try{let r=await e(n);return JSON.stringify(r??{})}catch(r){let o=r instanceof Error?r.message:String(r);return console.warn(`[Sable] ${t}: handler error`,o),JSON.stringify({error:o})}}}function as(t){t.registerRpcMethod("browser.execute_action",Qe("browser.execute_action",async(e)=>{let l=e.action;if(!l||typeof l!=="object")throw Error("execute_action: missing action");return await cs(l),{}})),t.registerRpcMethod("browser.get_dom_state",Qe("browser.get_dom_state",async()=>us())),t.registerRpcMethod("browser.get_url",Qe("browser.get_url",async()=>({url:window.location.href}))),t.registerRpcMethod("browser.get_viewport",Qe("browser.get_viewport",async()=>({width:window.innerWidth,height:window.innerHeight}))),t.registerRpcMethod("browser.verify_selector",Qe("browser.verify_selector",async(e)=>{let l=typeof e.selector==="string"?e.selector:"",n=!1;try{n=!!document.querySelector(l)}catch{n=!1}return{matches:n}})),t.registerRpcMethod("browser.settle",Qe("browser.settle",async()=>{return await ds(),{}})),console.log("[Sable] browser bridge RPCs registered")}var uu=2;function du(t){let e=typeof t==="number"&&t>0?t:uu;return Math.max(1,Math.round(1000/e))}function au(t){let e=Math.max(1,window.innerWidth),l=Math.max(1,window.innerHeight);if(t.width!==e||t.height!==l)t.width=e,t.height=l}function bs(t,e){let l=e.getContext("2d",{alpha:!1});if(!l)return console.warn("[Sable] frame source: 2d context unavailable"),()=>{};let n=du(t.rate),r=!1,o,s=!1,c=async()=>{if(r)return;if(!s){s=!0;try{if(au(e),t.type==="wireframe"){let i=t.features?.includeImages===!0,f=new(Dl())(document.body,{images:i}),{canvas:u}=await f.capture();l.fillStyle="#ffffff",l.fillRect(0,0,e.width,e.height),l.drawImage(u,0,0,e.width,e.height)}else if(t.type==="fn"){let i=t.captureFn();l.fillStyle="#ffffff",l.fillRect(0,0,e.width,e.height),l.drawImage(i,0,0,e.width,e.height)}}catch(i){console.warn("[Sable] frame source tick failed",i)}finally{s=!1}}if(!r)o=setTimeout(c,n)};return c(),()=>{if(r=!0,o!==void 0)clearTimeout(o)}}async function xs(t,e,l,n){let o=l.captureStream(n).getVideoTracks();if(o.length===0)throw Error("canvas.captureStream produced no video tracks");let s=o[0],c=new e.LocalVideoTrack(s,void 0,!0),i=await t.localParticipant.publishTrack(c,{source:e.Track.Source.ScreenShare,name:"browser"});return console.log("[Sable] vision track published",{trackSid:i.trackSid,fps:n}),async()=>{try{await t.localParticipant.unpublishTrack(c,!0)}catch(h){console.warn("[Sable] vision unpublishTrack failed",h)}try{s.stop()}catch{}console.log("[Sable] vision track stopped")}}var bu={type:"wireframe",rate:2,features:{includeImages:!1}};async function gs(t){let e=t.options.frameSource??bu,l=typeof e.rate==="number"&&e.rate>0?e.rate:2,n=document.createElement("canvas");n.width=Math.max(1,window.innerWidth),n.height=Math.max(1,window.innerHeight);let r=bs(e,n),o;try{o=await xs(t.room,t.lib,n,l)}catch(s){throw r(),s}return{canvas:n,stop:async()=>{r(),await o()}}}var Yl="0.1.0";function lr(){try{let t=window.localStorage?.getItem("sable:debug:panel");if(!t)return{};let e=JSON.parse(t);return typeof e==="object"&&e!==null?e:{}}catch{return{}}}function ws(t){try{window.localStorage?.setItem("sable:debug:panel",JSON.stringify(t))}catch{}}function ms(t){if(t)return!0;try{if(new URL(window.location.href).searchParams.get("sable-debug")==="1")return!0}catch{}try{if(window.localStorage?.getItem("sable:debug")==="1")return!0}catch{}return!1}function ys(t){let e=lr(),l=document.createElement("div");if(l.setAttribute("data-sable-debug","vision"),Object.assign(l.style,{position:"fixed",width:"240px",zIndex:"2147483647",background:"#111",color:"#ddd",border:"1px solid #444",borderRadius:"8px",font:"11px/1.3 system-ui, sans-serif",boxShadow:"0 8px 24px rgba(0,0,0,.4)",pointerEvents:"none",userSelect:"none",overflow:"hidden"}),typeof e.left==="number"&&typeof e.top==="number")l.style.left=`${e.left}px`,l.style.top=`${e.top}px`;else l.style.right="12px",l.style.top="12px";let n=document.createElement("div");Object.assign(n.style,{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"6px",padding:"6px 8px",background:"#1a1a1a",borderBottom:"1px solid #333",cursor:"move",pointerEvents:"auto"});let r=document.createElement("div");r.textContent="sable: agent vision",Object.assign(r.style,{opacity:"0.75",fontWeight:"600",flex:"1",pointerEvents:"none"}),n.appendChild(r);let o=document.createElement("button");o.setAttribute("aria-label","Minimize vision panel"),Object.assign(o.style,{background:"transparent",color:"#ddd",border:"1px solid #444",borderRadius:"4px",width:"20px",height:"20px",cursor:"pointer",fontSize:"12px",lineHeight:"1",padding:"0",pointerEvents:"auto"}),n.appendChild(o),l.appendChild(n);let s=document.createElement("div");Object.assign(s.style,{padding:"6px",background:"#111",pointerEvents:"none"}),t.style.width="100%",t.style.height="auto",t.style.display="block",t.style.background="#fff",t.style.borderRadius="4px",t.style.pointerEvents="none",s.appendChild(t),l.appendChild(s);let c=!!e.minimized,i=()=>{s.style.display=c?"none":"block",o.textContent=c?"▢":"–",o.setAttribute("aria-label",c?"Restore vision panel":"Minimize vision panel")};i(),o.addEventListener("click",(x)=>{x.stopPropagation(),c=!c,i(),ws({...lr(),minimized:c})});let h=null,f=(x)=>{if(x.target instanceof HTMLElement&&x.target.closest("button"))return;let g=l.getBoundingClientRect();h={offsetX:x.clientX-g.left,offsetY:x.clientY-g.top},l.style.left=`${g.left}px`,l.style.top=`${g.top}px`,l.style.right="auto",l.style.bottom="auto",n.setPointerCapture(x.pointerId),x.preventDefault()},u=(x)=>{if(!h)return;let{innerWidth:g,innerHeight:w}=window,p=l.offsetWidth,y=x.clientX-h.offsetX,$=x.clientY-h.offsetY;y=Math.min(Math.max(y,-p+48),g-48),$=Math.min(Math.max($,0),w-24),l.style.left=`${y}px`,l.style.top=`${$}px`},d=(x)=>{if(!h)return;h=null;try{n.releasePointerCapture(x.pointerId)}catch{}let g=parseFloat(l.style.left)||0,w=parseFloat(l.style.top)||0;ws({...lr(),left:g,top:w})};return n.addEventListener("pointerdown",f),n.addEventListener("pointermove",u),n.addEventListener("pointerup",d),n.addEventListener("pointercancel",d),document.body.appendChild(l),console.log("[Sable] debug vision panel mounted",{minimized:c,restoredPosition:typeof e.left==="number"&&typeof e.top==="number"}),()=>{try{n.removeEventListener("pointerdown",f),n.removeEventListener("pointermove",u),n.removeEventListener("pointerup",d),n.removeEventListener("pointercancel",d),l.remove()}catch{}}}var Gx=5,Pf=500;function zx(t){let e=t.remoteParticipants?Array.from(t.remoteParticipants.values()):[];return e.find((n)=>typeof n.identity==="string"&&n.identity.startsWith("agent"))?.identity??e[0]?.identity??null}async function Ox(t){for(let e=1;e<=Gx;e++){let l=zx(t);if(!l){console.warn("[Sable] sendUiReady: no agent participant yet",{attempt:e}),await new Promise((n)=>setTimeout(n,Pf));continue}try{await t.localParticipant.performRpc({destinationIdentity:l,method:"uiReady",payload:JSON.stringify({timestamp:Date.now()})}),console.log("[Sable] uiReady sent",{identity:l,attempt:e});return}catch(n){console.warn("[Sable] uiReady RPC failed",{attempt:e,err:n}),await new Promise((r)=>setTimeout(r,Pf))}}console.error("[Sable] uiReady: exhausted retries — agent will not greet")}class vo{version=Yl;emitter=new Un;activeRoom=null;visionHandle=null;unmountDebugPanel=null;on(t,e){return this.emitter.on(t,e)}async start(t){if(this.activeRoom)throw Error("Sable already started; call stop() first");let e=t.publicKey??t.agentPublicId;if(!e)throw Error("Sable.start: `publicKey` is required");let l=t.apiUrl??ns;console.log("[Sable] fetching connection details",{apiUrl:l});let n=await rs({apiUrl:l,publicKey:e});console.log("[Sable] connection details received",{roomName:n.roomName,participantName:n.participantName});let r=await Promise.resolve().then(() => (kf(),Ff)),{Room:o,RoomEvent:s,LocalVideoTrack:c,Track:i}=r,h=new o,f={LocalVideoTrack:c,Track:i};if(h.registerRpcMethod("agentReady",async()=>{return console.log("[Sable] RPC agentReady received"),Ox(h),JSON.stringify({success:!0})}),as(h),is(h,t.runtime),this.wireRoomEvents(h,s),await h.connect(n.serverUrl,n.participantToken),await h.localParticipant.setMicrophoneEnabled(!0),this.activeRoom=h,t.vision?.enabled)try{if(this.visionHandle=await gs({room:h,lib:f,options:t.vision}),ms(t.debug))this.unmountDebugPanel=ys(this.visionHandle.canvas)}catch(u){console.warn("[Sable] failed to start vision",u)}console.log("[Sable] session live",{roomName:n.roomName,participantName:n.participantName}),this.emitter.emit("session:started",{roomName:n.roomName,participantName:n.participantName}),setTimeout(()=>{if(this.activeRoom!==h)return;let u=h,x=(u.remoteParticipants?Array.from(u.remoteParticipants.values()):[]).map((w)=>({identity:w.identity,tracks:w.trackPublications?Array.from(w.trackPublications.values()).map((p)=>({kind:p.kind,subscribed:p.isSubscribed})):[]}));if(!x.some((w)=>w.tracks.some((p)=>p.kind==="audio")))console.warn("[Sable] no remote audio track after 10s — agent worker probably failed to publish. Remote participants:",x)},1e4)}async stop(){let t=this.activeRoom;if(!t)return;if(this.activeRoom=null,this.unmountDebugPanel){try{this.unmountDebugPanel()}catch(e){console.warn("[Sable] debug panel unmount failed",e)}this.unmountDebugPanel=null}if(this.visionHandle){try{await this.visionHandle.stop()}catch(e){console.warn("[Sable] vision stop failed",e)}this.visionHandle=null}try{await t.localParticipant.setMicrophoneEnabled(!1)}catch(e){console.warn("[Sable] setMicrophoneEnabled(false) failed",e)}await t.disconnect(),console.log("[Sable] session ended"),this.emitter.emit("session:ended",{})}wireRoomEvents(t,e){t.on(e.ConnectionStateChanged,(l)=>{console.log("[Sable] ConnectionStateChanged",l)}),t.on(e.Disconnected,(l)=>{if(console.log("[Sable] Disconnected",l),this.activeRoom===t)this.stop().catch((n)=>console.warn("[Sable] stop on disconnect failed",n))}),t.on(e.ParticipantConnected,(l)=>{let n=l;console.log("[Sable] ParticipantConnected",{identity:n.identity,sid:n.sid})}),t.on(e.ParticipantDisconnected,(l)=>{console.warn("[Sable] ParticipantDisconnected",{identity:l.identity})}),t.on(e.TrackSubscribed,(l,n,r)=>{let o=l,s=r;if(console.log("[Sable] TrackSubscribed",{kind:o.kind,participant:s.identity}),o.kind==="audio"&&typeof o.attach==="function"){let c=o.attach();c.setAttribute("data-sable","1"),c.setAttribute("playsinline",""),c.autoplay=!0,document.body.appendChild(c),console.log("[Sable] attached remote audio element")}}),t.on(e.TrackUnsubscribed,(l)=>{let n=l;if(typeof n.detach==="function")for(let r of n.detach())r.remove()}),t.on(e.ActiveSpeakersChanged,(l)=>{let n=l??[],r=n.some((s)=>typeof s.identity==="string"&&s.identity.startsWith("agent")),o=n.some((s)=>typeof s.identity==="string"&&!s.identity.startsWith("agent"));this.emitter.emit("agent:speaking",r),this.emitter.emit("user:speaking",o)})}}var Zn=new vo;function Uf(){if(typeof window>"u")return;if(window.Sable)return;window.Sable=Zn,console.log("[Sable] SDK loaded",Zn.version)}Uf();var Yx=Zn;})();
|
|
1486
|
+
})()`);return tr}var er=null;function fu(){if(!er)er=(0,eval)(`(${hs})`);return er}async function us(){let t=fu()();return{screenshot_jpeg_b64:(await new(Dl())(document.body,{}).toDataURL()).replace(/^data:[^,]+,/,""),elements:t,viewport:{width:window.innerWidth,height:window.innerHeight},url:window.location.href}}async function ds(){let t=()=>new Promise((e)=>requestAnimationFrame(()=>requestAnimationFrame(()=>e())));await t(),await new Promise((e)=>{let r=performance.now(),o=performance.now(),s=new MutationObserver(()=>{o=performance.now()});s.observe(document.documentElement,{subtree:!0,childList:!0,attributes:!0,characterData:!0});let c=()=>{let i=performance.now();if(i-o>=30){s.disconnect(),e();return}if(i-r>=30){s.disconnect(),e();return}requestAnimationFrame(c)};requestAnimationFrame(c)}),await t()}function Qe(t,e){return async(l)=>{let n={};try{n=l.payload?JSON.parse(l.payload):{}}catch(r){console.warn(`[Sable] ${t}: bad JSON payload`,r)}try{let r=await e(n);return JSON.stringify(r??{})}catch(r){let o=r instanceof Error?r.message:String(r);return console.warn(`[Sable] ${t}: handler error`,o),JSON.stringify({error:o})}}}function as(t){t.registerRpcMethod("browser.execute_action",Qe("browser.execute_action",async(e)=>{let l=e.action;if(!l||typeof l!=="object")throw Error("execute_action: missing action");return await cs(l),{}})),t.registerRpcMethod("browser.get_dom_state",Qe("browser.get_dom_state",async()=>us())),t.registerRpcMethod("browser.get_url",Qe("browser.get_url",async()=>({url:window.location.href}))),t.registerRpcMethod("browser.get_viewport",Qe("browser.get_viewport",async()=>({width:window.innerWidth,height:window.innerHeight}))),t.registerRpcMethod("browser.verify_selector",Qe("browser.verify_selector",async(e)=>{let l=typeof e.selector==="string"?e.selector:"",n=!1;try{n=!!document.querySelector(l)}catch{n=!1}return{matches:n}})),t.registerRpcMethod("browser.settle",Qe("browser.settle",async()=>{return await ds(),{}})),console.log("[Sable] browser bridge RPCs registered")}var uu=2;function du(t){let e=typeof t==="number"&&t>0?t:uu;return Math.max(1,Math.round(1000/e))}function au(t){let e=Math.max(1,window.innerWidth),l=Math.max(1,window.innerHeight);if(t.width!==e||t.height!==l)t.width=e,t.height=l}function bs(t,e){let l=e.getContext("2d",{alpha:!1});if(!l)return console.warn("[Sable] frame source: 2d context unavailable"),()=>{};let n=du(t.rate),r=!1,o,s=!1,c=async()=>{if(r)return;if(!s){s=!0;try{if(au(e),t.type==="wireframe"){let i=t.features?.includeImages===!0,f=new(Dl())(document.body,{images:i}),{canvas:u}=await f.capture();l.fillStyle="#ffffff",l.fillRect(0,0,e.width,e.height),l.drawImage(u,0,0,e.width,e.height)}else if(t.type==="fn"){let i=t.captureFn();l.fillStyle="#ffffff",l.fillRect(0,0,e.width,e.height),l.drawImage(i,0,0,e.width,e.height)}}catch(i){console.warn("[Sable] frame source tick failed",i)}finally{s=!1}}if(!r)o=setTimeout(c,n)};return c(),()=>{if(r=!0,o!==void 0)clearTimeout(o)}}async function xs(t,e,l,n){let o=l.captureStream(n).getVideoTracks();if(o.length===0)throw Error("canvas.captureStream produced no video tracks");let s=o[0],c=new e.LocalVideoTrack(s,void 0,!0),i=await t.localParticipant.publishTrack(c,{source:e.Track.Source.ScreenShare,name:"browser"});return console.log("[Sable] vision track published",{trackSid:i.trackSid,fps:n}),async()=>{try{await t.localParticipant.unpublishTrack(c,!0)}catch(h){console.warn("[Sable] vision unpublishTrack failed",h)}try{s.stop()}catch{}console.log("[Sable] vision track stopped")}}var bu={type:"wireframe",rate:2,features:{includeImages:!1}};async function gs(t){let e=t.options.frameSource??bu,l=typeof e.rate==="number"&&e.rate>0?e.rate:2,n=document.createElement("canvas");n.width=Math.max(1,window.innerWidth),n.height=Math.max(1,window.innerHeight);let r=bs(e,n),o;try{o=await xs(t.room,t.lib,n,l)}catch(s){throw r(),s}return{canvas:n,stop:async()=>{r(),await o()}}}var Yl="0.1.1";function lr(){try{let t=window.localStorage?.getItem("sable:debug:panel");if(!t)return{};let e=JSON.parse(t);return typeof e==="object"&&e!==null?e:{}}catch{return{}}}function ws(t){try{window.localStorage?.setItem("sable:debug:panel",JSON.stringify(t))}catch{}}function ms(t){if(t)return!0;try{if(new URL(window.location.href).searchParams.get("sable-debug")==="1")return!0}catch{}try{if(window.localStorage?.getItem("sable:debug")==="1")return!0}catch{}return!1}function ys(t){let e=lr(),l=document.createElement("div");if(l.setAttribute("data-sable-debug","vision"),Object.assign(l.style,{position:"fixed",width:"240px",zIndex:"2147483647",background:"#111",color:"#ddd",border:"1px solid #444",borderRadius:"8px",font:"11px/1.3 system-ui, sans-serif",boxShadow:"0 8px 24px rgba(0,0,0,.4)",pointerEvents:"none",userSelect:"none",overflow:"hidden"}),typeof e.left==="number"&&typeof e.top==="number")l.style.left=`${e.left}px`,l.style.top=`${e.top}px`;else l.style.right="12px",l.style.top="12px";let n=document.createElement("div");Object.assign(n.style,{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"6px",padding:"6px 8px",background:"#1a1a1a",borderBottom:"1px solid #333",cursor:"move",pointerEvents:"auto"});let r=document.createElement("div");r.textContent="sable: agent vision",Object.assign(r.style,{opacity:"0.75",fontWeight:"600",flex:"1",pointerEvents:"none"}),n.appendChild(r);let o=document.createElement("button");o.setAttribute("aria-label","Minimize vision panel"),Object.assign(o.style,{background:"transparent",color:"#ddd",border:"1px solid #444",borderRadius:"4px",width:"20px",height:"20px",cursor:"pointer",fontSize:"12px",lineHeight:"1",padding:"0",pointerEvents:"auto"}),n.appendChild(o),l.appendChild(n);let s=document.createElement("div");Object.assign(s.style,{padding:"6px",background:"#111",pointerEvents:"none"}),t.style.width="100%",t.style.height="auto",t.style.display="block",t.style.background="#fff",t.style.borderRadius="4px",t.style.pointerEvents="none",s.appendChild(t),l.appendChild(s);let c=!!e.minimized,i=()=>{s.style.display=c?"none":"block",o.textContent=c?"▢":"–",o.setAttribute("aria-label",c?"Restore vision panel":"Minimize vision panel")};i(),o.addEventListener("click",(x)=>{x.stopPropagation(),c=!c,i(),ws({...lr(),minimized:c})});let h=null,f=(x)=>{if(x.target instanceof HTMLElement&&x.target.closest("button"))return;let g=l.getBoundingClientRect();h={offsetX:x.clientX-g.left,offsetY:x.clientY-g.top},l.style.left=`${g.left}px`,l.style.top=`${g.top}px`,l.style.right="auto",l.style.bottom="auto",n.setPointerCapture(x.pointerId),x.preventDefault()},u=(x)=>{if(!h)return;let{innerWidth:g,innerHeight:w}=window,p=l.offsetWidth,y=x.clientX-h.offsetX,$=x.clientY-h.offsetY;y=Math.min(Math.max(y,-p+48),g-48),$=Math.min(Math.max($,0),w-24),l.style.left=`${y}px`,l.style.top=`${$}px`},d=(x)=>{if(!h)return;h=null;try{n.releasePointerCapture(x.pointerId)}catch{}let g=parseFloat(l.style.left)||0,w=parseFloat(l.style.top)||0;ws({...lr(),left:g,top:w})};return n.addEventListener("pointerdown",f),n.addEventListener("pointermove",u),n.addEventListener("pointerup",d),n.addEventListener("pointercancel",d),document.body.appendChild(l),console.log("[Sable] debug vision panel mounted",{minimized:c,restoredPosition:typeof e.left==="number"&&typeof e.top==="number"}),()=>{try{n.removeEventListener("pointerdown",f),n.removeEventListener("pointermove",u),n.removeEventListener("pointerup",d),n.removeEventListener("pointercancel",d),l.remove()}catch{}}}var Gx=5,Pf=500;function zx(t){let e=t.remoteParticipants?Array.from(t.remoteParticipants.values()):[];return e.find((n)=>typeof n.identity==="string"&&n.identity.startsWith("agent"))?.identity??e[0]?.identity??null}async function Ox(t){for(let e=1;e<=Gx;e++){let l=zx(t);if(!l){console.warn("[Sable] sendUiReady: no agent participant yet",{attempt:e}),await new Promise((n)=>setTimeout(n,Pf));continue}try{await t.localParticipant.performRpc({destinationIdentity:l,method:"uiReady",payload:JSON.stringify({timestamp:Date.now()})}),console.log("[Sable] uiReady sent",{identity:l,attempt:e});return}catch(n){console.warn("[Sable] uiReady RPC failed",{attempt:e,err:n}),await new Promise((r)=>setTimeout(r,Pf))}}console.error("[Sable] uiReady: exhausted retries — agent will not greet")}class vo{version=Yl;emitter=new Un;activeRoom=null;visionHandle=null;unmountDebugPanel=null;on(t,e){return this.emitter.on(t,e)}async start(t){if(this.activeRoom)throw Error("Sable already started; call stop() first");let e=t.publicKey??t.agentPublicId;if(!e)throw Error("Sable.start: `publicKey` is required");let l=t.apiUrl??ns;console.log("[Sable] fetching connection details",{apiUrl:l});let n=await rs({apiUrl:l,publicKey:e});console.log("[Sable] connection details received",{roomName:n.roomName,participantName:n.participantName});let r=await Promise.resolve().then(() => (kf(),Ff)),{Room:o,RoomEvent:s,LocalVideoTrack:c,Track:i}=r,h=new o,f={LocalVideoTrack:c,Track:i};if(h.registerRpcMethod("agentReady",async()=>{return console.log("[Sable] RPC agentReady received"),Ox(h),JSON.stringify({success:!0})}),as(h),is(h,t.runtime),this.wireRoomEvents(h,s),await h.connect(n.serverUrl,n.participantToken),await h.localParticipant.setMicrophoneEnabled(!0),this.activeRoom=h,t.vision?.enabled)try{if(this.visionHandle=await gs({room:h,lib:f,options:t.vision}),ms(t.debug))this.unmountDebugPanel=ys(this.visionHandle.canvas)}catch(u){console.warn("[Sable] failed to start vision",u)}console.log("[Sable] session live",{roomName:n.roomName,participantName:n.participantName}),this.emitter.emit("session:started",{roomName:n.roomName,participantName:n.participantName}),setTimeout(()=>{if(this.activeRoom!==h)return;let u=h,x=(u.remoteParticipants?Array.from(u.remoteParticipants.values()):[]).map((w)=>({identity:w.identity,tracks:w.trackPublications?Array.from(w.trackPublications.values()).map((p)=>({kind:p.kind,subscribed:p.isSubscribed})):[]}));if(!x.some((w)=>w.tracks.some((p)=>p.kind==="audio")))console.warn("[Sable] no remote audio track after 10s — agent worker probably failed to publish. Remote participants:",x)},1e4)}async stop(){let t=this.activeRoom;if(!t)return;if(this.activeRoom=null,this.unmountDebugPanel){try{this.unmountDebugPanel()}catch(e){console.warn("[Sable] debug panel unmount failed",e)}this.unmountDebugPanel=null}if(this.visionHandle){try{await this.visionHandle.stop()}catch(e){console.warn("[Sable] vision stop failed",e)}this.visionHandle=null}try{await t.localParticipant.setMicrophoneEnabled(!1)}catch(e){console.warn("[Sable] setMicrophoneEnabled(false) failed",e)}await t.disconnect(),console.log("[Sable] session ended"),this.emitter.emit("session:ended",{})}wireRoomEvents(t,e){t.on(e.ConnectionStateChanged,(l)=>{console.log("[Sable] ConnectionStateChanged",l)}),t.on(e.Disconnected,(l)=>{if(console.log("[Sable] Disconnected",l),this.activeRoom===t)this.stop().catch((n)=>console.warn("[Sable] stop on disconnect failed",n))}),t.on(e.ParticipantConnected,(l)=>{let n=l;console.log("[Sable] ParticipantConnected",{identity:n.identity,sid:n.sid})}),t.on(e.ParticipantDisconnected,(l)=>{console.warn("[Sable] ParticipantDisconnected",{identity:l.identity})}),t.on(e.TrackSubscribed,(l,n,r)=>{let o=l,s=r;if(console.log("[Sable] TrackSubscribed",{kind:o.kind,participant:s.identity}),o.kind==="audio"&&typeof o.attach==="function"){let c=o.attach();c.setAttribute("data-sable","1"),c.setAttribute("playsinline",""),c.autoplay=!0,document.body.appendChild(c),console.log("[Sable] attached remote audio element")}}),t.on(e.TrackUnsubscribed,(l)=>{let n=l;if(typeof n.detach==="function")for(let r of n.detach())r.remove()}),t.on(e.ActiveSpeakersChanged,(l)=>{let n=l??[],r=n.some((s)=>typeof s.identity==="string"&&s.identity.startsWith("agent")),o=n.some((s)=>typeof s.identity==="string"&&!s.identity.startsWith("agent"));this.emitter.emit("agent:speaking",r),this.emitter.emit("user:speaking",o)})}}var Zn=new vo;function Uf(){if(typeof window>"u")return;if(window.Sable)return;window.Sable=Zn,console.log("[Sable] SDK loaded",Zn.version)}Uf();var Yx=Zn;})();
|
|
@@ -23,7 +23,7 @@ import type { SableAPI, SableEventHandler, SableEvents, StartOptions } from "../
|
|
|
23
23
|
* state ownership explicit and the teardown path easier to reason about.
|
|
24
24
|
*/
|
|
25
25
|
export declare class Session implements SableAPI {
|
|
26
|
-
readonly version = "0.1.
|
|
26
|
+
readonly version = "0.1.1";
|
|
27
27
|
private readonly emitter;
|
|
28
28
|
private activeRoom;
|
|
29
29
|
private visionHandle;
|
package/dist/types/version.d.ts
CHANGED
package/package.json
CHANGED
package/src/index.test.ts
CHANGED
package/src/version.ts
CHANGED