From 470dc3ab9ea03c405f2d2a97ecfdaf7bac82e264 Mon Sep 17 00:00:00 2001 From: xjs Date: Fri, 25 Apr 2025 14:38:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AF=B9=E8=AF=9D=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{App-D4RUlINY.js => App-Bxrx0fG0.js} | 4 +- build/assets/index-CQS1KRBf.js | 1 + build/assets/index-DCCuNddn.js | 1 - .../{index-CN-hwWKH.js => index-mKhgCiGE.js} | 4 +- build/index.html | 2 +- .../Provider/RealtimeClientProvider.tsx | 127 +++++++++--------- 6 files changed, 72 insertions(+), 67 deletions(-) rename build/assets/{App-D4RUlINY.js => App-Bxrx0fG0.js} (59%) create mode 100644 build/assets/index-CQS1KRBf.js delete mode 100644 build/assets/index-DCCuNddn.js rename build/assets/{index-CN-hwWKH.js => index-mKhgCiGE.js} (95%) diff --git a/build/assets/App-D4RUlINY.js b/build/assets/App-Bxrx0fG0.js similarity index 59% rename from build/assets/App-D4RUlINY.js rename to build/assets/App-Bxrx0fG0.js index b202e76..39bdd12 100644 --- a/build/assets/App-D4RUlINY.js +++ b/build/assets/App-Bxrx0fG0.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DCCuNddn.js","assets/.pnpm-CAIuqsZ0.js","assets/use-toast-DO4tfD4I.js","assets/index-PFueeGmc.css"])))=>i.map(i=>d[i]); -import{_ as t}from"./index-CN-hwWKH.js";import{j as r,r as a}from"./.pnpm-CAIuqsZ0.js";const o=a.lazy(()=>t(()=>import("./index-DCCuNddn.js"),__vite__mapDeps([0,1,2,3])));function i(){return r.jsx("div",{className:"h-full bg-[#F4F6FA]",children:r.jsx(o,{})})}export{i as default}; +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-CQS1KRBf.js","assets/.pnpm-CAIuqsZ0.js","assets/use-toast-DO4tfD4I.js","assets/index-PFueeGmc.css"])))=>i.map(i=>d[i]); +import{_ as t}from"./index-mKhgCiGE.js";import{j as r,r as a}from"./.pnpm-CAIuqsZ0.js";const o=a.lazy(()=>t(()=>import("./index-CQS1KRBf.js"),__vite__mapDeps([0,1,2,3])));function i(){return r.jsx("div",{className:"h-full bg-[#F4F6FA]",children:r.jsx(o,{})})}export{i as default}; diff --git a/build/assets/index-CQS1KRBf.js b/build/assets/index-CQS1KRBf.js new file mode 100644 index 0000000..bc00e1f --- /dev/null +++ b/build/assets/index-CQS1KRBf.js @@ -0,0 +1 @@ +import{r,g as I,j as e,h as Y,i as O,u as M,k as X,l as A,m as S,M as ee,n as te,H as se,L as ne,o as P}from"./.pnpm-CAIuqsZ0.js";import{u as W}from"./use-toast-DO4tfD4I.js";const R=r.createContext({client:null,isConnecting:!1,isConnected:!1,audioEnabled:!0,isSupportVideo:!1,messageList:[],isAiTalking:!1,roomInfo:null,initClient:()=>{},handleConnect:()=>Promise.resolve(),handleInterrupt:()=>{},handleDisconnect:()=>{},toggleMicrophone:()=>{}}),re=()=>{const t=r.useContext(R);if(t===void 0)throw new Error("useRealtimeClient必须在RealtimeClientProvider内部使用");return{...t}},oe=({children:t})=>{const s="pat_NhhZGW7sxkuyP4mJrPrVyZx20b3m6lymg0y2Ln9EyM0CV9q2f9t3rlGbtzppLQua",o="7456409430717480998",c="7426720361733144585",a="1024",n=r.useRef(null),[d,m]=r.useState([]),[x,k]=r.useState(!1),[w,N]=r.useState(!1),[g,h]=r.useState(!0),[f]=r.useState(!1),[j,y]=r.useState(!1),[Q,q]=r.useState(null),{toast:L}=W(),G=async i=>{const l=await M.checkDevicePermission(!1),u=await M.getAudioDevices();if(!l.audio)throw L({title:"连接错误",description:"需要麦克风访问权限"}),new Error("需要麦克风访问权限");if(u.audioInputs.length===0)throw L({title:"连接错误",description:"没有麦克风设备"}),new Error("没有麦克风设备");const v=new X({accessToken:s,botId:o,voiceId:c,connectorId:a,allowPersonalAccessTokenInBrowser:!0,debug:!1});n.current=v,K(v),Z(v,i??""),J(v,i)},U=async i=>{var l;try{n.current||await G(i),await((l=n.current)==null?void 0:l.connect()),await H()}catch(u){if(console.error(u),u instanceof Y)switch(u.code){case O.CREATE_ROOM_ERROR:console.error(`创建房间失败: ${u.message}`);break;case O.CONNECTION_ERROR:console.error(`加入房间失败: ${u.message}`);break;case O.DEVICE_ACCESS_ERROR:console.error(`获取设备失败: ${u.message}`);break;default:console.error(`连接错误: ${u.message}`)}else console.error("连接错误:"+u)}},z=()=>{var i;try{(i=n.current)==null||i.interrupt()}catch(l){console.error("打断失败:"+l)}},F=async()=>{var i,l,u;try{y(!1),m([]),await((i=n.current)==null?void 0:i.setAudioEnable(!1)),h(!1),(l=n.current)==null||l.disconnect(),(u=n.current)==null||u.clearEventHandlers(),n.current=null,N(!1)}catch(v){console.error("断开失败:"+v)}},H=async()=>{var i;try{await((i=n.current)==null?void 0:i.setAudioEnable(!g)),h(!g)}catch(l){console.error("切换麦克风状态失败:"+l)}},J=r.useCallback((i,l)=>{i.on(I.ALL_SERVER,async(u,v)=>{var p;u==="server.session.created"&&await i.sendMessage({id:"",event_type:"session.update",data:{chat_config:{allow_voice_interrupt:!1}}}),u==="server.bot.join"&&l&&await((p=n.current)==null?void 0:p.sendMessage({id:"",event_type:"conversation.message.create",data:{role:"user",content_type:"text",content:l}}))})},[n.current]),Z=(i,l)=>{let u;i.on(I.ALL,(v,p)=>{if(p.event_type!==A.CONVERSATION_MESSAGE_DELTA&&p.event_type!==A.CONVERSATION_MESSAGE_COMPLETED&&p.event_type!=="conversation.created")return;const T=p.data.content;m(C=>(u==null?void 0:u.event_type)===A.CONVERSATION_MESSAGE_DELTA&&p.data.type==="answer"?[...C.slice(0,-1),{content:C[C.length-1].content+T,role:C[C.length-1].role}]:T!==""&&p.event_type===A.CONVERSATION_MESSAGE_DELTA||p.event_type===A.CONVERSATION_MESSAGE_COMPLETED&&(p.data.type==="answer"||p.data.type==="question")&&p.data.role!==S.Assistant?[...C,{content:T,role:p.data.role}]:l===""&&p.event_type==="conversation.created"?[...C,{content:p.data.prologue,role:S.Assistant}]:C),(p.data.type==="answer"||p.data.type==="question")&&(u=p)})},K=r.useCallback(i=>{i.on(I.AUDIO_AGENT_SPEECH_STARTED,async()=>{var l;y(!0),await((l=n.current)==null?void 0:l.setAudioEnable(!1)),h(!1)}),i.on(I.AUDIO_AGENT_SPEECH_STOPPED,async()=>{var l;y(!1),await((l=n.current)==null?void 0:l.setAudioEnable(!0)),h(!0)}),i.on(I.CONNECTING,()=>{k(!0),N(!1)}),i.on(I.CONNECTED,(l,u)=>{q(u),k(!1),N(!0)})},[n.current]);return e.jsx(R.Provider,{value:{client:n.current,isConnecting:x,isConnected:w,audioEnabled:g,isSupportVideo:f,messageList:d,isAiTalking:j,roomInfo:Q,initClient:G,handleConnect:U,handleInterrupt:z,handleDisconnect:F,toggleMicrophone:H},children:t})};function ce(){const{messageList:t}=r.useContext(R),s=r.useRef(null),o=()=>{var c;(c=s.current)==null||c.scrollIntoView({behavior:"smooth"})};return r.useEffect(()=>{o()},[t]),e.jsxs("div",{className:"flex-1 flex flex-col overflow-y-auto",children:[e.jsx("div",{className:"w-full min-h-[120px] h-[120px]",children:e.jsxs("div",{className:"relative h-full",children:[e.jsx("img",{src:"/icons/hello.gif",alt:"",className:"absolute top-0 h-[97px] left-[50%] translate-x-[-50%]"}),e.jsx("img",{src:"/icons/conversation-bg.png",alt:"background",className:"w-[222px] h-[49px] absolute bottom-0 left-[50%] translate-x-[-50%]"}),e.jsx("div",{className:"text-black text-[14px] absolute bottom-[22px] left-[50%] translate-x-[-50%] z-[10]",children:"Hey,我是您的六纬AI填报师"})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[t.map((c,a)=>e.jsx("div",{className:`flex ${c.role===S.Assistant?"justify-start":"justify-end"}`,children:e.jsx("div",{className:`max-w-3/4 p-3 rounded-lg ${c.role===S.Assistant?"bg-white text-black rounded-tl-none":"bg-blue-500 text-white rounded-tr-none"}`,children:e.jsx(ee,{remarkPlugins:[te],children:c.content})})},a)),e.jsx("div",{ref:s})]})]})}const ae="_talkWrapper_5jmgu_23",ie="_listenerDot_5jmgu_53",le="_isTalking_5jmgu_93",ue="_microphoneWrapper_5jmgu_157",b={talkWrapper:ae,listenerDot:ie,isTalking:le,microphoneWrapper:ue},de="/icons/lockmicrophone.png",pe="/icons/microphone.png",ge="/icons/handoff.png",he=t=>{const s=r.useRef(null),{handleDisconnect:o}=re(),{toast:c}=W(),a=r.useRef(null);return r.useEffect(()=>{if(!t.access_token||!t.roomId)return;const n=new se().withServerTimeout(3e4).withAutomaticReconnect().withUrl(`https://api.v3.ycymedu.com/hubs/weminpro?access_token=${t.access_token}&roomId=${t.roomId}`).configureLogging(ne.Information).build();return s.current=n,n.on("ForceOffline",function(d){c({variant:"destructive",title:"下线提醒",description:d}),o()}),n.on("SendWarn",function(d){console.warn(`下线提醒:${d}"`),c({variant:"destructive",title:"下线提醒",description:d})}),n.start().then(()=>{console.log("SignalR连接已建立"),a.current=setInterval(()=>{n.invoke("Ping")},5e3)}).catch(d=>{console.error("SignalR连接失败:",d)}),()=>{s.current&&s.current.stop().then(()=>{clearInterval(a.current),console.log("SignalR连接已关闭")}).catch(d=>{console.error("关闭SignalR连接失败:",d)})}},[t.access_token,t.roomId]),s.current};function me({className:t,...s}){const{handleDisconnect:o,toggleMicrophone:c,audioEnabled:a,isAiTalking:n,handleInterrupt:d,roomInfo:m}=r.useContext(R),[x]=P();return he({access_token:x.get("token")||"",roomId:(m==null?void 0:m.roomId)||""}),e.jsxs("div",{className:"flex items-center justify-center bg-white pb-[20px] pt-[10px] gap-[10px]",...s,children:[e.jsxs("div",{className:`${b.microphoneWrapper}`,onClick:o,children:[e.jsx("img",{src:ge,alt:"handoff"}),e.jsx("div",{children:"挂断"})]}),e.jsxs("div",{className:`${b.microphoneWrapper}`,onClick:c,children:[e.jsx("img",{src:a?pe:de,alt:"lock"}),e.jsx("div",{children:a?"关麦":"开麦"})]}),e.jsxs("div",{className:`${b.talkWrapper}`,onClick:d,children:[e.jsxs("div",{className:`${n?b.isTalking:""} ${b.listenerDot}`,children:[e.jsx("span",{style:{"--d":"2"}}),e.jsx("span",{style:{"--d":"1"}}),e.jsx("span",{style:{"--d":"0"}}),e.jsx("span",{style:{"--d":"1"}}),e.jsx("span",{style:{"--d":"2"}})]}),e.jsx("div",{children:n?"点击打断":"正在听"})]})]})}function fe(){return e.jsxs("div",{className:"flex flex-col max-h-full h-full",children:[e.jsx(ce,{}),e.jsx(me,{})]})}const xe="/icons/hello.gif",_e="/icons/whatsThing.png",je="/icons/circle.png",ye="/icons/right.png",Ee="_headerWrapper_lrk2k_1",ke="_wrapper_lrk2k_15",ve="_img_lrk2k_37",Ce="_text_lrk2k_81",Ne="_main_lrk2k_101",Re="_thing_lrk2k_135",we="_circle_lrk2k_153",Ie="_rightIcon_lrk2k_179",Ae="_change_lrk2k_189",be="_tip_lrk2k_197",Se="_rotating_lrk2k_223",_={headerWrapper:Ee,wrapper:ke,img:ve,text:Ce,"main-wrapper":"_main-wrapper_lrk2k_101",main:Ne,thing:Re,circle:we,rightIcon:Ie,change:Ae,tip:be,rotating:Se},Te=t=>async(s,o,c={})=>{const a={method:t,...c};if(t!=="GET"&&o)a.body=JSON.stringify(o);else if(t==="GET"&&o){const m=[];for(const[x,k]of Object.entries(o))m.push(`${x}=${k}`);s+=`?${m.join("&")}`}const n=await fetch(`${s}`,a),d=await n.json();return n.ok?d:{error:d.message||"Request failed",code:n.status}},D=Te("GET"),Oe=async({options:t})=>{const s=await D("https://api.v3.ycymedu.com/api/zhiYuan/aigcquestionswords?",{},t);return s.code===200?{result:s.result}:{result:[],message:s.message}};function B(){const t=r.useRef(null),s=()=>(t.current||(t.current=new AbortController),t.current.signal),o=()=>{t.current&&(t.current.abort(),t.current=null)},c=()=>(o(),t.current=new AbortController,t.current.signal);return r.useEffect(()=>()=>{o()},[]),{getSignal:s,abortAll:o,recreate:c}}function $e({toRoom:t}){const[s,o]=r.useState(!1),[c,a]=r.useState([]),[n,d]=r.useState([]),{getSignal:m}=B(),x=()=>{const g=Array.from(n),h=[],f=Math.min(4,g.length);for(let j=0;j{const{result:g,message:h}=await Oe({options:{signal:m()}});h?console.log(h):d(g)};r.useEffect(()=>{a(x())},[n]),r.useEffect(()=>{k()},[]);const w=()=>{o(!0),a(x()),setTimeout(()=>{o(!1)},1e3)},N=async g=>{t(g)};return e.jsxs("div",{className:_.headerWrapper,children:[e.jsxs("div",{className:_.wrapper,children:[e.jsx("img",{className:_.img,src:xe,alt:"hello"}),e.jsx("div",{className:_.text,children:"Hey,我是您的六纬AI小助手"})]}),e.jsxs("div",{className:_["main-wrapper"],children:[e.jsxs("div",{className:_.main,onClick:w,children:[e.jsx("img",{className:_.thing,src:_e,alt:"whatsThing"}),e.jsxs("div",{className:_.circle,children:[e.jsx("img",{src:je,className:s?_.rotating:"",alt:"circle"}),e.jsx("div",{className:_.change,children:"换一批"})]})]}),c.map((g,h)=>e.jsxs("div",{className:_.tip,onClick:()=>N(g),children:[e.jsx("div",{children:g}),e.jsx("img",{src:ye,alt:"right-icon",className:_.rightIcon})]},h))]})]})}const Me="_wrapper_e1j90_1",Pe="_text_e1j90_75",We="_call_e1j90_87",$={wrapper:Me,text:Pe,call:We},De="/icons/call.png";function Le(t){const{disable:s,loading:o,className:c,...a}=t,{isConnecting:n}=r.useContext(R);return e.jsxs("div",{className:`${$.wrapper} ${c}`,...a,children:[e.jsx("img",{className:$.call,src:De,alt:"call"}),e.jsx("div",{className:$.text,children:s?"暂不可用":n?"连接中":"发起通话"})]})}const Ge="/icons/myInput.png",He="/icons/rightBlue.png",Be="_scoreWrapper_1g8jt_1",Ve="_innerWrapper_1g8jt_13",Qe="_detail_1g8jt_37",qe="_right_1g8jt_53",Ue="_imgIcon_1g8jt_65",ze="_rightBlue_1g8jt_75",E={scoreWrapper:Be,innerWrapper:Ve,detail:Qe,right:qe,imgIcon:Ue,rightBlue:ze};function Fe({toRoom:t}){const[s]=P(),o=s.get("provinceName")||"山东省",c=s.get("subjectGroup")||"物/化/史",a=s.get("expectedScore")||500,n=async()=>{t(`我的高考地点在${o},我选择的科目是${c},我的高考分数为${a}分。我适合哪些学校和专业`)};return e.jsx("div",{className:E.scoreWrapper,children:e.jsxs("div",{className:E.innerWrapper,children:[e.jsxs("div",{className:E.left,children:[e.jsx("img",{src:Ge,className:E.imgIcon,alt:"input-ico"}),e.jsxs("div",{className:E.detail,children:[e.jsx("div",{className:E.city,children:o}),e.jsx("div",{className:E.subject,children:c.split(",").join("/")}),e.jsxs("div",{className:E.score,children:[a,"分"]})]})]}),e.jsxs("div",{className:E.right,onClick:n,children:[e.jsx("span",{children:"智能分析"}),e.jsx("img",{src:He,alt:"right",className:E.rightBlue})]})]})})}const Je=async({options:t})=>{const s=await D("https://api.v3.ycymedu.com/api/sysOnlineUser/hasitexpired",{},t);return s.code===200?{result:s.result}:{result:[],message:s.message}},Ze=async({params:t,options:s})=>{const o=await D("https://api.v3.ycymedu.com/api/busScale/GetBusAIReportKeyWord",t,s);return o.code===200?{result:o.result}:{result:[],message:o.message}},V=r.createContext({hasHandledReport:!1,setHasHandledReport:()=>{}}),Ke=({children:t})=>{const[s,o]=r.useState(!1);return e.jsx(V.Provider,{value:{hasHandledReport:s,setHasHandledReport:o},children:t})};function Ye(){const{handleConnect:t}=r.useContext(R),{setHasHandledReport:s,hasHandledReport:o}=r.useContext(V),[c]=P(),[a,n]=r.useState(!0),d=c.get("token")||"",m=c.get("reportId")||"",x=c.get("reportType")||"",{toast:k}=W(),{getSignal:w}=B(),N=async()=>{try{const{result:f,message:j}=await Je({options:{signal:w(),headers:{Authorization:`Bearer ${d}`}}});if(j)console.log(j);else{const y=f;n(!y.isExpired),!y.isExpired&&y.msg&&k({title:y.msg,description:"请重新登录"})}}catch(f){f.name!=="AbortError"&&console.error("获取用户令牌失败:",f)}},g=async()=>{try{const{result:f,message:j}=await Ze({params:{Type:x,Id:m},options:{signal:w(),headers:{Authorization:`Bearer ${d}`}}});j?console.log(j):(t(f),s(!0))}catch(f){f.name!=="AbortError"&&console.error("获取报告失败:",f)}};r.useEffect(()=>{N()},[d]),r.useEffect(()=>{m&&x&&!o&&g()},[m,x,o]);const h=f=>{a||t(f)};return e.jsxs("div",{className:"flex flex-col items-center h-full",children:[e.jsx($e,{toRoom:h}),e.jsx(Fe,{toRoom:h}),e.jsx(Le,{disable:a,onClick:()=>h()})]})}function Xe(){const{isConnected:t}=r.useContext(R),s=async()=>{await M.checkDevicePermission(!1)};return r.useEffect(()=>{s()},[]),e.jsx(Ke,{children:t?e.jsx(fe,{}):e.jsx(Ye,{})})}function st(){return e.jsx(oe,{children:e.jsx(Xe,{})})}export{st as default}; diff --git a/build/assets/index-DCCuNddn.js b/build/assets/index-DCCuNddn.js deleted file mode 100644 index f6bb6c4..0000000 --- a/build/assets/index-DCCuNddn.js +++ /dev/null @@ -1 +0,0 @@ -import{r,g as I,j as e,h as Y,i as O,u as M,k as X,l as A,m as S,M as ee,n as te,H as se,L as ne,o as P}from"./.pnpm-CAIuqsZ0.js";import{u as W}from"./use-toast-DO4tfD4I.js";const R=r.createContext({client:null,isConnecting:!1,isConnected:!1,audioEnabled:!0,isSupportVideo:!1,messageList:[],isAiTalking:!1,roomInfo:null,initClient:()=>{},handleConnect:()=>Promise.resolve(),handleInterrupt:()=>{},handleDisconnect:()=>{},toggleMicrophone:()=>{}}),re=()=>{const t=r.useContext(R);if(t===void 0)throw new Error("useRealtimeClient必须在RealtimeClientProvider内部使用");return{...t}},oe=({children:t})=>{const s="pat_NhhZGW7sxkuyP4mJrPrVyZx20b3m6lymg0y2Ln9EyM0CV9q2f9t3rlGbtzppLQua",o="7456409430717480998",c="7426720361733144585",a="1024",n=r.useRef(null),[d,m]=r.useState([]),[x,k]=r.useState(!1),[w,N]=r.useState(!1),[g,h]=r.useState(!0),[f]=r.useState(!1),[j,y]=r.useState(!1),[Q,q]=r.useState(null),{toast:L}=W(),G=async i=>{const l=await M.checkDevicePermission(!1),u=await M.getAudioDevices();if(!l.audio)throw L({title:"连接错误",description:"需要麦克风访问权限"}),new Error("需要麦克风访问权限");if(u.audioInputs.length===0)throw L({title:"连接错误",description:"没有麦克风设备"}),new Error("没有麦克风设备");const v=new X({accessToken:s,botId:o,voiceId:c,connectorId:a,allowPersonalAccessTokenInBrowser:!0,debug:!0});n.current=v,K(v),Z(v,i??""),J(v,i)},U=async i=>{var l;try{n.current||await G(i),await((l=n.current)==null?void 0:l.connect()),await H()}catch(u){if(console.error(u),u instanceof Y)switch(u.code){case O.CREATE_ROOM_ERROR:console.error(`创建房间失败: ${u.message}`);break;case O.CONNECTION_ERROR:console.error(`加入房间失败: ${u.message}`);break;case O.DEVICE_ACCESS_ERROR:console.error(`获取设备失败: ${u.message}`);break;default:console.error(`连接错误: ${u.message}`)}else console.error("连接错误:"+u)}},z=()=>{var i;try{(i=n.current)==null||i.interrupt()}catch(l){console.error("打断失败:"+l)}},F=async()=>{var i,l,u;try{y(!1),m([]),await((i=n.current)==null?void 0:i.setAudioEnable(!1)),h(!1),(l=n.current)==null||l.disconnect(),(u=n.current)==null||u.clearEventHandlers(),n.current=null,N(!1)}catch(v){console.error("断开失败:"+v)}},H=async()=>{var i;try{await((i=n.current)==null?void 0:i.setAudioEnable(!g)),h(!g)}catch(l){console.error("切换麦克风状态失败:"+l)}},J=r.useCallback((i,l)=>{i.on(I.ALL_SERVER,async(u,v)=>{var p;u==="server.session.created"&&await i.sendMessage({id:"",event_type:"session.update",data:{chat_config:{allow_voice_interrupt:!1}}}),u==="server.bot.join"&&l&&await((p=n.current)==null?void 0:p.sendMessage({id:"",event_type:"conversation.message.create",data:{role:"user",content_type:"text",content:l}}))})},[n.current]),Z=(i,l)=>{let u;i.on(I.ALL,(v,p)=>{if(p.event_type!==A.CONVERSATION_MESSAGE_DELTA&&p.event_type!==A.CONVERSATION_MESSAGE_COMPLETED&&p.event_type!=="conversation.created")return;const T=p.data.content;m(C=>(u==null?void 0:u.event_type)===A.CONVERSATION_MESSAGE_DELTA&&p.data.type==="answer"?[...C.slice(0,-1),{content:C[C.length-1].content+T,role:C[C.length-1].role}]:T!==""&&p.event_type===A.CONVERSATION_MESSAGE_DELTA||p.event_type===A.CONVERSATION_MESSAGE_COMPLETED&&(p.data.type==="answer"||p.data.type==="question")&&p.data.role!==S.Assistant?[...C,{content:T,role:p.data.role}]:l===""&&p.event_type==="conversation.created"?[...C,{content:p.data.prologue,role:S.Assistant}]:C),u=p})},K=r.useCallback(i=>{i.on(I.AUDIO_AGENT_SPEECH_STARTED,async()=>{var l;y(!0),await((l=n.current)==null?void 0:l.setAudioEnable(!1)),h(!1)}),i.on(I.AUDIO_AGENT_SPEECH_STOPPED,async()=>{var l;y(!1),await((l=n.current)==null?void 0:l.setAudioEnable(!0)),h(!0)}),i.on(I.CONNECTING,()=>{k(!0),N(!1)}),i.on(I.CONNECTED,(l,u)=>{q(u),k(!1),N(!0)})},[n.current]);return e.jsx(R.Provider,{value:{client:n.current,isConnecting:x,isConnected:w,audioEnabled:g,isSupportVideo:f,messageList:d,isAiTalking:j,roomInfo:Q,initClient:G,handleConnect:U,handleInterrupt:z,handleDisconnect:F,toggleMicrophone:H},children:t})};function ce(){const{messageList:t}=r.useContext(R),s=r.useRef(null),o=()=>{var c;(c=s.current)==null||c.scrollIntoView({behavior:"smooth"})};return r.useEffect(()=>{o()},[t]),e.jsxs("div",{className:"flex-1 flex flex-col overflow-y-auto",children:[e.jsx("div",{className:"w-full min-h-[120px] h-[120px]",children:e.jsxs("div",{className:"relative h-full",children:[e.jsx("img",{src:"/icons/hello.gif",alt:"",className:"absolute top-0 h-[97px] left-[50%] translate-x-[-50%]"}),e.jsx("img",{src:"/icons/conversation-bg.png",alt:"background",className:"w-[222px] h-[49px] absolute bottom-0 left-[50%] translate-x-[-50%]"}),e.jsx("div",{className:"text-black text-[14px] absolute bottom-[22px] left-[50%] translate-x-[-50%] z-[10]",children:"Hey,我是您的六纬AI填报师"})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[t.map((c,a)=>e.jsx("div",{className:`flex ${c.role===S.Assistant?"justify-start":"justify-end"}`,children:e.jsx("div",{className:`max-w-3/4 p-3 rounded-lg ${c.role===S.Assistant?"bg-white text-black rounded-tl-none":"bg-blue-500 text-white rounded-tr-none"}`,children:e.jsx(ee,{remarkPlugins:[te],children:c.content})})},a)),e.jsx("div",{ref:s})]})]})}const ae="_talkWrapper_5jmgu_23",ie="_listenerDot_5jmgu_53",le="_isTalking_5jmgu_93",ue="_microphoneWrapper_5jmgu_157",b={talkWrapper:ae,listenerDot:ie,isTalking:le,microphoneWrapper:ue},de="/icons/lockmicrophone.png",pe="/icons/microphone.png",ge="/icons/handoff.png",he=t=>{const s=r.useRef(null),{handleDisconnect:o}=re(),{toast:c}=W(),a=r.useRef(null);return r.useEffect(()=>{if(!t.access_token||!t.roomId)return;const n=new se().withServerTimeout(3e4).withAutomaticReconnect().withUrl(`https://api.v3.ycymedu.com/hubs/weminpro?access_token=${t.access_token}&roomId=${t.roomId}`).configureLogging(ne.Information).build();return s.current=n,n.on("ForceOffline",function(d){c({variant:"destructive",title:"下线提醒",description:d}),o()}),n.on("SendWarn",function(d){console.warn(`下线提醒:${d}"`),c({variant:"destructive",title:"下线提醒",description:d})}),n.start().then(()=>{console.log("SignalR连接已建立"),a.current=setInterval(()=>{n.invoke("Ping")},5e3)}).catch(d=>{console.error("SignalR连接失败:",d)}),()=>{s.current&&s.current.stop().then(()=>{clearInterval(a.current),console.log("SignalR连接已关闭")}).catch(d=>{console.error("关闭SignalR连接失败:",d)})}},[t.access_token,t.roomId]),s.current};function me({className:t,...s}){const{handleDisconnect:o,toggleMicrophone:c,audioEnabled:a,isAiTalking:n,handleInterrupt:d,roomInfo:m}=r.useContext(R),[x]=P();return he({access_token:x.get("token")||"",roomId:(m==null?void 0:m.roomId)||""}),e.jsxs("div",{className:"flex items-center justify-center bg-white pb-[20px] pt-[10px] gap-[10px]",...s,children:[e.jsxs("div",{className:`${b.microphoneWrapper}`,onClick:o,children:[e.jsx("img",{src:ge,alt:"handoff"}),e.jsx("div",{children:"挂断"})]}),e.jsxs("div",{className:`${b.microphoneWrapper}`,onClick:c,children:[e.jsx("img",{src:a?pe:de,alt:"lock"}),e.jsx("div",{children:a?"关麦":"开麦"})]}),e.jsxs("div",{className:`${b.talkWrapper}`,onClick:d,children:[e.jsxs("div",{className:`${n?b.isTalking:""} ${b.listenerDot}`,children:[e.jsx("span",{style:{"--d":"2"}}),e.jsx("span",{style:{"--d":"1"}}),e.jsx("span",{style:{"--d":"0"}}),e.jsx("span",{style:{"--d":"1"}}),e.jsx("span",{style:{"--d":"2"}})]}),e.jsx("div",{children:n?"点击打断":"正在听"})]})]})}function fe(){return e.jsxs("div",{className:"flex flex-col max-h-full h-full",children:[e.jsx(ce,{}),e.jsx(me,{})]})}const xe="/icons/hello.gif",_e="/icons/whatsThing.png",je="/icons/circle.png",ye="/icons/right.png",Ee="_headerWrapper_lrk2k_1",ke="_wrapper_lrk2k_15",ve="_img_lrk2k_37",Ce="_text_lrk2k_81",Ne="_main_lrk2k_101",Re="_thing_lrk2k_135",we="_circle_lrk2k_153",Ie="_rightIcon_lrk2k_179",Ae="_change_lrk2k_189",be="_tip_lrk2k_197",Se="_rotating_lrk2k_223",_={headerWrapper:Ee,wrapper:ke,img:ve,text:Ce,"main-wrapper":"_main-wrapper_lrk2k_101",main:Ne,thing:Re,circle:we,rightIcon:Ie,change:Ae,tip:be,rotating:Se},Te=t=>async(s,o,c={})=>{const a={method:t,...c};if(t!=="GET"&&o)a.body=JSON.stringify(o);else if(t==="GET"&&o){const m=[];for(const[x,k]of Object.entries(o))m.push(`${x}=${k}`);s+=`?${m.join("&")}`}const n=await fetch(`${s}`,a),d=await n.json();return n.ok?d:{error:d.message||"Request failed",code:n.status}},D=Te("GET"),Oe=async({options:t})=>{const s=await D("https://api.v3.ycymedu.com/api/zhiYuan/aigcquestionswords?",{},t);return s.code===200?{result:s.result}:{result:[],message:s.message}};function B(){const t=r.useRef(null),s=()=>(t.current||(t.current=new AbortController),t.current.signal),o=()=>{t.current&&(t.current.abort(),t.current=null)},c=()=>(o(),t.current=new AbortController,t.current.signal);return r.useEffect(()=>()=>{o()},[]),{getSignal:s,abortAll:o,recreate:c}}function $e({toRoom:t}){const[s,o]=r.useState(!1),[c,a]=r.useState([]),[n,d]=r.useState([]),{getSignal:m}=B(),x=()=>{const g=Array.from(n),h=[],f=Math.min(4,g.length);for(let j=0;j{const{result:g,message:h}=await Oe({options:{signal:m()}});h?console.log(h):d(g)};r.useEffect(()=>{a(x())},[n]),r.useEffect(()=>{k()},[]);const w=()=>{o(!0),a(x()),setTimeout(()=>{o(!1)},1e3)},N=async g=>{t(g)};return e.jsxs("div",{className:_.headerWrapper,children:[e.jsxs("div",{className:_.wrapper,children:[e.jsx("img",{className:_.img,src:xe,alt:"hello"}),e.jsx("div",{className:_.text,children:"Hey,我是您的六纬AI小助手"})]}),e.jsxs("div",{className:_["main-wrapper"],children:[e.jsxs("div",{className:_.main,onClick:w,children:[e.jsx("img",{className:_.thing,src:_e,alt:"whatsThing"}),e.jsxs("div",{className:_.circle,children:[e.jsx("img",{src:je,className:s?_.rotating:"",alt:"circle"}),e.jsx("div",{className:_.change,children:"换一批"})]})]}),c.map((g,h)=>e.jsxs("div",{className:_.tip,onClick:()=>N(g),children:[e.jsx("div",{children:g}),e.jsx("img",{src:ye,alt:"right-icon",className:_.rightIcon})]},h))]})]})}const Me="_wrapper_e1j90_1",Pe="_text_e1j90_75",We="_call_e1j90_87",$={wrapper:Me,text:Pe,call:We},De="/icons/call.png";function Le(t){const{disable:s,loading:o,className:c,...a}=t,{isConnecting:n}=r.useContext(R);return e.jsxs("div",{className:`${$.wrapper} ${c}`,...a,children:[e.jsx("img",{className:$.call,src:De,alt:"call"}),e.jsx("div",{className:$.text,children:s?"暂不可用":n?"连接中":"发起通话"})]})}const Ge="/icons/myInput.png",He="/icons/rightBlue.png",Be="_scoreWrapper_1g8jt_1",Ve="_innerWrapper_1g8jt_13",Qe="_detail_1g8jt_37",qe="_right_1g8jt_53",Ue="_imgIcon_1g8jt_65",ze="_rightBlue_1g8jt_75",E={scoreWrapper:Be,innerWrapper:Ve,detail:Qe,right:qe,imgIcon:Ue,rightBlue:ze};function Fe({toRoom:t}){const[s]=P(),o=s.get("provinceName")||"山东省",c=s.get("subjectGroup")||"物/化/史",a=s.get("expectedScore")||500,n=async()=>{t(`我的高考地点在${o},我选择的科目是${c},我的高考分数为${a}分。我适合哪些学校和专业`)};return e.jsx("div",{className:E.scoreWrapper,children:e.jsxs("div",{className:E.innerWrapper,children:[e.jsxs("div",{className:E.left,children:[e.jsx("img",{src:Ge,className:E.imgIcon,alt:"input-ico"}),e.jsxs("div",{className:E.detail,children:[e.jsx("div",{className:E.city,children:o}),e.jsx("div",{className:E.subject,children:c.split(",").join("/")}),e.jsxs("div",{className:E.score,children:[a,"分"]})]})]}),e.jsxs("div",{className:E.right,onClick:n,children:[e.jsx("span",{children:"智能分析"}),e.jsx("img",{src:He,alt:"right",className:E.rightBlue})]})]})})}const Je=async({options:t})=>{const s=await D("https://api.v3.ycymedu.com/api/sysOnlineUser/hasitexpired",{},t);return s.code===200?{result:s.result}:{result:[],message:s.message}},Ze=async({params:t,options:s})=>{const o=await D("https://api.v3.ycymedu.com/api/busScale/GetBusAIReportKeyWord",t,s);return o.code===200?{result:o.result}:{result:[],message:o.message}},V=r.createContext({hasHandledReport:!1,setHasHandledReport:()=>{}}),Ke=({children:t})=>{const[s,o]=r.useState(!1);return e.jsx(V.Provider,{value:{hasHandledReport:s,setHasHandledReport:o},children:t})};function Ye(){const{handleConnect:t}=r.useContext(R),{setHasHandledReport:s,hasHandledReport:o}=r.useContext(V),[c]=P(),[a,n]=r.useState(!0),d=c.get("token")||"",m=c.get("reportId")||"",x=c.get("reportType")||"",{toast:k}=W(),{getSignal:w}=B(),N=async()=>{try{const{result:f,message:j}=await Je({options:{signal:w(),headers:{Authorization:`Bearer ${d}`}}});if(j)console.log(j);else{const y=f;n(!y.isExpired),!y.isExpired&&y.msg&&k({title:y.msg,description:"请重新登录"})}}catch(f){f.name!=="AbortError"&&console.error("获取用户令牌失败:",f)}},g=async()=>{try{const{result:f,message:j}=await Ze({params:{Type:x,Id:m},options:{signal:w(),headers:{Authorization:`Bearer ${d}`}}});j?console.log(j):(t(f),s(!0))}catch(f){f.name!=="AbortError"&&console.error("获取报告失败:",f)}};r.useEffect(()=>{N()},[d]),r.useEffect(()=>{m&&x&&!o&&g()},[m,x,o]);const h=f=>{a||t(f)};return e.jsxs("div",{className:"flex flex-col items-center h-full",children:[e.jsx($e,{toRoom:h}),e.jsx(Fe,{toRoom:h}),e.jsx(Le,{disable:a,onClick:()=>h()})]})}function Xe(){const{isConnected:t}=r.useContext(R),s=async()=>{await M.checkDevicePermission(!1)};return r.useEffect(()=>{s()},[]),e.jsx(Ke,{children:t?e.jsx(fe,{}):e.jsx(Ye,{})})}function st(){return e.jsx(oe,{children:e.jsx(Xe,{})})}export{st as default}; diff --git a/build/assets/index-CN-hwWKH.js b/build/assets/index-mKhgCiGE.js similarity index 95% rename from build/assets/index-CN-hwWKH.js rename to build/assets/index-mKhgCiGE.js index 8a07245..d5edc01 100644 --- a/build/assets/index-CN-hwWKH.js +++ b/build/assets/index-mKhgCiGE.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/App-D4RUlINY.js","assets/.pnpm-CAIuqsZ0.js","assets/MainLayout-BMCWJnk-.js","assets/use-toast-DO4tfD4I.js"])))=>i.map(i=>d[i]); -var v=Object.defineProperty;var x=(s,t,n)=>t in s?v(s,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):s[t]=n;var m=(s,t,n)=>x(s,typeof t!="symbol"?t+"":t,n);import{r as d,c as P,j as a,a as _,R as L}from"./.pnpm-CAIuqsZ0.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))f(e);new MutationObserver(e=>{for(const o of e)if(o.type==="childList")for(const r of o.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&f(r)}).observe(document,{childList:!0,subtree:!0});function n(e){const o={};return e.integrity&&(o.integrity=e.integrity),e.referrerPolicy&&(o.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?o.credentials="include":e.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function f(e){if(e.ep)return;e.ep=!0;const o=n(e);fetch(e.href,o)}})();const j="modulepreload",O=function(s){return"/"+s},h={},p=function(t,n,f){let e=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),i=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));e=Promise.allSettled(n.map(c=>{if(c=O(c),c in h)return;h[c]=!0;const u=c.endsWith(".css"),E=u?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${E}`))return;const l=document.createElement("link");if(l.rel=u?"stylesheet":j,u||(l.as="script"),l.crossOrigin="",l.href=c,i&&l.setAttribute("nonce",i),document.head.appendChild(l),u)return new Promise((y,g)=>{l.addEventListener("load",y),l.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${c}`)))})}))}function o(r){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=r,window.dispatchEvent(i),!i.defaultPrevented)throw r}return e.then(r=>{for(const i of r||[])i.status==="rejected"&&o(i.reason);return t().catch(o)})},R=d.lazy(()=>p(()=>import("./App-D4RUlINY.js"),__vite__mapDeps([0,1]))),S=d.lazy(()=>p(()=>import("./MainLayout-BMCWJnk-.js"),__vite__mapDeps([2,1,3])));class w extends d.Component{constructor(){super(...arguments);m(this,"state",{hasError:!1})}static getDerivedStateFromError(n){return{hasError:!0}}render(){return this.state.hasError?a.jsx("h1",{children:"出错了,请稍后再试。"}):this.props.children}}const b=P([{path:"/",element:a.jsx(S,{}),errorElement:a.jsx(w,{children:a.jsx("div",{className:"flex-auto flex flex-col p-6",children:"出错了,请稍后再试。"})}),children:[{path:"/",element:a.jsx(R,{})}]}]);_(document.getElementById("root")).render(a.jsx(d.StrictMode,{children:a.jsx(L,{router:b})}));export{p as _}; +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/App-Bxrx0fG0.js","assets/.pnpm-CAIuqsZ0.js","assets/MainLayout-BMCWJnk-.js","assets/use-toast-DO4tfD4I.js"])))=>i.map(i=>d[i]); +var v=Object.defineProperty;var x=(s,t,n)=>t in s?v(s,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):s[t]=n;var m=(s,t,n)=>x(s,typeof t!="symbol"?t+"":t,n);import{r as d,c as P,j as a,a as _,R as L}from"./.pnpm-CAIuqsZ0.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))f(e);new MutationObserver(e=>{for(const o of e)if(o.type==="childList")for(const r of o.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&f(r)}).observe(document,{childList:!0,subtree:!0});function n(e){const o={};return e.integrity&&(o.integrity=e.integrity),e.referrerPolicy&&(o.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?o.credentials="include":e.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function f(e){if(e.ep)return;e.ep=!0;const o=n(e);fetch(e.href,o)}})();const j="modulepreload",O=function(s){return"/"+s},h={},p=function(t,n,f){let e=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),i=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));e=Promise.allSettled(n.map(c=>{if(c=O(c),c in h)return;h[c]=!0;const u=c.endsWith(".css"),E=u?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${E}`))return;const l=document.createElement("link");if(l.rel=u?"stylesheet":j,u||(l.as="script"),l.crossOrigin="",l.href=c,i&&l.setAttribute("nonce",i),document.head.appendChild(l),u)return new Promise((y,g)=>{l.addEventListener("load",y),l.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${c}`)))})}))}function o(r){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=r,window.dispatchEvent(i),!i.defaultPrevented)throw r}return e.then(r=>{for(const i of r||[])i.status==="rejected"&&o(i.reason);return t().catch(o)})},R=d.lazy(()=>p(()=>import("./App-Bxrx0fG0.js"),__vite__mapDeps([0,1]))),S=d.lazy(()=>p(()=>import("./MainLayout-BMCWJnk-.js"),__vite__mapDeps([2,1,3])));class w extends d.Component{constructor(){super(...arguments);m(this,"state",{hasError:!1})}static getDerivedStateFromError(n){return{hasError:!0}}render(){return this.state.hasError?a.jsx("h1",{children:"出错了,请稍后再试。"}):this.props.children}}const b=P([{path:"/",element:a.jsx(S,{}),errorElement:a.jsx(w,{children:a.jsx("div",{className:"flex-auto flex flex-col p-6",children:"出错了,请稍后再试。"})}),children:[{path:"/",element:a.jsx(R,{})}]}]);_(document.getElementById("root")).render(a.jsx(d.StrictMode,{children:a.jsx(L,{router:b})}));export{p as _}; diff --git a/build/index.html b/build/index.html index 0ab2972..2877795 100644 --- a/build/index.html +++ b/build/index.html @@ -23,7 +23,7 @@ // VConsole will be exported to `window.VConsole` by default. var vConsole = new window.VConsole(); --> - + diff --git a/src/components/Provider/RealtimeClientProvider.tsx b/src/components/Provider/RealtimeClientProvider.tsx index 37d9b1c..6b0e247 100644 --- a/src/components/Provider/RealtimeClientProvider.tsx +++ b/src/components/Provider/RealtimeClientProvider.tsx @@ -32,12 +32,11 @@ export const RealtimeClientContext = createContext<{ messageList: { content: string; role: RoleType }[]; isAiTalking: boolean; roomInfo: RoomInfo | null; - initClient: (initMessage?:string) => void; - handleConnect: (initMessage?:string) => Promise; + initClient: (initMessage?: string) => void; + handleConnect: (initMessage?: string) => Promise; handleInterrupt: () => void; handleDisconnect: () => void; toggleMicrophone: () => void; - }>({ client: null, isConnecting: false, @@ -52,7 +51,6 @@ export const RealtimeClientContext = createContext<{ handleInterrupt: () => {}, handleDisconnect: () => {}, toggleMicrophone: () => {}, - }); // 添加自定义hook @@ -92,13 +90,11 @@ export const RealtimeClientProvider = ({ // 是否正在说话 const [isAiTalking, setIsAiTalking] = useState(false); - - const [roomInfo, setRoomInfo] = useState(null); const { toast } = useToast(); - const initClient = async (_initMessage?:string) => { + const initClient = async (_initMessage?: string) => { const permission = await RealtimeUtils.checkDevicePermission(false); const device = await RealtimeUtils.getAudioDevices(); @@ -129,14 +125,12 @@ export const RealtimeClientProvider = ({ clientRef.current = client; - setupEventListeners(client); - setupMessageEventListeners(client,_initMessage ?? ''); - setupInitMessageEventListener(client,_initMessage) + setupMessageEventListeners(client, _initMessage ?? ""); + setupInitMessageEventListener(client, _initMessage); }; - - const handleConnect = async (initMessage?:string) => { + const handleConnect = async (initMessage?: string) => { try { if (!clientRef.current) { await initClient(initMessage); @@ -173,7 +167,7 @@ export const RealtimeClientProvider = ({ } }; - const handleDisconnect = async() => { + const handleDisconnect = async () => { try { // 关闭客户的时候清除一些信息 setIsAiTalking(false); @@ -199,53 +193,62 @@ export const RealtimeClientProvider = ({ } }; + const setupInitMessageEventListener = useCallback( + (client: RealtimeClient, _initMessage?: string) => { + client.on(EventNames.ALL_SERVER, async (eventName, _event: any) => { + if (eventName === "server.session.created") { + await client.sendMessage({ + id: "", + event_type: "session.update", + data: { + chat_config: { + allow_voice_interrupt: false, + }, + }, + }); + } + if (eventName === "server.bot.join" && _initMessage) { + // 这里需要加个 server. 前缀 + await clientRef.current?.sendMessage({ + id: "", + event_type: "conversation.message.create", + data: { + role: "user", + content_type: "text", + content: _initMessage, + }, + }); + } + }); + }, + [clientRef.current] + ); - const setupInitMessageEventListener = useCallback((client: RealtimeClient,_initMessage?:string) => { - client.on(EventNames.ALL_SERVER, async(eventName, _event: any) => { - if (eventName === "server.session.created") { - await client.sendMessage({ - id:'', - "event_type":"session.update", - data:{ - chat_config:{ - allow_voice_interrupt:false - } - } - }) - } - if(eventName === "server.bot.join" && _initMessage){ - // 这里需要加个 server. 前缀 - await clientRef.current?.sendMessage({ - id: "", - event_type: "conversation.message.create", - data: { - role: "user", - content_type: "text", - content: _initMessage, - }, - }); - } - }); - },[clientRef.current]); - - const setupMessageEventListeners = (client: RealtimeClient,_initMessage:string) => { + const setupMessageEventListeners = ( + client: RealtimeClient, + _initMessage: string + ) => { let lastEvent: any; + client.on(EventNames.ALL, (_eventName, event: any) => { // AI智能体设置 if ( event.event_type !== ChatEventType.CONVERSATION_MESSAGE_DELTA && event.event_type !== ChatEventType.CONVERSATION_MESSAGE_COMPLETED && - event.event_type !== "conversation.created" + event.event_type !== "conversation.created" && + event.event_type !== "conversation.message.create" ) { return; } const content = event.data.content; setMessageList((prev) => { - // 如果上一个事件是增量更新,则附加到最后一条消息 + // 如果上一个事件是增量更新,则附加到最后一条消息 if ( lastEvent?.event_type === ChatEventType.CONVERSATION_MESSAGE_DELTA && - (event.data.type === "answer") + event.event_type === ChatEventType.CONVERSATION_MESSAGE_DELTA && + lastEvent.data.type === event.data.type && + lastEvent.data.answer_id === event.data.answer_id ) { return [ ...prev.slice(0, -1), @@ -254,7 +257,21 @@ export const RealtimeClientProvider = ({ role: prev[prev.length - 1].role, }, ]; - }else if ( // 否则添加新消息 + } + + // 添加AI的欢迎语 + if ( + _initMessage === "" && + event.event_type === "conversation.created" + ) { + return [ + ...prev, + { content: event.data.prologue, role: RoleType.Assistant }, + ]; + } + + // 否则添加新消息 + if ( (content !== "" && event.event_type === ChatEventType.CONVERSATION_MESSAGE_DELTA) || (event.event_type === ChatEventType.CONVERSATION_MESSAGE_COMPLETED && @@ -263,20 +280,9 @@ export const RealtimeClientProvider = ({ ) { return [...prev, { content: content, role: event.data.role }]; } - - // 添加AI的欢迎语 - if (_initMessage === "" && event.event_type === "conversation.created") { - return [ - ...prev, - { content: event.data.prologue, role: RoleType.Assistant }, - ]; - } - return prev; }); - if(event.data.type === "answer" || event.data.type === "question"){ - lastEvent = event; - } + lastEvent = event; }); }; @@ -284,7 +290,7 @@ export const RealtimeClientProvider = ({ const setupEventListeners = useCallback( (client: RealtimeClient) => { // 监听 AI 开始说话事件 - client.on(EventNames.AUDIO_AGENT_SPEECH_STARTED, async() => { + client.on(EventNames.AUDIO_AGENT_SPEECH_STARTED, async () => { // console.log("AI开始说话"); setIsAiTalking(true); await clientRef.current?.setAudioEnable(false); @@ -292,7 +298,7 @@ export const RealtimeClientProvider = ({ }); // 监听 AI 结束说话事件 - client.on(EventNames.AUDIO_AGENT_SPEECH_STOPPED, async() => { + client.on(EventNames.AUDIO_AGENT_SPEECH_STOPPED, async () => { // console.log("AI结束说话"); setIsAiTalking(false); await clientRef.current?.setAudioEnable(true); @@ -348,7 +354,6 @@ export const RealtimeClientProvider = ({ handleInterrupt, handleDisconnect, toggleMicrophone, - }} > {children}