1import{d as R,b as T,an as B,bA as Q,w,M as i,z as f,ax as U,v as F,o as y,c as b,i as c,a as I,e as h,j,aM as V,F as H,y as G,n as S,bB as K,D as O,O as $,T as J,al as W,Q as X,bC as Y,B as Z}from"./DwtnIozm.js";import{_ as ee}from"./CqXVUoH5.js";import{_ as ae}from"./BJXFI6vg.js";import"./Bfd5Thr0.js";import"./C_YC4gad.js";const oe={class:"relative z-10 flex h-full flex-col bg-[#469270] text-white"},se={class:"flex-shrink-0 border-b border-white/10 p-4"},te={class:"flex items-center gap-3"},ne={class:"flex flex-grow flex-col overflow-hidden p-4"},le={class:"chat-image"},re={class:"h-8 w-8 overflow-hidden rounded-full"},ie={key:0,class:"h-full w-full bg-recrear p-1"},ce={key:1,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",class:"h-full w-full text-gray-600"},ue={key:0,class:"chat chat-start"},ve={class:"relative z-[70] flex-shrink-0 border-t border-white/10 p-4"},de={class:"flex gap-2"},ge=["disabled"],k=`Este interprete digital representa a Para la Naturaleza, una organización sin fines de lucro en Puerto Rico dedicada a la conservación y protección de los ecosistemas y la biodiversidad de las islas. Su propósito es informar, educar y conectar a las personas con la naturaleza mediante experiencias significativas y recursos digitales. 2 3IMPORTANTE: Debes presentarte siempre como "interprete digital" y NUNCA como "asistente digital" o "asistente". Tu rol es interpretar y conectar a las personas con la naturaleza, no asistir en tareas generales. 4 5Funciones principales: 6 71. Eventos y actividades: Proveer información sobre tours, talleres, voluntariados y eventos especiales organizados por Para la Naturaleza. Puede buscar por tipo de evento, región o área natural, incluyendo lugares como: 8 9⢠Antiguo Acueducto del RÃo Piedras 10⢠Cabezas de San Juan 11⢠Casa Ramón Power y Giralt 12⢠Cañón San Cristóbal 13⢠Estación Palo Colorado 14⢠Hacienda Buena Vista 15⢠Hacienda La Esperanza 16⢠Medio Mundo y Daguao 17 182. Especies y biodiversidad: Brindar información sobre la flora y fauna de Puerto Rico, con énfasis en especies nativas, endémicas y en peligro de extinción. 19 203. Conservación y participación: Explicar cómo las personas pueden participar en iniciativas de conservación como voluntariado, ciencia ciudadana, donaciones de tierras o campañas de reforestación. 21 224. Conciencia ambiental: Promover la sostenibilidad y la meta institucional de proteger el 33% de los terrenos de Puerto Rico para 2033. 23 245. Recursos y orientación: Dirigir a los usuarios a recursos sobre veredas, centros de visitantes y proyectos como La Siembra 2024. 25 26Acciones principales: 27 28⢠Recrear â /acciones/recrear 29⢠Aprender â /acciones/aprender 30⢠Sembrar â /acciones/sembrar 31⢠Conservar â /acciones/conservar 32⢠Donar â /acciones/donar 33 34Estructura de URLs (mismo sitio; anteponer el origen público si el usuario necesita enlace absoluto): 35 36⢠Eventos: /eventos/ID-AQUI 37⢠Ãrboles: /reforestacion/arboles?arbol=SLUG-AQUI 38⢠Centros: /centros/SLUG-AQUI 39 40El interprete digital debe abrir todos los enlaces en una nueva pestaña. 41 42Al comenzar una conversación, el interprete digital debe explicar brevemente que puede ayudar a descubrir eventos, conocer especies de árboles y aprender cómo participar en la conservación de Puerto Rico.`,me=R({__name:"ChatPanel",props:{initialMessage:{},query:{}},setup(A){const{t:L}=T(),m=A,v=B(),e=Q("chatMessages",()=>[]),u=f(""),n=Q("chatConversationId",null),r=f(!1);w([n,e],([t,a])=>{console.log("[ChatPanel] localStorage values changed",{conversationId:t,messagesCount:a?.length||0,localStorageConversationId:localStorage.getItem("chatConversationId"),localStorageMessages:localStorage.getItem("chatMessages")?.substring(0,100)})},{deep:!0});const x=f(null),{startStream:q}=Y(),d=()=>{x.value&&x.value.scrollTo({top:x.value.scrollHeight,behavior:"smooth"})},p=async()=>{if(!u.value.trim()||r.value){console.log("[ChatPanel] sendMessage blocked",{hasMessage:!!u.value.trim(),isLoading:r.value});return}console.log("[ChatPanel] sendMessage",{message:u.value,messagesCount:e.value.length});const t={role:"user",content:u.value};e.value=[...e.value,t],r.value=!0,await i(()=>d()),u.value,u.value="";let a=null,o=!1;try{const l=e.value.map(s=>({role:s.role,content:s.content}));await q(l,{onDelta:s=>{o?a!==null&&(e.value[a].content+=s):(console.log("[ChatPanel] First delta received, creating assistant message"),o=!0,a=e.value.length,e.value.push({role:"assistant",content:s}),r.value=!1),i(()=>d())},onDone:s=>{console.log("[ChatPanel] onDone - user message response",{conversationId:s.conversation,messagesCount:e.value.length}),n.value=s.conversation,r.value=!1,i(()=>d())},onError:s=>{console.error("Error en stream:",s),o?a!==null&&(e.value[a].content="Lo siento, hubo un error al procesar tu mensaje."):e.value.push({role:"assistant",content:"Lo siento, hubo un error al procesar tu mensaje."}),r.value=!1,i(()=>d())}},n.value,k)}catch(l){console.error("Error al enviar el mensaje:",l),o||e.value.push({role:"assistant",content:"Lo siento, hubo un error al procesar tu mensaje."}),r.value=!1,await i(()=>d())}},N=t=>t==="user"?"chat-bubble-primary":"chat-bubble-secondary",P=async()=>
42{if(n.value&&e.value.length>0){console.log("[ChatPanel] Restoring conversation from localStorage",{conversationId:n.value,messagesCount:e.value.length}),await i(()=>d());return}if(n.value&&e.value.length===0&&(console.log("[ChatPanel] Found conversationId but no messages, clearing and creating new conversation"),n.value=null),!n.value){r.value=!0;const a=[{role:"user",content:m.initialMessage||"¡Hola!"}],o=0;e.value=[];try{await q(a,{onDelta:l=>{e.value.length===0?e.value.push({role:"assistant",content:l}):e.value[o].content+=l,i(()=>d())},onDone:async l=>{console.log("[ChatPanel] onDone - initial conversation",{conversationId:l.conversation,data:l,queryFromProp:m.query,queryFromTripleta:v.chatQuery.value,tripletaMode:v.mode.value}),n.value=l.conversation,r.value=!1,await i(()=>d());const s=m.query||v.chatQuery.value;s&&s.trim()&&!M.value&&s!==g.value&&(console.log("[ChatPanel] onDone - sending query automatically:",s),M.value=!0,g.value=s.trim(),await new Promise(_=>setTimeout(_,300)),u.value=s.trim(),await i(),await p())},onError:l=>{console.error("Error al iniciar conversación:",l),e.value=[{role:"assistant",content:"Lo siento, hubo un error al iniciar la conversación."}],r.value=!1,i(()=>d())}},null,k)}catch(l){console.error("Error al iniciar conversación:",l),e.value=[{role:"assistant",content:"Lo siento, hubo un error al iniciar la conversación."}],r.value=!1,await i(()=>d())}}},C=f(!1);w(()=>m.initialMessage,(t,a)=>{C.value&&t&&t!==a&&(n.value?(u.value=t,p()):(n.value=null,e.value=[],P()))},{immediate:!1});const g=f(null);w(()=>v.mode.value,async(t,a)=>{if(t==="chat"&&a!=="chat"&&C.value){await i(),await i();const o=m.query||v.chatQuery.value;if(console.log("[ChatPanel] Mode changed to chat",{query:o,lastSentQuery:g.value,conversationId:n.value,isLoading:r.value,propsQuery:m.query,tripletaQuery:v.chatQuery.value}),!(n.value&&e.value.length>0))if(o&&o.trim()){console.log("[ChatPanel] No conversation yet but has query from Explore with AI, initializing...",{conversationId:n.value,messagesCount:e.value.length,query:o}),M.value=!1,g.value=null,await P();return}else{console.log("[ChatPanel] No conversation and no query, keeping empty state");return}console.log("[ChatPanel] Conversation exists, keeping it",{conversationId:n.value,messagesCount:e.value.length}),o&&o.trim()&&o.trim()!==g.value?(console.log("[ChatPanel] New query detected from Explore with AI, sending:",o),g.value=o.trim(),u.value=o.trim(),await p()):o&&o.trim()&&o.trim()===g.value?console.log("[ChatPanel] Query is same as last sent, keeping existing conversation"):console.log("[ChatPanel] No new query, keeping existing conversation")}},{immediate:!1}),w([()=>m.query,()=>v.chatQuery.value],async([t,a],[o,l])=>{const s=t||a,_=o||l,z=!_&&s&&s.trim(),E=s&&s.trim()&&s!==_&&s.trim()!==g.value;C.value&&v.mode.value==="chat"&&(z||E)&&(n.value&&!r.value?(console.log("[ChatPanel] Sending query to existing conversation:",s,{isNewQueryFromMenu:z,isQueryChanged:E}),g.value=s.trim(),u.value=s.trim(),await p()):n.value||(console.log("[ChatPanel] Query received but no conversation yet, will send after initial stream"),g.value=null))},{immediate:!1});const M=f(!1);U(async()=>{const t=m.query||v.chatQuery.value,a=v.mode.value;C.value&&a==="chat"&&t&&t.trim()&&n.value&&!r.value&&t.trim()!==g.value&&(console.log("[ChatPanel] watchEffect detected new query available, sending automatically:",t),g.value=t.trim(),u.value=t.trim(),await i(),await p())}),F(()=>{console.log("ChatPanel mounted",{hasQuery:!!m.query,query:m.query,hasInitialMessage:!!m.initialMessage,queryFromTripleta:v.chatQuery.value,conversationId:n.value,messagesCount:e.value.length}),C.value=!0,!n.value&&e.value.length===0?(console.log("[ChatPanel] onMounted: No conversation found, initializing..."),P()):n.value&&e.value.length>0&&(console.log("[ChatPanel] onMounted: Conversation found, restoring from localStorage",{conversationId:n.value,messagesCount:e.value.length}),i(()=>d()))}),w(r,t=>{t&&i(()=>d())});const D=t=>t;return(t,a)=>(y(),b("div",oe,[c("div",se,[c("div",te,[I(ae,{"aria-label":h(L)("tripleta_chat_back_to_menu","Volver al menú"),onClick:a[0]||(a[0]=o=>h(v).setMode("menu"))},{default:j(()=>[I(V,{class:"size-full"})]),_:1},8,["aria-label"]),a[2]||(a[2]=c("h3",{class:"font-national2Condensed text-lg font-medium text-white"}," Chat con Para la Naturaleza ",-1))])]),c("div",ne,[c("div",{ref_key:"chatContainer",ref:x,class:"flex flex-grow flex-col space-y-4 overflow-y-auto"},[(y(!0),b(H,null,G(h(e),(o,l)=>(y(),b("div",{key:l,class:S(o.role==="user"?"chat chat-end":"chat chat-start")},[c("div",le,[c("div",re,[o.role==="assistant"?(y(),b("div",ie,[...a[3]||(a[3]=[c("img",{src:ee,alt:"PLN Logo",class:"h-full w-full object-cover"},null,-1)])])):(y(),b("svg",ce,[...a[4]||(a[4]=[c("path",{"fill-rule":"evenodd",d:"M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75
42a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z","clip-rule":"evenodd"},null,-1)])]))])]),c("div",{class:S(["chat-bubble",N(o.role),"prose max-w-none !text-base"])},[I(h(K),{source:D(o.content)},null,8,["source"])],2)],2))),128)),h(r)?(y(),b("div",ue,[...a[5]||(a[5]=[c("div",{class:"chat-bubble bg-gray-200"},[c("span",{class:"loading loading-dots loading-sm text-black"})],-1)])])):O("",!0)],512)]),c("div",ve,[c("div",de,[$(c("input",{"onUpdate:modelValue":a[1]||(a[1]=o=>X(u)?u.value=o:null),onKeyup:W(p,["enter"]),type:"text",placeholder:"Escribe tu mensaje aquÃ",class:"input pointer-events-auto relative z-[70] flex-grow border border-white/20 bg-white/10 text-white placeholder-white/60 focus:border-white/40"},null,544),[[J,h(u)]]),c("button",{onClick:p,disabled:!h(u).trim()||h(r),class:"btn btn-primary pointer-events-auto relative z-[70]"}," Enviar ",8,ge)])])]))}}),Ce=Z(me,[["__scopeId","data-v-77ce5034"]]);export{Ce as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.