@szjy/ai-coms 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.umd.js CHANGED
@@ -1,3 +1,7 @@
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={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};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.16",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"}})});
1
+ (function(p,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(p=typeof globalThis<"u"?globalThis:p||self,e(p["szjy-ai-coms"]={},p.Vue))})(this,function(p,e){"use strict";var Br=Object.defineProperty;var Rr=(p,e,he)=>e in p?Br(p,e,{enumerable:!0,configurable:!0,writable:!0,value:he}):p[e]=he;var j=(p,e,he)=>Rr(p,typeof e!="symbol"?e+"":e,he);const he="/images/ai-round.png",sn="/images/ai-sqrt.png",ln="/images/sikao.svg",cn="/images/bars-loading.svg";function Qe(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${location.protocol}//${location.host}${t}`}async function un(t,n,r,o="",s={}){const{projectId:a}=s,i=Qe(o),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:r,...a?{projectId:a}:{}},messages:[{role:"system",content:"你是一个专业的AI助手,请用中文回答问题。"},{role:"user",content:t}]})});return fetch(u)}async function dn(t,n,r,o="",s={}){const a=new URL("http://localhost:11434/api/chat"),i={};Object.keys(i).forEach(c=>{a.searchParams.append(c,i[c])});const l=new Request(a,{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 fn(t,n,r,o="",s={}){const a=new URL(`${location.origin}/spark/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{a.searchParams.append(c,i[c])});const l=new Request(a,{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 mn(t,n,r,o="",s={}){const a=new URL(`${location.origin}/siliconflow/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{a.searchParams.append(c,i[c])});const l=new Request(a,{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 hn(t,n,r,o="",s={}){const a=new URL(`${location.origin}/moonshot/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{a.searchParams.append(c,i[c])});const l=new Request(a,{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 pn(t,n,r,o="",s={}){const a=new URL(`${location.origin}/dashscope/compatible-mode/v1/chat/completions`),i={};Object.keys(i).forEach(c=>{a.searchParams.append(c,i[c])});const l=new Request(a,{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 gn(t,n,r,o="",s={}){const a=Qe(o),i=new URL(`${a}/support/${r}/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 et=["根据您的问题,我为您整理了以下构件:","","```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
+ `),yn=8,kn=80,wn=t=>new Promise(n=>setTimeout(n,t));function Sn(t,n){const r=Math.ceil(t.length/n),o=[];for(let s=0;s<t.length;s+=r)o.push(t.slice(s,s+r));return o.length?o:[""]}async function tt(t,n,r,o="",s={}){const i=(s&&typeof s.mockResponse=="string"?s.mockResponse.trim():"")||et,l=new TextEncoder,c=new ReadableStream({async start(u){for(const f of Sn(i,yn))u.enqueue(l.encode(f)),await wn(kn);u.close()}});return new Response(c,{status:200,headers:{"Content-Type":"text/plain; charset=utf-8"}})}const bn=t=>{if(t.startsWith("data:")){const n=t.substring(5).trim();if(n==="[DONE]")return{done:!0};try{return JSON.parse(n)}catch(r){console.error("JSON parsing error:",r)}}return null},Re="<think>",ve="</think>",_e=(t,n)=>{const r=Math.max(0,t.length-(n.length-1));for(let o=r;o<t.length;o++)if(n.startsWith(t.slice(o)))return t.length-o;return 0},En=t=>{let n="",r="",o=t||"",s=!1;for(;o;){const a=o.indexOf(Re),i=o.indexOf(ve);if(a>=0&&(i<0||a<i))r+=o.slice(0,a),o=o.slice(a+Re.length),s=!0;else if(i>=0&&(a<0||i<a))n+=o.slice(0,i),o=o.slice(i+ve.length),s=!1;else if(s){const l=_e(o,ve);n+=o.slice(0,o.length-l),o=""}else{const l=Math.max(_e(o,Re),_e(o,ve));r+=o.slice(0,o.length-l),o=""}}return{thinking:n.trim(),content:r.trim(),isThinkingStreaming:s}},nt=[{label:"模拟数据模型",modelName:"standard",api:tt},{label:"Spark 星火大模型",modelName:"spark",api:fn},{label:"Ollama 3 大模型",modelName:"ollama3",api:dn},{label:"SiliconFlow 硅基流动大模型",modelName:"siliconflow",api:mn},{label:"Kimi Moonshot 月之暗面大模型",modelName:"moonshot",api:hn},{label:"通义千问大模型",modelName:"dashscope",api:pn},{label:"数智建管大模型",modelName:"szjy",api:gn},{label:"Dify (OpenAI 兼容)",modelName:"dify-openai",api:un}],ot={standard(t,n){let r="";return t instanceof Uint8Array?r=n.decode(t,{stream:!0}):r=t,{content:r}},spark(t){const n=bn(t);if(n.done)return{done:!0};const r=n.choices[0].delta,o=r.reasoning_content||r.reasoning;let s=r.content||"";return o&&(s=`<think>${o}</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}}},rt=(t,n,r)=>{const o=t.split(r);return o.slice(0,-1).forEach(s=>{s.trim()!==""&&n.enqueue(s)}),o[o.length-1]},Cn=t=>{let n="";return new TransformStream({transform(r,o){if(n+=r,n.trim().startsWith("data:"))n=rt(n,o,t);else try{JSON.parse(n),n=rt(n,o,t)}catch{o.enqueue(r),n=""}},flush(r){n.trim()!==""&&r.enqueue(n)}})};async function vn(t,n){const r=t.api;return r?new Promise(o=>{r(n.text,n.token,n.identifier,n.baseUrl,n.extraConfig).then(s=>{if(s.body){const a=s.body.pipeThrough(new TextDecoderStream).pipeThrough(Cn(`
3
+ `)).getReader();console.log("reader from response:",a),o({error:0,reader:a})}else o({error:1,reader:null})}).catch(()=>{o({error:1,reader:null})})}):{error:1,reader:null}}const Le=new Map,xe=new Map;function Ue(t,n){Le.set(t,n)}function at(t,n){xe.set(t,n)}function st(t){return Le.get(t)}function it(t){return Le.has(t)}function lt(t){return xe.get(t)}function ct(t){return xe.has(t)}const An={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function pe(t){return String(t??"").replace(/[&<>"']/g,n=>An[n])}function ut(t){const r=Pe(t,{block:t});return r?`<div class="szjy-ui" data-szjy-ui="1">${r}</div>`:""}function Pe(t,n){if(!t||typeof t!="object"||typeof t.type!="string")return"";const r=st(t.type);return r?r(t,n):""}function dt(t){const n=t.action;if(!n||typeof n!="string")return"";if(!ct(n))return` disabled title="未知动作:${pe(n)}"`;const r=t.actionParams===void 0?"":encodeURIComponent(JSON.stringify(t.actionParams??null));return` data-szjy-ui-action="${pe(n)}" data-szjy-ui-params="${r}"`}function Tn(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 Nn(t,n){const r=typeof t.title=="string"&&t.title?`<div class="szjy-ui-list__title">${pe(t.title)}</div>`:"",s=(Array.isArray(t.items)?t.items:[]).map(i=>Pe(i,n)).filter(Boolean).map(i=>`<div class="szjy-ui-list__item">${i}</div>`).join(""),a=pe(Tn(t.gap));return'<div class="szjy-ui-list">'+r+`<div class="szjy-ui-list__items" style="gap:${a}">${s}</div></div>`}Ue("list",Nn);const Vn=["default","primary","success","warning","danger","info","text"],Bn=["small","default","large"];function Rn(t,n){const r=t.props,o=r&&typeof r=="object"?r:{},s=Vn.includes(o.type)?o.type:"default",a=Bn.includes(o.size)?o.size:"default",i=pe(o.content??o.text??"按钮"),l=dt(t);return`<button type="button" class="${["szjy-ui-btn",`szjy-ui-btn--${s}`,`szjy-ui-btn--${a}`].join(" ")}"${l}><span class="szjy-ui-btn__text">${i}</span><span class="szjy-ui-btn__status" aria-live="polite"></span></button>`}Ue("button",Rn);const _n=15e3,ft=/未就绪|未加载/,Ln="BIM_SANDBOX",xn={locateComponent:t=>[t==null?void 0:t.wbsCode],openPDFSearch:()=>[]};let Un=0;function Pn(t,n){let r;if(!t||t==="self")r=[window];else if(t==="parent")r=[window.parent];else if(t==="top")r=[window.top];else if(typeof t=="function")try{r=t(n)}catch(a){console.error("[szjy-ui] 解析 postMessage 目标窗口失败:",a),r=[]}else Array.isArray(t)?r=t:r=[t];const o=[],s=a=>{if(a){if(Array.isArray(a)){a.forEach(s);return}typeof a.postMessage=="function"&&!o.includes(a)&&o.push(a)}};return s(r),o}function ge(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 Mn(t){try{const n=t.$bimSandbox;return n&&typeof n=="object"?n:null}catch{return null}}function zn(t,n,r){if(n.type!==Ln)return{handled:!1};const o=xn[n.action];if(!o)return{handled:!1};const s=Mn(t);if(!s||typeof s[n.action]!="function")return{handled:!1};const a=o(n.payload);let i;try{i=s[n.action](...a)}catch(l){return console.error("[szjy-ui] $bimSandbox 方法调用异常,回退 postMessage:",l),{handled:!1}}return r&&console.log("[szjy-ui] $bimSandbox 直调",{method:n.action,args:a,result:i,target:ge(t)}),{handled:!0,result:i}}function mt(t,n,r,o,s,a,i){return(()=>{const{handled:c,result:u}=zn(t,n,i);return c?(u&&u.success?a&&te(r,"success",u.message||"执行成功"):u&&ft.test(String(u.message||""))&&o>0?(i&&console.warn(`[szjy-ui] $bimSandbox 直调失败(${u.message}),${s}ms 后自动重试,剩余 ${o-1} 次`),a&&te(r,"retrying",`${u.message},${Math.round(s/1e3)}s 后自动重试`),setTimeout(()=>{mt(t,n,r,o-1,s,a,i)},s)):a&&te(r,"error",u&&u.message||"执行失败"),!0):!1})()}function jn(t){const n=In(t.config),r=!t.config||t.config.debug!==!1,o=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),te(t.triggerEl,"error","参数无效");return}const a={...t.params},i=Pn(n.target,a);if(!i.length){console.warn("[szjy-ui] postMessage 无可用目标窗口,target 配置:",n.target),te(t.triggerEl,"error","无目标窗口");return}const l=n.targetOrigin||"*",c=n.transport||"auto";if(c!=="postMessage"){let u=!1;for(const f of i)if(mt(f,a,t.triggerEl,s.retries,s.delay,o,r)){u=!0;break}if(u)return;if(c==="global"){console.warn("[szjy-ui] transport=global 但 $bimSandbox 全局方法不可用:",{targets:i.map(ge),message:a}),te(t.triggerEl,"error","全局方法不可用");return}r&&console.log("[szjy-ui] $bimSandbox 不可用,回退 postMessage 通道")}a.requestId===void 0&&(a.requestId=`szjy-ui-${Date.now()}-${++Un}`),ht(i,a,l),r&&console.log("[szjy-ui] postMessage 已发送",{message:a,targets:i.map(ge),targetOrigin:l,feedback:o}),o&&(te(t.triggerEl,"loading","已发送"),On(a,i,t.triggerEl,l,s,r))}function In(t){return t&&t.postMessage||{}}function ht(t,n,r){t.forEach(o=>{try{o.postMessage(n,r)}catch(s){console.error("[szjy-ui] postMessage 发送失败:",s)}})}function On(t,n,r,o,s,a){let i=s.retries;const l=s.delay;let c=null;const u=()=>{window.removeEventListener("message",V),c&&(clearTimeout(c),c=null)},f=()=>{c&&clearTimeout(c),c=setTimeout(()=>{u(),a&&console.warn("[szjy-ui] postMessage 超时未收到回执",{message:t,targets:n.map(ge),targetOrigin:o}),te(r,"none","未收到回执")},_n)},V=A=>{const g=A.data;!g||typeof g!="object"||t.type!==void 0&&g.type!==t.type||g.success!==void 0&&(t.requestId!==void 0&&g.requestId!==void 0&&String(g.requestId)!==String(t.requestId)||A.source&&!n.includes(A.source)||(a&&console.log("[szjy-ui] postMessage 收到回执",{requestId:g.requestId,success:g.success,message:g.message,data:g.data,from:ge(A.source)}),g.success?(u(),te(r,"success",g.message||"执行成功")):ft.test(String(g.message||""))&&i>0?(i-=1,a&&console.warn(`[szjy-ui] postMessage 回执失败(${g.message}),${l}ms 后自动重试,剩余 ${i} 次`),te(r,"retrying",`${g.message},${Math.round(l/1e3)}s 后自动重试`),c&&clearTimeout(c),setTimeout(()=>{ht(n,t,o),a&&console.log("[szjy-ui] postMessage 重试已发送",{message:t,targets:n.map(ge),targetOrigin:o}),te(r,"loading","已发送"),f()},l)):(u(),te(r,"error",g.message||"执行失败"))))};window.addEventListener("message",V),f()}function te(t,n,r){if(!t||!t.isConnected)return;const o=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}`),o&&(o.textContent=r||"")}at("postMessage",jn);const pt="szjy-ui";function gt(t){if(!t||typeof t!="string")return null;const n=t.trim();if(!n.startsWith("{"))return null;let r;try{r=JSON.parse(n)}catch{return null}return Dn(r)}function Dn(t){return!t||typeof t!="object"||Array.isArray(t)||typeof t.type!="string"||!it(t.type)||t.items!==void 0&&!Array.isArray(t.items)?null:t}function yt(t,n={}){if(!t)return()=>{};const r=o=>{var A;const s=o.target,a=s&&typeof s.closest=="function"?s.closest("[data-szjy-ui-action]"):null;if(!a||!t.contains(a))return;const i=a.getAttribute("data-szjy-ui-action")||"",l=lt(i);if(!l){console.warn(`[szjy-ui] 未注册的动作: ${i}`);return}const c=a.getAttribute("data-szjy-ui-params");let u=null;if(c)try{u=JSON.parse(decodeURIComponent(c))}catch(g){console.error("[szjy-ui] actionParams 解析失败:",g);return}const f=n.getConfig?n.getConfig():null;if(!f||f.debug!==!1){const g=(A=a.querySelector(":scope > .szjy-ui-btn__text"))==null?void 0:A.textContent;console.log("[szjy-ui] 动作触发",{action:i,params:u,text:(g||a.textContent||"").trim().slice(0,40),trigger:a})}const V=n.getInterceptor?n.getInterceptor():null;if(!(V&&V(i,u,a)===!1)){if(n.onAction)try{n.onAction({action:i,params:u,triggerEl:a})}catch(g){console.error("[szjy-ui] onAction 回调执行失败:",g)}l({params:u,config:f,triggerEl:a})}};return t.addEventListener("click",r),()=>{t.removeEventListener("click",r)}}let ie=null;function $n(){return ie||(window.markdownit?(ie=new window.markdownit({html:!0,linkify:!0,typographer:!0}),ie.renderer.rules.fence=(t,n)=>{const r=t[n],o=(r.info||"").trim().split(/\s+/)[0];if(o===pt){const a=gt(r.content),i=a?ut(a):"";if(i)return i}let s="";if(o&&window.hljs&&window.hljs.getLanguage(o))try{s=window.hljs.highlight(r.content,{language:o}).value}catch{s=""}return s||(s=ie.utils.escapeHtml(r.content)),`<pre class="md-code-block"><code class="hljs${o?" language-"+o:""}">${s}</code></pre>`}):console.log("markdownit is not loaded"),ie)}const Fn=(t,n)=>{const r=t.__vccOpts||t;for(const[o,s]of n)r[o]=s;return r},Hn=["src","alt"],Ae=Fn({__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,r=e.computed(()=>{if(n.name.startsWith("http://")||n.name.startsWith("https://")||n.name.startsWith("/"))return n.name;const a=n.name.endsWith(".svg")?n.name:`${n.name}.svg`;return`${n.basePath}${a}`}),o=e.computed(()=>{const a=typeof n.size=="number"?`${n.size}px`:n.size;return{width:a,height:a,display:"inline-flex",justifyContent:"center",alignItems:"center"}}),s=e.computed(()=>{const a={width:"100%",height:"100%"};return n.color&&(a.filter=`drop-shadow(0 0 0 ${n.color})`),a});return(a,i)=>(e.openBlock(),e.createElementBlock("div",{class:"svg-icon-wrapper",style:e.normalizeStyle(o.value)},[e.createElementVNode("img",{src:r.value,alt:t.name,class:e.normalizeClass(["svg-icon",t.className]),style:e.normalizeStyle(s.value)},null,14,Hn)],4))}},[["__scopeId","data-v-490b11c1"]]),qn=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)}},Wn={class:"thinking-title"},Gn={class:"thinking-toggle-hint"},Jn=["innerHTML"],Kn=["innerHTML"],Yn=10,Xn={__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","started","completed","updating","ui-action"],setup(t,{expose:n,emit:r}){const{appContext:o}=e.getCurrentInstance(),{$message:s}=o.config.globalProperties,a=t,i=e.ref(a.displayText||""),l=e.ref(!0),c=e.ref(!1),u=e.ref(!!a.displayText),f=r,V=e.ref(null);let A=null;e.watch(V,$=>{A&&(A(),A=null),$&&(A=yt($,{getConfig:()=>a.customUi,getInterceptor:()=>a.uiActionHandler,onAction:h=>f("ui-action",h)}))});let g=null;const C=e.computed(()=>En(i.value)),T=e.computed(()=>C.value.thinking.length>0),_=e.ref(a.displayText?C.value.content.length:0),S=e.computed(()=>C.value.isThinkingStreaming&&!u.value),d=e.ref(!1),E=()=>{d.value=!d.value};let y=null,m=null;const B=e.ref(0);e.watch(()=>C.value.thinking,$=>{!$||B.value>0||(m===null&&(m=y??Date.now()),C.value.content&&R())});const R=()=>{if(B.value>0||!T.value)return;const $=m??y;$&&(B.value=Math.max(1,Math.round((Date.now()-$)/1e3)))},O=e.computed(()=>S.value?"正在思考...":B.value>0?`已深度思考(用时 ${B.value} 秒)`:"思考过程"),x=e.computed(()=>T.value?ie?ie.render(C.value.thinking):C.value.thinking:""),M=e.computed(()=>C.value.content.slice(0,_.value)),N=e.computed(()=>ie?ie.render(M.value):M.value),D=()=>{a.reader&&a.reader.cancel(),c.value=!0,G.value=!1,ee(),u.value=!0,R(),f("completed",i.value),l.value=!1,g&&(cancelAnimationFrame(g),g=null)},X=e.computed(()=>`${N.value}`),q=e.ref(!1),Z=()=>{q.value=!0},ee=()=>{q.value=!1},G=e.ref(!1),ne=async()=>{if(!a.reader)return;const $=new TextDecoder("utf-8");for(l.value=!0;!c.value;)try{if(!a.reader){G.value=!0;break}const{value:h,done:L}=await a.reader.read();if(!a.reader){G.value=!0;break}if(L){G.value=!0;break}const I=ot[a.model];if(!I)break;const z=I.call(ot,h,$);if(z.done){G.value=!0;break}!y&&z.content&&(y=Date.now(),f("started")),i.value+=z.content,g===null&&oe()}catch(h){G.value=!0,console.log(3333,h),f("failed",h),D();break}finally{ee()}},re=async()=>{a.scrollToBottomFn&&a.scrollToBottomFn()},ae=($=()=>{},h=()=>{})=>{const L=C.value.content.length;_.value>L&&(_.value=L),_.value<L?(_.value=Math.min(L,_.value+Yn),$()):h()},oe=()=>{if(c.value&&g){cancelAnimationFrame(g),g=null,l.value=!1;return}G.value?ae(()=>{g=requestAnimationFrame(oe),f("updating",null)},()=>{R(),f("completed",i.value),l.value=!1,u.value=!0,e.nextTick(()=>{if(G.value=!1,a.messagePostRender&&V.value)try{a.messagePostRender(V.value,C.value.content)}catch($){console.error("messagePostRender 执行失败:",$)}}),g=null}):(ae(),g=requestAnimationFrame(oe)),re()};e.watch(()=>a.reader,()=>{a.reader&&ne()},{immediate:!0,deep:!0}),e.onUnmounted(()=>{A&&(A(),A=null),D()}),n({abortReader:D,initializeStart:Z,initializeEnd:ee,getRawText:()=>i.value,isAborted:()=>c.value}),e.computed(()=>q.value?!0:(!a.reader||!l||i.value,!1));const fe=async()=>{try{const $=C.value.content||i.value;await qn($),s.success("复制成功")}catch($){console.error("复制失败:",$),s.error("复制失败")}};return($,h)=>(e.openBlock(),e.createBlock(e.Transition,{name:"fade"},{default:e.withCtx(()=>[X.value||T.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"refWrapperContent",ref:V,"text-16":"",class:"w-full h-full overflow-y-auto relative","p-24px":""},[T.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["ai-thinking-block",{"is-expanded":d.value||S.value,"is-streaming":S.value}])},[e.createElementVNode("div",{class:"thinking-header",onClick:E},[h[0]||(h[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",Wn,e.toDisplayString(O.value),1),e.createElementVNode("span",Gn,e.toDisplayString(d.value||S.value?"收起":"展开"),1)]),e.withDirectives(e.createElementVNode("div",{class:"thinking-body",innerHTML:x.value},null,8,Jn),[[e.vShow,d.value||S.value]])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"markdown-wrapper",innerHTML:X.value},null,8,Kn),u.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:"ai-copy-btn-wrapper",onClick:fe},[e.createVNode(Ae,{name:"/images/svg/copy.svg",color:"#666666"}),h[1]||(h[1]=e.createElementVNode("span",{class:"copy-text"},"复制",-1))])):e.createCommentVNode("",!0)],512)):e.createCommentVNode("",!0)]),_:1}))}};class kt{constructor(n,r){j(this,"ratio");j(this,"leftover",new Float32Array(0));j(this,"fracOffset",0);this.ratio=n/r}reset(){this.leftover=new Float32Array(0),this.fracOffset=0}process(n){if(this.ratio===1)return new Float32Array(n);const r=new Float32Array(this.leftover.length+n.length);if(r.set(this.leftover),r.set(n,this.leftover.length),r.length<2)return this.leftover=r,new Float32Array(0);const o=[];let s=this.fracOffset;for(;s<r.length-1;){const i=Math.floor(s),l=s-i,c=r[i],u=r[i+1];o.push(c+l*(u-c)),s+=this.ratio}const a=Math.min(r.length,Math.floor(s));return this.leftover=r.slice(a),this.fracOffset=s-a,Float32Array.from(o)}}class wt{constructor(n={}){j(this,"targetSampleRate");j(this,"audioContext",null);j(this,"mediaStream",null);j(this,"sourceNode",null);j(this,"processorNode",null);j(this,"muteGain",null);j(this,"resampler",null);j(this,"audioChunks",[]);j(this,"onVolumeChange");j(this,"onAudioChunk");j(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(o){throw o.name==="NotAllowedError"||o.name==="PermissionDeniedError"?new Error("麦克风权限被拒绝,请在浏览器地址栏允许麦克风访问权限。"):o.name==="NotFoundError"||o.name==="DevicesNotFoundError"?new Error("未检测到可用的麦克风输入设备。"):new Error(`无法启动麦克风: ${o.message||o}`)}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 kt(this.audioContext.sampleRate,this.targetSampleRate),this.sourceNode=this.audioContext.createMediaStreamSource(this.mediaStream);const r=4096;this.processorNode=this.audioContext.createScriptProcessor(r,1,1),this.processorNode.onaudioprocess=o=>{var i;if(!this._isRecording)return;const s=new Float32Array(o.inputBuffer.getChannelData(0));if(this.onVolumeChange){let l=0;for(let f=0;f<s.length;f++)l+=s[f]*s[f];const c=Math.sqrt(l/s.length),u=Math.min(100,Math.round(c*100*5));this.onVolumeChange(u)}const a=this.resampler?this.resampler.process(s):s;a.length&&(this.audioChunks.push(a),(i=this.onAudioChunk)==null||i.call(this,a))},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,a)=>s+a.length,0),r=new Float32Array(n);let o=0;for(const s of this.audioChunks)r.set(s,o),o+=s.length;return this.audioChunks=[],r}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 St(t,n,r){if(n===r)return new Float32Array(t);const o=n/r,s=Math.round(t.length/o),a=new Float32Array(s);for(let i=0;i<s;i++){const l=i*o,c=Math.floor(l),u=l-c,f=t[c]??0,V=t[c+1]??f;a[i]=f+u*(V-f)}return a}async function bt(t,n=16e3){const r=await t.arrayBuffer(),o=window.AudioContext||window.webkitAudioContext,s=new o;try{const a=await s.decodeAudioData(r);let i;if(a.numberOfChannels>1){i=new Float32Array(a.length);for(let l=0;l<a.numberOfChannels;l++){const c=a.getChannelData(l);for(let u=0;u<a.length;u++)i[u]+=c[u]/a.numberOfChannels}}else i=a.getChannelData(0);return St(i,a.sampleRate,n)}finally{s.state!=="closed"&&await s.close().catch(()=>{})}}function Me(t,n=16e3){const r=new ArrayBuffer(44+t.length*2),o=new DataView(r),s=(i,l)=>{for(let c=0;c<l.length;c++)o.setUint8(i+c,l.charCodeAt(c))};s(0,"RIFF"),o.setUint32(4,36+t.length*2,!0),s(8,"WAVE"),s(12,"fmt "),o.setUint32(16,16,!0),o.setUint16(20,1,!0),o.setUint16(22,1,!0),o.setUint32(24,n,!0),o.setUint32(28,n*2,!0),o.setUint16(32,2,!0),o.setUint16(34,16,!0),s(36,"data"),o.setUint32(40,t.length*2,!0);let a=44;for(let i=0;i<t.length;i++,a+=2){const l=Math.max(-1,Math.min(1,t[i]));o.setInt16(a,l<0?l*32768:l*32767,!0)}return new Blob([o],{type:"audio/wav"})}const Et=16e3,Zn=Math.round(Et*.35),ze="/scripts/ai/whisper.worker.js";function Qn(){return new Worker(je(ze),{type:"module"})}function je(t){return/^https?:\/\//i.test(t)?t:typeof location<"u"?new URL(t,location.origin).href:t}function Ct(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 eo(t){try{const n=await fetch(t,{method:"HEAD"});if(Ct(n))return!0}catch{}try{const n=await fetch(t,{headers:{Range:"bytes=0-64"}});if(Ct(n))return!0}catch{}return!1}async function to(t){const n=[];t&&n.push(je(t)),n.push(je(ze));const r=[...new Set(n.filter(Boolean))];for(const o of r)if(await eo(o))return console.log("[VoiceInputManager] 使用语音 Worker:",o),o;return console.warn("[VoiceInputManager] 未探测到可访问的 Worker 脚本,将回退到 Vite 打包注入地址。已尝试:",r.join(" , ")),null}class vt{constructor(n={}){j(this,"recorder",null);j(this,"worker",null);j(this,"status","idle");j(this,"options");j(this,"isReady",!1);j(this,"initPromise",null);j(this,"currentTaskId",0);j(this,"pcmParts",[]);j(this,"pcmLength",0);j(this,"streamChunkIndex",0);j(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((r,o)=>{this.setStatus("loading","正在准备语音识别引擎..."),(async()=>{var a,i;try{const l=await to(this.options.workerUrl);this.worker=l?new Worker(l,{type:"module"}):Qn(),this.worker.onmessage=c=>{this.handleWorkerMessage(c,r,o)},this.worker.onerror=c=>{var V,A;const f=`语音后台线程异常: ${c.message||c.filename||l||"未知错误"}`;this.initPromise=null,this.setStatus("error",f),(A=(V=this.options).onError)==null||A.call(V,f),o(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=(a=this.options).onError)==null||i.call(a,c),o(l)}})()}),this.initPromise)}async startRecording(){var n,r,o,s;if(!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia){const a=window.isSecureContext?"当前浏览器环境不支持获取麦克风音频,请使用现代浏览器。":"当前页面不是安全上下文,浏览器禁止调用麦克风。请使用 https:// 或 http://localhost / http://127.0.0.1 访问(通过局域网 IP 的 http 地址无法录音)。";throw this.setStatus("error",a),(r=(n=this.options).onError)==null||r.call(n,a),new Error(a)}this.isReady||await this.init(),this.recorder||(this.recorder=new wt({onVolumeChange:a=>{var i,l;(l=(i=this.options).onVolumeChange)==null||l.call(i,a)},onAudioChunk:a=>{this.appendPcm(a)}}));try{this.currentTaskId++,this.resetStreamState(),await this.recorder.start(),this.setStatus("recording","正在录音...")}catch(a){throw this.setStatus("error",a.message||"启动录音失败"),(s=(o=this.options).onError)==null||s.call(o,a.message||"启动录音失败"),a}}async stopAndTranscribe(){var n,r,o,s;if(!(!this.recorder||!this.recorder.isRecording))try{await this.recorder.stop();const a=this.mergePcm();if(a.length===0){this.resetStreamState(),this.setStatus("idle");return}this.setStatus("transcribing","正在识别语音...");try{const i=Me(a),l=URL.createObjectURL(i);(r=(n=this.options).onAudioRecorded)==null||r.call(n,l,i)}catch(i){console.warn("生成录音回放音频失败:",i)}await this.transcribeAudioData(a)}catch(a){this.setStatus("error",a.message||"音频处理失败"),(s=(o=this.options).onError)==null||s.call(o,a.message||"音频处理失败")}}async transcribeAudioData(n,r){var o,s,a,i;this.isReady||await this.init(),this.setStatus("transcribing","正在流式识别音频...");try{r&&((s=(o=this.options).onAudioRecorded)==null||s.call(o,r,Me(n))),this.currentTaskId++,this.resetStreamState(),this.appendPcm(n),this.dispatchFullAudio()}catch(l){this.setStatus("error",l.message||"音频处理失败"),(i=(a=this.options).onError)==null||i.call(a,l.message||"音频处理失败")}}async transcribeFile(n){var r,o;this.isReady||await this.init(),this.setStatus("loading","正在解析音频文件...");try{const s=await bt(n);if(s.length===0)throw new Error("未能从该文件中提取出有效音频");const a=URL.createObjectURL(n);await this.transcribeAudioData(s,a)}catch(s){this.setStatus("error",s.message||"音频文件解析失败"),(o=(r=this.options).onError)==null||o.call(r,s.message||"音频文件解析失败")}}cancelRecording(){var r;const n=this.currentTaskId;this.currentTaskId++,(r=this.worker)==null||r.postMessage({type:"CANCEL",taskId:n}),this.resetStreamState(),this.recorder&&this.recorder.cancel(),this.setStatus("idle")}cancelTranscribe(){var r;const n=this.currentTaskId;this.currentTaskId++,(r=this.worker)==null||r.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 r;const n=this.currentTaskId;this.currentTaskId++,(r=this.worker)==null||r.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 r=0;for(const o of this.pcmParts)n.set(o,r),r+=o.length;return n}emitPartial(n){var r,o;(o=(r=this.options).onPartial)==null||o.call(r,(n||"").trim())}finishStream(n){var o,s;const r=(n??this.committedText).trim();this.setStatus("idle"),(s=(o=this.options).onResult)==null||s.call(o,r)}dispatchFullAudio(){if(!this.worker){this.finishStream();return}if(this.pcmLength<Zn){this.finishStream();return}const n=this.mergePcm(),r=n.length>Et*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:r}},[n.buffer])}handleWorkerMessage(n,r,o){var u,f,V,A;const{type:s,data:a,taskId:i,text:l,error:c}=n.data;switch(s){case"READY":this.isReady=!0,this.setStatus("ready","语音引擎就绪"),r==null||r();break;case"PROGRESS":if(a){const g=typeof a.progress=="number"?Math.round(a.progress):0;this.setStatus("downloading",`正在下载语音模型... ${g}%`),(f=(u=this.options).onProgress)==null||f.call(u,{status:a.status||"progress",progress:g,file:a.file,loaded:a.loaded,total:a.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||"语音服务异常"),(A=(V=this.options).onError)==null||A.call(V,c||"语音服务异常"),o==null||o(new Error(c));break}}setStatus(n,r){var o,s;this.status=n,(s=(o=this.options).onStatusChange)==null||s.call(o,n,r)}}const de=16e3,Ie=.015,At=.25,Tt=2e3,Oe=3e4,Nt=250,De=350,Vt=.25,Bt=900,Rt=.5,_t=12,$e=1024,Lt=260,xt=600,Ut=80,Fe=28,Te="/api/voice",no={filterLength:256,delay:64,step:.1,epsilon:1e-6},oo=256,ro=64,ao=.1,so=1e-6;class Pt{constructor(n={}){j(this,"w");j(this,"xBuf");j(this,"filterLength");j(this,"delay");j(this,"mu");j(this,"eps");j(this,"cursor",0);j(this,"filled",0);this.filterLength=n.filterLength??oo,this.delay=n.delay??ro,this.mu=n.step??ao,this.eps=n.epsilon??so,this.w=new Float32Array(this.filterLength),this.xBuf=new Float32Array(this.delay+this.filterLength)}process(n,r){const o=n.length,s=new Float32Array(o);if(o===0)return s;const a=this.xBuf,i=a.length;let l=this.cursor;for(let c=0;c<o;c++){a[l]=c<r.length?r[c]:0,l=(l+1)%i,this.filled=Math.min(this.filled+1,i);const u=n[c];if(this.filled>=this.delay+this.filterLength){let f=0,V=0,A=(l-this.delay+i)%i;for(let _=0;_<this.filterLength;_++){const S=a[A];f+=this.w[_]*S,V+=S*S,A=(A-1+i)%i}const g=u-f;s[c]=g;const C=V+this.eps,T=this.mu*g/C;A=(l-this.delay+i)%i;for(let _=0;_<this.filterLength;_++)this.w[_]+=T*a[A],A=(A-1+i)%i}else s[c]=u}return this.cursor=l,s}reset(){this.w.fill(0),this.xBuf.fill(0),this.cursor=0,this.filled=0}}const we=(t,n)=>`${t.replace(/\/+$/,"")}${n}`;function Mt(t=Te,n={}){return fetch(we(t,"/ready"),{headers:n}).then(r=>r.json())}function zt(t=Te,n={}){return fetch(we(t,"/config"),{headers:n}).then(r=>r.json())}function io(t,n={},r,o){const s={"content-type":"application/octet-stream",...n};return o!==void 0&&(s["x-voice-session"]=o),fetch(we(t,"/asr"),{method:"POST",headers:s,body:r.slice().buffer}).then(async a=>{if(!a.ok)throw new Error(`asr http ${a.status}`);return await a.json()})}function He(t,n={},r){return fetch(we(t,"/cancel"),{method:"POST",headers:{"content-type":"application/json",...n},body:JSON.stringify({sessionId:r})}).then(async o=>{if(!o.ok)throw new Error(`cancel http ${o.status}`);return await o.json()})}function jt(t,n={},r,o){const s=we(t,"/stream");if(!(Object.keys(n).length>0)){const C=new EventSource(s);return C.onopen=()=>o({connected:!0}),C.onerror=()=>o({connected:!1}),C.addEventListener("audio",T=>{try{r(JSON.parse(T.data))}catch{}}),{close:()=>C.close()}}let i=!1,l=null,c=null,u="";const f=()=>{i||c!==null||(c=setTimeout(()=>{c=null,g()},3e3))},V=(C,T)=>{if(C==="audio")try{r(JSON.parse(T))}catch{}},A=()=>{let C;for(;(C=u.indexOf(`
4
+
5
+ `))!==-1;){const T=u.slice(0,C);u=u.slice(C+2);let _="message";const S=[];for(const d of T.split(`
6
+ `))d.startsWith(":")||(d.startsWith("event:")?_=d.slice(6).trim():d.startsWith("data:")&&S.push(d.slice(5).trimStart()));S.length>0&&V(_,S.join(`
7
+ `))}},g=async()=>{if(!i){l=new AbortController;try{const C=await fetch(s,{headers:n,signal:l.signal});if(!C.ok||!C.body)throw new Error(`stream http ${C.status}`);o({connected:!0});const T=C.body.getReader(),_=new TextDecoder;for(;;){const{done:S,value:d}=await T.read();if(S)break;u+=_.decode(d,{stream:!0}),A()}}catch{}i||(o({connected:!1}),f())}};return g(),{close:()=>{i=!0,c!==null&&clearTimeout(c);try{l==null||l.abort()}catch{}}}}function It(t,n){const{asrUrl:r,getHeaders:o,getEchoReference:s}=n;let a="idle";const i=new Set,l=new Set,c=new Set,u=new Set,f=new Set;let V=!1,A=null,g=null,C=null,T=!1,_=!1,S=!1,d=[],E=[],y=0,m=0,B=!1,R=0,O=!1,x=0,M=null,N=0,D="";const X=()=>typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`p-${Date.now()}-${Math.random().toString(36).slice(2)}`,q=h=>{a=h;for(const L of i)try{L(h)}catch{}},Z=h=>{const L=h.trim();if(L)for(const I of l)try{I(L)}catch{}},ee=()=>{const h=new Float32Array(d.reduce((I,z)=>I+z.length,0));let L=0;for(const I of d)h.set(I,L),L+=I.length;return h},G=async()=>{if(O||f.size===0||d.length===0)return;const h=d.reduce((P,J)=>P+J.length,0)/de;if(h<Rt||h>_t)return;const L=ee();if(L.length<=N)return;const I=L.subarray(N);N=L.length;const z=x;O=!0;const W=new AbortController;M=W;try{const P=await fetch(r,{method:"POST",headers:{"content-type":"application/octet-stream",...(o==null?void 0:o())??{},"x-voice-session":D,"x-dsh-session":D},body:I.slice().buffer,signal:W.signal});if(!P.ok)return;const J=await P.json();if(z!==x)return;const k=(J.text??"").trim();if(!k)return;for(const v of f)try{v(k)}catch{}}catch{}finally{O=!1,M===W&&(M=null)}},ne=async h=>{if(!V){V=!0,q("transcribing");try{const L=h.slice().buffer,I=await fetch(r,{method:"POST",headers:{"content-type":"application/octet-stream",...(o==null?void 0:o())??{}},body:L});if(!I.ok)throw new Error(`asr http ${I.status}`);const z=await I.json();z.text&&Z(z.text)}catch(L){console.warn(`[voice] transcription failed: ${String(L)}`)}finally{V=!1,q(T?S?"speech":"recording":"idle")}}},re=()=>{if(d.length===0)return;const h=ee();d=[],S=!1,y=0,m=0,ne(h)},ae=()=>{const h=Math.floor(De/1e3*de);h>0&&d.push(new Float32Array(h)),re()},oe=h=>{if(!T||B)return;let L=0;for(let P=0;P<h.length;P++)L+=h[P]*h[P];const I=Math.sqrt(L/h.length),z=h.length/de*1e3,W=Math.min(1,I/At);for(const P of u)try{P(W)}catch{}if(_){if(!S&&I>Ie){S=!0,q("speech");for(const P of c)try{P()}catch{}}if(m+=z,d.push(h),m>Oe){ae();return}R+=z,R>=Bt&&(R=0,G());return}if(I>Ie){if(!S){S=!0,q("speech");for(const P of c)try{P()}catch{}for(const P of E)d.push(P);E=[]}m+=z,y=0,d.push(h),m>Oe&&ae()}else if(S)m+=z,y+=z,d.push(h),y>Tt&&ae();else{E.push(h);const P=Nt;let J=0,k=0;for(let v=E.length-1;v>=0;v--)if(J+=E[v].length/de*1e3,J>P){k=v+1;break}k>0&&(E=E.slice(k))}},fe=async()=>{var I;if(T)return;const h=((I=s==null?void 0:s())==null?void 0:I.node)??null;g=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:h===null,noiseSuppression:!0,autoGainControl:!0}}),A=new AudioContext({sampleRate:de}),await A.resume().catch(()=>{});const L=A.createMediaStreamSource(g);if(h===null)C=A.createScriptProcessor($e,1,1),C.onaudioprocess=z=>{const W=z.inputBuffer.getChannelData(0);oe(new Float32Array(W))},L.connect(C);else{const z=new Pt({});C=A.createScriptProcessor($e,2,1),C.onaudioprocess=W=>{const P=W.inputBuffer.getChannelData(0),J=W.inputBuffer.getChannelData(1);oe(z.process(P,J))},L.connect(C,0,0),h.connect(C,0,1)}C.connect(A.destination),T=!0},$=async(h=!1)=>{if(!T)return;T=!1,B=!0,x++,R=0;try{M==null||M.abort()}catch{}M=null;const L=_;_=!1;try{if(h?!1:L?d.length>0:S){const z=d.reduce((W,P)=>W+P.length,0)/de;if(!L||z>=Vt){const W=Math.floor(De/1e3*de);d.push(new Float32Array(W)),re()}else d=[]}else d=[];S=!1,y=0,m=0,E=[]}finally{B=!1}try{C==null||C.disconnect()}catch{}C=null,N=0,D="";try{g==null||g.getTracks().forEach(I=>I.stop())}catch{}g=null;try{await(A==null?void 0:A.close())}catch{}A=null};return{get state(){return a},async start(h){if(!T){_=(h==null?void 0:h.hold)===!0,x++,R=0,N=0,D=X(),q("recording");try{await fe()}catch(L){throw _=!1,q("idle"),L}}},async stop(){if(!T){q("idle");return}await $(),V||q("idle")},async cancel(){await $(!0),q("idle")},onSegment(h){return l.add(h),()=>{l.delete(h)}},onState(h){return i.add(h),h(a),()=>{i.delete(h)}},onSpeechStart(h){return c.add(h),()=>{c.delete(h)}},onLevel(h){return u.add(h),()=>{u.delete(h)}},onPartial(h){return f.add(h),()=>{f.delete(h)}}}}function Ot(t){const n=t instanceof DOMException?t.name:"",r=t instanceof Error?t.message:String(t);switch(n){case"NotAllowedError":case"SecurityError":return"麦克风被拒绝:请在浏览器地址栏的权限设置里允许麦克风";case"NotFoundError":case"OverconstrainedError":return"找不到麦克风设备:请检查系统输入设备";case"NotReadableError":return"麦克风被其他程序占用";default:return r?`麦克风不可用:${r}`:"麦克风不可用"}}function lo(t){const n=atob(t),r=new Uint8Array(n.length);for(let s=0;s<n.length;s++)r[s]=n.charCodeAt(s);const o=r[0]===82&&r[1]===73&&r[2]===70&&r[3]===70;return URL.createObjectURL(new Blob([r],{type:o?"audio/wav":"audio/mpeg"}))}function Dt(t){const n=new Set;let r={connected:!1,playing:!1,caption:null};const o=[],s=$t();let a=null;const i=()=>{for(const f of n)f(r)},l=f=>{r={...r,...f},i()},c=()=>{const f=o.shift();if(!f){l({playing:!1,caption:null});return}co();const V=lo(f.audio);s.src=V,s.onended=()=>{URL.revokeObjectURL(V),c()},s.onerror=()=>{URL.revokeObjectURL(V),c()},l({playing:!0,caption:f.text}),s.play().catch(()=>{l({playing:!1})})},u=f=>{f.sessionId===t.getSessionId()&&f.audio&&(o.push(f),s.paused&&c())};return{connect(){var f;a===null&&(a=jt(t.streamUrl,((f=t.getHeaders)==null?void 0:f.call(t))??{},u,V=>l({connected:V.connected})))},skip(){o.length=0,s.pause(),s.onended=null,s.onerror=null,l({playing:!1,caption:null})},subscribe(f){return n.add(f),f(r),()=>{n.delete(f)}},getEchoReference(){return be?{node:be}:null}}}let qe=null;function $t(){return qe===null&&(qe=typeof Audio<"u"?new Audio:{}),qe}let Se=null,be=null;function co(){if(Se===null){Se=new AudioContext;const t=$t();be===null&&(be=Se.createMediaElementSource(t),be.connect(Se.destination))}return Se}const We=Symbol("szjy-voice");function Ge(){const t=e.inject(We);if(!t)throw new Error("useVoiceContext() 必须在 useVoice() 所在组件的子树中调用");return t}function Ft(t){const n=e.ref("idle"),r=e.ref(null),o=e.shallowRef(null),s=e.shallowRef(null),a=e.ref(null),i=()=>{var d;return((d=t.getAuthHeaders)==null?void 0:d.call(t))??{}},l=()=>e.toValue(t.sessionId),c=()=>e.toValue(t.running)===!0;let u=!1;const f=()=>{u=!0},V=()=>{var d;(d=s.value)==null||d.skip(),He(g(),i(),l()).catch(()=>{})};let A=t.apiBase??Te;const g=()=>A;let C=!1;(async()=>{try{const d=await Mt(g(),i());if(C)return;if(d.protocolVersion!==void 0&&d.protocolVersion!==1){r.value="语音协议不兼容";return}if(d.modelReady!==void 0&&d.modelReady===!1){r.value="语音模型未就绪";return}const E=await zt(g(),i());if(C)return;A=t.apiBase??E.basePath??A,a.value=E.asr;const y=Dt({streamUrl:g(),getHeaders:i,getSessionId:l});s.value=y,y.connect();const m=It(E.asr,{asrUrl:`${g()}/asr`,getHeaders:i,getEchoReference:()=>y.getEchoReference()});m.onState(B=>{n.value=B}),m.onSpeechStart(()=>{y.skip(),He(g(),i(),l()).catch(()=>{}),c()&&t.onCancelTurn()}),m.onSegment(B=>{const R=B.trim();if(!R)return;t.onTranscript(R);const O=u||E.asr.autoSend;u=!1,O&&setTimeout(()=>{try{t.onSubmit()}catch{}},60)}),o.value=m}catch(d){C||(r.value=`语音服务不可用:${d instanceof Error?d.message:String(d)}`)}})();const T=()=>{var d,E;C=!0,(d=o.value)==null||d.stop(),o.value=null,(E=s.value)==null||E.skip(),s.value=null};e.onUnmounted(T);const _=(d,E=!1)=>{!d&&!E||fetch(`${g()}/speak`,{method:"POST",headers:{"content-type":"application/json",...i()},body:JSON.stringify({sessionId:l(),text:d,final:E})}).catch(()=>{})},S={engine:o,playback:s,config:a,asrState:n,error:r,requestSubmitOnNextSegment:f,skipPlayback:V,speak:_};return e.provide(We,S),{asrState:n,error:r,dispose:T,speak:_}}const uo={class:"szjyv-ptt-backdrop"},fo={key:0,class:"szjyv-ptt-caret"},mo={class:"szjyv-kbd"},Ht=e.defineComponent({__name:"VoiceOverlay",props:{levels:{},armedCancel:{type:Boolean},pending:{type:Boolean},partial:{},source:{},hotkey:{}},setup(t){const n=t,r=e.computed(()=>n.armedCancel?"#f85149":"#2ea043"),o=e.computed(()=>Array.from({length:Fe},(a,i)=>n.levels[i]??0)),s=e.computed(()=>{const a=n.hotkey,i=typeof navigator<"u"&&/Mac|iP(hone|ad|od)/.test(navigator.platform??"");switch(a){case"Control":return i?"⌃":"Ctrl";case"Alt":return i?"⌥":"Alt";case"Meta":return i?"⌘":"Win";case"Shift":return"Shift";case" ":return"Space";default:return a}});return(a,i)=>(e.openBlock(),e.createElementBlock("div",uo,[e.createElementVNode("div",{class:e.normalizeClass(["szjyv-ptt-card",{cancel:t.armedCancel}])},[e.createElementVNode("div",{class:e.normalizeClass(["szjyv-ptt-wave",{frozen:t.pending}])},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.value,(l,c)=>(e.openBlock(),e.createElementBlock("span",{key:c,class:"szjyv-ptt-bar",style:e.normalizeStyle({height:`${3+l*37}px`,background:r.value,opacity:.45+l*.55})},null,4))),128))],2),t.partial&&!t.armedCancel?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["szjyv-ptt-live",{stale:t.pending}])},[e.createTextVNode(e.toDisplayString(t.partial)+" ",1),t.pending?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("span",fo))],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"szjyv-ptt-hint",style:e.normalizeStyle({color:t.armedCancel?"#f85149":"#8b949e"})},[t.pending?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[i[0]||(i[0]=e.createElementVNode("span",{class:"szjyv-spin szjyv-ptt-spinner"},null,-1)),i[1]||(i[1]=e.createTextVNode(" 识别中… ",-1))],64)):t.armedCancel?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode("松开手指 取消发送")],64)):t.source==="key"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:2},[i[2]||(i[2]=e.createTextVNode(" 松开 ",-1)),e.createElementVNode("span",mo,e.toDisplayString(s.value),1),i[3]||(i[3]=e.createTextVNode(" 发送 · ",-1)),i[4]||(i[4]=e.createElementVNode("span",{class:"szjyv-kbd"},"Esc",-1)),i[5]||(i[5]=e.createTextVNode(" 取消 ",-1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:3},[e.createTextVNode("松开发送 · 上滑取消")],64))],4)],2)]))}}),Je=e.defineComponent({__name:"EqualizerBars",props:{color:{},height:{}},setup(t){return(n,r)=>(e.openBlock(),e.createElementBlock("span",{class:"szjyv-eq",style:e.normalizeStyle({height:`${t.height}px`})},[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(3,o=>e.createElementVNode("span",{key:o,style:e.normalizeStyle({background:t.color,animationDelay:`${(o-1)*.18}s`})},null,4)),64))],4))}}),ho={key:1,class:"szjyv-toast"},po=["title"],go={key:2,class:"szjyv-mic-icon",viewBox:"0 0 24 24",width:"17",height:"17",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true"},yo=["stroke"],ko={key:4,class:"szjyv-mic-label"},qt=e.defineComponent({__name:"VoiceMicButton",setup(t){const n=Ge(),r=n.asrState,o=e.ref(null),s={idle:"voice: 待识别(点按说话)",recording:"voice: 录音中…",speech:"voice: 说话中…",transcribing:"voice: 识别中…","loading-model":"voice: 模型加载中…"},a={idle:"#8b949e",recording:"#f85149",speech:"#2ea043",transcribing:"#58a6ff","loading-model":"#bc8cff"},i=e.ref(!1),l=e.ref(!1),c=e.ref([]),u=e.ref(""),f=e.ref(!1),V=e.ref("pointer"),A=e.ref(""),g=e.ref(null),C=e.ref(null),T=e.ref(null),_=e.ref(0),S=e.ref(!1),d=e.ref(!1),E=e.ref(!1);e.watch(()=>n.config.value,k=>{A.value=(k==null?void 0:k.hotkey)??""},{immediate:!0});const y=e.computed(()=>r.value==="transcribing"||r.value==="loading-model"),m=e.computed(()=>{var k;return o.value?"voice error":r.value==="idle"?"mic":((k=s[r.value])==null?void 0:k.replace("voice: ",""))??"mic"}),B=e.computed(()=>{if(o.value)return o.value;const k=A.value?`;也可长按 ${R(A.value)}`:"";return`${s[r.value]??""}(长按说话,松开发送${k})`});function R(k){const v=typeof navigator<"u"&&/Mac|iP(hone|ad|od)/.test(navigator.platform??"");switch(k){case"Control":return v?"⌃":"Ctrl";case"Alt":return v?"⌥":"Alt";case"Meta":return v?"⌘":"Win";case"Shift":return"Shift";case" ":return"Space";default:return k}}e.watch(()=>n.error.value,k=>{k!==null&&o.value===null&&(o.value=k)},{immediate:!0}),e.watch(o,k=>{k!==null&&setTimeout(()=>{o.value===k&&(o.value=null)},4e3)});const O=async()=>{const k=n.engine.value;if(k){if(E.value){E.value=!1;return}o.value=null;try{k.state==="idle"?await k.start():await k.stop()}catch(v){o.value=v instanceof Error?v.message:String(v)}}};e.watch(i,k=>{const v=n.engine.value;if(!k||!v)return;c.value=[];const F=v.onLevel(le=>{c.value=c.value.length<Fe?[...c.value,le]:[...c.value.slice(1),le]});u.value="";const K=v.onPartial(le=>{u.value=le}),Q=v.onSegment(()=>{f.value=!1,u.value=""});x=()=>{F(),K(),Q()}});let x=null;e.watch(i,(k,v)=>{!k&&v&&x&&(x(),x=null)}),e.watch([f,r],([k,v])=>{if(!k||v==="transcribing"||v==="loading-model")return;setTimeout(()=>{f.value=!1,u.value=""},v==="idle"?220:12e3)});const M=k=>{if(T.value&&(clearTimeout(T.value),T.value=null),!d.value){C.value=null;return}d.value=!1,C.value=null,E.value=!0,i.value=!1,l.value=!1,S.value=!1;const v=n.engine.value;if(k){u.value="",f.value=!1,v==null||v.cancel();return}f.value=!0,n.requestSubmitOnNextSegment(),v==null||v.stop()},N=(k,v,F="pointer",K=Lt)=>{n.engine.value!==null&&(T.value&&clearTimeout(T.value),_.value=k,C.value=F,v==null||v(),T.value=setTimeout(()=>{var Q;T.value=null,d.value=!0,V.value=F,i.value=!0,f.value=!1,u.value="",o.value=null,(Q=n.engine.value)==null||Q.start({hold:!0}).catch(le=>{o.value=Ot(le),d.value=!1,C.value=null,i.value=!1})},K))},D=k=>{if(!d.value||C.value==="key")return;const v=_.value-k>Ut;v!==S.value&&(S.value=v,l.value=v)},X=k=>{N(k.clientY,()=>{try{k.currentTarget.setPointerCapture(k.pointerId)}catch{}})},q=k=>D(k.clientY),Z=()=>{C.value!=="key"&&M(S.value)},ee=()=>{C.value!=="key"&&M(!0)},G=()=>{const k=g.value;if(!k)return null;let v=k.parentElement;for(let F=0;v&&F<4;F++){const K=Array.from(v.querySelectorAll("button")).filter(Q=>Q!==k&&!k.contains(Q));if(K.length>0)return K[K.length-1];v=v.parentElement}return null},ne=e.ref(G);ne.value=G;let re=!1;const ae=k=>{const v=ne.value();if(!v)return;const F=v.getBoundingClientRect();k.clientX>=F.left&&k.clientX<=F.right&&k.clientY>=F.top&&k.clientY<=F.bottom&&W.value(k.clientY)},oe=k=>J.value(k.clientY),fe=()=>{C.value!=="key"&&P.value(S.value)},$=()=>{C.value!=="key"&&P.value(!0)},h=k=>{if(!E.value)return;const v=ne.value(),F=k.target;!v||!F||!(v===F||v.contains(F))||(E.value=!1,k.preventDefault(),k.stopImmediatePropagation())},L=k=>{const v=A.value;if(v){if(C.value!==null){if(k.key===v||C.value==="pointer"&&k.key!=="Escape")return;P.value(!0);return}k.key!==v||k.repeat||k.isComposing||W.value(0,void 0,"key",xt)}},I=k=>{C.value==="key"&&k.key===A.value&&P.value(!1)},z=()=>{C.value==="key"&&P.value(!0)},W=e.ref(N);W.value=N;const P=e.ref(M);P.value=M;const J=e.ref(D);return J.value=D,e.onMounted(()=>{re||(window.addEventListener("pointerdown",ae),window.addEventListener("pointermove",oe),window.addEventListener("pointerup",fe),window.addEventListener("pointercancel",$),window.addEventListener("click",h,!0),window.addEventListener("keydown",L),window.addEventListener("keyup",I),window.addEventListener("blur",z))}),e.onUnmounted(()=>{re=!0,window.removeEventListener("pointerdown",ae),window.removeEventListener("pointermove",oe),window.removeEventListener("pointerup",fe),window.removeEventListener("pointercancel",$),window.removeEventListener("click",h,!0),window.removeEventListener("keydown",L),window.removeEventListener("keyup",I),window.removeEventListener("blur",z),T.value&&clearTimeout(T.value),x==null||x()}),(k,v)=>(e.openBlock(),e.createElementBlock(e.Fragment,null,[i.value||f.value?(e.openBlock(),e.createBlock(Ht,{key:0,levels:c.value,"armed-cancel":l.value,pending:f.value,partial:u.value,source:V.value,hotkey:A.value},null,8,["levels","armed-cancel","pending","partial","source","hotkey"])):e.createCommentVNode("",!0),o.value?(e.openBlock(),e.createElementBlock("div",ho,e.toDisplayString(o.value),1)):e.createCommentVNode("",!0),e.createElementVNode("button",{ref_key:"anchorRef",ref:g,class:"szjyv-mic",title:B.value,onClick:O,onPointerdown:X,onPointermove:v[0]||(v[0]=F=>q(F)),onPointerup:Z,onPointercancel:ee},[y.value?(e.openBlock(),e.createElementBlock("span",{key:0,class:"szjyv-spin szjyv-mic-spinner",style:e.normalizeStyle({borderTopColor:a[e.unref(r)]})},null,4)):e.unref(r)==="speech"?(e.openBlock(),e.createBlock(Je,{key:1,color:"#2ea043",height:11})):e.unref(r)==="idle"&&!i.value?(e.openBlock(),e.createElementBlock("svg",go,[e.createElementVNode("path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",stroke:o.value?"#f85149":"#57606a",fill:"currentColor","fill-opacity":"0.15"},null,8,yo),v[1]||(v[1]=e.createElementVNode("path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"},null,-1)),v[2]||(v[2]=e.createElementVNode("line",{x1:"12",y1:"19",x2:"12",y2:"22"},null,-1))])):(e.openBlock(),e.createElementBlock("span",{key:3,class:e.normalizeClass(["szjyv-mic-dot",{pulse:e.unref(r)==="recording"&&!o.value}]),style:e.normalizeStyle({background:o.value?"#f85149":a[e.unref(r)]})},null,6)),i.value||m.value!=="mic"?(e.openBlock(),e.createElementBlock("span",ko,e.toDisplayString(i.value?l.value?"松开取消":"松开发送":m.value),1)):e.createCommentVNode("",!0)],40,po)],64))}}),wo={class:"szjyv-captionbar"},Wt=e.defineComponent({__name:"VoiceCaptionBar",setup(t){const n=Ge(),r=e.reactive({connected:!1,playing:!1,caption:null});let o=null;const s=e.watch(()=>n.playback.value,c=>{!c||o||(o=c.subscribe(u=>Object.assign(r,u)))},{immediate:!0});e.onUnmounted(()=>{s(),o==null||o()});const a=e.computed(()=>r.connected&&r.playing),i=e.computed(()=>a.value?"#2ea043":r.connected?"#8b949e":"#f85149"),l=()=>{n.skipPlayback()};return(c,u)=>(e.openBlock(),e.createElementBlock("div",wo,[a.value?(e.openBlock(),e.createBlock(Je,{key:0,color:"#2ea043",height:13})):(e.openBlock(),e.createElementBlock("span",{key:1,class:e.normalizeClass(["szjyv-caption-dot",{offline:!r.connected}]),style:e.normalizeStyle({background:i.value})},null,6)),(e.openBlock(),e.createElementBlock("span",{key:r.caption??"idle",class:"szjyv-caption-text"},e.toDisplayString(r.caption??(r.connected?"voice ready":"voice offline")),1)),r.playing?(e.openBlock(),e.createElementBlock("button",{key:2,class:"szjyv-skip",onClick:l},"skip")):e.createCommentVNode("",!0)]))}}),So={class:"panel-header"},bo={class:"header-actions"},Eo={class:"header-title"},Co={class:"action-icons"},vo={class:"body-content"},Ao={key:0,class:"welcome-content"},To={class:"subtitle"},No={class:"highlight"},Vo={class:"quick-questions"},Bo=["onClick"],Ro={key:1,class:"message-content user-content"},_o={key:0,class:"ai-thinking-indicator"},Lo={key:1,class:"ai-failed-tip"},xo={class:"panel-footer"},Uo={key:0,class:"voice-progress-banner"},Po={class:"progress-info"},Mo={class:"progress-text"},zo={key:0,class:"progress-percent"},jo={key:0,class:"progress-track"},Io={class:"recording-main"},Oo={class:"recording-status"},Do={key:0,class:"recording-time"},$o={class:"recording-hint"},Fo={key:1,class:"volume-waves"},Ho={class:"recording-actions"},qo=["title"],Wo={key:0,class:"voice-playback-bar"},Go=["title"],Jo={class:"playback-play-icon"},Ko={key:0,viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},Yo={key:1,viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},Xo={class:"playback-title"},Zo={key:0,class:"playback-time"},Qo={key:1,class:"playback-waves"},er={class:"input-box"},tr={class:"input-actions-box"},nr=["src"],Gt={__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},enableDuplexVoice:{type:Boolean,default:!1},voiceApiBase:{type:String,default:""},enableVoiceTts:{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:r}=e.getCurrentInstance(),{$message:o}=r.config.globalProperties,s=t;let a=null;const i=e.ref("idle"),l=e.ref(""),c=e.ref(0),u=e.ref(0),f=e.ref(0);let V=null;const A=e.ref(""),g=e.ref(!1),C=e.ref(0);let T=null;const _=e.ref(""),S=e.ref(""),d=e.computed(()=>i.value==="downloading"),E=e.computed(()=>i.value==="loading"),y=e.computed(()=>i.value==="recording"),m=e.computed(()=>i.value==="transcribing"),B=e.computed(()=>y.value?"正在录音,点击完成后开始识别":_.value?"正在流式转写...":"正在识别语音中..."),R=e.computed(()=>s.enableVoiceInput?"请输入您的问题或点击麦克风语音输入":s.enableVoiceUpload?"请输入您的问题或上传音频识别":"请输入您的问题"),O=(w,b)=>{const U=(w||"").trim(),H=(b||"").trim();return H?U?/[A-Za-z0-9]$/.test(U)&&/[A-Za-z0-9]/.test(H.charAt(0))?`${U} ${H}`:`${U}${H}`:H:U},x=w=>{const b=Math.floor(w/60),U=w%60;return`${b.toString().padStart(2,"0")}:${U.toString().padStart(2,"0")}`},M=()=>(a||(a=new vt({soundBaseUrl:s.soundBaseUrl||"/sounds/",workerUrl:s.workerUrl||void 0,onStatusChange:(w,b)=>{i.value=w,b&&(l.value=b)},onProgress:w=>{typeof w.progress=="number"&&(c.value=w.progress)},onVolumeChange:w=>{u.value=w},onAudioRecorded:w=>{A.value&&URL.revokeObjectURL(A.value),A.value=w,C.value=f.value},onPartial:w=>{_.value=w||"",h.value=O(S.value,w)},onResult:w=>{_.value=w||"",h.value=O(S.value,w),w?o.success("语音识别完成"):o.warning("未能识别出有效语音,请重试"),setTimeout(()=>{_.value="",L.value&&L.value.focus()},100)},onError:w=>{o.error(w||"语音输入服务出错"),D()}})),a),N=()=>{D(),f.value=0,V=setInterval(()=>{f.value+=1},1e3)},D=()=>{V&&(clearInterval(V),V=null)},X=async()=>{if(!s.enableVoiceInput)return;if(y.value){await q();return}g.value&&T&&(T.pause(),g.value=!1);const w=M();try{S.value=h.value,_.value="",N(),await w.startRecording()}catch(b){D(),console.error("启动录音失败:",b)}},q=async()=>{D(),a&&await a.stopAndTranscribe()},Z=e.ref(null),ee=()=>{s.enableVoiceUpload&&Z.value&&(Z.value.value="",Z.value.click())},G=async w=>{var se;if(!s.enableVoiceUpload)return;const b=w.target,U=(se=b==null?void 0:b.files)==null?void 0:se[0];if(!U)return;g.value&&T&&(T.pause(),g.value=!1);const H=M();try{S.value=h.value,_.value="",o.info(`正在流式识别文件: ${U.name}`),await H.transcribeFile(U)}catch(Y){o.error(`文件识别失败: ${Y.message||Y}`)}},ne=()=>{D(),_.value="",h.value=S.value,a&&a.cancelRecording()},re=()=>{_.value="",h.value=S.value,a&&a.cancelTranscribe(),o.info("已取消本次语音识别")},ae=()=>{if(A.value){if(g.value&&T){T.pause(),g.value=!1;return}T&&(T.pause(),T=null),T=new Audio(A.value),T.onloadedmetadata=()=>{T&&!isNaN(T.duration)&&(C.value=Math.round(T.duration))},T.onended=()=>{g.value=!1},T.onerror=()=>{g.value=!1,o.error("音频试听播放失败")},T.play().then(()=>{g.value=!0}).catch(w=>{console.error("音频播放出错:",w),g.value=!1})}},oe=()=>{T&&(T.pause(),T=null),g.value=!1,A.value&&(URL.revokeObjectURL(A.value),A.value="")};e.onBeforeUnmount(()=>{D(),oe(),a&&(a.destroy(),a=null)});const fe=e.computed(()=>nt.find(w=>w.modelName===s.llmName)??nt.find(w=>w.modelName==="szjy")),$=n,h=e.ref(""),L=e.ref(null),I=e.ref(!1),z=e.ref([]),W=e.ref(["什么是AI助理,能做什么?","当前项目的基本情况?","当前项目的进度情况?","当前项目的参建方有哪些?","数智建管平台有哪些功能?能做什么?"]),P=e.ref([]),J=e.ref(!1),k=e.ref(null),v=()=>{e.nextTick(()=>{if(k.value){const w=k.value,b=w.scrollHeight,U=w.scrollTop,H=w.clientHeight;b-U-H<100?w.scrollTop=b:w.scrollTo({top:b})}})},F=e.ref(!1),K=e.ref(!1),Q=e.ref("");let le="";const wr=e.computed(()=>F.value?"/images/ai-stop.png":"/images/ai-send.png"),on=(w,b)=>{var ce;console.log("onFailedReader",w,b),Ce(),J.value=!1,K.value=!1;const U=Xe();U&&U.initializeEnd();const H=z.value[w],se=P.value[w],Y=((ce=se==null?void 0:se.getRawText)==null?void 0:ce.call(se))||"";H&&H.type==="ai"&&!H.displayText&&!Y&&z.value.splice(w,1),Q.value=le,F.value=!1,v(),setTimeout(()=>{L.value&&L.value.focus()})},Sr=w=>{K.value=!1},br=(w,b)=>{J.value=!1,F.value=!1,K.value=!1,v(),Vr(w,b),b&&z.value[w]&&(z.value[w].displayText=b),setTimeout(()=>{L.value&&L.value.focus()})},Er=w=>{F.value=!0,Nr(w)},Cr=()=>{F.value=!1,K.value=!1,Q.value="",$("update:modelValue",!1),I.value=!1,z.value=[]},Ye=e.ref(!1),vr=()=>{Ye.value=!Ye.value},Ar=w=>{h.value=w,Be()},Xe=()=>{for(let w=P.value.length-1;w>=0;w--)if(P.value[w])return P.value[w];return null},Be=async()=>{if(console.log("stylizingLoading:",J.value),J.value){K.value=!1;const b=Xe();console.log("lastPreviewer:",b),b&&(console.log("abortReader"),b.abortReader());return}if(!h.value.trim()){console.log("no input, return"),L.value.focus();return}z.value.push({type:"user",content:h.value}),F.value=!0,I.value=!0,Q.value="",$("submit",h.value),v();const w=h.value;le=w,h.value="",await rn(w)},Tr=async()=>{const w=Q.value;!w||J.value||(Q.value="",le=w,F.value=!0,v(),await rn(w))},rn=async w=>{const b=z.value.length;P.value[b]&&P.value[b].initializeStart(),J.value=!0,K.value=!0,z.value.push({type:"ai"});const{error:U,reader:H}=await vn(fe.value,{text:w,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),on(b,U);return}H&&(z.value[b].reader=H)};let ke=null,me=0,an=0;const Ze=e.ref(s.enableVoiceTts);e.watch(()=>s.enableVoiceTts,w=>{Ze.value=w,w||Ce()});const Ce=()=>{me=0},Nr=w=>{if(!ke)return;const b=P.value[w];if(!b||!b.getRawText)return;const U=b.getRawText()||"";if(!Ze.value){U.length>me&&(me=U.length);return}const H=Date.now();U.length>me&&H-an>250&&(ke(U.slice(me),!1),me=U.length,an=H)},Vr=(w,b)=>{if(!ke)return;if(!Ze.value){Ce();return}const U=P.value[w];if(U&&U.isAborted&&U.isAborted()){Ce();return}const H=b||(U&&U.getRawText?U.getRawText():"")||"";H.length>me&&ke(H.slice(me),!1),ke("",!0),Ce()};if(s.enableDuplexVoice){const w="chat-voice-"+Date.now().toString(36)+Math.random().toString(36).slice(2,8),{speak:b}=Ft({apiBase:s.voiceApiBase||void 0,sessionId:w,running:e.computed(()=>F.value),onTranscript:U=>{h.value=O(h.value,U)},onSubmit:()=>{Be()},onCancelTurn:()=>{const U=Xe();U&&U.abortReader()}});ke=b}return(w,b)=>{const U=e.resolveComponent("el-icon"),H=e.resolveComponent("el-button"),se=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":Ye.value,"embedded-mode":t.embedded}])},[e.createElementVNode("div",So,[e.createElementVNode("div",bo,[e.createElementVNode("div",Eo,e.toDisplayString(t.title),1),e.createElementVNode("div",Co,[t.embedded?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(U,{key:0,class:"action-icon",onClick:vr},{default:e.withCtx(()=>[e.createVNode(Ae,{name:"/images/svg/drawer-layout.svg",color:"#999999"})]),_:1})),e.createVNode(U,{class:"action-icon",onClick:Cr},{default:e.withCtx(()=>[e.createVNode(Ae,{name:"/images/svg/close.svg",color:"#999999"})]),_:1})])])]),e.createElementVNode("div",vo,[I.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:"chat-messages",ref_key:"messageContainerRef",ref:k},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(z.value,(Y,ce)=>(e.openBlock(),e.createElementBlock("div",{key:ce,class:e.normalizeClass(["message-item",Y.type==="user"?"user-message":"ai-message"])},[Y.type==="ai"?(e.openBlock(),e.createBlock(Xn,{key:0,ref_for:!0,ref:ue=>P.value[ce]=ue,reader:Y.reader,"onUpdate:reader":ue=>Y.reader=ue,model:s.llmName,displayText:Y.displayText,scrollToBottomFn:v,messagePostRender:t.messagePostRender,customUi:t.customUi,uiActionHandler:t.uiActionHandler,onFailed:ue=>on(ce,ue),onStarted:()=>Sr(),onCompleted:ue=>br(ce,ue),onUpdating:()=>Er(ce),onUiAction:b[0]||(b[0]=ue=>$("ui-action",ue))},null,8,["reader","onUpdate:reader","model","displayText","messagePostRender","customUi","uiActionHandler","onFailed","onStarted","onCompleted","onUpdating"])):(e.openBlock(),e.createElementBlock("div",Ro,e.toDisplayString(Y.content),1))],2))),128)),e.createVNode(e.Transition,{name:"ai-status-fade"},{default:e.withCtx(()=>[K.value?(e.openBlock(),e.createElementBlock("div",_o,[...b[4]||(b[4]=[e.createElementVNode("img",{src:ln,alt:"AI思考中",class:"thinking-icon"},null,-1),e.createElementVNode("img",{src:cn,alt:"",class:"thinking-loading-icon"},null,-1),e.createElementVNode("span",{class:"thinking-text"},"正在努力思考中~",-1)])])):Q.value?(e.openBlock(),e.createElementBlock("div",Lo,[b[5]||(b[5]=e.createElementVNode("span",{class:"failed-text"},"网络问题请重试",-1)),e.createElementVNode("button",{class:"retry-btn",onClick:Tr},"重试")])):e.createCommentVNode("",!0)]),_:1})],512)):(e.openBlock(),e.createElementBlock("div",Ao,[b[3]||(b[3]=e.createElementVNode("div",{class:"title"},[e.createElementVNode("img",{src:sn,alt:"AI助手",class:"panel-icon"}),e.createElementVNode("h3",{class:"title-text"},"Hi, 您好")],-1)),e.createElementVNode("div",To,[b[2]||(b[2]=e.createTextVNode(" 我是",-1)),e.createElementVNode("span",No,e.toDisplayString(t.title),1)]),e.createElementVNode("div",Vo,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(W.value,(Y,ce)=>(e.openBlock(),e.createElementBlock("div",{key:ce,class:"question-item",onClick:ue=>Ar(Y)},[e.createElementVNode("span",null,e.toDisplayString(Y),1),e.createVNode(U,null,{default:e.withCtx(()=>[e.createVNode(Ae,{name:"/images/svg/arrow-right.svg",color:"#999999"})]),_:1})],8,Bo))),128))])]))]),e.createElementVNode("div",xo,[e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[d.value||E.value?(e.openBlock(),e.createElementBlock("div",Uo,[e.createElementVNode("div",Po,[b[6]||(b[6]=e.createElementVNode("span",{class:"progress-icon"},"⏳",-1)),e.createElementVNode("span",Mo,e.toDisplayString(l.value),1),c.value>0?(e.openBlock(),e.createElementBlock("span",zo,e.toDisplayString(c.value)+"%",1)):e.createCommentVNode("",!0)]),c.value>0?(e.openBlock(),e.createElementBlock("div",jo,[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(()=>[y.value||m.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["voice-recording-panel",{"has-transcript":m.value}])},[e.createElementVNode("div",Io,[e.createElementVNode("div",Oo,[e.createElementVNode("span",{class:e.normalizeClass(["recording-pulse",{transcribing:m.value}])},null,2),y.value?(e.openBlock(),e.createElementBlock("span",Do,e.toDisplayString(x(f.value)),1)):e.createCommentVNode("",!0),e.createElementVNode("span",$o,e.toDisplayString(B.value),1),y.value?(e.openBlock(),e.createElementBlock("div",Fo,[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",Ho,[y.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createVNode(H,{size:"small",circle:"",onClick:ne,title:"取消录音",class:"voice-cancel-btn"},{default:e.withCtx(()=>[...b[7]||(b[7]=[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(H,{type:"primary",size:"small",round:"",onClick:q,class:"voice-finish-btn"},{default:e.withCtx(()=>[...b[8]||(b[8]=[e.createTextVNode(" 完成 ",-1)])]),_:1})],64)):m.value?(e.openBlock(),e.createBlock(H,{key:1,size:"small",round:"",onClick:re,class:"voice-cancel-transcribe-btn"},{default:e.withCtx(()=>[...b[9]||(b[9]=[e.createTextVNode(" 取消识别 ",-1)])]),_:1})):e.createCommentVNode("",!0)])]),m.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),b[10]||(b[10]=e.createElementVNode("span",{class:"caret"},"|",-1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode("正在识别,文字将实时显示...")],64))],10,qo)):e.createCommentVNode("",!0)],2)):e.createCommentVNode("",!0)]),_:1}),e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[A.value&&!y.value&&!m.value?(e.openBlock(),e.createElementBlock("div",Wo,[e.createElementVNode("div",{class:"playback-main",onClick:ae,title:g.value?"点击暂停":"点击播放录音"},[e.createElementVNode("div",Jo,[g.value?(e.openBlock(),e.createElementBlock("svg",Yo,[...b[12]||(b[12]=[e.createElementVNode("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"},null,-1)])])):(e.openBlock(),e.createElementBlock("svg",Ko,[...b[11]||(b[11]=[e.createElementVNode("path",{d:"M8 5v14l11-7z"},null,-1)])]))]),e.createElementVNode("span",Xo,e.toDisplayString(g.value?"正在播放录音...":"点击试听本次录音"),1),C.value>0?(e.openBlock(),e.createElementBlock("span",Zo,e.toDisplayString(x(C.value)),1)):e.createCommentVNode("",!0),g.value?(e.openBlock(),e.createElementBlock("div",Qo,[...b[13]||(b[13]=[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,Go),e.createElementVNode("div",{class:"playback-close",onClick:oe,title:"清除试听"},[...b[14]||(b[14]=[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",er,[e.createVNode(se,{modelValue:h.value,"onUpdate:modelValue":b[1]||(b[1]=Y=>h.value=Y),ref_key:"refInputTextString",ref:L,placeholder:R.value,autofocus:"",onKeyup:e.withKeys(Be,["enter"])},{append:e.withCtx(()=>[e.createElementVNode("div",tr,[t.enableVoiceUpload?(e.openBlock(),e.createElementBlock("div",{key:0,class:"voice-upload-btn",onClick:ee,title:"上传音频/视频文件识别 (支持 .wav, .mp4, .mp3, .m4a)"},[...b[15]||(b[15]=[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:Z,accept:"audio/*,video/mp4,.wav,.mp4,.mp3,.m4a",style:{display:"none"},onChange:G},null,544)):e.createCommentVNode("",!0),t.enableVoiceInput?(e.openBlock(),e.createElementBlock("div",{key:2,class:e.normalizeClass(["voice-mic-btn",{"loading-anim":d.value||E.value}]),onClick:X,title:"语音输入"},[...b[16]||(b[16]=[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),t.enableDuplexVoice?(e.openBlock(),e.createBlock(e.unref(qt),{key:3})):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"send-icon-box",onClick:Be},[e.createElementVNode("img",{src:wr.value,alt:"发送",class:"send-icon"},null,8,nr)])])]),_:1},8,["modelValue","placeholder"])],512),[[e.vShow,!y.value&&!m.value]]),t.enableDuplexVoice?(e.openBlock(),e.createBlock(e.unref(Wt),{key:0})):e.createCommentVNode("",!0)])],2)):e.createCommentVNode("",!0)]),_:1})}}};var Jt={exports:{}};(function(t,n){(function(r,o){t.exports=o()})(window,function(){return function(r){var o={};function s(a){if(o[a])return o[a].exports;var i=o[a]={i:a,l:!1,exports:{}};return r[a].call(i.exports,i,i.exports,s),i.l=!0,i.exports}return s.m=r,s.c=o,s.d=function(a,i,l){s.o(a,i)||Object.defineProperty(a,i,{enumerable:!0,get:l})},s.r=function(a){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},s.t=function(a,i){if(1&i&&(a=s(a)),8&i||4&i&&typeof a=="object"&&a&&a.__esModule)return a;var l=Object.create(null);if(s.r(l),Object.defineProperty(l,"default",{enumerable:!0,value:a}),2&i&&typeof a!="string")for(var c in a)s.d(l,c,(function(u){return a[u]}).bind(null,c));return l},s.n=function(a){var i=a&&a.__esModule?function(){return a.default}:function(){return a};return s.d(i,"a",i),i},s.o=function(a,i){return Object.prototype.hasOwnProperty.call(a,i)},s.p="",s(s.s=0)}([function(r,o,s){function a(S,d,E,y){E.push(S),y.push([].concat(d[S]||[]))}function i(S,d){if(!S)throw new Error("[getMaxDepsChain] dep 参数不能为空");var E=[],y=[],m=[];for(a(S,d,y,m);y.length;){var B=m.pop();if(B&&B.length){var R=B.shift();if(m.push(B),~y.indexOf(R))throw new Error("[getMaxDepsChain][loop] 存在循环依赖,请检查依赖关系; nextName: "+R+", mainStack: "+y);a(R,d,y,m)}else E.push([].concat(y)),y.pop()}return E.reduce(function(O,x){return x.length>O.length?x:O},[])}function l(S){if(!S)throw new Error("[depsParser] 入参不能为空");var d={};S.forEach(function(y){d[y.name]=y.deps||[]});var E=[];return S.forEach(function(y){var m=i(y.name,d).length-1;y.priority=m,E[m]=(E[m]||[]).concat(y)}),E}s.r(o),s.d(o,"loadScript",function(){return A}),s.d(o,"loadScripts",function(){return g}),s.d(o,"dynamicLoadScripts",function(){return C}),s.d(o,"createScriptsLoadIterator",function(){return T}),s.d(o,"loadScriptsQueue",function(){return _}),s.d(o,"getMaxDepsChain",function(){return i}),s.d(o,"depsParser",function(){return l});var c=function(){return(c=Object.assign||function(S){for(var d,E=1,y=arguments.length;E<y;E++)for(var m in d=arguments[E])Object.prototype.hasOwnProperty.call(d,m)&&(S[m]=d[m]);return S}).apply(this,arguments)},u=function(S,d,E,y){return new(E||(E=Promise))(function(m,B){function R(M){try{x(y.next(M))}catch(N){B(N)}}function O(M){try{x(y.throw(M))}catch(N){B(N)}}function x(M){var N;M.done?m(M.value):(N=M.value,N instanceof E?N:new E(function(D){D(N)})).then(R,O)}x((y=y.apply(S,[])).next())})},f=function(S,d){var E,y,m,B,R={label:0,sent:function(){if(1&m[0])throw m[1];return m[1]},trys:[],ops:[]};return B={next:O(0),throw:O(1),return:O(2)},typeof Symbol=="function"&&(B[Symbol.iterator]=function(){return this}),B;function O(x){return function(M){return function(N){if(E)throw new TypeError("Generator is already executing.");for(;R;)try{if(E=1,y&&(m=2&N[0]?y.return:N[0]?y.throw||((m=y.return)&&m.call(y),0):y.next)&&!(m=m.call(y,N[1])).done)return m;switch(y=0,m&&(N=[2&N[0],m.value]),N[0]){case 0:case 1:m=N;break;case 4:return R.label++,{value:N[1],done:!1};case 5:R.label++,y=N[1],N=[0];continue;case 7:N=R.ops.pop(),R.trys.pop();continue;default:if(m=R.trys,!((m=m.length>0&&m[m.length-1])||N[0]!==6&&N[0]!==2)){R=0;continue}if(N[0]===3&&(!m||N[1]>m[0]&&N[1]<m[3])){R.label=N[1];break}if(N[0]===6&&R.label<m[1]){R.label=m[1],m=N;break}if(m&&R.label<m[2]){R.label=m[2],R.ops.push(N);break}m[2]&&R.ops.pop(),R.trys.pop();continue}N=d.call(S,R)}catch(D){N=[6,D],y=0}finally{E=m=0}if(5&N[0])throw N[1];return{value:N[0]?N[1]:void 0,done:!0}}([x,M])}}},V=function(S){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var d,E=S[Symbol.asyncIterator];return E?E.call(S):(S=typeof __values=="function"?__values(S):S[Symbol.iterator](),d={},y("next"),y("throw"),y("return"),d[Symbol.asyncIterator]=function(){return this},d);function y(m){d[m]=S[m]&&function(B){return new Promise(function(R,O){(function(x,M,N,D){Promise.resolve(D).then(function(X){x({value:X,done:N})},M)})(R,O,(B=S[m](B)).done,B.value)})}}};function A(S,d){return d===void 0&&(d=!1),new Promise(function(E,y){var m=d?document.head:document.body,B=document.createElement("script");B.type="text/javascript",B.src=S,B.crossOrigin="anonymous",B.onreadystatechange=E,B.onload=E,B.onerror=y,m.appendChild(B)})}var g=function(S,d){return d===void 0&&(d={}),u(void 0,void 0,void 0,function(){var E,y,m,B,R;return f(this,function(O){switch(O.label){case 0:return E=d.baseUrl,y=E===void 0?"":E,m=d.lastLoadResult,B=d.inHead,R=B!==void 0&&B,[4,Promise.all(S.map(function(x){return u(void 0,void 0,void 0,function(){var M,N,D,X,q,Z,ee,G;return f(this,function(ne){switch(ne.label){case 0:return M=x.name,N=x.path,D=x.deps,(ee={})[M]=!0,X=ee,(G={})[M]=!1,q=G,window[M]?[2,X]:[3,1];case 1:return Z=!0,D&&m&&[].concat(D).forEach(function(re){m[re]!==!1&&(Z=!0)}),Z?[4,A(N.indexOf("http")===0||N.indexOf("//:")===0?N:y+N,R).then(function(){return X}).catch(function(){return q})]:[3,3];case 2:return[2,ne.sent()];case 3:return[2,q]}})})}))];case 1:return[2,O.sent()]}})})},C=function(S,d){return d===void 0&&(d={}),function(){var E=[].concat(l(S));return{next:function(){if(E.length){var y=E.shift();return g(y,d).then(function(m){return{value:m,done:!1}})}return Promise.resolve({done:!0})}}}},T=function(S,d){var E;return d===void 0&&(d={}),(E={})[Symbol.asyncIterator]=C(S,d),E},_=function(S,d){return d===void 0&&(d={}),u(void 0,void 0,void 0,function(){var E,y,m,B,R,O;return f(this,function(x){switch(x.label){case 0:x.trys.push([0,5,6,11]),E=V(T(S,d)),x.label=1;case 1:return[4,E.next()];case 2:if((y=x.sent()).done)return[3,4];m=y.value,d.lastLoadResult=d.lastLoadResult||{},console.log("current load: ",m),m.forEach(function(M){d.lastLoadResult=c(c({},d.lastLoadResult),M)}),x.label=3;case 3:return[3,1];case 4:return[3,11];case 5:return B=x.sent(),R={error:B},[3,11];case 6:return x.trys.push([6,,9,10]),y&&!y.done&&(O=E.return)?[4,O.call(E)]:[3,8];case 7:x.sent(),x.label=8;case 8:return[3,10];case 9:if(R)throw R.error;return[7];case 10:return[7];case 11:return[2,d.lastLoadResult]}})})}}])})})(Jt);var or=Jt.exports;function Kt(){const t=[{name:"markdownit",path:"markdown-it.min.js"},{name:"hljs",path:"highlight.11.11.1.min.js"}];let n={};or.loadScriptsQueue(t,{baseUrl:"/scripts/ai/",lastLoadResult:n,inHead:!1}).then(r=>{if(console.log("load ai deps: ",r),window.markdownit){const o=window.markdownit();console.log("markdownit: ",o),$n()}})}const rr={key:0,class:"ai-assistant"},ar={name:"AiChat"},Yt=e.defineComponent({...ar,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},enableDuplexVoice:{type:Boolean,default:!1},voiceApiBase:{type:String,default:""},enableVoiceTts:{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 r=e.ref(!1),o=e.ref(!1),s=n,a=()=>{r.value=!r.value},i=()=>{o.value=!0,r.value=!1},l=c=>{console.log("用户输入:",c)};return Kt(),(c,u)=>o.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",rr,[e.createVNode(Gt,{modelValue:r.value,"onUpdate:modelValue":u[0]||(u[0]=f=>r.value=f),onSubmit:l,onUiAction:u[1]||(u[1]=f=>s("ui-action",f)),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,enableDuplexVoice:t.enableDuplexVoice,voiceApiBase:t.voiceApiBase,enableVoiceTts:t.enableVoiceTts,enableVoiceUpload:t.enableVoiceUpload},null,8,["modelValue","token","identifier","baseUrl","title","llmName","messagePostRender","extraConfig","customUi","uiActionHandler","mockResponse","soundBaseUrl","workerUrl","enableVoiceInput","enableDuplexVoice","voiceApiBase","enableVoiceTts","enableVoiceUpload"]),e.createElementVNode("div",{class:"ai-icon",onClick:a},[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:he,alt:"AI助手"},null,-1)),u[4]||(u[4]=e.createElementVNode("span",{class:"ai-icon-text"},"AI助手",-1))])]))}}),sr={class:"ai-chat-plain"},ir={name:"AiChatPlain"},Xt=e.defineComponent({...ir,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},enableDuplexVoice:{type:Boolean,default:!1},voiceApiBase:{type:String,default:""},enableVoiceTts:{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 r=n;return Kt(),(o,s)=>(e.openBlock(),e.createElementBlock("div",sr,[e.createVNode(Gt,{"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,enableDuplexVoice:t.enableDuplexVoice,voiceApiBase:t.voiceApiBase,enableVoiceTts:t.enableVoiceTts,enableVoiceUpload:t.enableVoiceUpload,embedded:!0,onSubmit:s[0]||(s[0]=a=>r("submit",a)),onUiAction:s[1]||(s[1]=a=>r("ui-action",a))},null,8,["token","identifier","baseUrl","title","llmName","messagePostRender","extraConfig","customUi","uiActionHandler","mockResponse","soundBaseUrl","workerUrl","enableVoiceInput","enableDuplexVoice","voiceApiBase","enableVoiceTts","enableVoiceUpload"])]))}}),Zt=Object.freeze(Object.defineProperty({__proto__:null,SzAiChat:Yt,SzAiChatPlain:Xt},Symbol.toStringTag,{value:"Module"})),Ke=function(t){if(!Ke.installed){Ke.installed=!0;for(let n in Zt){const r=Reflect.get(Zt,n);t.component(r.name,r)}}},lr=(t,n)=>{const r=n?`?${new URLSearchParams(n).toString()}`:"";console.log(`点击了路由链接: ${t}${r}`)},Qt=t=>{const n=t.indexOf("?");if(n===-1)return{routeName:t};const r=t.substring(0,n),o=t.substring(n+1),s={};return new URLSearchParams(o).forEach((i,l)=>{s[l]=i}),{routeName:r,queryParams:Object.keys(s).length>0?s:void 0}},cr={color:"#536fec",fontWeight:"bold",textDecoration:"underline",cursor:"pointer",padding:"0 3px"},en=t=>{const n=/#router:([^#]+)#/g,r=[];let o=0,s;for(;(s=n.exec(t))!==null;){s.index>o&&r.push({text:t.substring(o,s.index)});const a=s[1],{routeName:i,queryParams:l}=Qt(a);r.push({text:i,routeName:i,queryParams:l}),o=n.lastIndex}return o<t.length&&r.push({text:t.substring(o)}),r},tn=(t,n,r={},o)=>{const{onRouteClick:s=lr,linkStyle:a={}}=r,i=document.createElement("a");i.href="#",i.textContent=t;const l={...cr,...a};return Object.assign(i.style,l),i.addEventListener("click",c=>{c.preventDefault(),s(n,o)}),i},nn=t=>{const n=/#router:([^#]+)#/g,r=[],o=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,null);let s=o.nextNode();for(;s;){const a=s,i=a.textContent||"";if(n.test(i)){n.lastIndex=0;const l=en(i);l.length>0&&r.push({node:a,replacements:l})}s=o.nextNode()}return r},ur=(t,n,r={})=>{const o=nn(t);o.forEach(({node:s,replacements:a})=>{var l;const i=document.createDocumentFragment();a.forEach(({text:c,routeName:u,queryParams:f})=>{if(u){const V=tn(c,u,r,f);i.appendChild(V)}else i.appendChild(document.createTextNode(c))}),(l=s.parentNode)==null||l.replaceChild(i,s)}),r!=null&&r.nodeCallback&&o.forEach(({node:s,replacements:a})=>{var i;(i=r.nodeCallback)==null||i.call(r,s,a)})},Ee="szjy-voice-models",Ne="szjy-voice-cache-v1";function ye(){return typeof navigator<"u"&&!!navigator.storage&&typeof navigator.storage.getDirectory=="function"}async function Ve(t=Ee){if(!ye())return null;try{return await(await navigator.storage.getDirectory()).getDirectoryHandle(t,{create:!0})}catch(n){return console.warn("[OPFS] 获取目录失败,将使用降级缓存:",n),null}}async function dr(t,n,r=Ee){if(ye())try{const o=await Ve(r);if(o){const a=await(await o.getFileHandle(t,{create:!0})).createWritable();return await a.write(n),await a.close(),!0}}catch(o){console.warn(`[OPFS] 写入文件 ${t} 失败:`,o)}if(typeof caches<"u")try{const o=await caches.open(Ne),s=new Response(n,{headers:{"Content-Type":"application/octet-stream"}});return await o.put(`/${r}/${t}`,s),!0}catch(o){console.warn(`[CacheStorage] 缓存写入 ${t} 失败:`,o)}return!1}async function fr(t,n=Ee){if(ye())try{const r=await Ve(n);if(r)return await(await(await r.getFileHandle(t,{create:!1})).getFile()).arrayBuffer()}catch{}if(typeof caches<"u")try{const o=await(await caches.open(Ne)).match(`/${n}/${t}`);if(o)return await o.arrayBuffer()}catch{}return null}async function mr(t,n=Ee){if(ye())try{const r=await Ve(n);if(r)return(await(await r.getFileHandle(t,{create:!1})).getFile()).size>0}catch{}if(typeof caches<"u")try{return!!await(await caches.open(Ne)).match(`/${n}/${t}`)}catch{}return!1}async function hr(t=Ee){let n=!1;if(ye())try{await(await navigator.storage.getDirectory()).removeEntry(t,{recursive:!0}),n=!0,console.log(`[OPFS] 成功清空语音模型缓存目录: ${t}`)}catch(r){r.name==="NotFoundError"?n=!0:console.warn(`[OPFS] 清理目录 ${t} 异常:`,r)}if(typeof caches<"u")try{const r=await caches.keys();for(const o of r)(o.includes("transformers")||o.includes("szjy-voice")||o===Ne)&&(await caches.delete(o),n=!0)}catch(r){console.warn("[CacheStorage] 清除缓存异常:",r)}return n}const pr="0.1.17",gr="Sz";function yr({componentPrefix:t=gr,components:n=[]}={}){const r=[];function o(a,i,l){a.component(t+i)||a.component(t+i,l)}function s(a){r.includes(a)||(r.push(a),n.forEach(i=>{const{name:l,alias:c}=i;o(a,l,i),c&&c.forEach(u=>{o(a,u,i)})}))}return{version:pr,componentPrefix:t,install:s}}const kr={install(t){Ke(t)}};p.AEC_DEFAULTS=no,p.AudioRecorder=wt,p.BUFFER_SIZE=$e,p.CANCEL_DRAG_PX=Ut,p.DEFAULT_BASE_PATH=Te,p.DEFAULT_MOCK_RESPONSE=et,p.DEFAULT_WHISPER_WORKER_URL=ze,p.ENERGY_THRESHOLD=Ie,p.EqualizerBars=Je,p.HOLD_THRESHOLD_MS=Lt,p.KEY_HOLD_THRESHOLD_MS=xt,p.LEVEL_CEILING=At,p.MAX_SEGMENT_MS=Oe,p.MIN_HOLD_SEGMENT_S=Vt,p.NlmsAec=Pt,p.PARTIAL_INTERVAL_MS=Bt,p.PARTIAL_MAX_S=_t,p.PARTIAL_MIN_S=Rt,p.POST_PAD_MS=De,p.PRE_PAD_MS=Nt,p.SAMPLE_RATE=de,p.SILENCE_TIMEOUT_MS=Tt,p.SZJY_UI_FENCE_LANG=pt,p.StreamResampler=kt,p.SzAiChat=Yt,p.SzAiChatPlain=Xt,p.VOICE_CONTEXT_KEY=We,p.VoiceCaptionBar=Wt,p.VoiceInputManager=vt,p.VoiceMicButton=qt,p.VoiceOverlay=Ht,p.WAVE_BARS=Fe,p.bindSzjyUiEvents=yt,p.clearVoiceModelCache=hr,p.create=yr,p.createAsrEngine=It,p.createMockStylized=tt,p.createPlaybackEngine=Dt,p.createRouteLink=tn,p.decodeAudioFile=bt,p.default=kr,p.escapeHtml=pe,p.findRouteTextNodes=nn,p.float32ToWav=Me,p.getConfig=zt,p.getFileFromCache=fr,p.getOPFSDirectory=Ve,p.getReady=Mt,p.getSzjyUiAction=lt,p.getSzjyUiComponent=st,p.hasFileInCache=mr,p.hasSzjyUiAction=ct,p.hasSzjyUiComponent=it,p.isOPFSSupported=ye,p.micErrorMessage=Ot,p.openAudioStream=jt,p.parseRouteMarkerContent=Qt,p.parseRouteMarkers=en,p.parseSzjyUiFence=gt,p.postAsr=io,p.postCancel=He,p.registerSzjyUiAction=at,p.registerSzjyUiComponent=Ue,p.renderActionAttrs=dt,p.renderSzjyUiBlock=ut,p.renderSzjyUiNode=Pe,p.resampleAudioData=St,p.routeLinkRender=ur,p.saveFileToCache=dr,p.useVoice=Ft,p.useVoiceContext=Ge,Object.defineProperties(p,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
@@ -0,0 +1,17 @@
1
+ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
2
+ color: string;
3
+ height?: number;
4
+ }>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
5
+ color: string;
6
+ height?: number;
7
+ }>>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
8
+ export default _default;
9
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
10
+ type __VLS_TypePropsToRuntimeProps<T> = {
11
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
12
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
13
+ } : {
14
+ type: import('vue').PropType<T[K]>;
15
+ required: true;
16
+ };
17
+ };
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,29 @@
1
+ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
2
+ levels: number[];
3
+ armedCancel: boolean;
4
+ /** Released, waiting on the authoritative transcript from the host. */
5
+ pending: boolean;
6
+ /** Interim transcript of the capture so far ('' until the first one lands). */
7
+ partial: string;
8
+ source: "pointer" | "key";
9
+ hotkey: string;
10
+ }>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
11
+ levels: number[];
12
+ armedCancel: boolean;
13
+ /** Released, waiting on the authoritative transcript from the host. */
14
+ pending: boolean;
15
+ /** Interim transcript of the capture so far ('' until the first one lands). */
16
+ partial: string;
17
+ source: "pointer" | "key";
18
+ hotkey: string;
19
+ }>>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
20
+ export default _default;
21
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
22
+ type __VLS_TypePropsToRuntimeProps<T> = {
23
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
24
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
25
+ } : {
26
+ type: import('vue').PropType<T[K]>;
27
+ required: true;
28
+ };
29
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * NLMS (normalized least-mean-squares) acoustic echo canceller.
3
+ *
4
+ * The browser's `echoCancellation` constraint is a black box: quality varies
5
+ * by OS/browser and it cannot see what *this* page is playing. When the TTS
6
+ * voice is loud, playback bleeds into the mic and falsely trips the barge-in
7
+ * VAD. This module runs a second, explicit echo canceller on the mic signal
8
+ * using the page's own TTS output as the reference — so the canceller is
9
+ * always aligned with exactly what the assistant said, not an OS guess.
10
+ *
11
+ * Algorithm: standard NLMS with a fixed tap delay + adaptive FIR.
12
+ * y[n] = w · x[n - D .. n - D - L] (estimated echo)
13
+ * e[n] = d[n] - y[n] (clean signal)
14
+ * w += μ · e[n] · x / (‖x‖² + ε)
15
+ *
16
+ * 移植自 dsh-voice src/aec.ts(PRD 7.2)。Pure module — no Web Audio types.
17
+ */
18
+ export interface AecOptions {
19
+ /** FIR filter length (taps). Covers speaker->mic delay + early reflections. */
20
+ filterLength?: number;
21
+ /**
22
+ * Fixed delay applied to the reference before the filter, in samples.
23
+ * The speaker->mic path has a short OS/buffer latency; a fixed lead-in
24
+ * lets a shorter filter still cover the tail.
25
+ */
26
+ delay?: number;
27
+ /** Normalized step size (0 < μ < 2; ~0.1 is a safe default). */
28
+ step?: number;
29
+ /** Regularizer on the denominator to avoid div-by-zero on silence. */
30
+ epsilon?: number;
31
+ }
32
+ export declare class NlmsAec {
33
+ private readonly w;
34
+ private readonly xBuf;
35
+ private readonly filterLength;
36
+ private readonly delay;
37
+ private readonly mu;
38
+ private readonly eps;
39
+ /** Ring cursor into xBuf (reference history). */
40
+ private cursor;
41
+ /** How many reference samples we have buffered so far (for warm-up). */
42
+ private filled;
43
+ constructor(options?: AecOptions);
44
+ /**
45
+ * Push the next mic/reference block; returns the echo-removed mic samples
46
+ * (same length as the input). Reference may be shorter than the mic block
47
+ * (e.g. silence pad) — it is zero-filled to the block length.
48
+ */
49
+ process(mic: Float32Array, ref: Float32Array): Float32Array;
50
+ /** Reset adaptation (call on start/stop to avoid stale speaker->mic path). */
51
+ reset(): void;
52
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import { ReadyResponse, VoiceConfig, VoiceFrame } from './types';
2
+
3
+ export declare function getReady(base?: string, headers?: Record<string, string>): Promise<ReadyResponse>;
4
+ export declare function getConfig(base?: string, headers?: Record<string, string>): Promise<VoiceConfig>;
5
+ /**
6
+ * POST PCM 识别。
7
+ *
8
+ * - 正式识别:不带 `x-voice-session`。
9
+ * - 预览:带 `x-voice-session`,body 只发相对上次预览的增量。
10
+ * - body 必须 `float32Array.slice().buffer`:subarray().buffer 仍是整段缓冲。
11
+ */
12
+ export declare function postAsr(base: string, headers: Record<string, string> | undefined, pcm: Float32Array, previewSessionId?: string): Promise<{
13
+ text: string;
14
+ }>;
15
+ export declare function postCancel(base: string, headers: Record<string, string> | undefined, sessionId: string): Promise<{
16
+ ok: boolean;
17
+ }>;
18
+ export interface AudioStreamHandle {
19
+ close(): void;
20
+ }
21
+ export interface AudioStreamStatus {
22
+ connected: boolean;
23
+ }
24
+ /**
25
+ * 订阅 TTS SSE 流(`GET {base}/stream`,`event: audio`)。
26
+ *
27
+ * - 有自定义头(如 Authorization):fetch + ReadableStream 手工解析 SSE。
28
+ * - 无自定义头:可用 EventSource。
29
+ * - 心跳行以 `:` 开头,忽略;连接失败 3s 后重试,不打崩页面。
30
+ */
31
+ export declare function openAudioStream(base: string, headers: Record<string, string> | undefined, onFrame: (frame: VoiceFrame) => void, onStatus: (status: AudioStreamStatus) => void): AudioStreamHandle;
@@ -0,0 +1 @@
1
+ export {};