@storvia/sdk 0.10.9 → 0.10.10

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.cjs.js CHANGED
@@ -117,6 +117,6 @@
117
117
  `,Ot={success:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',error:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',warning:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',info:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>'},je=!0;function Ke(o){je=o}function Pt(){if(typeof document>"u")return null;let o=document.getElementById(ue);if(!o){if(!document.getElementById(Ve)){let e=document.createElement("style");e.id=Ve,e.textContent=At,document.head.appendChild(e)}o=document.createElement("div"),o.id=ue,document.body.appendChild(o)}return o}function oe(o,e="info",t=3500,n){if(!je)return;let r=Pt();if(!r)return;let i=t<=0,s=document.createElement("div");s.className=`storvia-toast ${e}`,s.innerHTML=`
118
118
  <span class="storvia-toast-icon">${Ot[e]}</span>
119
119
  <span class="storvia-toast-msg"></span>
120
- `;let c=s.querySelector(".storvia-toast-msg");c&&(c.textContent=o);let l=()=>{s.isConnected&&(s.classList.add("leaving"),s.classList.remove("show"),setTimeout(()=>s.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(d){console.error("[Storvia toast] action error:",d)}l()}),s.appendChild(a)}if(i){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label",he("close")),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",l),s.appendChild(a)}r.appendChild(s),requestAnimationFrame(()=>s.classList.add("show")),i||setTimeout(l,t)}function bt(o){let e=o.filter(t=>t).map(t=>`\u300C${t}\u300D`).join("");return he("violationWords").replace("{words}",e)}var Nt=3e3,He={};function We(o){let e=Date.now();if(!(e-(He[o]??0)<Nt)){if(He[o]=e,!ve){console.warn(`[Storvia] navigate \u2192 wallet(${o})\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u751F\u4EA7\u73AF\u5883\u7531\u5BBF\u4E3B\u5F39\u5145\u503C\u5F15\u5BFC / \u8DF3\u94B1\u5305\u9875\u3002`);return}try{ve(y("navigate",{target:"wallet",reason:o}))}catch(t){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",t)}}}function R(o,e,t){if(o==="GENERATION_ABORTED")return;if(o==="INSUFFICIENT_CREDITS")return We("insufficient_credits");if(o==="DAISY_CARD_REQUIRED")return We("daisy_card_required");let n=o==="VIOLATION_WORD_DETECTED"&&t?.length?bt(t):Fe(o)||e||he("unknownError");oe(n,o==="RATE_LIMITED"?"warning":"error")}function Dt(o,e){let t=e?.tickMs??100,n=e?.baseLagMs??1e3,r=e?.maxLagMs??2500,i=e?.minCharsPerTick??2,s="",c=null,l=0,a=0,d=()=>Math.min(r,Math.max(n,l*1.35)),h=()=>{let w=Math.max(i,Math.ceil(s.length*t/d()));if(w>=s.length)w=s.length;else{let _=s.charCodeAt(w-1);_>=55296&&_<=56319&&w++}let v=s.slice(0,w);s=s.slice(w),v&&o(v)},m=()=>{c=null,h(),s&&(c=setTimeout(m,t))};return{push:w=>{let v=Date.now();if(a>0){let _=Math.min(v-a,r);l=l>0?l*.7+_*.3:_}a=v,s+=w,c===null&&m()},flush:()=>{c!==null&&(clearTimeout(c),c=null),s&&(o(s),s="")},cancel:()=>{c!==null&&(clearTimeout(c),c=null),s=""}}}function Ie(o){let e=Dt(o.onChunk);return{cbs:{onChunk:n=>e.push(n),onDone:(n,r)=>{e.flush(),o.onDone(n,r)},onAborted:o.onAborted?n=>{e.flush(),o.onAborted(n)}:void 0,onState:o.onState?(n,r)=>{e.flush(),o.onState(n,r)}:void 0,onThinking:o.onThinking?n=>{e.flush(),o.onThinking(n)}:void 0,onCreatedCharacters:o.onCreatedCharacters?n=>{e.flush(),o.onCreatedCharacters(n)}:void 0,onReconnect:o.onReconnect},flush:()=>e.flush()}}var Ye="0.10.9";function G(o,e){if(e.aborted){if(o.onAborted){o.onAborted(e.aborted);return}o.onDone(e.aborted.id,{truncated:!1});return}o.onDone(e.messageId,e.truncated===void 0?void 0:{truncated:e.truncated})}var T=class T{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}ttsClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/tts"),this.token,this.debug,this.devApiKey)}asrClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/asr"),this.token,this.debug,this.devApiKey)}async postForm(e,t,n=T.REQUEST_TIMEOUT){let r=this.buildHeaders();delete r["Content-Type"];let{controller:i,clear:s}=this.createTimeoutController(n);try{let c=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:r,body:t,signal:i.signal});return(await this.handleResponseWithRaw(c)).data}catch(c){let l=this.wrapAbortError(c);throw l===c&&this.maybeShowNetworkToast(c),l}finally{s()}}async postAudio(e,t){let{controller:n,clear:r}=this.createTimeoutController();try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:n.signal});i.ok||await this.handleResponseWithRaw(i);let{audio_url:s}=await i.json(),c=await fetch(s,{signal:n.signal});if(!c.ok)throw new u("TTS_UPSTREAM_FAILED",`Audio download failed: HTTP ${c.status}`);if(c.headers.get("Content-Type")?.includes("application/json"))throw new u("TTS_UPSTREAM_FAILED","Audio download returned JSON");return await c.blob()}catch(i){let s=this.wrapAbortError(i);throw s===i&&this.maybeShowNetworkToast(i),s}finally{r()}}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||R("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return R("REQUEST_TIMEOUT"),t}return e}createTimeoutController(e=T.REQUEST_TIMEOUT){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return{controller:t,clear:()=>clearTimeout(n)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e["x-client-info"]=`storvia-sdk/${Ye}`,e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:l,durationMs:a,modelName:d}=e,h="%c[Storvia SDK]",m="color: #6366f1; font-weight: bold",f=a!==void 0?` (${a}ms)`:"",p=i!==void 0?` [${i}]`:"",C=d?` [model: ${d}]`:"";l?(console.groupCollapsed(`${h} %c${t} ${n}${p}${C}${f} %c\u2717`,m,"color: #e0e0e0","color: #ef4444"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),console.error("Error:",l),console.groupEnd()):(console.groupCollapsed(`${h} %c${t} ${n}${p}${C}${f} %c\u2713`,m,"color: #e0e0e0","color: #22c55e"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),c!==void 0&&c!==s&&console.log("Response (data):",c),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,d])=>n.searchParams.set(a,d));let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});l(),i=a.status;let{raw:d,data:h}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:h,durationMs:Date.now()-r}),h}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r}),d===a&&this.maybeShowNetworkToast(a),d}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:c.signal});l(),i=a.status;let{raw:d,data:h}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:h,durationMs:Date.now()-r,modelName:n?.modelName}),h}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r,modelName:n?.modelName}),d===a&&this.maybeShowNetworkToast(a),d}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async delete(e){let t=Date.now(),n,r,{controller:i,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:i.signal});s(),n=c.status;let{raw:l,data:a}=await this.handleResponseWithRaw(c);return r=l,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let l=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:l,durationMs:Date.now()-t}),l===c&&this.maybeShowNetworkToast(c),l}}async stream(e,t,n,r,i,s,c,l,a,d,h,m){let f=Date.now(),p=i?.modelName?` [model: ${i.modelName}]`:"",C=[],w=E=>{this.debug&&C.push({t:Date.now()-f,event:E})},{cbs:v,flush:_}=Ie({onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:l,onReconnect:d,onAborted:h,onBase:m}),Oe=new AbortController,D=null,S=null,b=null,k=()=>{D!==null&&(clearTimeout(D),D=null),S!==null&&(clearTimeout(S),S=null)},Pe=E=>{b=E,k(),Oe.abort()};D=setTimeout(()=>Pe("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let A;try{A=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:Oe.signal})}catch(E){if(k(),b){let I=new u(b,"Request timed out");throw R(b),this.log({method:"STREAM",path:e,body:t,error:I,durationMs:Date.now()-f,modelName:i?.modelName}),I}throw this.maybeShowNetworkToast(E),E}if(D!==null&&(clearTimeout(D),D=null),!A.ok){k();let E=await A.text().catch(()=>""),I={};try{I=JSON.parse(E)}catch{}let P=I.code||"INTERNAL_ERROR",g=I.message||I.error||I.details,Me=Array.isArray(I.matched_words)?I.matched_words:void 0,xe=new u(P,g||`HTTP ${A.status}`,Me);throw R(P,g,Me),this.log({method:"STREAM",path:e,body:t,status:A.status,rawResponse:E,error:xe,durationMs:Date.now()-f,modelName:i?.modelName}),xe}let be=A.body?.getReader();if(!be)throw k(),new u("INTERNAL_ERROR","No response body for stream");S=setTimeout(()=>Pe("MODEL_LOADING_TIMEOUT"),T.INITIAL_TIMEOUT);let Ne=new TextDecoder,ee="",ge,ce,M="",de,le,U="",L=!1,O=null,De=E=>{if(L)return;let I=E.endsWith("\r")?E.slice(0,-1):E;if(I.startsWith("id: ")){le=I.slice(4);return}if(!I.startsWith("data: "))return;let P=I.slice(6);if(P==="[DONE]"){w("[DONE]"),L=!0;return}try{let g=JSON.parse(P);w(g),g.type==="done"&&g.id?(ee=g.id,ge=g.truncated===!0):g.type==="aborted"?(ce={id:typeof g.id=="string"?g.id:"",persisted:g.persisted===!0},L=!0):g.type==="error"?(O=new u(g.code||"INTERNAL_ERROR",g.message||"Generation failed",Array.isArray(g.matched_words)?g.matched_words:void 0),L=!0):g.type==="state"?(v.onState?.(g.delta,g.full??null),Array.isArray(g.createdNames)&&g.createdNames.length&&v.onCreatedCharacters?.(g.createdNames)):g.type==="start"?(S!==null&&(clearTimeout(S),S=null),typeof g.base_content=="string"&&m?.(g.base_content)):g.type==="thinking"?(g.status==="start"||g.status==="end")&&v.onThinking?.(g.status):g.content&&(S!==null&&(clearTimeout(S),S=null),M+=g.content,v.onChunk(g.content))}catch{w({raw:P})}le!==void 0&&(de=le,le=void 0)},ke=()=>{if(k(),O)throw _(),R(O.code,O.message,O.matchedWords),this.log({method:"STREAM",path:e,body:t,error:O,durationMs:Date.now()-f,modelName:i?.modelName}),O;this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log("Message ID:",ee),ce&&console.log("Aborted:",ce),console.log(`SSE events (${C.length}):`,C),console.groupEnd()),G(v,{messageId:ee,truncated:ge,aborted:ce})};try{for(;;){let{done:E,value:I}=await be.read();if(E)break;U+=Ne.decode(I,{stream:!0});let P=U.split(`
121
- `);U=P.pop()??"";for(let g of P)De(g);if(L){ke();return}}if(U+=Ne.decode(),U&&De(U),L){ke();return}}catch(E){if(k(),O)throw O;if(b){let I=new u(b,"Stream did not start in time");if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2717 ${b}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Timeout:",I),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw R(b),_(),I}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Stream error:",E),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw _(),E}if(k(),ee){G(v,{messageId:ee,truncated:ge});return}if(a){await this.resumeLoop(a,de,v,{finalize:!0});return}_()}async resumeLoop(e,t,n,r){let i=t;for(let c=1;c<=T.RECONNECT_MAX_ATTEMPTS;c++){let l=Math.min(T.RECONNECT_BACKOFF_CAP,1e3*2**(c-1));await new Promise(h=>setTimeout(h,l)),n.onReconnect?.({attempt:c});let a={messageId:"",lastId:i},d;try{d=await this.pumpGetStream(e.conversationId,e.topic,i,a,n)}catch{continue}if(i=a.lastId??i,d==="done"){if(a.errorCode)throw this.terminalError(a);G(n,a);return}if(d==="inactive"){(a.messageId||r?.finalize)&&G(n,a);return}}let s=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw R("STREAM_INTERRUPTED"),s}async resumeStream(e,t,n){let{cbs:r}=Ie(n),i={messageId:""},s;try{s=await this.pumpGetStream(e,t,void 0,i,r)}catch{await this.resumeLoop({conversationId:e,topic:t},i.lastId,r);return}if(s==="done"){if(i.errorCode)throw this.terminalError(i);G(r,i);return}if(s==="inactive"){i.messageId&&G(r,i);return}await this.resumeLoop({conversationId:e,topic:t},i.lastId,r)}terminalError(e){let t=new u(e.errorCode??"INTERNAL_ERROR",e.errorMessage||"Generation failed",e.errorMatchedWords);return R(t.code,t.message,t.matchedWords),t}async pumpGetStream(e,t,n,r,i){let s=new URL(`${this.baseUrl}/conversations/${encodeURIComponent(e)}/stream`);n&&s.searchParams.set("from",n),t&&s.searchParams.set("topic",t);let c=new AbortController,l=setTimeout(()=>c.abort(),T.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(l)}if(!a.ok)throw new u("STREAM_INTERRUPTED",`Resume HTTP ${a.status}`);if(!(a.headers.get("content-type")||"").includes("text/event-stream"))return"inactive";let h=a.body?.getReader();return h?await this.pumpReader(h,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},T.RESUME_STALL_TIMEOUT)};c();let l="",a=!1,d=h=>{if(a)return;let m=h.endsWith("\r")?h.slice(0,-1):h;if(m.startsWith("id: ")){i=m.slice(4);return}if(!m.startsWith("data: "))return;let f=m.slice(6);if(f==="[DONE]"){a=!0;return}try{let p=JSON.parse(f);p.type==="done"&&p.id?(t.messageId=p.id,t.truncated=p.truncated===!0):p.type==="aborted"?(t.aborted={id:typeof p.id=="string"?p.id:"",persisted:p.persisted===!0},a=!0):p.type==="error"?(t.errorCode=p.code||"INTERNAL_ERROR",t.errorMessage=p.message||"Generation failed",Array.isArray(p.matched_words)&&(t.errorMatchedWords=p.matched_words),a=!0):p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="start"?typeof p.base_content=="string"&&n.onBase?.(p.base_content):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}i!==void 0&&(t.lastId=i,i=void 0)};try{for(;;){let{done:h,value:m}=await e.read();if(h)break;c(),l+=r.decode(m,{stream:!0});let f=l.split(`
122
- `);l=f.pop()??"";for(let p of f)d(p);if(a)return s&&clearTimeout(s),"done"}if(l+=r.decode(),l&&d(l),a)return s&&clearTimeout(s),"done"}catch{}finally{s&&clearTimeout(s)}return"eof"}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let r=n&&typeof n=="object"?n:{},i={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.error_code??r.code,c=s==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":s==="TTS_RATE_LIMITED"?"RATE_LIMITED":s||i[e.status]||"INTERNAL_ERROR",l=Array.isArray(r.matched_words)?r.matched_words:void 0,a=new u(c,r.message||`HTTP ${e.status}`,l);throw R(c,r.message,l),a}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.INITIAL_TIMEOUT=3e4,T.RESUME_STALL_TIMEOUT=6e4,T.RECONNECT_MAX_ATTEMPTS=10,T.RECONNECT_BACKOFF_CAP=15e3;var ie=T;var Ee=o=>o.trim().toLowerCase();function se(o){let e=re(),t=o.name_i18n??{};return t[e]||t[e.replace("-","_")]||o.name}function qe(o,e){let t=Ee(e);return o.find(n=>Ee(n.name)===t)??o.find(n=>Object.values(n.name_i18n??{}).some(r=>typeof r=="string"&&Ee(r)===t))}var Xe="storvia_chat_main";function kt(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let o=new Uint8Array(16);crypto.getRandomValues(o),o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=Array.from(o,t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}var ze=20,Qe=40,V=class{constructor(e,t,n,r,i=!1,s,c,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewHistory=[];this.previewConfig=s,this.getModelName=c,this.getPreset=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.(),client_message_uuid:kt()};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{game_id:this.getGameId(),conversation_id:this.getConversationId(),role:e.role,content:e.content,topic:e.topic})}async generate(e){if(this.isPreview)return this.sendPreview({message:"",topic:e.topic,sceneKey:e.sceneKey,stream:e.stream,onChunk:e.onChunk,onDone:e.onDone,onState:e.onState,onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters});let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/generate",t,this.reqMeta())}async once(e){if(this.isPreview)return this.oncePreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,stream:e.stream===!0,preset:this.getPreset?.()};if(!e.stream)return this.http.post("/once",t,this.reqMeta());let n="";return await this.http.stream("/once",t,r=>{n+=r,e.onChunk?.(r)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:n}}async oncePreview(e){let t={model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,history_messages:[],preset:this.getPreset?.()};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language);let r="";return await this.http.stream("/preview",t,i=>{r+=i,e.onChunk?.(i)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:r}}async retry(e={}){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.retry() is not available in preview mode. Publish the game and test on the Storvia platform.");let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/retry",t,this.reqMeta())}async continue(e={}){if(this.isPreview)return;let t={conversation_id:this.getConversationId(),topic:e.topic??null,game_id:this.getGameId(),preset:this.getPreset?.(),scene_key:e.sceneKey,extract:e.extract};await this.http.stream("/continue",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted,e.onBase)}async cancel(e={}){if(this.isPreview)return{active:!1};let t=await this.http.post(`/conversations/${encodeURIComponent(this.getConversationId())}/cancel`,{topic:e.topic});return{active:t.active===!0,generationId:t.generation_id}}async messages(e){if(this.isPreview)return{data:[],hasMore:!1,nextCursor:null};let t={conversation_id:this.getConversationId(),order:e.order,limit:String(e.limit??20)};e.topic&&(t.topic=e.topic),e.cursor&&(t.cursor_uuid=e.cursor.uuid,t.cursor_created_at=e.cursor.createdAt);let n=await this.http.get("/messages",t);return{data:n.messages.map(r=>({uuid:r.uuid,role:r.role,content:r.content,topic:r.topic,status:r.status,model:r.model,createdAt:r.created_at,truncated:r.truncated===!0})),hasMore:n.has_more,nextCursor:n.next_cursor?{uuid:n.next_cursor.cursor_uuid,createdAt:n.next_cursor.cursor_created_at}:null}}async edit(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.edit() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.patch(`/messages/${encodeURIComponent(e.uuid)}`,{content:e.content});return{uuid:t.uuid,role:t.role,content:t.content,updatedAt:t.updated_at}}async delete(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.delete() is not available in preview mode. Publish the game and test on the Storvia platform.");return{uuid:(await this.http.delete(`/messages/${encodeURIComponent(e.uuid)}`)).uuid}}async rollback(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.rollback() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.post(`/messages/${encodeURIComponent(e.uuid)}/rollback`,{});return{deletedCount:t.deleted_count,deletedUuids:t.deleted_uuids,restoredGameState:t.restored_game_state}}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:F(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting,onAborted:e.onAborted})}async sendPreview(e){let t=e.message.trim().length>0,n=this.previewHistory.slice(t?-(ze-1):-ze);t&&this.pushPreviewHistory({role:"user",content:e.message});let r={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:n,preset:this.getPreset?.()};this.previewConfig?r.prompt_config=this.previewConfig:r.game_id=this.getGameId();let i=this.previewConfig;if(i?.reply_length&&(r.reply_length=i.reply_length),i?.reply_language&&(r.reply_language=i.reply_language),e.stream){let h="";await this.http.stream("/preview",r,m=>{h+=m,e.onChunk?.(m)},(m,f)=>{h&&this.pushPreviewHistory({role:"assistant",content:h}),e.onDone?.(m,f)},this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters);return}let s="",c=null,l=null,a=[];await this.http.stream("/preview",r,h=>{s+=h},()=>{},this.reqMeta(),(h,m)=>{c=h,l=m,e.onState&&e.onState(c,l)},void 0,h=>{a=h,e.onCreatedCharacters&&e.onCreatedCharacters(h)}),s&&this.pushPreviewHistory({role:"assistant",content:s});let d={id:"",content:s,truncated:!1};return c&&(d.delta=c,l&&(d.full=l)),a.length&&(d.createdNames=a),d}pushPreviewHistory(e){this.previewHistory.push(e),this.previewHistory.length>Qe&&this.previewHistory.splice(0,this.previewHistory.length-Qe)}};function F(o){if(o)return(e,t)=>o(e,t)}var we=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let r=this.mem[e]||{};return t?{...r[t]||{}}:{...r}}let n=t?{group:t}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,n)}async update(e,t,n){if(this.isPreview){let r=this.mem[e]||(this.mem[e]={});r[t]={...r[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}async remove(e,t,n){if(n.length){if(this.isPreview){let r=this.mem[e]?.[t];if(r)for(let i of n)delete r[i];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeKeys:n})}}async removeGroup(e,t){if(this.isPreview){let n=this.mem[e];n&&delete n[t];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeGroup:!0})}},H=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(Ze)),this.state=new we(e,t,n,i)}previewNames(){return this.mem.map(e=>e.name)}setInitial(e,t){this.mem=e?e.map(Ze):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Je):(await this.http.get(`/conversations/${this.getConversationId()}/characters`)).map(Te)}async get(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return n?Je(n):{name:e,hasVoice:!1}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`);return Te(t)}async add(e){if(this.isPreview){this.mem.push({...e,isPreset:!1});return}await this.http.post(`/conversations/${this.getConversationId()}/characters`,e)}async update(e,t){if(this.isPreview){let n=this.mem.find(r=>r.name===e);n&&Object.assign(n,t);return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`,t)}async remove(e){if(this.isPreview){this.mem=this.mem.filter(t=>t.name!==e);return}await this.http.delete(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}async merge(e,t){if(this.isPreview){if(this.mem.find(r=>r.name===e)?.isPreset)throw new u("INVALID_REQUEST","\u9884\u8BBE\u89D2\u8272\u4E0D\u53EF\u88AB\u5408\u5E76");if(e===t||!this.mem.some(r=>r.name===t))throw new u("INVALID_REQUEST","\u76EE\u6807\u89D2\u8272\u4E0D\u5B58\u5728\u6216\u4E0E\u6765\u6E90\u76F8\u540C");this.mem=this.mem.filter(r=>r.name!==e);return}await this.http.post(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/merge`,{target:t})}async detail(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return{name:e,avatar:n?.avatar,description:n?.description,hasVoice:n?.hasVoice===!0,...n?.introduction!==void 0?{introduction:n.introduction}:{},...n?.visibleAtStart!==void 0?{visibleAtStart:n.visibleAtStart}:{},userDescription:n?.userDescription,...n?.gender?{gender:n.gender}:{},...n?.isPreset!==void 0?{isPreset:n.isPreset}:{},state:await this.state.get(e)}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`);return Te(t)}async setPriority(e,t){let n=Math.max(0,Math.min(100,Math.round(t)));this.isPreview||await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{priority:n})}};function Ze(o){return{name:o.name,description:o.description,avatar:o.avatar,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Je(o){return{name:o.name,avatar:o.avatar,description:o.description,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Te(o){let{voice:e,...t}=o;return{...t,hasVoice:!!e}}var et="\u73A9\u5BB6",Mt=["Player","player","PLAYER","\u30D7\u30EC\u30A4\u30E4\u30FC","\uD50C\uB808\uC774\uC5B4","\u4E3B\u63A7","{{user}}","user"],ye=o=>o.toLowerCase().replace(/[\s_\-]+/g,""),xt=new Set(["\u73A9\u5BB6",...Mt].map(ye));function tt(o,e){if(o==="\u73A9\u5BB6")return o;let t=ye(o);return xt.has(t)?e.some(n=>ye(n)===t)?o:"\u73A9\u5BB6":o}var W=class{constructor(e,t,n=!1,r,i=()=>[]){this.http=e;this.getConversationId=t;this.isPreview=n;this.getCharacterNames=i;this.mem=[];r&&(this.mem=r.map(s=>({...s})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}entity(e){return this.isPreview?tt(e,this.getCharacterNames()):e}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t);let n=this.mem.find(r=>r.from===e&&r.to===t);if(n)return{...n};throw new Error("Relationship not found")}return this.http.get(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}async add(e){if(this.isPreview){this.mem.push({...e,from:this.entity(e.from),to:this.entity(e.to)});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){e=this.entity(e),t=this.entity(t);let r=this.mem.find(i=>i.from===e&&i.to===t);r?Object.assign(r,n):this.mem.push({from:e,to:t,...n});return}await this.http.patch(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,n)}async remove(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t),this.mem=this.mem.filter(n=>!(n.from===e&&n.to===t));return}await this.http.delete(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}};function nt(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function Ce(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let r={};for(let[i,s]of Object.entries(n))r[i]=nt(s);e[t]=r}return e}function Ut(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=nt(n);return e}var B=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=Ce(r))}setInitial(e){this.mem=e?Ce(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[r,i]of Object.entries(this.mem))n[r]={...i};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return Ut(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return Ce(t)}async add(e){let{group:t,name:n,count:r=1,desc:i,iconUrl:s}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:r};i!==void 0&&(l.desc=i),s!==void 0&&(l.iconUrl=s),this.mem[t][n]=l;return}let c={group:t,name:n,count:r};i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,c)}async update(e){let{group:t,name:n,count:r,desc:i,iconUrl:s}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];r!==void 0&&(a.count=r),i!==void 0&&(a.desc=i),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,c)}async remove(e){let{group:t,name:n}=e;if(this.isPreview){this.mem[t]&&delete this.mem[t][n];return}await this.http.delete(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`)}async removeBatch(e){if(this.isPreview){for(let{group:t,name:n}of e)this.mem[t]&&delete this.mem[t][n];return}e.length!==0&&await this.http.post(`/conversations/${this.getConversationId()}/inventory/batch-delete`,{items:e})}async move(e){let{fromGroup:t,toGroup:n,name:r,newName:i}=e;if(this.isPreview){let s=this.mem[t];if(!s||!(r in s))throw new Error(`Source item "${t}/${r}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let c=i||r;if(t===n&&c===r)return;if(c in this.mem[n])throw new Error(`Item "${c}" already exists in target group`);this.mem[n][c]=s[r],delete s[r];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:r,newName:i})}async ensureGroup(e){if(this.isPreview){this.mem[e]||(this.mem[e]={});return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}`,{})}async removeGroup(e,t){let n=t?.cascade??!1;if(this.isPreview){let i=this.mem[e];if(i&&Object.keys(i).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let r=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${r}`)}};var j=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:this.http.get(`/conversations/${this.getConversationId()}/world`)}async update(e){if(this.isPreview){Object.assign(this.mem,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/world`,e)}};var _e=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e){if(this.isPreview)return e?{...this.mem[e]||{}}:{...this.mem};let t=e?{group:e}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/player/state`,t)}async update(e,t){if(this.isPreview){this.mem[e]={...this.mem[e]||{},...t};return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,values:t})}async remove(e,t){if(t.length){if(this.isPreview){let n=this.mem[e];if(n)for(let r of t)delete n[r];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeKeys:t})}}async removeGroup(e){if(this.isPreview){delete this.mem[e];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeGroup:!0})}},K=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new _e(e,t,n,i)}setInitial(e,t){this.memPersona=e?{...e}:{name:""},this.state.setInitial(t)}async get(){return this.isPreview?{...this.memPersona}:this.http.get(`/conversations/${this.getConversationId()}/player`)}async update(e){if(this.isPreview){Object.assign(this.memPersona,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/player`,e)}};function Y(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var q=class{constructor(e,t,n,r=!1,i,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};i&&(this.mem=rt(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?rt(e):{},this.memInject=t?{...t}:{}}async get(e){if(this.isPreview)return e!==void 0?this.mem[e]:{...this.mem};let t=await this.http.get(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,i]of Object.entries(e))typeof i=="object"&&i!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...i}:this.mem[r]=i,t?.inject!==void 0&&(this.memInject[r]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,this.getGameId()),{inject:t})}getInject(){return{...this.memInject}}async delete(e){if(this.isPreview){delete this.mem[e],delete this.memInject[e];return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}`,this.getGameId()))}async setGroupField(e,t,n){if(this.isPreview){(!this.mem[e]||typeof this.mem[e]!="object")&&(this.mem[e]={}),this.mem[e][t]=n;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()),{value:n})}async deleteGroupField(e,t){if(this.isPreview){if(typeof this.mem[e]=="object"&&this.mem[e]!==null){let n=this.mem[e];delete n[t]}return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function rt(o){let e={};for(let[t,n]of Object.entries(o))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function ot(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var z=class{constructor(e,t,n,r=!1,i){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var Q=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n}async get(){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.state.get() is not available in preview mode. Publish the game and test on the Storvia platform. (Use per-module get() like storvia.world.get() if you need to inspect state during preview.)");return this.http.get(`/conversations/${this.getConversationId()}/state`)}};var X=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null;this.wb=null;this.worldbook={get:async()=>this.isPreview?this.wb?it(this.wb):null:(await this.http.get(`/conversations/${this.getConversationId()}/worldbook`)).worldbook,update:async e=>{let t=typeof e=="string"?{content:e}:{...e};if(t.content!==void 0&&(t.content=(t.content??"").trim()),t.entries!==void 0&&(t.entries=Lt(t.entries)),this.isPreview){let r=this.wb?.presets??[],i=t.enabledPresets?r.map(c=>({...c,enabled:t.enabledPresets.includes(c.id)})):r,s={content:t.content??this.wb?.content??"",contentWidget:t.contentWidget??this.wb?.contentWidget??!1,entries:t.entries??this.wb?.entries??[],presets:i,updated_at:new Date().toISOString()};return this.wb=s,it(s)}return(await this.http.patch(`/conversations/${this.getConversationId()}/worldbook`,t)).worldbook}}}async get(){return this.isPreview?this.mem?{...this.mem}:null:(await this.http.get(`/conversations/${this.getConversationId()}/summary`)).ai_summary}async update(e){let t=(e??"").trim();if(this.isPreview){let r={content:t,updated_at:new Date().toISOString()};return this.mem=r,{...r}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};function it(o){return{...o,entries:o.entries.map(e=>({...e,keys:[...e.keys]})),presets:(o.presets??[]).map(e=>({...e}))}}function Lt(o){return(o??[]).flatMap(e=>{let t=(e?.content??"").trim(),n=[...new Set((e?.keys??[]).map(s=>(s??"").trim()).filter(s=>s!==""))],r=e?.constant===!0;if(!t||!r&&n.length===0)return[];let i=(e?.title??"").trim();return[{id:e.id||$t(),keys:n,content:t,...i?{title:i}:{},constant:r,enabled:e?.enabled!==!1,widget:e?.widget===!0}]})}function $t(){let o=globalThis.crypto;return o?.randomUUID?o.randomUUID():`ewr-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var Re=60,Se=1e3,pe=1e4,N=class{constructor(e,t=!1,n=()=>Date.now()){this.send=e;this.isPreview=t;this.now=n;this.lastNotifyAt=0;this.lastRefreshAt=0;this.lastRefreshMessagesAt=0}notify(e){let t=Gt(e);if(!t)return!1;let n=this.now();return n-this.lastNotifyAt<Se?!1:(this.lastNotifyAt=n,this.isPreview?(oe(t,"info"),!0):(this.send(y("host-notify",{text:t})),!0))}refreshPanel(e){if(this.isPreview)return!1;let t=this.now();return t-this.lastRefreshAt<pe?!1:(this.lastRefreshAt=t,this.send(y("host-state-changed",e?.length?{scope:e}:{})),!0)}refreshMessages(){if(this.isPreview)return!1;let e=this.now();return e-this.lastRefreshMessagesAt<pe?!1:(this.lastRefreshMessagesAt=e,this.send(y("host-messages-changed",{})),!0)}};function Gt(o){return typeof o!="string"?"":o.replace(/\s+/g," ").trim().slice(0,Re)}var Ft;function st(){return Ft??(Ft=new Promise((o,e)=>{let t=indexedDB.open("storvia-sdk-speech",1);t.onupgradeneeded=()=>t.result.createObjectStore("audio"),t.onsuccess=()=>o(t.result),t.onerror=()=>e(t.error)}))}async function at(o){let e=await st();return new Promise((t,n)=>{let r=e.transaction("audio").objectStore("audio").get(o);r.onsuccess=()=>t(r.result??null),r.onerror=()=>n(r.error)})}async function ct(o,e){let t=await st();return new Promise((n,r)=>{let i=t.transaction("audio","readwrite");i.objectStore("audio").put(e,o),i.oncomplete=()=>n(),i.onabort=()=>r(i.error)})}function dt(o){let e=o,t;do t=e,e=e.replace(/[((][^()()]*[))]/g,"");while(e!==t);return e.replace(/\s+/g," ").trim()}var Z=class{constructor(e,t,n,r,i=!1){this.getHttp=e;this.getConversationId=t;this.getGameId=n;this.getVoice=r;this.isPreview=i;this.pending=new Map}async speak(e){let t=dt(e.text),n=await this.getVoice(e.character);if(!n)throw new u("TTS_UNKNOWN_VOICE","Character has no voice configured");let r=this.isPreview?this.getGameId():this.getConversationId(),i=JSON.stringify([r,n,t]),s={text:t,...this.isPreview?{voice:n}:{conversation_id:this.getConversationId(),character_name:e.character}},c=globalThis;if(c.__storviaNativeTts&&c.flutter_inappwebview){let d=await c.flutter_inappwebview.callHandler("storviaTts",{body:s,key:i});if(d.error){let m=d.error==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":d.error==="TTS_RATE_LIMITED"?"RATE_LIMITED":d.error;throw R(m),new u(m,d.error)}let h=Uint8Array.from(atob(d.audio),m=>m.charCodeAt(0));return{audio:new Blob([h],{type:"audio/mpeg"}),cached:d.cached}}let l=await at(i);if(l)return{audio:l,cached:!0};let a=this.pending.get(i);return a||(a=this.getHttp().postAudio("/speak",s).then(async d=>{try{await ct(i,d)}catch{console.warn("[Storvia TTS] \u97F3\u9891\u7F13\u5B58\u4FDD\u5B58\u5931\u8D25")}return{audio:d,cached:!1}}),this.pending.set(i,a),a.then(()=>this.pending.delete(i),()=>this.pending.delete(i))),a}};var J=class{constructor(e){this.getHttp=e}async transcribe(e){if(!e||typeof e!="object")throw new u("INVALID_REQUEST","Recognition options are required");if(!(e.audio instanceof Blob)||e.audio.size===0||e.audio.size>10485760)throw new u("ASR_BAD_AUDIO","Audio must be a non-empty file of at most 10 MB");let t=e.audio.type.split(";")[0].trim().toLowerCase(),n=e.format??qt[t];if(!n||!Kt.includes(n))throw new u("ASR_BAD_AUDIO","Specify a supported audio format");if(e.context!==void 0&&typeof e.context!="string"||!lt(e.languageHints,4)||!lt(e.hotwords,50)||(e.context?.length??0)>400||e.hotwords?.some(i=>i.length>64))throw new u("INVALID_REQUEST","Recognition context, language hints, or hotwords exceed the limits");let r=new FormData;return r.append("file",e.audio,`audio.${n}`),r.append("format",n),e.context!==void 0&&r.append("context",e.context),e.languageHints!==void 0&&r.append("language_hints",JSON.stringify(e.languageHints)),e.hotwords!==void 0&&r.append("hotwords",JSON.stringify(e.hotwords)),this.getHttp().postForm("/transcribe",r,Yt)}},Kt=["wav","mp3","m4a","webm","ogg","opus","flac","aac"],Yt=15e4;function lt(o,e){return o===void 0||Array.isArray(o)&&o.length<=e&&o.every(t=>typeof t=="string"&&t.trim().length>0)}var qt={"audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav","audio/mpeg":"mp3","audio/mp3":"mp3","audio/mp4":"m4a","audio/x-m4a":"m4a","audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/opus":"opus","audio/flac":"flac","audio/x-flac":"flac","audio/aac":"aac"};var ht="/functions/v1/world-engine/v1",zt="https://api.storvia.ai";function Qt(){return window.__STORVIA__||{}}function Xt(o,e=3e4){let t=Qt();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let i=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,lang:a.payload.lang,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(i),s(),c();let d=window;d.__STORVIA__=a,n(a)}o.send(y("ready",{}))})}var ae=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.presetId="";this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0;this.previewVoices=new Map}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new x({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?d=>d.source===null||d.source===window:d=>d.source===window.parent,customSend:t?d=>e.callHandler("storviaBus",d):void 0}),Be(d=>this.bus.send(d));let n=await Xt(this.bus),r=n.apiBase;if(!r)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${r}${ht}`,this.isPreview=!!n.preview,this.previewConfig=n.previewConfig,!n.gameId)throw new u("GAME_NOT_FOUND","window.__STORVIA__.gameId is not set. The platform must inject it before SDK init.");if(this.gameId=n.gameId,!n.accessToken)throw new u("UNAUTHORIZED","window.__STORVIA__.accessToken is not set. The platform must inject the user token before SDK init.");if(this.accessToken=n.accessToken,$e(n.lang),this.http=new ie(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000",this.models=n.models??[],this.modelId=n.selectedModelId||this.models[0]?.id||"";let[d,h]=await Promise.all([this.fetchPreviewSnapshot(),this.modelId?Promise.resolve(null):this.fetchModels()]);h&&(this.models=h,this.modelId=h[0]?.id||""),this.presetId=n.presetId||"";let m=()=>this.gameId,f=()=>this.conversationId,p=()=>this.modelId,C=()=>{let v=this.models.find(_=>_.id===this.modelId);return v?se(v):void 0},w=()=>this.presetId||void 0;this.chat=new V(this.http,m,f,p,!0,this.previewConfig,C,w),this.characters=new H(this.http,f,!0,d.characters,d.characterStates),this.tts=new Z(()=>this.http.ttsClient(),f,m,v=>this.getCharacterVoice(v),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,f,!0,d.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,f,!0,d.inventory),this.world=new j(this.http,f,!0,d.world),this.player=new K(this.http,f,!0,d.player,d.playerState),this.custom=new q(this.http,f,m,!0,d.custom,d.custom_inject),this.save=new z(this.http,f,m,!0,d.save_data),this.state=new Q(this.http,f,!0),this.memory=new X(this.http,f,!0),this.host=new N(v=>this.bus.send(v),!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}if(!n.conversationId)throw new u("NOT_INITIALIZED","window.__STORVIA__.conversationId is not set. The platform must inject it before SDK init.");this.conversationId=n.conversationId,this.modelId=n.selectedModelId||"",this.modelId||(this.models=await this.fetchModels(),this.modelId=this.models[0]?.id||""),this.presetId=n.presetId||"";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(h=>h.id===this.modelId);return d?se(d):void 0},a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!1,void 0,l,a),this.characters=new H(this.http,s),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s),this.inventory=new B(this.http,s),this.world=new j(this.http,s),this.player=new K(this.http,s),this.custom=new q(this.http,s,i),this.save=new z(this.http,s,i),this.state=new Q(this.http,s),this.memory=new X(this.http,s),this.host=new N(d=>this.bus.send(d),!1),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""})}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}listenForPreviewMessages(){this.bus.on("set-model",e=>{this.modelId=e.payload.modelId||""}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""}),this.bus.on("config-update",e=>{this.previewConfig=e.payload.previewConfig,this.chat&&this.chat.updatePreviewConfig(this.previewConfig),this.refreshPreviewSnapshot().catch(t=>{console.warn("[Storvia SDK] refreshPreviewSnapshot failed:",t)})})}async getCharacterVoice(e){return this.isPreview?this.previewVoices.get(e):(await this.http.get(`/conversations/${this.conversationId}/characters/${encodeURIComponent(e)}`)).voice}async fetchPreviewSnapshot(){let e={game_id:this.gameId};this.previewConfig&&("game_config"in this.previewConfig&&(e.game_config=this.previewConfig.game_config),"game_state"in this.previewConfig&&(e.game_state_override=this.previewConfig.game_state));let t=await this.http.post("/preview/initial-snapshot",e);return this.previewVoices=new Map(t.characters.map(n=>[n.name,n.voice])),{...t,characters:t.characters.map(({voice:n,...r})=>({...r,hasVoice:!!n}))}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();this.characters?.setInitial(e.characters,e.characterStates),this.player?.setInitial(e.player,e.playerState),this.inventory?.setInitial(e.inventory),this.relationships?.setInitial(e.relationships),this.world?.setInitial(e.world),this.custom?.setInitial(e.custom,e.custom_inject),this.save?.setInitial(e.save_data)}async fetchModels(e=!1){try{return await this.http.get("/models",e?void 0:{locale:re()})}catch{}return[]}async initDev(e){if(this.initialized)return;this.baseUrl=`${zt}${ht}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new ie(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(!!e.model),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?qe(t,e.model):void 0;e.model&&!r&&console.warn(`[Storvia SDK] dev.model "${e.model}" not found, falling back to the first model. Available:`,t.map(se)),this.modelId=r?.id||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(h=>h.id===this.modelId);return d?se(d):void 0};this.presetId=e.preset||"";let a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!0,void 0,l,a),this.characters=new H(this.http,s,!0,n.characters,n.characterStates),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s,!0,n.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,s,!0,n.inventory),this.world=new j(this.http,s,!0,n.world),this.player=new K(this.http,s,!0,n.player,n.playerState),this.custom=new q(this.http,s,i,!0,n.custom,n.custom_inject),this.save=new z(this.http,s,i,!0,n.save_data),this.state=new Q(this.http,s,!0),this.memory=new X(this.http,s,!0),this.host=new N(()=>{},!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e,locale:re()};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,assetId:i.asset_id,name:i.name,nameI18n:i.meta.name_i18n,url:i.url,assetType:i.asset_type,category:i.category,categoryI18n:i.category_i18n,tags:i.tags.map(s=>({id:s.id,label:s.label,labelI18n:s.label_i18n}))}))}};async function ut(o){Ge();let e=new ae;return o?.dev?await e.initDev(o.dev):await e.init(),e}function Ae(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function pt(o){return Ae(o)?o.value:o}0&&(module.exports={HOST_NOTIFY_MAX_LENGTH,HOST_NOTIFY_MIN_INTERVAL_MS,HOST_PANEL_SCOPES,HOST_REFRESH_MIN_INTERVAL_MS,HostModule,MAIN_CHAT_TOPIC,PLAYER_ID,PROTOCOL_VERSION,StorviaBus,StorviaError,StorviaSDK,createStorviaSDK,envelope,extractFieldValue,isProtocolEnvelope,isRichFieldValue,setToastEnabled,showToast});
120
+ `;let c=s.querySelector(".storvia-toast-msg");c&&(c.textContent=o);let l=()=>{s.isConnected&&(s.classList.add("leaving"),s.classList.remove("show"),setTimeout(()=>s.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(d){console.error("[Storvia toast] action error:",d)}l()}),s.appendChild(a)}if(i){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label",he("close")),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",l),s.appendChild(a)}r.appendChild(s),requestAnimationFrame(()=>s.classList.add("show")),i||setTimeout(l,t)}function bt(o){let e=o.filter(t=>t).map(t=>`\u300C${t}\u300D`).join("");return he("violationWords").replace("{words}",e)}var Nt=3e3,He={};function We(o){let e=Date.now();if(!(e-(He[o]??0)<Nt)){if(He[o]=e,!ve){console.warn(`[Storvia] navigate \u2192 wallet(${o})\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u751F\u4EA7\u73AF\u5883\u7531\u5BBF\u4E3B\u5F39\u5145\u503C\u5F15\u5BFC / \u8DF3\u94B1\u5305\u9875\u3002`);return}try{ve(y("navigate",{target:"wallet",reason:o}))}catch(t){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",t)}}}function R(o,e,t){if(o==="GENERATION_ABORTED")return;if(o==="INSUFFICIENT_CREDITS")return We("insufficient_credits");if(o==="DAISY_CARD_REQUIRED")return We("daisy_card_required");let n=o==="VIOLATION_WORD_DETECTED"&&t?.length?bt(t):Fe(o)||e||he("unknownError");oe(n,o==="RATE_LIMITED"?"warning":"error")}function Dt(o,e){let t=e?.tickMs??100,n=e?.baseLagMs??1e3,r=e?.maxLagMs??2500,i=e?.minCharsPerTick??2,s="",c=null,l=0,a=0,d=()=>Math.min(r,Math.max(n,l*1.35)),g=()=>{let w=Math.max(i,Math.ceil(s.length*t/d()));if(w>=s.length)w=s.length;else{let _=s.charCodeAt(w-1);_>=55296&&_<=56319&&w++}let v=s.slice(0,w);s=s.slice(w),v&&o(v)},p=()=>{c=null,g(),s&&(c=setTimeout(p,t))};return{push:w=>{let v=Date.now();if(a>0){let _=Math.min(v-a,r);l=l>0?l*.7+_*.3:_}a=v,s+=w,c===null&&p()},flush:()=>{c!==null&&(clearTimeout(c),c=null),s&&(o(s),s="")},cancel:()=>{c!==null&&(clearTimeout(c),c=null),s=""}}}function Ie(o){let e=Dt(o.onChunk);return{cbs:{onChunk:n=>e.push(n),onDone:(n,r)=>{e.flush(),o.onDone(n,r)},onAborted:o.onAborted?n=>{e.flush(),o.onAborted(n)}:void 0,onState:o.onState?(n,r)=>{e.flush(),o.onState(n,r)}:void 0,onThinking:o.onThinking?n=>{e.flush(),o.onThinking(n)}:void 0,onCreatedCharacters:o.onCreatedCharacters?n=>{e.flush(),o.onCreatedCharacters(n)}:void 0,onReconnect:o.onReconnect},flush:()=>e.flush()}}var Ye="0.10.10";function G(o,e){if(e.aborted){if(o.onAborted){o.onAborted(e.aborted);return}o.onDone(e.aborted.id,{truncated:!1});return}o.onDone(e.messageId,e.truncated===void 0?void 0:{truncated:e.truncated})}var T=class T{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}ttsClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/tts"),this.token,this.debug,this.devApiKey)}asrClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/asr"),this.token,this.debug,this.devApiKey)}async postForm(e,t,n=T.REQUEST_TIMEOUT){let r=this.buildHeaders();delete r["Content-Type"];let{controller:i,clear:s}=this.createTimeoutController(n);try{let c=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:r,body:t,signal:i.signal});return(await this.handleResponseWithRaw(c)).data}catch(c){let l=this.wrapAbortError(c);throw l===c&&this.maybeShowNetworkToast(c),l}finally{s()}}async postAudio(e,t){let{controller:n,clear:r}=this.createTimeoutController();try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:n.signal});i.ok||await this.handleResponseWithRaw(i);let{audio_url:s}=await i.json(),c=await fetch(s,{signal:n.signal});if(!c.ok)throw new u("TTS_UPSTREAM_FAILED",`Audio download failed: HTTP ${c.status}`);if(c.headers.get("Content-Type")?.includes("application/json"))throw new u("TTS_UPSTREAM_FAILED","Audio download returned JSON");return await c.blob()}catch(i){let s=this.wrapAbortError(i);throw s===i&&this.maybeShowNetworkToast(i),s}finally{r()}}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||R("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return R("REQUEST_TIMEOUT"),t}return e}createTimeoutController(e=T.REQUEST_TIMEOUT){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return{controller:t,clear:()=>clearTimeout(n)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e["x-client-info"]=`storvia-sdk/${Ye}`,e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:l,durationMs:a,modelName:d}=e,g="%c[Storvia SDK]",p="color: #6366f1; font-weight: bold",m=a!==void 0?` (${a}ms)`:"",h=i!==void 0?` [${i}]`:"",C=d?` [model: ${d}]`:"";l?(console.groupCollapsed(`${g} %c${t} ${n}${h}${C}${m} %c\u2717`,p,"color: #e0e0e0","color: #ef4444"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),console.error("Error:",l),console.groupEnd()):(console.groupCollapsed(`${g} %c${t} ${n}${h}${C}${m} %c\u2713`,p,"color: #e0e0e0","color: #22c55e"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),c!==void 0&&c!==s&&console.log("Response (data):",c),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,d])=>n.searchParams.set(a,d));let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});l(),i=a.status;let{raw:d,data:g}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:g,durationMs:Date.now()-r}),g}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r}),d===a&&this.maybeShowNetworkToast(a),d}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:c.signal});l(),i=a.status;let{raw:d,data:g}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:g,durationMs:Date.now()-r,modelName:n?.modelName}),g}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r,modelName:n?.modelName}),d===a&&this.maybeShowNetworkToast(a),d}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async delete(e){let t=Date.now(),n,r,{controller:i,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:i.signal});s(),n=c.status;let{raw:l,data:a}=await this.handleResponseWithRaw(c);return r=l,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let l=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:l,durationMs:Date.now()-t}),l===c&&this.maybeShowNetworkToast(c),l}}async stream(e,t,n,r,i,s,c,l,a,d,g,p){let m=Date.now(),h=i?.modelName?` [model: ${i.modelName}]`:"",C=[],w=E=>{this.debug&&C.push({t:Date.now()-m,event:E})},{cbs:v,flush:_}=Ie({onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:l,onReconnect:d,onAborted:g,onBase:p}),Oe=new AbortController,D=null,S=null,b=null,k=()=>{D!==null&&(clearTimeout(D),D=null),S!==null&&(clearTimeout(S),S=null)},Pe=E=>{b=E,k(),Oe.abort()};D=setTimeout(()=>Pe("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let A;try{A=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:Oe.signal})}catch(E){if(k(),b){let I=new u(b,"Request timed out");throw R(b),this.log({method:"STREAM",path:e,body:t,error:I,durationMs:Date.now()-m,modelName:i?.modelName}),I}throw this.maybeShowNetworkToast(E),E}if(D!==null&&(clearTimeout(D),D=null),!A.ok){k();let E=await A.text().catch(()=>""),I={};try{I=JSON.parse(E)}catch{}let P=I.code||"INTERNAL_ERROR",f=I.message||I.error||I.details,Me=Array.isArray(I.matched_words)?I.matched_words:void 0,xe=new u(P,f||`HTTP ${A.status}`,Me);throw R(P,f,Me),this.log({method:"STREAM",path:e,body:t,status:A.status,rawResponse:E,error:xe,durationMs:Date.now()-m,modelName:i?.modelName}),xe}let be=A.body?.getReader();if(!be)throw k(),new u("INTERNAL_ERROR","No response body for stream");S=setTimeout(()=>Pe("MODEL_LOADING_TIMEOUT"),T.INITIAL_TIMEOUT);let Ne=new TextDecoder,ee="",ge,ce,M="",de,le,U="",L=!1,O=null,De=E=>{if(L)return;let I=E.endsWith("\r")?E.slice(0,-1):E;if(I.startsWith("id: ")){le=I.slice(4);return}if(!I.startsWith("data: "))return;let P=I.slice(6);if(P==="[DONE]"){w("[DONE]"),L=!0;return}try{let f=JSON.parse(P);w(f),f.type==="done"&&f.id?(ee=f.id,ge=f.truncated===!0):f.type==="aborted"?(ce={id:typeof f.id=="string"?f.id:"",persisted:f.persisted===!0},L=!0):f.type==="error"?(O=new u(f.code||"INTERNAL_ERROR",f.message||"Generation failed",Array.isArray(f.matched_words)?f.matched_words:void 0),L=!0):f.type==="state"?(v.onState?.(f.delta,f.full??null),Array.isArray(f.createdNames)&&f.createdNames.length&&v.onCreatedCharacters?.(f.createdNames)):f.type==="start"?(S!==null&&(clearTimeout(S),S=null),typeof f.base_content=="string"&&p?.(f.base_content)):f.type==="thinking"?(f.status==="start"||f.status==="end")&&v.onThinking?.(f.status):f.content&&(S!==null&&(clearTimeout(S),S=null),M+=f.content,v.onChunk(f.content))}catch{w({raw:P})}le!==void 0&&(de=le,le=void 0)},ke=()=>{if(k(),O)throw _(),R(O.code,O.message,O.matchedWords),this.log({method:"STREAM",path:e,body:t,error:O,durationMs:Date.now()-m,modelName:i?.modelName}),O;this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log("Message ID:",ee),ce&&console.log("Aborted:",ce),console.log(`SSE events (${C.length}):`,C),console.groupEnd()),G(v,{messageId:ee,truncated:ge,aborted:ce})};try{for(;;){let{done:E,value:I}=await be.read();if(E)break;U+=Ne.decode(I,{stream:!0});let P=U.split(`
121
+ `);U=P.pop()??"";for(let f of P)De(f);if(L){ke();return}}if(U+=Ne.decode(),U&&De(U),L){ke();return}}catch(E){if(k(),O)throw O;if(b){let I=new u(b,"Stream did not start in time");if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2717 ${b}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Timeout:",I),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw R(b),_(),I}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Stream error:",E),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw _(),E}if(k(),ee){G(v,{messageId:ee,truncated:ge});return}if(a){await this.resumeLoop(a,de,v,{finalize:!0});return}_()}async resumeLoop(e,t,n,r){let i=t;for(let c=1;c<=T.RECONNECT_MAX_ATTEMPTS;c++){let l=Math.min(T.RECONNECT_BACKOFF_CAP,1e3*2**(c-1));await new Promise(g=>setTimeout(g,l)),n.onReconnect?.({attempt:c});let a={messageId:"",lastId:i},d;try{d=await this.pumpGetStream(e.conversationId,e.topic,i,a,n)}catch{continue}if(i=a.lastId??i,d==="done"){if(a.errorCode)throw this.terminalError(a);G(n,a);return}if(d==="inactive"){(a.messageId||r?.finalize)&&G(n,a);return}}let s=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw R("STREAM_INTERRUPTED"),s}async resumeStream(e,t,n){let{cbs:r}=Ie(n),i={messageId:""},s;try{s=await this.pumpGetStream(e,t,void 0,i,r)}catch{await this.resumeLoop({conversationId:e,topic:t},i.lastId,r);return}if(s==="done"){if(i.errorCode)throw this.terminalError(i);G(r,i);return}if(s==="inactive"){i.messageId&&G(r,i);return}await this.resumeLoop({conversationId:e,topic:t},i.lastId,r)}terminalError(e){let t=new u(e.errorCode??"INTERNAL_ERROR",e.errorMessage||"Generation failed",e.errorMatchedWords);return R(t.code,t.message,t.matchedWords),t}async pumpGetStream(e,t,n,r,i){let s=new URL(`${this.baseUrl}/conversations/${encodeURIComponent(e)}/stream`);n&&s.searchParams.set("from",n),t&&s.searchParams.set("topic",t);let c=new AbortController,l=setTimeout(()=>c.abort(),T.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(l)}if(!a.ok)throw new u("STREAM_INTERRUPTED",`Resume HTTP ${a.status}`);if(!(a.headers.get("content-type")||"").includes("text/event-stream"))return"inactive";let g=a.body?.getReader();return g?await this.pumpReader(g,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},T.RESUME_STALL_TIMEOUT)};c();let l="",a=!1,d=g=>{if(a)return;let p=g.endsWith("\r")?g.slice(0,-1):g;if(p.startsWith("id: ")){i=p.slice(4);return}if(!p.startsWith("data: "))return;let m=p.slice(6);if(m==="[DONE]"){a=!0;return}try{let h=JSON.parse(m);h.type==="done"&&h.id?(t.messageId=h.id,t.truncated=h.truncated===!0):h.type==="aborted"?(t.aborted={id:typeof h.id=="string"?h.id:"",persisted:h.persisted===!0},a=!0):h.type==="error"?(t.errorCode=h.code||"INTERNAL_ERROR",t.errorMessage=h.message||"Generation failed",Array.isArray(h.matched_words)&&(t.errorMatchedWords=h.matched_words),a=!0):h.type==="state"?(n.onState?.(h.delta,h.full??null),Array.isArray(h.createdNames)&&h.createdNames.length&&n.onCreatedCharacters?.(h.createdNames)):h.type==="start"?typeof h.base_content=="string"&&n.onBase?.(h.base_content):h.type==="thinking"?(h.status==="start"||h.status==="end")&&n.onThinking?.(h.status):h.content&&n.onChunk(h.content)}catch{}i!==void 0&&(t.lastId=i,i=void 0)};try{for(;;){let{done:g,value:p}=await e.read();if(g)break;c(),l+=r.decode(p,{stream:!0});let m=l.split(`
122
+ `);l=m.pop()??"";for(let h of m)d(h);if(a)return s&&clearTimeout(s),"done"}if(l+=r.decode(),l&&d(l),a)return s&&clearTimeout(s),"done"}catch{}finally{s&&clearTimeout(s)}return"eof"}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let r=n&&typeof n=="object"?n:{},i={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.error_code??r.code,c=s==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":s==="TTS_RATE_LIMITED"?"RATE_LIMITED":s||i[e.status]||"INTERNAL_ERROR",l=Array.isArray(r.matched_words)?r.matched_words:void 0,a=new u(c,r.message||`HTTP ${e.status}`,l);throw R(c,r.message,l),a}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.INITIAL_TIMEOUT=3e4,T.RESUME_STALL_TIMEOUT=6e4,T.RECONNECT_MAX_ATTEMPTS=10,T.RECONNECT_BACKOFF_CAP=15e3;var ie=T;var Ee=o=>o.trim().toLowerCase();function se(o){let e=re(),t=o.name_i18n??{};return t[e]||t[e.replace("-","_")]||o.name}function qe(o,e){let t=Ee(e);return o.find(n=>Ee(n.name)===t)??o.find(n=>Object.values(n.name_i18n??{}).some(r=>typeof r=="string"&&Ee(r)===t))}var Xe="storvia_chat_main";function kt(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let o=new Uint8Array(16);crypto.getRandomValues(o),o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=Array.from(o,t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}var ze=20,Qe=40,V=class{constructor(e,t,n,r,i=!1,s,c,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewHistory=[];this.previewConfig=s,this.getModelName=c,this.getPreset=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.(),client_message_uuid:kt()};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{game_id:this.getGameId(),conversation_id:this.getConversationId(),role:e.role,content:e.content,topic:e.topic})}async generate(e){if(this.isPreview)return this.sendPreview({message:"",topic:e.topic,sceneKey:e.sceneKey,stream:e.stream,onChunk:e.onChunk,onDone:e.onDone,onState:e.onState,onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters});let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/generate",t,this.reqMeta())}async once(e){if(this.isPreview)return this.oncePreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,stream:e.stream===!0,preset:this.getPreset?.()};if(!e.stream)return this.http.post("/once",t,this.reqMeta());let n="";return await this.http.stream("/once",t,r=>{n+=r,e.onChunk?.(r)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:n}}async oncePreview(e){let t={model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,history_messages:[],preset:this.getPreset?.()};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language);let r="";return await this.http.stream("/preview",t,i=>{r+=i,e.onChunk?.(i)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:r}}async retry(e={}){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.retry() is not available in preview mode. Publish the game and test on the Storvia platform.");let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/retry",t,this.reqMeta())}async continue(e={}){if(this.isPreview)return;let t={conversation_id:this.getConversationId(),topic:e.topic??null,game_id:this.getGameId(),preset:this.getPreset?.(),scene_key:e.sceneKey,extract:e.extract};await this.http.stream("/continue",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted,e.onBase)}async cancel(e={}){if(this.isPreview)return{active:!1};let t=await this.http.post(`/conversations/${encodeURIComponent(this.getConversationId())}/cancel`,{topic:e.topic});return{active:t.active===!0,generationId:t.generation_id}}async messages(e){if(this.isPreview)return{data:[],hasMore:!1,nextCursor:null};let t={conversation_id:this.getConversationId(),order:e.order,limit:String(e.limit??20)};e.topic&&(t.topic=e.topic),e.cursor&&(t.cursor_uuid=e.cursor.uuid,t.cursor_created_at=e.cursor.createdAt);let n=await this.http.get("/messages",t);return{data:n.messages.map(r=>({uuid:r.uuid,role:r.role,content:r.content,topic:r.topic,status:r.status,model:r.model,createdAt:r.created_at,truncated:r.truncated===!0})),hasMore:n.has_more,nextCursor:n.next_cursor?{uuid:n.next_cursor.cursor_uuid,createdAt:n.next_cursor.cursor_created_at}:null}}async edit(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.edit() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.patch(`/messages/${encodeURIComponent(e.uuid)}`,{content:e.content});return{uuid:t.uuid,role:t.role,content:t.content,updatedAt:t.updated_at}}async delete(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.delete() is not available in preview mode. Publish the game and test on the Storvia platform.");return{uuid:(await this.http.delete(`/messages/${encodeURIComponent(e.uuid)}`)).uuid}}async rollback(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.rollback() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.post(`/messages/${encodeURIComponent(e.uuid)}/rollback`,{});return{deletedCount:t.deleted_count,deletedUuids:t.deleted_uuids,restoredGameState:t.restored_game_state}}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:F(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting,onAborted:e.onAborted})}async sendPreview(e){let t=e.message.trim().length>0,n=e.topic||null,r=this.previewHistory.filter(p=>n===null||p.topic===n).slice(t?-(ze-1):-ze).map(({role:p,content:m})=>({role:p,content:m}));t&&this.pushPreviewHistory({role:"user",content:e.message},n);let i={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:r,preset:this.getPreset?.()};this.previewConfig?i.prompt_config=this.previewConfig:i.game_id=this.getGameId();let s=this.previewConfig;if(s?.reply_length&&(i.reply_length=s.reply_length),s?.reply_language&&(i.reply_language=s.reply_language),e.stream){let p="";await this.http.stream("/preview",i,m=>{p+=m,e.onChunk?.(m)},(m,h)=>{p&&this.pushPreviewHistory({role:"assistant",content:p},n),e.onDone?.(m,h)},this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters);return}let c="",l=null,a=null,d=[];await this.http.stream("/preview",i,p=>{c+=p},()=>{},this.reqMeta(),(p,m)=>{l=p,a=m,e.onState&&e.onState(l,a)},void 0,p=>{d=p,e.onCreatedCharacters&&e.onCreatedCharacters(p)}),c&&this.pushPreviewHistory({role:"assistant",content:c},n);let g={id:"",content:c,truncated:!1};return l&&(g.delta=l,a&&(g.full=a)),d.length&&(g.createdNames=d),g}pushPreviewHistory(e,t){this.previewHistory.push({...e,topic:t}),this.previewHistory.length>Qe&&this.previewHistory.splice(0,this.previewHistory.length-Qe)}};function F(o){if(o)return(e,t)=>o(e,t)}var we=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let r=this.mem[e]||{};return t?{...r[t]||{}}:{...r}}let n=t?{group:t}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,n)}async update(e,t,n){if(this.isPreview){let r=this.mem[e]||(this.mem[e]={});r[t]={...r[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}async remove(e,t,n){if(n.length){if(this.isPreview){let r=this.mem[e]?.[t];if(r)for(let i of n)delete r[i];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeKeys:n})}}async removeGroup(e,t){if(this.isPreview){let n=this.mem[e];n&&delete n[t];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeGroup:!0})}},H=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(Ze)),this.state=new we(e,t,n,i)}previewNames(){return this.mem.map(e=>e.name)}setInitial(e,t){this.mem=e?e.map(Ze):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Je):(await this.http.get(`/conversations/${this.getConversationId()}/characters`)).map(Te)}async get(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return n?Je(n):{name:e,hasVoice:!1}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`);return Te(t)}async add(e){if(this.isPreview){this.mem.push({...e,isPreset:!1});return}await this.http.post(`/conversations/${this.getConversationId()}/characters`,e)}async update(e,t){if(this.isPreview){let n=this.mem.find(r=>r.name===e);n&&Object.assign(n,t);return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`,t)}async remove(e){if(this.isPreview){this.mem=this.mem.filter(t=>t.name!==e);return}await this.http.delete(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}async merge(e,t){if(this.isPreview){if(this.mem.find(r=>r.name===e)?.isPreset)throw new u("INVALID_REQUEST","\u9884\u8BBE\u89D2\u8272\u4E0D\u53EF\u88AB\u5408\u5E76");if(e===t||!this.mem.some(r=>r.name===t))throw new u("INVALID_REQUEST","\u76EE\u6807\u89D2\u8272\u4E0D\u5B58\u5728\u6216\u4E0E\u6765\u6E90\u76F8\u540C");this.mem=this.mem.filter(r=>r.name!==e);return}await this.http.post(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/merge`,{target:t})}async detail(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return{name:e,avatar:n?.avatar,description:n?.description,hasVoice:n?.hasVoice===!0,...n?.introduction!==void 0?{introduction:n.introduction}:{},...n?.visibleAtStart!==void 0?{visibleAtStart:n.visibleAtStart}:{},userDescription:n?.userDescription,...n?.gender?{gender:n.gender}:{},...n?.isPreset!==void 0?{isPreset:n.isPreset}:{},state:await this.state.get(e)}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`);return Te(t)}async setPriority(e,t){let n=Math.max(0,Math.min(100,Math.round(t)));this.isPreview||await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{priority:n})}};function Ze(o){return{name:o.name,description:o.description,avatar:o.avatar,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Je(o){return{name:o.name,avatar:o.avatar,description:o.description,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Te(o){let{voice:e,...t}=o;return{...t,hasVoice:!!e}}var et="\u73A9\u5BB6",Mt=["Player","player","PLAYER","\u30D7\u30EC\u30A4\u30E4\u30FC","\uD50C\uB808\uC774\uC5B4","\u4E3B\u63A7","{{user}}","user"],ye=o=>o.toLowerCase().replace(/[\s_\-]+/g,""),xt=new Set(["\u73A9\u5BB6",...Mt].map(ye));function tt(o,e){if(o==="\u73A9\u5BB6")return o;let t=ye(o);return xt.has(t)?e.some(n=>ye(n)===t)?o:"\u73A9\u5BB6":o}var W=class{constructor(e,t,n=!1,r,i=()=>[]){this.http=e;this.getConversationId=t;this.isPreview=n;this.getCharacterNames=i;this.mem=[];r&&(this.mem=r.map(s=>({...s})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}entity(e){return this.isPreview?tt(e,this.getCharacterNames()):e}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t);let n=this.mem.find(r=>r.from===e&&r.to===t);if(n)return{...n};throw new Error("Relationship not found")}return this.http.get(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}async add(e){if(this.isPreview){this.mem.push({...e,from:this.entity(e.from),to:this.entity(e.to)});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){e=this.entity(e),t=this.entity(t);let r=this.mem.find(i=>i.from===e&&i.to===t);r?Object.assign(r,n):this.mem.push({from:e,to:t,...n});return}await this.http.patch(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,n)}async remove(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t),this.mem=this.mem.filter(n=>!(n.from===e&&n.to===t));return}await this.http.delete(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}};function nt(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function Ce(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let r={};for(let[i,s]of Object.entries(n))r[i]=nt(s);e[t]=r}return e}function Ut(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=nt(n);return e}var B=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=Ce(r))}setInitial(e){this.mem=e?Ce(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[r,i]of Object.entries(this.mem))n[r]={...i};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return Ut(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return Ce(t)}async add(e){let{group:t,name:n,count:r=1,desc:i,iconUrl:s}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:r};i!==void 0&&(l.desc=i),s!==void 0&&(l.iconUrl=s),this.mem[t][n]=l;return}let c={group:t,name:n,count:r};i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,c)}async update(e){let{group:t,name:n,count:r,desc:i,iconUrl:s}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];r!==void 0&&(a.count=r),i!==void 0&&(a.desc=i),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,c)}async remove(e){let{group:t,name:n}=e;if(this.isPreview){this.mem[t]&&delete this.mem[t][n];return}await this.http.delete(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`)}async removeBatch(e){if(this.isPreview){for(let{group:t,name:n}of e)this.mem[t]&&delete this.mem[t][n];return}e.length!==0&&await this.http.post(`/conversations/${this.getConversationId()}/inventory/batch-delete`,{items:e})}async move(e){let{fromGroup:t,toGroup:n,name:r,newName:i}=e;if(this.isPreview){let s=this.mem[t];if(!s||!(r in s))throw new Error(`Source item "${t}/${r}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let c=i||r;if(t===n&&c===r)return;if(c in this.mem[n])throw new Error(`Item "${c}" already exists in target group`);this.mem[n][c]=s[r],delete s[r];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:r,newName:i})}async ensureGroup(e){if(this.isPreview){this.mem[e]||(this.mem[e]={});return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}`,{})}async removeGroup(e,t){let n=t?.cascade??!1;if(this.isPreview){let i=this.mem[e];if(i&&Object.keys(i).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let r=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${r}`)}};var j=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:this.http.get(`/conversations/${this.getConversationId()}/world`)}async update(e){if(this.isPreview){Object.assign(this.mem,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/world`,e)}};var _e=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e){if(this.isPreview)return e?{...this.mem[e]||{}}:{...this.mem};let t=e?{group:e}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/player/state`,t)}async update(e,t){if(this.isPreview){this.mem[e]={...this.mem[e]||{},...t};return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,values:t})}async remove(e,t){if(t.length){if(this.isPreview){let n=this.mem[e];if(n)for(let r of t)delete n[r];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeKeys:t})}}async removeGroup(e){if(this.isPreview){delete this.mem[e];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeGroup:!0})}},K=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new _e(e,t,n,i)}setInitial(e,t){this.memPersona=e?{...e}:{name:""},this.state.setInitial(t)}async get(){return this.isPreview?{...this.memPersona}:this.http.get(`/conversations/${this.getConversationId()}/player`)}async update(e){if(this.isPreview){Object.assign(this.memPersona,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/player`,e)}};function Y(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var q=class{constructor(e,t,n,r=!1,i,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};i&&(this.mem=rt(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?rt(e):{},this.memInject=t?{...t}:{}}async get(e){if(this.isPreview)return e!==void 0?this.mem[e]:{...this.mem};let t=await this.http.get(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,i]of Object.entries(e))typeof i=="object"&&i!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...i}:this.mem[r]=i,t?.inject!==void 0&&(this.memInject[r]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,this.getGameId()),{inject:t})}getInject(){return{...this.memInject}}async delete(e){if(this.isPreview){delete this.mem[e],delete this.memInject[e];return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}`,this.getGameId()))}async setGroupField(e,t,n){if(this.isPreview){(!this.mem[e]||typeof this.mem[e]!="object")&&(this.mem[e]={}),this.mem[e][t]=n;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()),{value:n})}async deleteGroupField(e,t){if(this.isPreview){if(typeof this.mem[e]=="object"&&this.mem[e]!==null){let n=this.mem[e];delete n[t]}return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function rt(o){let e={};for(let[t,n]of Object.entries(o))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function ot(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var z=class{constructor(e,t,n,r=!1,i){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var Q=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n}async get(){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.state.get() is not available in preview mode. Publish the game and test on the Storvia platform. (Use per-module get() like storvia.world.get() if you need to inspect state during preview.)");return this.http.get(`/conversations/${this.getConversationId()}/state`)}};var X=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null;this.wb=null;this.worldbook={get:async()=>this.isPreview?this.wb?it(this.wb):null:(await this.http.get(`/conversations/${this.getConversationId()}/worldbook`)).worldbook,update:async e=>{let t=typeof e=="string"?{content:e}:{...e};if(t.content!==void 0&&(t.content=(t.content??"").trim()),t.entries!==void 0&&(t.entries=Lt(t.entries)),this.isPreview){let r=this.wb?.presets??[],i=t.enabledPresets?r.map(c=>({...c,enabled:t.enabledPresets.includes(c.id)})):r,s={content:t.content??this.wb?.content??"",contentWidget:t.contentWidget??this.wb?.contentWidget??!1,entries:t.entries??this.wb?.entries??[],presets:i,updated_at:new Date().toISOString()};return this.wb=s,it(s)}return(await this.http.patch(`/conversations/${this.getConversationId()}/worldbook`,t)).worldbook}}}async get(){return this.isPreview?this.mem?{...this.mem}:null:(await this.http.get(`/conversations/${this.getConversationId()}/summary`)).ai_summary}async update(e){let t=(e??"").trim();if(this.isPreview){let r={content:t,updated_at:new Date().toISOString()};return this.mem=r,{...r}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};function it(o){return{...o,entries:o.entries.map(e=>({...e,keys:[...e.keys]})),presets:(o.presets??[]).map(e=>({...e}))}}function Lt(o){return(o??[]).flatMap(e=>{let t=(e?.content??"").trim(),n=[...new Set((e?.keys??[]).map(s=>(s??"").trim()).filter(s=>s!==""))],r=e?.constant===!0;if(!t||!r&&n.length===0)return[];let i=(e?.title??"").trim();return[{id:e.id||$t(),keys:n,content:t,...i?{title:i}:{},constant:r,enabled:e?.enabled!==!1,widget:e?.widget===!0}]})}function $t(){let o=globalThis.crypto;return o?.randomUUID?o.randomUUID():`ewr-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var Re=60,Se=1e3,pe=1e4,N=class{constructor(e,t=!1,n=()=>Date.now()){this.send=e;this.isPreview=t;this.now=n;this.lastNotifyAt=0;this.lastRefreshAt=0;this.lastRefreshMessagesAt=0}notify(e){let t=Gt(e);if(!t)return!1;let n=this.now();return n-this.lastNotifyAt<Se?!1:(this.lastNotifyAt=n,this.isPreview?(oe(t,"info"),!0):(this.send(y("host-notify",{text:t})),!0))}refreshPanel(e){if(this.isPreview)return!1;let t=this.now();return t-this.lastRefreshAt<pe?!1:(this.lastRefreshAt=t,this.send(y("host-state-changed",e?.length?{scope:e}:{})),!0)}refreshMessages(){if(this.isPreview)return!1;let e=this.now();return e-this.lastRefreshMessagesAt<pe?!1:(this.lastRefreshMessagesAt=e,this.send(y("host-messages-changed",{})),!0)}};function Gt(o){return typeof o!="string"?"":o.replace(/\s+/g," ").trim().slice(0,Re)}var Ft;function st(){return Ft??(Ft=new Promise((o,e)=>{let t=indexedDB.open("storvia-sdk-speech",1);t.onupgradeneeded=()=>t.result.createObjectStore("audio"),t.onsuccess=()=>o(t.result),t.onerror=()=>e(t.error)}))}async function at(o){let e=await st();return new Promise((t,n)=>{let r=e.transaction("audio").objectStore("audio").get(o);r.onsuccess=()=>t(r.result??null),r.onerror=()=>n(r.error)})}async function ct(o,e){let t=await st();return new Promise((n,r)=>{let i=t.transaction("audio","readwrite");i.objectStore("audio").put(e,o),i.oncomplete=()=>n(),i.onabort=()=>r(i.error)})}function dt(o){let e=o,t;do t=e,e=e.replace(/[((][^()()]*[))]/g,"");while(e!==t);return e.replace(/\s+/g," ").trim()}var Z=class{constructor(e,t,n,r,i=!1){this.getHttp=e;this.getConversationId=t;this.getGameId=n;this.getVoice=r;this.isPreview=i;this.pending=new Map}async speak(e){let t=dt(e.text),n=await this.getVoice(e.character);if(!n)throw new u("TTS_UNKNOWN_VOICE","Character has no voice configured");let r=this.isPreview?this.getGameId():this.getConversationId(),i=JSON.stringify([r,n,t]),s={text:t,...this.isPreview?{voice:n}:{conversation_id:this.getConversationId(),character_name:e.character}},c=globalThis;if(c.__storviaNativeTts&&c.flutter_inappwebview){let d=await c.flutter_inappwebview.callHandler("storviaTts",{body:s,key:i});if(d.error){let p=d.error==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":d.error==="TTS_RATE_LIMITED"?"RATE_LIMITED":d.error;throw R(p),new u(p,d.error)}let g=Uint8Array.from(atob(d.audio),p=>p.charCodeAt(0));return{audio:new Blob([g],{type:"audio/mpeg"}),cached:d.cached}}let l=await at(i);if(l)return{audio:l,cached:!0};let a=this.pending.get(i);return a||(a=this.getHttp().postAudio("/speak",s).then(async d=>{try{await ct(i,d)}catch{console.warn("[Storvia TTS] \u97F3\u9891\u7F13\u5B58\u4FDD\u5B58\u5931\u8D25")}return{audio:d,cached:!1}}),this.pending.set(i,a),a.then(()=>this.pending.delete(i),()=>this.pending.delete(i))),a}};var J=class{constructor(e){this.getHttp=e}async transcribe(e){if(!e||typeof e!="object")throw new u("INVALID_REQUEST","Recognition options are required");if(!(e.audio instanceof Blob)||e.audio.size===0||e.audio.size>10485760)throw new u("ASR_BAD_AUDIO","Audio must be a non-empty file of at most 10 MB");let t=e.audio.type.split(";")[0].trim().toLowerCase(),n=e.format??qt[t];if(!n||!Kt.includes(n))throw new u("ASR_BAD_AUDIO","Specify a supported audio format");if(e.context!==void 0&&typeof e.context!="string"||!lt(e.languageHints,4)||!lt(e.hotwords,50)||(e.context?.length??0)>400||e.hotwords?.some(i=>i.length>64))throw new u("INVALID_REQUEST","Recognition context, language hints, or hotwords exceed the limits");let r=new FormData;return r.append("file",e.audio,`audio.${n}`),r.append("format",n),e.context!==void 0&&r.append("context",e.context),e.languageHints!==void 0&&r.append("language_hints",JSON.stringify(e.languageHints)),e.hotwords!==void 0&&r.append("hotwords",JSON.stringify(e.hotwords)),this.getHttp().postForm("/transcribe",r,Yt)}},Kt=["wav","mp3","m4a","webm","ogg","opus","flac","aac"],Yt=15e4;function lt(o,e){return o===void 0||Array.isArray(o)&&o.length<=e&&o.every(t=>typeof t=="string"&&t.trim().length>0)}var qt={"audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav","audio/mpeg":"mp3","audio/mp3":"mp3","audio/mp4":"m4a","audio/x-m4a":"m4a","audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/opus":"opus","audio/flac":"flac","audio/x-flac":"flac","audio/aac":"aac"};var ht="/functions/v1/world-engine/v1",zt="https://api.storvia.ai";function Qt(){return window.__STORVIA__||{}}function Xt(o,e=3e4){let t=Qt();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let i=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,lang:a.payload.lang,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(i),s(),c();let d=window;d.__STORVIA__=a,n(a)}o.send(y("ready",{}))})}var ae=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.presetId="";this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0;this.previewVoices=new Map}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new x({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?d=>d.source===null||d.source===window:d=>d.source===window.parent,customSend:t?d=>e.callHandler("storviaBus",d):void 0}),Be(d=>this.bus.send(d));let n=await Xt(this.bus),r=n.apiBase;if(!r)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${r}${ht}`,this.isPreview=!!n.preview,this.previewConfig=n.previewConfig,!n.gameId)throw new u("GAME_NOT_FOUND","window.__STORVIA__.gameId is not set. The platform must inject it before SDK init.");if(this.gameId=n.gameId,!n.accessToken)throw new u("UNAUTHORIZED","window.__STORVIA__.accessToken is not set. The platform must inject the user token before SDK init.");if(this.accessToken=n.accessToken,$e(n.lang),this.http=new ie(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000",this.models=n.models??[],this.modelId=n.selectedModelId||this.models[0]?.id||"";let[d,g]=await Promise.all([this.fetchPreviewSnapshot(),this.modelId?Promise.resolve(null):this.fetchModels()]);g&&(this.models=g,this.modelId=g[0]?.id||""),this.presetId=n.presetId||"";let p=()=>this.gameId,m=()=>this.conversationId,h=()=>this.modelId,C=()=>{let v=this.models.find(_=>_.id===this.modelId);return v?se(v):void 0},w=()=>this.presetId||void 0;this.chat=new V(this.http,p,m,h,!0,this.previewConfig,C,w),this.characters=new H(this.http,m,!0,d.characters,d.characterStates),this.tts=new Z(()=>this.http.ttsClient(),m,p,v=>this.getCharacterVoice(v),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,m,!0,d.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,m,!0,d.inventory),this.world=new j(this.http,m,!0,d.world),this.player=new K(this.http,m,!0,d.player,d.playerState),this.custom=new q(this.http,m,p,!0,d.custom,d.custom_inject),this.save=new z(this.http,m,p,!0,d.save_data),this.state=new Q(this.http,m,!0),this.memory=new X(this.http,m,!0),this.host=new N(v=>this.bus.send(v),!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}if(!n.conversationId)throw new u("NOT_INITIALIZED","window.__STORVIA__.conversationId is not set. The platform must inject it before SDK init.");this.conversationId=n.conversationId,this.modelId=n.selectedModelId||"",this.modelId||(this.models=await this.fetchModels(),this.modelId=this.models[0]?.id||""),this.presetId=n.presetId||"";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(g=>g.id===this.modelId);return d?se(d):void 0},a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!1,void 0,l,a),this.characters=new H(this.http,s),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s),this.inventory=new B(this.http,s),this.world=new j(this.http,s),this.player=new K(this.http,s),this.custom=new q(this.http,s,i),this.save=new z(this.http,s,i),this.state=new Q(this.http,s),this.memory=new X(this.http,s),this.host=new N(d=>this.bus.send(d),!1),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""})}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}listenForPreviewMessages(){this.bus.on("set-model",e=>{this.modelId=e.payload.modelId||""}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""}),this.bus.on("config-update",e=>{this.previewConfig=e.payload.previewConfig,this.chat&&this.chat.updatePreviewConfig(this.previewConfig),this.refreshPreviewSnapshot().catch(t=>{console.warn("[Storvia SDK] refreshPreviewSnapshot failed:",t)})})}async getCharacterVoice(e){return this.isPreview?this.previewVoices.get(e):(await this.http.get(`/conversations/${this.conversationId}/characters/${encodeURIComponent(e)}`)).voice}async fetchPreviewSnapshot(){let e={game_id:this.gameId};this.previewConfig&&("game_config"in this.previewConfig&&(e.game_config=this.previewConfig.game_config),"game_state"in this.previewConfig&&(e.game_state_override=this.previewConfig.game_state));let t=await this.http.post("/preview/initial-snapshot",e);return this.previewVoices=new Map(t.characters.map(n=>[n.name,n.voice])),{...t,characters:t.characters.map(({voice:n,...r})=>({...r,hasVoice:!!n}))}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();this.characters?.setInitial(e.characters,e.characterStates),this.player?.setInitial(e.player,e.playerState),this.inventory?.setInitial(e.inventory),this.relationships?.setInitial(e.relationships),this.world?.setInitial(e.world),this.custom?.setInitial(e.custom,e.custom_inject),this.save?.setInitial(e.save_data)}async fetchModels(e=!1){try{return await this.http.get("/models",e?void 0:{locale:re()})}catch{}return[]}async initDev(e){if(this.initialized)return;this.baseUrl=`${zt}${ht}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new ie(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(!!e.model),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?qe(t,e.model):void 0;e.model&&!r&&console.warn(`[Storvia SDK] dev.model "${e.model}" not found, falling back to the first model. Available:`,t.map(se)),this.modelId=r?.id||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(g=>g.id===this.modelId);return d?se(d):void 0};this.presetId=e.preset||"";let a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!0,void 0,l,a),this.characters=new H(this.http,s,!0,n.characters,n.characterStates),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s,!0,n.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,s,!0,n.inventory),this.world=new j(this.http,s,!0,n.world),this.player=new K(this.http,s,!0,n.player,n.playerState),this.custom=new q(this.http,s,i,!0,n.custom,n.custom_inject),this.save=new z(this.http,s,i,!0,n.save_data),this.state=new Q(this.http,s,!0),this.memory=new X(this.http,s,!0),this.host=new N(()=>{},!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e,locale:re()};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,assetId:i.asset_id,name:i.name,nameI18n:i.meta.name_i18n,url:i.url,assetType:i.asset_type,category:i.category,categoryI18n:i.category_i18n,tags:i.tags.map(s=>({id:s.id,label:s.label,labelI18n:s.label_i18n}))}))}};async function ut(o){Ge();let e=new ae;return o?.dev?await e.initDev(o.dev):await e.init(),e}function Ae(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function pt(o){return Ae(o)?o.value:o}0&&(module.exports={HOST_NOTIFY_MAX_LENGTH,HOST_NOTIFY_MIN_INTERVAL_MS,HOST_PANEL_SCOPES,HOST_REFRESH_MIN_INTERVAL_MS,HostModule,MAIN_CHAT_TOPIC,PLAYER_ID,PROTOCOL_VERSION,StorviaBus,StorviaError,StorviaSDK,createStorviaSDK,envelope,extractFieldValue,isProtocolEnvelope,isRichFieldValue,setToastEnabled,showToast});
package/dist/index.esm.js CHANGED
@@ -117,6 +117,6 @@ var u=class extends Error{constructor(e,t,n){super(t),this.name="StorviaError",t
117
117
  `,ft={success:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',error:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',warning:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',info:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>'},Ve=!0;function vt(o){Ve=o}function It(){if(typeof document>"u")return null;let o=document.getElementById(le);if(!o){if(!document.getElementById(Le)){let e=document.createElement("style");e.id=Le,e.textContent=mt,document.head.appendChild(e)}o=document.createElement("div"),o.id=le,document.body.appendChild(o)}return o}function he(o,e="info",t=3500,n){if(!Ve)return;let r=It();if(!r)return;let i=t<=0,s=document.createElement("div");s.className=`storvia-toast ${e}`,s.innerHTML=`
118
118
  <span class="storvia-toast-icon">${ft[e]}</span>
119
119
  <span class="storvia-toast-msg"></span>
120
- `;let c=s.querySelector(".storvia-toast-msg");c&&(c.textContent=o);let l=()=>{s.isConnected&&(s.classList.add("leaving"),s.classList.remove("show"),setTimeout(()=>s.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(d){console.error("[Storvia toast] action error:",d)}l()}),s.appendChild(a)}if(i){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label",de("close")),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",l),s.appendChild(a)}r.appendChild(s),requestAnimationFrame(()=>s.classList.add("show")),i||setTimeout(l,t)}function Et(o){let e=o.filter(t=>t).map(t=>`\u300C${t}\u300D`).join("");return de("violationWords").replace("{words}",e)}var Tt=3e3,$e={};function Ge(o){let e=Date.now();if(!(e-($e[o]??0)<Tt)){if($e[o]=e,!ge){console.warn(`[Storvia] navigate \u2192 wallet(${o})\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u751F\u4EA7\u73AF\u5883\u7531\u5BBF\u4E3B\u5F39\u5145\u503C\u5F15\u5BFC / \u8DF3\u94B1\u5305\u9875\u3002`);return}try{ge(C("navigate",{target:"wallet",reason:o}))}catch(t){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",t)}}}function R(o,e,t){if(o==="GENERATION_ABORTED")return;if(o==="INSUFFICIENT_CREDITS")return Ge("insufficient_credits");if(o==="DAISY_CARD_REQUIRED")return Ge("daisy_card_required");let n=o==="VIOLATION_WORD_DETECTED"&&t?.length?Et(t):Ue(o)||e||de("unknownError");he(n,o==="RATE_LIMITED"?"warning":"error")}function wt(o,e){let t=e?.tickMs??100,n=e?.baseLagMs??1e3,r=e?.maxLagMs??2500,i=e?.minCharsPerTick??2,s="",c=null,l=0,a=0,d=()=>Math.min(r,Math.max(n,l*1.35)),h=()=>{let w=Math.max(i,Math.ceil(s.length*t/d()));if(w>=s.length)w=s.length;else{let _=s.charCodeAt(w-1);_>=55296&&_<=56319&&w++}let v=s.slice(0,w);s=s.slice(w),v&&o(v)},m=()=>{c=null,h(),s&&(c=setTimeout(m,t))};return{push:w=>{let v=Date.now();if(a>0){let _=Math.min(v-a,r);l=l>0?l*.7+_*.3:_}a=v,s+=w,c===null&&m()},flush:()=>{c!==null&&(clearTimeout(c),c=null),s&&(o(s),s="")},cancel:()=>{c!==null&&(clearTimeout(c),c=null),s=""}}}function me(o){let e=wt(o.onChunk);return{cbs:{onChunk:n=>e.push(n),onDone:(n,r)=>{e.flush(),o.onDone(n,r)},onAborted:o.onAborted?n=>{e.flush(),o.onAborted(n)}:void 0,onState:o.onState?(n,r)=>{e.flush(),o.onState(n,r)}:void 0,onThinking:o.onThinking?n=>{e.flush(),o.onThinking(n)}:void 0,onCreatedCharacters:o.onCreatedCharacters?n=>{e.flush(),o.onCreatedCharacters(n)}:void 0,onReconnect:o.onReconnect},flush:()=>e.flush()}}var He="0.10.9";function $(o,e){if(e.aborted){if(o.onAborted){o.onAborted(e.aborted);return}o.onDone(e.aborted.id,{truncated:!1});return}o.onDone(e.messageId,e.truncated===void 0?void 0:{truncated:e.truncated})}var T=class T{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}ttsClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/tts"),this.token,this.debug,this.devApiKey)}asrClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/asr"),this.token,this.debug,this.devApiKey)}async postForm(e,t,n=T.REQUEST_TIMEOUT){let r=this.buildHeaders();delete r["Content-Type"];let{controller:i,clear:s}=this.createTimeoutController(n);try{let c=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:r,body:t,signal:i.signal});return(await this.handleResponseWithRaw(c)).data}catch(c){let l=this.wrapAbortError(c);throw l===c&&this.maybeShowNetworkToast(c),l}finally{s()}}async postAudio(e,t){let{controller:n,clear:r}=this.createTimeoutController();try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:n.signal});i.ok||await this.handleResponseWithRaw(i);let{audio_url:s}=await i.json(),c=await fetch(s,{signal:n.signal});if(!c.ok)throw new u("TTS_UPSTREAM_FAILED",`Audio download failed: HTTP ${c.status}`);if(c.headers.get("Content-Type")?.includes("application/json"))throw new u("TTS_UPSTREAM_FAILED","Audio download returned JSON");return await c.blob()}catch(i){let s=this.wrapAbortError(i);throw s===i&&this.maybeShowNetworkToast(i),s}finally{r()}}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||R("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return R("REQUEST_TIMEOUT"),t}return e}createTimeoutController(e=T.REQUEST_TIMEOUT){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return{controller:t,clear:()=>clearTimeout(n)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e["x-client-info"]=`storvia-sdk/${He}`,e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:l,durationMs:a,modelName:d}=e,h="%c[Storvia SDK]",m="color: #6366f1; font-weight: bold",f=a!==void 0?` (${a}ms)`:"",p=i!==void 0?` [${i}]`:"",y=d?` [model: ${d}]`:"";l?(console.groupCollapsed(`${h} %c${t} ${n}${p}${y}${f} %c\u2717`,m,"color: #e0e0e0","color: #ef4444"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),console.error("Error:",l),console.groupEnd()):(console.groupCollapsed(`${h} %c${t} ${n}${p}${y}${f} %c\u2713`,m,"color: #e0e0e0","color: #22c55e"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),c!==void 0&&c!==s&&console.log("Response (data):",c),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,d])=>n.searchParams.set(a,d));let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});l(),i=a.status;let{raw:d,data:h}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:h,durationMs:Date.now()-r}),h}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r}),d===a&&this.maybeShowNetworkToast(a),d}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:c.signal});l(),i=a.status;let{raw:d,data:h}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:h,durationMs:Date.now()-r,modelName:n?.modelName}),h}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r,modelName:n?.modelName}),d===a&&this.maybeShowNetworkToast(a),d}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async delete(e){let t=Date.now(),n,r,{controller:i,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:i.signal});s(),n=c.status;let{raw:l,data:a}=await this.handleResponseWithRaw(c);return r=l,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let l=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:l,durationMs:Date.now()-t}),l===c&&this.maybeShowNetworkToast(c),l}}async stream(e,t,n,r,i,s,c,l,a,d,h,m){let f=Date.now(),p=i?.modelName?` [model: ${i.modelName}]`:"",y=[],w=E=>{this.debug&&y.push({t:Date.now()-f,event:E})},{cbs:v,flush:_}=me({onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:l,onReconnect:d,onAborted:h,onBase:m}),Ce=new AbortController,N=null,S=null,b=null,D=()=>{N!==null&&(clearTimeout(N),N=null),S!==null&&(clearTimeout(S),S=null)},_e=E=>{b=E,D(),Ce.abort()};N=setTimeout(()=>_e("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let A;try{A=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:Ce.signal})}catch(E){if(D(),b){let I=new u(b,"Request timed out");throw R(b),this.log({method:"STREAM",path:e,body:t,error:I,durationMs:Date.now()-f,modelName:i?.modelName}),I}throw this.maybeShowNetworkToast(E),E}if(N!==null&&(clearTimeout(N),N=null),!A.ok){D();let E=await A.text().catch(()=>""),I={};try{I=JSON.parse(E)}catch{}let P=I.code||"INTERNAL_ERROR",g=I.message||I.error||I.details,Pe=Array.isArray(I.matched_words)?I.matched_words:void 0,be=new u(P,g||`HTTP ${A.status}`,Pe);throw R(P,g,Pe),this.log({method:"STREAM",path:e,body:t,status:A.status,rawResponse:E,error:be,durationMs:Date.now()-f,modelName:i?.modelName}),be}let Re=A.body?.getReader();if(!Re)throw D(),new u("INTERNAL_ERROR","No response body for stream");S=setTimeout(()=>_e("MODEL_LOADING_TIMEOUT"),T.INITIAL_TIMEOUT);let Se=new TextDecoder,J="",pe,ie,k="",se,ae,x="",U=!1,O=null,Ae=E=>{if(U)return;let I=E.endsWith("\r")?E.slice(0,-1):E;if(I.startsWith("id: ")){ae=I.slice(4);return}if(!I.startsWith("data: "))return;let P=I.slice(6);if(P==="[DONE]"){w("[DONE]"),U=!0;return}try{let g=JSON.parse(P);w(g),g.type==="done"&&g.id?(J=g.id,pe=g.truncated===!0):g.type==="aborted"?(ie={id:typeof g.id=="string"?g.id:"",persisted:g.persisted===!0},U=!0):g.type==="error"?(O=new u(g.code||"INTERNAL_ERROR",g.message||"Generation failed",Array.isArray(g.matched_words)?g.matched_words:void 0),U=!0):g.type==="state"?(v.onState?.(g.delta,g.full??null),Array.isArray(g.createdNames)&&g.createdNames.length&&v.onCreatedCharacters?.(g.createdNames)):g.type==="start"?(S!==null&&(clearTimeout(S),S=null),typeof g.base_content=="string"&&m?.(g.base_content)):g.type==="thinking"?(g.status==="start"||g.status==="end")&&v.onThinking?.(g.status):g.content&&(S!==null&&(clearTimeout(S),S=null),k+=g.content,v.onChunk(g.content))}catch{w({raw:P})}ae!==void 0&&(se=ae,ae=void 0)},Oe=()=>{if(D(),O)throw _(),R(O.code,O.message,O.matchedWords),this.log({method:"STREAM",path:e,body:t,error:O,durationMs:Date.now()-f,modelName:i?.modelName}),O;this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${k.length} chars):`,k),console.log("Message ID:",J),ie&&console.log("Aborted:",ie),console.log(`SSE events (${y.length}):`,y),console.groupEnd()),$(v,{messageId:J,truncated:pe,aborted:ie})};try{for(;;){let{done:E,value:I}=await Re.read();if(E)break;x+=Se.decode(I,{stream:!0});let P=x.split(`
121
- `);x=P.pop()??"";for(let g of P)Ae(g);if(U){Oe();return}}if(x+=Se.decode(),x&&Ae(x),U){Oe();return}}catch(E){if(D(),O)throw O;if(b){let I=new u(b,"Stream did not start in time");if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2717 ${b}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${k.length} chars):`,k),console.log(`SSE events (${y.length}):`,y),console.error("Timeout:",I),console.groupEnd()),a){await this.resumeLoop(a,se,v,{finalize:!0});return}throw R(b),_(),I}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${k.length} chars):`,k),console.log(`SSE events (${y.length}):`,y),console.error("Stream error:",E),console.groupEnd()),a){await this.resumeLoop(a,se,v,{finalize:!0});return}throw _(),E}if(D(),J){$(v,{messageId:J,truncated:pe});return}if(a){await this.resumeLoop(a,se,v,{finalize:!0});return}_()}async resumeLoop(e,t,n,r){let i=t;for(let c=1;c<=T.RECONNECT_MAX_ATTEMPTS;c++){let l=Math.min(T.RECONNECT_BACKOFF_CAP,1e3*2**(c-1));await new Promise(h=>setTimeout(h,l)),n.onReconnect?.({attempt:c});let a={messageId:"",lastId:i},d;try{d=await this.pumpGetStream(e.conversationId,e.topic,i,a,n)}catch{continue}if(i=a.lastId??i,d==="done"){if(a.errorCode)throw this.terminalError(a);$(n,a);return}if(d==="inactive"){(a.messageId||r?.finalize)&&$(n,a);return}}let s=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw R("STREAM_INTERRUPTED"),s}async resumeStream(e,t,n){let{cbs:r}=me(n),i={messageId:""},s;try{s=await this.pumpGetStream(e,t,void 0,i,r)}catch{await this.resumeLoop({conversationId:e,topic:t},i.lastId,r);return}if(s==="done"){if(i.errorCode)throw this.terminalError(i);$(r,i);return}if(s==="inactive"){i.messageId&&$(r,i);return}await this.resumeLoop({conversationId:e,topic:t},i.lastId,r)}terminalError(e){let t=new u(e.errorCode??"INTERNAL_ERROR",e.errorMessage||"Generation failed",e.errorMatchedWords);return R(t.code,t.message,t.matchedWords),t}async pumpGetStream(e,t,n,r,i){let s=new URL(`${this.baseUrl}/conversations/${encodeURIComponent(e)}/stream`);n&&s.searchParams.set("from",n),t&&s.searchParams.set("topic",t);let c=new AbortController,l=setTimeout(()=>c.abort(),T.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(l)}if(!a.ok)throw new u("STREAM_INTERRUPTED",`Resume HTTP ${a.status}`);if(!(a.headers.get("content-type")||"").includes("text/event-stream"))return"inactive";let h=a.body?.getReader();return h?await this.pumpReader(h,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},T.RESUME_STALL_TIMEOUT)};c();let l="",a=!1,d=h=>{if(a)return;let m=h.endsWith("\r")?h.slice(0,-1):h;if(m.startsWith("id: ")){i=m.slice(4);return}if(!m.startsWith("data: "))return;let f=m.slice(6);if(f==="[DONE]"){a=!0;return}try{let p=JSON.parse(f);p.type==="done"&&p.id?(t.messageId=p.id,t.truncated=p.truncated===!0):p.type==="aborted"?(t.aborted={id:typeof p.id=="string"?p.id:"",persisted:p.persisted===!0},a=!0):p.type==="error"?(t.errorCode=p.code||"INTERNAL_ERROR",t.errorMessage=p.message||"Generation failed",Array.isArray(p.matched_words)&&(t.errorMatchedWords=p.matched_words),a=!0):p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="start"?typeof p.base_content=="string"&&n.onBase?.(p.base_content):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}i!==void 0&&(t.lastId=i,i=void 0)};try{for(;;){let{done:h,value:m}=await e.read();if(h)break;c(),l+=r.decode(m,{stream:!0});let f=l.split(`
122
- `);l=f.pop()??"";for(let p of f)d(p);if(a)return s&&clearTimeout(s),"done"}if(l+=r.decode(),l&&d(l),a)return s&&clearTimeout(s),"done"}catch{}finally{s&&clearTimeout(s)}return"eof"}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let r=n&&typeof n=="object"?n:{},i={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.error_code??r.code,c=s==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":s==="TTS_RATE_LIMITED"?"RATE_LIMITED":s||i[e.status]||"INTERNAL_ERROR",l=Array.isArray(r.matched_words)?r.matched_words:void 0,a=new u(c,r.message||`HTTP ${e.status}`,l);throw R(c,r.message,l),a}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.INITIAL_TIMEOUT=3e4,T.RESUME_STALL_TIMEOUT=6e4,T.RECONNECT_MAX_ATTEMPTS=10,T.RECONNECT_BACKOFF_CAP=15e3;var re=T;var fe=o=>o.trim().toLowerCase();function oe(o){let e=ne(),t=o.name_i18n??{};return t[e]||t[e.replace("-","_")]||o.name}function We(o,e){let t=fe(e);return o.find(n=>fe(n.name)===t)??o.find(n=>Object.values(n.name_i18n??{}).some(r=>typeof r=="string"&&fe(r)===t))}var yt="storvia_chat_main";function Ct(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let o=new Uint8Array(16);crypto.getRandomValues(o),o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=Array.from(o,t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}var Be=20,je=40,F=class{constructor(e,t,n,r,i=!1,s,c,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewHistory=[];this.previewConfig=s,this.getModelName=c,this.getPreset=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.(),client_message_uuid:Ct()};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{game_id:this.getGameId(),conversation_id:this.getConversationId(),role:e.role,content:e.content,topic:e.topic})}async generate(e){if(this.isPreview)return this.sendPreview({message:"",topic:e.topic,sceneKey:e.sceneKey,stream:e.stream,onChunk:e.onChunk,onDone:e.onDone,onState:e.onState,onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters});let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/generate",t,this.reqMeta())}async once(e){if(this.isPreview)return this.oncePreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,stream:e.stream===!0,preset:this.getPreset?.()};if(!e.stream)return this.http.post("/once",t,this.reqMeta());let n="";return await this.http.stream("/once",t,r=>{n+=r,e.onChunk?.(r)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:n}}async oncePreview(e){let t={model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,history_messages:[],preset:this.getPreset?.()};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language);let r="";return await this.http.stream("/preview",t,i=>{r+=i,e.onChunk?.(i)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:r}}async retry(e={}){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.retry() is not available in preview mode. Publish the game and test on the Storvia platform.");let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/retry",t,this.reqMeta())}async continue(e={}){if(this.isPreview)return;let t={conversation_id:this.getConversationId(),topic:e.topic??null,game_id:this.getGameId(),preset:this.getPreset?.(),scene_key:e.sceneKey,extract:e.extract};await this.http.stream("/continue",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted,e.onBase)}async cancel(e={}){if(this.isPreview)return{active:!1};let t=await this.http.post(`/conversations/${encodeURIComponent(this.getConversationId())}/cancel`,{topic:e.topic});return{active:t.active===!0,generationId:t.generation_id}}async messages(e){if(this.isPreview)return{data:[],hasMore:!1,nextCursor:null};let t={conversation_id:this.getConversationId(),order:e.order,limit:String(e.limit??20)};e.topic&&(t.topic=e.topic),e.cursor&&(t.cursor_uuid=e.cursor.uuid,t.cursor_created_at=e.cursor.createdAt);let n=await this.http.get("/messages",t);return{data:n.messages.map(r=>({uuid:r.uuid,role:r.role,content:r.content,topic:r.topic,status:r.status,model:r.model,createdAt:r.created_at,truncated:r.truncated===!0})),hasMore:n.has_more,nextCursor:n.next_cursor?{uuid:n.next_cursor.cursor_uuid,createdAt:n.next_cursor.cursor_created_at}:null}}async edit(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.edit() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.patch(`/messages/${encodeURIComponent(e.uuid)}`,{content:e.content});return{uuid:t.uuid,role:t.role,content:t.content,updatedAt:t.updated_at}}async delete(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.delete() is not available in preview mode. Publish the game and test on the Storvia platform.");return{uuid:(await this.http.delete(`/messages/${encodeURIComponent(e.uuid)}`)).uuid}}async rollback(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.rollback() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.post(`/messages/${encodeURIComponent(e.uuid)}/rollback`,{});return{deletedCount:t.deleted_count,deletedUuids:t.deleted_uuids,restoredGameState:t.restored_game_state}}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:G(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting,onAborted:e.onAborted})}async sendPreview(e){let t=e.message.trim().length>0,n=this.previewHistory.slice(t?-(Be-1):-Be);t&&this.pushPreviewHistory({role:"user",content:e.message});let r={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:n,preset:this.getPreset?.()};this.previewConfig?r.prompt_config=this.previewConfig:r.game_id=this.getGameId();let i=this.previewConfig;if(i?.reply_length&&(r.reply_length=i.reply_length),i?.reply_language&&(r.reply_language=i.reply_language),e.stream){let h="";await this.http.stream("/preview",r,m=>{h+=m,e.onChunk?.(m)},(m,f)=>{h&&this.pushPreviewHistory({role:"assistant",content:h}),e.onDone?.(m,f)},this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters);return}let s="",c=null,l=null,a=[];await this.http.stream("/preview",r,h=>{s+=h},()=>{},this.reqMeta(),(h,m)=>{c=h,l=m,e.onState&&e.onState(c,l)},void 0,h=>{a=h,e.onCreatedCharacters&&e.onCreatedCharacters(h)}),s&&this.pushPreviewHistory({role:"assistant",content:s});let d={id:"",content:s,truncated:!1};return c&&(d.delta=c,l&&(d.full=l)),a.length&&(d.createdNames=a),d}pushPreviewHistory(e){this.previewHistory.push(e),this.previewHistory.length>je&&this.previewHistory.splice(0,this.previewHistory.length-je)}};function G(o){if(o)return(e,t)=>o(e,t)}var Ie=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let r=this.mem[e]||{};return t?{...r[t]||{}}:{...r}}let n=t?{group:t}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,n)}async update(e,t,n){if(this.isPreview){let r=this.mem[e]||(this.mem[e]={});r[t]={...r[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}async remove(e,t,n){if(n.length){if(this.isPreview){let r=this.mem[e]?.[t];if(r)for(let i of n)delete r[i];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeKeys:n})}}async removeGroup(e,t){if(this.isPreview){let n=this.mem[e];n&&delete n[t];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeGroup:!0})}},V=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(Ke)),this.state=new Ie(e,t,n,i)}previewNames(){return this.mem.map(e=>e.name)}setInitial(e,t){this.mem=e?e.map(Ke):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Ye):(await this.http.get(`/conversations/${this.getConversationId()}/characters`)).map(ve)}async get(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return n?Ye(n):{name:e,hasVoice:!1}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`);return ve(t)}async add(e){if(this.isPreview){this.mem.push({...e,isPreset:!1});return}await this.http.post(`/conversations/${this.getConversationId()}/characters`,e)}async update(e,t){if(this.isPreview){let n=this.mem.find(r=>r.name===e);n&&Object.assign(n,t);return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`,t)}async remove(e){if(this.isPreview){this.mem=this.mem.filter(t=>t.name!==e);return}await this.http.delete(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}async merge(e,t){if(this.isPreview){if(this.mem.find(r=>r.name===e)?.isPreset)throw new u("INVALID_REQUEST","\u9884\u8BBE\u89D2\u8272\u4E0D\u53EF\u88AB\u5408\u5E76");if(e===t||!this.mem.some(r=>r.name===t))throw new u("INVALID_REQUEST","\u76EE\u6807\u89D2\u8272\u4E0D\u5B58\u5728\u6216\u4E0E\u6765\u6E90\u76F8\u540C");this.mem=this.mem.filter(r=>r.name!==e);return}await this.http.post(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/merge`,{target:t})}async detail(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return{name:e,avatar:n?.avatar,description:n?.description,hasVoice:n?.hasVoice===!0,...n?.introduction!==void 0?{introduction:n.introduction}:{},...n?.visibleAtStart!==void 0?{visibleAtStart:n.visibleAtStart}:{},userDescription:n?.userDescription,...n?.gender?{gender:n.gender}:{},...n?.isPreset!==void 0?{isPreset:n.isPreset}:{},state:await this.state.get(e)}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`);return ve(t)}async setPriority(e,t){let n=Math.max(0,Math.min(100,Math.round(t)));this.isPreview||await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{priority:n})}};function Ke(o){return{name:o.name,description:o.description,avatar:o.avatar,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Ye(o){return{name:o.name,avatar:o.avatar,description:o.description,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function ve(o){let{voice:e,...t}=o;return{...t,hasVoice:!!e}}var _t="\u73A9\u5BB6",Rt=["Player","player","PLAYER","\u30D7\u30EC\u30A4\u30E4\u30FC","\uD50C\uB808\uC774\uC5B4","\u4E3B\u63A7","{{user}}","user"],Ee=o=>o.toLowerCase().replace(/[\s_\-]+/g,""),St=new Set(["\u73A9\u5BB6",...Rt].map(Ee));function qe(o,e){if(o==="\u73A9\u5BB6")return o;let t=Ee(o);return St.has(t)?e.some(n=>Ee(n)===t)?o:"\u73A9\u5BB6":o}var H=class{constructor(e,t,n=!1,r,i=()=>[]){this.http=e;this.getConversationId=t;this.isPreview=n;this.getCharacterNames=i;this.mem=[];r&&(this.mem=r.map(s=>({...s})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}entity(e){return this.isPreview?qe(e,this.getCharacterNames()):e}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t);let n=this.mem.find(r=>r.from===e&&r.to===t);if(n)return{...n};throw new Error("Relationship not found")}return this.http.get(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}async add(e){if(this.isPreview){this.mem.push({...e,from:this.entity(e.from),to:this.entity(e.to)});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){e=this.entity(e),t=this.entity(t);let r=this.mem.find(i=>i.from===e&&i.to===t);r?Object.assign(r,n):this.mem.push({from:e,to:t,...n});return}await this.http.patch(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,n)}async remove(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t),this.mem=this.mem.filter(n=>!(n.from===e&&n.to===t));return}await this.http.delete(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}};function ze(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function Te(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let r={};for(let[i,s]of Object.entries(n))r[i]=ze(s);e[t]=r}return e}function At(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=ze(n);return e}var W=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=Te(r))}setInitial(e){this.mem=e?Te(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[r,i]of Object.entries(this.mem))n[r]={...i};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return At(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return Te(t)}async add(e){let{group:t,name:n,count:r=1,desc:i,iconUrl:s}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:r};i!==void 0&&(l.desc=i),s!==void 0&&(l.iconUrl=s),this.mem[t][n]=l;return}let c={group:t,name:n,count:r};i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,c)}async update(e){let{group:t,name:n,count:r,desc:i,iconUrl:s}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];r!==void 0&&(a.count=r),i!==void 0&&(a.desc=i),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,c)}async remove(e){let{group:t,name:n}=e;if(this.isPreview){this.mem[t]&&delete this.mem[t][n];return}await this.http.delete(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`)}async removeBatch(e){if(this.isPreview){for(let{group:t,name:n}of e)this.mem[t]&&delete this.mem[t][n];return}e.length!==0&&await this.http.post(`/conversations/${this.getConversationId()}/inventory/batch-delete`,{items:e})}async move(e){let{fromGroup:t,toGroup:n,name:r,newName:i}=e;if(this.isPreview){let s=this.mem[t];if(!s||!(r in s))throw new Error(`Source item "${t}/${r}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let c=i||r;if(t===n&&c===r)return;if(c in this.mem[n])throw new Error(`Item "${c}" already exists in target group`);this.mem[n][c]=s[r],delete s[r];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:r,newName:i})}async ensureGroup(e){if(this.isPreview){this.mem[e]||(this.mem[e]={});return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}`,{})}async removeGroup(e,t){let n=t?.cascade??!1;if(this.isPreview){let i=this.mem[e];if(i&&Object.keys(i).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let r=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${r}`)}};var B=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:this.http.get(`/conversations/${this.getConversationId()}/world`)}async update(e){if(this.isPreview){Object.assign(this.mem,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/world`,e)}};var we=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e){if(this.isPreview)return e?{...this.mem[e]||{}}:{...this.mem};let t=e?{group:e}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/player/state`,t)}async update(e,t){if(this.isPreview){this.mem[e]={...this.mem[e]||{},...t};return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,values:t})}async remove(e,t){if(t.length){if(this.isPreview){let n=this.mem[e];if(n)for(let r of t)delete n[r];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeKeys:t})}}async removeGroup(e){if(this.isPreview){delete this.mem[e];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeGroup:!0})}},j=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new we(e,t,n,i)}setInitial(e,t){this.memPersona=e?{...e}:{name:""},this.state.setInitial(t)}async get(){return this.isPreview?{...this.memPersona}:this.http.get(`/conversations/${this.getConversationId()}/player`)}async update(e){if(this.isPreview){Object.assign(this.memPersona,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/player`,e)}};function K(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var Y=class{constructor(e,t,n,r=!1,i,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};i&&(this.mem=Qe(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Qe(e):{},this.memInject=t?{...t}:{}}async get(e){if(this.isPreview)return e!==void 0?this.mem[e]:{...this.mem};let t=await this.http.get(K(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,i]of Object.entries(e))typeof i=="object"&&i!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...i}:this.mem[r]=i,t?.inject!==void 0&&(this.memInject[r]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(K(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(K(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,this.getGameId()),{inject:t})}getInject(){return{...this.memInject}}async delete(e){if(this.isPreview){delete this.mem[e],delete this.memInject[e];return}await this.http.delete(K(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}`,this.getGameId()))}async setGroupField(e,t,n){if(this.isPreview){(!this.mem[e]||typeof this.mem[e]!="object")&&(this.mem[e]={}),this.mem[e][t]=n;return}await this.http.patch(K(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()),{value:n})}async deleteGroupField(e,t){if(this.isPreview){if(typeof this.mem[e]=="object"&&this.mem[e]!==null){let n=this.mem[e];delete n[t]}return}await this.http.delete(K(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Qe(o){let e={};for(let[t,n]of Object.entries(o))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function Xe(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var q=class{constructor(e,t,n,r=!1,i){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(Xe(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Xe(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var z=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n}async get(){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.state.get() is not available in preview mode. Publish the game and test on the Storvia platform. (Use per-module get() like storvia.world.get() if you need to inspect state during preview.)");return this.http.get(`/conversations/${this.getConversationId()}/state`)}};var Q=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null;this.wb=null;this.worldbook={get:async()=>this.isPreview?this.wb?Ze(this.wb):null:(await this.http.get(`/conversations/${this.getConversationId()}/worldbook`)).worldbook,update:async e=>{let t=typeof e=="string"?{content:e}:{...e};if(t.content!==void 0&&(t.content=(t.content??"").trim()),t.entries!==void 0&&(t.entries=Ot(t.entries)),this.isPreview){let r=this.wb?.presets??[],i=t.enabledPresets?r.map(c=>({...c,enabled:t.enabledPresets.includes(c.id)})):r,s={content:t.content??this.wb?.content??"",contentWidget:t.contentWidget??this.wb?.contentWidget??!1,entries:t.entries??this.wb?.entries??[],presets:i,updated_at:new Date().toISOString()};return this.wb=s,Ze(s)}return(await this.http.patch(`/conversations/${this.getConversationId()}/worldbook`,t)).worldbook}}}async get(){return this.isPreview?this.mem?{...this.mem}:null:(await this.http.get(`/conversations/${this.getConversationId()}/summary`)).ai_summary}async update(e){let t=(e??"").trim();if(this.isPreview){let r={content:t,updated_at:new Date().toISOString()};return this.mem=r,{...r}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};function Ze(o){return{...o,entries:o.entries.map(e=>({...e,keys:[...e.keys]})),presets:(o.presets??[]).map(e=>({...e}))}}function Ot(o){return(o??[]).flatMap(e=>{let t=(e?.content??"").trim(),n=[...new Set((e?.keys??[]).map(s=>(s??"").trim()).filter(s=>s!==""))],r=e?.constant===!0;if(!t||!r&&n.length===0)return[];let i=(e?.title??"").trim();return[{id:e.id||Pt(),keys:n,content:t,...i?{title:i}:{},constant:r,enabled:e?.enabled!==!1,widget:e?.widget===!0}]})}function Pt(){let o=globalThis.crypto;return o?.randomUUID?o.randomUUID():`ewr-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var Je=60,et=1e3,ye=1e4,M=class{constructor(e,t=!1,n=()=>Date.now()){this.send=e;this.isPreview=t;this.now=n;this.lastNotifyAt=0;this.lastRefreshAt=0;this.lastRefreshMessagesAt=0}notify(e){let t=bt(e);if(!t)return!1;let n=this.now();return n-this.lastNotifyAt<et?!1:(this.lastNotifyAt=n,this.isPreview?(he(t,"info"),!0):(this.send(C("host-notify",{text:t})),!0))}refreshPanel(e){if(this.isPreview)return!1;let t=this.now();return t-this.lastRefreshAt<ye?!1:(this.lastRefreshAt=t,this.send(C("host-state-changed",e?.length?{scope:e}:{})),!0)}refreshMessages(){if(this.isPreview)return!1;let e=this.now();return e-this.lastRefreshMessagesAt<ye?!1:(this.lastRefreshMessagesAt=e,this.send(C("host-messages-changed",{})),!0)}};function bt(o){return typeof o!="string"?"":o.replace(/\s+/g," ").trim().slice(0,Je)}var Nt;function tt(){return Nt??(Nt=new Promise((o,e)=>{let t=indexedDB.open("storvia-sdk-speech",1);t.onupgradeneeded=()=>t.result.createObjectStore("audio"),t.onsuccess=()=>o(t.result),t.onerror=()=>e(t.error)}))}async function nt(o){let e=await tt();return new Promise((t,n)=>{let r=e.transaction("audio").objectStore("audio").get(o);r.onsuccess=()=>t(r.result??null),r.onerror=()=>n(r.error)})}async function rt(o,e){let t=await tt();return new Promise((n,r)=>{let i=t.transaction("audio","readwrite");i.objectStore("audio").put(e,o),i.oncomplete=()=>n(),i.onabort=()=>r(i.error)})}function ot(o){let e=o,t;do t=e,e=e.replace(/[((][^()()]*[))]/g,"");while(e!==t);return e.replace(/\s+/g," ").trim()}var X=class{constructor(e,t,n,r,i=!1){this.getHttp=e;this.getConversationId=t;this.getGameId=n;this.getVoice=r;this.isPreview=i;this.pending=new Map}async speak(e){let t=ot(e.text),n=await this.getVoice(e.character);if(!n)throw new u("TTS_UNKNOWN_VOICE","Character has no voice configured");let r=this.isPreview?this.getGameId():this.getConversationId(),i=JSON.stringify([r,n,t]),s={text:t,...this.isPreview?{voice:n}:{conversation_id:this.getConversationId(),character_name:e.character}},c=globalThis;if(c.__storviaNativeTts&&c.flutter_inappwebview){let d=await c.flutter_inappwebview.callHandler("storviaTts",{body:s,key:i});if(d.error){let m=d.error==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":d.error==="TTS_RATE_LIMITED"?"RATE_LIMITED":d.error;throw R(m),new u(m,d.error)}let h=Uint8Array.from(atob(d.audio),m=>m.charCodeAt(0));return{audio:new Blob([h],{type:"audio/mpeg"}),cached:d.cached}}let l=await nt(i);if(l)return{audio:l,cached:!0};let a=this.pending.get(i);return a||(a=this.getHttp().postAudio("/speak",s).then(async d=>{try{await rt(i,d)}catch{console.warn("[Storvia TTS] \u97F3\u9891\u7F13\u5B58\u4FDD\u5B58\u5931\u8D25")}return{audio:d,cached:!1}}),this.pending.set(i,a),a.then(()=>this.pending.delete(i),()=>this.pending.delete(i))),a}};var Z=class{constructor(e){this.getHttp=e}async transcribe(e){if(!e||typeof e!="object")throw new u("INVALID_REQUEST","Recognition options are required");if(!(e.audio instanceof Blob)||e.audio.size===0||e.audio.size>10485760)throw new u("ASR_BAD_AUDIO","Audio must be a non-empty file of at most 10 MB");let t=e.audio.type.split(";")[0].trim().toLowerCase(),n=e.format??Gt[t];if(!n||!Lt.includes(n))throw new u("ASR_BAD_AUDIO","Specify a supported audio format");if(e.context!==void 0&&typeof e.context!="string"||!it(e.languageHints,4)||!it(e.hotwords,50)||(e.context?.length??0)>400||e.hotwords?.some(i=>i.length>64))throw new u("INVALID_REQUEST","Recognition context, language hints, or hotwords exceed the limits");let r=new FormData;return r.append("file",e.audio,`audio.${n}`),r.append("format",n),e.context!==void 0&&r.append("context",e.context),e.languageHints!==void 0&&r.append("language_hints",JSON.stringify(e.languageHints)),e.hotwords!==void 0&&r.append("hotwords",JSON.stringify(e.hotwords)),this.getHttp().postForm("/transcribe",r,$t)}},Lt=["wav","mp3","m4a","webm","ogg","opus","flac","aac"],$t=15e4;function it(o,e){return o===void 0||Array.isArray(o)&&o.length<=e&&o.every(t=>typeof t=="string"&&t.trim().length>0)}var Gt={"audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav","audio/mpeg":"mp3","audio/mp3":"mp3","audio/mp4":"m4a","audio/x-m4a":"m4a","audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/opus":"opus","audio/flac":"flac","audio/x-flac":"flac","audio/aac":"aac"};var st="/functions/v1/world-engine/v1",Ft="https://api.storvia.ai";function Vt(){return window.__STORVIA__||{}}function Ht(o,e=3e4){let t=Vt();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let i=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,lang:a.payload.lang,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(i),s(),c();let d=window;d.__STORVIA__=a,n(a)}o.send(C("ready",{}))})}var ue=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.presetId="";this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0;this.previewVoices=new Map}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new L({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?d=>d.source===null||d.source===window:d=>d.source===window.parent,customSend:t?d=>e.callHandler("storviaBus",d):void 0}),Fe(d=>this.bus.send(d));let n=await Ht(this.bus),r=n.apiBase;if(!r)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${r}${st}`,this.isPreview=!!n.preview,this.previewConfig=n.previewConfig,!n.gameId)throw new u("GAME_NOT_FOUND","window.__STORVIA__.gameId is not set. The platform must inject it before SDK init.");if(this.gameId=n.gameId,!n.accessToken)throw new u("UNAUTHORIZED","window.__STORVIA__.accessToken is not set. The platform must inject the user token before SDK init.");if(this.accessToken=n.accessToken,Me(n.lang),this.http=new re(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000",this.models=n.models??[],this.modelId=n.selectedModelId||this.models[0]?.id||"";let[d,h]=await Promise.all([this.fetchPreviewSnapshot(),this.modelId?Promise.resolve(null):this.fetchModels()]);h&&(this.models=h,this.modelId=h[0]?.id||""),this.presetId=n.presetId||"";let m=()=>this.gameId,f=()=>this.conversationId,p=()=>this.modelId,y=()=>{let v=this.models.find(_=>_.id===this.modelId);return v?oe(v):void 0},w=()=>this.presetId||void 0;this.chat=new F(this.http,m,f,p,!0,this.previewConfig,y,w),this.characters=new V(this.http,f,!0,d.characters,d.characterStates),this.tts=new X(()=>this.http.ttsClient(),f,m,v=>this.getCharacterVoice(v),this.isPreview),this.asr=new Z(()=>this.http.asrClient()),this.relationships=new H(this.http,f,!0,d.relationships,()=>this.characters.previewNames()),this.inventory=new W(this.http,f,!0,d.inventory),this.world=new B(this.http,f,!0,d.world),this.player=new j(this.http,f,!0,d.player,d.playerState),this.custom=new Y(this.http,f,m,!0,d.custom,d.custom_inject),this.save=new q(this.http,f,m,!0,d.save_data),this.state=new z(this.http,f,!0),this.memory=new Q(this.http,f,!0),this.host=new M(v=>this.bus.send(v),!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}if(!n.conversationId)throw new u("NOT_INITIALIZED","window.__STORVIA__.conversationId is not set. The platform must inject it before SDK init.");this.conversationId=n.conversationId,this.modelId=n.selectedModelId||"",this.modelId||(this.models=await this.fetchModels(),this.modelId=this.models[0]?.id||""),this.presetId=n.presetId||"";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(h=>h.id===this.modelId);return d?oe(d):void 0},a=()=>this.presetId||void 0;this.chat=new F(this.http,i,s,c,!1,void 0,l,a),this.characters=new V(this.http,s),this.tts=new X(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new Z(()=>this.http.asrClient()),this.relationships=new H(this.http,s),this.inventory=new W(this.http,s),this.world=new B(this.http,s),this.player=new j(this.http,s),this.custom=new Y(this.http,s,i),this.save=new q(this.http,s,i),this.state=new z(this.http,s),this.memory=new Q(this.http,s),this.host=new M(d=>this.bus.send(d),!1),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""})}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}listenForPreviewMessages(){this.bus.on("set-model",e=>{this.modelId=e.payload.modelId||""}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""}),this.bus.on("config-update",e=>{this.previewConfig=e.payload.previewConfig,this.chat&&this.chat.updatePreviewConfig(this.previewConfig),this.refreshPreviewSnapshot().catch(t=>{console.warn("[Storvia SDK] refreshPreviewSnapshot failed:",t)})})}async getCharacterVoice(e){return this.isPreview?this.previewVoices.get(e):(await this.http.get(`/conversations/${this.conversationId}/characters/${encodeURIComponent(e)}`)).voice}async fetchPreviewSnapshot(){let e={game_id:this.gameId};this.previewConfig&&("game_config"in this.previewConfig&&(e.game_config=this.previewConfig.game_config),"game_state"in this.previewConfig&&(e.game_state_override=this.previewConfig.game_state));let t=await this.http.post("/preview/initial-snapshot",e);return this.previewVoices=new Map(t.characters.map(n=>[n.name,n.voice])),{...t,characters:t.characters.map(({voice:n,...r})=>({...r,hasVoice:!!n}))}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();this.characters?.setInitial(e.characters,e.characterStates),this.player?.setInitial(e.player,e.playerState),this.inventory?.setInitial(e.inventory),this.relationships?.setInitial(e.relationships),this.world?.setInitial(e.world),this.custom?.setInitial(e.custom,e.custom_inject),this.save?.setInitial(e.save_data)}async fetchModels(e=!1){try{return await this.http.get("/models",e?void 0:{locale:ne()})}catch{}return[]}async initDev(e){if(this.initialized)return;this.baseUrl=`${Ft}${st}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new re(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(!!e.model),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?We(t,e.model):void 0;e.model&&!r&&console.warn(`[Storvia SDK] dev.model "${e.model}" not found, falling back to the first model. Available:`,t.map(oe)),this.modelId=r?.id||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(h=>h.id===this.modelId);return d?oe(d):void 0};this.presetId=e.preset||"";let a=()=>this.presetId||void 0;this.chat=new F(this.http,i,s,c,!0,void 0,l,a),this.characters=new V(this.http,s,!0,n.characters,n.characterStates),this.tts=new X(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new Z(()=>this.http.asrClient()),this.relationships=new H(this.http,s,!0,n.relationships,()=>this.characters.previewNames()),this.inventory=new W(this.http,s,!0,n.inventory),this.world=new B(this.http,s,!0,n.world),this.player=new j(this.http,s,!0,n.player,n.playerState),this.custom=new Y(this.http,s,i,!0,n.custom,n.custom_inject),this.save=new q(this.http,s,i,!0,n.save_data),this.state=new z(this.http,s,!0),this.memory=new Q(this.http,s,!0),this.host=new M(()=>{},!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e,locale:ne()};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,assetId:i.asset_id,name:i.name,nameI18n:i.meta.name_i18n,url:i.url,assetType:i.asset_type,category:i.category,categoryI18n:i.category_i18n,tags:i.tags.map(s=>({id:s.id,label:s.label,labelI18n:s.label_i18n}))}))}};async function Wt(o){xe();let e=new ue;return o?.dev?await e.initDev(o.dev):await e.init(),e}function at(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function Bt(o){return at(o)?o.value:o}export{Je as HOST_NOTIFY_MAX_LENGTH,et as HOST_NOTIFY_MIN_INTERVAL_MS,Ne as HOST_PANEL_SCOPES,ye as HOST_REFRESH_MIN_INTERVAL_MS,M as HostModule,yt as MAIN_CHAT_TOPIC,_t as PLAYER_ID,ee as PROTOCOL_VERSION,L as StorviaBus,u as StorviaError,ue as StorviaSDK,Wt as createStorviaSDK,C as envelope,Bt as extractFieldValue,ce as isProtocolEnvelope,at as isRichFieldValue,vt as setToastEnabled,he as showToast};
120
+ `;let c=s.querySelector(".storvia-toast-msg");c&&(c.textContent=o);let l=()=>{s.isConnected&&(s.classList.add("leaving"),s.classList.remove("show"),setTimeout(()=>s.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(d){console.error("[Storvia toast] action error:",d)}l()}),s.appendChild(a)}if(i){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label",de("close")),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",l),s.appendChild(a)}r.appendChild(s),requestAnimationFrame(()=>s.classList.add("show")),i||setTimeout(l,t)}function Et(o){let e=o.filter(t=>t).map(t=>`\u300C${t}\u300D`).join("");return de("violationWords").replace("{words}",e)}var Tt=3e3,$e={};function Ge(o){let e=Date.now();if(!(e-($e[o]??0)<Tt)){if($e[o]=e,!ge){console.warn(`[Storvia] navigate \u2192 wallet(${o})\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u751F\u4EA7\u73AF\u5883\u7531\u5BBF\u4E3B\u5F39\u5145\u503C\u5F15\u5BFC / \u8DF3\u94B1\u5305\u9875\u3002`);return}try{ge(C("navigate",{target:"wallet",reason:o}))}catch(t){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",t)}}}function R(o,e,t){if(o==="GENERATION_ABORTED")return;if(o==="INSUFFICIENT_CREDITS")return Ge("insufficient_credits");if(o==="DAISY_CARD_REQUIRED")return Ge("daisy_card_required");let n=o==="VIOLATION_WORD_DETECTED"&&t?.length?Et(t):Ue(o)||e||de("unknownError");he(n,o==="RATE_LIMITED"?"warning":"error")}function wt(o,e){let t=e?.tickMs??100,n=e?.baseLagMs??1e3,r=e?.maxLagMs??2500,i=e?.minCharsPerTick??2,s="",c=null,l=0,a=0,d=()=>Math.min(r,Math.max(n,l*1.35)),g=()=>{let w=Math.max(i,Math.ceil(s.length*t/d()));if(w>=s.length)w=s.length;else{let _=s.charCodeAt(w-1);_>=55296&&_<=56319&&w++}let v=s.slice(0,w);s=s.slice(w),v&&o(v)},p=()=>{c=null,g(),s&&(c=setTimeout(p,t))};return{push:w=>{let v=Date.now();if(a>0){let _=Math.min(v-a,r);l=l>0?l*.7+_*.3:_}a=v,s+=w,c===null&&p()},flush:()=>{c!==null&&(clearTimeout(c),c=null),s&&(o(s),s="")},cancel:()=>{c!==null&&(clearTimeout(c),c=null),s=""}}}function me(o){let e=wt(o.onChunk);return{cbs:{onChunk:n=>e.push(n),onDone:(n,r)=>{e.flush(),o.onDone(n,r)},onAborted:o.onAborted?n=>{e.flush(),o.onAborted(n)}:void 0,onState:o.onState?(n,r)=>{e.flush(),o.onState(n,r)}:void 0,onThinking:o.onThinking?n=>{e.flush(),o.onThinking(n)}:void 0,onCreatedCharacters:o.onCreatedCharacters?n=>{e.flush(),o.onCreatedCharacters(n)}:void 0,onReconnect:o.onReconnect},flush:()=>e.flush()}}var He="0.10.10";function $(o,e){if(e.aborted){if(o.onAborted){o.onAborted(e.aborted);return}o.onDone(e.aborted.id,{truncated:!1});return}o.onDone(e.messageId,e.truncated===void 0?void 0:{truncated:e.truncated})}var T=class T{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}ttsClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/tts"),this.token,this.debug,this.devApiKey)}asrClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/asr"),this.token,this.debug,this.devApiKey)}async postForm(e,t,n=T.REQUEST_TIMEOUT){let r=this.buildHeaders();delete r["Content-Type"];let{controller:i,clear:s}=this.createTimeoutController(n);try{let c=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:r,body:t,signal:i.signal});return(await this.handleResponseWithRaw(c)).data}catch(c){let l=this.wrapAbortError(c);throw l===c&&this.maybeShowNetworkToast(c),l}finally{s()}}async postAudio(e,t){let{controller:n,clear:r}=this.createTimeoutController();try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:n.signal});i.ok||await this.handleResponseWithRaw(i);let{audio_url:s}=await i.json(),c=await fetch(s,{signal:n.signal});if(!c.ok)throw new u("TTS_UPSTREAM_FAILED",`Audio download failed: HTTP ${c.status}`);if(c.headers.get("Content-Type")?.includes("application/json"))throw new u("TTS_UPSTREAM_FAILED","Audio download returned JSON");return await c.blob()}catch(i){let s=this.wrapAbortError(i);throw s===i&&this.maybeShowNetworkToast(i),s}finally{r()}}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||R("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return R("REQUEST_TIMEOUT"),t}return e}createTimeoutController(e=T.REQUEST_TIMEOUT){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return{controller:t,clear:()=>clearTimeout(n)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e["x-client-info"]=`storvia-sdk/${He}`,e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:l,durationMs:a,modelName:d}=e,g="%c[Storvia SDK]",p="color: #6366f1; font-weight: bold",m=a!==void 0?` (${a}ms)`:"",h=i!==void 0?` [${i}]`:"",y=d?` [model: ${d}]`:"";l?(console.groupCollapsed(`${g} %c${t} ${n}${h}${y}${m} %c\u2717`,p,"color: #e0e0e0","color: #ef4444"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),console.error("Error:",l),console.groupEnd()):(console.groupCollapsed(`${g} %c${t} ${n}${h}${y}${m} %c\u2713`,p,"color: #e0e0e0","color: #22c55e"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),c!==void 0&&c!==s&&console.log("Response (data):",c),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,d])=>n.searchParams.set(a,d));let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});l(),i=a.status;let{raw:d,data:g}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:g,durationMs:Date.now()-r}),g}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r}),d===a&&this.maybeShowNetworkToast(a),d}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:c.signal});l(),i=a.status;let{raw:d,data:g}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:g,durationMs:Date.now()-r,modelName:n?.modelName}),g}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r,modelName:n?.modelName}),d===a&&this.maybeShowNetworkToast(a),d}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async delete(e){let t=Date.now(),n,r,{controller:i,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:i.signal});s(),n=c.status;let{raw:l,data:a}=await this.handleResponseWithRaw(c);return r=l,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let l=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:l,durationMs:Date.now()-t}),l===c&&this.maybeShowNetworkToast(c),l}}async stream(e,t,n,r,i,s,c,l,a,d,g,p){let m=Date.now(),h=i?.modelName?` [model: ${i.modelName}]`:"",y=[],w=E=>{this.debug&&y.push({t:Date.now()-m,event:E})},{cbs:v,flush:_}=me({onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:l,onReconnect:d,onAborted:g,onBase:p}),Ce=new AbortController,N=null,S=null,b=null,D=()=>{N!==null&&(clearTimeout(N),N=null),S!==null&&(clearTimeout(S),S=null)},_e=E=>{b=E,D(),Ce.abort()};N=setTimeout(()=>_e("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let A;try{A=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:Ce.signal})}catch(E){if(D(),b){let I=new u(b,"Request timed out");throw R(b),this.log({method:"STREAM",path:e,body:t,error:I,durationMs:Date.now()-m,modelName:i?.modelName}),I}throw this.maybeShowNetworkToast(E),E}if(N!==null&&(clearTimeout(N),N=null),!A.ok){D();let E=await A.text().catch(()=>""),I={};try{I=JSON.parse(E)}catch{}let P=I.code||"INTERNAL_ERROR",f=I.message||I.error||I.details,Pe=Array.isArray(I.matched_words)?I.matched_words:void 0,be=new u(P,f||`HTTP ${A.status}`,Pe);throw R(P,f,Pe),this.log({method:"STREAM",path:e,body:t,status:A.status,rawResponse:E,error:be,durationMs:Date.now()-m,modelName:i?.modelName}),be}let Re=A.body?.getReader();if(!Re)throw D(),new u("INTERNAL_ERROR","No response body for stream");S=setTimeout(()=>_e("MODEL_LOADING_TIMEOUT"),T.INITIAL_TIMEOUT);let Se=new TextDecoder,J="",pe,ie,k="",se,ae,x="",U=!1,O=null,Ae=E=>{if(U)return;let I=E.endsWith("\r")?E.slice(0,-1):E;if(I.startsWith("id: ")){ae=I.slice(4);return}if(!I.startsWith("data: "))return;let P=I.slice(6);if(P==="[DONE]"){w("[DONE]"),U=!0;return}try{let f=JSON.parse(P);w(f),f.type==="done"&&f.id?(J=f.id,pe=f.truncated===!0):f.type==="aborted"?(ie={id:typeof f.id=="string"?f.id:"",persisted:f.persisted===!0},U=!0):f.type==="error"?(O=new u(f.code||"INTERNAL_ERROR",f.message||"Generation failed",Array.isArray(f.matched_words)?f.matched_words:void 0),U=!0):f.type==="state"?(v.onState?.(f.delta,f.full??null),Array.isArray(f.createdNames)&&f.createdNames.length&&v.onCreatedCharacters?.(f.createdNames)):f.type==="start"?(S!==null&&(clearTimeout(S),S=null),typeof f.base_content=="string"&&p?.(f.base_content)):f.type==="thinking"?(f.status==="start"||f.status==="end")&&v.onThinking?.(f.status):f.content&&(S!==null&&(clearTimeout(S),S=null),k+=f.content,v.onChunk(f.content))}catch{w({raw:P})}ae!==void 0&&(se=ae,ae=void 0)},Oe=()=>{if(D(),O)throw _(),R(O.code,O.message,O.matchedWords),this.log({method:"STREAM",path:e,body:t,error:O,durationMs:Date.now()-m,modelName:i?.modelName}),O;this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${k.length} chars):`,k),console.log("Message ID:",J),ie&&console.log("Aborted:",ie),console.log(`SSE events (${y.length}):`,y),console.groupEnd()),$(v,{messageId:J,truncated:pe,aborted:ie})};try{for(;;){let{done:E,value:I}=await Re.read();if(E)break;x+=Se.decode(I,{stream:!0});let P=x.split(`
121
+ `);x=P.pop()??"";for(let f of P)Ae(f);if(U){Oe();return}}if(x+=Se.decode(),x&&Ae(x),U){Oe();return}}catch(E){if(D(),O)throw O;if(b){let I=new u(b,"Stream did not start in time");if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2717 ${b}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${k.length} chars):`,k),console.log(`SSE events (${y.length}):`,y),console.error("Timeout:",I),console.groupEnd()),a){await this.resumeLoop(a,se,v,{finalize:!0});return}throw R(b),_(),I}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${k.length} chars):`,k),console.log(`SSE events (${y.length}):`,y),console.error("Stream error:",E),console.groupEnd()),a){await this.resumeLoop(a,se,v,{finalize:!0});return}throw _(),E}if(D(),J){$(v,{messageId:J,truncated:pe});return}if(a){await this.resumeLoop(a,se,v,{finalize:!0});return}_()}async resumeLoop(e,t,n,r){let i=t;for(let c=1;c<=T.RECONNECT_MAX_ATTEMPTS;c++){let l=Math.min(T.RECONNECT_BACKOFF_CAP,1e3*2**(c-1));await new Promise(g=>setTimeout(g,l)),n.onReconnect?.({attempt:c});let a={messageId:"",lastId:i},d;try{d=await this.pumpGetStream(e.conversationId,e.topic,i,a,n)}catch{continue}if(i=a.lastId??i,d==="done"){if(a.errorCode)throw this.terminalError(a);$(n,a);return}if(d==="inactive"){(a.messageId||r?.finalize)&&$(n,a);return}}let s=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw R("STREAM_INTERRUPTED"),s}async resumeStream(e,t,n){let{cbs:r}=me(n),i={messageId:""},s;try{s=await this.pumpGetStream(e,t,void 0,i,r)}catch{await this.resumeLoop({conversationId:e,topic:t},i.lastId,r);return}if(s==="done"){if(i.errorCode)throw this.terminalError(i);$(r,i);return}if(s==="inactive"){i.messageId&&$(r,i);return}await this.resumeLoop({conversationId:e,topic:t},i.lastId,r)}terminalError(e){let t=new u(e.errorCode??"INTERNAL_ERROR",e.errorMessage||"Generation failed",e.errorMatchedWords);return R(t.code,t.message,t.matchedWords),t}async pumpGetStream(e,t,n,r,i){let s=new URL(`${this.baseUrl}/conversations/${encodeURIComponent(e)}/stream`);n&&s.searchParams.set("from",n),t&&s.searchParams.set("topic",t);let c=new AbortController,l=setTimeout(()=>c.abort(),T.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(l)}if(!a.ok)throw new u("STREAM_INTERRUPTED",`Resume HTTP ${a.status}`);if(!(a.headers.get("content-type")||"").includes("text/event-stream"))return"inactive";let g=a.body?.getReader();return g?await this.pumpReader(g,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},T.RESUME_STALL_TIMEOUT)};c();let l="",a=!1,d=g=>{if(a)return;let p=g.endsWith("\r")?g.slice(0,-1):g;if(p.startsWith("id: ")){i=p.slice(4);return}if(!p.startsWith("data: "))return;let m=p.slice(6);if(m==="[DONE]"){a=!0;return}try{let h=JSON.parse(m);h.type==="done"&&h.id?(t.messageId=h.id,t.truncated=h.truncated===!0):h.type==="aborted"?(t.aborted={id:typeof h.id=="string"?h.id:"",persisted:h.persisted===!0},a=!0):h.type==="error"?(t.errorCode=h.code||"INTERNAL_ERROR",t.errorMessage=h.message||"Generation failed",Array.isArray(h.matched_words)&&(t.errorMatchedWords=h.matched_words),a=!0):h.type==="state"?(n.onState?.(h.delta,h.full??null),Array.isArray(h.createdNames)&&h.createdNames.length&&n.onCreatedCharacters?.(h.createdNames)):h.type==="start"?typeof h.base_content=="string"&&n.onBase?.(h.base_content):h.type==="thinking"?(h.status==="start"||h.status==="end")&&n.onThinking?.(h.status):h.content&&n.onChunk(h.content)}catch{}i!==void 0&&(t.lastId=i,i=void 0)};try{for(;;){let{done:g,value:p}=await e.read();if(g)break;c(),l+=r.decode(p,{stream:!0});let m=l.split(`
122
+ `);l=m.pop()??"";for(let h of m)d(h);if(a)return s&&clearTimeout(s),"done"}if(l+=r.decode(),l&&d(l),a)return s&&clearTimeout(s),"done"}catch{}finally{s&&clearTimeout(s)}return"eof"}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let r=n&&typeof n=="object"?n:{},i={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.error_code??r.code,c=s==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":s==="TTS_RATE_LIMITED"?"RATE_LIMITED":s||i[e.status]||"INTERNAL_ERROR",l=Array.isArray(r.matched_words)?r.matched_words:void 0,a=new u(c,r.message||`HTTP ${e.status}`,l);throw R(c,r.message,l),a}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.INITIAL_TIMEOUT=3e4,T.RESUME_STALL_TIMEOUT=6e4,T.RECONNECT_MAX_ATTEMPTS=10,T.RECONNECT_BACKOFF_CAP=15e3;var re=T;var fe=o=>o.trim().toLowerCase();function oe(o){let e=ne(),t=o.name_i18n??{};return t[e]||t[e.replace("-","_")]||o.name}function We(o,e){let t=fe(e);return o.find(n=>fe(n.name)===t)??o.find(n=>Object.values(n.name_i18n??{}).some(r=>typeof r=="string"&&fe(r)===t))}var yt="storvia_chat_main";function Ct(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let o=new Uint8Array(16);crypto.getRandomValues(o),o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=Array.from(o,t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}var Be=20,je=40,F=class{constructor(e,t,n,r,i=!1,s,c,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewHistory=[];this.previewConfig=s,this.getModelName=c,this.getPreset=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.(),client_message_uuid:Ct()};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{game_id:this.getGameId(),conversation_id:this.getConversationId(),role:e.role,content:e.content,topic:e.topic})}async generate(e){if(this.isPreview)return this.sendPreview({message:"",topic:e.topic,sceneKey:e.sceneKey,stream:e.stream,onChunk:e.onChunk,onDone:e.onDone,onState:e.onState,onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters});let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/generate",t,this.reqMeta())}async once(e){if(this.isPreview)return this.oncePreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,stream:e.stream===!0,preset:this.getPreset?.()};if(!e.stream)return this.http.post("/once",t,this.reqMeta());let n="";return await this.http.stream("/once",t,r=>{n+=r,e.onChunk?.(r)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:n}}async oncePreview(e){let t={model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,history_messages:[],preset:this.getPreset?.()};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language);let r="";return await this.http.stream("/preview",t,i=>{r+=i,e.onChunk?.(i)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:r}}async retry(e={}){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.retry() is not available in preview mode. Publish the game and test on the Storvia platform.");let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/retry",t,this.reqMeta())}async continue(e={}){if(this.isPreview)return;let t={conversation_id:this.getConversationId(),topic:e.topic??null,game_id:this.getGameId(),preset:this.getPreset?.(),scene_key:e.sceneKey,extract:e.extract};await this.http.stream("/continue",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted,e.onBase)}async cancel(e={}){if(this.isPreview)return{active:!1};let t=await this.http.post(`/conversations/${encodeURIComponent(this.getConversationId())}/cancel`,{topic:e.topic});return{active:t.active===!0,generationId:t.generation_id}}async messages(e){if(this.isPreview)return{data:[],hasMore:!1,nextCursor:null};let t={conversation_id:this.getConversationId(),order:e.order,limit:String(e.limit??20)};e.topic&&(t.topic=e.topic),e.cursor&&(t.cursor_uuid=e.cursor.uuid,t.cursor_created_at=e.cursor.createdAt);let n=await this.http.get("/messages",t);return{data:n.messages.map(r=>({uuid:r.uuid,role:r.role,content:r.content,topic:r.topic,status:r.status,model:r.model,createdAt:r.created_at,truncated:r.truncated===!0})),hasMore:n.has_more,nextCursor:n.next_cursor?{uuid:n.next_cursor.cursor_uuid,createdAt:n.next_cursor.cursor_created_at}:null}}async edit(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.edit() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.patch(`/messages/${encodeURIComponent(e.uuid)}`,{content:e.content});return{uuid:t.uuid,role:t.role,content:t.content,updatedAt:t.updated_at}}async delete(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.delete() is not available in preview mode. Publish the game and test on the Storvia platform.");return{uuid:(await this.http.delete(`/messages/${encodeURIComponent(e.uuid)}`)).uuid}}async rollback(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.rollback() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.post(`/messages/${encodeURIComponent(e.uuid)}/rollback`,{});return{deletedCount:t.deleted_count,deletedUuids:t.deleted_uuids,restoredGameState:t.restored_game_state}}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:G(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting,onAborted:e.onAborted})}async sendPreview(e){let t=e.message.trim().length>0,n=e.topic||null,r=this.previewHistory.filter(p=>n===null||p.topic===n).slice(t?-(Be-1):-Be).map(({role:p,content:m})=>({role:p,content:m}));t&&this.pushPreviewHistory({role:"user",content:e.message},n);let i={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:r,preset:this.getPreset?.()};this.previewConfig?i.prompt_config=this.previewConfig:i.game_id=this.getGameId();let s=this.previewConfig;if(s?.reply_length&&(i.reply_length=s.reply_length),s?.reply_language&&(i.reply_language=s.reply_language),e.stream){let p="";await this.http.stream("/preview",i,m=>{p+=m,e.onChunk?.(m)},(m,h)=>{p&&this.pushPreviewHistory({role:"assistant",content:p},n),e.onDone?.(m,h)},this.reqMeta(),G(e.onState),e.onThinking,e.onCreatedCharacters);return}let c="",l=null,a=null,d=[];await this.http.stream("/preview",i,p=>{c+=p},()=>{},this.reqMeta(),(p,m)=>{l=p,a=m,e.onState&&e.onState(l,a)},void 0,p=>{d=p,e.onCreatedCharacters&&e.onCreatedCharacters(p)}),c&&this.pushPreviewHistory({role:"assistant",content:c},n);let g={id:"",content:c,truncated:!1};return l&&(g.delta=l,a&&(g.full=a)),d.length&&(g.createdNames=d),g}pushPreviewHistory(e,t){this.previewHistory.push({...e,topic:t}),this.previewHistory.length>je&&this.previewHistory.splice(0,this.previewHistory.length-je)}};function G(o){if(o)return(e,t)=>o(e,t)}var Ie=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let r=this.mem[e]||{};return t?{...r[t]||{}}:{...r}}let n=t?{group:t}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,n)}async update(e,t,n){if(this.isPreview){let r=this.mem[e]||(this.mem[e]={});r[t]={...r[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}async remove(e,t,n){if(n.length){if(this.isPreview){let r=this.mem[e]?.[t];if(r)for(let i of n)delete r[i];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeKeys:n})}}async removeGroup(e,t){if(this.isPreview){let n=this.mem[e];n&&delete n[t];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeGroup:!0})}},V=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(Ke)),this.state=new Ie(e,t,n,i)}previewNames(){return this.mem.map(e=>e.name)}setInitial(e,t){this.mem=e?e.map(Ke):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Ye):(await this.http.get(`/conversations/${this.getConversationId()}/characters`)).map(ve)}async get(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return n?Ye(n):{name:e,hasVoice:!1}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`);return ve(t)}async add(e){if(this.isPreview){this.mem.push({...e,isPreset:!1});return}await this.http.post(`/conversations/${this.getConversationId()}/characters`,e)}async update(e,t){if(this.isPreview){let n=this.mem.find(r=>r.name===e);n&&Object.assign(n,t);return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`,t)}async remove(e){if(this.isPreview){this.mem=this.mem.filter(t=>t.name!==e);return}await this.http.delete(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}async merge(e,t){if(this.isPreview){if(this.mem.find(r=>r.name===e)?.isPreset)throw new u("INVALID_REQUEST","\u9884\u8BBE\u89D2\u8272\u4E0D\u53EF\u88AB\u5408\u5E76");if(e===t||!this.mem.some(r=>r.name===t))throw new u("INVALID_REQUEST","\u76EE\u6807\u89D2\u8272\u4E0D\u5B58\u5728\u6216\u4E0E\u6765\u6E90\u76F8\u540C");this.mem=this.mem.filter(r=>r.name!==e);return}await this.http.post(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/merge`,{target:t})}async detail(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return{name:e,avatar:n?.avatar,description:n?.description,hasVoice:n?.hasVoice===!0,...n?.introduction!==void 0?{introduction:n.introduction}:{},...n?.visibleAtStart!==void 0?{visibleAtStart:n.visibleAtStart}:{},userDescription:n?.userDescription,...n?.gender?{gender:n.gender}:{},...n?.isPreset!==void 0?{isPreset:n.isPreset}:{},state:await this.state.get(e)}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`);return ve(t)}async setPriority(e,t){let n=Math.max(0,Math.min(100,Math.round(t)));this.isPreview||await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{priority:n})}};function Ke(o){return{name:o.name,description:o.description,avatar:o.avatar,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Ye(o){return{name:o.name,avatar:o.avatar,description:o.description,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function ve(o){let{voice:e,...t}=o;return{...t,hasVoice:!!e}}var _t="\u73A9\u5BB6",Rt=["Player","player","PLAYER","\u30D7\u30EC\u30A4\u30E4\u30FC","\uD50C\uB808\uC774\uC5B4","\u4E3B\u63A7","{{user}}","user"],Ee=o=>o.toLowerCase().replace(/[\s_\-]+/g,""),St=new Set(["\u73A9\u5BB6",...Rt].map(Ee));function qe(o,e){if(o==="\u73A9\u5BB6")return o;let t=Ee(o);return St.has(t)?e.some(n=>Ee(n)===t)?o:"\u73A9\u5BB6":o}var H=class{constructor(e,t,n=!1,r,i=()=>[]){this.http=e;this.getConversationId=t;this.isPreview=n;this.getCharacterNames=i;this.mem=[];r&&(this.mem=r.map(s=>({...s})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}entity(e){return this.isPreview?qe(e,this.getCharacterNames()):e}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t);let n=this.mem.find(r=>r.from===e&&r.to===t);if(n)return{...n};throw new Error("Relationship not found")}return this.http.get(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}async add(e){if(this.isPreview){this.mem.push({...e,from:this.entity(e.from),to:this.entity(e.to)});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){e=this.entity(e),t=this.entity(t);let r=this.mem.find(i=>i.from===e&&i.to===t);r?Object.assign(r,n):this.mem.push({from:e,to:t,...n});return}await this.http.patch(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,n)}async remove(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t),this.mem=this.mem.filter(n=>!(n.from===e&&n.to===t));return}await this.http.delete(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}};function ze(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function Te(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let r={};for(let[i,s]of Object.entries(n))r[i]=ze(s);e[t]=r}return e}function At(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=ze(n);return e}var W=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=Te(r))}setInitial(e){this.mem=e?Te(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[r,i]of Object.entries(this.mem))n[r]={...i};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return At(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return Te(t)}async add(e){let{group:t,name:n,count:r=1,desc:i,iconUrl:s}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:r};i!==void 0&&(l.desc=i),s!==void 0&&(l.iconUrl=s),this.mem[t][n]=l;return}let c={group:t,name:n,count:r};i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,c)}async update(e){let{group:t,name:n,count:r,desc:i,iconUrl:s}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];r!==void 0&&(a.count=r),i!==void 0&&(a.desc=i),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,c)}async remove(e){let{group:t,name:n}=e;if(this.isPreview){this.mem[t]&&delete this.mem[t][n];return}await this.http.delete(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`)}async removeBatch(e){if(this.isPreview){for(let{group:t,name:n}of e)this.mem[t]&&delete this.mem[t][n];return}e.length!==0&&await this.http.post(`/conversations/${this.getConversationId()}/inventory/batch-delete`,{items:e})}async move(e){let{fromGroup:t,toGroup:n,name:r,newName:i}=e;if(this.isPreview){let s=this.mem[t];if(!s||!(r in s))throw new Error(`Source item "${t}/${r}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let c=i||r;if(t===n&&c===r)return;if(c in this.mem[n])throw new Error(`Item "${c}" already exists in target group`);this.mem[n][c]=s[r],delete s[r];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:r,newName:i})}async ensureGroup(e){if(this.isPreview){this.mem[e]||(this.mem[e]={});return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}`,{})}async removeGroup(e,t){let n=t?.cascade??!1;if(this.isPreview){let i=this.mem[e];if(i&&Object.keys(i).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let r=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${r}`)}};var B=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:this.http.get(`/conversations/${this.getConversationId()}/world`)}async update(e){if(this.isPreview){Object.assign(this.mem,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/world`,e)}};var we=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e){if(this.isPreview)return e?{...this.mem[e]||{}}:{...this.mem};let t=e?{group:e}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/player/state`,t)}async update(e,t){if(this.isPreview){this.mem[e]={...this.mem[e]||{},...t};return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,values:t})}async remove(e,t){if(t.length){if(this.isPreview){let n=this.mem[e];if(n)for(let r of t)delete n[r];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeKeys:t})}}async removeGroup(e){if(this.isPreview){delete this.mem[e];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeGroup:!0})}},j=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new we(e,t,n,i)}setInitial(e,t){this.memPersona=e?{...e}:{name:""},this.state.setInitial(t)}async get(){return this.isPreview?{...this.memPersona}:this.http.get(`/conversations/${this.getConversationId()}/player`)}async update(e){if(this.isPreview){Object.assign(this.memPersona,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/player`,e)}};function K(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var Y=class{constructor(e,t,n,r=!1,i,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};i&&(this.mem=Qe(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Qe(e):{},this.memInject=t?{...t}:{}}async get(e){if(this.isPreview)return e!==void 0?this.mem[e]:{...this.mem};let t=await this.http.get(K(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,i]of Object.entries(e))typeof i=="object"&&i!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...i}:this.mem[r]=i,t?.inject!==void 0&&(this.memInject[r]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(K(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(K(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,this.getGameId()),{inject:t})}getInject(){return{...this.memInject}}async delete(e){if(this.isPreview){delete this.mem[e],delete this.memInject[e];return}await this.http.delete(K(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}`,this.getGameId()))}async setGroupField(e,t,n){if(this.isPreview){(!this.mem[e]||typeof this.mem[e]!="object")&&(this.mem[e]={}),this.mem[e][t]=n;return}await this.http.patch(K(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()),{value:n})}async deleteGroupField(e,t){if(this.isPreview){if(typeof this.mem[e]=="object"&&this.mem[e]!==null){let n=this.mem[e];delete n[t]}return}await this.http.delete(K(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Qe(o){let e={};for(let[t,n]of Object.entries(o))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function Xe(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var q=class{constructor(e,t,n,r=!1,i){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(Xe(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Xe(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var z=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n}async get(){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.state.get() is not available in preview mode. Publish the game and test on the Storvia platform. (Use per-module get() like storvia.world.get() if you need to inspect state during preview.)");return this.http.get(`/conversations/${this.getConversationId()}/state`)}};var Q=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null;this.wb=null;this.worldbook={get:async()=>this.isPreview?this.wb?Ze(this.wb):null:(await this.http.get(`/conversations/${this.getConversationId()}/worldbook`)).worldbook,update:async e=>{let t=typeof e=="string"?{content:e}:{...e};if(t.content!==void 0&&(t.content=(t.content??"").trim()),t.entries!==void 0&&(t.entries=Ot(t.entries)),this.isPreview){let r=this.wb?.presets??[],i=t.enabledPresets?r.map(c=>({...c,enabled:t.enabledPresets.includes(c.id)})):r,s={content:t.content??this.wb?.content??"",contentWidget:t.contentWidget??this.wb?.contentWidget??!1,entries:t.entries??this.wb?.entries??[],presets:i,updated_at:new Date().toISOString()};return this.wb=s,Ze(s)}return(await this.http.patch(`/conversations/${this.getConversationId()}/worldbook`,t)).worldbook}}}async get(){return this.isPreview?this.mem?{...this.mem}:null:(await this.http.get(`/conversations/${this.getConversationId()}/summary`)).ai_summary}async update(e){let t=(e??"").trim();if(this.isPreview){let r={content:t,updated_at:new Date().toISOString()};return this.mem=r,{...r}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};function Ze(o){return{...o,entries:o.entries.map(e=>({...e,keys:[...e.keys]})),presets:(o.presets??[]).map(e=>({...e}))}}function Ot(o){return(o??[]).flatMap(e=>{let t=(e?.content??"").trim(),n=[...new Set((e?.keys??[]).map(s=>(s??"").trim()).filter(s=>s!==""))],r=e?.constant===!0;if(!t||!r&&n.length===0)return[];let i=(e?.title??"").trim();return[{id:e.id||Pt(),keys:n,content:t,...i?{title:i}:{},constant:r,enabled:e?.enabled!==!1,widget:e?.widget===!0}]})}function Pt(){let o=globalThis.crypto;return o?.randomUUID?o.randomUUID():`ewr-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var Je=60,et=1e3,ye=1e4,M=class{constructor(e,t=!1,n=()=>Date.now()){this.send=e;this.isPreview=t;this.now=n;this.lastNotifyAt=0;this.lastRefreshAt=0;this.lastRefreshMessagesAt=0}notify(e){let t=bt(e);if(!t)return!1;let n=this.now();return n-this.lastNotifyAt<et?!1:(this.lastNotifyAt=n,this.isPreview?(he(t,"info"),!0):(this.send(C("host-notify",{text:t})),!0))}refreshPanel(e){if(this.isPreview)return!1;let t=this.now();return t-this.lastRefreshAt<ye?!1:(this.lastRefreshAt=t,this.send(C("host-state-changed",e?.length?{scope:e}:{})),!0)}refreshMessages(){if(this.isPreview)return!1;let e=this.now();return e-this.lastRefreshMessagesAt<ye?!1:(this.lastRefreshMessagesAt=e,this.send(C("host-messages-changed",{})),!0)}};function bt(o){return typeof o!="string"?"":o.replace(/\s+/g," ").trim().slice(0,Je)}var Nt;function tt(){return Nt??(Nt=new Promise((o,e)=>{let t=indexedDB.open("storvia-sdk-speech",1);t.onupgradeneeded=()=>t.result.createObjectStore("audio"),t.onsuccess=()=>o(t.result),t.onerror=()=>e(t.error)}))}async function nt(o){let e=await tt();return new Promise((t,n)=>{let r=e.transaction("audio").objectStore("audio").get(o);r.onsuccess=()=>t(r.result??null),r.onerror=()=>n(r.error)})}async function rt(o,e){let t=await tt();return new Promise((n,r)=>{let i=t.transaction("audio","readwrite");i.objectStore("audio").put(e,o),i.oncomplete=()=>n(),i.onabort=()=>r(i.error)})}function ot(o){let e=o,t;do t=e,e=e.replace(/[((][^()()]*[))]/g,"");while(e!==t);return e.replace(/\s+/g," ").trim()}var X=class{constructor(e,t,n,r,i=!1){this.getHttp=e;this.getConversationId=t;this.getGameId=n;this.getVoice=r;this.isPreview=i;this.pending=new Map}async speak(e){let t=ot(e.text),n=await this.getVoice(e.character);if(!n)throw new u("TTS_UNKNOWN_VOICE","Character has no voice configured");let r=this.isPreview?this.getGameId():this.getConversationId(),i=JSON.stringify([r,n,t]),s={text:t,...this.isPreview?{voice:n}:{conversation_id:this.getConversationId(),character_name:e.character}},c=globalThis;if(c.__storviaNativeTts&&c.flutter_inappwebview){let d=await c.flutter_inappwebview.callHandler("storviaTts",{body:s,key:i});if(d.error){let p=d.error==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":d.error==="TTS_RATE_LIMITED"?"RATE_LIMITED":d.error;throw R(p),new u(p,d.error)}let g=Uint8Array.from(atob(d.audio),p=>p.charCodeAt(0));return{audio:new Blob([g],{type:"audio/mpeg"}),cached:d.cached}}let l=await nt(i);if(l)return{audio:l,cached:!0};let a=this.pending.get(i);return a||(a=this.getHttp().postAudio("/speak",s).then(async d=>{try{await rt(i,d)}catch{console.warn("[Storvia TTS] \u97F3\u9891\u7F13\u5B58\u4FDD\u5B58\u5931\u8D25")}return{audio:d,cached:!1}}),this.pending.set(i,a),a.then(()=>this.pending.delete(i),()=>this.pending.delete(i))),a}};var Z=class{constructor(e){this.getHttp=e}async transcribe(e){if(!e||typeof e!="object")throw new u("INVALID_REQUEST","Recognition options are required");if(!(e.audio instanceof Blob)||e.audio.size===0||e.audio.size>10485760)throw new u("ASR_BAD_AUDIO","Audio must be a non-empty file of at most 10 MB");let t=e.audio.type.split(";")[0].trim().toLowerCase(),n=e.format??Gt[t];if(!n||!Lt.includes(n))throw new u("ASR_BAD_AUDIO","Specify a supported audio format");if(e.context!==void 0&&typeof e.context!="string"||!it(e.languageHints,4)||!it(e.hotwords,50)||(e.context?.length??0)>400||e.hotwords?.some(i=>i.length>64))throw new u("INVALID_REQUEST","Recognition context, language hints, or hotwords exceed the limits");let r=new FormData;return r.append("file",e.audio,`audio.${n}`),r.append("format",n),e.context!==void 0&&r.append("context",e.context),e.languageHints!==void 0&&r.append("language_hints",JSON.stringify(e.languageHints)),e.hotwords!==void 0&&r.append("hotwords",JSON.stringify(e.hotwords)),this.getHttp().postForm("/transcribe",r,$t)}},Lt=["wav","mp3","m4a","webm","ogg","opus","flac","aac"],$t=15e4;function it(o,e){return o===void 0||Array.isArray(o)&&o.length<=e&&o.every(t=>typeof t=="string"&&t.trim().length>0)}var Gt={"audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav","audio/mpeg":"mp3","audio/mp3":"mp3","audio/mp4":"m4a","audio/x-m4a":"m4a","audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/opus":"opus","audio/flac":"flac","audio/x-flac":"flac","audio/aac":"aac"};var st="/functions/v1/world-engine/v1",Ft="https://api.storvia.ai";function Vt(){return window.__STORVIA__||{}}function Ht(o,e=3e4){let t=Vt();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let i=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,lang:a.payload.lang,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(i),s(),c();let d=window;d.__STORVIA__=a,n(a)}o.send(C("ready",{}))})}var ue=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.presetId="";this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0;this.previewVoices=new Map}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new L({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?d=>d.source===null||d.source===window:d=>d.source===window.parent,customSend:t?d=>e.callHandler("storviaBus",d):void 0}),Fe(d=>this.bus.send(d));let n=await Ht(this.bus),r=n.apiBase;if(!r)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${r}${st}`,this.isPreview=!!n.preview,this.previewConfig=n.previewConfig,!n.gameId)throw new u("GAME_NOT_FOUND","window.__STORVIA__.gameId is not set. The platform must inject it before SDK init.");if(this.gameId=n.gameId,!n.accessToken)throw new u("UNAUTHORIZED","window.__STORVIA__.accessToken is not set. The platform must inject the user token before SDK init.");if(this.accessToken=n.accessToken,Me(n.lang),this.http=new re(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000",this.models=n.models??[],this.modelId=n.selectedModelId||this.models[0]?.id||"";let[d,g]=await Promise.all([this.fetchPreviewSnapshot(),this.modelId?Promise.resolve(null):this.fetchModels()]);g&&(this.models=g,this.modelId=g[0]?.id||""),this.presetId=n.presetId||"";let p=()=>this.gameId,m=()=>this.conversationId,h=()=>this.modelId,y=()=>{let v=this.models.find(_=>_.id===this.modelId);return v?oe(v):void 0},w=()=>this.presetId||void 0;this.chat=new F(this.http,p,m,h,!0,this.previewConfig,y,w),this.characters=new V(this.http,m,!0,d.characters,d.characterStates),this.tts=new X(()=>this.http.ttsClient(),m,p,v=>this.getCharacterVoice(v),this.isPreview),this.asr=new Z(()=>this.http.asrClient()),this.relationships=new H(this.http,m,!0,d.relationships,()=>this.characters.previewNames()),this.inventory=new W(this.http,m,!0,d.inventory),this.world=new B(this.http,m,!0,d.world),this.player=new j(this.http,m,!0,d.player,d.playerState),this.custom=new Y(this.http,m,p,!0,d.custom,d.custom_inject),this.save=new q(this.http,m,p,!0,d.save_data),this.state=new z(this.http,m,!0),this.memory=new Q(this.http,m,!0),this.host=new M(v=>this.bus.send(v),!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}if(!n.conversationId)throw new u("NOT_INITIALIZED","window.__STORVIA__.conversationId is not set. The platform must inject it before SDK init.");this.conversationId=n.conversationId,this.modelId=n.selectedModelId||"",this.modelId||(this.models=await this.fetchModels(),this.modelId=this.models[0]?.id||""),this.presetId=n.presetId||"";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(g=>g.id===this.modelId);return d?oe(d):void 0},a=()=>this.presetId||void 0;this.chat=new F(this.http,i,s,c,!1,void 0,l,a),this.characters=new V(this.http,s),this.tts=new X(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new Z(()=>this.http.asrClient()),this.relationships=new H(this.http,s),this.inventory=new W(this.http,s),this.world=new B(this.http,s),this.player=new j(this.http,s),this.custom=new Y(this.http,s,i),this.save=new q(this.http,s,i),this.state=new z(this.http,s),this.memory=new Q(this.http,s),this.host=new M(d=>this.bus.send(d),!1),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""})}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}listenForPreviewMessages(){this.bus.on("set-model",e=>{this.modelId=e.payload.modelId||""}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""}),this.bus.on("config-update",e=>{this.previewConfig=e.payload.previewConfig,this.chat&&this.chat.updatePreviewConfig(this.previewConfig),this.refreshPreviewSnapshot().catch(t=>{console.warn("[Storvia SDK] refreshPreviewSnapshot failed:",t)})})}async getCharacterVoice(e){return this.isPreview?this.previewVoices.get(e):(await this.http.get(`/conversations/${this.conversationId}/characters/${encodeURIComponent(e)}`)).voice}async fetchPreviewSnapshot(){let e={game_id:this.gameId};this.previewConfig&&("game_config"in this.previewConfig&&(e.game_config=this.previewConfig.game_config),"game_state"in this.previewConfig&&(e.game_state_override=this.previewConfig.game_state));let t=await this.http.post("/preview/initial-snapshot",e);return this.previewVoices=new Map(t.characters.map(n=>[n.name,n.voice])),{...t,characters:t.characters.map(({voice:n,...r})=>({...r,hasVoice:!!n}))}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();this.characters?.setInitial(e.characters,e.characterStates),this.player?.setInitial(e.player,e.playerState),this.inventory?.setInitial(e.inventory),this.relationships?.setInitial(e.relationships),this.world?.setInitial(e.world),this.custom?.setInitial(e.custom,e.custom_inject),this.save?.setInitial(e.save_data)}async fetchModels(e=!1){try{return await this.http.get("/models",e?void 0:{locale:ne()})}catch{}return[]}async initDev(e){if(this.initialized)return;this.baseUrl=`${Ft}${st}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new re(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(!!e.model),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?We(t,e.model):void 0;e.model&&!r&&console.warn(`[Storvia SDK] dev.model "${e.model}" not found, falling back to the first model. Available:`,t.map(oe)),this.modelId=r?.id||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(g=>g.id===this.modelId);return d?oe(d):void 0};this.presetId=e.preset||"";let a=()=>this.presetId||void 0;this.chat=new F(this.http,i,s,c,!0,void 0,l,a),this.characters=new V(this.http,s,!0,n.characters,n.characterStates),this.tts=new X(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new Z(()=>this.http.asrClient()),this.relationships=new H(this.http,s,!0,n.relationships,()=>this.characters.previewNames()),this.inventory=new W(this.http,s,!0,n.inventory),this.world=new B(this.http,s,!0,n.world),this.player=new j(this.http,s,!0,n.player,n.playerState),this.custom=new Y(this.http,s,i,!0,n.custom,n.custom_inject),this.save=new q(this.http,s,i,!0,n.save_data),this.state=new z(this.http,s,!0),this.memory=new Q(this.http,s,!0),this.host=new M(()=>{},!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e,locale:ne()};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,assetId:i.asset_id,name:i.name,nameI18n:i.meta.name_i18n,url:i.url,assetType:i.asset_type,category:i.category,categoryI18n:i.category_i18n,tags:i.tags.map(s=>({id:s.id,label:s.label,labelI18n:s.label_i18n}))}))}};async function Wt(o){xe();let e=new ue;return o?.dev?await e.initDev(o.dev):await e.init(),e}function at(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function Bt(o){return at(o)?o.value:o}export{Je as HOST_NOTIFY_MAX_LENGTH,et as HOST_NOTIFY_MIN_INTERVAL_MS,Ne as HOST_PANEL_SCOPES,ye as HOST_REFRESH_MIN_INTERVAL_MS,M as HostModule,yt as MAIN_CHAT_TOPIC,_t as PLAYER_ID,ee as PROTOCOL_VERSION,L as StorviaBus,u as StorviaError,ue as StorviaSDK,Wt as createStorviaSDK,C as envelope,Bt as extractFieldValue,ce as isProtocolEnvelope,at as isRichFieldValue,vt as setToastEnabled,he as showToast};
package/dist/index.umd.js CHANGED
@@ -117,7 +117,7 @@
117
117
  `,Ot={success:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',error:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',warning:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',info:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>'},je=!0;function Ke(o){je=o}function Pt(){if(typeof document>"u")return null;let o=document.getElementById(ue);if(!o){if(!document.getElementById(Ve)){let e=document.createElement("style");e.id=Ve,e.textContent=At,document.head.appendChild(e)}o=document.createElement("div"),o.id=ue,document.body.appendChild(o)}return o}function oe(o,e="info",t=3500,n){if(!je)return;let r=Pt();if(!r)return;let i=t<=0,s=document.createElement("div");s.className=`storvia-toast ${e}`,s.innerHTML=`
118
118
  <span class="storvia-toast-icon">${Ot[e]}</span>
119
119
  <span class="storvia-toast-msg"></span>
120
- `;let c=s.querySelector(".storvia-toast-msg");c&&(c.textContent=o);let l=()=>{s.isConnected&&(s.classList.add("leaving"),s.classList.remove("show"),setTimeout(()=>s.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(d){console.error("[Storvia toast] action error:",d)}l()}),s.appendChild(a)}if(i){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label",he("close")),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",l),s.appendChild(a)}r.appendChild(s),requestAnimationFrame(()=>s.classList.add("show")),i||setTimeout(l,t)}function bt(o){let e=o.filter(t=>t).map(t=>`\u300C${t}\u300D`).join("");return he("violationWords").replace("{words}",e)}var Nt=3e3,He={};function We(o){let e=Date.now();if(!(e-(He[o]??0)<Nt)){if(He[o]=e,!ve){console.warn(`[Storvia] navigate \u2192 wallet(${o})\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u751F\u4EA7\u73AF\u5883\u7531\u5BBF\u4E3B\u5F39\u5145\u503C\u5F15\u5BFC / \u8DF3\u94B1\u5305\u9875\u3002`);return}try{ve(y("navigate",{target:"wallet",reason:o}))}catch(t){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",t)}}}function R(o,e,t){if(o==="GENERATION_ABORTED")return;if(o==="INSUFFICIENT_CREDITS")return We("insufficient_credits");if(o==="DAISY_CARD_REQUIRED")return We("daisy_card_required");let n=o==="VIOLATION_WORD_DETECTED"&&t?.length?bt(t):Fe(o)||e||he("unknownError");oe(n,o==="RATE_LIMITED"?"warning":"error")}function Dt(o,e){let t=e?.tickMs??100,n=e?.baseLagMs??1e3,r=e?.maxLagMs??2500,i=e?.minCharsPerTick??2,s="",c=null,l=0,a=0,d=()=>Math.min(r,Math.max(n,l*1.35)),h=()=>{let w=Math.max(i,Math.ceil(s.length*t/d()));if(w>=s.length)w=s.length;else{let _=s.charCodeAt(w-1);_>=55296&&_<=56319&&w++}let v=s.slice(0,w);s=s.slice(w),v&&o(v)},m=()=>{c=null,h(),s&&(c=setTimeout(m,t))};return{push:w=>{let v=Date.now();if(a>0){let _=Math.min(v-a,r);l=l>0?l*.7+_*.3:_}a=v,s+=w,c===null&&m()},flush:()=>{c!==null&&(clearTimeout(c),c=null),s&&(o(s),s="")},cancel:()=>{c!==null&&(clearTimeout(c),c=null),s=""}}}function Ie(o){let e=Dt(o.onChunk);return{cbs:{onChunk:n=>e.push(n),onDone:(n,r)=>{e.flush(),o.onDone(n,r)},onAborted:o.onAborted?n=>{e.flush(),o.onAborted(n)}:void 0,onState:o.onState?(n,r)=>{e.flush(),o.onState(n,r)}:void 0,onThinking:o.onThinking?n=>{e.flush(),o.onThinking(n)}:void 0,onCreatedCharacters:o.onCreatedCharacters?n=>{e.flush(),o.onCreatedCharacters(n)}:void 0,onReconnect:o.onReconnect},flush:()=>e.flush()}}var Ye="0.10.9";function G(o,e){if(e.aborted){if(o.onAborted){o.onAborted(e.aborted);return}o.onDone(e.aborted.id,{truncated:!1});return}o.onDone(e.messageId,e.truncated===void 0?void 0:{truncated:e.truncated})}var T=class T{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}ttsClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/tts"),this.token,this.debug,this.devApiKey)}asrClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/asr"),this.token,this.debug,this.devApiKey)}async postForm(e,t,n=T.REQUEST_TIMEOUT){let r=this.buildHeaders();delete r["Content-Type"];let{controller:i,clear:s}=this.createTimeoutController(n);try{let c=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:r,body:t,signal:i.signal});return(await this.handleResponseWithRaw(c)).data}catch(c){let l=this.wrapAbortError(c);throw l===c&&this.maybeShowNetworkToast(c),l}finally{s()}}async postAudio(e,t){let{controller:n,clear:r}=this.createTimeoutController();try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:n.signal});i.ok||await this.handleResponseWithRaw(i);let{audio_url:s}=await i.json(),c=await fetch(s,{signal:n.signal});if(!c.ok)throw new u("TTS_UPSTREAM_FAILED",`Audio download failed: HTTP ${c.status}`);if(c.headers.get("Content-Type")?.includes("application/json"))throw new u("TTS_UPSTREAM_FAILED","Audio download returned JSON");return await c.blob()}catch(i){let s=this.wrapAbortError(i);throw s===i&&this.maybeShowNetworkToast(i),s}finally{r()}}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||R("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return R("REQUEST_TIMEOUT"),t}return e}createTimeoutController(e=T.REQUEST_TIMEOUT){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return{controller:t,clear:()=>clearTimeout(n)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e["x-client-info"]=`storvia-sdk/${Ye}`,e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:l,durationMs:a,modelName:d}=e,h="%c[Storvia SDK]",m="color: #6366f1; font-weight: bold",f=a!==void 0?` (${a}ms)`:"",p=i!==void 0?` [${i}]`:"",C=d?` [model: ${d}]`:"";l?(console.groupCollapsed(`${h} %c${t} ${n}${p}${C}${f} %c\u2717`,m,"color: #e0e0e0","color: #ef4444"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),console.error("Error:",l),console.groupEnd()):(console.groupCollapsed(`${h} %c${t} ${n}${p}${C}${f} %c\u2713`,m,"color: #e0e0e0","color: #22c55e"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),c!==void 0&&c!==s&&console.log("Response (data):",c),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,d])=>n.searchParams.set(a,d));let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});l(),i=a.status;let{raw:d,data:h}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:h,durationMs:Date.now()-r}),h}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r}),d===a&&this.maybeShowNetworkToast(a),d}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:c.signal});l(),i=a.status;let{raw:d,data:h}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:h,durationMs:Date.now()-r,modelName:n?.modelName}),h}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r,modelName:n?.modelName}),d===a&&this.maybeShowNetworkToast(a),d}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async delete(e){let t=Date.now(),n,r,{controller:i,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:i.signal});s(),n=c.status;let{raw:l,data:a}=await this.handleResponseWithRaw(c);return r=l,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let l=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:l,durationMs:Date.now()-t}),l===c&&this.maybeShowNetworkToast(c),l}}async stream(e,t,n,r,i,s,c,l,a,d,h,m){let f=Date.now(),p=i?.modelName?` [model: ${i.modelName}]`:"",C=[],w=E=>{this.debug&&C.push({t:Date.now()-f,event:E})},{cbs:v,flush:_}=Ie({onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:l,onReconnect:d,onAborted:h,onBase:m}),Oe=new AbortController,D=null,S=null,b=null,k=()=>{D!==null&&(clearTimeout(D),D=null),S!==null&&(clearTimeout(S),S=null)},Pe=E=>{b=E,k(),Oe.abort()};D=setTimeout(()=>Pe("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let A;try{A=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:Oe.signal})}catch(E){if(k(),b){let I=new u(b,"Request timed out");throw R(b),this.log({method:"STREAM",path:e,body:t,error:I,durationMs:Date.now()-f,modelName:i?.modelName}),I}throw this.maybeShowNetworkToast(E),E}if(D!==null&&(clearTimeout(D),D=null),!A.ok){k();let E=await A.text().catch(()=>""),I={};try{I=JSON.parse(E)}catch{}let P=I.code||"INTERNAL_ERROR",g=I.message||I.error||I.details,Me=Array.isArray(I.matched_words)?I.matched_words:void 0,xe=new u(P,g||`HTTP ${A.status}`,Me);throw R(P,g,Me),this.log({method:"STREAM",path:e,body:t,status:A.status,rawResponse:E,error:xe,durationMs:Date.now()-f,modelName:i?.modelName}),xe}let be=A.body?.getReader();if(!be)throw k(),new u("INTERNAL_ERROR","No response body for stream");S=setTimeout(()=>Pe("MODEL_LOADING_TIMEOUT"),T.INITIAL_TIMEOUT);let Ne=new TextDecoder,ee="",ge,ce,M="",de,le,U="",L=!1,O=null,De=E=>{if(L)return;let I=E.endsWith("\r")?E.slice(0,-1):E;if(I.startsWith("id: ")){le=I.slice(4);return}if(!I.startsWith("data: "))return;let P=I.slice(6);if(P==="[DONE]"){w("[DONE]"),L=!0;return}try{let g=JSON.parse(P);w(g),g.type==="done"&&g.id?(ee=g.id,ge=g.truncated===!0):g.type==="aborted"?(ce={id:typeof g.id=="string"?g.id:"",persisted:g.persisted===!0},L=!0):g.type==="error"?(O=new u(g.code||"INTERNAL_ERROR",g.message||"Generation failed",Array.isArray(g.matched_words)?g.matched_words:void 0),L=!0):g.type==="state"?(v.onState?.(g.delta,g.full??null),Array.isArray(g.createdNames)&&g.createdNames.length&&v.onCreatedCharacters?.(g.createdNames)):g.type==="start"?(S!==null&&(clearTimeout(S),S=null),typeof g.base_content=="string"&&m?.(g.base_content)):g.type==="thinking"?(g.status==="start"||g.status==="end")&&v.onThinking?.(g.status):g.content&&(S!==null&&(clearTimeout(S),S=null),M+=g.content,v.onChunk(g.content))}catch{w({raw:P})}le!==void 0&&(de=le,le=void 0)},ke=()=>{if(k(),O)throw _(),R(O.code,O.message,O.matchedWords),this.log({method:"STREAM",path:e,body:t,error:O,durationMs:Date.now()-f,modelName:i?.modelName}),O;this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log("Message ID:",ee),ce&&console.log("Aborted:",ce),console.log(`SSE events (${C.length}):`,C),console.groupEnd()),G(v,{messageId:ee,truncated:ge,aborted:ce})};try{for(;;){let{done:E,value:I}=await be.read();if(E)break;U+=Ne.decode(I,{stream:!0});let P=U.split(`
121
- `);U=P.pop()??"";for(let g of P)De(g);if(L){ke();return}}if(U+=Ne.decode(),U&&De(U),L){ke();return}}catch(E){if(k(),O)throw O;if(b){let I=new u(b,"Stream did not start in time");if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2717 ${b}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Timeout:",I),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw R(b),_(),I}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${p} (${Date.now()-f}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Stream error:",E),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw _(),E}if(k(),ee){G(v,{messageId:ee,truncated:ge});return}if(a){await this.resumeLoop(a,de,v,{finalize:!0});return}_()}async resumeLoop(e,t,n,r){let i=t;for(let c=1;c<=T.RECONNECT_MAX_ATTEMPTS;c++){let l=Math.min(T.RECONNECT_BACKOFF_CAP,1e3*2**(c-1));await new Promise(h=>setTimeout(h,l)),n.onReconnect?.({attempt:c});let a={messageId:"",lastId:i},d;try{d=await this.pumpGetStream(e.conversationId,e.topic,i,a,n)}catch{continue}if(i=a.lastId??i,d==="done"){if(a.errorCode)throw this.terminalError(a);G(n,a);return}if(d==="inactive"){(a.messageId||r?.finalize)&&G(n,a);return}}let s=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw R("STREAM_INTERRUPTED"),s}async resumeStream(e,t,n){let{cbs:r}=Ie(n),i={messageId:""},s;try{s=await this.pumpGetStream(e,t,void 0,i,r)}catch{await this.resumeLoop({conversationId:e,topic:t},i.lastId,r);return}if(s==="done"){if(i.errorCode)throw this.terminalError(i);G(r,i);return}if(s==="inactive"){i.messageId&&G(r,i);return}await this.resumeLoop({conversationId:e,topic:t},i.lastId,r)}terminalError(e){let t=new u(e.errorCode??"INTERNAL_ERROR",e.errorMessage||"Generation failed",e.errorMatchedWords);return R(t.code,t.message,t.matchedWords),t}async pumpGetStream(e,t,n,r,i){let s=new URL(`${this.baseUrl}/conversations/${encodeURIComponent(e)}/stream`);n&&s.searchParams.set("from",n),t&&s.searchParams.set("topic",t);let c=new AbortController,l=setTimeout(()=>c.abort(),T.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(l)}if(!a.ok)throw new u("STREAM_INTERRUPTED",`Resume HTTP ${a.status}`);if(!(a.headers.get("content-type")||"").includes("text/event-stream"))return"inactive";let h=a.body?.getReader();return h?await this.pumpReader(h,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},T.RESUME_STALL_TIMEOUT)};c();let l="",a=!1,d=h=>{if(a)return;let m=h.endsWith("\r")?h.slice(0,-1):h;if(m.startsWith("id: ")){i=m.slice(4);return}if(!m.startsWith("data: "))return;let f=m.slice(6);if(f==="[DONE]"){a=!0;return}try{let p=JSON.parse(f);p.type==="done"&&p.id?(t.messageId=p.id,t.truncated=p.truncated===!0):p.type==="aborted"?(t.aborted={id:typeof p.id=="string"?p.id:"",persisted:p.persisted===!0},a=!0):p.type==="error"?(t.errorCode=p.code||"INTERNAL_ERROR",t.errorMessage=p.message||"Generation failed",Array.isArray(p.matched_words)&&(t.errorMatchedWords=p.matched_words),a=!0):p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="start"?typeof p.base_content=="string"&&n.onBase?.(p.base_content):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}i!==void 0&&(t.lastId=i,i=void 0)};try{for(;;){let{done:h,value:m}=await e.read();if(h)break;c(),l+=r.decode(m,{stream:!0});let f=l.split(`
122
- `);l=f.pop()??"";for(let p of f)d(p);if(a)return s&&clearTimeout(s),"done"}if(l+=r.decode(),l&&d(l),a)return s&&clearTimeout(s),"done"}catch{}finally{s&&clearTimeout(s)}return"eof"}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let r=n&&typeof n=="object"?n:{},i={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.error_code??r.code,c=s==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":s==="TTS_RATE_LIMITED"?"RATE_LIMITED":s||i[e.status]||"INTERNAL_ERROR",l=Array.isArray(r.matched_words)?r.matched_words:void 0,a=new u(c,r.message||`HTTP ${e.status}`,l);throw R(c,r.message,l),a}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.INITIAL_TIMEOUT=3e4,T.RESUME_STALL_TIMEOUT=6e4,T.RECONNECT_MAX_ATTEMPTS=10,T.RECONNECT_BACKOFF_CAP=15e3;var ie=T;var Ee=o=>o.trim().toLowerCase();function se(o){let e=re(),t=o.name_i18n??{};return t[e]||t[e.replace("-","_")]||o.name}function qe(o,e){let t=Ee(e);return o.find(n=>Ee(n.name)===t)??o.find(n=>Object.values(n.name_i18n??{}).some(r=>typeof r=="string"&&Ee(r)===t))}var Xe="storvia_chat_main";function kt(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let o=new Uint8Array(16);crypto.getRandomValues(o),o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=Array.from(o,t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}var ze=20,Qe=40,V=class{constructor(e,t,n,r,i=!1,s,c,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewHistory=[];this.previewConfig=s,this.getModelName=c,this.getPreset=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.(),client_message_uuid:kt()};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{game_id:this.getGameId(),conversation_id:this.getConversationId(),role:e.role,content:e.content,topic:e.topic})}async generate(e){if(this.isPreview)return this.sendPreview({message:"",topic:e.topic,sceneKey:e.sceneKey,stream:e.stream,onChunk:e.onChunk,onDone:e.onDone,onState:e.onState,onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters});let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/generate",t,this.reqMeta())}async once(e){if(this.isPreview)return this.oncePreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,stream:e.stream===!0,preset:this.getPreset?.()};if(!e.stream)return this.http.post("/once",t,this.reqMeta());let n="";return await this.http.stream("/once",t,r=>{n+=r,e.onChunk?.(r)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:n}}async oncePreview(e){let t={model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,history_messages:[],preset:this.getPreset?.()};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language);let r="";return await this.http.stream("/preview",t,i=>{r+=i,e.onChunk?.(i)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:r}}async retry(e={}){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.retry() is not available in preview mode. Publish the game and test on the Storvia platform.");let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/retry",t,this.reqMeta())}async continue(e={}){if(this.isPreview)return;let t={conversation_id:this.getConversationId(),topic:e.topic??null,game_id:this.getGameId(),preset:this.getPreset?.(),scene_key:e.sceneKey,extract:e.extract};await this.http.stream("/continue",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted,e.onBase)}async cancel(e={}){if(this.isPreview)return{active:!1};let t=await this.http.post(`/conversations/${encodeURIComponent(this.getConversationId())}/cancel`,{topic:e.topic});return{active:t.active===!0,generationId:t.generation_id}}async messages(e){if(this.isPreview)return{data:[],hasMore:!1,nextCursor:null};let t={conversation_id:this.getConversationId(),order:e.order,limit:String(e.limit??20)};e.topic&&(t.topic=e.topic),e.cursor&&(t.cursor_uuid=e.cursor.uuid,t.cursor_created_at=e.cursor.createdAt);let n=await this.http.get("/messages",t);return{data:n.messages.map(r=>({uuid:r.uuid,role:r.role,content:r.content,topic:r.topic,status:r.status,model:r.model,createdAt:r.created_at,truncated:r.truncated===!0})),hasMore:n.has_more,nextCursor:n.next_cursor?{uuid:n.next_cursor.cursor_uuid,createdAt:n.next_cursor.cursor_created_at}:null}}async edit(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.edit() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.patch(`/messages/${encodeURIComponent(e.uuid)}`,{content:e.content});return{uuid:t.uuid,role:t.role,content:t.content,updatedAt:t.updated_at}}async delete(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.delete() is not available in preview mode. Publish the game and test on the Storvia platform.");return{uuid:(await this.http.delete(`/messages/${encodeURIComponent(e.uuid)}`)).uuid}}async rollback(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.rollback() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.post(`/messages/${encodeURIComponent(e.uuid)}/rollback`,{});return{deletedCount:t.deleted_count,deletedUuids:t.deleted_uuids,restoredGameState:t.restored_game_state}}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:F(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting,onAborted:e.onAborted})}async sendPreview(e){let t=e.message.trim().length>0,n=this.previewHistory.slice(t?-(ze-1):-ze);t&&this.pushPreviewHistory({role:"user",content:e.message});let r={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:n,preset:this.getPreset?.()};this.previewConfig?r.prompt_config=this.previewConfig:r.game_id=this.getGameId();let i=this.previewConfig;if(i?.reply_length&&(r.reply_length=i.reply_length),i?.reply_language&&(r.reply_language=i.reply_language),e.stream){let h="";await this.http.stream("/preview",r,m=>{h+=m,e.onChunk?.(m)},(m,f)=>{h&&this.pushPreviewHistory({role:"assistant",content:h}),e.onDone?.(m,f)},this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters);return}let s="",c=null,l=null,a=[];await this.http.stream("/preview",r,h=>{s+=h},()=>{},this.reqMeta(),(h,m)=>{c=h,l=m,e.onState&&e.onState(c,l)},void 0,h=>{a=h,e.onCreatedCharacters&&e.onCreatedCharacters(h)}),s&&this.pushPreviewHistory({role:"assistant",content:s});let d={id:"",content:s,truncated:!1};return c&&(d.delta=c,l&&(d.full=l)),a.length&&(d.createdNames=a),d}pushPreviewHistory(e){this.previewHistory.push(e),this.previewHistory.length>Qe&&this.previewHistory.splice(0,this.previewHistory.length-Qe)}};function F(o){if(o)return(e,t)=>o(e,t)}var we=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let r=this.mem[e]||{};return t?{...r[t]||{}}:{...r}}let n=t?{group:t}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,n)}async update(e,t,n){if(this.isPreview){let r=this.mem[e]||(this.mem[e]={});r[t]={...r[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}async remove(e,t,n){if(n.length){if(this.isPreview){let r=this.mem[e]?.[t];if(r)for(let i of n)delete r[i];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeKeys:n})}}async removeGroup(e,t){if(this.isPreview){let n=this.mem[e];n&&delete n[t];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeGroup:!0})}},H=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(Ze)),this.state=new we(e,t,n,i)}previewNames(){return this.mem.map(e=>e.name)}setInitial(e,t){this.mem=e?e.map(Ze):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Je):(await this.http.get(`/conversations/${this.getConversationId()}/characters`)).map(Te)}async get(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return n?Je(n):{name:e,hasVoice:!1}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`);return Te(t)}async add(e){if(this.isPreview){this.mem.push({...e,isPreset:!1});return}await this.http.post(`/conversations/${this.getConversationId()}/characters`,e)}async update(e,t){if(this.isPreview){let n=this.mem.find(r=>r.name===e);n&&Object.assign(n,t);return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`,t)}async remove(e){if(this.isPreview){this.mem=this.mem.filter(t=>t.name!==e);return}await this.http.delete(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}async merge(e,t){if(this.isPreview){if(this.mem.find(r=>r.name===e)?.isPreset)throw new u("INVALID_REQUEST","\u9884\u8BBE\u89D2\u8272\u4E0D\u53EF\u88AB\u5408\u5E76");if(e===t||!this.mem.some(r=>r.name===t))throw new u("INVALID_REQUEST","\u76EE\u6807\u89D2\u8272\u4E0D\u5B58\u5728\u6216\u4E0E\u6765\u6E90\u76F8\u540C");this.mem=this.mem.filter(r=>r.name!==e);return}await this.http.post(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/merge`,{target:t})}async detail(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return{name:e,avatar:n?.avatar,description:n?.description,hasVoice:n?.hasVoice===!0,...n?.introduction!==void 0?{introduction:n.introduction}:{},...n?.visibleAtStart!==void 0?{visibleAtStart:n.visibleAtStart}:{},userDescription:n?.userDescription,...n?.gender?{gender:n.gender}:{},...n?.isPreset!==void 0?{isPreset:n.isPreset}:{},state:await this.state.get(e)}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`);return Te(t)}async setPriority(e,t){let n=Math.max(0,Math.min(100,Math.round(t)));this.isPreview||await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{priority:n})}};function Ze(o){return{name:o.name,description:o.description,avatar:o.avatar,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Je(o){return{name:o.name,avatar:o.avatar,description:o.description,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Te(o){let{voice:e,...t}=o;return{...t,hasVoice:!!e}}var et="\u73A9\u5BB6",Mt=["Player","player","PLAYER","\u30D7\u30EC\u30A4\u30E4\u30FC","\uD50C\uB808\uC774\uC5B4","\u4E3B\u63A7","{{user}}","user"],ye=o=>o.toLowerCase().replace(/[\s_\-]+/g,""),xt=new Set(["\u73A9\u5BB6",...Mt].map(ye));function tt(o,e){if(o==="\u73A9\u5BB6")return o;let t=ye(o);return xt.has(t)?e.some(n=>ye(n)===t)?o:"\u73A9\u5BB6":o}var W=class{constructor(e,t,n=!1,r,i=()=>[]){this.http=e;this.getConversationId=t;this.isPreview=n;this.getCharacterNames=i;this.mem=[];r&&(this.mem=r.map(s=>({...s})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}entity(e){return this.isPreview?tt(e,this.getCharacterNames()):e}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t);let n=this.mem.find(r=>r.from===e&&r.to===t);if(n)return{...n};throw new Error("Relationship not found")}return this.http.get(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}async add(e){if(this.isPreview){this.mem.push({...e,from:this.entity(e.from),to:this.entity(e.to)});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){e=this.entity(e),t=this.entity(t);let r=this.mem.find(i=>i.from===e&&i.to===t);r?Object.assign(r,n):this.mem.push({from:e,to:t,...n});return}await this.http.patch(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,n)}async remove(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t),this.mem=this.mem.filter(n=>!(n.from===e&&n.to===t));return}await this.http.delete(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}};function nt(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function Ce(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let r={};for(let[i,s]of Object.entries(n))r[i]=nt(s);e[t]=r}return e}function Ut(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=nt(n);return e}var B=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=Ce(r))}setInitial(e){this.mem=e?Ce(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[r,i]of Object.entries(this.mem))n[r]={...i};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return Ut(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return Ce(t)}async add(e){let{group:t,name:n,count:r=1,desc:i,iconUrl:s}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:r};i!==void 0&&(l.desc=i),s!==void 0&&(l.iconUrl=s),this.mem[t][n]=l;return}let c={group:t,name:n,count:r};i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,c)}async update(e){let{group:t,name:n,count:r,desc:i,iconUrl:s}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];r!==void 0&&(a.count=r),i!==void 0&&(a.desc=i),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,c)}async remove(e){let{group:t,name:n}=e;if(this.isPreview){this.mem[t]&&delete this.mem[t][n];return}await this.http.delete(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`)}async removeBatch(e){if(this.isPreview){for(let{group:t,name:n}of e)this.mem[t]&&delete this.mem[t][n];return}e.length!==0&&await this.http.post(`/conversations/${this.getConversationId()}/inventory/batch-delete`,{items:e})}async move(e){let{fromGroup:t,toGroup:n,name:r,newName:i}=e;if(this.isPreview){let s=this.mem[t];if(!s||!(r in s))throw new Error(`Source item "${t}/${r}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let c=i||r;if(t===n&&c===r)return;if(c in this.mem[n])throw new Error(`Item "${c}" already exists in target group`);this.mem[n][c]=s[r],delete s[r];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:r,newName:i})}async ensureGroup(e){if(this.isPreview){this.mem[e]||(this.mem[e]={});return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}`,{})}async removeGroup(e,t){let n=t?.cascade??!1;if(this.isPreview){let i=this.mem[e];if(i&&Object.keys(i).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let r=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${r}`)}};var j=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:this.http.get(`/conversations/${this.getConversationId()}/world`)}async update(e){if(this.isPreview){Object.assign(this.mem,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/world`,e)}};var _e=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e){if(this.isPreview)return e?{...this.mem[e]||{}}:{...this.mem};let t=e?{group:e}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/player/state`,t)}async update(e,t){if(this.isPreview){this.mem[e]={...this.mem[e]||{},...t};return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,values:t})}async remove(e,t){if(t.length){if(this.isPreview){let n=this.mem[e];if(n)for(let r of t)delete n[r];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeKeys:t})}}async removeGroup(e){if(this.isPreview){delete this.mem[e];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeGroup:!0})}},K=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new _e(e,t,n,i)}setInitial(e,t){this.memPersona=e?{...e}:{name:""},this.state.setInitial(t)}async get(){return this.isPreview?{...this.memPersona}:this.http.get(`/conversations/${this.getConversationId()}/player`)}async update(e){if(this.isPreview){Object.assign(this.memPersona,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/player`,e)}};function Y(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var q=class{constructor(e,t,n,r=!1,i,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};i&&(this.mem=rt(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?rt(e):{},this.memInject=t?{...t}:{}}async get(e){if(this.isPreview)return e!==void 0?this.mem[e]:{...this.mem};let t=await this.http.get(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,i]of Object.entries(e))typeof i=="object"&&i!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...i}:this.mem[r]=i,t?.inject!==void 0&&(this.memInject[r]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,this.getGameId()),{inject:t})}getInject(){return{...this.memInject}}async delete(e){if(this.isPreview){delete this.mem[e],delete this.memInject[e];return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}`,this.getGameId()))}async setGroupField(e,t,n){if(this.isPreview){(!this.mem[e]||typeof this.mem[e]!="object")&&(this.mem[e]={}),this.mem[e][t]=n;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()),{value:n})}async deleteGroupField(e,t){if(this.isPreview){if(typeof this.mem[e]=="object"&&this.mem[e]!==null){let n=this.mem[e];delete n[t]}return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function rt(o){let e={};for(let[t,n]of Object.entries(o))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function ot(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var z=class{constructor(e,t,n,r=!1,i){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var Q=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n}async get(){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.state.get() is not available in preview mode. Publish the game and test on the Storvia platform. (Use per-module get() like storvia.world.get() if you need to inspect state during preview.)");return this.http.get(`/conversations/${this.getConversationId()}/state`)}};var X=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null;this.wb=null;this.worldbook={get:async()=>this.isPreview?this.wb?it(this.wb):null:(await this.http.get(`/conversations/${this.getConversationId()}/worldbook`)).worldbook,update:async e=>{let t=typeof e=="string"?{content:e}:{...e};if(t.content!==void 0&&(t.content=(t.content??"").trim()),t.entries!==void 0&&(t.entries=Lt(t.entries)),this.isPreview){let r=this.wb?.presets??[],i=t.enabledPresets?r.map(c=>({...c,enabled:t.enabledPresets.includes(c.id)})):r,s={content:t.content??this.wb?.content??"",contentWidget:t.contentWidget??this.wb?.contentWidget??!1,entries:t.entries??this.wb?.entries??[],presets:i,updated_at:new Date().toISOString()};return this.wb=s,it(s)}return(await this.http.patch(`/conversations/${this.getConversationId()}/worldbook`,t)).worldbook}}}async get(){return this.isPreview?this.mem?{...this.mem}:null:(await this.http.get(`/conversations/${this.getConversationId()}/summary`)).ai_summary}async update(e){let t=(e??"").trim();if(this.isPreview){let r={content:t,updated_at:new Date().toISOString()};return this.mem=r,{...r}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};function it(o){return{...o,entries:o.entries.map(e=>({...e,keys:[...e.keys]})),presets:(o.presets??[]).map(e=>({...e}))}}function Lt(o){return(o??[]).flatMap(e=>{let t=(e?.content??"").trim(),n=[...new Set((e?.keys??[]).map(s=>(s??"").trim()).filter(s=>s!==""))],r=e?.constant===!0;if(!t||!r&&n.length===0)return[];let i=(e?.title??"").trim();return[{id:e.id||$t(),keys:n,content:t,...i?{title:i}:{},constant:r,enabled:e?.enabled!==!1,widget:e?.widget===!0}]})}function $t(){let o=globalThis.crypto;return o?.randomUUID?o.randomUUID():`ewr-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var Re=60,Se=1e3,pe=1e4,N=class{constructor(e,t=!1,n=()=>Date.now()){this.send=e;this.isPreview=t;this.now=n;this.lastNotifyAt=0;this.lastRefreshAt=0;this.lastRefreshMessagesAt=0}notify(e){let t=Gt(e);if(!t)return!1;let n=this.now();return n-this.lastNotifyAt<Se?!1:(this.lastNotifyAt=n,this.isPreview?(oe(t,"info"),!0):(this.send(y("host-notify",{text:t})),!0))}refreshPanel(e){if(this.isPreview)return!1;let t=this.now();return t-this.lastRefreshAt<pe?!1:(this.lastRefreshAt=t,this.send(y("host-state-changed",e?.length?{scope:e}:{})),!0)}refreshMessages(){if(this.isPreview)return!1;let e=this.now();return e-this.lastRefreshMessagesAt<pe?!1:(this.lastRefreshMessagesAt=e,this.send(y("host-messages-changed",{})),!0)}};function Gt(o){return typeof o!="string"?"":o.replace(/\s+/g," ").trim().slice(0,Re)}var Ft;function st(){return Ft??(Ft=new Promise((o,e)=>{let t=indexedDB.open("storvia-sdk-speech",1);t.onupgradeneeded=()=>t.result.createObjectStore("audio"),t.onsuccess=()=>o(t.result),t.onerror=()=>e(t.error)}))}async function at(o){let e=await st();return new Promise((t,n)=>{let r=e.transaction("audio").objectStore("audio").get(o);r.onsuccess=()=>t(r.result??null),r.onerror=()=>n(r.error)})}async function ct(o,e){let t=await st();return new Promise((n,r)=>{let i=t.transaction("audio","readwrite");i.objectStore("audio").put(e,o),i.oncomplete=()=>n(),i.onabort=()=>r(i.error)})}function dt(o){let e=o,t;do t=e,e=e.replace(/[((][^()()]*[))]/g,"");while(e!==t);return e.replace(/\s+/g," ").trim()}var Z=class{constructor(e,t,n,r,i=!1){this.getHttp=e;this.getConversationId=t;this.getGameId=n;this.getVoice=r;this.isPreview=i;this.pending=new Map}async speak(e){let t=dt(e.text),n=await this.getVoice(e.character);if(!n)throw new u("TTS_UNKNOWN_VOICE","Character has no voice configured");let r=this.isPreview?this.getGameId():this.getConversationId(),i=JSON.stringify([r,n,t]),s={text:t,...this.isPreview?{voice:n}:{conversation_id:this.getConversationId(),character_name:e.character}},c=globalThis;if(c.__storviaNativeTts&&c.flutter_inappwebview){let d=await c.flutter_inappwebview.callHandler("storviaTts",{body:s,key:i});if(d.error){let m=d.error==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":d.error==="TTS_RATE_LIMITED"?"RATE_LIMITED":d.error;throw R(m),new u(m,d.error)}let h=Uint8Array.from(atob(d.audio),m=>m.charCodeAt(0));return{audio:new Blob([h],{type:"audio/mpeg"}),cached:d.cached}}let l=await at(i);if(l)return{audio:l,cached:!0};let a=this.pending.get(i);return a||(a=this.getHttp().postAudio("/speak",s).then(async d=>{try{await ct(i,d)}catch{console.warn("[Storvia TTS] \u97F3\u9891\u7F13\u5B58\u4FDD\u5B58\u5931\u8D25")}return{audio:d,cached:!1}}),this.pending.set(i,a),a.then(()=>this.pending.delete(i),()=>this.pending.delete(i))),a}};var J=class{constructor(e){this.getHttp=e}async transcribe(e){if(!e||typeof e!="object")throw new u("INVALID_REQUEST","Recognition options are required");if(!(e.audio instanceof Blob)||e.audio.size===0||e.audio.size>10485760)throw new u("ASR_BAD_AUDIO","Audio must be a non-empty file of at most 10 MB");let t=e.audio.type.split(";")[0].trim().toLowerCase(),n=e.format??qt[t];if(!n||!Kt.includes(n))throw new u("ASR_BAD_AUDIO","Specify a supported audio format");if(e.context!==void 0&&typeof e.context!="string"||!lt(e.languageHints,4)||!lt(e.hotwords,50)||(e.context?.length??0)>400||e.hotwords?.some(i=>i.length>64))throw new u("INVALID_REQUEST","Recognition context, language hints, or hotwords exceed the limits");let r=new FormData;return r.append("file",e.audio,`audio.${n}`),r.append("format",n),e.context!==void 0&&r.append("context",e.context),e.languageHints!==void 0&&r.append("language_hints",JSON.stringify(e.languageHints)),e.hotwords!==void 0&&r.append("hotwords",JSON.stringify(e.hotwords)),this.getHttp().postForm("/transcribe",r,Yt)}},Kt=["wav","mp3","m4a","webm","ogg","opus","flac","aac"],Yt=15e4;function lt(o,e){return o===void 0||Array.isArray(o)&&o.length<=e&&o.every(t=>typeof t=="string"&&t.trim().length>0)}var qt={"audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav","audio/mpeg":"mp3","audio/mp3":"mp3","audio/mp4":"m4a","audio/x-m4a":"m4a","audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/opus":"opus","audio/flac":"flac","audio/x-flac":"flac","audio/aac":"aac"};var ht="/functions/v1/world-engine/v1",zt="https://api.storvia.ai";function Qt(){return window.__STORVIA__||{}}function Xt(o,e=3e4){let t=Qt();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let i=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,lang:a.payload.lang,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(i),s(),c();let d=window;d.__STORVIA__=a,n(a)}o.send(y("ready",{}))})}var ae=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.presetId="";this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0;this.previewVoices=new Map}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new x({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?d=>d.source===null||d.source===window:d=>d.source===window.parent,customSend:t?d=>e.callHandler("storviaBus",d):void 0}),Be(d=>this.bus.send(d));let n=await Xt(this.bus),r=n.apiBase;if(!r)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${r}${ht}`,this.isPreview=!!n.preview,this.previewConfig=n.previewConfig,!n.gameId)throw new u("GAME_NOT_FOUND","window.__STORVIA__.gameId is not set. The platform must inject it before SDK init.");if(this.gameId=n.gameId,!n.accessToken)throw new u("UNAUTHORIZED","window.__STORVIA__.accessToken is not set. The platform must inject the user token before SDK init.");if(this.accessToken=n.accessToken,$e(n.lang),this.http=new ie(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000",this.models=n.models??[],this.modelId=n.selectedModelId||this.models[0]?.id||"";let[d,h]=await Promise.all([this.fetchPreviewSnapshot(),this.modelId?Promise.resolve(null):this.fetchModels()]);h&&(this.models=h,this.modelId=h[0]?.id||""),this.presetId=n.presetId||"";let m=()=>this.gameId,f=()=>this.conversationId,p=()=>this.modelId,C=()=>{let v=this.models.find(_=>_.id===this.modelId);return v?se(v):void 0},w=()=>this.presetId||void 0;this.chat=new V(this.http,m,f,p,!0,this.previewConfig,C,w),this.characters=new H(this.http,f,!0,d.characters,d.characterStates),this.tts=new Z(()=>this.http.ttsClient(),f,m,v=>this.getCharacterVoice(v),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,f,!0,d.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,f,!0,d.inventory),this.world=new j(this.http,f,!0,d.world),this.player=new K(this.http,f,!0,d.player,d.playerState),this.custom=new q(this.http,f,m,!0,d.custom,d.custom_inject),this.save=new z(this.http,f,m,!0,d.save_data),this.state=new Q(this.http,f,!0),this.memory=new X(this.http,f,!0),this.host=new N(v=>this.bus.send(v),!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}if(!n.conversationId)throw new u("NOT_INITIALIZED","window.__STORVIA__.conversationId is not set. The platform must inject it before SDK init.");this.conversationId=n.conversationId,this.modelId=n.selectedModelId||"",this.modelId||(this.models=await this.fetchModels(),this.modelId=this.models[0]?.id||""),this.presetId=n.presetId||"";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(h=>h.id===this.modelId);return d?se(d):void 0},a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!1,void 0,l,a),this.characters=new H(this.http,s),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s),this.inventory=new B(this.http,s),this.world=new j(this.http,s),this.player=new K(this.http,s),this.custom=new q(this.http,s,i),this.save=new z(this.http,s,i),this.state=new Q(this.http,s),this.memory=new X(this.http,s),this.host=new N(d=>this.bus.send(d),!1),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""})}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}listenForPreviewMessages(){this.bus.on("set-model",e=>{this.modelId=e.payload.modelId||""}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""}),this.bus.on("config-update",e=>{this.previewConfig=e.payload.previewConfig,this.chat&&this.chat.updatePreviewConfig(this.previewConfig),this.refreshPreviewSnapshot().catch(t=>{console.warn("[Storvia SDK] refreshPreviewSnapshot failed:",t)})})}async getCharacterVoice(e){return this.isPreview?this.previewVoices.get(e):(await this.http.get(`/conversations/${this.conversationId}/characters/${encodeURIComponent(e)}`)).voice}async fetchPreviewSnapshot(){let e={game_id:this.gameId};this.previewConfig&&("game_config"in this.previewConfig&&(e.game_config=this.previewConfig.game_config),"game_state"in this.previewConfig&&(e.game_state_override=this.previewConfig.game_state));let t=await this.http.post("/preview/initial-snapshot",e);return this.previewVoices=new Map(t.characters.map(n=>[n.name,n.voice])),{...t,characters:t.characters.map(({voice:n,...r})=>({...r,hasVoice:!!n}))}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();this.characters?.setInitial(e.characters,e.characterStates),this.player?.setInitial(e.player,e.playerState),this.inventory?.setInitial(e.inventory),this.relationships?.setInitial(e.relationships),this.world?.setInitial(e.world),this.custom?.setInitial(e.custom,e.custom_inject),this.save?.setInitial(e.save_data)}async fetchModels(e=!1){try{return await this.http.get("/models",e?void 0:{locale:re()})}catch{}return[]}async initDev(e){if(this.initialized)return;this.baseUrl=`${zt}${ht}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new ie(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(!!e.model),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?qe(t,e.model):void 0;e.model&&!r&&console.warn(`[Storvia SDK] dev.model "${e.model}" not found, falling back to the first model. Available:`,t.map(se)),this.modelId=r?.id||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(h=>h.id===this.modelId);return d?se(d):void 0};this.presetId=e.preset||"";let a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!0,void 0,l,a),this.characters=new H(this.http,s,!0,n.characters,n.characterStates),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s,!0,n.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,s,!0,n.inventory),this.world=new j(this.http,s,!0,n.world),this.player=new K(this.http,s,!0,n.player,n.playerState),this.custom=new q(this.http,s,i,!0,n.custom,n.custom_inject),this.save=new z(this.http,s,i,!0,n.save_data),this.state=new Q(this.http,s,!0),this.memory=new X(this.http,s,!0),this.host=new N(()=>{},!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e,locale:re()};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,assetId:i.asset_id,name:i.name,nameI18n:i.meta.name_i18n,url:i.url,assetType:i.asset_type,category:i.category,categoryI18n:i.category_i18n,tags:i.tags.map(s=>({id:s.id,label:s.label,labelI18n:s.label_i18n}))}))}};async function ut(o){Ge();let e=new ae;return o?.dev?await e.initDev(o.dev):await e.init(),e}function Ae(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function pt(o){return Ae(o)?o.value:o}return Et(Zt);})();
120
+ `;let c=s.querySelector(".storvia-toast-msg");c&&(c.textContent=o);let l=()=>{s.isConnected&&(s.classList.add("leaving"),s.classList.remove("show"),setTimeout(()=>s.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(d){console.error("[Storvia toast] action error:",d)}l()}),s.appendChild(a)}if(i){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label",he("close")),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",l),s.appendChild(a)}r.appendChild(s),requestAnimationFrame(()=>s.classList.add("show")),i||setTimeout(l,t)}function bt(o){let e=o.filter(t=>t).map(t=>`\u300C${t}\u300D`).join("");return he("violationWords").replace("{words}",e)}var Nt=3e3,He={};function We(o){let e=Date.now();if(!(e-(He[o]??0)<Nt)){if(He[o]=e,!ve){console.warn(`[Storvia] navigate \u2192 wallet(${o})\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u751F\u4EA7\u73AF\u5883\u7531\u5BBF\u4E3B\u5F39\u5145\u503C\u5F15\u5BFC / \u8DF3\u94B1\u5305\u9875\u3002`);return}try{ve(y("navigate",{target:"wallet",reason:o}))}catch(t){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",t)}}}function R(o,e,t){if(o==="GENERATION_ABORTED")return;if(o==="INSUFFICIENT_CREDITS")return We("insufficient_credits");if(o==="DAISY_CARD_REQUIRED")return We("daisy_card_required");let n=o==="VIOLATION_WORD_DETECTED"&&t?.length?bt(t):Fe(o)||e||he("unknownError");oe(n,o==="RATE_LIMITED"?"warning":"error")}function Dt(o,e){let t=e?.tickMs??100,n=e?.baseLagMs??1e3,r=e?.maxLagMs??2500,i=e?.minCharsPerTick??2,s="",c=null,l=0,a=0,d=()=>Math.min(r,Math.max(n,l*1.35)),g=()=>{let w=Math.max(i,Math.ceil(s.length*t/d()));if(w>=s.length)w=s.length;else{let _=s.charCodeAt(w-1);_>=55296&&_<=56319&&w++}let v=s.slice(0,w);s=s.slice(w),v&&o(v)},p=()=>{c=null,g(),s&&(c=setTimeout(p,t))};return{push:w=>{let v=Date.now();if(a>0){let _=Math.min(v-a,r);l=l>0?l*.7+_*.3:_}a=v,s+=w,c===null&&p()},flush:()=>{c!==null&&(clearTimeout(c),c=null),s&&(o(s),s="")},cancel:()=>{c!==null&&(clearTimeout(c),c=null),s=""}}}function Ie(o){let e=Dt(o.onChunk);return{cbs:{onChunk:n=>e.push(n),onDone:(n,r)=>{e.flush(),o.onDone(n,r)},onAborted:o.onAborted?n=>{e.flush(),o.onAborted(n)}:void 0,onState:o.onState?(n,r)=>{e.flush(),o.onState(n,r)}:void 0,onThinking:o.onThinking?n=>{e.flush(),o.onThinking(n)}:void 0,onCreatedCharacters:o.onCreatedCharacters?n=>{e.flush(),o.onCreatedCharacters(n)}:void 0,onReconnect:o.onReconnect},flush:()=>e.flush()}}var Ye="0.10.10";function G(o,e){if(e.aborted){if(o.onAborted){o.onAborted(e.aborted);return}o.onDone(e.aborted.id,{truncated:!1});return}o.onDone(e.messageId,e.truncated===void 0?void 0:{truncated:e.truncated})}var T=class T{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}ttsClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/tts"),this.token,this.debug,this.devApiKey)}asrClient(){return new T(this.baseUrl.replace(/\/world-engine\/v1$/,"/asr"),this.token,this.debug,this.devApiKey)}async postForm(e,t,n=T.REQUEST_TIMEOUT){let r=this.buildHeaders();delete r["Content-Type"];let{controller:i,clear:s}=this.createTimeoutController(n);try{let c=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:r,body:t,signal:i.signal});return(await this.handleResponseWithRaw(c)).data}catch(c){let l=this.wrapAbortError(c);throw l===c&&this.maybeShowNetworkToast(c),l}finally{s()}}async postAudio(e,t){let{controller:n,clear:r}=this.createTimeoutController();try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:n.signal});i.ok||await this.handleResponseWithRaw(i);let{audio_url:s}=await i.json(),c=await fetch(s,{signal:n.signal});if(!c.ok)throw new u("TTS_UPSTREAM_FAILED",`Audio download failed: HTTP ${c.status}`);if(c.headers.get("Content-Type")?.includes("application/json"))throw new u("TTS_UPSTREAM_FAILED","Audio download returned JSON");return await c.blob()}catch(i){let s=this.wrapAbortError(i);throw s===i&&this.maybeShowNetworkToast(i),s}finally{r()}}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||R("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return R("REQUEST_TIMEOUT"),t}return e}createTimeoutController(e=T.REQUEST_TIMEOUT){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return{controller:t,clear:()=>clearTimeout(n)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e["x-client-info"]=`storvia-sdk/${Ye}`,e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:l,durationMs:a,modelName:d}=e,g="%c[Storvia SDK]",p="color: #6366f1; font-weight: bold",m=a!==void 0?` (${a}ms)`:"",h=i!==void 0?` [${i}]`:"",C=d?` [model: ${d}]`:"";l?(console.groupCollapsed(`${g} %c${t} ${n}${h}${C}${m} %c\u2717`,p,"color: #e0e0e0","color: #ef4444"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),console.error("Error:",l),console.groupEnd()):(console.groupCollapsed(`${g} %c${t} ${n}${h}${C}${m} %c\u2713`,p,"color: #e0e0e0","color: #22c55e"),r!==void 0&&console.log("Request:",r),s!==void 0&&console.log("Response (raw):",s),c!==void 0&&c!==s&&console.log("Response (data):",c),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,d])=>n.searchParams.set(a,d));let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});l(),i=a.status;let{raw:d,data:g}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:g,durationMs:Date.now()-r}),g}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r}),d===a&&this.maybeShowNetworkToast(a),d}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:l}=this.createTimeoutController();try{let a=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:c.signal});l(),i=a.status;let{raw:d,data:g}=await this.handleResponseWithRaw(a);return s=d,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:g,durationMs:Date.now()-r,modelName:n?.modelName}),g}catch(a){l();let d=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:d,durationMs:Date.now()-r,modelName:n?.modelName}),d===a&&this.maybeShowNetworkToast(a),d}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=l.status;let{raw:a,data:d}=await this.handleResponseWithRaw(l);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:d,durationMs:Date.now()-n}),d}catch(l){c();let a=this.wrapAbortError(l);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===l&&this.maybeShowNetworkToast(l),a}}async delete(e){let t=Date.now(),n,r,{controller:i,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:i.signal});s(),n=c.status;let{raw:l,data:a}=await this.handleResponseWithRaw(c);return r=l,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let l=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:l,durationMs:Date.now()-t}),l===c&&this.maybeShowNetworkToast(c),l}}async stream(e,t,n,r,i,s,c,l,a,d,g,p){let m=Date.now(),h=i?.modelName?` [model: ${i.modelName}]`:"",C=[],w=E=>{this.debug&&C.push({t:Date.now()-m,event:E})},{cbs:v,flush:_}=Ie({onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:l,onReconnect:d,onAborted:g,onBase:p}),Oe=new AbortController,D=null,S=null,b=null,k=()=>{D!==null&&(clearTimeout(D),D=null),S!==null&&(clearTimeout(S),S=null)},Pe=E=>{b=E,k(),Oe.abort()};D=setTimeout(()=>Pe("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let A;try{A=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:Oe.signal})}catch(E){if(k(),b){let I=new u(b,"Request timed out");throw R(b),this.log({method:"STREAM",path:e,body:t,error:I,durationMs:Date.now()-m,modelName:i?.modelName}),I}throw this.maybeShowNetworkToast(E),E}if(D!==null&&(clearTimeout(D),D=null),!A.ok){k();let E=await A.text().catch(()=>""),I={};try{I=JSON.parse(E)}catch{}let P=I.code||"INTERNAL_ERROR",f=I.message||I.error||I.details,Me=Array.isArray(I.matched_words)?I.matched_words:void 0,xe=new u(P,f||`HTTP ${A.status}`,Me);throw R(P,f,Me),this.log({method:"STREAM",path:e,body:t,status:A.status,rawResponse:E,error:xe,durationMs:Date.now()-m,modelName:i?.modelName}),xe}let be=A.body?.getReader();if(!be)throw k(),new u("INTERNAL_ERROR","No response body for stream");S=setTimeout(()=>Pe("MODEL_LOADING_TIMEOUT"),T.INITIAL_TIMEOUT);let Ne=new TextDecoder,ee="",ge,ce,M="",de,le,U="",L=!1,O=null,De=E=>{if(L)return;let I=E.endsWith("\r")?E.slice(0,-1):E;if(I.startsWith("id: ")){le=I.slice(4);return}if(!I.startsWith("data: "))return;let P=I.slice(6);if(P==="[DONE]"){w("[DONE]"),L=!0;return}try{let f=JSON.parse(P);w(f),f.type==="done"&&f.id?(ee=f.id,ge=f.truncated===!0):f.type==="aborted"?(ce={id:typeof f.id=="string"?f.id:"",persisted:f.persisted===!0},L=!0):f.type==="error"?(O=new u(f.code||"INTERNAL_ERROR",f.message||"Generation failed",Array.isArray(f.matched_words)?f.matched_words:void 0),L=!0):f.type==="state"?(v.onState?.(f.delta,f.full??null),Array.isArray(f.createdNames)&&f.createdNames.length&&v.onCreatedCharacters?.(f.createdNames)):f.type==="start"?(S!==null&&(clearTimeout(S),S=null),typeof f.base_content=="string"&&p?.(f.base_content)):f.type==="thinking"?(f.status==="start"||f.status==="end")&&v.onThinking?.(f.status):f.content&&(S!==null&&(clearTimeout(S),S=null),M+=f.content,v.onChunk(f.content))}catch{w({raw:P})}le!==void 0&&(de=le,le=void 0)},ke=()=>{if(k(),O)throw _(),R(O.code,O.message,O.matchedWords),this.log({method:"STREAM",path:e,body:t,error:O,durationMs:Date.now()-m,modelName:i?.modelName}),O;this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log("Message ID:",ee),ce&&console.log("Aborted:",ce),console.log(`SSE events (${C.length}):`,C),console.groupEnd()),G(v,{messageId:ee,truncated:ge,aborted:ce})};try{for(;;){let{done:E,value:I}=await be.read();if(E)break;U+=Ne.decode(I,{stream:!0});let P=U.split(`
121
+ `);U=P.pop()??"";for(let f of P)De(f);if(L){ke();return}}if(U+=Ne.decode(),U&&De(U),L){ke();return}}catch(E){if(k(),O)throw O;if(b){let I=new u(b,"Stream did not start in time");if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2717 ${b}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Timeout:",I),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw R(b),_(),I}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${A.status}]${h} (${Date.now()-m}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${M.length} chars):`,M),console.log(`SSE events (${C.length}):`,C),console.error("Stream error:",E),console.groupEnd()),a){await this.resumeLoop(a,de,v,{finalize:!0});return}throw _(),E}if(k(),ee){G(v,{messageId:ee,truncated:ge});return}if(a){await this.resumeLoop(a,de,v,{finalize:!0});return}_()}async resumeLoop(e,t,n,r){let i=t;for(let c=1;c<=T.RECONNECT_MAX_ATTEMPTS;c++){let l=Math.min(T.RECONNECT_BACKOFF_CAP,1e3*2**(c-1));await new Promise(g=>setTimeout(g,l)),n.onReconnect?.({attempt:c});let a={messageId:"",lastId:i},d;try{d=await this.pumpGetStream(e.conversationId,e.topic,i,a,n)}catch{continue}if(i=a.lastId??i,d==="done"){if(a.errorCode)throw this.terminalError(a);G(n,a);return}if(d==="inactive"){(a.messageId||r?.finalize)&&G(n,a);return}}let s=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw R("STREAM_INTERRUPTED"),s}async resumeStream(e,t,n){let{cbs:r}=Ie(n),i={messageId:""},s;try{s=await this.pumpGetStream(e,t,void 0,i,r)}catch{await this.resumeLoop({conversationId:e,topic:t},i.lastId,r);return}if(s==="done"){if(i.errorCode)throw this.terminalError(i);G(r,i);return}if(s==="inactive"){i.messageId&&G(r,i);return}await this.resumeLoop({conversationId:e,topic:t},i.lastId,r)}terminalError(e){let t=new u(e.errorCode??"INTERNAL_ERROR",e.errorMessage||"Generation failed",e.errorMatchedWords);return R(t.code,t.message,t.matchedWords),t}async pumpGetStream(e,t,n,r,i){let s=new URL(`${this.baseUrl}/conversations/${encodeURIComponent(e)}/stream`);n&&s.searchParams.set("from",n),t&&s.searchParams.set("topic",t);let c=new AbortController,l=setTimeout(()=>c.abort(),T.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(l)}if(!a.ok)throw new u("STREAM_INTERRUPTED",`Resume HTTP ${a.status}`);if(!(a.headers.get("content-type")||"").includes("text/event-stream"))return"inactive";let g=a.body?.getReader();return g?await this.pumpReader(g,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},T.RESUME_STALL_TIMEOUT)};c();let l="",a=!1,d=g=>{if(a)return;let p=g.endsWith("\r")?g.slice(0,-1):g;if(p.startsWith("id: ")){i=p.slice(4);return}if(!p.startsWith("data: "))return;let m=p.slice(6);if(m==="[DONE]"){a=!0;return}try{let h=JSON.parse(m);h.type==="done"&&h.id?(t.messageId=h.id,t.truncated=h.truncated===!0):h.type==="aborted"?(t.aborted={id:typeof h.id=="string"?h.id:"",persisted:h.persisted===!0},a=!0):h.type==="error"?(t.errorCode=h.code||"INTERNAL_ERROR",t.errorMessage=h.message||"Generation failed",Array.isArray(h.matched_words)&&(t.errorMatchedWords=h.matched_words),a=!0):h.type==="state"?(n.onState?.(h.delta,h.full??null),Array.isArray(h.createdNames)&&h.createdNames.length&&n.onCreatedCharacters?.(h.createdNames)):h.type==="start"?typeof h.base_content=="string"&&n.onBase?.(h.base_content):h.type==="thinking"?(h.status==="start"||h.status==="end")&&n.onThinking?.(h.status):h.content&&n.onChunk(h.content)}catch{}i!==void 0&&(t.lastId=i,i=void 0)};try{for(;;){let{done:g,value:p}=await e.read();if(g)break;c(),l+=r.decode(p,{stream:!0});let m=l.split(`
122
+ `);l=m.pop()??"";for(let h of m)d(h);if(a)return s&&clearTimeout(s),"done"}if(l+=r.decode(),l&&d(l),a)return s&&clearTimeout(s),"done"}catch{}finally{s&&clearTimeout(s)}return"eof"}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let r=n&&typeof n=="object"?n:{},i={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.error_code??r.code,c=s==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":s==="TTS_RATE_LIMITED"?"RATE_LIMITED":s||i[e.status]||"INTERNAL_ERROR",l=Array.isArray(r.matched_words)?r.matched_words:void 0,a=new u(c,r.message||`HTTP ${e.status}`,l);throw R(c,r.message,l),a}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.INITIAL_TIMEOUT=3e4,T.RESUME_STALL_TIMEOUT=6e4,T.RECONNECT_MAX_ATTEMPTS=10,T.RECONNECT_BACKOFF_CAP=15e3;var ie=T;var Ee=o=>o.trim().toLowerCase();function se(o){let e=re(),t=o.name_i18n??{};return t[e]||t[e.replace("-","_")]||o.name}function qe(o,e){let t=Ee(e);return o.find(n=>Ee(n.name)===t)??o.find(n=>Object.values(n.name_i18n??{}).some(r=>typeof r=="string"&&Ee(r)===t))}var Xe="storvia_chat_main";function kt(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let o=new Uint8Array(16);crypto.getRandomValues(o),o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=Array.from(o,t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}var ze=20,Qe=40,V=class{constructor(e,t,n,r,i=!1,s,c,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewHistory=[];this.previewConfig=s,this.getModelName=c,this.getPreset=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.(),client_message_uuid:kt()};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{game_id:this.getGameId(),conversation_id:this.getConversationId(),role:e.role,content:e.content,topic:e.topic})}async generate(e){if(this.isPreview)return this.sendPreview({message:"",topic:e.topic,sceneKey:e.sceneKey,stream:e.stream,onChunk:e.onChunk,onDone:e.onDone,onState:e.onState,onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters});let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/generate",t,this.reqMeta())}async once(e){if(this.isPreview)return this.oncePreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,stream:e.stream===!0,preset:this.getPreset?.()};if(!e.stream)return this.http.post("/once",t,this.reqMeta());let n="";return await this.http.stream("/once",t,r=>{n+=r,e.onChunk?.(r)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:n}}async oncePreview(e){let t={model_id:this.getModelId(),message:e.message,scene_key:e.sceneKey,history_messages:[],preset:this.getPreset?.()};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language);let r="";return await this.http.stream("/preview",t,i=>{r+=i,e.onChunk?.(i)},()=>{},this.reqMeta(),void 0,e.onThinking),{content:r}}async retry(e={}){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.retry() is not available in preview mode. Publish the game and test on the Storvia platform.");let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1,preset:this.getPreset?.()};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted);return}return this.http.post("/retry",t,this.reqMeta())}async continue(e={}){if(this.isPreview)return;let t={conversation_id:this.getConversationId(),topic:e.topic??null,game_id:this.getGameId(),preset:this.getPreset?.(),scene_key:e.sceneKey,extract:e.extract};await this.http.stream("/continue",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting,e.onAborted,e.onBase)}async cancel(e={}){if(this.isPreview)return{active:!1};let t=await this.http.post(`/conversations/${encodeURIComponent(this.getConversationId())}/cancel`,{topic:e.topic});return{active:t.active===!0,generationId:t.generation_id}}async messages(e){if(this.isPreview)return{data:[],hasMore:!1,nextCursor:null};let t={conversation_id:this.getConversationId(),order:e.order,limit:String(e.limit??20)};e.topic&&(t.topic=e.topic),e.cursor&&(t.cursor_uuid=e.cursor.uuid,t.cursor_created_at=e.cursor.createdAt);let n=await this.http.get("/messages",t);return{data:n.messages.map(r=>({uuid:r.uuid,role:r.role,content:r.content,topic:r.topic,status:r.status,model:r.model,createdAt:r.created_at,truncated:r.truncated===!0})),hasMore:n.has_more,nextCursor:n.next_cursor?{uuid:n.next_cursor.cursor_uuid,createdAt:n.next_cursor.cursor_created_at}:null}}async edit(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.edit() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.patch(`/messages/${encodeURIComponent(e.uuid)}`,{content:e.content});return{uuid:t.uuid,role:t.role,content:t.content,updatedAt:t.updated_at}}async delete(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.delete() is not available in preview mode. Publish the game and test on the Storvia platform.");return{uuid:(await this.http.delete(`/messages/${encodeURIComponent(e.uuid)}`)).uuid}}async rollback(e){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.chat.rollback() is not available in preview mode. Publish the game and test on the Storvia platform.");let t=await this.http.post(`/messages/${encodeURIComponent(e.uuid)}/rollback`,{});return{deletedCount:t.deleted_count,deletedUuids:t.deleted_uuids,restoredGameState:t.restored_game_state}}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:F(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting,onAborted:e.onAborted})}async sendPreview(e){let t=e.message.trim().length>0,n=e.topic||null,r=this.previewHistory.filter(p=>n===null||p.topic===n).slice(t?-(ze-1):-ze).map(({role:p,content:m})=>({role:p,content:m}));t&&this.pushPreviewHistory({role:"user",content:e.message},n);let i={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:r,preset:this.getPreset?.()};this.previewConfig?i.prompt_config=this.previewConfig:i.game_id=this.getGameId();let s=this.previewConfig;if(s?.reply_length&&(i.reply_length=s.reply_length),s?.reply_language&&(i.reply_language=s.reply_language),e.stream){let p="";await this.http.stream("/preview",i,m=>{p+=m,e.onChunk?.(m)},(m,h)=>{p&&this.pushPreviewHistory({role:"assistant",content:p},n),e.onDone?.(m,h)},this.reqMeta(),F(e.onState),e.onThinking,e.onCreatedCharacters);return}let c="",l=null,a=null,d=[];await this.http.stream("/preview",i,p=>{c+=p},()=>{},this.reqMeta(),(p,m)=>{l=p,a=m,e.onState&&e.onState(l,a)},void 0,p=>{d=p,e.onCreatedCharacters&&e.onCreatedCharacters(p)}),c&&this.pushPreviewHistory({role:"assistant",content:c},n);let g={id:"",content:c,truncated:!1};return l&&(g.delta=l,a&&(g.full=a)),d.length&&(g.createdNames=d),g}pushPreviewHistory(e,t){this.previewHistory.push({...e,topic:t}),this.previewHistory.length>Qe&&this.previewHistory.splice(0,this.previewHistory.length-Qe)}};function F(o){if(o)return(e,t)=>o(e,t)}var we=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let r=this.mem[e]||{};return t?{...r[t]||{}}:{...r}}let n=t?{group:t}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,n)}async update(e,t,n){if(this.isPreview){let r=this.mem[e]||(this.mem[e]={});r[t]={...r[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}async remove(e,t,n){if(n.length){if(this.isPreview){let r=this.mem[e]?.[t];if(r)for(let i of n)delete r[i];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeKeys:n})}}async removeGroup(e,t){if(this.isPreview){let n=this.mem[e];n&&delete n[t];return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,removeGroup:!0})}},H=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(Ze)),this.state=new we(e,t,n,i)}previewNames(){return this.mem.map(e=>e.name)}setInitial(e,t){this.mem=e?e.map(Ze):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Je):(await this.http.get(`/conversations/${this.getConversationId()}/characters`)).map(Te)}async get(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return n?Je(n):{name:e,hasVoice:!1}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`);return Te(t)}async add(e){if(this.isPreview){this.mem.push({...e,isPreset:!1});return}await this.http.post(`/conversations/${this.getConversationId()}/characters`,e)}async update(e,t){if(this.isPreview){let n=this.mem.find(r=>r.name===e);n&&Object.assign(n,t);return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`,t)}async remove(e){if(this.isPreview){this.mem=this.mem.filter(t=>t.name!==e);return}await this.http.delete(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}async merge(e,t){if(this.isPreview){if(this.mem.find(r=>r.name===e)?.isPreset)throw new u("INVALID_REQUEST","\u9884\u8BBE\u89D2\u8272\u4E0D\u53EF\u88AB\u5408\u5E76");if(e===t||!this.mem.some(r=>r.name===t))throw new u("INVALID_REQUEST","\u76EE\u6807\u89D2\u8272\u4E0D\u5B58\u5728\u6216\u4E0E\u6765\u6E90\u76F8\u540C");this.mem=this.mem.filter(r=>r.name!==e);return}await this.http.post(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/merge`,{target:t})}async detail(e){if(this.isPreview){let n=this.mem.find(r=>r.name===e);return{name:e,avatar:n?.avatar,description:n?.description,hasVoice:n?.hasVoice===!0,...n?.introduction!==void 0?{introduction:n.introduction}:{},...n?.visibleAtStart!==void 0?{visibleAtStart:n.visibleAtStart}:{},userDescription:n?.userDescription,...n?.gender?{gender:n.gender}:{},...n?.isPreset!==void 0?{isPreset:n.isPreset}:{},state:await this.state.get(e)}}let t=await this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`);return Te(t)}async setPriority(e,t){let n=Math.max(0,Math.min(100,Math.round(t)));this.isPreview||await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{priority:n})}};function Ze(o){return{name:o.name,description:o.description,avatar:o.avatar,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Je(o){return{name:o.name,avatar:o.avatar,description:o.description,...o.introduction!==void 0?{introduction:o.introduction}:{},...o.visibleAtStart!==void 0?{visibleAtStart:o.visibleAtStart}:{},hasVoice:o.hasVoice===!0,...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function Te(o){let{voice:e,...t}=o;return{...t,hasVoice:!!e}}var et="\u73A9\u5BB6",Mt=["Player","player","PLAYER","\u30D7\u30EC\u30A4\u30E4\u30FC","\uD50C\uB808\uC774\uC5B4","\u4E3B\u63A7","{{user}}","user"],ye=o=>o.toLowerCase().replace(/[\s_\-]+/g,""),xt=new Set(["\u73A9\u5BB6",...Mt].map(ye));function tt(o,e){if(o==="\u73A9\u5BB6")return o;let t=ye(o);return xt.has(t)?e.some(n=>ye(n)===t)?o:"\u73A9\u5BB6":o}var W=class{constructor(e,t,n=!1,r,i=()=>[]){this.http=e;this.getConversationId=t;this.isPreview=n;this.getCharacterNames=i;this.mem=[];r&&(this.mem=r.map(s=>({...s})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}entity(e){return this.isPreview?tt(e,this.getCharacterNames()):e}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t);let n=this.mem.find(r=>r.from===e&&r.to===t);if(n)return{...n};throw new Error("Relationship not found")}return this.http.get(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}async add(e){if(this.isPreview){this.mem.push({...e,from:this.entity(e.from),to:this.entity(e.to)});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){e=this.entity(e),t=this.entity(t);let r=this.mem.find(i=>i.from===e&&i.to===t);r?Object.assign(r,n):this.mem.push({from:e,to:t,...n});return}await this.http.patch(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,n)}async remove(e,t){if(this.isPreview){e=this.entity(e),t=this.entity(t),this.mem=this.mem.filter(n=>!(n.from===e&&n.to===t));return}await this.http.delete(`/conversations/${this.getConversationId()}/relationships/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)}};function nt(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function Ce(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let r={};for(let[i,s]of Object.entries(n))r[i]=nt(s);e[t]=r}return e}function Ut(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=nt(n);return e}var B=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=Ce(r))}setInitial(e){this.mem=e?Ce(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[r,i]of Object.entries(this.mem))n[r]={...i};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return Ut(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return Ce(t)}async add(e){let{group:t,name:n,count:r=1,desc:i,iconUrl:s}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:r};i!==void 0&&(l.desc=i),s!==void 0&&(l.iconUrl=s),this.mem[t][n]=l;return}let c={group:t,name:n,count:r};i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,c)}async update(e){let{group:t,name:n,count:r,desc:i,iconUrl:s}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];r!==void 0&&(a.count=r),i!==void 0&&(a.desc=i),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),i!==void 0&&(c.desc=i),s!==void 0&&(c.icon_url=s),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,c)}async remove(e){let{group:t,name:n}=e;if(this.isPreview){this.mem[t]&&delete this.mem[t][n];return}await this.http.delete(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`)}async removeBatch(e){if(this.isPreview){for(let{group:t,name:n}of e)this.mem[t]&&delete this.mem[t][n];return}e.length!==0&&await this.http.post(`/conversations/${this.getConversationId()}/inventory/batch-delete`,{items:e})}async move(e){let{fromGroup:t,toGroup:n,name:r,newName:i}=e;if(this.isPreview){let s=this.mem[t];if(!s||!(r in s))throw new Error(`Source item "${t}/${r}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let c=i||r;if(t===n&&c===r)return;if(c in this.mem[n])throw new Error(`Item "${c}" already exists in target group`);this.mem[n][c]=s[r],delete s[r];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:r,newName:i})}async ensureGroup(e){if(this.isPreview){this.mem[e]||(this.mem[e]={});return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}`,{})}async removeGroup(e,t){let n=t?.cascade??!1;if(this.isPreview){let i=this.mem[e];if(i&&Object.keys(i).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let r=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${r}`)}};var j=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:this.http.get(`/conversations/${this.getConversationId()}/world`)}async update(e){if(this.isPreview){Object.assign(this.mem,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/world`,e)}};var _e=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem={...r})}setInitial(e){this.mem=e?{...e}:{}}async get(e){if(this.isPreview)return e?{...this.mem[e]||{}}:{...this.mem};let t=e?{group:e}:void 0;return this.http.get(`/conversations/${this.getConversationId()}/player/state`,t)}async update(e,t){if(this.isPreview){this.mem[e]={...this.mem[e]||{},...t};return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,values:t})}async remove(e,t){if(t.length){if(this.isPreview){let n=this.mem[e];if(n)for(let r of t)delete n[r];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeKeys:t})}}async removeGroup(e){if(this.isPreview){delete this.mem[e];return}await this.http.patch(`/conversations/${this.getConversationId()}/player/state`,{group:e,removeGroup:!0})}},K=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new _e(e,t,n,i)}setInitial(e,t){this.memPersona=e?{...e}:{name:""},this.state.setInitial(t)}async get(){return this.isPreview?{...this.memPersona}:this.http.get(`/conversations/${this.getConversationId()}/player`)}async update(e){if(this.isPreview){Object.assign(this.memPersona,e);return}await this.http.patch(`/conversations/${this.getConversationId()}/player`,e)}};function Y(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var q=class{constructor(e,t,n,r=!1,i,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};i&&(this.mem=rt(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?rt(e):{},this.memInject=t?{...t}:{}}async get(e){if(this.isPreview)return e!==void 0?this.mem[e]:{...this.mem};let t=await this.http.get(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,i]of Object.entries(e))typeof i=="object"&&i!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...i}:this.mem[r]=i,t?.inject!==void 0&&(this.memInject[r]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,this.getGameId()),{inject:t})}getInject(){return{...this.memInject}}async delete(e){if(this.isPreview){delete this.mem[e],delete this.memInject[e];return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}`,this.getGameId()))}async setGroupField(e,t,n){if(this.isPreview){(!this.mem[e]||typeof this.mem[e]!="object")&&(this.mem[e]={}),this.mem[e][t]=n;return}await this.http.patch(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()),{value:n})}async deleteGroupField(e,t){if(this.isPreview){if(typeof this.mem[e]=="object"&&this.mem[e]!==null){let n=this.mem[e];delete n[t]}return}await this.http.delete(Y(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function rt(o){let e={};for(let[t,n]of Object.entries(o))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function ot(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var z=class{constructor(e,t,n,r=!1,i){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(ot(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var Q=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n}async get(){if(this.isPreview)throw new u("NOT_SUPPORTED_IN_PREVIEW","storvia.state.get() is not available in preview mode. Publish the game and test on the Storvia platform. (Use per-module get() like storvia.world.get() if you need to inspect state during preview.)");return this.http.get(`/conversations/${this.getConversationId()}/state`)}};var X=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null;this.wb=null;this.worldbook={get:async()=>this.isPreview?this.wb?it(this.wb):null:(await this.http.get(`/conversations/${this.getConversationId()}/worldbook`)).worldbook,update:async e=>{let t=typeof e=="string"?{content:e}:{...e};if(t.content!==void 0&&(t.content=(t.content??"").trim()),t.entries!==void 0&&(t.entries=Lt(t.entries)),this.isPreview){let r=this.wb?.presets??[],i=t.enabledPresets?r.map(c=>({...c,enabled:t.enabledPresets.includes(c.id)})):r,s={content:t.content??this.wb?.content??"",contentWidget:t.contentWidget??this.wb?.contentWidget??!1,entries:t.entries??this.wb?.entries??[],presets:i,updated_at:new Date().toISOString()};return this.wb=s,it(s)}return(await this.http.patch(`/conversations/${this.getConversationId()}/worldbook`,t)).worldbook}}}async get(){return this.isPreview?this.mem?{...this.mem}:null:(await this.http.get(`/conversations/${this.getConversationId()}/summary`)).ai_summary}async update(e){let t=(e??"").trim();if(this.isPreview){let r={content:t,updated_at:new Date().toISOString()};return this.mem=r,{...r}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};function it(o){return{...o,entries:o.entries.map(e=>({...e,keys:[...e.keys]})),presets:(o.presets??[]).map(e=>({...e}))}}function Lt(o){return(o??[]).flatMap(e=>{let t=(e?.content??"").trim(),n=[...new Set((e?.keys??[]).map(s=>(s??"").trim()).filter(s=>s!==""))],r=e?.constant===!0;if(!t||!r&&n.length===0)return[];let i=(e?.title??"").trim();return[{id:e.id||$t(),keys:n,content:t,...i?{title:i}:{},constant:r,enabled:e?.enabled!==!1,widget:e?.widget===!0}]})}function $t(){let o=globalThis.crypto;return o?.randomUUID?o.randomUUID():`ewr-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var Re=60,Se=1e3,pe=1e4,N=class{constructor(e,t=!1,n=()=>Date.now()){this.send=e;this.isPreview=t;this.now=n;this.lastNotifyAt=0;this.lastRefreshAt=0;this.lastRefreshMessagesAt=0}notify(e){let t=Gt(e);if(!t)return!1;let n=this.now();return n-this.lastNotifyAt<Se?!1:(this.lastNotifyAt=n,this.isPreview?(oe(t,"info"),!0):(this.send(y("host-notify",{text:t})),!0))}refreshPanel(e){if(this.isPreview)return!1;let t=this.now();return t-this.lastRefreshAt<pe?!1:(this.lastRefreshAt=t,this.send(y("host-state-changed",e?.length?{scope:e}:{})),!0)}refreshMessages(){if(this.isPreview)return!1;let e=this.now();return e-this.lastRefreshMessagesAt<pe?!1:(this.lastRefreshMessagesAt=e,this.send(y("host-messages-changed",{})),!0)}};function Gt(o){return typeof o!="string"?"":o.replace(/\s+/g," ").trim().slice(0,Re)}var Ft;function st(){return Ft??(Ft=new Promise((o,e)=>{let t=indexedDB.open("storvia-sdk-speech",1);t.onupgradeneeded=()=>t.result.createObjectStore("audio"),t.onsuccess=()=>o(t.result),t.onerror=()=>e(t.error)}))}async function at(o){let e=await st();return new Promise((t,n)=>{let r=e.transaction("audio").objectStore("audio").get(o);r.onsuccess=()=>t(r.result??null),r.onerror=()=>n(r.error)})}async function ct(o,e){let t=await st();return new Promise((n,r)=>{let i=t.transaction("audio","readwrite");i.objectStore("audio").put(e,o),i.oncomplete=()=>n(),i.onabort=()=>r(i.error)})}function dt(o){let e=o,t;do t=e,e=e.replace(/[((][^()()]*[))]/g,"");while(e!==t);return e.replace(/\s+/g," ").trim()}var Z=class{constructor(e,t,n,r,i=!1){this.getHttp=e;this.getConversationId=t;this.getGameId=n;this.getVoice=r;this.isPreview=i;this.pending=new Map}async speak(e){let t=dt(e.text),n=await this.getVoice(e.character);if(!n)throw new u("TTS_UNKNOWN_VOICE","Character has no voice configured");let r=this.isPreview?this.getGameId():this.getConversationId(),i=JSON.stringify([r,n,t]),s={text:t,...this.isPreview?{voice:n}:{conversation_id:this.getConversationId(),character_name:e.character}},c=globalThis;if(c.__storviaNativeTts&&c.flutter_inappwebview){let d=await c.flutter_inappwebview.callHandler("storviaTts",{body:s,key:i});if(d.error){let p=d.error==="TTS_INSUFFICIENT_CREDITS"?"INSUFFICIENT_CREDITS":d.error==="TTS_RATE_LIMITED"?"RATE_LIMITED":d.error;throw R(p),new u(p,d.error)}let g=Uint8Array.from(atob(d.audio),p=>p.charCodeAt(0));return{audio:new Blob([g],{type:"audio/mpeg"}),cached:d.cached}}let l=await at(i);if(l)return{audio:l,cached:!0};let a=this.pending.get(i);return a||(a=this.getHttp().postAudio("/speak",s).then(async d=>{try{await ct(i,d)}catch{console.warn("[Storvia TTS] \u97F3\u9891\u7F13\u5B58\u4FDD\u5B58\u5931\u8D25")}return{audio:d,cached:!1}}),this.pending.set(i,a),a.then(()=>this.pending.delete(i),()=>this.pending.delete(i))),a}};var J=class{constructor(e){this.getHttp=e}async transcribe(e){if(!e||typeof e!="object")throw new u("INVALID_REQUEST","Recognition options are required");if(!(e.audio instanceof Blob)||e.audio.size===0||e.audio.size>10485760)throw new u("ASR_BAD_AUDIO","Audio must be a non-empty file of at most 10 MB");let t=e.audio.type.split(";")[0].trim().toLowerCase(),n=e.format??qt[t];if(!n||!Kt.includes(n))throw new u("ASR_BAD_AUDIO","Specify a supported audio format");if(e.context!==void 0&&typeof e.context!="string"||!lt(e.languageHints,4)||!lt(e.hotwords,50)||(e.context?.length??0)>400||e.hotwords?.some(i=>i.length>64))throw new u("INVALID_REQUEST","Recognition context, language hints, or hotwords exceed the limits");let r=new FormData;return r.append("file",e.audio,`audio.${n}`),r.append("format",n),e.context!==void 0&&r.append("context",e.context),e.languageHints!==void 0&&r.append("language_hints",JSON.stringify(e.languageHints)),e.hotwords!==void 0&&r.append("hotwords",JSON.stringify(e.hotwords)),this.getHttp().postForm("/transcribe",r,Yt)}},Kt=["wav","mp3","m4a","webm","ogg","opus","flac","aac"],Yt=15e4;function lt(o,e){return o===void 0||Array.isArray(o)&&o.length<=e&&o.every(t=>typeof t=="string"&&t.trim().length>0)}var qt={"audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav","audio/mpeg":"mp3","audio/mp3":"mp3","audio/mp4":"m4a","audio/x-m4a":"m4a","audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/opus":"opus","audio/flac":"flac","audio/x-flac":"flac","audio/aac":"aac"};var ht="/functions/v1/world-engine/v1",zt="https://api.storvia.ai";function Qt(){return window.__STORVIA__||{}}function Xt(o,e=3e4){let t=Qt();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let i=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,lang:a.payload.lang,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(i),s(),c();let d=window;d.__STORVIA__=a,n(a)}o.send(y("ready",{}))})}var ae=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.presetId="";this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0;this.previewVoices=new Map}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new x({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?d=>d.source===null||d.source===window:d=>d.source===window.parent,customSend:t?d=>e.callHandler("storviaBus",d):void 0}),Be(d=>this.bus.send(d));let n=await Xt(this.bus),r=n.apiBase;if(!r)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${r}${ht}`,this.isPreview=!!n.preview,this.previewConfig=n.previewConfig,!n.gameId)throw new u("GAME_NOT_FOUND","window.__STORVIA__.gameId is not set. The platform must inject it before SDK init.");if(this.gameId=n.gameId,!n.accessToken)throw new u("UNAUTHORIZED","window.__STORVIA__.accessToken is not set. The platform must inject the user token before SDK init.");if(this.accessToken=n.accessToken,$e(n.lang),this.http=new ie(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000",this.models=n.models??[],this.modelId=n.selectedModelId||this.models[0]?.id||"";let[d,g]=await Promise.all([this.fetchPreviewSnapshot(),this.modelId?Promise.resolve(null):this.fetchModels()]);g&&(this.models=g,this.modelId=g[0]?.id||""),this.presetId=n.presetId||"";let p=()=>this.gameId,m=()=>this.conversationId,h=()=>this.modelId,C=()=>{let v=this.models.find(_=>_.id===this.modelId);return v?se(v):void 0},w=()=>this.presetId||void 0;this.chat=new V(this.http,p,m,h,!0,this.previewConfig,C,w),this.characters=new H(this.http,m,!0,d.characters,d.characterStates),this.tts=new Z(()=>this.http.ttsClient(),m,p,v=>this.getCharacterVoice(v),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,m,!0,d.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,m,!0,d.inventory),this.world=new j(this.http,m,!0,d.world),this.player=new K(this.http,m,!0,d.player,d.playerState),this.custom=new q(this.http,m,p,!0,d.custom,d.custom_inject),this.save=new z(this.http,m,p,!0,d.save_data),this.state=new Q(this.http,m,!0),this.memory=new X(this.http,m,!0),this.host=new N(v=>this.bus.send(v),!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}if(!n.conversationId)throw new u("NOT_INITIALIZED","window.__STORVIA__.conversationId is not set. The platform must inject it before SDK init.");this.conversationId=n.conversationId,this.modelId=n.selectedModelId||"",this.modelId||(this.models=await this.fetchModels(),this.modelId=this.models[0]?.id||""),this.presetId=n.presetId||"";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(g=>g.id===this.modelId);return d?se(d):void 0},a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!1,void 0,l,a),this.characters=new H(this.http,s),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s),this.inventory=new B(this.http,s),this.world=new j(this.http,s),this.player=new K(this.http,s),this.custom=new q(this.http,s,i),this.save=new z(this.http,s,i),this.state=new Q(this.http,s),this.memory=new X(this.http,s),this.host=new N(d=>this.bus.send(d),!1),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""})}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}listenForPreviewMessages(){this.bus.on("set-model",e=>{this.modelId=e.payload.modelId||""}),this.bus.on("set-preset",e=>{this.presetId=e.payload?.presetId||""}),this.bus.on("config-update",e=>{this.previewConfig=e.payload.previewConfig,this.chat&&this.chat.updatePreviewConfig(this.previewConfig),this.refreshPreviewSnapshot().catch(t=>{console.warn("[Storvia SDK] refreshPreviewSnapshot failed:",t)})})}async getCharacterVoice(e){return this.isPreview?this.previewVoices.get(e):(await this.http.get(`/conversations/${this.conversationId}/characters/${encodeURIComponent(e)}`)).voice}async fetchPreviewSnapshot(){let e={game_id:this.gameId};this.previewConfig&&("game_config"in this.previewConfig&&(e.game_config=this.previewConfig.game_config),"game_state"in this.previewConfig&&(e.game_state_override=this.previewConfig.game_state));let t=await this.http.post("/preview/initial-snapshot",e);return this.previewVoices=new Map(t.characters.map(n=>[n.name,n.voice])),{...t,characters:t.characters.map(({voice:n,...r})=>({...r,hasVoice:!!n}))}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();this.characters?.setInitial(e.characters,e.characterStates),this.player?.setInitial(e.player,e.playerState),this.inventory?.setInitial(e.inventory),this.relationships?.setInitial(e.relationships),this.world?.setInitial(e.world),this.custom?.setInitial(e.custom,e.custom_inject),this.save?.setInitial(e.save_data)}async fetchModels(e=!1){try{return await this.http.get("/models",e?void 0:{locale:re()})}catch{}return[]}async initDev(e){if(this.initialized)return;this.baseUrl=`${zt}${ht}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new ie(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(!!e.model),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?qe(t,e.model):void 0;e.model&&!r&&console.warn(`[Storvia SDK] dev.model "${e.model}" not found, falling back to the first model. Available:`,t.map(se)),this.modelId=r?.id||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,l=()=>{let d=this.models.find(g=>g.id===this.modelId);return d?se(d):void 0};this.presetId=e.preset||"";let a=()=>this.presetId||void 0;this.chat=new V(this.http,i,s,c,!0,void 0,l,a),this.characters=new H(this.http,s,!0,n.characters,n.characterStates),this.tts=new Z(()=>this.http.ttsClient(),s,i,d=>this.getCharacterVoice(d),this.isPreview),this.asr=new J(()=>this.http.asrClient()),this.relationships=new W(this.http,s,!0,n.relationships,()=>this.characters.previewNames()),this.inventory=new B(this.http,s,!0,n.inventory),this.world=new j(this.http,s,!0,n.world),this.player=new K(this.http,s,!0,n.player,n.playerState),this.custom=new q(this.http,s,i,!0,n.custom,n.custom_inject),this.save=new z(this.http,s,i,!0,n.save_data),this.state=new Q(this.http,s,!0),this.memory=new X(this.http,s,!0),this.host=new N(()=>{},!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e,locale:re()};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,assetId:i.asset_id,name:i.name,nameI18n:i.meta.name_i18n,url:i.url,assetType:i.asset_type,category:i.category,categoryI18n:i.category_i18n,tags:i.tags.map(s=>({id:s.id,label:s.label,labelI18n:s.label_i18n}))}))}};async function ut(o){Ge();let e=new ae;return o?.dev?await e.initDev(o.dev):await e.init(),e}function Ae(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function pt(o){return Ae(o)?o.value:o}return Et(Zt);})();
123
123
  if(typeof window!=="undefined"){window.createStorviaSDK=StorviaSDK.createStorviaSDK;}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storvia/sdk",
3
- "version": "0.10.9",
3
+ "version": "0.10.10",
4
4
  "description": "Storvia World SDK - Build interactive text games on the Storvia platform",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",