openclaw-liveavatar 1.0.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.
- package/.next/BUILD_ID +1 -0
- package/.next/app-build-manifest.json +42 -0
- package/.next/app-path-routes-manifest.json +6 -0
- package/.next/build-manifest.json +33 -0
- package/.next/cache/.previewinfo +1 -0
- package/.next/cache/.rscinfo +1 -0
- package/.next/cache/.tsbuildinfo +1 -0
- package/.next/cache/chrome-devtools-workspace-uuid +1 -0
- package/.next/cache/next-devtools-config.json +1 -0
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/3.pack +0 -0
- package/.next/cache/webpack/client-production/4.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +58 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +61 -0
- package/.next/react-loadable-manifest.json +1 -0
- package/.next/required-server-files.json +320 -0
- package/.next/routes-manifest.json +53 -0
- package/.next/server/app/_not-found/page.js +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +4 -0
- package/.next/server/app/_not-found.meta +8 -0
- package/.next/server/app/_not-found.rsc +15 -0
- package/.next/server/app/api/get-avatars/route.js +1 -0
- package/.next/server/app/api/get-avatars/route.js.nft.json +1 -0
- package/.next/server/app/api/get-avatars/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/start-session/route.js +1 -0
- package/.next/server/app/api/start-session/route.js.nft.json +1 -0
- package/.next/server/app/api/start-session/route_client-reference-manifest.js +1 -0
- package/.next/server/app/index.html +4 -0
- package/.next/server/app/index.meta +7 -0
- package/.next/server/app/index.rsc +16 -0
- package/.next/server/app/page.js +9 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +6 -0
- package/.next/server/chunks/361.js +9 -0
- package/.next/server/chunks/611.js +6 -0
- package/.next/server/chunks/873.js +22 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +4 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages/_app.js +1 -0
- package/.next/server/pages/_app.js.nft.json +1 -0
- package/.next/server/pages/_document.js +1 -0
- package/.next/server/pages/_document.js.nft.json +1 -0
- package/.next/server/pages/_error.js +19 -0
- package/.next/server/pages/_error.js.nft.json +1 -0
- package/.next/server/pages-manifest.json +6 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/chunks/144d3bae-37bcc55d23f188ee.js +1 -0
- package/.next/static/chunks/255-35bf8c00c5dde345.js +1 -0
- package/.next/static/chunks/336-a66237a0a1db954a.js +1 -0
- package/.next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
- package/.next/static/chunks/app/_not-found/page-dfc6e5d8e6c6203c.js +1 -0
- package/.next/static/chunks/app/api/get-avatars/route-8017e1cff542d5d0.js +1 -0
- package/.next/static/chunks/app/api/start-session/route-8017e1cff542d5d0.js +1 -0
- package/.next/static/chunks/app/layout-ff675313cc8f8fcf.js +1 -0
- package/.next/static/chunks/app/page-9e4b703722bef650.js +1 -0
- package/.next/static/chunks/framework-de98b93a850cfc71.js +1 -0
- package/.next/static/chunks/main-1a0dcce460eb61ce.js +1 -0
- package/.next/static/chunks/main-app-e7f1007edc7ad7e1.js +1 -0
- package/.next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
- package/.next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-4a462cecab786e93.js +1 -0
- package/.next/static/css/bfd73afa11897439.css +3 -0
- package/.next/static/v_GdCj8lVweDVhmIhhEcM/_buildManifest.js +1 -0
- package/.next/static/v_GdCj8lVweDVhmIhhEcM/_ssgManifest.js +1 -0
- package/.next/trace +2 -0
- package/.next/types/app/api/get-avatars/route.ts +347 -0
- package/.next/types/app/api/start-session/route.ts +347 -0
- package/.next/types/app/layout.ts +84 -0
- package/.next/types/app/page.ts +84 -0
- package/.next/types/cache-life.d.ts +141 -0
- package/.next/types/package.json +1 -0
- package/.next/types/routes.d.ts +74 -0
- package/.next/types/validator.ts +88 -0
- package/README.md +241 -0
- package/app/api/config.ts +18 -0
- package/app/api/get-avatars/route.ts +117 -0
- package/app/api/start-session/route.ts +95 -0
- package/app/globals.css +3 -0
- package/app/layout.tsx +37 -0
- package/app/page.tsx +9 -0
- package/bin/cli.js +100 -0
- package/package.json +66 -0
- package/src/components/LiveAvatarSession.tsx +825 -0
- package/src/components/OpenClawDemo.tsx +399 -0
- package/src/gateway/client.ts +522 -0
- package/src/gateway/types.ts +83 -0
- package/src/liveavatar/context.tsx +750 -0
- package/src/liveavatar/index.ts +6 -0
- package/src/liveavatar/types.ts +10 -0
- package/src/liveavatar/useAvatarActions.ts +41 -0
- package/src/liveavatar/useChatHistory.ts +7 -0
- package/src/liveavatar/useSession.ts +37 -0
- package/src/liveavatar/useTextChat.ts +32 -0
- package/src/liveavatar/useVoiceChat.ts +70 -0
- package/tsconfig.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[974],{3858:(e,t,n)=>{"use strict";n.d(t,{OpenClawDemo:()=>S});var a=n(5155),s=n(2115),r=n(336),o=function(e){return e.USER="user",e.AVATAR="avatar",e}({}),i=n(5704);i.env.LIVEAVATAR_API_KEY,i.env.OPENCLAW_GATEWAY_URL,i.env.OPENCLAW_GATEWAY_TOKEN;class l{get state(){return this.connectionState}setConnectionState(e){this.connectionState=e,this.onConnectionStateHandlers.forEach(t=>t(e))}async connect(){return new Promise((e,t)=>{try{this.setConnectionState("connecting");let n=this.url;if(this.token){let e=n.includes("?")?"&":"?";n="".concat(n).concat(e,"token=").concat(encodeURIComponent(this.token))}this.ws=new WebSocket(n),this.ws.onopen=()=>{console.log("[Gateway] WebSocket connected"),this.reconnectAttempts=0,this.performHandshake().then(()=>{this.setConnectionState("connected"),e()}).catch(e=>{this.setConnectionState("error"),t(e)})},this.ws.onclose=e=>{console.log("[Gateway] WebSocket closed:",e.code,e.reason),this.setConnectionState("disconnected"),this.handleReconnect()},this.ws.onerror=e=>{console.error("[Gateway] WebSocket error:",e),this.setConnectionState("error"),t(Error("WebSocket connection failed"))},this.ws.onmessage=e=>{this.handleMessage(e.data)}}catch(e){this.setConnectionState("error"),t(e)}})}async performHandshake(){var e,t;let n={minProtocol:3,maxProtocol:3,client:{id:"webchat",version:"0.1.0",platform:"web",mode:"webchat",displayName:"OpenClaw LiveAvatar"}};this.token&&(n.auth={token:this.token});let a=await this.sendRequest("connect",n);(null==(t=a.snapshot)||null==(e=t.sessionDefaults)?void 0:e.mainSessionKey)&&(this.sessionKey=a.snapshot.sessionDefaults.mainSessionKey,console.log("[Gateway] Session key captured:",this.sessionKey)),console.log("[Gateway] Handshake complete:",a)}handleMessage(e){try{let n=JSON.parse(e);if(this.onMessageHandlers.forEach(e=>e(n)),"res"===n.type){let e=this.pendingRequests.get(n.id);if(e)if(this.pendingRequests.delete(n.id),n.ok)e.resolve(n.payload);else{var t;e.reject(Error((null==(t=n.error)?void 0:t.message)||"Request failed"))}}else"event"===n.type&&this.handleEvent(n)}catch(e){console.error("[Gateway] Failed to parse message:",e)}}handleEvent(e){if(console.log("[Gateway] Event:",e.event,JSON.stringify(e.payload)),"agent"===e.event){let t=e.payload;console.log("[Gateway] Agent event received:",t.runId,t.stream,t.data),this.onAgentEventHandlers.forEach(e=>e(t))}}onAgentEvent(e){this.onAgentEventHandlers.push(e)}offAgentEvent(e){let t=this.onAgentEventHandlers.indexOf(e);t>-1&&this.onAgentEventHandlers.splice(t,1)}handleReconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts)return void console.log("[Gateway] Max reconnect attempts reached");this.reconnectAttempts++;let e=this.reconnectDelay*Math.pow(2,this.reconnectAttempts-1);console.log("[Gateway] Reconnecting in ".concat(e,"ms (attempt ").concat(this.reconnectAttempts,")")),setTimeout(()=>{this.connect().catch(e=>{console.error("[Gateway] Reconnect failed:",e)})},e)}async sendRequest(e,t){return new Promise((n,a)=>{if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return void a(Error("WebSocket not connected"));let s="".concat(++this.messageId);this.pendingRequests.set(s,{resolve:n,reject:a}),setTimeout(()=>{this.pendingRequests.has(s)&&(this.pendingRequests.delete(s),a(Error("Request timeout")))},3e4),this.ws.send(JSON.stringify({type:"req",id:s,method:e,params:t}))})}async sendToAgent(e){let t,n,a="liveavatar-".concat(Date.now(),"-").concat(Math.random().toString(36).substring(2,9)),s={message:"".concat(e,"\n\n[RESPONSE FORMAT: Start with a 3-5 sentence spoken summary wrapped in [TTS]...[/TTS] tags that captures the key points of your response, then provide your full detailed response. The TTS summary should be informative and conversational, giving the user the gist while they read the full text. Example:\n[TTS]Here's what I found. The main issue is X, which can be solved by Y. I'd recommend starting with Z approach because it's the most straightforward.[/TTS]\nFull detailed response here with all the specifics...]"),idempotencyKey:a};this.sessionKey&&(s.sessionKey=this.sessionKey),this.conversationId&&(s.conversationId=this.conversationId);let r=null,o="",i=!1,l=[],c=new Promise((e,a)=>{t=e,n=a}),d=setTimeout(()=>{this.offAgentEvent(m),n(Error("Agent response timeout"))},6e4),u=new Set,h=e=>{var n,a,s,l,c,h;!i&&(void 0!==e.seq&&u.has(e.seq)||(void 0!==e.seq&&u.add(e.seq),console.log("[Gateway] Agent event:",e.stream,e.seq,null==(a=e.data)||null==(n=a.delta)?void 0:n.substring(0,20)),"assistant"===e.stream&&(null==(c=e.data)?void 0:c.delta)&&(o+=e.data.delta),"lifecycle"===e.stream&&(null==(s=e.data)?void 0:s.phase)==="end"&&(i=!0,clearTimeout(d),this.offAgentEvent(m),t({runId:r,status:"completed",text:o||void 0})),"lifecycle"===e.stream&&(null==(l=e.data)?void 0:l.phase)==="error"&&(i=!0,clearTimeout(d),this.offAgentEvent(m),t({runId:r,status:"failed",text:(null==(h=e.data)?void 0:h.error)||"Agent encountered an error"}))))},m=e=>{if(!r)return void l.push(e);e.runId===r&&h(e)};this.onAgentEvent(m);try{let e=await this.sendRequest("agent",s);for(let t of(console.log("[Gateway] Agent request accepted:",e),r=e.runId,e.conversationId&&(this.conversationId=e.conversationId),l))t.runId===r&&h(t)}catch(e){throw clearTimeout(d),this.offAgentEvent(m),e}return c}async getStatus(){return this.sendRequest("status")}parseResponse(e){let t=e.match(/\[TTS\]([\s\S]*?)\[\/TTS\]/i);if(t){let n=t[1].trim(),a=e.replace(/\[TTS\][\s\S]*?\[\/TTS\]\n?/i,"").trim();return console.log("[Gateway] Parsed TTS summary:",n.length,"chars"),{tts:n,full:a||e}}console.log("[Gateway] No [TTS] block found, extracting first sentences");let n=e.match(/[^.!?]+[.!?]+/g)||[],a="";for(let e=0;e<Math.min(5,n.length);e++){let t=n[e].trim();if(a.length+t.length>400&&a.length>0)break;a+=(a?" ":"")+t}return{tts:a||this.truncateToSentences(e,300),full:e}}truncateToSentences(e,t){if(e.length<=t)return e;let n=e.substring(0,t),a=Math.max(n.lastIndexOf(". "),n.lastIndexOf("! "),n.lastIndexOf("? "),n.lastIndexOf(".\n"),n.lastIndexOf("!\n"),n.lastIndexOf("?\n"));if(a>.5*t)return n.substring(0,a+1).trim();let s=n.lastIndexOf(" ");return s>.7*t?n.substring(0,s).trim()+"...":n.trim()+"..."}disconnect(){this.ws&&(this.ws.close(),this.ws=null),this.setConnectionState("disconnected")}onMessage(e){this.onMessageHandlers.push(e)}offMessage(e){let t=this.onMessageHandlers.indexOf(e);t>-1&&this.onMessageHandlers.splice(t,1)}onConnectionState(e){this.onConnectionStateHandlers.push(e)}offConnectionState(e){let t=this.onConnectionStateHandlers.indexOf(e);t>-1&&this.onConnectionStateHandlers.splice(t,1)}constructor(e,t){this.ws=null,this.reconnectAttempts=0,this.maxReconnectAttempts=5,this.reconnectDelay=1e3,this.messageId=0,this.pendingRequests=new Map,this.connectionState="disconnected",this.conversationId=null,this.sessionKey=null,this.onMessageHandlers=[],this.onConnectionStateHandlers=[],this.onAgentEventHandlers=[],this.url=e,this.token=t||""}}let c=null;function d(){return c||(c=new l(window.__OPENCLAW_GATEWAY_URL||"ws://127.0.0.1:18789",window.__OPENCLAW_GATEWAY_TOKEN||"")),c}let u=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:200;if(e.length<=t)return e;let n=e.substring(0,t),a=Math.max(n.lastIndexOf(". "),n.lastIndexOf("! "),n.lastIndexOf("? "),n.lastIndexOf(".\n"),n.lastIndexOf("!\n"),n.lastIndexOf("?\n"));if(a>.5*t)return n.substring(0,a+1).trim();let s=n.lastIndexOf(" ");return s>.7*t?n.substring(0,s).trim()+"...":n.trim()+"..."},h=["Let me think about that...","One moment please...","Let me check on that...","Give me a second...","Looking into that...","Hmm, let me see..."],m=()=>h[Math.floor(Math.random()*h.length)],g=["Hey there! I'm ready to help. What can I do for you today?","Hi! Good to see you. What would you like to work on?","Hello! I'm all set. What's on your mind?","Hey! Ready when you are. What can I help you with?","Hi there! Let's get started. What do you need?","Hello! I'm here to assist. What are you working on today?"],p=["Hi there! Welcome to the OpenClaw demo. Feel free to ask me anything, or say 'help' to learn more!","Hello! This is the OpenClaw LiveAvatar demo. Try asking me what I can do!","Hey! Welcome to the demo. I'm here to show you how this works. What would you like to know?"],x=(0,s.createContext)({sessionRef:{current:null},connectionQuality:r._N.UNKNOWN,isMuted:!0,voiceChatState:r.y4.INACTIVE,sessionState:r.Yj.DISCONNECTED,isStreamReady:!1,isUserTalking:!1,isAvatarTalking:!1,messages:[],addMessage:()=>{},addTypedMessage:()=>{},gatewayState:"disconnected",isProcessingAgent:!1,isDemoMode:!0}),f=e=>{let t=e.toLowerCase().trim();return t.match(/^(hi|hello|hey|greetings|good morning|good afternoon|good evening)\.?$/)?"Hello! Welcome to the OpenClaw LiveAvatar integration demo. I'm here to show you how this works. Try asking me 'what is this?' or 'how does it work?' to learn more!":t.includes("what is this")||t.includes("what are you")||t.includes("who are you")?"I'm a LiveAvatar - a real-time AI video avatar that serves as your voice and video interface to OpenClaw agents. Think of me as a friendly face for your AI assistant. When connected to OpenClaw, I'll speak your agent's responses and listen to your voice commands!":t.includes("how does it work")||t.includes("how do you work")||t.includes("explain")?"Here's how it works: You speak to me or type a message. Your input goes to your OpenClaw agent, which processes it and generates a response. Then I speak that response back to you with natural lip-sync and expressions. It's like having a video call with your AI agent!":t.includes("openclaw")&&(t.includes("what")||t.includes("tell me about"))?"OpenClaw is an AI agent platform that lets you build and deploy intelligent assistants. These agents can handle tasks, answer questions, and integrate with your tools. This LiveAvatar integration adds a human-like video interface to make interactions more engaging and natural.":t.includes("liveavatar")&&(t.includes("what")||t.includes("tell me about"))?"LiveAvatar is powered by HeyGen's streaming avatar technology. It creates real-time, photorealistic AI avatars that can speak any text with natural expressions and lip-sync. Combined with OpenClaw, it transforms text-based AI interactions into face-to-face conversations.":"help"===t||t.includes("what can i ask")||t.includes("what can you do")||t.includes("commands")?"In demo mode, you can ask me about: 'What is this?', 'How does it work?', 'What is OpenClaw?', 'What is LiveAvatar?', 'How do I connect?', 'Features', 'Requirements', 'Pricing', or 'Get started'. Once connected to OpenClaw, I'll respond with your actual agent's intelligence!":t.includes("connect")||t.includes("setup")||t.includes("get started")||t.includes("install")?"To connect to your OpenClaw agent: First, make sure OpenClaw is running on your computer with the Gateway enabled on port 18789. Then refresh this page - I'll automatically detect the connection and switch from demo mode to live mode. You'll see the status change from 'Demo Mode' to 'OpenClaw Connected'.":t.includes("feature")?"Key features include: Voice-to-voice conversations with your AI agent, real-time video avatar with natural expressions, text chat as an alternative to voice, multiple avatar options to choose from, and seamless integration with your OpenClaw workflows. It's like giving your AI a face!":t.includes("requirement")||t.includes("need")||t.includes("prerequisite")?"To use this integration you'll need: An OpenClaw account with an active agent, the OpenClaw Gateway running locally, a LiveAvatar API key from HeyGen, a modern browser with microphone access, and a stable internet connection for the video stream.":t.includes("price")||t.includes("cost")||t.includes("free")||t.includes("pricing")?"LiveAvatar sessions consume HeyGen credits based on session duration. OpenClaw has its own pricing for agent usage. Check openclaw.ai and heygen.com for current pricing. This demo mode is free to try and shows you exactly how the integration works!":t.includes("demo mode")||t.includes("demo")?"You're currently in demo mode because no OpenClaw Gateway connection was detected. In this mode, I respond with pre-set information about the integration. Once you connect to OpenClaw, I'll relay your messages to your actual AI agent and speak its responses!":t.includes("voice")||t.includes("microphone")||t.includes("speak")||t.includes("talk")?"You can talk to me using your microphone! Click the green microphone button to unmute, then just speak naturally. I'll transcribe what you say, process it, and respond verbally. You can also type in the chat box if you prefer text input.":t.includes("avatar")||t.includes("change")||t.includes("appearance")?"You can change my appearance by clicking the person icon in the bottom right of the video. This opens the avatar selector where you can choose from different available avatars. Each avatar has its own look and voice!":t.includes("bye")||t.includes("goodbye")||t.includes("see you")||t.includes("thanks")?"Thank you for trying the OpenClaw LiveAvatar demo! When you're ready to use it with your actual OpenClaw agent, just start the Gateway and refresh this page. Have a great day!":'I heard: "'.concat(e,"\". I'm currently in demo mode, showing you how this integration works. Try asking me about 'what is this?', 'how does it work?', or type 'help' for more options. Once connected to OpenClaw, your agent will provide intelligent responses to any question!")},v=e=>{let{children:t,sessionAccessToken:n}=e,i=(0,s.useRef)(new r.i5(n,{voiceChat:{defaultMuted:!1},apiUrl:"https://api.liveavatar.com"})),[l,c]=(0,s.useState)([]),h=(0,s.useRef)(new Set),v=(0,s.useRef)(new Set),w=(0,s.useCallback)(e=>{c(t=>[...t,e])},[]),{sessionState:y,isStreamReady:b,connectionQuality:k}=(e=>{var t,n;let[a,o]=(0,s.useState)((null==(t=e.current)?void 0:t.state)||r.Yj.INACTIVE),[i,l]=(0,s.useState)((null==(n=e.current)?void 0:n.connectionQuality)||r._N.UNKNOWN),[c,d]=(0,s.useState)(!1);return(0,s.useEffect)(()=>{e.current&&(e.current.on(r.b9.SESSION_STATE_CHANGED,t=>{o(t),t===r.Yj.DISCONNECTED&&(e.current.removeAllListeners(),e.current.voiceChat.removeAllListeners(),d(!1))}),e.current.on(r.b9.SESSION_STREAM_READY,()=>{d(!0)}),e.current.on(r.b9.SESSION_CONNECTION_QUALITY_CHANGED,l))},[e]),{sessionState:a,isStreamReady:c,connectionQuality:i}})(i),{isMuted:j,voiceChatState:N}=(e=>{var t;let[n,a]=(0,s.useState)(!0),[o,i]=(0,s.useState)((null==(t=e.current)?void 0:t.voiceChat.state)||r.y4.INACTIVE);return(0,s.useEffect)(()=>{e.current&&(e.current.voiceChat.on(r.hm.MUTED,()=>{a(!0)}),e.current.voiceChat.on(r.hm.UNMUTED,()=>{a(!1)}),e.current.voiceChat.on(r.hm.STATE_CHANGED,i))},[e]),{isMuted:n,voiceChatState:o}})(i),{isUserTalking:C,isAvatarTalking:A}=(e=>{let[t,n]=(0,s.useState)(!1),[a,o]=(0,s.useState)(!1);return(0,s.useEffect)(()=>{e.current&&(e.current.on(r.Oz.USER_SPEAK_STARTED,()=>{n(!0)}),e.current.on(r.Oz.USER_SPEAK_ENDED,()=>{n(!1)}),e.current.on(r.Oz.AVATAR_SPEAK_STARTED,()=>{o(!0)}),e.current.on(r.Oz.AVATAR_SPEAK_ENDED,()=>{o(!1)}))},[e]),{isUserTalking:t,isAvatarTalking:a}})(i),S=(0,s.useRef)(!1);(0,s.useEffect)(()=>{S.current=A},[A]);let{gatewayState:E,isProcessingAgent:T,isDemoMode:I}=((e,t,n,a,i)=>{let[l,c]=(0,s.useState)("disconnected"),[h,g]=(0,s.useState)(!1),[p,x]=(0,s.useState)(!0),v=(0,s.useRef)(null);return(0,s.useEffect)(()=>{let e=d();return v.current=e,e.onConnectionState(e=>{c(e),"connected"===e&&(console.log("[OpenClaw] Gateway connected - switching to live mode"),x(!1)),("disconnected"===e||"error"===e)&&(console.log("[OpenClaw] Gateway disconnected - falling back to demo mode"),x(!0))}),e.connect().catch(e=>{console.log("[OpenClaw] Gateway not available, staying in demo mode:",e.message),x(!0)}),()=>{e.disconnect()}},[]),(0,s.useEffect)(()=>{let s=e.current;if(!s)return;let l=async e=>{var l,c,d;let h=e.text||e.transcript||"";if(!h.trim())return;if(i.current)return void console.log("[Voice] Ignoring transcription while avatar is speaking:",h.substring(0,30));if(null==(l=n.current)?void 0:l.has(h.trim()))return void n.current.delete(h.trim());let x="user:".concat(h.trim());if(null==(c=a.current)||!c.has(x)){null==(d=a.current)||d.add(x),setTimeout(()=>{var e;return null==(e=a.current)?void 0:e.delete(x)},3e3),t({sender:o.USER,message:h,timestamp:Date.now()});try{let e;g(!0);let n=!1;if(p)console.log("[Demo] Processing voice message locally:",h),e=f(h);else{let t=v.current;if(t&&"connected"===t.state){console.log("[OpenClaw] Sending to agent:",h);let a=null;s&&s.state===r.Yj.CONNECTED&&(a=setTimeout(async()=>{let e=m();console.log("[Avatar] Speaking placeholder (slow response):",e),n=!0;try{await s.repeat(e)}catch(e){console.error("[Avatar] Failed to speak placeholder:",e)}},2e3));let o=await t.sendToAgent(h);a&&clearTimeout(a),console.log("[OpenClaw] Agent response:",o),e="completed"===o.status&&o.text?o.text:"Sorry, I didn't get a response from the agent."}else console.warn("[OpenClaw] Gateway not connected, cannot send message"),e="I'm not connected to the agent. Please check the Gateway connection."}let a=v.current,i=e,l=e;if(!p&&a){let t=a.parseResponse(e);i=t.tts,l=t.full}else i=u(e);if(t({sender:o.AVATAR,message:l,timestamp:Date.now()}),s&&s.state===r.Yj.CONNECTED)try{n&&await new Promise(e=>setTimeout(e,500)),console.log("[Avatar] Speaking TTS summary:",i),await s.repeat(i)}catch(e){console.error("[Avatar] Failed to make avatar speak:",e)}}catch(e){console.error("[Chat] Failed to process voice message:",e),t({sender:o.AVATAR,message:"Sorry, I couldn't process that. Please try again.",timestamp:Date.now()})}finally{g(!1)}}};return s.on(r.Oz.USER_TRANSCRIPTION,l),()=>{s.off(r.Oz.USER_TRANSCRIPTION,l)}},[e,t,n,a,p]),{gatewayState:l,isProcessingAgent:h,isDemoMode:p}})(i,w,h,v,S),[O,R]=(0,s.useState)(!1),L=(0,s.useRef)(null),D=(0,s.useRef)(!1);(0,s.useEffect)(()=>{L.current=d()},[]),(0,s.useEffect)(()=>{if(console.log("[Intro] Effect triggered - isStreamReady:",b,"hasPlayed:",D.current),!b||D.current)return;let e=i.current;if(!e)return void console.log("[Intro] No session ref");console.log("[Intro] Session state:",e.state),D.current=!0,setTimeout(async()=>{let t=(e=>{let t=e?p:g;return t[Math.floor(Math.random()*t.length)]})(I);w({sender:o.AVATAR,message:t,timestamp:Date.now()});try{console.log("[Intro] Playing intro:",t),await e.repeat(t),console.log("[Intro] Intro played successfully")}catch(e){console.error("[Intro] Failed to play intro:",e)}},1e3)},[b,I,w,i]);let M=(0,s.useCallback)(async e=>{h.current.add(e),setTimeout(()=>{h.current.delete(e)},2e3),w({sender:o.USER,message:e,timestamp:Date.now()});try{let t;R(!0);let n=!1,a=i.current;if(I)console.log("[Demo] Processing typed message locally:",e),t=f(e);else{let s=L.current;if(s&&"connected"===s.state){console.log("[OpenClaw] Sending typed message to agent:",e);let o=null;a&&a.state===r.Yj.CONNECTED&&(o=setTimeout(async()=>{let e=m();console.log("[Avatar] Speaking placeholder (slow response):",e),n=!0;try{await a.repeat(e)}catch(e){console.error("[Avatar] Failed to speak placeholder:",e)}},2e3));let i=await s.sendToAgent(e);o&&clearTimeout(o),console.log("[OpenClaw] Agent response:",i),t="completed"===i.status&&i.text?i.text:"Sorry, I didn't get a response from the agent."}else console.warn("[OpenClaw] Gateway not connected, cannot send typed message"),t="I'm not connected to the OpenClaw agent yet. Please make sure the Gateway is running."}let s=L.current,l=t,c=t;if(!I&&s){let e=s.parseResponse(t);l=e.tts,c=e.full}else l=u(t);if(w({sender:o.AVATAR,message:c,timestamp:Date.now()}),a&&a.state===r.Yj.CONNECTED)try{n&&await new Promise(e=>setTimeout(e,500)),console.log("[Avatar] Speaking TTS summary:",l),await a.repeat(l)}catch(e){console.error("[Avatar] Failed to make avatar speak:",e)}}catch(e){console.error("[Chat] Failed to process message:",e),w({sender:o.AVATAR,message:"Sorry, I couldn't process that. Please try again.",timestamp:Date.now()})}finally{R(!1)}},[w,i,I]);return(0,a.jsx)(x.Provider,{value:{sessionRef:i,sessionState:y,isStreamReady:b,connectionQuality:k,isMuted:j,voiceChatState:N,isUserTalking:C,isAvatarTalking:A,messages:l,addMessage:w,addTypedMessage:M,gatewayState:E,isProcessingAgent:T||O,isDemoMode:I},children:t})},w=()=>(0,s.useContext)(x),y=e=>{let{deviceId:t,isActive:n}=e,[r,o]=(0,s.useState)(0),i=(0,s.useRef)(null),l=(0,s.useRef)(null),c=(0,s.useRef)(null),d=(0,s.useRef)(!0);(0,s.useEffect)(()=>(d.current=!0,n&&t&&"default"!==t)?((async()=>{if(await new Promise(e=>setTimeout(e,500)),d.current)try{let e=await navigator.mediaDevices.getUserMedia({audio:{deviceId:{ideal:t}}});if(!d.current)return void e.getTracks().forEach(e=>e.stop());l.current=e;let n=new AudioContext;i.current=n;let a=n.createMediaStreamSource(e),s=n.createAnalyser();s.fftSize=256,s.smoothingTimeConstant=.3,a.connect(s);let r=new Uint8Array(s.frequencyBinCount),u=()=>{if(!d.current)return;s.getByteFrequencyData(r);let e=0;for(let t=0;t<r.length;t++)e+=r[t];let t=e/r.length,n=Math.min(100,t/128*100);o(n),c.current=requestAnimationFrame(u)};u()}catch(e){console.error("Failed to start audio analyser:",e),o(0)}})(),()=>{d.current=!1,c.current&&(cancelAnimationFrame(c.current),c.current=null),l.current&&(l.current.getTracks().forEach(e=>e.stop()),l.current=null),i.current&&(i.current.close().catch(()=>{}),i.current=null)}):void o(0),[t,n]);let u=Array.from({length:5},(e,t)=>{let n=20*(t+1);return r>=n?100:r/n*100});return(0,a.jsx)("div",{className:"flex items-end gap-0.5 h-6",children:u.map((e,t)=>(0,a.jsx)("div",{className:"w-1 bg-green-500 rounded-full transition-all duration-75",style:{height:"".concat(Math.max(4,.24*e),"px"),opacity:r>5?1:.3}},t))})},b=e=>{let{selectedDeviceId:t,onDeviceChange:n,disabled:r,showAudioLevel:o}=e,[i,l]=(0,s.useState)([]),[c,d]=(0,s.useState)(!1);(0,s.useEffect)(()=>{let e=async()=>{try{await navigator.mediaDevices.getUserMedia({audio:!0});let e=(await navigator.mediaDevices.enumerateDevices()).filter(e=>"audioinput"===e.kind);l(e),e.length>0&&"default"===t&&n(e[0].deviceId)}catch(e){console.error("Failed to get audio devices:",e)}};return e(),navigator.mediaDevices.addEventListener("devicechange",e),()=>{navigator.mediaDevices.removeEventListener("devicechange",e)}},[t,n]);let u=i.find(e=>e.deviceId===t),h=(null==u?void 0:u.label)||"Select microphone";return(0,a.jsxs)("div",{className:"relative",children:[(0,a.jsxs)("button",{onClick:()=>!r&&d(!c),disabled:r,className:"flex items-center gap-2 bg-white/10 hover:bg-white/20 text-white px-3 py-2 rounded-lg text-sm transition-colors ".concat(r?"opacity-50 cursor-not-allowed":""),children:[(0,a.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"})}),(0,a.jsx)("span",{className:"max-w-[180px] truncate",children:h}),o&&"default"!==t&&(0,a.jsx)(y,{deviceId:t,isActive:!0},t),(0,a.jsx)("svg",{className:"w-4 h-4 transition-transform ".concat(c?"rotate-180":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),c&&(0,a.jsxs)("div",{className:"absolute bottom-full left-0 mb-2 w-80 bg-white rounded-lg shadow-xl overflow-hidden z-50",children:[(0,a.jsx)("div",{className:"px-4 py-2 bg-gray-100 text-gray-600 text-sm font-medium border-b",children:"Select microphone"}),(0,a.jsx)("div",{className:"max-h-64 overflow-y-auto",children:i.map(e=>(0,a.jsx)("button",{onClick:()=>{n(e.deviceId),d(!1)},className:"w-full px-4 py-3 text-left text-sm hover:bg-gray-50 transition-colors ".concat(e.deviceId===t?"bg-blue-50 text-blue-700":"text-gray-800"),children:e.label||"Microphone ".concat(e.deviceId.slice(0,8))},e.deviceId))})]})]})},k=e=>{let{state:t,isProcessing:n,isDemoMode:s}=e;return(0,a.jsxs)("div",{className:"flex items-center gap-2 px-3 py-1.5 bg-black/30 rounded-full",children:[(0,a.jsx)("span",{className:"w-2 h-2 rounded-full ".concat((()=>{if(n)return"bg-yellow-500";if(s)return"bg-blue-500";switch(t){case"connected":return"bg-green-500";case"connecting":return"bg-yellow-500";case"error":return"bg-red-500";default:return"bg-gray-500"}})()," ").concat(n?"animate-pulse":"")}),(0,a.jsx)("span",{className:"text-xs text-white/80",children:(()=>{if(n)return"Processing...";if(s)return"Demo Mode";switch(t){case"connected":return"OpenClaw Connected";case"connecting":return"Connecting...";case"error":return"Connection Error";default:return"Disconnected"}})()})]})},j=()=>{let{messages:e,gatewayState:t,isProcessingAgent:n,addTypedMessage:r,isDemoMode:i}=w(),l=(0,s.useRef)(null),[c,d]=(0,s.useState)(""),u=i||"connected"===t;(0,s.useEffect)(()=>{var e;null==(e=l.current)||e.scrollIntoView({behavior:"smooth"})},[e]);let h=()=>{let e=c.trim();e&&(r(e),d(""))};return(0,a.jsxs)("div",{className:"flex flex-col h-full overflow-hidden bg-gray-900/50 rounded-2xl border border-white/10",children:[(0,a.jsxs)("div",{className:"flex-shrink-0 px-4 py-3 border-b border-white/10 flex items-center justify-between",children:[(0,a.jsx)("h3",{className:"text-white font-medium",children:"Conversation"}),(0,a.jsx)(k,{state:t,isProcessing:n,isDemoMode:i})]}),(0,a.jsxs)("div",{className:"flex-1 min-h-0 overflow-y-auto p-4 space-y-3",children:[0===e.length?(0,a.jsx)("div",{className:"text-gray-500 text-sm text-center py-8",children:i?(0,a.jsx)(a.Fragment,{children:'Demo mode active. Type "help" to learn about this integration!'}):"connected"===t?(0,a.jsx)(a.Fragment,{children:"Start speaking or type below to chat with your OpenClaw agent"}):(0,a.jsx)(a.Fragment,{children:"Connecting to OpenClaw Gateway..."})}):e.map((e,t)=>(0,a.jsx)("div",{className:"flex ".concat(e.sender===o.USER?"justify-end":"justify-start"),children:(0,a.jsxs)("div",{className:"max-w-[90%] px-4 py-3 rounded-xl text-sm leading-relaxed ".concat(e.sender===o.USER?"bg-blue-600 text-white":"bg-gray-700 text-gray-100"),children:[(0,a.jsx)("div",{className:"text-xs opacity-70 mb-1.5 font-medium",children:e.sender===o.USER?"You":"OpenClaw Agent"}),(0,a.jsx)("div",{className:"whitespace-pre-wrap",children:e.message})]})},t)),n&&(0,a.jsx)("div",{className:"flex justify-start",children:(0,a.jsx)("div",{className:"bg-gray-700 text-gray-100 px-3 py-2 rounded-lg text-sm",children:(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)("div",{className:"w-2 h-2 bg-blue-400 rounded-full animate-bounce"}),(0,a.jsx)("div",{className:"w-2 h-2 bg-blue-400 rounded-full animate-bounce",style:{animationDelay:"0.1s"}}),(0,a.jsx)("div",{className:"w-2 h-2 bg-blue-400 rounded-full animate-bounce",style:{animationDelay:"0.2s"}})]})})}),(0,a.jsx)("div",{ref:l})]}),(0,a.jsx)("div",{className:"flex-shrink-0 p-3 border-t border-white/10",children:(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)("input",{type:"text",value:c,onChange:e=>d(e.target.value),onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),h())},placeholder:u?"Type a message...":"Waiting for connection...",disabled:!u||n,className:"flex-1 bg-gray-800 text-white text-sm px-3 py-2 rounded-lg border border-white/10 focus:border-orange-500/50 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed placeholder-gray-500"}),(0,a.jsx)("button",{onClick:h,disabled:!c.trim()||!u||n,className:"bg-orange-500 hover:bg-orange-600 disabled:bg-gray-600 disabled:cursor-not-allowed text-white px-4 py-2 rounded-lg transition-colors",children:(0,a.jsx)("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 19l9 2-9-18-9 18 9-2zm0 0v-8"})})})]})})]})},N=e=>{let{onSessionStopped:t}=e,[n,o]=(0,s.useState)("default"),{sessionState:i,isStreamReady:l,startSession:c,stopSession:d,connectionQuality:u,attachElement:h,sessionRef:m}=(()=>{let{sessionRef:e,sessionState:t,isStreamReady:n,connectionQuality:a}=w(),r=(0,s.useCallback)(async()=>await e.current.start(),[e]),o=(0,s.useCallback)(async()=>await e.current.stop(),[e]);return{sessionState:t,isStreamReady:n,connectionQuality:a,startSession:r,stopSession:o,keepAlive:(0,s.useCallback)(async()=>await e.current.keepAlive(),[e]),attachElement:(0,s.useCallback)(t=>e.current.attach(t),[e]),sessionRef:e}})(),{isAvatarTalking:g,isUserTalking:p,isMuted:x,isActive:f,mute:v,unmute:y,restartWithDevice:k}=(()=>{let{sessionRef:e,isMuted:t,voiceChatState:n,isUserTalking:a,isAvatarTalking:o}=w(),i=(0,s.useCallback)(async()=>await e.current.voiceChat.mute(),[e]),l=(0,s.useCallback)(async()=>await e.current.voiceChat.unmute(),[e]),c=(0,s.useCallback)(async t=>await e.current.voiceChat.start(t?{deviceId:t,defaultMuted:!1}:{defaultMuted:!1}),[e]),d=(0,s.useCallback)(()=>e.current.voiceChat.stop(),[e]),u=(0,s.useCallback)(async t=>{console.log("Restarting voice chat with device:",t);try{return e.current.voiceChat.stop(),await new Promise(e=>setTimeout(e,100)),await e.current.voiceChat.start({deviceId:t,defaultMuted:!1}),console.log("Voice chat restarted successfully"),!0}catch(e){return console.error("Failed to restart voice chat:",e),!1}},[e]);return{mute:i,unmute:l,start:c,stop:d,restartWithDevice:u,isLoading:(0,s.useMemo)(()=>n===r.y4.STARTING,[n]),isActive:(0,s.useMemo)(()=>n===r.y4.ACTIVE,[n]),isMuted:t,isUserTalking:a,isAvatarTalking:o}})(),{interrupt:N}=(e=>{let{sessionRef:t}=w(),n=(0,s.useCallback)(()=>t.current.interrupt(),[t]),a=(0,s.useCallback)(async n=>{if("FULL"===e)return t.current.repeat(n);if("CUSTOM"===e){let e=await fetch("/api/elevenlabs-text-to-speech",{method:"POST",body:JSON.stringify({text:n})}),{audio:a}=await e.json();return t.current.repeatAudio(a)}},[t,e]);return{interrupt:n,repeat:a,startListening:(0,s.useCallback)(()=>t.current.startListening(),[t]),stopListening:(0,s.useCallback)(()=>t.current.stopListening(),[t])}})("FULL"),{gatewayState:C,isProcessingAgent:A}=w(),S=(0,s.useRef)(null);(0,s.useEffect)(()=>{i===r.Yj.DISCONNECTED&&t()},[i,t]),(0,s.useEffect)(()=>{l&&S.current&&h(S.current)},[h,l]),(0,s.useEffect)(()=>{i===r.Yj.INACTIVE&&c()},[c,i]);let E=(0,s.useCallback)(async e=>{console.log("Changing microphone to:",e),o(e);try{var t;let n=null==(t=m.current)?void 0:t.voiceChat;n&&!await n.setDevice(e)&&f&&await k(e)}catch(t){console.error("Failed to set microphone device:",t),f&&await k(e)}},[m,f,k]),T=(0,s.useCallback)(async()=>{x?await y():await v()},[x,v,y]),I=(0,s.useRef)(null),[O,R]=(0,s.useState)(0);return(0,s.useEffect)(()=>{let e=()=>{if(I.current){let e=I.current.parentElement;e&&R(e.offsetHeight)}};return e(),window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[l]),(0,a.jsxs)("div",{className:"w-full max-w-6xl flex gap-4 py-4 px-4",children:[(0,a.jsxs)("div",{className:"flex-1 flex flex-col gap-4",children:[(0,a.jsxs)("div",{ref:I,className:"relative w-full aspect-video overflow-hidden rounded-2xl bg-gray-800 flex flex-col items-center justify-center",children:[(0,a.jsx)("video",{ref:S,autoPlay:!0,playsInline:!0,className:"w-full h-full object-contain"}),i!==r.Yj.CONNECTED&&(0,a.jsx)("div",{className:"absolute inset-0 flex items-center justify-center bg-black/50",children:(0,a.jsxs)("div",{className:"text-white text-lg",children:[i===r.Yj.CONNECTING&&"Connecting...",i===r.Yj.INACTIVE&&"Starting...",i===r.Yj.DISCONNECTING&&"Disconnecting..."]})}),(0,a.jsx)("div",{className:"absolute bottom-4 right-4 flex items-center gap-2",children:(0,a.jsx)("button",{className:"bg-red-500 hover:bg-red-600 text-white p-3 rounded-full transition-colors",onClick:()=>d(),title:"End conversation",children:(0,a.jsx)("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})}),(0,a.jsxs)("div",{className:"absolute top-4 left-4 flex flex-col gap-2",children:[p&&(0,a.jsxs)("div",{className:"bg-green-500/80 text-white text-xs px-2 py-1 rounded-full flex items-center gap-1",children:[(0,a.jsx)("span",{className:"w-2 h-2 bg-white rounded-full animate-pulse"}),"You're speaking"]}),g&&(0,a.jsxs)("div",{className:"bg-blue-500/80 text-white text-xs px-2 py-1 rounded-full flex items-center gap-1",children:[(0,a.jsx)("span",{className:"w-2 h-2 bg-white rounded-full animate-pulse"}),"Agent speaking"]}),A&&(0,a.jsxs)("div",{className:"bg-yellow-500/80 text-white text-xs px-2 py-1 rounded-full flex items-center gap-1",children:[(0,a.jsx)("span",{className:"w-2 h-2 bg-white rounded-full animate-pulse"}),"Thinking..."]})]}),(0,a.jsx)("div",{className:"absolute top-4 right-4 px-3 py-1.5 rounded-full text-xs bg-black/50 text-white",children:u})]}),(0,a.jsxs)("div",{className:"w-full flex items-center justify-center gap-3",children:[(0,a.jsx)(b,{selectedDeviceId:n,onDeviceChange:E,showAudioLevel:!x}),(0,a.jsx)("button",{onClick:T,className:"p-4 rounded-full transition-colors ".concat(x?"bg-red-500 hover:bg-red-600":"bg-green-500 hover:bg-green-600"),title:x?"Click to unmute":"Click to mute",children:x?(0,a.jsxs)("svg",{className:"w-6 h-6 text-white",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:[(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"}),(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 3l18 18"})]}):(0,a.jsx)("svg",{className:"w-6 h-6 text-white",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"})})}),(0,a.jsx)("button",{onClick:()=>N(),className:"bg-orange-500 hover:bg-orange-600 text-white p-3 rounded-full transition-colors",title:"Interrupt avatar",children:(0,a.jsxs)("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:[(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M21 12a9 9 0 11-18 0 9 9 0 0118 0z"}),(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 10a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z"})]})})]}),(0,a.jsx)("div",{className:"text-sm text-gray-400 text-center",children:"connected"!==C?(0,a.jsx)("span",{className:"text-yellow-400",children:"Waiting for OpenClaw Gateway connection..."}):x?"Microphone is muted - click to speak":"Speak to chat with your OpenClaw agent"})]}),(0,a.jsx)("div",{className:"w-[420px] flex flex-col overflow-hidden",style:{height:O>0?"".concat(O,"px"):"500px"},children:(0,a.jsx)(j,{})})]})},C=e=>{let{sessionAccessToken:t,onSessionStopped:n,onAvatarChange:s}=e;return(0,a.jsx)(v,{sessionAccessToken:t,children:(0,a.jsx)(N,{onSessionStopped:n,onAvatarChange:s})})},A=e=>{let{title:t,avatars:n,isExpanded:s,onToggle:r,onSelectAvatar:o,badge:i,showExpiredBadge:l=!0}=e,c=n.filter(e=>!0===e.is_expired).length,d=n.length-c;return(0,a.jsxs)("div",{className:"w-full",children:[(0,a.jsxs)("button",{onClick:r,className:"w-full flex items-center justify-between px-3 py-2 bg-gray-800/50 hover:bg-gray-800/70 rounded-lg transition-colors",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)("svg",{className:"w-4 h-4 text-gray-400 transition-transform ".concat(s?"rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,a.jsx)("span",{className:"text-sm font-medium text-white",children:t}),i&&(0,a.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded ".concat(i.color),children:i.text})]}),(0,a.jsx)("span",{className:"text-xs text-gray-500",children:c>0?"".concat(d," active / ").concat(n.length," total"):"".concat(n.length," available")})]}),s&&n.length>0&&(0,a.jsx)("div",{className:"grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-3 mt-3 px-1",children:n.map(e=>{let t=!0===e.is_expired;return(0,a.jsxs)("button",{onClick:()=>o(e.id),disabled:t,className:"relative aspect-square rounded-lg overflow-hidden border-2 transition-all group ".concat(t?"border-red-500/30 opacity-50 cursor-not-allowed":"border-white/10 hover:border-orange-500/50 hover:scale-105"),children:[e.preview_url?(0,a.jsx)("img",{src:e.preview_url,alt:e.name,className:"w-full h-full object-cover"}):(0,a.jsx)("div",{className:"w-full h-full bg-gray-700 flex items-center justify-center",children:(0,a.jsx)("span",{className:"text-gray-400 text-xs text-center px-1",children:e.name.slice(0,10)})}),(0,a.jsx)("div",{className:"absolute inset-0 bg-black/0 group-hover:bg-black/40 transition-colors flex items-end",children:(0,a.jsx)("div",{className:"w-full p-2 bg-gradient-to-t from-black/80 to-transparent opacity-0 group-hover:opacity-100 transition-opacity",children:(0,a.jsx)("span",{className:"text-white text-xs truncate block",children:e.name})})}),l&&t&&(0,a.jsx)("div",{className:"absolute top-1 left-1 bg-red-500 text-white text-[10px] px-1.5 py-0.5 rounded",children:"Expired"})]},e.id)})}),s&&0===n.length&&(0,a.jsxs)("div",{className:"text-center py-6 text-gray-500 text-sm",children:["No ",t.toLowerCase()," available"]})]})},S=()=>{let[e,t]=(0,s.useState)(""),[n,r]=(0,s.useState)(null),[o,i]=(0,s.useState)("connecting"),[l,c]=(0,s.useState)([]),[u,h]=(0,s.useState)([]),[m,g]=(0,s.useState)(!0),[p,x]=(0,s.useState)("disconnected"),[f,v]=(0,s.useState)(!1),[w,y]=(0,s.useState)(!0),b=(0,s.useRef)(!1),k=(0,s.useCallback)(async e=>{r(null),i("connecting");try{let n=await fetch("/api/start-session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e?{avatarId:e}:{})});if(!n.ok){let e=await n.json();throw Error(e.error||"Failed to start session")}let{session_token:a}=await n.json();t(a),i("session")}catch(e){r(e.message),i("error")}},[]);(0,s.useEffect)(()=>{(async()=>{g(!0);try{let e=await fetch("/api/get-avatars");if(e.ok){let t=await e.json(),n=t.customAvatars||[],a=t.publicAvatars||[];if(c(n),h(a),!b.current){b.current=!0;let e=n.find(e=>!e.is_expired),t=a[0],s=e||t;s?(console.log("[AutoStart] Starting session with avatar:",s.name),k(s.id)):i("ended")}}else i("error"),r("Failed to fetch avatars")}catch(e){console.error("Failed to fetch avatars:",e),i("error"),r("Failed to connect to avatar service")}finally{g(!1)}})();let e=d();return e.onConnectionState(x),e.connect().catch(e=>{console.log("[OpenClaw] Gateway not available:",e.message)}),()=>{e.offConnectionState(x)}},[k]);let j=(0,s.useCallback)(()=>{t(""),i("ended")},[]);return"connecting"===o?(0,a.jsx)("div",{className:"w-full h-full flex flex-col items-center justify-center gap-6 p-4",children:(0,a.jsxs)("div",{className:"flex flex-col items-center gap-4",children:[(0,a.jsxs)("div",{className:"relative",children:[(0,a.jsx)("div",{className:"w-16 h-16 border-4 border-orange-500/30 rounded-full"}),(0,a.jsx)("div",{className:"absolute top-0 left-0 w-16 h-16 border-4 border-orange-500 rounded-full border-t-transparent animate-spin"})]}),(0,a.jsxs)("div",{className:"text-center",children:[(0,a.jsxs)("div",{className:"flex items-center justify-center gap-3 mb-4",children:[(0,a.jsx)("div",{className:"w-10 h-10 bg-gradient-to-br from-orange-500 to-red-600 rounded-xl flex items-center justify-center",children:(0,a.jsx)("span",{className:"text-xl",children:"\uD83E\uDD9E"})}),(0,a.jsx)("h1",{className:"text-2xl font-bold text-white",children:"OpenClaw LiveAvatar"})]}),(0,a.jsx)("p",{className:"text-gray-400 text-sm",children:"Connecting to your AI avatar..."})]})]})}):"error"===o?(0,a.jsx)("div",{className:"w-full h-full flex flex-col items-center justify-center gap-6 p-4",children:(0,a.jsxs)("div",{className:"w-full max-w-md flex flex-col items-center gap-6",children:[(0,a.jsxs)("div",{className:"text-center",children:[(0,a.jsx)("div",{className:"w-16 h-16 bg-red-500/20 rounded-full flex items-center justify-center mx-auto mb-4",children:(0,a.jsx)("svg",{className:"w-8 h-8 text-red-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,a.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})}),(0,a.jsx)("h1",{className:"text-2xl font-bold text-white mb-2",children:"Connection Failed"}),(0,a.jsx)("p",{className:"text-gray-400 mb-4",children:"Could not connect to the LiveAvatar service."}),n&&(0,a.jsx)("div",{className:"text-red-400 bg-red-900/30 px-4 py-3 rounded-lg text-sm mb-4",children:n})]}),(0,a.jsx)("button",{onClick:()=>i("idle"),className:"px-6 py-2 bg-gradient-to-r from-orange-500 to-red-600 hover:from-orange-600 hover:to-red-700 text-white rounded-lg transition-all",children:"Back to Avatar Selection"}),(0,a.jsx)("p",{className:"text-xs text-gray-500 text-center",children:"Make sure your LIVEAVATAR_API_KEY is configured in .env.local"})]})}):"ended"===o?(0,a.jsx)("div",{className:"w-full h-full flex flex-col items-center justify-center gap-6 p-4",children:(0,a.jsxs)("div",{className:"w-full max-w-2xl flex flex-col items-center gap-6",children:[(0,a.jsxs)("div",{className:"text-center",children:[(0,a.jsxs)("div",{className:"flex items-center justify-center gap-3 mb-4",children:[(0,a.jsx)("div",{className:"w-10 h-10 bg-gradient-to-br from-orange-500 to-red-600 rounded-xl flex items-center justify-center",children:(0,a.jsx)("span",{className:"text-xl",children:"\uD83E\uDD9E"})}),(0,a.jsx)("h1",{className:"text-2xl font-bold text-white",children:"OpenClaw LiveAvatar"})]}),(0,a.jsx)("p",{className:"text-gray-400 mb-2",children:"Session ended. Select an avatar to start a new conversation."})]}),(0,a.jsxs)("div",{className:"flex items-center gap-2 px-4 py-2 bg-gray-800/50 rounded-lg",children:[(0,a.jsx)("div",{className:"w-2 h-2 rounded-full ".concat("connected"===p?"bg-green-500":"connecting"===p?"bg-yellow-500 animate-pulse":"bg-gray-500")}),(0,a.jsx)("span",{className:"text-sm text-gray-300",children:"connected"===p?"OpenClaw Connected":"connecting"===p?"Connecting to OpenClaw...":"OpenClaw Disconnected"})]}),(0,a.jsxs)("div",{className:"w-full space-y-4",children:[(0,a.jsx)("h2",{className:"text-lg font-medium text-white",children:"Select an Avatar"}),m?(0,a.jsx)("div",{className:"flex items-center justify-center py-12",children:(0,a.jsx)("div",{className:"w-8 h-8 border-2 border-orange-500/30 border-t-orange-500 rounded-full animate-spin"})}):0===l.length&&0===u.length?(0,a.jsx)("div",{className:"text-center py-12 text-gray-400",children:"No avatars available. Check your LiveAvatar API key."}):(0,a.jsxs)("div",{className:"space-y-4",children:[l.length>0&&(0,a.jsx)(A,{title:"Custom Avatars",avatars:l,isExpanded:f,onToggle:()=>v(!f),onSelectAvatar:k}),u.length>0&&(0,a.jsx)(A,{title:"Public Avatars",avatars:u,isExpanded:w,onToggle:()=>y(!w),onSelectAvatar:k,showExpiredBadge:!1})]})]}),(0,a.jsxs)("p",{className:"text-xs text-gray-500 text-center",children:["Powered by"," ",(0,a.jsx)("a",{href:"https://liveavatar.com",target:"_blank",rel:"noopener noreferrer",className:"text-blue-400 hover:underline",children:"LiveAvatar"})," ","+"," ",(0,a.jsx)("a",{href:"https://openclaw.ai",target:"_blank",rel:"noopener noreferrer",className:"text-orange-400 hover:underline",children:"OpenClaw"})]})]})}):(0,a.jsx)(C,{sessionAccessToken:e,onSessionStopped:j})}},7718:(e,t,n)=>{Promise.resolve().then(n.bind(n,3858))}},e=>{e.O(0,[501,336,441,255,358],()=>e(e.s=7718)),_N_E=e.O()}]);
|