@szjy/ai-coms 0.1.12 → 0.1.13
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/README.md +40 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +1598 -1120
- package/dist/index.umd.js +3 -2
- package/dist/packages/api/mock.d.ts +16 -0
- package/dist/packages/components/AiChat/src/custom-ui/actions/postMessage.d.ts +12 -0
- package/dist/packages/components/AiChat/src/custom-ui/components/button.d.ts +9 -0
- package/dist/packages/components/AiChat/src/custom-ui/components/list.d.ts +8 -0
- package/dist/packages/components/AiChat/src/custom-ui/events.d.ts +27 -0
- package/dist/packages/components/AiChat/src/custom-ui/index.d.ts +7 -0
- package/dist/packages/components/AiChat/src/custom-ui/parse.d.ts +11 -0
- package/dist/packages/components/AiChat/src/custom-ui/registry.d.ts +8 -0
- package/dist/packages/components/AiChat/src/custom-ui/render.d.ts +18 -0
- package/dist/packages/components/AiChat/src/custom-ui/types.d.ts +84 -0
- package/dist/packages/components/AiChat/src/index.vue.d.ts +56 -3
- package/dist/packages/components/AiChat/src/transform/index.d.ts +2 -1
- package/dist/packages/components/AiChatPlain/src/index.vue.d.ts +52 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
(function(
|
|
2
|
-
`)).getReader();console.log("reader from response:",o),n({error:0,reader:o})}else n({error:1,reader:null})}).catch(()=>{n({error:1,reader:null})})}):{error:1,reader:null}}let H=null;function rt(){return H||(window.markdownit?(H=new window.markdownit({html:!0,linkify:!0,typographer:!0}),H.renderer.rules.fence=(r,t)=>{const a=r[t],n=(a.info||"").trim().split(/\s+/)[0];let s="";if(n&&window.hljs&&window.hljs.getLanguage(n))try{s=window.hljs.highlight(a.content,{language:n}).value}catch{s=""}return s||(s=H.utils.escapeHtml(a.content)),`<pre class="md-code-block"><code class="hljs${n?" language-"+n:""}">${s}</code></pre>`}):console.log("markdownit is not loaded"),H)}const at=(r,t)=>{const a=r.__vccOpts||r;for(const[n,s]of t)a[n]=s;return a},st=["src","alt"],le=at({__name:"SvgIcon",props:{name:{type:String,required:!0},size:{type:[Number,String],default:16},color:{type:String,default:""},className:{type:String,default:""},basePath:{type:String,default:"/icons/"}},setup(r){const t=r,a=e.computed(()=>{if(t.name.startsWith("http://")||t.name.startsWith("https://")||t.name.startsWith("/"))return t.name;const o=t.name.endsWith(".svg")?t.name:`${t.name}.svg`;return`${t.basePath}${o}`}),n=e.computed(()=>{const o=typeof t.size=="number"?`${t.size}px`:t.size;return{width:o,height:o,display:"inline-flex",justifyContent:"center",alignItems:"center"}}),s=e.computed(()=>{const o={width:"100%",height:"100%"};return t.color&&(o.filter=`drop-shadow(0 0 0 ${t.color})`),o});return(o,i)=>(e.openBlock(),e.createElementBlock("div",{class:"svg-icon-wrapper",style:e.normalizeStyle(n.value)},[e.createElementVNode("img",{src:a.value,alt:r.name,class:e.normalizeClass(["svg-icon",r.className]),style:e.normalizeStyle(s.value)},null,14,st)],4))}},[["__scopeId","data-v-490b11c1"]]),it=async r=>{if(navigator.clipboard&&navigator.permissions)await navigator.clipboard.writeText(r);else{const t=document.createElement("textArea");t.value=r,t.style.width=0,t.style.position="fixed",t.style.left="-999px",t.style.top="10px",t.setAttribute("readonly","readonly"),document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t)}},lt={class:"thinking-title"},ct={class:"thinking-toggle-hint"},dt=["innerHTML"],ut=["innerHTML"],ht=10,mt={__name:"Previewer",props:{reader:null,model:"szjy",scrollToBottomFn:null,displayText:"",messagePostRender:{type:Function,default:null}},emits:["failed","completed","updating"],setup(r,{expose:t,emit:a}){const{appContext:n}=e.getCurrentInstance(),{$message:s}=n.config.globalProperties,o=r,i=e.ref(o.displayText||""),l=e.ref(!0),c=e.ref(!1),k=e.ref(!!o.displayText),E=a,_=e.ref(null);let V=null;const S=e.computed(()=>tt(i.value)),z=e.computed(()=>S.value.thinking.length>0),v=e.ref(o.displayText?S.value.content.length:0),P=e.computed(()=>S.value.isThinkingStreaming&&!k.value),y=e.ref(!1),f=()=>{y.value=!y.value};let p=null,u=null;const d=e.ref(0);e.watch(()=>S.value.thinking,I=>{!I||d.value>0||(u===null&&(u=p??Date.now()),S.value.content&&w())});const w=()=>{if(d.value>0||!z.value)return;const I=u??p;I&&(d.value=Math.max(1,Math.round((Date.now()-I)/1e3)))},b=e.computed(()=>P.value?"正在思考...":d.value>0?`已深度思考(用时 ${d.value} 秒)`:"思考过程"),B=e.computed(()=>z.value?H?H.render(S.value.thinking):S.value.thinking:""),N=e.computed(()=>S.value.content.slice(0,v.value)),R=e.computed(()=>H?H.render(N.value):N.value),g=()=>{o.reader&&o.reader.cancel(),c.value=!0,O.value=!1,D(),k.value=!0,w(),E("completed",i.value),l.value=!1,V&&(cancelAnimationFrame(V),V=null)},U=e.computed(()=>`${R.value}`),$=e.ref(!1),q=()=>{$.value=!0},D=()=>{$.value=!1},O=e.ref(!1),X=async()=>{if(!o.reader)return;const I=new TextDecoder("utf-8");for(l.value=!0;!c.value;)try{if(!o.reader){O.value=!0;break}const{value:M,done:A}=await o.reader.read();if(!o.reader){O.value=!0;break}if(A){O.value=!0;break}const j=ve[o.model];if(!j)break;const K=j.call(ve,M,I);if(K.done){O.value=!0;break}!p&&K.content&&(p=Date.now()),i.value+=K.content,V===null&&ae()}catch(M){O.value=!0,console.log(3333,M),E("failed",M),g();break}finally{D()}},ee=async()=>{o.scrollToBottomFn&&o.scrollToBottomFn()},te=(I=()=>{},M=()=>{})=>{const A=S.value.content.length;v.value>A&&(v.value=A),v.value<A?(v.value=Math.min(A,v.value+ht),I()):M()},ae=()=>{if(c.value&&V){cancelAnimationFrame(V),V=null,l.value=!1;return}O.value?te(()=>{V=requestAnimationFrame(ae),E("updating",null)},()=>{w(),E("completed",i.value),l.value=!1,k.value=!0,e.nextTick(()=>{if(O.value=!1,o.messagePostRender&&_.value)try{o.messagePostRender(_.value,S.value.content)}catch(I){console.error("messagePostRender 执行失败:",I)}}),V=null}):(te(),V=requestAnimationFrame(ae)),ee()};e.watch(()=>o.reader,()=>{o.reader&&X()},{immediate:!0,deep:!0}),e.onUnmounted(()=>{g()}),t({abortReader:g,initializeStart:q,initializeEnd:D}),e.computed(()=>$.value?!0:(!o.reader||!l||i.value,!1));const ue=async()=>{try{const I=S.value.content||i.value;await it(I),s.success("复制成功")}catch(I){console.error("复制失败:",I),s.error("复制失败")}};return(I,M)=>(e.openBlock(),e.createBlock(e.Transition,{name:"fade"},{default:e.withCtx(()=>[U.value||z.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"refWrapperContent",ref:_,"text-16":"",class:"w-full h-full overflow-y-auto relative","p-24px":""},[z.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["ai-thinking-block",{"is-expanded":y.value||P.value,"is-streaming":P.value}])},[e.createElementVNode("div",{class:"thinking-header",onClick:f},[M[0]||(M[0]=e.createElementVNode("svg",{class:"thinking-arrow",viewBox:"0 0 1024 1024",width:"10",height:"10"},[e.createElementVNode("path",{d:"M704 512 320 256v512z",fill:"currentColor"})],-1)),e.createElementVNode("span",lt,e.toDisplayString(b.value),1),e.createElementVNode("span",ct,e.toDisplayString(y.value||P.value?"收起":"展开"),1)]),e.withDirectives(e.createElementVNode("div",{class:"thinking-body",innerHTML:B.value},null,8,dt),[[e.vShow,y.value||P.value]])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"markdown-wrapper",innerHTML:U.value},null,8,ut),k.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:"ai-copy-btn-wrapper",onClick:ue},[e.createVNode(le,{name:"/images/svg/copy.svg",color:"#666666"}),M[1]||(M[1]=e.createElementVNode("span",{class:"copy-text"},"复制",-1))])):e.createCommentVNode("",!0)],512)):e.createCommentVNode("",!0)]),_:1}))}};class Ve{constructor(t,a){x(this,"ratio");x(this,"leftover",new Float32Array(0));x(this,"fracOffset",0);this.ratio=t/a}reset(){this.leftover=new Float32Array(0),this.fracOffset=0}process(t){if(this.ratio===1)return new Float32Array(t);const a=new Float32Array(this.leftover.length+t.length);if(a.set(this.leftover),a.set(t,this.leftover.length),a.length<2)return this.leftover=a,new Float32Array(0);const n=[];let s=this.fracOffset;for(;s<a.length-1;){const i=Math.floor(s),l=s-i,c=a[i],k=a[i+1];n.push(c+l*(k-c)),s+=this.ratio}const o=Math.min(a.length,Math.floor(s));return this.leftover=a.slice(o),this.fracOffset=s-o,Float32Array.from(n)}}class xe{constructor(t={}){x(this,"targetSampleRate");x(this,"audioContext",null);x(this,"mediaStream",null);x(this,"sourceNode",null);x(this,"processorNode",null);x(this,"muteGain",null);x(this,"resampler",null);x(this,"audioChunks",[]);x(this,"onVolumeChange");x(this,"onAudioChunk");x(this,"_isRecording",!1);this.targetSampleRate=t.sampleRate||16e3,this.onVolumeChange=t.onVolumeChange,this.onAudioChunk=t.onAudioChunk}get isRecording(){return this._isRecording}async start(){if(this._isRecording)return;if(!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia)throw new Error("当前浏览器环境不支持获取麦克风音频,请使用现代浏览器并确保在 HTTPS/localhost 环境下运行。");try{this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:{channelCount:{ideal:1},sampleRate:{ideal:this.targetSampleRate},echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})}catch(n){throw n.name==="NotAllowedError"||n.name==="PermissionDeniedError"?new Error("麦克风权限被拒绝,请在浏览器地址栏允许麦克风访问权限。"):n.name==="NotFoundError"||n.name==="DevicesNotFoundError"?new Error("未检测到可用的麦克风输入设备。"):new Error(`无法启动麦克风: ${n.message||n}`)}const t=window.AudioContext||window.webkitAudioContext;try{this.audioContext=new t({sampleRate:this.targetSampleRate})}catch{this.audioContext=new t}this.audioContext.state==="suspended"&&await this.audioContext.resume(),this.audioChunks=[],this.resampler=this.audioContext.sampleRate===this.targetSampleRate?null:new Ve(this.audioContext.sampleRate,this.targetSampleRate),this.sourceNode=this.audioContext.createMediaStreamSource(this.mediaStream);const a=4096;this.processorNode=this.audioContext.createScriptProcessor(a,1,1),this.processorNode.onaudioprocess=n=>{var i;if(!this._isRecording)return;const s=new Float32Array(n.inputBuffer.getChannelData(0));if(this.onVolumeChange){let l=0;for(let E=0;E<s.length;E++)l+=s[E]*s[E];const c=Math.sqrt(l/s.length),k=Math.min(100,Math.round(c*100*5));this.onVolumeChange(k)}const o=this.resampler?this.resampler.process(s):s;o.length&&(this.audioChunks.push(o),(i=this.onAudioChunk)==null||i.call(this,o))},this.muteGain=this.audioContext.createGain(),this.muteGain.gain.value=0,this.sourceNode.connect(this.processorNode),this.processorNode.connect(this.muteGain),this.muteGain.connect(this.audioContext.destination),this._isRecording=!0}async stop(){if(!this._isRecording)return new Float32Array(0);this._isRecording=!1,this.cleanup();const t=this.audioChunks.reduce((s,o)=>s+o.length,0),a=new Float32Array(t);let n=0;for(const s of this.audioChunks)a.set(s,n),n+=s.length;return this.audioChunks=[],a}cancel(){this._isRecording=!1,this.audioChunks=[],this.cleanup()}cleanup(){this.processorNode&&(this.processorNode.disconnect(),this.processorNode.onaudioprocess=null,this.processorNode=null),this.muteGain&&(this.muteGain.disconnect(),this.muteGain=null),this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode=null),this.resampler=null,this.mediaStream&&(this.mediaStream.getTracks().forEach(t=>t.stop()),this.mediaStream=null),this.audioContext&&this.audioContext.state!=="closed"&&(this.audioContext.close().catch(()=>{}),this.audioContext=null)}}function Te(r,t,a){if(t===a)return new Float32Array(r);const n=t/a,s=Math.round(r.length/n),o=new Float32Array(s);for(let i=0;i<s;i++){const l=i*n,c=Math.floor(l),k=l-c,E=r[c]??0,_=r[c+1]??E;o[i]=E+k*(_-E)}return o}async function Re(r,t=16e3){const a=await r.arrayBuffer(),n=window.AudioContext||window.webkitAudioContext,s=new n;try{const o=await s.decodeAudioData(a);let i;if(o.numberOfChannels>1){i=new Float32Array(o.length);for(let l=0;l<o.numberOfChannels;l++){const c=o.getChannelData(l);for(let k=0;k<o.length;k++)i[k]+=c[k]/o.numberOfChannels}}else i=o.getChannelData(0);return Te(i,o.sampleRate,t)}finally{s.state!=="closed"&&await s.close().catch(()=>{})}}function fe(r,t=16e3){const a=new ArrayBuffer(44+r.length*2),n=new DataView(a),s=(i,l)=>{for(let c=0;c<l.length;c++)n.setUint8(i+c,l.charCodeAt(c))};s(0,"RIFF"),n.setUint32(4,36+r.length*2,!0),s(8,"WAVE"),s(12,"fmt "),n.setUint32(16,16,!0),n.setUint16(20,1,!0),n.setUint16(22,1,!0),n.setUint32(24,t,!0),n.setUint32(28,t*2,!0),n.setUint16(32,2,!0),n.setUint16(34,16,!0),s(36,"data"),n.setUint32(40,r.length*2,!0);let o=44;for(let i=0;i<r.length;i++,o+=2){const l=Math.max(-1,Math.min(1,r[i]));n.setInt16(o,l<0?l*32768:l*32767,!0)}return new Blob([n],{type:"audio/wav"})}const Be=16e3,ft=Math.round(Be*.35),pe="/scripts/ai/whisper.worker.js";function pt(){return new Worker(ge(pe),{type:"module"})}function ge(r){return/^https?:\/\//i.test(r)?r:typeof location<"u"?new URL(r,location.origin).href:r}function Ae(r){if(!r.ok)return!1;const t=(r.headers.get("content-type")||"").toLowerCase();return!(t.includes("text/html")||t.includes("application/xhtml+xml"))}async function gt(r){try{const t=await fetch(r,{method:"HEAD"});if(Ae(t))return!0}catch{}try{const t=await fetch(r,{headers:{Range:"bytes=0-64"}});if(Ae(t))return!0}catch{}return!1}async function yt(r){const t=[];r&&t.push(ge(r)),t.push(ge(pe));const a=[...new Set(t.filter(Boolean))];for(const n of a)if(await gt(n))return console.log("[VoiceInputManager] 使用语音 Worker:",n),n;return console.warn("[VoiceInputManager] 未探测到可访问的 Worker 脚本,将回退到 Vite 打包注入地址。已尝试:",a.join(" , ")),null}class _e{constructor(t={}){x(this,"recorder",null);x(this,"worker",null);x(this,"status","idle");x(this,"options");x(this,"isReady",!1);x(this,"initPromise",null);x(this,"currentTaskId",0);x(this,"pcmParts",[]);x(this,"pcmLength",0);x(this,"streamChunkIndex",0);x(this,"committedText","");this.options={soundBaseUrl:"/sounds/",remoteHost:"https://hf-mirror.com",modelId:"onnx-community/whisper-base",language:"chinese",...t}}get currentStatus(){return this.status}get ready(){return this.isReady}async init(t){if(!this.isReady)return this.initPromise?this.initPromise:(t&&(this.options.soundBaseUrl=t),this.initPromise=new Promise((a,n)=>{this.setStatus("loading","正在准备语音识别引擎..."),(async()=>{var o,i;try{const l=await yt(this.options.workerUrl);this.worker=l?new Worker(l,{type:"module"}):pt(),this.worker.onmessage=c=>{this.handleWorkerMessage(c,a,n)},this.worker.onerror=c=>{var _,V;const E=`语音后台线程异常: ${c.message||c.filename||l||"未知错误"}`;this.initPromise=null,this.setStatus("error",E),(V=(_=this.options).onError)==null||V.call(_,E),n(c)},this.worker.postMessage({type:"INIT",data:{modelId:this.options.modelId,soundBaseUrl:this.options.soundBaseUrl,remoteHost:this.options.remoteHost}})}catch(l){const c=`创建语音 Worker 失败: ${l.message||l}`;this.initPromise=null,this.setStatus("error",c),(i=(o=this.options).onError)==null||i.call(o,c),n(l)}})()}),this.initPromise)}async startRecording(){var t,a,n,s;if(!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia){const o=window.isSecureContext?"当前浏览器环境不支持获取麦克风音频,请使用现代浏览器。":"当前页面不是安全上下文,浏览器禁止调用麦克风。请使用 https:// 或 http://localhost / http://127.0.0.1 访问(通过局域网 IP 的 http 地址无法录音)。";throw this.setStatus("error",o),(a=(t=this.options).onError)==null||a.call(t,o),new Error(o)}this.isReady||await this.init(),this.recorder||(this.recorder=new xe({onVolumeChange:o=>{var i,l;(l=(i=this.options).onVolumeChange)==null||l.call(i,o)},onAudioChunk:o=>{this.appendPcm(o)}}));try{this.currentTaskId++,this.resetStreamState(),await this.recorder.start(),this.setStatus("recording","正在录音...")}catch(o){throw this.setStatus("error",o.message||"启动录音失败"),(s=(n=this.options).onError)==null||s.call(n,o.message||"启动录音失败"),o}}async stopAndTranscribe(){var t,a,n,s;if(!(!this.recorder||!this.recorder.isRecording))try{await this.recorder.stop();const o=this.mergePcm();if(o.length===0){this.resetStreamState(),this.setStatus("idle");return}this.setStatus("transcribing","正在识别语音...");try{const i=fe(o),l=URL.createObjectURL(i);(a=(t=this.options).onAudioRecorded)==null||a.call(t,l,i)}catch(i){console.warn("生成录音回放音频失败:",i)}await this.transcribeAudioData(o)}catch(o){this.setStatus("error",o.message||"音频处理失败"),(s=(n=this.options).onError)==null||s.call(n,o.message||"音频处理失败")}}async transcribeAudioData(t,a){var n,s,o,i;this.isReady||await this.init(),this.setStatus("transcribing","正在流式识别音频...");try{a&&((s=(n=this.options).onAudioRecorded)==null||s.call(n,a,fe(t))),this.currentTaskId++,this.resetStreamState(),this.appendPcm(t),this.dispatchFullAudio()}catch(l){this.setStatus("error",l.message||"音频处理失败"),(i=(o=this.options).onError)==null||i.call(o,l.message||"音频处理失败")}}async transcribeFile(t){var a,n;this.isReady||await this.init(),this.setStatus("loading","正在解析音频文件...");try{const s=await Re(t);if(s.length===0)throw new Error("未能从该文件中提取出有效音频");const o=URL.createObjectURL(t);await this.transcribeAudioData(s,o)}catch(s){this.setStatus("error",s.message||"音频文件解析失败"),(n=(a=this.options).onError)==null||n.call(a,s.message||"音频文件解析失败")}}cancelRecording(){var a;const t=this.currentTaskId;this.currentTaskId++,(a=this.worker)==null||a.postMessage({type:"CANCEL",taskId:t}),this.resetStreamState(),this.recorder&&this.recorder.cancel(),this.setStatus("idle")}cancelTranscribe(){var a;const t=this.currentTaskId;this.currentTaskId++,(a=this.worker)==null||a.postMessage({type:"CANCEL",taskId:t}),this.resetStreamState(),(this.status==="transcribing"||this.status==="recording")&&this.setStatus("idle")}async clearCache(){this.worker&&(this.worker.postMessage({type:"CLEAR_CACHE"}),this.isReady=!1,this.initPromise=null)}destroy(){var a;const t=this.currentTaskId;this.currentTaskId++,(a=this.worker)==null||a.postMessage({type:"CANCEL",taskId:t}),this.resetStreamState(),this.recorder&&(this.recorder.cancel(),this.recorder=null),this.worker&&(this.worker.terminate(),this.worker=null),this.isReady=!1,this.initPromise=null,this.setStatus("idle")}resetStreamState(){this.pcmParts=[],this.pcmLength=0,this.streamChunkIndex=0,this.committedText=""}appendPcm(t){!t||t.length===0||(this.pcmParts.push(new Float32Array(t)),this.pcmLength+=t.length)}mergePcm(){const t=new Float32Array(this.pcmLength);let a=0;for(const n of this.pcmParts)t.set(n,a),a+=n.length;return t}emitPartial(t){var a,n;(n=(a=this.options).onPartial)==null||n.call(a,(t||"").trim())}finishStream(t){var n,s;const a=(t??this.committedText).trim();this.setStatus("idle"),(s=(n=this.options).onResult)==null||s.call(n,a)}dispatchFullAudio(){if(!this.worker){this.finishStream();return}if(this.pcmLength<ft){this.finishStream();return}const t=this.mergePcm(),a=t.length>Be*30;this.committedText="",this.worker.postMessage({type:"TRANSCRIBE",data:{taskId:this.currentTaskId,audio:t,language:this.options.language,stream:!0,chunkIndex:this.streamChunkIndex++,isFinal:!0,mode:"append",nativeChunking:a}},[t.buffer])}handleWorkerMessage(t,a,n){var k,E,_,V;const{type:s,data:o,taskId:i,text:l,error:c}=t.data;switch(s){case"READY":this.isReady=!0,this.setStatus("ready","语音引擎就绪"),a==null||a();break;case"PROGRESS":if(o){const S=typeof o.progress=="number"?Math.round(o.progress):0;this.setStatus("downloading",`正在下载语音模型... ${S}%`),(E=(k=this.options).onProgress)==null||E.call(k,{status:o.status||"progress",progress:S,file:o.file,loaded:o.loaded,total:o.total})}break;case"TRANSCRIBING":if(i&&i!==this.currentTaskId)return;this.status!=="recording"&&this.setStatus("transcribing","正在流式转写文字...");break;case"PARTIAL":if(i&&i!==this.currentTaskId)return;this.committedText=l||"",this.emitPartial(this.committedText);break;case"RESULT":if(i&&i!==this.currentTaskId)return;this.committedText=(l||"").trim()||this.committedText,this.emitPartial(this.committedText),this.finishStream(this.committedText);break;case"CACHE_CLEARED":this.setStatus("idle","语音模型缓存已清空");break;case"ERROR":if(i&&i!==this.currentTaskId)return;this.setStatus("error",c||"语音服务异常"),(V=(_=this.options).onError)==null||V.call(_,c||"语音服务异常"),n==null||n(new Error(c));break}}setStatus(t,a){var n,s;this.status=t,(s=(n=this.options).onStatusChange)==null||s.call(n,t,a)}}const kt={class:"panel-header"},wt={class:"header-actions"},bt={class:"header-title"},Ct={class:"action-icons"},St={class:"body-content"},Et={key:0,class:"welcome-content"},vt={class:"subtitle"},Nt={class:"highlight"},Vt={class:"quick-questions"},xt=["onClick"],Tt={key:1,class:"message-content user-content"},Rt={class:"panel-footer"},Bt={key:0,src:qe,alt:"加载中",class:"loading-icon"},At={key:0,class:"voice-progress-banner"},_t={class:"progress-info"},Pt={class:"progress-text"},Ut={key:0,class:"progress-percent"},It={key:0,class:"progress-track"},Lt={class:"recording-main"},Mt={class:"recording-status"},Ft={key:0,class:"recording-time"},Ot={class:"recording-hint"},zt={key:1,class:"volume-waves"},Dt={class:"recording-actions"},$t=["title"],jt={key:0,class:"voice-playback-bar"},Ht=["title"],Wt={class:"playback-play-icon"},qt={key:0,viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},Gt={key:1,viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},Jt={class:"playback-title"},Kt={key:0,class:"playback-time"},Qt={key:1,class:"playback-waves"},Zt={class:"input-box"},Yt={class:"input-actions-box"},Xt=["src"],Pe={__name:"ChatPanel",props:{modelValue:{type:Boolean,default:!1},token:{type:String,default:""},identifier:{type:String,default:""},baseUrl:{type:String,default:""},title:{type:String,default:"数智AI助理"},llmName:{type:String,default:"szjy"},messagePostRender:{type:Function,default:null},extraConfig:{type:Object,default:()=>({})},soundBaseUrl:{type:String,default:"/sounds/"},workerUrl:{type:String,default:""},enableVoiceInput:{type:Boolean,default:!1},enableVoiceUpload:{type:Boolean,default:!1},embedded:{type:Boolean,default:!1}},emits:["update:modelValue","submit"],setup(r,{emit:t}){const{appContext:a}=e.getCurrentInstance(),{$message:n}=a.config.globalProperties,s=r;let o=null;const i=e.ref("idle"),l=e.ref(""),c=e.ref(0),k=e.ref(0),E=e.ref(0);let _=null;const V=e.ref(""),S=e.ref(!1),z=e.ref(0);let v=null;const P=e.ref(""),y=e.ref(""),f=e.computed(()=>i.value==="downloading"),p=e.computed(()=>i.value==="loading"),u=e.computed(()=>i.value==="recording"),d=e.computed(()=>i.value==="transcribing"),w=e.computed(()=>u.value?"正在录音,点击完成后开始识别":P.value?"正在流式转写...":"正在识别语音中..."),b=e.computed(()=>s.enableVoiceInput?"请输入您的问题或点击麦克风语音输入":s.enableVoiceUpload?"请输入您的问题或上传音频识别":"请输入您的问题"),B=(m,h)=>{const T=(m||"").trim(),L=(h||"").trim();return L?T?/[A-Za-z0-9]$/.test(T)&&/[A-Za-z0-9]/.test(L.charAt(0))?`${T} ${L}`:`${T}${L}`:L:T},N=m=>{const h=Math.floor(m/60),T=m%60;return`${h.toString().padStart(2,"0")}:${T.toString().padStart(2,"0")}`},R=()=>(o||(o=new _e({soundBaseUrl:s.soundBaseUrl||"/sounds/",workerUrl:s.workerUrl||void 0,onStatusChange:(m,h)=>{i.value=m,h&&(l.value=h)},onProgress:m=>{typeof m.progress=="number"&&(c.value=m.progress)},onVolumeChange:m=>{k.value=m},onAudioRecorded:m=>{V.value&&URL.revokeObjectURL(V.value),V.value=m,z.value=E.value},onPartial:m=>{P.value=m||"",A.value=B(y.value,m)},onResult:m=>{P.value=m||"",A.value=B(y.value,m),m?n.success("语音识别完成"):n.warning("未能识别出有效语音,请重试"),setTimeout(()=>{P.value="",j.value&&j.value.focus()},100)},onError:m=>{n.error(m||"语音输入服务出错"),U()}})),o),g=()=>{U(),E.value=0,_=setInterval(()=>{E.value+=1},1e3)},U=()=>{_&&(clearInterval(_),_=null)},$=async()=>{if(!s.enableVoiceInput)return;if(u.value){await q();return}S.value&&v&&(v.pause(),S.value=!1);const m=R();try{y.value=A.value,P.value="",g(),await m.startRecording()}catch(h){U(),console.error("启动录音失败:",h)}},q=async()=>{U(),o&&await o.stopAndTranscribe()},D=e.ref(null),O=()=>{s.enableVoiceUpload&&D.value&&(D.value.value="",D.value.click())},X=async m=>{var W;if(!s.enableVoiceUpload)return;const h=m.target,T=(W=h==null?void 0:h.files)==null?void 0:W[0];if(!T)return;S.value&&v&&(v.pause(),S.value=!1);const L=R();try{y.value=A.value,P.value="",n.info(`正在流式识别文件: ${T.name}`),await L.transcribeFile(T)}catch(F){n.error(`文件识别失败: ${F.message||F}`)}},ee=()=>{U(),P.value="",A.value=y.value,o&&o.cancelRecording()},te=()=>{P.value="",A.value=y.value,o&&o.cancelTranscribe(),n.info("已取消本次语音识别")},ae=()=>{if(V.value){if(S.value&&v){v.pause(),S.value=!1;return}v&&(v.pause(),v=null),v=new Audio(V.value),v.onloadedmetadata=()=>{v&&!isNaN(v.duration)&&(z.value=Math.round(v.duration))},v.onended=()=>{S.value=!1},v.onerror=()=>{S.value=!1,n.error("音频试听播放失败")},v.play().then(()=>{S.value=!0}).catch(m=>{console.error("音频播放出错:",m),S.value=!1})}},ue=()=>{v&&(v.pause(),v=null),S.value=!1,V.value&&(URL.revokeObjectURL(V.value),V.value="")};e.onBeforeUnmount(()=>{U(),ue(),o&&(o.destroy(),o=null)});const I=e.computed(()=>Ee.find(m=>m.modelName===s.llmName)??Ee.find(m=>m.modelName==="szjy")),M=t,A=e.ref(""),j=e.ref(null),K=e.ref(!1),G=e.ref([]),yn=e.ref(["什么是AI助理,能做什么?","当前项目的基本情况?","当前项目的进度情况?","当前项目的参建方有哪些?","数智建管平台有哪些功能?能做什么?"]),ne=e.ref([]),se=e.ref(!1),ke=e.ref(null),we=()=>{e.nextTick(()=>{if(ke.value){const m=ke.value,h=m.scrollHeight,T=m.scrollTop,L=m.clientHeight;h-T-L<100?m.scrollTop=h:m.scrollTo({top:h})}})},Q=e.ref(!1),kn=e.computed(()=>Q.value?"/images/ai-stop.png":"/images/ai-send.png"),je=(m,h)=>{console.log("onFailedReader",m,h),se.value=!1;const T=He();T&&T.initializeEnd(),n.error("转换失败,请重试"),Q.value=!1,setTimeout(()=>{j.value&&j.value.focus()})},wn=(m,h)=>{se.value=!1,Q.value=!1,we(),h&&G.value[m]&&(G.value[m].displayText=h),setTimeout(()=>{j.value&&j.value.focus()})},bn=m=>{Q.value=!0},Cn=()=>{Q.value=!1,M("update:modelValue",!1),K.value=!1,G.value=[]},be=e.ref(!1),Sn=()=>{be.value=!be.value},En=m=>{A.value=m,Ce()},He=()=>{for(let m=ne.value.length-1;m>=0;m--)if(ne.value[m])return ne.value[m];return null},Ce=async()=>{if(console.log("stylizingLoading:",se.value),se.value){const W=He();console.log("lastPreviewer:",W),W&&(console.log("abortReader"),W.abortReader());return}if(!A.value.trim()){console.log("no input, return"),j.value.focus();return}G.value.push({type:"user",content:A.value}),Q.value=!0,K.value=!0,M("submit",A.value),we();const m=A.value;A.value="";const h=G.value.length;ne.value[h]&&ne.value[h].initializeStart(),se.value=!0,G.value.push({type:"ai"});const{error:T,reader:L}=await ot(I.value,{text:m,token:s.token,identifier:s.identifier,baseUrl:s.baseUrl,extraConfig:s.extraConfig});if(T){console.log(45455,T),je(h,T);return}L&&(G.value[h].reader=L)};return(m,h)=>{const T=e.resolveComponent("el-icon"),L=e.resolveComponent("el-button"),W=e.resolveComponent("el-input");return e.openBlock(),e.createBlock(e.Transition,{name:"slide"},{default:e.withCtx(()=>[r.modelValue?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["ai-panel",{"drawer-mode":be.value,"embedded-mode":r.embedded}])},[e.createElementVNode("div",kt,[e.createElementVNode("div",wt,[e.createElementVNode("div",bt,e.toDisplayString(r.title),1),e.createElementVNode("div",Ct,[r.embedded?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(T,{key:0,class:"action-icon",onClick:Sn},{default:e.withCtx(()=>[e.createVNode(le,{name:"/images/svg/drawer-layout.svg",color:"#999999"})]),_:1})),e.createVNode(T,{class:"action-icon",onClick:Cn},{default:e.withCtx(()=>[e.createVNode(le,{name:"/images/svg/close.svg",color:"#999999"})]),_:1})])])]),e.createElementVNode("div",St,[K.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:"chat-messages",ref_key:"messageContainerRef",ref:ke},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(G.value,(F,oe)=>(e.openBlock(),e.createElementBlock("div",{key:oe,class:e.normalizeClass(["message-item",F.type==="user"?"user-message":"ai-message"])},[F.type==="ai"?(e.openBlock(),e.createBlock(mt,{key:0,ref_for:!0,ref:J=>ne.value[oe]=J,reader:F.reader,"onUpdate:reader":J=>F.reader=J,model:s.llmName,displayText:F.displayText,scrollToBottomFn:we,messagePostRender:r.messagePostRender,onFailed:J=>je(oe,J),onCompleted:J=>wn(oe,J),onUpdating:()=>bn()},null,8,["reader","onUpdate:reader","model","displayText","messagePostRender","onFailed","onCompleted","onUpdating"])):(e.openBlock(),e.createElementBlock("div",Tt,e.toDisplayString(F.content),1))],2))),128))],512)):(e.openBlock(),e.createElementBlock("div",Et,[h[2]||(h[2]=e.createElementVNode("div",{class:"title"},[e.createElementVNode("img",{src:We,alt:"AI助手",class:"panel-icon"}),e.createElementVNode("h3",{class:"title-text"},"Hi, 您好")],-1)),e.createElementVNode("div",vt,[h[1]||(h[1]=e.createTextVNode(" 我是",-1)),e.createElementVNode("span",Nt,e.toDisplayString(r.title),1)]),e.createElementVNode("div",Vt,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(yn.value,(F,oe)=>(e.openBlock(),e.createElementBlock("div",{key:oe,class:"question-item",onClick:J=>En(F)},[e.createElementVNode("span",null,e.toDisplayString(F),1),e.createVNode(T,null,{default:e.withCtx(()=>[e.createVNode(le,{name:"/images/svg/arrow-right.svg",color:"#999999"})]),_:1})],8,xt))),128))])]))]),e.createElementVNode("div",Rt,[Q.value?(e.openBlock(),e.createElementBlock("img",Bt)):e.createCommentVNode("",!0),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[f.value||p.value?(e.openBlock(),e.createElementBlock("div",At,[e.createElementVNode("div",_t,[h[3]||(h[3]=e.createElementVNode("span",{class:"progress-icon"},"⏳",-1)),e.createElementVNode("span",Pt,e.toDisplayString(l.value),1),c.value>0?(e.openBlock(),e.createElementBlock("span",Ut,e.toDisplayString(c.value)+"%",1)):e.createCommentVNode("",!0)]),c.value>0?(e.openBlock(),e.createElementBlock("div",It,[e.createElementVNode("div",{class:"progress-bar",style:e.normalizeStyle({width:c.value+"%"})},null,4)])):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0)]),_:1}),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[u.value||d.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["voice-recording-panel",{"has-transcript":d.value}])},[e.createElementVNode("div",Lt,[e.createElementVNode("div",Mt,[e.createElementVNode("span",{class:e.normalizeClass(["recording-pulse",{transcribing:d.value}])},null,2),u.value?(e.openBlock(),e.createElementBlock("span",Ft,e.toDisplayString(N(E.value)),1)):e.createCommentVNode("",!0),e.createElementVNode("span",Ot,e.toDisplayString(w.value),1),u.value?(e.openBlock(),e.createElementBlock("div",zt,[e.createElementVNode("span",{class:"wave",style:e.normalizeStyle({height:Math.max(4,Math.min(22,k.value*.3))+"px"})},null,4),e.createElementVNode("span",{class:"wave",style:e.normalizeStyle({height:Math.max(4,Math.min(30,k.value*.5))+"px"})},null,4),e.createElementVNode("span",{class:"wave",style:e.normalizeStyle({height:Math.max(4,Math.min(18,k.value*.25))+"px"})},null,4)])):e.createCommentVNode("",!0)]),e.createElementVNode("div",Dt,[u.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createVNode(L,{size:"small",circle:"",onClick:ee,title:"取消录音",class:"voice-cancel-btn"},{default:e.withCtx(()=>[...h[4]||(h[4]=[e.createElementVNode("svg",{viewBox:"0 0 1024 1024",width:"12",height:"12"},[e.createElementVNode("path",{d:"M512 456.310154L94.247385 38.557538a39.384615 39.384615 0 0 0-55.689847 55.689847L456.310154 512 38.557538 929.752615a39.384615 39.384615 0 0 0 55.689847 55.689847L512 567.689846l417.752615 417.752616c15.163077 15.163077 40.526769 15.163077 55.689847 0s15.163077-40.526769 0-55.689847L567.689846 512l417.752616-417.752615a39.384615 39.384615 0 0 0-55.689847-55.689847L512 456.310154z",fill:"currentColor"})],-1)])]),_:1}),e.createVNode(L,{type:"primary",size:"small",round:"",onClick:q,class:"voice-finish-btn"},{default:e.withCtx(()=>[...h[5]||(h[5]=[e.createTextVNode(" 完成 ",-1)])]),_:1})],64)):d.value?(e.openBlock(),e.createBlock(L,{key:1,size:"small",round:"",onClick:te,class:"voice-cancel-transcribe-btn"},{default:e.withCtx(()=>[...h[6]||(h[6]=[e.createTextVNode(" 取消识别 ",-1)])]),_:1})):e.createCommentVNode("",!0)])]),d.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["live-transcript",{empty:!P.value}]),title:P.value},[P.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(e.toDisplayString(P.value),1),h[7]||(h[7]=e.createElementVNode("span",{class:"caret"},"|",-1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode("正在识别,文字将实时显示...")],64))],10,$t)):e.createCommentVNode("",!0)],2)):e.createCommentVNode("",!0)]),_:1}),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[V.value&&!u.value&&!d.value?(e.openBlock(),e.createElementBlock("div",jt,[e.createElementVNode("div",{class:"playback-main",onClick:ae,title:S.value?"点击暂停":"点击播放录音"},[e.createElementVNode("div",Wt,[S.value?(e.openBlock(),e.createElementBlock("svg",Gt,[...h[9]||(h[9]=[e.createElementVNode("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"},null,-1)])])):(e.openBlock(),e.createElementBlock("svg",qt,[...h[8]||(h[8]=[e.createElementVNode("path",{d:"M8 5v14l11-7z"},null,-1)])]))]),e.createElementVNode("span",Jt,e.toDisplayString(S.value?"正在播放录音...":"点击试听本次录音"),1),z.value>0?(e.openBlock(),e.createElementBlock("span",Kt,e.toDisplayString(N(z.value)),1)):e.createCommentVNode("",!0),S.value?(e.openBlock(),e.createElementBlock("div",Qt,[...h[10]||(h[10]=[e.createElementVNode("span",{class:"wave-bar"},null,-1),e.createElementVNode("span",{class:"wave-bar"},null,-1),e.createElementVNode("span",{class:"wave-bar"},null,-1),e.createElementVNode("span",{class:"wave-bar"},null,-1)])])):e.createCommentVNode("",!0)],8,Ht),e.createElementVNode("div",{class:"playback-close",onClick:ue,title:"清除试听"},[...h[11]||(h[11]=[e.createElementVNode("svg",{viewBox:"0 0 1024 1024",width:"12",height:"12"},[e.createElementVNode("path",{d:"M512 456.310154L94.247385 38.557538a39.384615 39.384615 0 0 0-55.689847 55.689847L456.310154 512 38.557538 929.752615a39.384615 39.384615 0 0 0 55.689847 55.689847L512 567.689846l417.752615 417.752616c15.163077 15.163077 40.526769 15.163077 55.689847 0s15.163077-40.526769 0-55.689847L567.689846 512l417.752616-417.752615a39.384615 39.384615 0 0 0-55.689847-55.689847L512 456.310154z",fill:"currentColor"})],-1)])])])):e.createCommentVNode("",!0)]),_:1}),e.withDirectives(e.createElementVNode("div",Zt,[e.createVNode(W,{modelValue:A.value,"onUpdate:modelValue":h[0]||(h[0]=F=>A.value=F),ref_key:"refInputTextString",ref:j,placeholder:b.value,autofocus:"",onKeyup:e.withKeys(Ce,["enter"])},{append:e.withCtx(()=>[e.createElementVNode("div",Yt,[r.enableVoiceUpload?(e.openBlock(),e.createElementBlock("div",{key:0,class:"voice-upload-btn",onClick:O,title:"上传音频/视频文件识别 (支持 .wav, .mp4, .mp3, .m4a)"},[...h[12]||(h[12]=[e.createElementVNode("svg",{viewBox:"0 0 24 24",width:"17",height:"17",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}),e.createElementVNode("polyline",{points:"17 8 12 3 7 8"}),e.createElementVNode("line",{x1:"12",y1:"3",x2:"12",y2:"15"})],-1)])])):e.createCommentVNode("",!0),r.enableVoiceUpload?(e.openBlock(),e.createElementBlock("input",{key:1,type:"file",ref_key:"refAudioFileInput",ref:D,accept:"audio/*,video/mp4,.wav,.mp4,.mp3,.m4a",style:{display:"none"},onChange:X},null,544)):e.createCommentVNode("",!0),r.enableVoiceInput?(e.openBlock(),e.createElementBlock("div",{key:2,class:e.normalizeClass(["voice-mic-btn",{"loading-anim":f.value||p.value}]),onClick:$,title:"语音输入"},[...h[13]||(h[13]=[e.createElementVNode("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",fill:"currentColor",opacity:"0.2"}),e.createElementVNode("path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"}),e.createElementVNode("path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"}),e.createElementVNode("line",{x1:"12",y1:"19",x2:"12",y2:"22"})],-1)])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"send-icon-box",onClick:Ce},[e.createElementVNode("img",{src:kn.value,alt:"发送",class:"send-icon"},null,8,Xt)])])]),_:1},8,["modelValue","placeholder"])],512),[[e.vShow,!u.value&&!d.value]])])],2)):e.createCommentVNode("",!0)]),_:1})}}};var Ue={exports:{}};(function(r,t){(function(a,n){r.exports=n()})(window,function(){return function(a){var n={};function s(o){if(n[o])return n[o].exports;var i=n[o]={i:o,l:!1,exports:{}};return a[o].call(i.exports,i,i.exports,s),i.l=!0,i.exports}return s.m=a,s.c=n,s.d=function(o,i,l){s.o(o,i)||Object.defineProperty(o,i,{enumerable:!0,get:l})},s.r=function(o){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})},s.t=function(o,i){if(1&i&&(o=s(o)),8&i||4&i&&typeof o=="object"&&o&&o.__esModule)return o;var l=Object.create(null);if(s.r(l),Object.defineProperty(l,"default",{enumerable:!0,value:o}),2&i&&typeof o!="string")for(var c in o)s.d(l,c,(function(k){return o[k]}).bind(null,c));return l},s.n=function(o){var i=o&&o.__esModule?function(){return o.default}:function(){return o};return s.d(i,"a",i),i},s.o=function(o,i){return Object.prototype.hasOwnProperty.call(o,i)},s.p="",s(s.s=0)}([function(a,n,s){function o(y,f,p,u){p.push(y),u.push([].concat(f[y]||[]))}function i(y,f){if(!y)throw new Error("[getMaxDepsChain] dep 参数不能为空");var p=[],u=[],d=[];for(o(y,f,u,d);u.length;){var w=d.pop();if(w&&w.length){var b=w.shift();if(d.push(w),~u.indexOf(b))throw new Error("[getMaxDepsChain][loop] 存在循环依赖,请检查依赖关系; nextName: "+b+", mainStack: "+u);o(b,f,u,d)}else p.push([].concat(u)),u.pop()}return p.reduce(function(B,N){return N.length>B.length?N:B},[])}function l(y){if(!y)throw new Error("[depsParser] 入参不能为空");var f={};y.forEach(function(u){f[u.name]=u.deps||[]});var p=[];return y.forEach(function(u){var d=i(u.name,f).length-1;u.priority=d,p[d]=(p[d]||[]).concat(u)}),p}s.r(n),s.d(n,"loadScript",function(){return V}),s.d(n,"loadScripts",function(){return S}),s.d(n,"dynamicLoadScripts",function(){return z}),s.d(n,"createScriptsLoadIterator",function(){return v}),s.d(n,"loadScriptsQueue",function(){return P}),s.d(n,"getMaxDepsChain",function(){return i}),s.d(n,"depsParser",function(){return l});var c=function(){return(c=Object.assign||function(y){for(var f,p=1,u=arguments.length;p<u;p++)for(var d in f=arguments[p])Object.prototype.hasOwnProperty.call(f,d)&&(y[d]=f[d]);return y}).apply(this,arguments)},k=function(y,f,p,u){return new(p||(p=Promise))(function(d,w){function b(R){try{N(u.next(R))}catch(g){w(g)}}function B(R){try{N(u.throw(R))}catch(g){w(g)}}function N(R){var g;R.done?d(R.value):(g=R.value,g instanceof p?g:new p(function(U){U(g)})).then(b,B)}N((u=u.apply(y,[])).next())})},E=function(y,f){var p,u,d,w,b={label:0,sent:function(){if(1&d[0])throw d[1];return d[1]},trys:[],ops:[]};return w={next:B(0),throw:B(1),return:B(2)},typeof Symbol=="function"&&(w[Symbol.iterator]=function(){return this}),w;function B(N){return function(R){return function(g){if(p)throw new TypeError("Generator is already executing.");for(;b;)try{if(p=1,u&&(d=2&g[0]?u.return:g[0]?u.throw||((d=u.return)&&d.call(u),0):u.next)&&!(d=d.call(u,g[1])).done)return d;switch(u=0,d&&(g=[2&g[0],d.value]),g[0]){case 0:case 1:d=g;break;case 4:return b.label++,{value:g[1],done:!1};case 5:b.label++,u=g[1],g=[0];continue;case 7:g=b.ops.pop(),b.trys.pop();continue;default:if(d=b.trys,!((d=d.length>0&&d[d.length-1])||g[0]!==6&&g[0]!==2)){b=0;continue}if(g[0]===3&&(!d||g[1]>d[0]&&g[1]<d[3])){b.label=g[1];break}if(g[0]===6&&b.label<d[1]){b.label=d[1],d=g;break}if(d&&b.label<d[2]){b.label=d[2],b.ops.push(g);break}d[2]&&b.ops.pop(),b.trys.pop();continue}g=f.call(y,b)}catch(U){g=[6,U],u=0}finally{p=d=0}if(5&g[0])throw g[1];return{value:g[0]?g[1]:void 0,done:!0}}([N,R])}}},_=function(y){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var f,p=y[Symbol.asyncIterator];return p?p.call(y):(y=typeof __values=="function"?__values(y):y[Symbol.iterator](),f={},u("next"),u("throw"),u("return"),f[Symbol.asyncIterator]=function(){return this},f);function u(d){f[d]=y[d]&&function(w){return new Promise(function(b,B){(function(N,R,g,U){Promise.resolve(U).then(function($){N({value:$,done:g})},R)})(b,B,(w=y[d](w)).done,w.value)})}}};function V(y,f){return f===void 0&&(f=!1),new Promise(function(p,u){var d=f?document.head:document.body,w=document.createElement("script");w.type="text/javascript",w.src=y,w.crossOrigin="anonymous",w.onreadystatechange=p,w.onload=p,w.onerror=u,d.appendChild(w)})}var S=function(y,f){return f===void 0&&(f={}),k(void 0,void 0,void 0,function(){var p,u,d,w,b;return E(this,function(B){switch(B.label){case 0:return p=f.baseUrl,u=p===void 0?"":p,d=f.lastLoadResult,w=f.inHead,b=w!==void 0&&w,[4,Promise.all(y.map(function(N){return k(void 0,void 0,void 0,function(){var R,g,U,$,q,D,O,X;return E(this,function(ee){switch(ee.label){case 0:return R=N.name,g=N.path,U=N.deps,(O={})[R]=!0,$=O,(X={})[R]=!1,q=X,window[R]?[2,$]:[3,1];case 1:return D=!0,U&&d&&[].concat(U).forEach(function(te){d[te]!==!1&&(D=!0)}),D?[4,V(g.indexOf("http")===0||g.indexOf("//:")===0?g:u+g,b).then(function(){return $}).catch(function(){return q})]:[3,3];case 2:return[2,ee.sent()];case 3:return[2,q]}})})}))];case 1:return[2,B.sent()]}})})},z=function(y,f){return f===void 0&&(f={}),function(){var p=[].concat(l(y));return{next:function(){if(p.length){var u=p.shift();return S(u,f).then(function(d){return{value:d,done:!1}})}return Promise.resolve({done:!0})}}}},v=function(y,f){var p;return f===void 0&&(f={}),(p={})[Symbol.asyncIterator]=z(y,f),p},P=function(y,f){return f===void 0&&(f={}),k(void 0,void 0,void 0,function(){var p,u,d,w,b,B;return E(this,function(N){switch(N.label){case 0:N.trys.push([0,5,6,11]),p=_(v(y,f)),N.label=1;case 1:return[4,p.next()];case 2:if((u=N.sent()).done)return[3,4];d=u.value,f.lastLoadResult=f.lastLoadResult||{},console.log("current load: ",d),d.forEach(function(R){f.lastLoadResult=c(c({},f.lastLoadResult),R)}),N.label=3;case 3:return[3,1];case 4:return[3,11];case 5:return w=N.sent(),b={error:w},[3,11];case 6:return N.trys.push([6,,9,10]),u&&!u.done&&(B=p.return)?[4,B.call(p)]:[3,8];case 7:N.sent(),N.label=8;case 8:return[3,10];case 9:if(b)throw b.error;return[7];case 10:return[7];case 11:return[2,f.lastLoadResult]}})})}}])})})(Ue);var en=Ue.exports;function Ie(){const r=[{name:"markdownit",path:"markdown-it.min.js"},{name:"hljs",path:"highlight.11.11.1.min.js"}];let t={};en.loadScriptsQueue(r,{baseUrl:"/scripts/ai/",lastLoadResult:t,inHead:!1}).then(a=>{if(console.log("load ai deps: ",a),window.markdownit){const n=window.markdownit();console.log("markdownit: ",n),rt()}})}const tn={key:0,class:"ai-assistant"},nn={name:"AiChat"},Le=e.defineComponent({...nn,props:{token:{type:String,default:""},identifier:{type:String,default:""},baseUrl:{type:String,default:""},title:{type:String,default:"数智AI助理"},llmName:{type:String,default:"szjy"},messagePostRender:{type:Function,default:null},extraConfig:{type:Object,default:()=>({})},soundBaseUrl:{type:String,default:"/sounds/"},workerUrl:{type:String,default:""},enableVoiceInput:{type:Boolean,default:!1},enableVoiceUpload:{type:Boolean,default:!1}},setup(r){const t=e.ref(!1),a=e.ref(!1),n=()=>{t.value=!t.value},s=()=>{a.value=!0,t.value=!1},o=i=>{console.log("用户输入:",i)};return Ie(),(i,l)=>a.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",tn,[e.createVNode(Pe,{modelValue:t.value,"onUpdate:modelValue":l[0]||(l[0]=c=>t.value=c),onSubmit:o,token:r.token,identifier:r.identifier,baseUrl:r.baseUrl,title:r.title,llmName:r.llmName,messagePostRender:r.messagePostRender,extraConfig:r.extraConfig,soundBaseUrl:r.soundBaseUrl,workerUrl:r.workerUrl,enableVoiceInput:r.enableVoiceInput,enableVoiceUpload:r.enableVoiceUpload},null,8,["modelValue","token","identifier","baseUrl","title","llmName","messagePostRender","extraConfig","soundBaseUrl","workerUrl","enableVoiceInput","enableVoiceUpload"]),e.createElementVNode("div",{class:"ai-icon",onClick:n},[e.createElementVNode("div",{class:"close-icon",onClick:e.withModifiers(s,["stop"])},[...l[1]||(l[1]=[e.createElementVNode("svg",{viewBox:"0 0 1024 1024",width:"8",height:"8"},[e.createElementVNode("path",{d:"M512 456.310154L94.247385 38.557538a39.384615 39.384615 0 0 0-55.689847 55.689847L456.310154 512 38.557538 929.752615a39.384615 39.384615 0 0 0 55.689847 55.689847L512 567.689846l417.752615 417.752616c15.163077 15.163077 40.526769 15.163077 55.689847 0s15.163077-40.526769 0-55.689847L567.689846 512l417.752616-417.752615a39.384615 39.384615 0 0 0-55.689847-55.689847L512 456.310154z",fill:"currentColor"})],-1)])]),l[2]||(l[2]=e.createElementVNode("img",{src:Z,alt:"AI助手"},null,-1)),l[3]||(l[3]=e.createElementVNode("span",{class:"ai-icon-text"},"AI助手",-1))])]))}}),on={class:"ai-chat-plain"},rn={name:"AiChatPlain"},Me=e.defineComponent({...rn,props:{token:{type:String,default:""},identifier:{type:String,default:""},baseUrl:{type:String,default:""},title:{type:String,default:"数智AI助理"},llmName:{type:String,default:"szjy"},messagePostRender:{type:Function,default:null},extraConfig:{type:Object,default:()=>({})},soundBaseUrl:{type:String,default:"/sounds/"},workerUrl:{type:String,default:""},enableVoiceInput:{type:Boolean,default:!1},enableVoiceUpload:{type:Boolean,default:!1}},emits:["submit"],setup(r,{emit:t}){const a=t;return Ie(),(n,s)=>(e.openBlock(),e.createElementBlock("div",on,[e.createVNode(Pe,{"model-value":!0,token:r.token,identifier:r.identifier,baseUrl:r.baseUrl,title:r.title,llmName:r.llmName,messagePostRender:r.messagePostRender,extraConfig:r.extraConfig,soundBaseUrl:r.soundBaseUrl,workerUrl:r.workerUrl,enableVoiceInput:r.enableVoiceInput,enableVoiceUpload:r.enableVoiceUpload,embedded:!0,onSubmit:s[0]||(s[0]=o=>a("submit",o))},null,8,["token","identifier","baseUrl","title","llmName","messagePostRender","extraConfig","soundBaseUrl","workerUrl","enableVoiceInput","enableVoiceUpload"])]))}}),Fe=Object.freeze(Object.defineProperty({__proto__:null,SzAiChat:Le,SzAiChatPlain:Me},Symbol.toStringTag,{value:"Module"})),ye=function(r){if(!ye.installed){ye.installed=!0;for(let t in Fe){const a=Reflect.get(Fe,t);r.component(a.name,a)}}},an=(r,t)=>{const a=t?`?${new URLSearchParams(t).toString()}`:"";console.log(`点击了路由链接: ${r}${a}`)},Oe=r=>{const t=r.indexOf("?");if(t===-1)return{routeName:r};const a=r.substring(0,t),n=r.substring(t+1),s={};return new URLSearchParams(n).forEach((i,l)=>{s[l]=i}),{routeName:a,queryParams:Object.keys(s).length>0?s:void 0}},sn={color:"#536fec",fontWeight:"bold",textDecoration:"underline",cursor:"pointer",padding:"0 3px"},ze=r=>{const t=/#router:([^#]+)#/g,a=[];let n=0,s;for(;(s=t.exec(r))!==null;){s.index>n&&a.push({text:r.substring(n,s.index)});const o=s[1],{routeName:i,queryParams:l}=Oe(o);a.push({text:i,routeName:i,queryParams:l}),n=t.lastIndex}return n<r.length&&a.push({text:r.substring(n)}),a},De=(r,t,a={},n)=>{const{onRouteClick:s=an,linkStyle:o={}}=a,i=document.createElement("a");i.href="#",i.textContent=r;const l={...sn,...o};return Object.assign(i.style,l),i.addEventListener("click",c=>{c.preventDefault(),s(t,n)}),i},$e=r=>{const t=/#router:([^#]+)#/g,a=[],n=document.createTreeWalker(r,NodeFilter.SHOW_TEXT,null);let s=n.nextNode();for(;s;){const o=s,i=o.textContent||"";if(t.test(i)){t.lastIndex=0;const l=ze(i);l.length>0&&a.push({node:o,replacements:l})}s=n.nextNode()}return a},ln=(r,t,a={})=>{const n=$e(r);n.forEach(({node:s,replacements:o})=>{var l;const i=document.createDocumentFragment();o.forEach(({text:c,routeName:k,queryParams:E})=>{if(k){const _=De(c,k,a,E);i.appendChild(_)}else i.appendChild(document.createTextNode(c))}),(l=s.parentNode)==null||l.replaceChild(i,s)}),a!=null&&a.nodeCallback&&n.forEach(({node:s,replacements:o})=>{var i;(i=a.nodeCallback)==null||i.call(a,s,o)})},re="szjy-voice-models",ce="szjy-voice-cache-v1";function Y(){return typeof navigator<"u"&&!!navigator.storage&&typeof navigator.storage.getDirectory=="function"}async function de(r=re){if(!Y())return null;try{return await(await navigator.storage.getDirectory()).getDirectoryHandle(r,{create:!0})}catch(t){return console.warn("[OPFS] 获取目录失败,将使用降级缓存:",t),null}}async function cn(r,t,a=re){if(Y())try{const n=await de(a);if(n){const o=await(await n.getFileHandle(r,{create:!0})).createWritable();return await o.write(t),await o.close(),!0}}catch(n){console.warn(`[OPFS] 写入文件 ${r} 失败:`,n)}if(typeof caches<"u")try{const n=await caches.open(ce),s=new Response(t,{headers:{"Content-Type":"application/octet-stream"}});return await n.put(`/${a}/${r}`,s),!0}catch(n){console.warn(`[CacheStorage] 缓存写入 ${r} 失败:`,n)}return!1}async function dn(r,t=re){if(Y())try{const a=await de(t);if(a)return await(await(await a.getFileHandle(r,{create:!1})).getFile()).arrayBuffer()}catch{}if(typeof caches<"u")try{const n=await(await caches.open(ce)).match(`/${t}/${r}`);if(n)return await n.arrayBuffer()}catch{}return null}async function un(r,t=re){if(Y())try{const a=await de(t);if(a)return(await(await a.getFileHandle(r,{create:!1})).getFile()).size>0}catch{}if(typeof caches<"u")try{return!!await(await caches.open(ce)).match(`/${t}/${r}`)}catch{}return!1}async function hn(r=re){let t=!1;if(Y())try{await(await navigator.storage.getDirectory()).removeEntry(r,{recursive:!0}),t=!0,console.log(`[OPFS] 成功清空语音模型缓存目录: ${r}`)}catch(a){a.name==="NotFoundError"?t=!0:console.warn(`[OPFS] 清理目录 ${r} 异常:`,a)}if(typeof caches<"u")try{const a=await caches.keys();for(const n of a)(n.includes("transformers")||n.includes("szjy-voice")||n===ce)&&(await caches.delete(n),t=!0)}catch(a){console.warn("[CacheStorage] 清除缓存异常:",a)}return t}const mn="0.1.12",fn="Sz";function pn({componentPrefix:r=fn,components:t=[]}={}){const a=[];function n(o,i,l){o.component(r+i)||o.component(r+i,l)}function s(o){a.includes(o)||(a.push(o),t.forEach(i=>{const{name:l,alias:c}=i;n(o,l,i),c&&c.forEach(k=>{n(o,k,i)})}))}return{version:mn,componentPrefix:r,install:s}}const gn={install(r){ye(r)}};C.AudioRecorder=xe,C.DEFAULT_WHISPER_WORKER_URL=pe,C.StreamResampler=Ve,C.SzAiChat=Le,C.SzAiChatPlain=Me,C.VoiceInputManager=_e,C.clearVoiceModelCache=hn,C.create=pn,C.createRouteLink=De,C.decodeAudioFile=Re,C.default=gn,C.findRouteTextNodes=$e,C.float32ToWav=fe,C.getFileFromCache=dn,C.getOPFSDirectory=de,C.hasFileInCache=un,C.isOPFSSupported=Y,C.parseRouteMarkerContent=Oe,C.parseRouteMarkers=ze,C.resampleAudioData=Te,C.routeLinkRender=ln,C.saveFileToCache=cn,Object.defineProperties(C,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
1
|
+
(function(y,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(y=typeof globalThis<"u"?globalThis:y||self,e(y["szjy-ai-coms"]={},y.Vue))})(this,function(y,e){"use strict";var ho=Object.defineProperty;var po=(y,e,Z)=>e in y?ho(y,e,{enumerable:!0,configurable:!0,writable:!0,value:Z}):y[e]=Z;var V=(y,e,Z)=>po(y,typeof e!="symbol"?e+"":e,Z);const Z="/images/ai-round.png",mt="/images/ai-sqrt.png",ht="/images/bars-loading.svg";function Ve(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${location.protocol}//${location.host}${t}`}async function pt(t,n,a,r="",s={}){const{projectId:o}=s,i=Ve(r),l=new URL(`${i}/v1/chat/completions`),c=(s==null?void 0:s.authToken)||"app-oLZVFFdYyJX2QK3rdOLWsC2u";s!=null&&s.authToken||console.error("缺少 authToken!现在默认使用内网的 authToken");const u=new Request(l,{method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({model:"dify",stream:!0,inputs:{token:n,projectCode:a,...o?{projectId:o}:{}},messages:[{role:"system",content:"你是一个专业的AI助手,请用中文回答问题。"},{role:"user",content:t}]})});return fetch(u)}async function gt(t,n,a,r="",s={}){const o=new URL("http://localhost:11434/api/chat"),i={};Object.keys(i).forEach(c=>{o.searchParams.append(c,i[c])});const l=new Request(o,{mode:"cors",method:"post",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:"llama3",stream:!0,messages:[{role:"system",content:"全程使用中文回答问题。"},{role:"user",content:t}]})});return fetch(l)}async function yt(t,n,a,r="",s={}){const o=new URL(`${location.origin}/spark/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{o.searchParams.append(c,i[c])});const l=new Request(o,{method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:"generalv4.0Ultra",stream:!0,messages:[{role:"user",content:t}]})});return fetch(l)}async function kt(t,n,a,r="",s={}){const o=new URL(`${location.origin}/siliconflow/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{o.searchParams.append(c,i[c])});const l=new Request(o,{method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:"Qwen/Qwen1.5-110B-Chat",stream:!0,messages:[{role:"user",content:t}]})});return fetch(l)}async function wt(t,n,a,r="",s={}){const o=new URL(`${location.origin}/moonshot/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{o.searchParams.append(c,i[c])});const l=new Request(o,{method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:"moonshot-v1-8k",stream:!0,messages:[{role:"system",content:"你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},{role:"user",content:t}]})});return fetch(l)}async function bt(t,n,a,r="",s={}){const o=new URL(`${location.origin}/dashscope/compatible-mode/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{o.searchParams.append(c,i[c])});const l=new Request(o,{method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:"qwq-32b-preview",stream:!0,messages:[{role:"system",content:"全程使用中文回答问题"},{role:"user",content:t}]})});return fetch(l)}async function St(t,n,a,r="",s={}){const o=Ve(r),i=new URL(`${o}/support/${a}/a`),l={};Object.keys(l).forEach(u=>{i.searchParams.append(u,l[u])});const c=new Request(i,{method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({content:t})});return fetch(c)}const xe=["根据您的问题,我为您整理了以下构件:","","```szjy-ui",JSON.stringify({title:"构件列表",type:"list",gap:12,items:[{type:"button",props:{type:"primary",content:"查看构件1(CHKS-TJ01-02-01-01-01-01)"},action:"postMessage",actionParams:{type:"BIM_SANDBOX",action:"locateComponent",payload:{wbsCode:"CHKS-TJ01-02-01-01-01-01"}}},{type:"button",props:{type:"primary",content:"查看构件2(CHKS-TJ01-02-01-01-04-02)"},action:"postMessage",actionParams:{type:"BIM_SANDBOX",action:"locateComponent",payload:{wbsCode:"CHKS-TJ01-02-01-01-04-02"}}},{type:"button",props:{type:"default",content:"查看构件3(不存在的编码,演示失败反馈)"},action:"postMessage",actionParams:{type:"BIM_SANDBOX",action:"locateComponent",payload:{wbsCode:"CHKS-NOT-EXIST"}}}]},null,2),"```","","点击上方按钮即可在 BIM 沙盘中定位对应构件。"].join(`
|
|
2
|
+
`),Ct=8,Et=80,vt=t=>new Promise(n=>setTimeout(n,t));function Nt(t,n){const a=Math.ceil(t.length/n),r=[];for(let s=0;s<t.length;s+=a)r.push(t.slice(s,s+a));return r.length?r:[""]}async function Ue(t,n,a,r="",s={}){const i=(s&&typeof s.mockResponse=="string"?s.mockResponse.trim():"")||xe,l=new TextEncoder,c=new ReadableStream({async start(u){for(const S of Nt(i,Ct))u.enqueue(l.encode(S)),await vt(Et);u.close()}});return new Response(c,{status:200,headers:{"Content-Type":"text/plain; charset=utf-8"}})}const At=t=>{if(t.startsWith("data:")){const n=t.substring(5).trim();if(n==="[DONE]")return{done:!0};try{return JSON.parse(n)}catch(a){console.error("JSON parsing error:",a)}}return null},he="<think>",ce="</think>",pe=(t,n)=>{const a=Math.max(0,t.length-(n.length-1));for(let r=a;r<t.length;r++)if(n.startsWith(t.slice(r)))return t.length-r;return 0},Tt=t=>{let n="",a="",r=t||"",s=!1;for(;r;){const o=r.indexOf(he),i=r.indexOf(ce);if(o>=0&&(i<0||o<i))a+=r.slice(0,o),r=r.slice(o+he.length),s=!0;else if(i>=0&&(o<0||i<o))n+=r.slice(0,i),r=r.slice(i+ce.length),s=!1;else if(s){const l=pe(r,ce);n+=r.slice(0,r.length-l),r=""}else{const l=Math.max(pe(r,he),pe(r,ce));a+=r.slice(0,r.length-l),r=""}}return{thinking:n.trim(),content:a.trim(),isThinkingStreaming:s}},Be=[{label:"模拟数据模型",modelName:"standard",api:Ue},{label:"Spark 星火大模型",modelName:"spark",api:yt},{label:"Ollama 3 大模型",modelName:"ollama3",api:gt},{label:"SiliconFlow 硅基流动大模型",modelName:"siliconflow",api:kt},{label:"Kimi Moonshot 月之暗面大模型",modelName:"moonshot",api:wt},{label:"通义千问大模型",modelName:"dashscope",api:bt},{label:"数智建管大模型",modelName:"szjy",api:St},{label:"Dify (OpenAI 兼容)",modelName:"dify-openai",api:pt}],_e={standard(t,n){let a="";return t instanceof Uint8Array?a=n.decode(t,{stream:!0}):a=t,{content:a}},spark(t){const n=At(t);if(n.done)return{done:!0};const a=n.choices[0].delta,r=a.reasoning_content||a.reasoning;let s=a.content||"";return r&&(s=`<think>${r}</think>${s}`),{content:s}},siliconflow(t){return this.spark(t)},moonshot(t){return this.spark(t)},dashscope(t){return this.spark(t)},szjy(t){return this.spark(t)},"dify-openai"(t){return this.spark(t)},ollama3(t){return{content:JSON.parse(t).message.content}}},ze=(t,n,a)=>{const r=t.split(a);return r.slice(0,-1).forEach(s=>{s.trim()!==""&&n.enqueue(s)}),r[r.length-1]},Rt=t=>{let n="";return new TransformStream({transform(a,r){if(n+=a,n.trim().startsWith("data:"))n=ze(n,r,t);else try{JSON.parse(n),n=ze(n,r,t)}catch{r.enqueue(a),n=""}},flush(a){n.trim()!==""&&a.enqueue(n)}})};async function Vt(t,n){const a=t.api;return a?new Promise(r=>{a(n.text,n.token,n.identifier,n.baseUrl,n.extraConfig).then(s=>{if(s.body){const o=s.body.pipeThrough(new TextDecoderStream).pipeThrough(Rt(`
|
|
3
|
+
`)).getReader();console.log("reader from response:",o),r({error:0,reader:o})}else r({error:1,reader:null})}).catch(()=>{r({error:1,reader:null})})}):{error:1,reader:null}}const ge=new Map,ye=new Map;function ke(t,n){ge.set(t,n)}function Pe(t,n){ye.set(t,n)}function Me(t){return ge.get(t)}function je(t){return ge.has(t)}function Ie(t){return ye.get(t)}function Le(t){return ye.has(t)}const xt={"&":"&","<":"<",">":">",'"':""","'":"'"};function X(t){return String(t??"").replace(/[&<>"']/g,n=>xt[n])}function $e(t){const a=we(t,{block:t});return a?`<div class="szjy-ui" data-szjy-ui="1">${a}</div>`:""}function we(t,n){if(!t||typeof t!="object"||typeof t.type!="string")return"";const a=Me(t.type);return a?a(t,n):""}function Fe(t){const n=t.action;if(!n||typeof n!="string")return"";if(!Le(n))return` disabled title="未知动作:${X(n)}"`;const a=t.actionParams===void 0?"":encodeURIComponent(JSON.stringify(t.actionParams??null));return` data-szjy-ui-action="${X(n)}" data-szjy-ui-params="${a}"`}function Ut(t){return typeof t=="number"&&Number.isFinite(t)&&t>=0?`${t}px`:typeof t=="string"&&/^\d+(\.\d+)?(px|rem|em|%)?$/.test(t.trim())?/^\d+(\.\d+)?$/.test(t.trim())?`${t.trim()}px`:t.trim():"12px"}function Bt(t,n){const a=typeof t.title=="string"&&t.title?`<div class="szjy-ui-list__title">${X(t.title)}</div>`:"",s=(Array.isArray(t.items)?t.items:[]).map(i=>we(i,n)).filter(Boolean).map(i=>`<div class="szjy-ui-list__item">${i}</div>`).join(""),o=X(Ut(t.gap));return'<div class="szjy-ui-list">'+a+`<div class="szjy-ui-list__items" style="gap:${o}">${s}</div></div>`}ke("list",Bt);const _t=["default","primary","success","warning","danger","info","text"],zt=["small","default","large"];function Pt(t,n){const a=t.props,r=a&&typeof a=="object"?a:{},s=_t.includes(r.type)?r.type:"default",o=zt.includes(r.size)?r.size:"default",i=X(r.content??r.text??"按钮"),l=Fe(t);return`<button type="button" class="${["szjy-ui-btn",`szjy-ui-btn--${s}`,`szjy-ui-btn--${o}`].join(" ")}"${l}><span class="szjy-ui-btn__text">${i}</span><span class="szjy-ui-btn__status" aria-live="polite"></span></button>`}ke("button",Pt);const Mt=15e3,Oe=/未就绪|未加载/,jt="BIM_SANDBOX",It={locateComponent:t=>[t==null?void 0:t.wbsCode],openPDFSearch:()=>[]};let Lt=0;function $t(t,n){let a;if(!t||t==="self")a=[window];else if(t==="parent")a=[window.parent];else if(t==="top")a=[window.top];else if(typeof t=="function")try{a=t(n)}catch(o){console.error("[szjy-ui] 解析 postMessage 目标窗口失败:",o),a=[]}else Array.isArray(t)?a=t:a=[t];const r=[],s=o=>{if(o){if(Array.isArray(o)){o.forEach(s);return}typeof o.postMessage=="function"&&!r.includes(o)&&r.push(o)}};return s(a),r}function Q(t){if(t===window)return`self (${location.origin})`;if(t===window.parent)return"parent";if(t===window.top)return"top";try{return`window (${t.location.href.slice(0,60)})`}catch{return"window (cross-origin)"}}function Ft(t){try{const n=t.$bimSandbox;return n&&typeof n=="object"?n:null}catch{return null}}function Ot(t,n,a){if(n.type!==jt)return{handled:!1};const r=It[n.action];if(!r)return{handled:!1};const s=Ft(t);if(!s||typeof s[n.action]!="function")return{handled:!1};const o=r(n.payload);let i;try{i=s[n.action](...o)}catch(l){return console.error("[szjy-ui] $bimSandbox 方法调用异常,回退 postMessage:",l),{handled:!1}}return a&&console.log("[szjy-ui] $bimSandbox 直调",{method:n.action,args:o,result:i,target:Q(t)}),{handled:!0,result:i}}function De(t,n,a,r,s,o,i){return(()=>{const{handled:c,result:u}=Ot(t,n,i);return c?(u&&u.success?o&&F(a,"success",u.message||"执行成功"):u&&Oe.test(String(u.message||""))&&r>0?(i&&console.warn(`[szjy-ui] $bimSandbox 直调失败(${u.message}),${s}ms 后自动重试,剩余 ${r-1} 次`),o&&F(a,"retrying",`${u.message},${Math.round(s/1e3)}s 后自动重试`),setTimeout(()=>{De(t,n,a,r-1,s,o,i)},s)):o&&F(a,"error",u&&u.message||"执行失败"),!0):!1})()}function Dt(t){const n=Ht(t.config),a=!t.config||t.config.debug!==!1,r=n.feedback!==!1,s=n.retry===!1?{retries:0,delay:2e3}:{retries:2,delay:2e3,...n.retry||{}};if(!t.params||typeof t.params!="object"||Array.isArray(t.params)){console.warn("[szjy-ui] postMessage 动作的 actionParams 必须是对象:",t.params),F(t.triggerEl,"error","参数无效");return}const o={...t.params},i=$t(n.target,o);if(!i.length){console.warn("[szjy-ui] postMessage 无可用目标窗口,target 配置:",n.target),F(t.triggerEl,"error","无目标窗口");return}const l=n.targetOrigin||"*",c=n.transport||"auto";if(c!=="postMessage"){let u=!1;for(const S of i)if(De(S,o,t.triggerEl,s.retries,s.delay,r,a)){u=!0;break}if(u)return;if(c==="global"){console.warn("[szjy-ui] transport=global 但 $bimSandbox 全局方法不可用:",{targets:i.map(Q),message:o}),F(t.triggerEl,"error","全局方法不可用");return}a&&console.log("[szjy-ui] $bimSandbox 不可用,回退 postMessage 通道")}o.requestId===void 0&&(o.requestId=`szjy-ui-${Date.now()}-${++Lt}`),He(i,o,l),a&&console.log("[szjy-ui] postMessage 已发送",{message:o,targets:i.map(Q),targetOrigin:l,feedback:r}),r&&(F(t.triggerEl,"loading","已发送"),qt(o,i,t.triggerEl,l,s,a))}function Ht(t){return t&&t.postMessage||{}}function He(t,n,a){t.forEach(r=>{try{r.postMessage(n,a)}catch(s){console.error("[szjy-ui] postMessage 发送失败:",s)}})}function qt(t,n,a,r,s,o){let i=s.retries;const l=s.delay;let c=null;const u=()=>{window.removeEventListener("message",R),c&&(clearTimeout(c),c=null)},S=()=>{c&&clearTimeout(c),c=setTimeout(()=>{u(),o&&console.warn("[szjy-ui] postMessage 超时未收到回执",{message:t,targets:n.map(Q),targetOrigin:r}),F(a,"none","未收到回执")},Mt)},R=v=>{const h=v.data;!h||typeof h!="object"||t.type!==void 0&&h.type!==t.type||h.success!==void 0&&(t.requestId!==void 0&&h.requestId!==void 0&&String(h.requestId)!==String(t.requestId)||v.source&&!n.includes(v.source)||(o&&console.log("[szjy-ui] postMessage 收到回执",{requestId:h.requestId,success:h.success,message:h.message,data:h.data,from:Q(v.source)}),h.success?(u(),F(a,"success",h.message||"执行成功")):Oe.test(String(h.message||""))&&i>0?(i-=1,o&&console.warn(`[szjy-ui] postMessage 回执失败(${h.message}),${l}ms 后自动重试,剩余 ${i} 次`),F(a,"retrying",`${h.message},${Math.round(l/1e3)}s 后自动重试`),c&&clearTimeout(c),setTimeout(()=>{He(n,t,r),o&&console.log("[szjy-ui] postMessage 重试已发送",{message:t,targets:n.map(Q),targetOrigin:r}),F(a,"loading","已发送"),S()},l)):(u(),F(a,"error",h.message||"执行失败"))))};window.addEventListener("message",R),S()}function F(t,n,a){if(!t||!t.isConnected)return;const r=t.querySelector(":scope > .szjy-ui-btn__status");t.classList.remove("is-loading","is-success","is-error","is-retrying"),n&&n!=="none"&&t.classList.add(`is-${n}`),r&&(r.textContent=a||"")}Pe("postMessage",Dt);const qe="szjy-ui";function We(t){if(!t||typeof t!="string")return null;const n=t.trim();if(!n.startsWith("{"))return null;let a;try{a=JSON.parse(n)}catch{return null}return Wt(a)}function Wt(t){return!t||typeof t!="object"||Array.isArray(t)||typeof t.type!="string"||!je(t.type)||t.items!==void 0&&!Array.isArray(t.items)?null:t}function Ge(t,n={}){if(!t)return()=>{};const a=r=>{var v;const s=r.target,o=s&&typeof s.closest=="function"?s.closest("[data-szjy-ui-action]"):null;if(!o||!t.contains(o))return;const i=o.getAttribute("data-szjy-ui-action")||"",l=Ie(i);if(!l){console.warn(`[szjy-ui] 未注册的动作: ${i}`);return}const c=o.getAttribute("data-szjy-ui-params");let u=null;if(c)try{u=JSON.parse(decodeURIComponent(c))}catch(h){console.error("[szjy-ui] actionParams 解析失败:",h);return}const S=n.getConfig?n.getConfig():null;if(!S||S.debug!==!1){const h=(v=o.querySelector(":scope > .szjy-ui-btn__text"))==null?void 0:v.textContent;console.log("[szjy-ui] 动作触发",{action:i,params:u,text:(h||o.textContent||"").trim().slice(0,40),trigger:o})}const R=n.getInterceptor?n.getInterceptor():null;if(!(R&&R(i,u,o)===!1)){if(n.onAction)try{n.onAction({action:i,params:u,triggerEl:o})}catch(h){console.error("[szjy-ui] onAction 回调执行失败:",h)}l({params:u,config:S,triggerEl:o})}};return t.addEventListener("click",a),()=>{t.removeEventListener("click",a)}}let D=null;function Gt(){return D||(window.markdownit?(D=new window.markdownit({html:!0,linkify:!0,typographer:!0}),D.renderer.rules.fence=(t,n)=>{const a=t[n],r=(a.info||"").trim().split(/\s+/)[0];if(r===qe){const o=We(a.content),i=o?$e(o):"";if(i)return i}let s="";if(r&&window.hljs&&window.hljs.getLanguage(r))try{s=window.hljs.highlight(a.content,{language:r}).value}catch{s=""}return s||(s=D.utils.escapeHtml(a.content)),`<pre class="md-code-block"><code class="hljs${r?" language-"+r:""}">${s}</code></pre>`}):console.log("markdownit is not loaded"),D)}const Jt=(t,n)=>{const a=t.__vccOpts||t;for(const[r,s]of n)a[r]=s;return a},Kt=["src","alt"],ue=Jt({__name:"SvgIcon",props:{name:{type:String,required:!0},size:{type:[Number,String],default:16},color:{type:String,default:""},className:{type:String,default:""},basePath:{type:String,default:"/icons/"}},setup(t){const n=t,a=e.computed(()=>{if(n.name.startsWith("http://")||n.name.startsWith("https://")||n.name.startsWith("/"))return n.name;const o=n.name.endsWith(".svg")?n.name:`${n.name}.svg`;return`${n.basePath}${o}`}),r=e.computed(()=>{const o=typeof n.size=="number"?`${n.size}px`:n.size;return{width:o,height:o,display:"inline-flex",justifyContent:"center",alignItems:"center"}}),s=e.computed(()=>{const o={width:"100%",height:"100%"};return n.color&&(o.filter=`drop-shadow(0 0 0 ${n.color})`),o});return(o,i)=>(e.openBlock(),e.createElementBlock("div",{class:"svg-icon-wrapper",style:e.normalizeStyle(r.value)},[e.createElementVNode("img",{src:a.value,alt:t.name,class:e.normalizeClass(["svg-icon",t.className]),style:e.normalizeStyle(s.value)},null,14,Kt)],4))}},[["__scopeId","data-v-490b11c1"]]),Yt=async t=>{if(navigator.clipboard&&navigator.permissions)await navigator.clipboard.writeText(t);else{const n=document.createElement("textArea");n.value=t,n.style.width=0,n.style.position="fixed",n.style.left="-999px",n.style.top="10px",n.setAttribute("readonly","readonly"),document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}},Zt={class:"thinking-title"},Xt={class:"thinking-toggle-hint"},Qt=["innerHTML"],en=["innerHTML"],tn=10,nn={__name:"Previewer",props:{reader:null,model:"szjy",scrollToBottomFn:null,displayText:"",messagePostRender:{type:Function,default:null},customUi:{type:Object,default:null},uiActionHandler:{type:Function,default:null}},emits:["failed","completed","updating","ui-action"],setup(t,{expose:n,emit:a}){const{appContext:r}=e.getCurrentInstance(),{$message:s}=r.config.globalProperties,o=t,i=e.ref(o.displayText||""),l=e.ref(!0),c=e.ref(!1),u=e.ref(!!o.displayText),S=a,R=e.ref(null);let v=null;e.watch(R,B=>{v&&(v(),v=null),B&&(v=Ge(B,{getConfig:()=>o.customUi,getInterceptor:()=>o.uiActionHandler,onAction:T=>S("ui-action",T)}))});let h=null;const M=e.computed(()=>Tt(i.value)),A=e.computed(()=>M.value.thinking.length>0),_=e.ref(o.displayText?M.value.content.length:0),k=e.computed(()=>M.value.isThinkingStreaming&&!u.value),p=e.ref(!1),w=()=>{p.value=!p.value};let f=null,d=null;const C=e.ref(0);e.watch(()=>M.value.thinking,B=>{!B||C.value>0||(d===null&&(d=f??Date.now()),M.value.content&&E())});const E=()=>{if(C.value>0||!A.value)return;const B=d??f;B&&(C.value=Math.max(1,Math.round((Date.now()-B)/1e3)))},z=e.computed(()=>k.value?"正在思考...":C.value>0?`已深度思考(用时 ${C.value} 秒)`:"思考过程"),N=e.computed(()=>A.value?D?D.render(M.value.thinking):M.value.thinking:""),x=e.computed(()=>M.value.content.slice(0,_.value)),b=e.computed(()=>D?D.render(x.value):x.value),P=()=>{o.reader&&o.reader.cancel(),c.value=!0,$.value=!1,K(),u.value=!0,E(),S("completed",i.value),l.value=!1,h&&(cancelAnimationFrame(h),h=null)},H=e.computed(()=>`${b.value}`),q=e.ref(!1),W=()=>{q.value=!0},K=()=>{q.value=!1},$=e.ref(!1),te=async()=>{if(!o.reader)return;const B=new TextDecoder("utf-8");for(l.value=!0;!c.value;)try{if(!o.reader){$.value=!0;break}const{value:T,done:I}=await o.reader.read();if(!o.reader){$.value=!0;break}if(I){$.value=!0;break}const oe=_e[o.model];if(!oe)break;const O=oe.call(_e,T,B);if(O.done){$.value=!0;break}!f&&O.content&&(f=Date.now()),i.value+=O.content,h===null&&ne()}catch(T){$.value=!0,console.log(3333,T),S("failed",T),P();break}finally{K()}},ie=async()=>{o.scrollToBottomFn&&o.scrollToBottomFn()},me=(B=()=>{},T=()=>{})=>{const I=M.value.content.length;_.value>I&&(_.value=I),_.value<I?(_.value=Math.min(I,_.value+tn),B()):T()},ne=()=>{if(c.value&&h){cancelAnimationFrame(h),h=null,l.value=!1;return}$.value?me(()=>{h=requestAnimationFrame(ne),S("updating",null)},()=>{E(),S("completed",i.value),l.value=!1,u.value=!0,e.nextTick(()=>{if($.value=!1,o.messagePostRender&&R.value)try{o.messagePostRender(R.value,M.value.content)}catch(B){console.error("messagePostRender 执行失败:",B)}}),h=null}):(me(),h=requestAnimationFrame(ne)),ie()};e.watch(()=>o.reader,()=>{o.reader&&te()},{immediate:!0,deep:!0}),e.onUnmounted(()=>{v&&(v(),v=null),P()}),n({abortReader:P,initializeStart:W,initializeEnd:K}),e.computed(()=>q.value?!0:(!o.reader||!l||i.value,!1));const ve=async()=>{try{const B=M.value.content||i.value;await Yt(B),s.success("复制成功")}catch(B){console.error("复制失败:",B),s.error("复制失败")}};return(B,T)=>(e.openBlock(),e.createBlock(e.Transition,{name:"fade"},{default:e.withCtx(()=>[H.value||A.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"refWrapperContent",ref:R,"text-16":"",class:"w-full h-full overflow-y-auto relative","p-24px":""},[A.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["ai-thinking-block",{"is-expanded":p.value||k.value,"is-streaming":k.value}])},[e.createElementVNode("div",{class:"thinking-header",onClick:w},[T[0]||(T[0]=e.createElementVNode("svg",{class:"thinking-arrow",viewBox:"0 0 1024 1024",width:"10",height:"10"},[e.createElementVNode("path",{d:"M704 512 320 256v512z",fill:"currentColor"})],-1)),e.createElementVNode("span",Zt,e.toDisplayString(z.value),1),e.createElementVNode("span",Xt,e.toDisplayString(p.value||k.value?"收起":"展开"),1)]),e.withDirectives(e.createElementVNode("div",{class:"thinking-body",innerHTML:N.value},null,8,Qt),[[e.vShow,p.value||k.value]])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"markdown-wrapper",innerHTML:H.value},null,8,en),u.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:"ai-copy-btn-wrapper",onClick:ve},[e.createVNode(ue,{name:"/images/svg/copy.svg",color:"#666666"}),T[1]||(T[1]=e.createElementVNode("span",{class:"copy-text"},"复制",-1))])):e.createCommentVNode("",!0)],512)):e.createCommentVNode("",!0)]),_:1}))}};class Je{constructor(n,a){V(this,"ratio");V(this,"leftover",new Float32Array(0));V(this,"fracOffset",0);this.ratio=n/a}reset(){this.leftover=new Float32Array(0),this.fracOffset=0}process(n){if(this.ratio===1)return new Float32Array(n);const a=new Float32Array(this.leftover.length+n.length);if(a.set(this.leftover),a.set(n,this.leftover.length),a.length<2)return this.leftover=a,new Float32Array(0);const r=[];let s=this.fracOffset;for(;s<a.length-1;){const i=Math.floor(s),l=s-i,c=a[i],u=a[i+1];r.push(c+l*(u-c)),s+=this.ratio}const o=Math.min(a.length,Math.floor(s));return this.leftover=a.slice(o),this.fracOffset=s-o,Float32Array.from(r)}}class Ke{constructor(n={}){V(this,"targetSampleRate");V(this,"audioContext",null);V(this,"mediaStream",null);V(this,"sourceNode",null);V(this,"processorNode",null);V(this,"muteGain",null);V(this,"resampler",null);V(this,"audioChunks",[]);V(this,"onVolumeChange");V(this,"onAudioChunk");V(this,"_isRecording",!1);this.targetSampleRate=n.sampleRate||16e3,this.onVolumeChange=n.onVolumeChange,this.onAudioChunk=n.onAudioChunk}get isRecording(){return this._isRecording}async start(){if(this._isRecording)return;if(!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia)throw new Error("当前浏览器环境不支持获取麦克风音频,请使用现代浏览器并确保在 HTTPS/localhost 环境下运行。");try{this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:{channelCount:{ideal:1},sampleRate:{ideal:this.targetSampleRate},echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})}catch(r){throw r.name==="NotAllowedError"||r.name==="PermissionDeniedError"?new Error("麦克风权限被拒绝,请在浏览器地址栏允许麦克风访问权限。"):r.name==="NotFoundError"||r.name==="DevicesNotFoundError"?new Error("未检测到可用的麦克风输入设备。"):new Error(`无法启动麦克风: ${r.message||r}`)}const n=window.AudioContext||window.webkitAudioContext;try{this.audioContext=new n({sampleRate:this.targetSampleRate})}catch{this.audioContext=new n}this.audioContext.state==="suspended"&&await this.audioContext.resume(),this.audioChunks=[],this.resampler=this.audioContext.sampleRate===this.targetSampleRate?null:new Je(this.audioContext.sampleRate,this.targetSampleRate),this.sourceNode=this.audioContext.createMediaStreamSource(this.mediaStream);const a=4096;this.processorNode=this.audioContext.createScriptProcessor(a,1,1),this.processorNode.onaudioprocess=r=>{var i;if(!this._isRecording)return;const s=new Float32Array(r.inputBuffer.getChannelData(0));if(this.onVolumeChange){let l=0;for(let S=0;S<s.length;S++)l+=s[S]*s[S];const c=Math.sqrt(l/s.length),u=Math.min(100,Math.round(c*100*5));this.onVolumeChange(u)}const o=this.resampler?this.resampler.process(s):s;o.length&&(this.audioChunks.push(o),(i=this.onAudioChunk)==null||i.call(this,o))},this.muteGain=this.audioContext.createGain(),this.muteGain.gain.value=0,this.sourceNode.connect(this.processorNode),this.processorNode.connect(this.muteGain),this.muteGain.connect(this.audioContext.destination),this._isRecording=!0}async stop(){if(!this._isRecording)return new Float32Array(0);this._isRecording=!1,this.cleanup();const n=this.audioChunks.reduce((s,o)=>s+o.length,0),a=new Float32Array(n);let r=0;for(const s of this.audioChunks)a.set(s,r),r+=s.length;return this.audioChunks=[],a}cancel(){this._isRecording=!1,this.audioChunks=[],this.cleanup()}cleanup(){this.processorNode&&(this.processorNode.disconnect(),this.processorNode.onaudioprocess=null,this.processorNode=null),this.muteGain&&(this.muteGain.disconnect(),this.muteGain=null),this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode=null),this.resampler=null,this.mediaStream&&(this.mediaStream.getTracks().forEach(n=>n.stop()),this.mediaStream=null),this.audioContext&&this.audioContext.state!=="closed"&&(this.audioContext.close().catch(()=>{}),this.audioContext=null)}}function Ye(t,n,a){if(n===a)return new Float32Array(t);const r=n/a,s=Math.round(t.length/r),o=new Float32Array(s);for(let i=0;i<s;i++){const l=i*r,c=Math.floor(l),u=l-c,S=t[c]??0,R=t[c+1]??S;o[i]=S+u*(R-S)}return o}async function Ze(t,n=16e3){const a=await t.arrayBuffer(),r=window.AudioContext||window.webkitAudioContext,s=new r;try{const o=await s.decodeAudioData(a);let i;if(o.numberOfChannels>1){i=new Float32Array(o.length);for(let l=0;l<o.numberOfChannels;l++){const c=o.getChannelData(l);for(let u=0;u<o.length;u++)i[u]+=c[u]/o.numberOfChannels}}else i=o.getChannelData(0);return Ye(i,o.sampleRate,n)}finally{s.state!=="closed"&&await s.close().catch(()=>{})}}function be(t,n=16e3){const a=new ArrayBuffer(44+t.length*2),r=new DataView(a),s=(i,l)=>{for(let c=0;c<l.length;c++)r.setUint8(i+c,l.charCodeAt(c))};s(0,"RIFF"),r.setUint32(4,36+t.length*2,!0),s(8,"WAVE"),s(12,"fmt "),r.setUint32(16,16,!0),r.setUint16(20,1,!0),r.setUint16(22,1,!0),r.setUint32(24,n,!0),r.setUint32(28,n*2,!0),r.setUint16(32,2,!0),r.setUint16(34,16,!0),s(36,"data"),r.setUint32(40,t.length*2,!0);let o=44;for(let i=0;i<t.length;i++,o+=2){const l=Math.max(-1,Math.min(1,t[i]));r.setInt16(o,l<0?l*32768:l*32767,!0)}return new Blob([r],{type:"audio/wav"})}const Xe=16e3,on=Math.round(Xe*.35),Se="/scripts/ai/whisper.worker.js";function rn(){return new Worker(Ce(Se),{type:"module"})}function Ce(t){return/^https?:\/\//i.test(t)?t:typeof location<"u"?new URL(t,location.origin).href:t}function Qe(t){if(!t.ok)return!1;const n=(t.headers.get("content-type")||"").toLowerCase();return!(n.includes("text/html")||n.includes("application/xhtml+xml"))}async function an(t){try{const n=await fetch(t,{method:"HEAD"});if(Qe(n))return!0}catch{}try{const n=await fetch(t,{headers:{Range:"bytes=0-64"}});if(Qe(n))return!0}catch{}return!1}async function sn(t){const n=[];t&&n.push(Ce(t)),n.push(Ce(Se));const a=[...new Set(n.filter(Boolean))];for(const r of a)if(await an(r))return console.log("[VoiceInputManager] 使用语音 Worker:",r),r;return console.warn("[VoiceInputManager] 未探测到可访问的 Worker 脚本,将回退到 Vite 打包注入地址。已尝试:",a.join(" , ")),null}class et{constructor(n={}){V(this,"recorder",null);V(this,"worker",null);V(this,"status","idle");V(this,"options");V(this,"isReady",!1);V(this,"initPromise",null);V(this,"currentTaskId",0);V(this,"pcmParts",[]);V(this,"pcmLength",0);V(this,"streamChunkIndex",0);V(this,"committedText","");this.options={soundBaseUrl:"/sounds/",remoteHost:"https://hf-mirror.com",modelId:"onnx-community/whisper-base",language:"chinese",...n}}get currentStatus(){return this.status}get ready(){return this.isReady}async init(n){if(!this.isReady)return this.initPromise?this.initPromise:(n&&(this.options.soundBaseUrl=n),this.initPromise=new Promise((a,r)=>{this.setStatus("loading","正在准备语音识别引擎..."),(async()=>{var o,i;try{const l=await sn(this.options.workerUrl);this.worker=l?new Worker(l,{type:"module"}):rn(),this.worker.onmessage=c=>{this.handleWorkerMessage(c,a,r)},this.worker.onerror=c=>{var R,v;const S=`语音后台线程异常: ${c.message||c.filename||l||"未知错误"}`;this.initPromise=null,this.setStatus("error",S),(v=(R=this.options).onError)==null||v.call(R,S),r(c)},this.worker.postMessage({type:"INIT",data:{modelId:this.options.modelId,soundBaseUrl:this.options.soundBaseUrl,remoteHost:this.options.remoteHost}})}catch(l){const c=`创建语音 Worker 失败: ${l.message||l}`;this.initPromise=null,this.setStatus("error",c),(i=(o=this.options).onError)==null||i.call(o,c),r(l)}})()}),this.initPromise)}async startRecording(){var n,a,r,s;if(!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia){const o=window.isSecureContext?"当前浏览器环境不支持获取麦克风音频,请使用现代浏览器。":"当前页面不是安全上下文,浏览器禁止调用麦克风。请使用 https:// 或 http://localhost / http://127.0.0.1 访问(通过局域网 IP 的 http 地址无法录音)。";throw this.setStatus("error",o),(a=(n=this.options).onError)==null||a.call(n,o),new Error(o)}this.isReady||await this.init(),this.recorder||(this.recorder=new Ke({onVolumeChange:o=>{var i,l;(l=(i=this.options).onVolumeChange)==null||l.call(i,o)},onAudioChunk:o=>{this.appendPcm(o)}}));try{this.currentTaskId++,this.resetStreamState(),await this.recorder.start(),this.setStatus("recording","正在录音...")}catch(o){throw this.setStatus("error",o.message||"启动录音失败"),(s=(r=this.options).onError)==null||s.call(r,o.message||"启动录音失败"),o}}async stopAndTranscribe(){var n,a,r,s;if(!(!this.recorder||!this.recorder.isRecording))try{await this.recorder.stop();const o=this.mergePcm();if(o.length===0){this.resetStreamState(),this.setStatus("idle");return}this.setStatus("transcribing","正在识别语音...");try{const i=be(o),l=URL.createObjectURL(i);(a=(n=this.options).onAudioRecorded)==null||a.call(n,l,i)}catch(i){console.warn("生成录音回放音频失败:",i)}await this.transcribeAudioData(o)}catch(o){this.setStatus("error",o.message||"音频处理失败"),(s=(r=this.options).onError)==null||s.call(r,o.message||"音频处理失败")}}async transcribeAudioData(n,a){var r,s,o,i;this.isReady||await this.init(),this.setStatus("transcribing","正在流式识别音频...");try{a&&((s=(r=this.options).onAudioRecorded)==null||s.call(r,a,be(n))),this.currentTaskId++,this.resetStreamState(),this.appendPcm(n),this.dispatchFullAudio()}catch(l){this.setStatus("error",l.message||"音频处理失败"),(i=(o=this.options).onError)==null||i.call(o,l.message||"音频处理失败")}}async transcribeFile(n){var a,r;this.isReady||await this.init(),this.setStatus("loading","正在解析音频文件...");try{const s=await Ze(n);if(s.length===0)throw new Error("未能从该文件中提取出有效音频");const o=URL.createObjectURL(n);await this.transcribeAudioData(s,o)}catch(s){this.setStatus("error",s.message||"音频文件解析失败"),(r=(a=this.options).onError)==null||r.call(a,s.message||"音频文件解析失败")}}cancelRecording(){var a;const n=this.currentTaskId;this.currentTaskId++,(a=this.worker)==null||a.postMessage({type:"CANCEL",taskId:n}),this.resetStreamState(),this.recorder&&this.recorder.cancel(),this.setStatus("idle")}cancelTranscribe(){var a;const n=this.currentTaskId;this.currentTaskId++,(a=this.worker)==null||a.postMessage({type:"CANCEL",taskId:n}),this.resetStreamState(),(this.status==="transcribing"||this.status==="recording")&&this.setStatus("idle")}async clearCache(){this.worker&&(this.worker.postMessage({type:"CLEAR_CACHE"}),this.isReady=!1,this.initPromise=null)}destroy(){var a;const n=this.currentTaskId;this.currentTaskId++,(a=this.worker)==null||a.postMessage({type:"CANCEL",taskId:n}),this.resetStreamState(),this.recorder&&(this.recorder.cancel(),this.recorder=null),this.worker&&(this.worker.terminate(),this.worker=null),this.isReady=!1,this.initPromise=null,this.setStatus("idle")}resetStreamState(){this.pcmParts=[],this.pcmLength=0,this.streamChunkIndex=0,this.committedText=""}appendPcm(n){!n||n.length===0||(this.pcmParts.push(new Float32Array(n)),this.pcmLength+=n.length)}mergePcm(){const n=new Float32Array(this.pcmLength);let a=0;for(const r of this.pcmParts)n.set(r,a),a+=r.length;return n}emitPartial(n){var a,r;(r=(a=this.options).onPartial)==null||r.call(a,(n||"").trim())}finishStream(n){var r,s;const a=(n??this.committedText).trim();this.setStatus("idle"),(s=(r=this.options).onResult)==null||s.call(r,a)}dispatchFullAudio(){if(!this.worker){this.finishStream();return}if(this.pcmLength<on){this.finishStream();return}const n=this.mergePcm(),a=n.length>Xe*30;this.committedText="",this.worker.postMessage({type:"TRANSCRIBE",data:{taskId:this.currentTaskId,audio:n,language:this.options.language,stream:!0,chunkIndex:this.streamChunkIndex++,isFinal:!0,mode:"append",nativeChunking:a}},[n.buffer])}handleWorkerMessage(n,a,r){var u,S,R,v;const{type:s,data:o,taskId:i,text:l,error:c}=n.data;switch(s){case"READY":this.isReady=!0,this.setStatus("ready","语音引擎就绪"),a==null||a();break;case"PROGRESS":if(o){const h=typeof o.progress=="number"?Math.round(o.progress):0;this.setStatus("downloading",`正在下载语音模型... ${h}%`),(S=(u=this.options).onProgress)==null||S.call(u,{status:o.status||"progress",progress:h,file:o.file,loaded:o.loaded,total:o.total})}break;case"TRANSCRIBING":if(i&&i!==this.currentTaskId)return;this.status!=="recording"&&this.setStatus("transcribing","正在流式转写文字...");break;case"PARTIAL":if(i&&i!==this.currentTaskId)return;this.committedText=l||"",this.emitPartial(this.committedText);break;case"RESULT":if(i&&i!==this.currentTaskId)return;this.committedText=(l||"").trim()||this.committedText,this.emitPartial(this.committedText),this.finishStream(this.committedText);break;case"CACHE_CLEARED":this.setStatus("idle","语音模型缓存已清空");break;case"ERROR":if(i&&i!==this.currentTaskId)return;this.setStatus("error",c||"语音服务异常"),(v=(R=this.options).onError)==null||v.call(R,c||"语音服务异常"),r==null||r(new Error(c));break}}setStatus(n,a){var r,s;this.status=n,(s=(r=this.options).onStatusChange)==null||s.call(r,n,a)}}const ln={class:"panel-header"},cn={class:"header-actions"},un={class:"header-title"},dn={class:"action-icons"},fn={class:"body-content"},mn={key:0,class:"welcome-content"},hn={class:"subtitle"},pn={class:"highlight"},gn={class:"quick-questions"},yn=["onClick"],kn={key:1,class:"message-content user-content"},wn={class:"panel-footer"},bn={key:0,src:ht,alt:"加载中",class:"loading-icon"},Sn={key:0,class:"voice-progress-banner"},Cn={class:"progress-info"},En={class:"progress-text"},vn={key:0,class:"progress-percent"},Nn={key:0,class:"progress-track"},An={class:"recording-main"},Tn={class:"recording-status"},Rn={key:0,class:"recording-time"},Vn={class:"recording-hint"},xn={key:1,class:"volume-waves"},Un={class:"recording-actions"},Bn=["title"],_n={key:0,class:"voice-playback-bar"},zn=["title"],Pn={class:"playback-play-icon"},Mn={key:0,viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},jn={key:1,viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},In={class:"playback-title"},Ln={key:0,class:"playback-time"},$n={key:1,class:"playback-waves"},Fn={class:"input-box"},On={class:"input-actions-box"},Dn=["src"],tt={__name:"ChatPanel",props:{modelValue:{type:Boolean,default:!1},token:{type:String,default:""},identifier:{type:String,default:""},baseUrl:{type:String,default:""},title:{type:String,default:"数智AI助理"},llmName:{type:String,default:"szjy"},messagePostRender:{type:Function,default:null},extraConfig:{type:Object,default:()=>({})},soundBaseUrl:{type:String,default:"/sounds/"},workerUrl:{type:String,default:""},enableVoiceInput:{type:Boolean,default:!1},enableVoiceUpload:{type:Boolean,default:!1},embedded:{type:Boolean,default:!1},customUi:{type:Object,default:null},uiActionHandler:{type:Function,default:null},mockResponse:{type:String,default:""}},emits:["update:modelValue","submit","ui-action"],setup(t,{emit:n}){const{appContext:a}=e.getCurrentInstance(),{$message:r}=a.config.globalProperties,s=t;let o=null;const i=e.ref("idle"),l=e.ref(""),c=e.ref(0),u=e.ref(0),S=e.ref(0);let R=null;const v=e.ref(""),h=e.ref(!1),M=e.ref(0);let A=null;const _=e.ref(""),k=e.ref(""),p=e.computed(()=>i.value==="downloading"),w=e.computed(()=>i.value==="loading"),f=e.computed(()=>i.value==="recording"),d=e.computed(()=>i.value==="transcribing"),C=e.computed(()=>f.value?"正在录音,点击完成后开始识别":_.value?"正在流式转写...":"正在识别语音中..."),E=e.computed(()=>s.enableVoiceInput?"请输入您的问题或点击麦克风语音输入":s.enableVoiceUpload?"请输入您的问题或上传音频识别":"请输入您的问题"),z=(g,m)=>{const U=(g||"").trim(),j=(m||"").trim();return j?U?/[A-Za-z0-9]$/.test(U)&&/[A-Za-z0-9]/.test(j.charAt(0))?`${U} ${j}`:`${U}${j}`:j:U},N=g=>{const m=Math.floor(g/60),U=g%60;return`${m.toString().padStart(2,"0")}:${U.toString().padStart(2,"0")}`},x=()=>(o||(o=new et({soundBaseUrl:s.soundBaseUrl||"/sounds/",workerUrl:s.workerUrl||void 0,onStatusChange:(g,m)=>{i.value=g,m&&(l.value=m)},onProgress:g=>{typeof g.progress=="number"&&(c.value=g.progress)},onVolumeChange:g=>{u.value=g},onAudioRecorded:g=>{v.value&&URL.revokeObjectURL(v.value),v.value=g,M.value=S.value},onPartial:g=>{_.value=g||"",T.value=z(k.value,g)},onResult:g=>{_.value=g||"",T.value=z(k.value,g),g?r.success("语音识别完成"):r.warning("未能识别出有效语音,请重试"),setTimeout(()=>{_.value="",I.value&&I.value.focus()},100)},onError:g=>{r.error(g||"语音输入服务出错"),P()}})),o),b=()=>{P(),S.value=0,R=setInterval(()=>{S.value+=1},1e3)},P=()=>{R&&(clearInterval(R),R=null)},H=async()=>{if(!s.enableVoiceInput)return;if(f.value){await q();return}h.value&&A&&(A.pause(),h.value=!1);const g=x();try{k.value=T.value,_.value="",b(),await g.startRecording()}catch(m){P(),console.error("启动录音失败:",m)}},q=async()=>{P(),o&&await o.stopAndTranscribe()},W=e.ref(null),K=()=>{s.enableVoiceUpload&&W.value&&(W.value.value="",W.value.click())},$=async g=>{var J;if(!s.enableVoiceUpload)return;const m=g.target,U=(J=m==null?void 0:m.files)==null?void 0:J[0];if(!U)return;h.value&&A&&(A.pause(),h.value=!1);const j=x();try{k.value=T.value,_.value="",r.info(`正在流式识别文件: ${U.name}`),await j.transcribeFile(U)}catch(L){r.error(`文件识别失败: ${L.message||L}`)}},te=()=>{P(),_.value="",T.value=k.value,o&&o.cancelRecording()},ie=()=>{_.value="",T.value=k.value,o&&o.cancelTranscribe(),r.info("已取消本次语音识别")},me=()=>{if(v.value){if(h.value&&A){A.pause(),h.value=!1;return}A&&(A.pause(),A=null),A=new Audio(v.value),A.onloadedmetadata=()=>{A&&!isNaN(A.duration)&&(M.value=Math.round(A.duration))},A.onended=()=>{h.value=!1},A.onerror=()=>{h.value=!1,r.error("音频试听播放失败")},A.play().then(()=>{h.value=!0}).catch(g=>{console.error("音频播放出错:",g),h.value=!1})}},ne=()=>{A&&(A.pause(),A=null),h.value=!1,v.value&&(URL.revokeObjectURL(v.value),v.value="")};e.onBeforeUnmount(()=>{P(),ne(),o&&(o.destroy(),o=null)});const ve=e.computed(()=>Be.find(g=>g.modelName===s.llmName)??Be.find(g=>g.modelName==="szjy")),B=n,T=e.ref(""),I=e.ref(null),oe=e.ref(!1),O=e.ref([]),so=e.ref(["什么是AI助理,能做什么?","当前项目的基本情况?","当前项目的进度情况?","当前项目的参建方有哪些?","数智建管平台有哪些功能?能做什么?"]),re=e.ref([]),le=e.ref(!1),Ne=e.ref(null),Ae=()=>{e.nextTick(()=>{if(Ne.value){const g=Ne.value,m=g.scrollHeight,U=g.scrollTop,j=g.clientHeight;m-U-j<100?g.scrollTop=m:g.scrollTo({top:m})}})},Y=e.ref(!1),io=e.computed(()=>Y.value?"/images/ai-stop.png":"/images/ai-send.png"),dt=(g,m)=>{console.log("onFailedReader",g,m),le.value=!1;const U=ft();U&&U.initializeEnd(),r.error("转换失败,请重试"),Y.value=!1,setTimeout(()=>{I.value&&I.value.focus()})},lo=(g,m)=>{le.value=!1,Y.value=!1,Ae(),m&&O.value[g]&&(O.value[g].displayText=m),setTimeout(()=>{I.value&&I.value.focus()})},co=g=>{Y.value=!0},uo=()=>{Y.value=!1,B("update:modelValue",!1),oe.value=!1,O.value=[]},Te=e.ref(!1),fo=()=>{Te.value=!Te.value},mo=g=>{T.value=g,Re()},ft=()=>{for(let g=re.value.length-1;g>=0;g--)if(re.value[g])return re.value[g];return null},Re=async()=>{if(console.log("stylizingLoading:",le.value),le.value){const J=ft();console.log("lastPreviewer:",J),J&&(console.log("abortReader"),J.abortReader());return}if(!T.value.trim()){console.log("no input, return"),I.value.focus();return}O.value.push({type:"user",content:T.value}),Y.value=!0,oe.value=!0,B("submit",T.value),Ae();const g=T.value;T.value="";const m=O.value.length;re.value[m]&&re.value[m].initializeStart(),le.value=!0,O.value.push({type:"ai"});const{error:U,reader:j}=await Vt(ve.value,{text:g,token:s.token,identifier:s.identifier,baseUrl:s.baseUrl,extraConfig:s.mockResponse?Object.assign({},s.extraConfig,{mockResponse:s.mockResponse}):s.extraConfig});if(U){console.log(45455,U),dt(m,U);return}j&&(O.value[m].reader=j)};return(g,m)=>{const U=e.resolveComponent("el-icon"),j=e.resolveComponent("el-button"),J=e.resolveComponent("el-input");return e.openBlock(),e.createBlock(e.Transition,{name:"slide"},{default:e.withCtx(()=>[t.modelValue?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["ai-panel",{"drawer-mode":Te.value,"embedded-mode":t.embedded}])},[e.createElementVNode("div",ln,[e.createElementVNode("div",cn,[e.createElementVNode("div",un,e.toDisplayString(t.title),1),e.createElementVNode("div",dn,[t.embedded?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(U,{key:0,class:"action-icon",onClick:fo},{default:e.withCtx(()=>[e.createVNode(ue,{name:"/images/svg/drawer-layout.svg",color:"#999999"})]),_:1})),e.createVNode(U,{class:"action-icon",onClick:uo},{default:e.withCtx(()=>[e.createVNode(ue,{name:"/images/svg/close.svg",color:"#999999"})]),_:1})])])]),e.createElementVNode("div",fn,[oe.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:"chat-messages",ref_key:"messageContainerRef",ref:Ne},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(O.value,(L,ae)=>(e.openBlock(),e.createElementBlock("div",{key:ae,class:e.normalizeClass(["message-item",L.type==="user"?"user-message":"ai-message"])},[L.type==="ai"?(e.openBlock(),e.createBlock(nn,{key:0,ref_for:!0,ref:G=>re.value[ae]=G,reader:L.reader,"onUpdate:reader":G=>L.reader=G,model:s.llmName,displayText:L.displayText,scrollToBottomFn:Ae,messagePostRender:t.messagePostRender,customUi:t.customUi,uiActionHandler:t.uiActionHandler,onFailed:G=>dt(ae,G),onCompleted:G=>lo(ae,G),onUpdating:()=>co(),onUiAction:m[0]||(m[0]=G=>B("ui-action",G))},null,8,["reader","onUpdate:reader","model","displayText","messagePostRender","customUi","uiActionHandler","onFailed","onCompleted","onUpdating"])):(e.openBlock(),e.createElementBlock("div",kn,e.toDisplayString(L.content),1))],2))),128))],512)):(e.openBlock(),e.createElementBlock("div",mn,[m[3]||(m[3]=e.createElementVNode("div",{class:"title"},[e.createElementVNode("img",{src:mt,alt:"AI助手",class:"panel-icon"}),e.createElementVNode("h3",{class:"title-text"},"Hi, 您好")],-1)),e.createElementVNode("div",hn,[m[2]||(m[2]=e.createTextVNode(" 我是",-1)),e.createElementVNode("span",pn,e.toDisplayString(t.title),1)]),e.createElementVNode("div",gn,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(so.value,(L,ae)=>(e.openBlock(),e.createElementBlock("div",{key:ae,class:"question-item",onClick:G=>mo(L)},[e.createElementVNode("span",null,e.toDisplayString(L),1),e.createVNode(U,null,{default:e.withCtx(()=>[e.createVNode(ue,{name:"/images/svg/arrow-right.svg",color:"#999999"})]),_:1})],8,yn))),128))])]))]),e.createElementVNode("div",wn,[Y.value?(e.openBlock(),e.createElementBlock("img",bn)):e.createCommentVNode("",!0),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[p.value||w.value?(e.openBlock(),e.createElementBlock("div",Sn,[e.createElementVNode("div",Cn,[m[4]||(m[4]=e.createElementVNode("span",{class:"progress-icon"},"⏳",-1)),e.createElementVNode("span",En,e.toDisplayString(l.value),1),c.value>0?(e.openBlock(),e.createElementBlock("span",vn,e.toDisplayString(c.value)+"%",1)):e.createCommentVNode("",!0)]),c.value>0?(e.openBlock(),e.createElementBlock("div",Nn,[e.createElementVNode("div",{class:"progress-bar",style:e.normalizeStyle({width:c.value+"%"})},null,4)])):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0)]),_:1}),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[f.value||d.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["voice-recording-panel",{"has-transcript":d.value}])},[e.createElementVNode("div",An,[e.createElementVNode("div",Tn,[e.createElementVNode("span",{class:e.normalizeClass(["recording-pulse",{transcribing:d.value}])},null,2),f.value?(e.openBlock(),e.createElementBlock("span",Rn,e.toDisplayString(N(S.value)),1)):e.createCommentVNode("",!0),e.createElementVNode("span",Vn,e.toDisplayString(C.value),1),f.value?(e.openBlock(),e.createElementBlock("div",xn,[e.createElementVNode("span",{class:"wave",style:e.normalizeStyle({height:Math.max(4,Math.min(22,u.value*.3))+"px"})},null,4),e.createElementVNode("span",{class:"wave",style:e.normalizeStyle({height:Math.max(4,Math.min(30,u.value*.5))+"px"})},null,4),e.createElementVNode("span",{class:"wave",style:e.normalizeStyle({height:Math.max(4,Math.min(18,u.value*.25))+"px"})},null,4)])):e.createCommentVNode("",!0)]),e.createElementVNode("div",Un,[f.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createVNode(j,{size:"small",circle:"",onClick:te,title:"取消录音",class:"voice-cancel-btn"},{default:e.withCtx(()=>[...m[5]||(m[5]=[e.createElementVNode("svg",{viewBox:"0 0 1024 1024",width:"12",height:"12"},[e.createElementVNode("path",{d:"M512 456.310154L94.247385 38.557538a39.384615 39.384615 0 0 0-55.689847 55.689847L456.310154 512 38.557538 929.752615a39.384615 39.384615 0 0 0 55.689847 55.689847L512 567.689846l417.752615 417.752616c15.163077 15.163077 40.526769 15.163077 55.689847 0s15.163077-40.526769 0-55.689847L567.689846 512l417.752616-417.752615a39.384615 39.384615 0 0 0-55.689847-55.689847L512 456.310154z",fill:"currentColor"})],-1)])]),_:1}),e.createVNode(j,{type:"primary",size:"small",round:"",onClick:q,class:"voice-finish-btn"},{default:e.withCtx(()=>[...m[6]||(m[6]=[e.createTextVNode(" 完成 ",-1)])]),_:1})],64)):d.value?(e.openBlock(),e.createBlock(j,{key:1,size:"small",round:"",onClick:ie,class:"voice-cancel-transcribe-btn"},{default:e.withCtx(()=>[...m[7]||(m[7]=[e.createTextVNode(" 取消识别 ",-1)])]),_:1})):e.createCommentVNode("",!0)])]),d.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["live-transcript",{empty:!_.value}]),title:_.value},[_.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(e.toDisplayString(_.value),1),m[8]||(m[8]=e.createElementVNode("span",{class:"caret"},"|",-1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode("正在识别,文字将实时显示...")],64))],10,Bn)):e.createCommentVNode("",!0)],2)):e.createCommentVNode("",!0)]),_:1}),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[v.value&&!f.value&&!d.value?(e.openBlock(),e.createElementBlock("div",_n,[e.createElementVNode("div",{class:"playback-main",onClick:me,title:h.value?"点击暂停":"点击播放录音"},[e.createElementVNode("div",Pn,[h.value?(e.openBlock(),e.createElementBlock("svg",jn,[...m[10]||(m[10]=[e.createElementVNode("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"},null,-1)])])):(e.openBlock(),e.createElementBlock("svg",Mn,[...m[9]||(m[9]=[e.createElementVNode("path",{d:"M8 5v14l11-7z"},null,-1)])]))]),e.createElementVNode("span",In,e.toDisplayString(h.value?"正在播放录音...":"点击试听本次录音"),1),M.value>0?(e.openBlock(),e.createElementBlock("span",Ln,e.toDisplayString(N(M.value)),1)):e.createCommentVNode("",!0),h.value?(e.openBlock(),e.createElementBlock("div",$n,[...m[11]||(m[11]=[e.createElementVNode("span",{class:"wave-bar"},null,-1),e.createElementVNode("span",{class:"wave-bar"},null,-1),e.createElementVNode("span",{class:"wave-bar"},null,-1),e.createElementVNode("span",{class:"wave-bar"},null,-1)])])):e.createCommentVNode("",!0)],8,zn),e.createElementVNode("div",{class:"playback-close",onClick:ne,title:"清除试听"},[...m[12]||(m[12]=[e.createElementVNode("svg",{viewBox:"0 0 1024 1024",width:"12",height:"12"},[e.createElementVNode("path",{d:"M512 456.310154L94.247385 38.557538a39.384615 39.384615 0 0 0-55.689847 55.689847L456.310154 512 38.557538 929.752615a39.384615 39.384615 0 0 0 55.689847 55.689847L512 567.689846l417.752615 417.752616c15.163077 15.163077 40.526769 15.163077 55.689847 0s15.163077-40.526769 0-55.689847L567.689846 512l417.752616-417.752615a39.384615 39.384615 0 0 0-55.689847-55.689847L512 456.310154z",fill:"currentColor"})],-1)])])])):e.createCommentVNode("",!0)]),_:1}),e.withDirectives(e.createElementVNode("div",Fn,[e.createVNode(J,{modelValue:T.value,"onUpdate:modelValue":m[1]||(m[1]=L=>T.value=L),ref_key:"refInputTextString",ref:I,placeholder:E.value,autofocus:"",onKeyup:e.withKeys(Re,["enter"])},{append:e.withCtx(()=>[e.createElementVNode("div",On,[t.enableVoiceUpload?(e.openBlock(),e.createElementBlock("div",{key:0,class:"voice-upload-btn",onClick:K,title:"上传音频/视频文件识别 (支持 .wav, .mp4, .mp3, .m4a)"},[...m[13]||(m[13]=[e.createElementVNode("svg",{viewBox:"0 0 24 24",width:"17",height:"17",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}),e.createElementVNode("polyline",{points:"17 8 12 3 7 8"}),e.createElementVNode("line",{x1:"12",y1:"3",x2:"12",y2:"15"})],-1)])])):e.createCommentVNode("",!0),t.enableVoiceUpload?(e.openBlock(),e.createElementBlock("input",{key:1,type:"file",ref_key:"refAudioFileInput",ref:W,accept:"audio/*,video/mp4,.wav,.mp4,.mp3,.m4a",style:{display:"none"},onChange:$},null,544)):e.createCommentVNode("",!0),t.enableVoiceInput?(e.openBlock(),e.createElementBlock("div",{key:2,class:e.normalizeClass(["voice-mic-btn",{"loading-anim":p.value||w.value}]),onClick:H,title:"语音输入"},[...m[14]||(m[14]=[e.createElementVNode("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",fill:"currentColor",opacity:"0.2"}),e.createElementVNode("path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"}),e.createElementVNode("path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"}),e.createElementVNode("line",{x1:"12",y1:"19",x2:"12",y2:"22"})],-1)])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"send-icon-box",onClick:Re},[e.createElementVNode("img",{src:io.value,alt:"发送",class:"send-icon"},null,8,Dn)])])]),_:1},8,["modelValue","placeholder"])],512),[[e.vShow,!f.value&&!d.value]])])],2)):e.createCommentVNode("",!0)]),_:1})}}};var nt={exports:{}};(function(t,n){(function(a,r){t.exports=r()})(window,function(){return function(a){var r={};function s(o){if(r[o])return r[o].exports;var i=r[o]={i:o,l:!1,exports:{}};return a[o].call(i.exports,i,i.exports,s),i.l=!0,i.exports}return s.m=a,s.c=r,s.d=function(o,i,l){s.o(o,i)||Object.defineProperty(o,i,{enumerable:!0,get:l})},s.r=function(o){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})},s.t=function(o,i){if(1&i&&(o=s(o)),8&i||4&i&&typeof o=="object"&&o&&o.__esModule)return o;var l=Object.create(null);if(s.r(l),Object.defineProperty(l,"default",{enumerable:!0,value:o}),2&i&&typeof o!="string")for(var c in o)s.d(l,c,(function(u){return o[u]}).bind(null,c));return l},s.n=function(o){var i=o&&o.__esModule?function(){return o.default}:function(){return o};return s.d(i,"a",i),i},s.o=function(o,i){return Object.prototype.hasOwnProperty.call(o,i)},s.p="",s(s.s=0)}([function(a,r,s){function o(k,p,w,f){w.push(k),f.push([].concat(p[k]||[]))}function i(k,p){if(!k)throw new Error("[getMaxDepsChain] dep 参数不能为空");var w=[],f=[],d=[];for(o(k,p,f,d);f.length;){var C=d.pop();if(C&&C.length){var E=C.shift();if(d.push(C),~f.indexOf(E))throw new Error("[getMaxDepsChain][loop] 存在循环依赖,请检查依赖关系; nextName: "+E+", mainStack: "+f);o(E,p,f,d)}else w.push([].concat(f)),f.pop()}return w.reduce(function(z,N){return N.length>z.length?N:z},[])}function l(k){if(!k)throw new Error("[depsParser] 入参不能为空");var p={};k.forEach(function(f){p[f.name]=f.deps||[]});var w=[];return k.forEach(function(f){var d=i(f.name,p).length-1;f.priority=d,w[d]=(w[d]||[]).concat(f)}),w}s.r(r),s.d(r,"loadScript",function(){return v}),s.d(r,"loadScripts",function(){return h}),s.d(r,"dynamicLoadScripts",function(){return M}),s.d(r,"createScriptsLoadIterator",function(){return A}),s.d(r,"loadScriptsQueue",function(){return _}),s.d(r,"getMaxDepsChain",function(){return i}),s.d(r,"depsParser",function(){return l});var c=function(){return(c=Object.assign||function(k){for(var p,w=1,f=arguments.length;w<f;w++)for(var d in p=arguments[w])Object.prototype.hasOwnProperty.call(p,d)&&(k[d]=p[d]);return k}).apply(this,arguments)},u=function(k,p,w,f){return new(w||(w=Promise))(function(d,C){function E(x){try{N(f.next(x))}catch(b){C(b)}}function z(x){try{N(f.throw(x))}catch(b){C(b)}}function N(x){var b;x.done?d(x.value):(b=x.value,b instanceof w?b:new w(function(P){P(b)})).then(E,z)}N((f=f.apply(k,[])).next())})},S=function(k,p){var w,f,d,C,E={label:0,sent:function(){if(1&d[0])throw d[1];return d[1]},trys:[],ops:[]};return C={next:z(0),throw:z(1),return:z(2)},typeof Symbol=="function"&&(C[Symbol.iterator]=function(){return this}),C;function z(N){return function(x){return function(b){if(w)throw new TypeError("Generator is already executing.");for(;E;)try{if(w=1,f&&(d=2&b[0]?f.return:b[0]?f.throw||((d=f.return)&&d.call(f),0):f.next)&&!(d=d.call(f,b[1])).done)return d;switch(f=0,d&&(b=[2&b[0],d.value]),b[0]){case 0:case 1:d=b;break;case 4:return E.label++,{value:b[1],done:!1};case 5:E.label++,f=b[1],b=[0];continue;case 7:b=E.ops.pop(),E.trys.pop();continue;default:if(d=E.trys,!((d=d.length>0&&d[d.length-1])||b[0]!==6&&b[0]!==2)){E=0;continue}if(b[0]===3&&(!d||b[1]>d[0]&&b[1]<d[3])){E.label=b[1];break}if(b[0]===6&&E.label<d[1]){E.label=d[1],d=b;break}if(d&&E.label<d[2]){E.label=d[2],E.ops.push(b);break}d[2]&&E.ops.pop(),E.trys.pop();continue}b=p.call(k,E)}catch(P){b=[6,P],f=0}finally{w=d=0}if(5&b[0])throw b[1];return{value:b[0]?b[1]:void 0,done:!0}}([N,x])}}},R=function(k){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var p,w=k[Symbol.asyncIterator];return w?w.call(k):(k=typeof __values=="function"?__values(k):k[Symbol.iterator](),p={},f("next"),f("throw"),f("return"),p[Symbol.asyncIterator]=function(){return this},p);function f(d){p[d]=k[d]&&function(C){return new Promise(function(E,z){(function(N,x,b,P){Promise.resolve(P).then(function(H){N({value:H,done:b})},x)})(E,z,(C=k[d](C)).done,C.value)})}}};function v(k,p){return p===void 0&&(p=!1),new Promise(function(w,f){var d=p?document.head:document.body,C=document.createElement("script");C.type="text/javascript",C.src=k,C.crossOrigin="anonymous",C.onreadystatechange=w,C.onload=w,C.onerror=f,d.appendChild(C)})}var h=function(k,p){return p===void 0&&(p={}),u(void 0,void 0,void 0,function(){var w,f,d,C,E;return S(this,function(z){switch(z.label){case 0:return w=p.baseUrl,f=w===void 0?"":w,d=p.lastLoadResult,C=p.inHead,E=C!==void 0&&C,[4,Promise.all(k.map(function(N){return u(void 0,void 0,void 0,function(){var x,b,P,H,q,W,K,$;return S(this,function(te){switch(te.label){case 0:return x=N.name,b=N.path,P=N.deps,(K={})[x]=!0,H=K,($={})[x]=!1,q=$,window[x]?[2,H]:[3,1];case 1:return W=!0,P&&d&&[].concat(P).forEach(function(ie){d[ie]!==!1&&(W=!0)}),W?[4,v(b.indexOf("http")===0||b.indexOf("//:")===0?b:f+b,E).then(function(){return H}).catch(function(){return q})]:[3,3];case 2:return[2,te.sent()];case 3:return[2,q]}})})}))];case 1:return[2,z.sent()]}})})},M=function(k,p){return p===void 0&&(p={}),function(){var w=[].concat(l(k));return{next:function(){if(w.length){var f=w.shift();return h(f,p).then(function(d){return{value:d,done:!1}})}return Promise.resolve({done:!0})}}}},A=function(k,p){var w;return p===void 0&&(p={}),(w={})[Symbol.asyncIterator]=M(k,p),w},_=function(k,p){return p===void 0&&(p={}),u(void 0,void 0,void 0,function(){var w,f,d,C,E,z;return S(this,function(N){switch(N.label){case 0:N.trys.push([0,5,6,11]),w=R(A(k,p)),N.label=1;case 1:return[4,w.next()];case 2:if((f=N.sent()).done)return[3,4];d=f.value,p.lastLoadResult=p.lastLoadResult||{},console.log("current load: ",d),d.forEach(function(x){p.lastLoadResult=c(c({},p.lastLoadResult),x)}),N.label=3;case 3:return[3,1];case 4:return[3,11];case 5:return C=N.sent(),E={error:C},[3,11];case 6:return N.trys.push([6,,9,10]),f&&!f.done&&(z=w.return)?[4,z.call(w)]:[3,8];case 7:N.sent(),N.label=8;case 8:return[3,10];case 9:if(E)throw E.error;return[7];case 10:return[7];case 11:return[2,p.lastLoadResult]}})})}}])})})(nt);var Hn=nt.exports;function ot(){const t=[{name:"markdownit",path:"markdown-it.min.js"},{name:"hljs",path:"highlight.11.11.1.min.js"}];let n={};Hn.loadScriptsQueue(t,{baseUrl:"/scripts/ai/",lastLoadResult:n,inHead:!1}).then(a=>{if(console.log("load ai deps: ",a),window.markdownit){const r=window.markdownit();console.log("markdownit: ",r),Gt()}})}const qn={key:0,class:"ai-assistant"},Wn={name:"AiChat"},rt=e.defineComponent({...Wn,props:{token:{type:String,default:""},identifier:{type:String,default:""},baseUrl:{type:String,default:""},title:{type:String,default:"数智AI助理"},llmName:{type:String,default:"szjy"},messagePostRender:{type:Function,default:null},extraConfig:{type:Object,default:()=>({})},soundBaseUrl:{type:String,default:"/sounds/"},workerUrl:{type:String,default:""},enableVoiceInput:{type:Boolean,default:!1},enableVoiceUpload:{type:Boolean,default:!1},customUi:{type:Object,default:null},uiActionHandler:{type:Function,default:null},mockResponse:{type:String,default:""}},emits:["ui-action"],setup(t,{emit:n}){const a=e.ref(!1),r=e.ref(!1),s=n,o=()=>{a.value=!a.value},i=()=>{r.value=!0,a.value=!1},l=c=>{console.log("用户输入:",c)};return ot(),(c,u)=>r.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",qn,[e.createVNode(tt,{modelValue:a.value,"onUpdate:modelValue":u[0]||(u[0]=S=>a.value=S),onSubmit:l,onUiAction:u[1]||(u[1]=S=>s("ui-action",S)),token:t.token,identifier:t.identifier,baseUrl:t.baseUrl,title:t.title,llmName:t.llmName,messagePostRender:t.messagePostRender,extraConfig:t.extraConfig,customUi:t.customUi,uiActionHandler:t.uiActionHandler,mockResponse:t.mockResponse,soundBaseUrl:t.soundBaseUrl,workerUrl:t.workerUrl,enableVoiceInput:t.enableVoiceInput,enableVoiceUpload:t.enableVoiceUpload},null,8,["modelValue","token","identifier","baseUrl","title","llmName","messagePostRender","extraConfig","customUi","uiActionHandler","mockResponse","soundBaseUrl","workerUrl","enableVoiceInput","enableVoiceUpload"]),e.createElementVNode("div",{class:"ai-icon",onClick:o},[e.createElementVNode("div",{class:"close-icon",onClick:e.withModifiers(i,["stop"])},[...u[2]||(u[2]=[e.createElementVNode("svg",{viewBox:"0 0 1024 1024",width:"8",height:"8"},[e.createElementVNode("path",{d:"M512 456.310154L94.247385 38.557538a39.384615 39.384615 0 0 0-55.689847 55.689847L456.310154 512 38.557538 929.752615a39.384615 39.384615 0 0 0 55.689847 55.689847L512 567.689846l417.752615 417.752616c15.163077 15.163077 40.526769 15.163077 55.689847 0s15.163077-40.526769 0-55.689847L567.689846 512l417.752616-417.752615a39.384615 39.384615 0 0 0-55.689847-55.689847L512 456.310154z",fill:"currentColor"})],-1)])]),u[3]||(u[3]=e.createElementVNode("img",{src:Z,alt:"AI助手"},null,-1)),u[4]||(u[4]=e.createElementVNode("span",{class:"ai-icon-text"},"AI助手",-1))])]))}}),Gn={class:"ai-chat-plain"},Jn={name:"AiChatPlain"},at=e.defineComponent({...Jn,props:{token:{type:String,default:""},identifier:{type:String,default:""},baseUrl:{type:String,default:""},title:{type:String,default:"数智AI助理"},llmName:{type:String,default:"szjy"},messagePostRender:{type:Function,default:null},extraConfig:{type:Object,default:()=>({})},soundBaseUrl:{type:String,default:"/sounds/"},workerUrl:{type:String,default:""},enableVoiceInput:{type:Boolean,default:!1},enableVoiceUpload:{type:Boolean,default:!1},customUi:{type:Object,default:null},uiActionHandler:{type:Function,default:null},mockResponse:{type:String,default:""}},emits:["submit","ui-action"],setup(t,{emit:n}){const a=n;return ot(),(r,s)=>(e.openBlock(),e.createElementBlock("div",Gn,[e.createVNode(tt,{"model-value":!0,token:t.token,identifier:t.identifier,baseUrl:t.baseUrl,title:t.title,llmName:t.llmName,messagePostRender:t.messagePostRender,extraConfig:t.extraConfig,customUi:t.customUi,uiActionHandler:t.uiActionHandler,mockResponse:t.mockResponse,soundBaseUrl:t.soundBaseUrl,workerUrl:t.workerUrl,enableVoiceInput:t.enableVoiceInput,enableVoiceUpload:t.enableVoiceUpload,embedded:!0,onSubmit:s[0]||(s[0]=o=>a("submit",o)),onUiAction:s[1]||(s[1]=o=>a("ui-action",o))},null,8,["token","identifier","baseUrl","title","llmName","messagePostRender","extraConfig","customUi","uiActionHandler","mockResponse","soundBaseUrl","workerUrl","enableVoiceInput","enableVoiceUpload"])]))}}),st=Object.freeze(Object.defineProperty({__proto__:null,SzAiChat:rt,SzAiChatPlain:at},Symbol.toStringTag,{value:"Module"})),Ee=function(t){if(!Ee.installed){Ee.installed=!0;for(let n in st){const a=Reflect.get(st,n);t.component(a.name,a)}}},Kn=(t,n)=>{const a=n?`?${new URLSearchParams(n).toString()}`:"";console.log(`点击了路由链接: ${t}${a}`)},it=t=>{const n=t.indexOf("?");if(n===-1)return{routeName:t};const a=t.substring(0,n),r=t.substring(n+1),s={};return new URLSearchParams(r).forEach((i,l)=>{s[l]=i}),{routeName:a,queryParams:Object.keys(s).length>0?s:void 0}},Yn={color:"#536fec",fontWeight:"bold",textDecoration:"underline",cursor:"pointer",padding:"0 3px"},lt=t=>{const n=/#router:([^#]+)#/g,a=[];let r=0,s;for(;(s=n.exec(t))!==null;){s.index>r&&a.push({text:t.substring(r,s.index)});const o=s[1],{routeName:i,queryParams:l}=it(o);a.push({text:i,routeName:i,queryParams:l}),r=n.lastIndex}return r<t.length&&a.push({text:t.substring(r)}),a},ct=(t,n,a={},r)=>{const{onRouteClick:s=Kn,linkStyle:o={}}=a,i=document.createElement("a");i.href="#",i.textContent=t;const l={...Yn,...o};return Object.assign(i.style,l),i.addEventListener("click",c=>{c.preventDefault(),s(n,r)}),i},ut=t=>{const n=/#router:([^#]+)#/g,a=[],r=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,null);let s=r.nextNode();for(;s;){const o=s,i=o.textContent||"";if(n.test(i)){n.lastIndex=0;const l=lt(i);l.length>0&&a.push({node:o,replacements:l})}s=r.nextNode()}return a},Zn=(t,n,a={})=>{const r=ut(t);r.forEach(({node:s,replacements:o})=>{var l;const i=document.createDocumentFragment();o.forEach(({text:c,routeName:u,queryParams:S})=>{if(u){const R=ct(c,u,a,S);i.appendChild(R)}else i.appendChild(document.createTextNode(c))}),(l=s.parentNode)==null||l.replaceChild(i,s)}),a!=null&&a.nodeCallback&&r.forEach(({node:s,replacements:o})=>{var i;(i=a.nodeCallback)==null||i.call(a,s,o)})},se="szjy-voice-models",de="szjy-voice-cache-v1";function ee(){return typeof navigator<"u"&&!!navigator.storage&&typeof navigator.storage.getDirectory=="function"}async function fe(t=se){if(!ee())return null;try{return await(await navigator.storage.getDirectory()).getDirectoryHandle(t,{create:!0})}catch(n){return console.warn("[OPFS] 获取目录失败,将使用降级缓存:",n),null}}async function Xn(t,n,a=se){if(ee())try{const r=await fe(a);if(r){const o=await(await r.getFileHandle(t,{create:!0})).createWritable();return await o.write(n),await o.close(),!0}}catch(r){console.warn(`[OPFS] 写入文件 ${t} 失败:`,r)}if(typeof caches<"u")try{const r=await caches.open(de),s=new Response(n,{headers:{"Content-Type":"application/octet-stream"}});return await r.put(`/${a}/${t}`,s),!0}catch(r){console.warn(`[CacheStorage] 缓存写入 ${t} 失败:`,r)}return!1}async function Qn(t,n=se){if(ee())try{const a=await fe(n);if(a)return await(await(await a.getFileHandle(t,{create:!1})).getFile()).arrayBuffer()}catch{}if(typeof caches<"u")try{const r=await(await caches.open(de)).match(`/${n}/${t}`);if(r)return await r.arrayBuffer()}catch{}return null}async function eo(t,n=se){if(ee())try{const a=await fe(n);if(a)return(await(await a.getFileHandle(t,{create:!1})).getFile()).size>0}catch{}if(typeof caches<"u")try{return!!await(await caches.open(de)).match(`/${n}/${t}`)}catch{}return!1}async function to(t=se){let n=!1;if(ee())try{await(await navigator.storage.getDirectory()).removeEntry(t,{recursive:!0}),n=!0,console.log(`[OPFS] 成功清空语音模型缓存目录: ${t}`)}catch(a){a.name==="NotFoundError"?n=!0:console.warn(`[OPFS] 清理目录 ${t} 异常:`,a)}if(typeof caches<"u")try{const a=await caches.keys();for(const r of a)(r.includes("transformers")||r.includes("szjy-voice")||r===de)&&(await caches.delete(r),n=!0)}catch(a){console.warn("[CacheStorage] 清除缓存异常:",a)}return n}const no="0.1.13",oo="Sz";function ro({componentPrefix:t=oo,components:n=[]}={}){const a=[];function r(o,i,l){o.component(t+i)||o.component(t+i,l)}function s(o){a.includes(o)||(a.push(o),n.forEach(i=>{const{name:l,alias:c}=i;r(o,l,i),c&&c.forEach(u=>{r(o,u,i)})}))}return{version:no,componentPrefix:t,install:s}}const ao={install(t){Ee(t)}};y.AudioRecorder=Ke,y.DEFAULT_MOCK_RESPONSE=xe,y.DEFAULT_WHISPER_WORKER_URL=Se,y.SZJY_UI_FENCE_LANG=qe,y.StreamResampler=Je,y.SzAiChat=rt,y.SzAiChatPlain=at,y.VoiceInputManager=et,y.bindSzjyUiEvents=Ge,y.clearVoiceModelCache=to,y.create=ro,y.createMockStylized=Ue,y.createRouteLink=ct,y.decodeAudioFile=Ze,y.default=ao,y.escapeHtml=X,y.findRouteTextNodes=ut,y.float32ToWav=be,y.getFileFromCache=Qn,y.getOPFSDirectory=fe,y.getSzjyUiAction=Ie,y.getSzjyUiComponent=Me,y.hasFileInCache=eo,y.hasSzjyUiAction=Le,y.hasSzjyUiComponent=je,y.isOPFSSupported=ee,y.parseRouteMarkerContent=it,y.parseRouteMarkers=lt,y.parseSzjyUiFence=We,y.registerSzjyUiAction=Pe,y.registerSzjyUiComponent=ke,y.renderActionAttrs=Fe,y.renderSzjyUiBlock=$e,y.renderSzjyUiNode=we,y.resampleAudioData=Ye,y.routeLinkRender=Zn,y.saveFileToCache=Xn,Object.defineProperties(y,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模拟后端(llmName: 'standard',LLMTypes 中标注「模拟数据模型」)。
|
|
3
|
+
*
|
|
4
|
+
* 不请求真实后端:将 extraConfig.mockResponse(或内置样例)按小块流式返回,
|
|
5
|
+
* 走与真实供应商完全一致的 reader / 打字机渲染管线,
|
|
6
|
+
* 用于联调 szjy-ui fence 渲染与 postMessage 动作。
|
|
7
|
+
*/
|
|
8
|
+
/** 内置 mock 样例:包含 szjy-ui fence 块,演示驱动 BIM 沙盘定位构件
|
|
9
|
+
* wbsCode 为演示项目 BIM2024CHKSLDY(125.122.34.243:8867)结构目录中的真实编码 */
|
|
10
|
+
export declare const DEFAULT_MOCK_RESPONSE: string;
|
|
11
|
+
/**
|
|
12
|
+
* mock 供应商 API,签名与其他供应商一致。
|
|
13
|
+
* 优先使用 extraConfig.mockResponse(由 sz-ai-chat 的 mockResponse prop 注入),
|
|
14
|
+
* 未提供时使用内置样例。
|
|
15
|
+
*/
|
|
16
|
+
export declare function createMockStylized(_text: string, _token: string, _identifier: string, _baseUrl?: string, extraConfig?: any): Promise<Response>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SzjyUiActionContext } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* postMessage 动作:把 actionParams 原样作为消息体发送到目标窗口。
|
|
5
|
+
* 典型消息体即 BIM 沙盘外部通信协议:
|
|
6
|
+
* { type: 'BIM_SANDBOX', action: 'locateComponent', payload: { wbsCode } }
|
|
7
|
+
*
|
|
8
|
+
* 传输通道(customUi.postMessage.transport,默认 'auto'):
|
|
9
|
+
* - 同窗口/同源目标存在 window.$bimSandbox 时优先直调全局方法(同步返回、即时反馈);
|
|
10
|
+
* - 否则走 postMessage 并监听回执(跨域 iframe 场景)。
|
|
11
|
+
*/
|
|
12
|
+
export declare function runPostMessageAction(ctx: SzjyUiActionContext): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SzjyUiNode, SzjyUiRenderContext } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* button 组件渲染器。
|
|
5
|
+
* props: { type?: 按钮类型, size?: 尺寸, content?: 按钮文案 }
|
|
6
|
+
* action / actionParams 由 renderActionAttrs 统一落到 data-* 属性。
|
|
7
|
+
* 内部固定包含 .szjy-ui-btn__status 状态位,供 postMessage 回执反馈就地展示。
|
|
8
|
+
*/
|
|
9
|
+
export declare function renderButton(node: SzjyUiNode, _ctx: SzjyUiRenderContext): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SzjyUiConfig } from './types';
|
|
2
|
+
|
|
3
|
+
export interface SzjyUiEventOptions {
|
|
4
|
+
/**
|
|
5
|
+
* 读取宿主 customUi 配置。支持 getter(推荐)——点击时求值,
|
|
6
|
+
* 避免宿主后续更新配置(如切换沙盘地址/targetOrigin)后仍用旧值导致消息被静默丢弃
|
|
7
|
+
*/
|
|
8
|
+
getConfig?: () => SzjyUiConfig | null;
|
|
9
|
+
/**
|
|
10
|
+
* 宿主拦截钩子:动作执行前调用,返回 false 阻止内置动作执行
|
|
11
|
+
* (用于宿主自定义路由/改写消息体等场景),点击时求值
|
|
12
|
+
*/
|
|
13
|
+
getInterceptor?: () => ((action: string, params: any, triggerEl: HTMLElement) => any) | null | undefined;
|
|
14
|
+
/** 动作触发通知(观察性质,不影响执行),随 ui-action 事件冒泡给宿主 */
|
|
15
|
+
onAction?: (payload: {
|
|
16
|
+
action: string;
|
|
17
|
+
params: any;
|
|
18
|
+
triggerEl: HTMLElement;
|
|
19
|
+
}) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 在容器上绑定 szjy-ui 委托点击事件,返回解绑函数。
|
|
23
|
+
*
|
|
24
|
+
* 为什么用事件委托:打字机效果每帧用 v-html 整块重建消息内容,
|
|
25
|
+
* 直接绑定在按钮节点上的监听器会随之丢失;委托挂在稳定的容器上不受影响。
|
|
26
|
+
*/
|
|
27
|
+
export declare function bindSzjyUiEvents(el: HTMLElement, options?: SzjyUiEventOptions): () => void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
|
|
2
|
+
export * from './types';
|
|
3
|
+
export { SZJY_UI_FENCE_LANG, parseSzjyUiFence } from './parse';
|
|
4
|
+
export { escapeHtml, renderSzjyUiBlock, renderSzjyUiNode, renderActionAttrs } from './render';
|
|
5
|
+
export { registerSzjyUiComponent, registerSzjyUiAction, getSzjyUiComponent, hasSzjyUiComponent, getSzjyUiAction, hasSzjyUiAction } from './registry';
|
|
6
|
+
export { bindSzjyUiEvents } from './events';
|
|
7
|
+
export type { SzjyUiEventOptions } from './events';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SzjyUiBlock } from './types';
|
|
2
|
+
|
|
3
|
+
/** szjy-ui 自定义 fence 的语言标识 */
|
|
4
|
+
export declare const SZJY_UI_FENCE_LANG = "szjy-ui";
|
|
5
|
+
/**
|
|
6
|
+
* 解析 szjy-ui fence 内容为块描述。
|
|
7
|
+
* 流式输出中 JSON 尚未输出完整、或结构不合法时返回 null,
|
|
8
|
+
* 调用方(markdown fence 规则)降级为普通代码块展示;
|
|
9
|
+
* 待流式推进、JSON 完整后下一次渲染自然切换为组件。
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseSzjyUiFence(content: string): SzjyUiBlock | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SzjyUiComponentRenderer, SzjyUiActionHandler } from './types';
|
|
2
|
+
|
|
3
|
+
export declare function registerSzjyUiComponent(type: string, renderer: SzjyUiComponentRenderer): void;
|
|
4
|
+
export declare function registerSzjyUiAction(name: string, handler: SzjyUiActionHandler): void;
|
|
5
|
+
export declare function getSzjyUiComponent(type: string): SzjyUiComponentRenderer | undefined;
|
|
6
|
+
export declare function hasSzjyUiComponent(type: string): boolean;
|
|
7
|
+
export declare function getSzjyUiAction(name: string): SzjyUiActionHandler | undefined;
|
|
8
|
+
export declare function hasSzjyUiAction(name: string): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SzjyUiBlock, SzjyUiNode, SzjyUiRenderContext } from './types';
|
|
2
|
+
|
|
3
|
+
/** 输出进入 v-html,所有动态文本必须经此转义 */
|
|
4
|
+
export declare function escapeHtml(text: unknown): string;
|
|
5
|
+
/**
|
|
6
|
+
* 渲染整个 szjy-ui 块为 HTML 字符串(含外层标识容器)。
|
|
7
|
+
* 块内未知类型的子节点在 renderSzjyUiNode 中被跳过,不影响其余节点。
|
|
8
|
+
*/
|
|
9
|
+
export declare function renderSzjyUiBlock(block: SzjyUiBlock): string;
|
|
10
|
+
/** 按注册表分发渲染单个节点;未注册类型返回空字符串 */
|
|
11
|
+
export declare function renderSzjyUiNode(node: SzjyUiNode, ctx: SzjyUiRenderContext): string;
|
|
12
|
+
/**
|
|
13
|
+
* 构造节点上的动作属性(data-*),供事件委托读取。
|
|
14
|
+
* - 无 action:普通展示型组件
|
|
15
|
+
* - action 未注册:渲染为禁用态并提示,避免点击无反馈
|
|
16
|
+
* - actionParams 经 encodeURIComponent 存入 data 属性,规避引号/换行转义问题
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderActionAttrs(node: SzjyUiNode): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* szjy-ui fence 块类型定义
|
|
3
|
+
*
|
|
4
|
+
* AI 响应中的 ```szjy-ui fence 块(JSON)经 parseSzjyUiFence 解析为 SzjyUiBlock,
|
|
5
|
+
* 再按组件注册表渲染为 HTML 字符串(v-html 输出),交互走容器级事件委托。
|
|
6
|
+
*/
|
|
7
|
+
/** 动作参数。postMessage 动作下即消息体本身(如 BIM_SANDBOX 定位协议) */
|
|
8
|
+
export type SzjyUiActionParams = Record<string, any>;
|
|
9
|
+
/** 单个 UI 节点(button、未来的 card/tag 等) */
|
|
10
|
+
export interface SzjyUiNode {
|
|
11
|
+
type: string;
|
|
12
|
+
props?: Record<string, any>;
|
|
13
|
+
action?: string;
|
|
14
|
+
actionParams?: SzjyUiActionParams;
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
}
|
|
17
|
+
/** 容器类节点(list 等),items 递归走组件注册表渲染 */
|
|
18
|
+
export interface SzjyUiBlock extends SzjyUiNode {
|
|
19
|
+
title?: string;
|
|
20
|
+
gap?: number | string;
|
|
21
|
+
items?: SzjyUiNode[];
|
|
22
|
+
}
|
|
23
|
+
/** 组件渲染上下文:当前节点所属的根块 */
|
|
24
|
+
export interface SzjyUiRenderContext {
|
|
25
|
+
block: SzjyUiBlock;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 组件渲染器:节点 → HTML 字符串。
|
|
29
|
+
* 输出会进入 v-html,渲染器必须对一切动态文本使用 escapeHtml 转义。
|
|
30
|
+
*/
|
|
31
|
+
export type SzjyUiComponentRenderer = (node: SzjyUiNode, ctx: SzjyUiRenderContext) => string;
|
|
32
|
+
/** postMessage 动作配置(sz-ai-chat 的 customUi.postMessage) */
|
|
33
|
+
export interface SzjyUiPostMessageConfig {
|
|
34
|
+
/**
|
|
35
|
+
* 目标窗口:
|
|
36
|
+
* - 'self'(默认,聊天与 BIM 沙盘同窗口的部署形态)/ 'parent' / 'top'
|
|
37
|
+
* - Window 或 Window[](如沙盘 iframe 的 contentWindow)
|
|
38
|
+
* - 函数:发送前以消息体求值,返回 Window | Window[]
|
|
39
|
+
*/
|
|
40
|
+
target?: 'self' | 'parent' | 'top' | Window | Window[] | ((message: SzjyUiActionParams) => Window | Window[]);
|
|
41
|
+
/** postMessage 的 targetOrigin,默认 '*';生产环境建议配置为沙盘真实源 */
|
|
42
|
+
targetOrigin?: string;
|
|
43
|
+
/**
|
|
44
|
+
* 传输通道:
|
|
45
|
+
* - 'auto'(默认):消息为 BIM_SANDBOX 协议且目标窗口存在 window.$bimSandbox 时
|
|
46
|
+
* 直调全局方法(同步返回、即时反馈,见《BIM沙盘全局方法调用文档》),否则回退 postMessage;
|
|
47
|
+
* 跨域 iframe 访问不到全局对象,自动回退
|
|
48
|
+
* - 'global':强制仅用全局方法,不可用时按钮报「全局方法不可用」
|
|
49
|
+
* - 'postMessage':强制仅用 postMessage(与《BIM沙盘外部通信文档》一致)
|
|
50
|
+
*/
|
|
51
|
+
transport?: 'auto' | 'postMessage' | 'global';
|
|
52
|
+
/**
|
|
53
|
+
* 回执失败且原因匹配「未就绪/未加载」时的自动重试;
|
|
54
|
+
* 默认 { retries: 2, delay: 2000 },传 false 关闭
|
|
55
|
+
*/
|
|
56
|
+
retry?: false | {
|
|
57
|
+
retries?: number;
|
|
58
|
+
delay?: number;
|
|
59
|
+
};
|
|
60
|
+
/** 是否监听回执并在按钮旁展示成功/失败反馈,默认 true */
|
|
61
|
+
feedback?: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** sz-ai-chat / sz-ai-chat-plain 的 customUi prop 结构 */
|
|
64
|
+
export interface SzjyUiConfig {
|
|
65
|
+
postMessage?: SzjyUiPostMessageConfig;
|
|
66
|
+
/**
|
|
67
|
+
* 动作调试日志:点击时在 console 打印动作名、参数、消息体、目标窗口与回执结果,
|
|
68
|
+
* 默认 true;生产环境如需安静可传 false
|
|
69
|
+
*/
|
|
70
|
+
debug?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** 动作执行上下文 */
|
|
73
|
+
export interface SzjyUiActionContext {
|
|
74
|
+
/** actionParams 解析结果 */
|
|
75
|
+
params: SzjyUiActionParams;
|
|
76
|
+
/** 触发动作的节点(按钮等),供反馈定位 */
|
|
77
|
+
node?: SzjyUiNode;
|
|
78
|
+
/** 宿主传入的 customUi 配置 */
|
|
79
|
+
config: SzjyUiConfig | null;
|
|
80
|
+
/** 触发动作的 DOM 元素,用于就地展示发送/成功/失败状态 */
|
|
81
|
+
triggerEl: HTMLElement;
|
|
82
|
+
}
|
|
83
|
+
/** 动作处理器 */
|
|
84
|
+
export type SzjyUiActionHandler = (ctx: SzjyUiActionContext) => void;
|