@storvia/sdk 0.8.0 → 0.8.1

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
@@ -236,4 +236,4 @@
236
236
  </div>
237
237
  `;let t=e.querySelector(".storvia-sheet-title");t&&(t.textContent=i.title);let n=e.querySelector(".storvia-sheet-msg");n&&(n.textContent=i.msg);let r=e.querySelector('[data-role="navigate"]');r&&(r.textContent=i.primaryLabel);let o=()=>{e.isConnected&&(e.classList.add("leaving"),e.classList.remove("show"),setTimeout(()=>{e.remove(),J===e&&(J=null)},240))};e.querySelector('[data-role="cancel"]')?.addEventListener("click",o),e.addEventListener("click",s=>{s.target===e&&o()}),r?.addEventListener("click",()=>{if(se)try{se(C("navigate",{target:"wallet"})),console.log("[Storvia] navigate \u2192 wallet\uFF1A\u5DF2\u901A\u8FC7 bus \u901A\u77E5\u5BBF\u4E3B\u8DF3\u8F6C\u94B1\u5305\u9875")}catch(s){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",s)}else console.warn("[Storvia] navigate \u2192 wallet\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u6309\u94AE\u5DF2\u70B9\u4F46\u65E0\u4EBA\u63A5\u6536\u3002\u751F\u4EA7\u73AF\u5883\u4F1A\u81EA\u52A8\u8DF3\u5230\u4E3B\u7AD9 /wallet \u6216 App \u94B1\u5305\u9875\u3002");o()}),document.body.appendChild(e),J=e,requestAnimationFrame(()=>e.classList.add("show"))}var f=class f{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||S("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return S("REQUEST_TIMEOUT"),t}return e}createTimeoutController(){let e=new AbortController,t=setTimeout(()=>e.abort(),f.REQUEST_TIMEOUT);return{controller:e,clear:()=>clearTimeout(t)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:o,rawResponse:s,parsedData:c,error:d,durationMs:a,modelName:h}=e,l="%c[Storvia SDK]",m="color: #6366f1; font-weight: bold",p=a!==void 0?` (${a}ms)`:"",g=o!==void 0?` [${o}]`:"",b=h?` [model: ${h}]`:"";d?(console.groupCollapsed(`${l} %c${t} ${n}${g}${b}${p} %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:",d),console.groupEnd()):(console.groupCollapsed(`${l} %c${t} ${n}${g}${b}${p} %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,h])=>n.searchParams.set(a,h));let r=Date.now(),o,s,{controller:c,clear:d}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});d(),o=a.status;let{raw:h,data:l}=await this.handleResponseWithRaw(a);return s=h,this.log({method:"GET",path:e,body:t,status:o,rawResponse:s,parsedData:l,durationMs:Date.now()-r}),l}catch(a){d();let h=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:o,rawResponse:s,error:h,durationMs:Date.now()-r}),h===a&&this.maybeShowNetworkToast(a),h}}async post(e,t,n){let r=Date.now(),o,s,{controller:c,clear:d}=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});d(),o=a.status;let{raw:h,data:l}=await this.handleResponseWithRaw(a);return s=h,this.log({method:"POST",path:e,body:t,status:o,rawResponse:s,parsedData:l,durationMs:Date.now()-r,modelName:n?.modelName}),l}catch(a){d();let h=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:o,rawResponse:s,error:h,durationMs:Date.now()-r,modelName:n?.modelName}),h===a&&this.maybeShowNetworkToast(a),h}}async patch(e,t){let n=Date.now(),r,o,{controller:s,clear:c}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=d.status;let{raw:a,data:h}=await this.handleResponseWithRaw(d);return o=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:o,parsedData:h,durationMs:Date.now()-n}),h}catch(d){c();let a=this.wrapAbortError(d);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:o,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async put(e,t){let n=Date.now(),r,o,{controller:s,clear:c}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=d.status;let{raw:a,data:h}=await this.handleResponseWithRaw(d);return o=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:o,parsedData:h,durationMs:Date.now()-n}),h}catch(d){c();let a=this.wrapAbortError(d);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:o,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async delete(e){let t=Date.now(),n,r,{controller:o,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:o.signal});s(),n=c.status;let{raw:d,data:a}=await this.handleResponseWithRaw(c);return r=d,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let d=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:d,durationMs:Date.now()-t}),d===c&&this.maybeShowNetworkToast(c),d}}async stream(e,t,n,r,o,s,c,d,a,h){let l=Date.now(),m=o?.modelName?` [model: ${o.modelName}]`:"",p=[],g=w=>{this.debug&&p.push({t:Date.now()-l,event:w})},b=new AbortController,R=null,I=null,P=null,T=null,k=()=>{R!==null&&(clearTimeout(R),R=null),I!==null&&(clearTimeout(I),I=null),P!==null&&(clearTimeout(P),P=null)},z=w=>{T=w,k(),b.abort()};R=setTimeout(()=>z("REQUEST_TIMEOUT"),f.REQUEST_TIMEOUT);let E;try{E=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:b.signal})}catch(w){if(k(),T){let y=new u(T,"Request timed out");throw S(T),this.log({method:"STREAM",path:e,body:t,error:y,durationMs:Date.now()-l,modelName:o?.modelName}),y}throw this.maybeShowNetworkToast(w),w}if(R!==null&&(clearTimeout(R),R=null),!E.ok){k();let w=await E.text().catch(()=>""),y={};try{y=JSON.parse(w)}catch{}let ne=y.code||"INTERNAL_ERROR",Q=new u(ne,y.message||`HTTP ${E.status}`);throw S(ne,y.message),this.log({method:"STREAM",path:e,body:t,status:E.status,rawResponse:w,error:Q,durationMs:Date.now()-l,modelName:o?.modelName}),Q}let pe=E.body?.getReader();if(!pe)throw k(),new u("INTERNAL_ERROR","No response body for stream");I=setTimeout(()=>z("MODEL_LOADING_TIMEOUT"),f.MODEL_LOADING_TIMEOUT);let Pe=new TextDecoder,j="",x="",ue=!1,te,Y;try{for(;;){let{done:w,value:y}=await pe.read();if(w)break;let Q=Pe.decode(y,{stream:!0}).split(`
238
238
  `);for(let Z of Q){if(Z.startsWith("id: ")){Y=Z.slice(4);continue}if(!Z.startsWith("data: "))continue;let re=Z.slice(6);if(re==="[DONE]"){g("[DONE]"),k(),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${E.status}]${m} (${Date.now()-l}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log("Message ID:",j),console.log(`SSE events (${p.length}):`,p),console.groupEnd()),r(j);return}try{let v=JSON.parse(re);g(v),v.type==="done"&&v.id?j=v.id:v.type==="state"?(s&&s(v.delta,v.full??null),d&&Array.isArray(v.createdNames)&&v.createdNames.length&&d(v.createdNames)):v.type==="thinking"?c&&(v.status==="start"||v.status==="end")&&c(v.status):v.content&&(ue?(P!==null&&clearTimeout(P),P=setTimeout(()=>z("STREAM_INACTIVITY"),f.STREAM_INACTIVITY_TIMEOUT)):(ue=!0,I!==null&&(clearTimeout(I),I=null),P=setTimeout(()=>z("STREAM_INACTIVITY"),f.STREAM_INACTIVITY_TIMEOUT)),x+=v.content,n(v.content))}catch{g({raw:re})}Y!==void 0&&(te=Y,Y=void 0)}}}catch(w){if(k(),T){let y=new u(T,T==="MODEL_LOADING_TIMEOUT"?"Model loading timed out":"Stream inactivity timed out");throw S(T),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${E.status}]${m} (${Date.now()-l}ms) %c\u2717 ${T}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log(`SSE events (${p.length}):`,p),console.error("Timeout:",y),console.groupEnd()),y}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${E.status}]${m} (${Date.now()-l}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log(`SSE events (${p.length}):`,p),console.error("Stream error:",w),console.groupEnd()),a){await this.resumeLoop(a,te,{onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:d,onReconnect:h});return}throw w}if(k(),j){r(j);return}a&&await this.resumeLoop(a,te,{onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:d,onReconnect:h})}async resumeLoop(e,t,n){let r=t;for(let s=1;s<=f.RECONNECT_MAX_ATTEMPTS;s++){let c=Math.min(f.RECONNECT_BACKOFF_CAP,1e3*2**(s-1));await new Promise(h=>setTimeout(h,c)),n.onReconnect?.({attempt:s});let d={messageId:"",lastId:r},a;try{a=await this.pumpGetStream(e.conversationId,e.topic,r,d,n)}catch{continue}if(r=d.lastId??r,a==="done"){n.onDone(d.messageId);return}if(a==="inactive"){d.messageId&&n.onDone(d.messageId);return}}let o=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw S("STREAM_INTERRUPTED"),o}async resumeStream(e,t,n){let r={messageId:""},o;try{o=await this.pumpGetStream(e,t,void 0,r,n)}catch{await this.resumeLoop({conversationId:e,topic:t},r.lastId,n);return}if(o==="done"){n.onDone(r.messageId);return}if(o==="inactive"){r.messageId&&n.onDone(r.messageId);return}await this.resumeLoop({conversationId:e,topic:t},r.lastId,n)}async pumpGetStream(e,t,n,r,o){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,d=setTimeout(()=>c.abort(),f.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(d)}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 l=a.body?.getReader();return l?await this.pumpReader(l,r,o):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,o,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},f.STREAM_INACTIVITY_TIMEOUT)};c();try{for(;;){let{done:d,value:a}=await e.read();if(d)break;c();let h=r.decode(a,{stream:!0});for(let l of h.split(`
239
- `)){if(l.startsWith("id: ")){o=l.slice(4);continue}if(!l.startsWith("data: "))continue;let m=l.slice(6);if(m==="[DONE]")return s&&clearTimeout(s),"done";try{let p=JSON.parse(m);p.type==="done"&&p.id?t.messageId=p.id:p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}o!==void 0&&(t.lastId=o,o=void 0)}}}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:{},o={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.code||o[e.status]||"INTERNAL_ERROR",c=new u(s,r.message||`HTTP ${e.status}`);throw S(s,r.message),c}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};f.REQUEST_TIMEOUT=6e4,f.MODEL_LOADING_TIMEOUT=18e4,f.STREAM_INACTIVITY_TIMEOUT=6e4,f.RECONNECT_MAX_ATTEMPTS=10,f.RECONNECT_BACKOFF_CAP=15e3;var H=f;var A=class{constructor(e,t,n,r,o=!1,s,c){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=o;this.previewConfig=s,this.getModelName=c}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};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/generate",t,this.reqMeta())}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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/retry",t,this.reqMeta())}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})),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 active(e={}){if(this.isPreview)return{active:!1};let t={};return e.topic&&(t.topic=e.topic),this.http.get(`/conversations/${encodeURIComponent(this.getConversationId())}/active`,t)}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:W(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting})}async sendPreview(e){let t={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:[]};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;if(n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters);return}let r="",o=null,s=null,c=[];await this.http.stream("/preview",t,a=>{r+=a},()=>{},this.reqMeta(),(a,h)=>{o=a,s=h,e.onState&&e.onState(o,s)},void 0,a=>{c=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:r};return o&&(d.delta=o,s&&(d.full=s)),c.length&&(d.createdNames=c),d}};function W(i){if(i)return(e,t)=>i(e,t)}var de=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})}},M=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(ye)),this.state=new de(e,t,n,o)}setInitial(e,t){this.mem=e?e.map(ye):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Ie):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?Ie(t):{name:e}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}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 detail(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return{name:e,avatar:t?.avatar,description:t?.description,...t?.introduction!==void 0?{introduction:t.introduction}:{},...t?.visibleAtStart!==void 0?{visibleAtStart:t.visibleAtStart}:{},userDescription:t?.userDescription,...t?.gender?{gender:t.gender}:{},...t?.isPreset!==void 0?{isPreset:t.isPreset}:{},state:await this.state.get(e)}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`)}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 ye(i){return{name:i.name,description:i.description,avatar:i.avatar,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.gender?{gender:i.gender}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}function Ie(i){return{name:i.name,avatar:i.avatar,description:i.description,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.gender?{gender:i.gender}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}var D=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(o=>({...o})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){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});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){let r=this.mem.find(o=>o.from===e&&o.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){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 Ce(i){let e={count:i.count};return i.desc!==void 0&&(e.desc=i.desc),i.icon_url!==void 0&&(e.iconUrl=i.icon_url),e}function ce(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i)){let r={};for(let[o,s]of Object.entries(n))r[o]=Ce(s);e[t]=r}return e}function $e(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i))e[t]=Ce(n);return e}var N=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,o]of Object.entries(this.mem))n[r]={...o};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return $e(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:o,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 d={count:r};o!==void 0&&(d.desc=o),s!==void 0&&(d.iconUrl=s),this.mem[t][n]=d;return}let c={group:t,name:n,count:r};o!==void 0&&(c.desc=o),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:o,iconUrl:s}=e;if(this.isPreview){let d=this.mem[t];if(!d||!(n in d))throw new Error(`Item "${t}/${n}" not found`);let a=d[n];r!==void 0&&(a.count=r),o!==void 0&&(a.desc=o),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),o!==void 0&&(c.desc=o),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 move(e){let{fromGroup:t,toGroup:n,name:r,newName:o}=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=o||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:o})}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 o=this.mem[e];if(o&&Object.keys(o).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 U=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 le=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})}},$=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new le(e,t,n,o)}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 L(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var F=class{constructor(e,t,n,r=!1,o,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};o&&(this.mem=Re(o)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Re(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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,o]of Object.entries(e))typeof o=="object"&&o!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...o}:this.mem[r]=o,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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(L(`/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(L(`/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(L(`/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(L(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Re(i){let e={};for(let[t,n]of Object.entries(i))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function Te(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var G=class{constructor(e,t,n,r=!1,o){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};o&&(this.mem={...o})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var K=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 V=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null}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}};var Ee="/functions/v1/world-engine/v1",Le="https://api.storvia.ai";function Fe(){return window.__STORVIA__||{}}function Ge(i,e=3e4){let t=Fe();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let o=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=i.on("init",a=>{a.payload?.apiBase&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,debug:a.payload.debug})}),c=i.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(o),s(),c();let h=window;h.__STORVIA__=a,n(a)}i.send(C("ready",{}))})}var q=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new _({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?l=>l.source===null||l.source===window:l=>l.source===window.parent,customSend:t?l=>e.callHandler("storviaBus",l):void 0}),ge(l=>this.bus.send(l));let n=await Ge(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}${Ee}`,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,this.http=new H(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[l,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=l,this.modelId=(n.selectedModelId&&l.some(I=>I.id===n.selectedModelId)?n.selectedModelId:"")||l[0]?.id||"";let p=()=>this.gameId,g=()=>this.conversationId,b=()=>this.modelId,R=()=>this.models.find(I=>I.id===this.modelId)?.name;this.chat=new A(this.http,p,g,b,!0,this.previewConfig,R),this.characters=new M(this.http,g,!0,m?.characters,m?.characterStates),this.relationships=new D(this.http,g,!0,m?.relationships),this.inventory=new N(this.http,g,!0,m?.inventory),this.world=new U(this.http,g,!0,m?.world),this.player=new $(this.http,g,!0,m?.player,m?.playerState),this.custom=new F(this.http,g,p,!0,m?.custom,m?.custom_inject),this.save=new G(this.http,g,p,!0,m?.save_data),this.state=new K(this.http,g,!0),this.memory=new V(this.http,g,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[o,s]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=o.conversationId,this.models=s,this.modelId=(n.selectedModelId&&s.some(l=>l.id===n.selectedModelId)?n.selectedModelId:"")||s[0]?.id||"";let c=()=>this.gameId,d=()=>this.conversationId,a=()=>this.modelId,h=()=>this.models.find(l=>l.id===this.modelId)?.name;this.chat=new A(this.http,c,d,a,!1,void 0,h),this.characters=new M(this.http,d),this.relationships=new D(this.http,d),this.inventory=new N(this.http,d),this.world=new U(this.http,d),this.player=new $(this.http,d),this.custom=new F(this.http,d,c),this.save=new G(this.http,d,c),this.state=new K(this.http,d),this.memory=new V(this.http,d),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)})}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("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 fetchPreviewSnapshot(){try{let e={game_id:this.gameId};return 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)),await this.http.post("/preview/initial-snapshot",e)}catch(e){return console.warn("[Storvia SDK] fetchPreviewSnapshot failed:",e),null}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();e&&(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(){try{return await this.http.get("/models")}catch{}return[]}async authenticate(){let e={game_id:this.gameId};this.conversationId&&(e.conversation_id=this.conversationId);let t=await fetch(`${this.baseUrl}/auth`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`},body:JSON.stringify(e)});if(!t.ok)throw t.status===401?new u("UNAUTHORIZED","User not authenticated"):t.status===404?new u("GAME_NOT_FOUND","Game not found or not published"):new u("INTERNAL_ERROR",`Auth failed: HTTP ${t.status}`);let n=await t.json();return n.data??n}async initDev(e){if(this.initialized)return;this.baseUrl=`${Le}${Ee}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new H(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?t.find(a=>a.name===e.model)?.id??"":"";this.modelId=r||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let o=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new A(this.http,o,s,c,!0,void 0,d),this.characters=new M(this.http,s,!0,n?.characters,n?.characterStates),this.relationships=new D(this.http,s,!0,n?.relationships),this.inventory=new N(this.http,s,!0,n?.inventory),this.world=new U(this.http,s,!0,n?.world),this.player=new $(this.http,s,!0,n?.player,n?.playerState),this.custom=new F(this.http,s,o,!0,n?.custom),this.save=new G(this.http,s,o,!0,n?.save_data),this.memory=new V(this.http,s,!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e};return t&&(n.category=t),(await this.http.get("/assets",n)).map(o=>({id:o.id,name:o.name,url:o.url,assetType:o.asset_type,category:o.category}))}};async function Se(i){let e=new q;return i?.dev?await e.initDev(i.dev):await e.init(),e}function he(i){return typeof i=="object"&&i!==null&&"value"in i&&"type"in i&&(i.type==="number"||i.type==="text")}function be(i){return he(i)?i.value:i}0&&(module.exports={PROTOCOL_VERSION,StorviaBus,StorviaError,StorviaSDK,createStorviaSDK,envelope,extractFieldValue,isProtocolEnvelope,isRichFieldValue,setToastEnabled,showToast});
239
+ `)){if(l.startsWith("id: ")){o=l.slice(4);continue}if(!l.startsWith("data: "))continue;let m=l.slice(6);if(m==="[DONE]")return s&&clearTimeout(s),"done";try{let p=JSON.parse(m);p.type==="done"&&p.id?t.messageId=p.id:p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}o!==void 0&&(t.lastId=o,o=void 0)}}}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:{},o={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.code||o[e.status]||"INTERNAL_ERROR",c=new u(s,r.message||`HTTP ${e.status}`);throw S(s,r.message),c}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};f.REQUEST_TIMEOUT=6e4,f.MODEL_LOADING_TIMEOUT=18e4,f.STREAM_INACTIVITY_TIMEOUT=6e4,f.RECONNECT_MAX_ATTEMPTS=10,f.RECONNECT_BACKOFF_CAP=15e3;var H=f;var A=class{constructor(e,t,n,r,o=!1,s,c){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=o;this.previewConfig=s,this.getModelName=c}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};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/generate",t,this.reqMeta())}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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/retry",t,this.reqMeta())}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})),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:W(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting})}async sendPreview(e){let t={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:[]};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;if(n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters);return}let r="",o=null,s=null,c=[];await this.http.stream("/preview",t,a=>{r+=a},()=>{},this.reqMeta(),(a,h)=>{o=a,s=h,e.onState&&e.onState(o,s)},void 0,a=>{c=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:r};return o&&(d.delta=o,s&&(d.full=s)),c.length&&(d.createdNames=c),d}};function W(i){if(i)return(e,t)=>i(e,t)}var de=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})}},M=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(ye)),this.state=new de(e,t,n,o)}setInitial(e,t){this.mem=e?e.map(ye):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Ie):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?Ie(t):{name:e}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}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 detail(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return{name:e,avatar:t?.avatar,description:t?.description,...t?.introduction!==void 0?{introduction:t.introduction}:{},...t?.visibleAtStart!==void 0?{visibleAtStart:t.visibleAtStart}:{},userDescription:t?.userDescription,...t?.gender?{gender:t.gender}:{},...t?.isPreset!==void 0?{isPreset:t.isPreset}:{},state:await this.state.get(e)}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`)}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 ye(i){return{name:i.name,description:i.description,avatar:i.avatar,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.gender?{gender:i.gender}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}function Ie(i){return{name:i.name,avatar:i.avatar,description:i.description,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.gender?{gender:i.gender}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}var D=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(o=>({...o})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){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});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){let r=this.mem.find(o=>o.from===e&&o.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){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 Ce(i){let e={count:i.count};return i.desc!==void 0&&(e.desc=i.desc),i.icon_url!==void 0&&(e.iconUrl=i.icon_url),e}function ce(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i)){let r={};for(let[o,s]of Object.entries(n))r[o]=Ce(s);e[t]=r}return e}function $e(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i))e[t]=Ce(n);return e}var N=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,o]of Object.entries(this.mem))n[r]={...o};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return $e(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:o,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 d={count:r};o!==void 0&&(d.desc=o),s!==void 0&&(d.iconUrl=s),this.mem[t][n]=d;return}let c={group:t,name:n,count:r};o!==void 0&&(c.desc=o),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:o,iconUrl:s}=e;if(this.isPreview){let d=this.mem[t];if(!d||!(n in d))throw new Error(`Item "${t}/${n}" not found`);let a=d[n];r!==void 0&&(a.count=r),o!==void 0&&(a.desc=o),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),o!==void 0&&(c.desc=o),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 move(e){let{fromGroup:t,toGroup:n,name:r,newName:o}=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=o||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:o})}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 o=this.mem[e];if(o&&Object.keys(o).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 U=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 le=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})}},$=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new le(e,t,n,o)}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 L(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var F=class{constructor(e,t,n,r=!1,o,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};o&&(this.mem=Re(o)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Re(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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,o]of Object.entries(e))typeof o=="object"&&o!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...o}:this.mem[r]=o,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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(L(`/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(L(`/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(L(`/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(L(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Re(i){let e={};for(let[t,n]of Object.entries(i))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function Te(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var G=class{constructor(e,t,n,r=!1,o){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};o&&(this.mem={...o})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var K=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 V=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null}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}};var Ee="/functions/v1/world-engine/v1",Le="https://api.storvia.ai";function Fe(){return window.__STORVIA__||{}}function Ge(i,e=3e4){let t=Fe();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let o=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=i.on("init",a=>{a.payload?.apiBase&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,debug:a.payload.debug})}),c=i.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(o),s(),c();let h=window;h.__STORVIA__=a,n(a)}i.send(C("ready",{}))})}var q=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new _({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?l=>l.source===null||l.source===window:l=>l.source===window.parent,customSend:t?l=>e.callHandler("storviaBus",l):void 0}),ge(l=>this.bus.send(l));let n=await Ge(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}${Ee}`,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,this.http=new H(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[l,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=l,this.modelId=(n.selectedModelId&&l.some(I=>I.id===n.selectedModelId)?n.selectedModelId:"")||l[0]?.id||"";let p=()=>this.gameId,g=()=>this.conversationId,b=()=>this.modelId,R=()=>this.models.find(I=>I.id===this.modelId)?.name;this.chat=new A(this.http,p,g,b,!0,this.previewConfig,R),this.characters=new M(this.http,g,!0,m?.characters,m?.characterStates),this.relationships=new D(this.http,g,!0,m?.relationships),this.inventory=new N(this.http,g,!0,m?.inventory),this.world=new U(this.http,g,!0,m?.world),this.player=new $(this.http,g,!0,m?.player,m?.playerState),this.custom=new F(this.http,g,p,!0,m?.custom,m?.custom_inject),this.save=new G(this.http,g,p,!0,m?.save_data),this.state=new K(this.http,g,!0),this.memory=new V(this.http,g,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[o,s]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=o.conversationId,this.models=s,this.modelId=(n.selectedModelId&&s.some(l=>l.id===n.selectedModelId)?n.selectedModelId:"")||s[0]?.id||"";let c=()=>this.gameId,d=()=>this.conversationId,a=()=>this.modelId,h=()=>this.models.find(l=>l.id===this.modelId)?.name;this.chat=new A(this.http,c,d,a,!1,void 0,h),this.characters=new M(this.http,d),this.relationships=new D(this.http,d),this.inventory=new N(this.http,d),this.world=new U(this.http,d),this.player=new $(this.http,d),this.custom=new F(this.http,d,c),this.save=new G(this.http,d,c),this.state=new K(this.http,d),this.memory=new V(this.http,d),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)})}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("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 fetchPreviewSnapshot(){try{let e={game_id:this.gameId};return 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)),await this.http.post("/preview/initial-snapshot",e)}catch(e){return console.warn("[Storvia SDK] fetchPreviewSnapshot failed:",e),null}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();e&&(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(){try{return await this.http.get("/models")}catch{}return[]}async authenticate(){let e={game_id:this.gameId};this.conversationId&&(e.conversation_id=this.conversationId);let t=await fetch(`${this.baseUrl}/auth`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`},body:JSON.stringify(e)});if(!t.ok)throw t.status===401?new u("UNAUTHORIZED","User not authenticated"):t.status===404?new u("GAME_NOT_FOUND","Game not found or not published"):new u("INTERNAL_ERROR",`Auth failed: HTTP ${t.status}`);let n=await t.json();return n.data??n}async initDev(e){if(this.initialized)return;this.baseUrl=`${Le}${Ee}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new H(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?t.find(a=>a.name===e.model)?.id??"":"";this.modelId=r||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let o=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new A(this.http,o,s,c,!0,void 0,d),this.characters=new M(this.http,s,!0,n?.characters,n?.characterStates),this.relationships=new D(this.http,s,!0,n?.relationships),this.inventory=new N(this.http,s,!0,n?.inventory),this.world=new U(this.http,s,!0,n?.world),this.player=new $(this.http,s,!0,n?.player,n?.playerState),this.custom=new F(this.http,s,o,!0,n?.custom),this.save=new G(this.http,s,o,!0,n?.save_data),this.memory=new V(this.http,s,!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e};return t&&(n.category=t),(await this.http.get("/assets",n)).map(o=>({id:o.id,name:o.name,url:o.url,assetType:o.asset_type,category:o.category}))}};async function Se(i){let e=new q;return i?.dev?await e.initDev(i.dev):await e.init(),e}function he(i){return typeof i=="object"&&i!==null&&"value"in i&&"type"in i&&(i.type==="number"||i.type==="text")}function be(i){return he(i)?i.value:i}0&&(module.exports={PROTOCOL_VERSION,StorviaBus,StorviaError,StorviaSDK,createStorviaSDK,envelope,extractFieldValue,isProtocolEnvelope,isRichFieldValue,setToastEnabled,showToast});
package/dist/index.d.mts CHANGED
@@ -228,13 +228,6 @@ interface ChatResponse {
228
228
  /** 本轮出现的「真·新角色」名字数组,仅在有新角色时出现 */
229
229
  createdNames?: string[];
230
230
  }
231
- /** chat.active() 返回:该会话/ topic 当前是否有在途生成。 */
232
- interface ChatActiveResult {
233
- /** 是否有正在进行的生成 */
234
- active: boolean;
235
- /** 在途生成的 id(active 为 true 时存在) */
236
- generationId?: string;
237
- }
238
231
  /**
239
232
  * chat.resume() 选项:接管会话/ topic 的在途生成(刷新 / 换设备 / 多端接力)。
240
233
  * 流式回调与 send 一致;无在途生成时静默返回。
@@ -511,14 +504,6 @@ declare class ChatModule {
511
504
  * - 该消息本身不会被删除;它之后的所有消息会被删除
512
505
  */
513
506
  rollback(options: ChatRollbackOptions): Promise<ChatRollbackResponse>;
514
- /**
515
- * 查询当前会话(可按 topic)是否有正在进行的生成。
516
- * 进入对话 / 刷新 / 换设备后先调它,命中再用 resume() 接管在途流。
517
- * 预览模式无在途生成,恒返回 { active: false }。
518
- */
519
- active(options?: {
520
- topic?: string;
521
- }): Promise<ChatActiveResult>;
522
507
  /**
523
508
  * 接管会话/ topic 的在途生成并续读(刷新、换设备、多端接力时用)。
524
509
  * - 生成跑在 chat-worker、产物在 Redis 流,与发起请求的连接解耦;从头实时接上正在输出的内容。
@@ -1019,4 +1004,4 @@ interface ToastAction {
1019
1004
  */
1020
1005
  declare function showToast(message: string, type?: ToastType, duration?: number, action?: ToastAction): void;
1021
1006
 
1022
- export { type AISummary, type AckPayload, type AssetItem, type CharacterAddOptions, type CharacterDetail, type CharacterPersona, type CharacterUpdateOptions, type ChatActiveResult, type ChatGenerateOptions, type ChatMessage, type ChatMessageCursor, type ChatMessagesOptions, type ChatMessagesResponse, type ChatReconnectingCallback, type ChatResponse, type ChatResumeOptions, type ChatRetryOptions, type ChatSaveOptions, type ChatSendOptions, type ChatStateCallback, type ConfigUpdatePayload, type CurrentState, type DormantState, type DownstreamMsg, type FieldValue, type Gender, type InitPayload, type InventoryAddOptions, type InventoryMoveOptions, type InventoryRemoveGroupOptions, type InventoryRemoveOptions, type InventoryState, type InventoryUpdateOptions, type ItemData, type OrientationPayload, PROTOCOL_VERSION, type PlayerPersona, type PreviewConfig, type PreviewInitPayload, type ProtocolEnvelope, type ReadyPayload, type Relationship, type RichFieldValue, type SdkErrorPayload, type SetModelPayload, type State, type StateChanges, StorviaBus, type StorviaBusOptions, StorviaError, type StorviaErrorCode, StorviaSDK, type TokenUpdatePayload, type UpstreamMsg, createStorviaSDK, envelope, extractFieldValue, isProtocolEnvelope, isRichFieldValue, setToastEnabled, showToast };
1007
+ export { type AISummary, type AckPayload, type AssetItem, type CharacterAddOptions, type CharacterDetail, type CharacterPersona, type CharacterUpdateOptions, type ChatGenerateOptions, type ChatMessage, type ChatMessageCursor, type ChatMessagesOptions, type ChatMessagesResponse, type ChatReconnectingCallback, type ChatResponse, type ChatResumeOptions, type ChatRetryOptions, type ChatSaveOptions, type ChatSendOptions, type ChatStateCallback, type ConfigUpdatePayload, type CurrentState, type DormantState, type DownstreamMsg, type FieldValue, type Gender, type InitPayload, type InventoryAddOptions, type InventoryMoveOptions, type InventoryRemoveGroupOptions, type InventoryRemoveOptions, type InventoryState, type InventoryUpdateOptions, type ItemData, type OrientationPayload, PROTOCOL_VERSION, type PlayerPersona, type PreviewConfig, type PreviewInitPayload, type ProtocolEnvelope, type ReadyPayload, type Relationship, type RichFieldValue, type SdkErrorPayload, type SetModelPayload, type State, type StateChanges, StorviaBus, type StorviaBusOptions, StorviaError, type StorviaErrorCode, StorviaSDK, type TokenUpdatePayload, type UpstreamMsg, createStorviaSDK, envelope, extractFieldValue, isProtocolEnvelope, isRichFieldValue, setToastEnabled, showToast };
package/dist/index.esm.js CHANGED
@@ -236,4 +236,4 @@ var u=class extends Error{constructor(e,t){super(t),this.name="StorviaError",thi
236
236
  </div>
237
237
  `;let t=e.querySelector(".storvia-sheet-title");t&&(t.textContent=o.title);let n=e.querySelector(".storvia-sheet-msg");n&&(n.textContent=o.msg);let r=e.querySelector('[data-role="navigate"]');r&&(r.textContent=o.primaryLabel);let i=()=>{e.isConnected&&(e.classList.add("leaving"),e.classList.remove("show"),setTimeout(()=>{e.remove(),Z===e&&(Z=null)},240))};e.querySelector('[data-role="cancel"]')?.addEventListener("click",i),e.addEventListener("click",s=>{s.target===e&&i()}),r?.addEventListener("click",()=>{if(oe)try{oe(E("navigate",{target:"wallet"})),console.log("[Storvia] navigate \u2192 wallet\uFF1A\u5DF2\u901A\u8FC7 bus \u901A\u77E5\u5BBF\u4E3B\u8DF3\u8F6C\u94B1\u5305\u9875")}catch(s){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",s)}else console.warn("[Storvia] navigate \u2192 wallet\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u6309\u94AE\u5DF2\u70B9\u4F46\u65E0\u4EBA\u63A5\u6536\u3002\u751F\u4EA7\u73AF\u5883\u4F1A\u81EA\u52A8\u8DF3\u5230\u4E3B\u7AD9 /wallet \u6216 App \u94B1\u5305\u9875\u3002");i()}),document.body.appendChild(e),Z=e,requestAnimationFrame(()=>e.classList.add("show"))}var f=class f{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||S("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return S("REQUEST_TIMEOUT"),t}return e}createTimeoutController(){let e=new AbortController,t=setTimeout(()=>e.abort(),f.REQUEST_TIMEOUT);return{controller:e,clear:()=>clearTimeout(t)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:i,rawResponse:s,parsedData:c,error:d,durationMs:a,modelName:h}=e,l="%c[Storvia SDK]",m="color: #6366f1; font-weight: bold",p=a!==void 0?` (${a}ms)`:"",g=i!==void 0?` [${i}]`:"",b=h?` [model: ${h}]`:"";d?(console.groupCollapsed(`${l} %c${t} ${n}${g}${b}${p} %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:",d),console.groupEnd()):(console.groupCollapsed(`${l} %c${t} ${n}${g}${b}${p} %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,h])=>n.searchParams.set(a,h));let r=Date.now(),i,s,{controller:c,clear:d}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});d(),i=a.status;let{raw:h,data:l}=await this.handleResponseWithRaw(a);return s=h,this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,parsedData:l,durationMs:Date.now()-r}),l}catch(a){d();let h=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:i,rawResponse:s,error:h,durationMs:Date.now()-r}),h===a&&this.maybeShowNetworkToast(a),h}}async post(e,t,n){let r=Date.now(),i,s,{controller:c,clear:d}=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});d(),i=a.status;let{raw:h,data:l}=await this.handleResponseWithRaw(a);return s=h,this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,parsedData:l,durationMs:Date.now()-r,modelName:n?.modelName}),l}catch(a){d();let h=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:i,rawResponse:s,error:h,durationMs:Date.now()-r,modelName:n?.modelName}),h===a&&this.maybeShowNetworkToast(a),h}}async patch(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=d.status;let{raw:a,data:h}=await this.handleResponseWithRaw(d);return i=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,parsedData:h,durationMs:Date.now()-n}),h}catch(d){c();let a=this.wrapAbortError(d);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async put(e,t){let n=Date.now(),r,i,{controller:s,clear:c}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=d.status;let{raw:a,data:h}=await this.handleResponseWithRaw(d);return i=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,parsedData:h,durationMs:Date.now()-n}),h}catch(d){c();let a=this.wrapAbortError(d);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:i,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),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:d,data:a}=await this.handleResponseWithRaw(c);return r=d,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let d=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:d,durationMs:Date.now()-t}),d===c&&this.maybeShowNetworkToast(c),d}}async stream(e,t,n,r,i,s,c,d,a,h){let l=Date.now(),m=i?.modelName?` [model: ${i.modelName}]`:"",p=[],g=w=>{this.debug&&p.push({t:Date.now()-l,event:w})},b=new AbortController,C=null,I=null,P=null,R=null,k=()=>{C!==null&&(clearTimeout(C),C=null),I!==null&&(clearTimeout(I),I=null),P!==null&&(clearTimeout(P),P=null)},K=w=>{R=w,k(),b.abort()};C=setTimeout(()=>K("REQUEST_TIMEOUT"),f.REQUEST_TIMEOUT);let T;try{T=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:b.signal})}catch(w){if(k(),R){let y=new u(R,"Request timed out");throw S(R),this.log({method:"STREAM",path:e,body:t,error:y,durationMs:Date.now()-l,modelName:i?.modelName}),y}throw this.maybeShowNetworkToast(w),w}if(C!==null&&(clearTimeout(C),C=null),!T.ok){k();let w=await T.text().catch(()=>""),y={};try{y=JSON.parse(w)}catch{}let ne=y.code||"INTERNAL_ERROR",z=new u(ne,y.message||`HTTP ${T.status}`);throw S(ne,y.message),this.log({method:"STREAM",path:e,body:t,status:T.status,rawResponse:w,error:z,durationMs:Date.now()-l,modelName:i?.modelName}),z}let ce=T.body?.getReader();if(!ce)throw k(),new u("INTERNAL_ERROR","No response body for stream");I=setTimeout(()=>K("MODEL_LOADING_TIMEOUT"),f.MODEL_LOADING_TIMEOUT);let Te=new TextDecoder,V="",x="",le=!1,te,q;try{for(;;){let{done:w,value:y}=await ce.read();if(w)break;let z=Te.decode(y,{stream:!0}).split(`
238
238
  `);for(let Y of z){if(Y.startsWith("id: ")){q=Y.slice(4);continue}if(!Y.startsWith("data: "))continue;let re=Y.slice(6);if(re==="[DONE]"){g("[DONE]"),k(),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${T.status}]${m} (${Date.now()-l}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log("Message ID:",V),console.log(`SSE events (${p.length}):`,p),console.groupEnd()),r(V);return}try{let v=JSON.parse(re);g(v),v.type==="done"&&v.id?V=v.id:v.type==="state"?(s&&s(v.delta,v.full??null),d&&Array.isArray(v.createdNames)&&v.createdNames.length&&d(v.createdNames)):v.type==="thinking"?c&&(v.status==="start"||v.status==="end")&&c(v.status):v.content&&(le?(P!==null&&clearTimeout(P),P=setTimeout(()=>K("STREAM_INACTIVITY"),f.STREAM_INACTIVITY_TIMEOUT)):(le=!0,I!==null&&(clearTimeout(I),I=null),P=setTimeout(()=>K("STREAM_INACTIVITY"),f.STREAM_INACTIVITY_TIMEOUT)),x+=v.content,n(v.content))}catch{g({raw:re})}q!==void 0&&(te=q,q=void 0)}}}catch(w){if(k(),R){let y=new u(R,R==="MODEL_LOADING_TIMEOUT"?"Model loading timed out":"Stream inactivity timed out");throw S(R),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${T.status}]${m} (${Date.now()-l}ms) %c\u2717 ${R}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log(`SSE events (${p.length}):`,p),console.error("Timeout:",y),console.groupEnd()),y}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${T.status}]${m} (${Date.now()-l}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log(`SSE events (${p.length}):`,p),console.error("Stream error:",w),console.groupEnd()),a){await this.resumeLoop(a,te,{onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:d,onReconnect:h});return}throw w}if(k(),V){r(V);return}a&&await this.resumeLoop(a,te,{onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:d,onReconnect:h})}async resumeLoop(e,t,n){let r=t;for(let s=1;s<=f.RECONNECT_MAX_ATTEMPTS;s++){let c=Math.min(f.RECONNECT_BACKOFF_CAP,1e3*2**(s-1));await new Promise(h=>setTimeout(h,c)),n.onReconnect?.({attempt:s});let d={messageId:"",lastId:r},a;try{a=await this.pumpGetStream(e.conversationId,e.topic,r,d,n)}catch{continue}if(r=d.lastId??r,a==="done"){n.onDone(d.messageId);return}if(a==="inactive"){d.messageId&&n.onDone(d.messageId);return}}let i=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw S("STREAM_INTERRUPTED"),i}async resumeStream(e,t,n){let r={messageId:""},i;try{i=await this.pumpGetStream(e,t,void 0,r,n)}catch{await this.resumeLoop({conversationId:e,topic:t},r.lastId,n);return}if(i==="done"){n.onDone(r.messageId);return}if(i==="inactive"){r.messageId&&n.onDone(r.messageId);return}await this.resumeLoop({conversationId:e,topic:t},r.lastId,n)}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,d=setTimeout(()=>c.abort(),f.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(d)}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 l=a.body?.getReader();return l?await this.pumpReader(l,r,i):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,i,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},f.STREAM_INACTIVITY_TIMEOUT)};c();try{for(;;){let{done:d,value:a}=await e.read();if(d)break;c();let h=r.decode(a,{stream:!0});for(let l of h.split(`
239
- `)){if(l.startsWith("id: ")){i=l.slice(4);continue}if(!l.startsWith("data: "))continue;let m=l.slice(6);if(m==="[DONE]")return s&&clearTimeout(s),"done";try{let p=JSON.parse(m);p.type==="done"&&p.id?t.messageId=p.id:p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):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)}}}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.code||i[e.status]||"INTERNAL_ERROR",c=new u(s,r.message||`HTTP ${e.status}`);throw S(s,r.message),c}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};f.REQUEST_TIMEOUT=6e4,f.MODEL_LOADING_TIMEOUT=18e4,f.STREAM_INACTIVITY_TIMEOUT=6e4,f.RECONNECT_MAX_ATTEMPTS=10,f.RECONNECT_BACKOFF_CAP=15e3;var B=f;var O=class{constructor(e,t,n,r,i=!1,s,c){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewConfig=s,this.getModelName=c}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};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/generate",t,this.reqMeta())}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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/retry",t,this.reqMeta())}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})),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 active(e={}){if(this.isPreview)return{active:!1};let t={};return e.topic&&(t.topic=e.topic),this.http.get(`/conversations/${encodeURIComponent(this.getConversationId())}/active`,t)}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:H(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting})}async sendPreview(e){let t={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:[]};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;if(n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters);return}let r="",i=null,s=null,c=[];await this.http.stream("/preview",t,a=>{r+=a},()=>{},this.reqMeta(),(a,h)=>{i=a,s=h,e.onState&&e.onState(i,s)},void 0,a=>{c=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:r};return i&&(d.delta=i,s&&(d.full=s)),c.length&&(d.createdNames=c),d}};function H(o){if(o)return(e,t)=>o(e,t)}var se=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})}},A=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(ve)),this.state=new se(e,t,n,i)}setInitial(e,t){this.mem=e?e.map(ve):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(fe):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?fe(t):{name:e}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}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 detail(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return{name:e,avatar:t?.avatar,description:t?.description,...t?.introduction!==void 0?{introduction:t.introduction}:{},...t?.visibleAtStart!==void 0?{visibleAtStart:t.visibleAtStart}:{},userDescription:t?.userDescription,...t?.gender?{gender:t.gender}:{},...t?.isPreset!==void 0?{isPreset:t.isPreset}:{},state:await this.state.get(e)}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`)}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 ve(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}:{},...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function fe(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}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}var M=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(i=>({...i})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){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});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){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){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 we(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 ae(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]=we(s);e[t]=r}return e}function ke(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=we(n);return e}var D=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=ae(r))}setInitial(e){this.mem=e?ae(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 ke(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return ae(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 d={count:r};i!==void 0&&(d.desc=i),s!==void 0&&(d.iconUrl=s),this.mem[t][n]=d;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 d=this.mem[t];if(!d||!(n in d))throw new Error(`Item "${t}/${n}" not found`);let a=d[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 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 N=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 de=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})}},U=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 de(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 $(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var L=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=ye(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?ye(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($(`/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($(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch($(`/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($(`/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($(`/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($(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function ye(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 Ie(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var F=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(Ie(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Ie(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var W=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 G=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null}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}};var Ce="/functions/v1/world-engine/v1",xe="https://api.storvia.ai";function _e(){return window.__STORVIA__||{}}function Oe(o,e=3e4){let t=_e();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&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(i),s(),c();let h=window;h.__STORVIA__=a,n(a)}o.send(E("ready",{}))})}var ee=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new _({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?l=>l.source===null||l.source===window:l=>l.source===window.parent,customSend:t?l=>e.callHandler("storviaBus",l):void 0}),pe(l=>this.bus.send(l));let n=await Oe(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}${Ce}`,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,this.http=new B(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[l,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=l,this.modelId=(n.selectedModelId&&l.some(I=>I.id===n.selectedModelId)?n.selectedModelId:"")||l[0]?.id||"";let p=()=>this.gameId,g=()=>this.conversationId,b=()=>this.modelId,C=()=>this.models.find(I=>I.id===this.modelId)?.name;this.chat=new O(this.http,p,g,b,!0,this.previewConfig,C),this.characters=new A(this.http,g,!0,m?.characters,m?.characterStates),this.relationships=new M(this.http,g,!0,m?.relationships),this.inventory=new D(this.http,g,!0,m?.inventory),this.world=new N(this.http,g,!0,m?.world),this.player=new U(this.http,g,!0,m?.player,m?.playerState),this.custom=new L(this.http,g,p,!0,m?.custom,m?.custom_inject),this.save=new F(this.http,g,p,!0,m?.save_data),this.state=new W(this.http,g,!0),this.memory=new G(this.http,g,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[i,s]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=i.conversationId,this.models=s,this.modelId=(n.selectedModelId&&s.some(l=>l.id===n.selectedModelId)?n.selectedModelId:"")||s[0]?.id||"";let c=()=>this.gameId,d=()=>this.conversationId,a=()=>this.modelId,h=()=>this.models.find(l=>l.id===this.modelId)?.name;this.chat=new O(this.http,c,d,a,!1,void 0,h),this.characters=new A(this.http,d),this.relationships=new M(this.http,d),this.inventory=new D(this.http,d),this.world=new N(this.http,d),this.player=new U(this.http,d),this.custom=new L(this.http,d,c),this.save=new F(this.http,d,c),this.state=new W(this.http,d),this.memory=new G(this.http,d),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)})}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("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 fetchPreviewSnapshot(){try{let e={game_id:this.gameId};return 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)),await this.http.post("/preview/initial-snapshot",e)}catch(e){return console.warn("[Storvia SDK] fetchPreviewSnapshot failed:",e),null}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();e&&(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(){try{return await this.http.get("/models")}catch{}return[]}async authenticate(){let e={game_id:this.gameId};this.conversationId&&(e.conversation_id=this.conversationId);let t=await fetch(`${this.baseUrl}/auth`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`},body:JSON.stringify(e)});if(!t.ok)throw t.status===401?new u("UNAUTHORIZED","User not authenticated"):t.status===404?new u("GAME_NOT_FOUND","Game not found or not published"):new u("INTERNAL_ERROR",`Auth failed: HTTP ${t.status}`);let n=await t.json();return n.data??n}async initDev(e){if(this.initialized)return;this.baseUrl=`${xe}${Ce}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new B(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?t.find(a=>a.name===e.model)?.id??"":"";this.modelId=r||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new O(this.http,i,s,c,!0,void 0,d),this.characters=new A(this.http,s,!0,n?.characters,n?.characterStates),this.relationships=new M(this.http,s,!0,n?.relationships),this.inventory=new D(this.http,s,!0,n?.inventory),this.world=new N(this.http,s,!0,n?.world),this.player=new U(this.http,s,!0,n?.player,n?.playerState),this.custom=new L(this.http,s,i,!0,n?.custom),this.save=new F(this.http,s,i,!0,n?.save_data),this.memory=new G(this.http,s,!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,name:i.name,url:i.url,assetType:i.asset_type,category:i.category}))}};async function Ae(o){let e=new ee;return o?.dev?await e.initDev(o.dev):await e.init(),e}function Re(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function Me(o){return Re(o)?o.value:o}export{j as PROTOCOL_VERSION,_ as StorviaBus,u as StorviaError,ee as StorviaSDK,Ae as createStorviaSDK,E as envelope,Me as extractFieldValue,Q as isProtocolEnvelope,Re as isRichFieldValue,be as setToastEnabled,ge as showToast};
239
+ `)){if(l.startsWith("id: ")){i=l.slice(4);continue}if(!l.startsWith("data: "))continue;let m=l.slice(6);if(m==="[DONE]")return s&&clearTimeout(s),"done";try{let p=JSON.parse(m);p.type==="done"&&p.id?t.messageId=p.id:p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):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)}}}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.code||i[e.status]||"INTERNAL_ERROR",c=new u(s,r.message||`HTTP ${e.status}`);throw S(s,r.message),c}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};f.REQUEST_TIMEOUT=6e4,f.MODEL_LOADING_TIMEOUT=18e4,f.STREAM_INACTIVITY_TIMEOUT=6e4,f.RECONNECT_MAX_ATTEMPTS=10,f.RECONNECT_BACKOFF_CAP=15e3;var B=f;var O=class{constructor(e,t,n,r,i=!1,s,c){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=i;this.previewConfig=s,this.getModelName=c}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};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/generate",t,this.reqMeta())}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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/retry",t,this.reqMeta())}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})),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:H(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting})}async sendPreview(e){let t={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:[]};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;if(n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),H(e.onState),e.onThinking,e.onCreatedCharacters);return}let r="",i=null,s=null,c=[];await this.http.stream("/preview",t,a=>{r+=a},()=>{},this.reqMeta(),(a,h)=>{i=a,s=h,e.onState&&e.onState(i,s)},void 0,a=>{c=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:r};return i&&(d.delta=i,s&&(d.full=s)),c.length&&(d.createdNames=c),d}};function H(o){if(o)return(e,t)=>o(e,t)}var se=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})}},A=class{constructor(e,t,n=!1,r,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(ve)),this.state=new se(e,t,n,i)}setInitial(e,t){this.mem=e?e.map(ve):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(fe):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?fe(t):{name:e}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}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 detail(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return{name:e,avatar:t?.avatar,description:t?.description,...t?.introduction!==void 0?{introduction:t.introduction}:{},...t?.visibleAtStart!==void 0?{visibleAtStart:t.visibleAtStart}:{},userDescription:t?.userDescription,...t?.gender?{gender:t.gender}:{},...t?.isPreset!==void 0?{isPreset:t.isPreset}:{},state:await this.state.get(e)}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`)}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 ve(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}:{},...o.gender?{gender:o.gender}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}function fe(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}:{},...o.userDescription!==void 0?{userDescription:o.userDescription}:{},...o.gender?{gender:o.gender}:{},...o.isPreset!==void 0?{isPreset:o.isPreset}:{}}}var M=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(i=>({...i})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){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});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){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){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 we(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 ae(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]=we(s);e[t]=r}return e}function ke(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=we(n);return e}var D=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};r&&(this.mem=ae(r))}setInitial(e){this.mem=e?ae(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 ke(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return ae(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 d={count:r};i!==void 0&&(d.desc=i),s!==void 0&&(d.iconUrl=s),this.mem[t][n]=d;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 d=this.mem[t];if(!d||!(n in d))throw new Error(`Item "${t}/${n}" not found`);let a=d[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 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 N=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 de=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})}},U=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 de(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 $(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var L=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=ye(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?ye(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($(`/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($(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch($(`/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($(`/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($(`/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($(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function ye(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 Ie(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var F=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(Ie(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Ie(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var W=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 G=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null}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}};var Ce="/functions/v1/world-engine/v1",xe="https://api.storvia.ai";function _e(){return window.__STORVIA__||{}}function Oe(o,e=3e4){let t=_e();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&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,debug:a.payload.debug})}),c=o.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(i),s(),c();let h=window;h.__STORVIA__=a,n(a)}o.send(E("ready",{}))})}var ee=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new _({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?l=>l.source===null||l.source===window:l=>l.source===window.parent,customSend:t?l=>e.callHandler("storviaBus",l):void 0}),pe(l=>this.bus.send(l));let n=await Oe(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}${Ce}`,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,this.http=new B(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[l,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=l,this.modelId=(n.selectedModelId&&l.some(I=>I.id===n.selectedModelId)?n.selectedModelId:"")||l[0]?.id||"";let p=()=>this.gameId,g=()=>this.conversationId,b=()=>this.modelId,C=()=>this.models.find(I=>I.id===this.modelId)?.name;this.chat=new O(this.http,p,g,b,!0,this.previewConfig,C),this.characters=new A(this.http,g,!0,m?.characters,m?.characterStates),this.relationships=new M(this.http,g,!0,m?.relationships),this.inventory=new D(this.http,g,!0,m?.inventory),this.world=new N(this.http,g,!0,m?.world),this.player=new U(this.http,g,!0,m?.player,m?.playerState),this.custom=new L(this.http,g,p,!0,m?.custom,m?.custom_inject),this.save=new F(this.http,g,p,!0,m?.save_data),this.state=new W(this.http,g,!0),this.memory=new G(this.http,g,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[i,s]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=i.conversationId,this.models=s,this.modelId=(n.selectedModelId&&s.some(l=>l.id===n.selectedModelId)?n.selectedModelId:"")||s[0]?.id||"";let c=()=>this.gameId,d=()=>this.conversationId,a=()=>this.modelId,h=()=>this.models.find(l=>l.id===this.modelId)?.name;this.chat=new O(this.http,c,d,a,!1,void 0,h),this.characters=new A(this.http,d),this.relationships=new M(this.http,d),this.inventory=new D(this.http,d),this.world=new N(this.http,d),this.player=new U(this.http,d),this.custom=new L(this.http,d,c),this.save=new F(this.http,d,c),this.state=new W(this.http,d),this.memory=new G(this.http,d),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)})}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("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 fetchPreviewSnapshot(){try{let e={game_id:this.gameId};return 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)),await this.http.post("/preview/initial-snapshot",e)}catch(e){return console.warn("[Storvia SDK] fetchPreviewSnapshot failed:",e),null}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();e&&(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(){try{return await this.http.get("/models")}catch{}return[]}async authenticate(){let e={game_id:this.gameId};this.conversationId&&(e.conversation_id=this.conversationId);let t=await fetch(`${this.baseUrl}/auth`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`},body:JSON.stringify(e)});if(!t.ok)throw t.status===401?new u("UNAUTHORIZED","User not authenticated"):t.status===404?new u("GAME_NOT_FOUND","Game not found or not published"):new u("INTERNAL_ERROR",`Auth failed: HTTP ${t.status}`);let n=await t.json();return n.data??n}async initDev(e){if(this.initialized)return;this.baseUrl=`${xe}${Ce}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new B(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?t.find(a=>a.name===e.model)?.id??"":"";this.modelId=r||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let i=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new O(this.http,i,s,c,!0,void 0,d),this.characters=new A(this.http,s,!0,n?.characters,n?.characterStates),this.relationships=new M(this.http,s,!0,n?.relationships),this.inventory=new D(this.http,s,!0,n?.inventory),this.world=new N(this.http,s,!0,n?.world),this.player=new U(this.http,s,!0,n?.player,n?.playerState),this.custom=new L(this.http,s,i,!0,n?.custom),this.save=new F(this.http,s,i,!0,n?.save_data),this.memory=new G(this.http,s,!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e};return t&&(n.category=t),(await this.http.get("/assets",n)).map(i=>({id:i.id,name:i.name,url:i.url,assetType:i.asset_type,category:i.category}))}};async function Ae(o){let e=new ee;return o?.dev?await e.initDev(o.dev):await e.init(),e}function Re(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function Me(o){return Re(o)?o.value:o}export{j as PROTOCOL_VERSION,_ as StorviaBus,u as StorviaError,ee as StorviaSDK,Ae as createStorviaSDK,E as envelope,Me as extractFieldValue,Q as isProtocolEnvelope,Re as isRichFieldValue,be as setToastEnabled,ge as showToast};
package/dist/index.umd.js CHANGED
@@ -236,5 +236,5 @@
236
236
  </div>
237
237
  `;let t=e.querySelector(".storvia-sheet-title");t&&(t.textContent=i.title);let n=e.querySelector(".storvia-sheet-msg");n&&(n.textContent=i.msg);let r=e.querySelector('[data-role="navigate"]');r&&(r.textContent=i.primaryLabel);let o=()=>{e.isConnected&&(e.classList.add("leaving"),e.classList.remove("show"),setTimeout(()=>{e.remove(),J===e&&(J=null)},240))};e.querySelector('[data-role="cancel"]')?.addEventListener("click",o),e.addEventListener("click",s=>{s.target===e&&o()}),r?.addEventListener("click",()=>{if(se)try{se(C("navigate",{target:"wallet"})),console.log("[Storvia] navigate \u2192 wallet\uFF1A\u5DF2\u901A\u8FC7 bus \u901A\u77E5\u5BBF\u4E3B\u8DF3\u8F6C\u94B1\u5305\u9875")}catch(s){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",s)}else console.warn("[Storvia] navigate \u2192 wallet\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u5BBF\u4E3B\uFF08dev \u6A21\u5F0F\uFF09\uFF0C\u6309\u94AE\u5DF2\u70B9\u4F46\u65E0\u4EBA\u63A5\u6536\u3002\u751F\u4EA7\u73AF\u5883\u4F1A\u81EA\u52A8\u8DF3\u5230\u4E3B\u7AD9 /wallet \u6216 App \u94B1\u5305\u9875\u3002");o()}),document.body.appendChild(e),J=e,requestAnimationFrame(()=>e.classList.add("show"))}var f=class f{constructor(e,t,n=!1,r=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=r}setToken(e){this.token=e}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||S("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return S("REQUEST_TIMEOUT"),t}return e}createTimeoutController(){let e=new AbortController,t=setTimeout(()=>e.abort(),f.REQUEST_TIMEOUT);return{controller:e,clear:()=>clearTimeout(t)}}buildHeaders(){let e={"Content-Type":"application/json"};return this.token&&(e.Authorization=`Bearer ${this.token}`),this.devApiKey&&(e["x-api-key"]=this.devApiKey),e}log(e){if(!this.debug)return;let{method:t,path:n,body:r,status:o,rawResponse:s,parsedData:c,error:d,durationMs:a,modelName:h}=e,l="%c[Storvia SDK]",m="color: #6366f1; font-weight: bold",p=a!==void 0?` (${a}ms)`:"",g=o!==void 0?` [${o}]`:"",b=h?` [model: ${h}]`:"";d?(console.groupCollapsed(`${l} %c${t} ${n}${g}${b}${p} %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:",d),console.groupEnd()):(console.groupCollapsed(`${l} %c${t} ${n}${g}${b}${p} %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,h])=>n.searchParams.set(a,h));let r=Date.now(),o,s,{controller:c,clear:d}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal});d(),o=a.status;let{raw:h,data:l}=await this.handleResponseWithRaw(a);return s=h,this.log({method:"GET",path:e,body:t,status:o,rawResponse:s,parsedData:l,durationMs:Date.now()-r}),l}catch(a){d();let h=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:o,rawResponse:s,error:h,durationMs:Date.now()-r}),h===a&&this.maybeShowNetworkToast(a),h}}async post(e,t,n){let r=Date.now(),o,s,{controller:c,clear:d}=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});d(),o=a.status;let{raw:h,data:l}=await this.handleResponseWithRaw(a);return s=h,this.log({method:"POST",path:e,body:t,status:o,rawResponse:s,parsedData:l,durationMs:Date.now()-r,modelName:n?.modelName}),l}catch(a){d();let h=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:o,rawResponse:s,error:h,durationMs:Date.now()-r,modelName:n?.modelName}),h===a&&this.maybeShowNetworkToast(a),h}}async patch(e,t){let n=Date.now(),r,o,{controller:s,clear:c}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=d.status;let{raw:a,data:h}=await this.handleResponseWithRaw(d);return o=a,this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:o,parsedData:h,durationMs:Date.now()-n}),h}catch(d){c();let a=this.wrapAbortError(d);throw this.log({method:"PATCH",path:e,body:t,status:r,rawResponse:o,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async put(e,t){let n=Date.now(),r,o,{controller:s,clear:c}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:s.signal});c(),r=d.status;let{raw:a,data:h}=await this.handleResponseWithRaw(d);return o=a,this.log({method:"PUT",path:e,body:t,status:r,rawResponse:o,parsedData:h,durationMs:Date.now()-n}),h}catch(d){c();let a=this.wrapAbortError(d);throw this.log({method:"PUT",path:e,body:t,status:r,rawResponse:o,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async delete(e){let t=Date.now(),n,r,{controller:o,clear:s}=this.createTimeoutController();try{let c=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:o.signal});s(),n=c.status;let{raw:d,data:a}=await this.handleResponseWithRaw(c);return r=d,this.log({method:"DELETE",path:e,status:n,rawResponse:r,parsedData:a,durationMs:Date.now()-t}),a}catch(c){s();let d=this.wrapAbortError(c);throw this.log({method:"DELETE",path:e,status:n,rawResponse:r,error:d,durationMs:Date.now()-t}),d===c&&this.maybeShowNetworkToast(c),d}}async stream(e,t,n,r,o,s,c,d,a,h){let l=Date.now(),m=o?.modelName?` [model: ${o.modelName}]`:"",p=[],g=w=>{this.debug&&p.push({t:Date.now()-l,event:w})},b=new AbortController,R=null,I=null,P=null,T=null,k=()=>{R!==null&&(clearTimeout(R),R=null),I!==null&&(clearTimeout(I),I=null),P!==null&&(clearTimeout(P),P=null)},z=w=>{T=w,k(),b.abort()};R=setTimeout(()=>z("REQUEST_TIMEOUT"),f.REQUEST_TIMEOUT);let E;try{E=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:b.signal})}catch(w){if(k(),T){let y=new u(T,"Request timed out");throw S(T),this.log({method:"STREAM",path:e,body:t,error:y,durationMs:Date.now()-l,modelName:o?.modelName}),y}throw this.maybeShowNetworkToast(w),w}if(R!==null&&(clearTimeout(R),R=null),!E.ok){k();let w=await E.text().catch(()=>""),y={};try{y=JSON.parse(w)}catch{}let ne=y.code||"INTERNAL_ERROR",Q=new u(ne,y.message||`HTTP ${E.status}`);throw S(ne,y.message),this.log({method:"STREAM",path:e,body:t,status:E.status,rawResponse:w,error:Q,durationMs:Date.now()-l,modelName:o?.modelName}),Q}let pe=E.body?.getReader();if(!pe)throw k(),new u("INTERNAL_ERROR","No response body for stream");I=setTimeout(()=>z("MODEL_LOADING_TIMEOUT"),f.MODEL_LOADING_TIMEOUT);let Pe=new TextDecoder,j="",x="",ue=!1,te,Y;try{for(;;){let{done:w,value:y}=await pe.read();if(w)break;let Q=Pe.decode(y,{stream:!0}).split(`
238
238
  `);for(let Z of Q){if(Z.startsWith("id: ")){Y=Z.slice(4);continue}if(!Z.startsWith("data: "))continue;let re=Z.slice(6);if(re==="[DONE]"){g("[DONE]"),k(),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${E.status}]${m} (${Date.now()-l}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log("Message ID:",j),console.log(`SSE events (${p.length}):`,p),console.groupEnd()),r(j);return}try{let v=JSON.parse(re);g(v),v.type==="done"&&v.id?j=v.id:v.type==="state"?(s&&s(v.delta,v.full??null),d&&Array.isArray(v.createdNames)&&v.createdNames.length&&d(v.createdNames)):v.type==="thinking"?c&&(v.status==="start"||v.status==="end")&&c(v.status):v.content&&(ue?(P!==null&&clearTimeout(P),P=setTimeout(()=>z("STREAM_INACTIVITY"),f.STREAM_INACTIVITY_TIMEOUT)):(ue=!0,I!==null&&(clearTimeout(I),I=null),P=setTimeout(()=>z("STREAM_INACTIVITY"),f.STREAM_INACTIVITY_TIMEOUT)),x+=v.content,n(v.content))}catch{g({raw:re})}Y!==void 0&&(te=Y,Y=void 0)}}}catch(w){if(k(),T){let y=new u(T,T==="MODEL_LOADING_TIMEOUT"?"Model loading timed out":"Stream inactivity timed out");throw S(T),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${E.status}]${m} (${Date.now()-l}ms) %c\u2717 ${T}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log(`SSE events (${p.length}):`,p),console.error("Timeout:",y),console.groupEnd()),y}if(this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${E.status}]${m} (${Date.now()-l}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${x.length} chars):`,x),console.log(`SSE events (${p.length}):`,p),console.error("Stream error:",w),console.groupEnd()),a){await this.resumeLoop(a,te,{onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:d,onReconnect:h});return}throw w}if(k(),j){r(j);return}a&&await this.resumeLoop(a,te,{onChunk:n,onDone:r,onState:s,onThinking:c,onCreatedCharacters:d,onReconnect:h})}async resumeLoop(e,t,n){let r=t;for(let s=1;s<=f.RECONNECT_MAX_ATTEMPTS;s++){let c=Math.min(f.RECONNECT_BACKOFF_CAP,1e3*2**(s-1));await new Promise(h=>setTimeout(h,c)),n.onReconnect?.({attempt:s});let d={messageId:"",lastId:r},a;try{a=await this.pumpGetStream(e.conversationId,e.topic,r,d,n)}catch{continue}if(r=d.lastId??r,a==="done"){n.onDone(d.messageId);return}if(a==="inactive"){d.messageId&&n.onDone(d.messageId);return}}let o=new u("STREAM_INTERRUPTED","Stream reconnection failed after maximum attempts");throw S("STREAM_INTERRUPTED"),o}async resumeStream(e,t,n){let r={messageId:""},o;try{o=await this.pumpGetStream(e,t,void 0,r,n)}catch{await this.resumeLoop({conversationId:e,topic:t},r.lastId,n);return}if(o==="done"){n.onDone(r.messageId);return}if(o==="inactive"){r.messageId&&n.onDone(r.messageId);return}await this.resumeLoop({conversationId:e,topic:t},r.lastId,n)}async pumpGetStream(e,t,n,r,o){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,d=setTimeout(()=>c.abort(),f.REQUEST_TIMEOUT),a;try{a=await fetch(s.toString(),{method:"GET",headers:this.buildHeaders(),signal:c.signal})}finally{clearTimeout(d)}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 l=a.body?.getReader();return l?await this.pumpReader(l,r,o):"inactive"}async pumpReader(e,t,n){let r=new TextDecoder,o,s=null,c=()=>{s&&clearTimeout(s),s=setTimeout(()=>{e.cancel().catch(()=>{})},f.STREAM_INACTIVITY_TIMEOUT)};c();try{for(;;){let{done:d,value:a}=await e.read();if(d)break;c();let h=r.decode(a,{stream:!0});for(let l of h.split(`
239
- `)){if(l.startsWith("id: ")){o=l.slice(4);continue}if(!l.startsWith("data: "))continue;let m=l.slice(6);if(m==="[DONE]")return s&&clearTimeout(s),"done";try{let p=JSON.parse(m);p.type==="done"&&p.id?t.messageId=p.id:p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}o!==void 0&&(t.lastId=o,o=void 0)}}}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:{},o={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.code||o[e.status]||"INTERNAL_ERROR",c=new u(s,r.message||`HTTP ${e.status}`);throw S(s,r.message),c}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};f.REQUEST_TIMEOUT=6e4,f.MODEL_LOADING_TIMEOUT=18e4,f.STREAM_INACTIVITY_TIMEOUT=6e4,f.RECONNECT_MAX_ATTEMPTS=10,f.RECONNECT_BACKOFF_CAP=15e3;var H=f;var A=class{constructor(e,t,n,r,o=!1,s,c){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=o;this.previewConfig=s,this.getModelName=c}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};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/generate",t,this.reqMeta())}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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/retry",t,this.reqMeta())}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})),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 active(e={}){if(this.isPreview)return{active:!1};let t={};return e.topic&&(t.topic=e.topic),this.http.get(`/conversations/${encodeURIComponent(this.getConversationId())}/active`,t)}async resume(e={}){this.isPreview||await this.http.resumeStream(this.getConversationId(),e.topic,{onChunk:e.onChunk??(()=>{}),onDone:e.onDone??(()=>{}),onState:W(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting})}async sendPreview(e){let t={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:[]};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;if(n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters);return}let r="",o=null,s=null,c=[];await this.http.stream("/preview",t,a=>{r+=a},()=>{},this.reqMeta(),(a,h)=>{o=a,s=h,e.onState&&e.onState(o,s)},void 0,a=>{c=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:r};return o&&(d.delta=o,s&&(d.full=s)),c.length&&(d.createdNames=c),d}};function W(i){if(i)return(e,t)=>i(e,t)}var de=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})}},M=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(ye)),this.state=new de(e,t,n,o)}setInitial(e,t){this.mem=e?e.map(ye):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Ie):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?Ie(t):{name:e}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}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 detail(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return{name:e,avatar:t?.avatar,description:t?.description,...t?.introduction!==void 0?{introduction:t.introduction}:{},...t?.visibleAtStart!==void 0?{visibleAtStart:t.visibleAtStart}:{},userDescription:t?.userDescription,...t?.gender?{gender:t.gender}:{},...t?.isPreset!==void 0?{isPreset:t.isPreset}:{},state:await this.state.get(e)}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`)}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 ye(i){return{name:i.name,description:i.description,avatar:i.avatar,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.gender?{gender:i.gender}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}function Ie(i){return{name:i.name,avatar:i.avatar,description:i.description,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.gender?{gender:i.gender}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}var D=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(o=>({...o})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){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});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){let r=this.mem.find(o=>o.from===e&&o.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){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 Ce(i){let e={count:i.count};return i.desc!==void 0&&(e.desc=i.desc),i.icon_url!==void 0&&(e.iconUrl=i.icon_url),e}function ce(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i)){let r={};for(let[o,s]of Object.entries(n))r[o]=Ce(s);e[t]=r}return e}function $e(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i))e[t]=Ce(n);return e}var N=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,o]of Object.entries(this.mem))n[r]={...o};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return $e(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:o,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 d={count:r};o!==void 0&&(d.desc=o),s!==void 0&&(d.iconUrl=s),this.mem[t][n]=d;return}let c={group:t,name:n,count:r};o!==void 0&&(c.desc=o),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:o,iconUrl:s}=e;if(this.isPreview){let d=this.mem[t];if(!d||!(n in d))throw new Error(`Item "${t}/${n}" not found`);let a=d[n];r!==void 0&&(a.count=r),o!==void 0&&(a.desc=o),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),o!==void 0&&(c.desc=o),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 move(e){let{fromGroup:t,toGroup:n,name:r,newName:o}=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=o||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:o})}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 o=this.mem[e];if(o&&Object.keys(o).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 U=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 le=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})}},$=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new le(e,t,n,o)}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 L(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var F=class{constructor(e,t,n,r=!1,o,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};o&&(this.mem=Re(o)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Re(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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,o]of Object.entries(e))typeof o=="object"&&o!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...o}:this.mem[r]=o,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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(L(`/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(L(`/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(L(`/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(L(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Re(i){let e={};for(let[t,n]of Object.entries(i))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function Te(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var G=class{constructor(e,t,n,r=!1,o){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};o&&(this.mem={...o})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var K=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 V=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null}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}};var Ee="/functions/v1/world-engine/v1",Le="https://api.storvia.ai";function Fe(){return window.__STORVIA__||{}}function Ge(i,e=3e4){let t=Fe();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let o=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=i.on("init",a=>{a.payload?.apiBase&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,debug:a.payload.debug})}),c=i.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(o),s(),c();let h=window;h.__STORVIA__=a,n(a)}i.send(C("ready",{}))})}var q=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new _({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?l=>l.source===null||l.source===window:l=>l.source===window.parent,customSend:t?l=>e.callHandler("storviaBus",l):void 0}),ge(l=>this.bus.send(l));let n=await Ge(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}${Ee}`,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,this.http=new H(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[l,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=l,this.modelId=(n.selectedModelId&&l.some(I=>I.id===n.selectedModelId)?n.selectedModelId:"")||l[0]?.id||"";let p=()=>this.gameId,g=()=>this.conversationId,b=()=>this.modelId,R=()=>this.models.find(I=>I.id===this.modelId)?.name;this.chat=new A(this.http,p,g,b,!0,this.previewConfig,R),this.characters=new M(this.http,g,!0,m?.characters,m?.characterStates),this.relationships=new D(this.http,g,!0,m?.relationships),this.inventory=new N(this.http,g,!0,m?.inventory),this.world=new U(this.http,g,!0,m?.world),this.player=new $(this.http,g,!0,m?.player,m?.playerState),this.custom=new F(this.http,g,p,!0,m?.custom,m?.custom_inject),this.save=new G(this.http,g,p,!0,m?.save_data),this.state=new K(this.http,g,!0),this.memory=new V(this.http,g,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[o,s]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=o.conversationId,this.models=s,this.modelId=(n.selectedModelId&&s.some(l=>l.id===n.selectedModelId)?n.selectedModelId:"")||s[0]?.id||"";let c=()=>this.gameId,d=()=>this.conversationId,a=()=>this.modelId,h=()=>this.models.find(l=>l.id===this.modelId)?.name;this.chat=new A(this.http,c,d,a,!1,void 0,h),this.characters=new M(this.http,d),this.relationships=new D(this.http,d),this.inventory=new N(this.http,d),this.world=new U(this.http,d),this.player=new $(this.http,d),this.custom=new F(this.http,d,c),this.save=new G(this.http,d,c),this.state=new K(this.http,d),this.memory=new V(this.http,d),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)})}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("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 fetchPreviewSnapshot(){try{let e={game_id:this.gameId};return 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)),await this.http.post("/preview/initial-snapshot",e)}catch(e){return console.warn("[Storvia SDK] fetchPreviewSnapshot failed:",e),null}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();e&&(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(){try{return await this.http.get("/models")}catch{}return[]}async authenticate(){let e={game_id:this.gameId};this.conversationId&&(e.conversation_id=this.conversationId);let t=await fetch(`${this.baseUrl}/auth`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`},body:JSON.stringify(e)});if(!t.ok)throw t.status===401?new u("UNAUTHORIZED","User not authenticated"):t.status===404?new u("GAME_NOT_FOUND","Game not found or not published"):new u("INTERNAL_ERROR",`Auth failed: HTTP ${t.status}`);let n=await t.json();return n.data??n}async initDev(e){if(this.initialized)return;this.baseUrl=`${Le}${Ee}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new H(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?t.find(a=>a.name===e.model)?.id??"":"";this.modelId=r||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let o=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new A(this.http,o,s,c,!0,void 0,d),this.characters=new M(this.http,s,!0,n?.characters,n?.characterStates),this.relationships=new D(this.http,s,!0,n?.relationships),this.inventory=new N(this.http,s,!0,n?.inventory),this.world=new U(this.http,s,!0,n?.world),this.player=new $(this.http,s,!0,n?.player,n?.playerState),this.custom=new F(this.http,s,o,!0,n?.custom),this.save=new G(this.http,s,o,!0,n?.save_data),this.memory=new V(this.http,s,!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e};return t&&(n.category=t),(await this.http.get("/assets",n)).map(o=>({id:o.id,name:o.name,url:o.url,assetType:o.asset_type,category:o.category}))}};async function Se(i){let e=new q;return i?.dev?await e.initDev(i.dev):await e.init(),e}function he(i){return typeof i=="object"&&i!==null&&"value"in i&&"type"in i&&(i.type==="number"||i.type==="text")}function be(i){return he(i)?i.value:i}return Me(Ve);})();
239
+ `)){if(l.startsWith("id: ")){o=l.slice(4);continue}if(!l.startsWith("data: "))continue;let m=l.slice(6);if(m==="[DONE]")return s&&clearTimeout(s),"done";try{let p=JSON.parse(m);p.type==="done"&&p.id?t.messageId=p.id:p.type==="state"?(n.onState?.(p.delta,p.full??null),Array.isArray(p.createdNames)&&p.createdNames.length&&n.onCreatedCharacters?.(p.createdNames)):p.type==="thinking"?(p.status==="start"||p.status==="end")&&n.onThinking?.(p.status):p.content&&n.onChunk(p.content)}catch{}o!==void 0&&(t.lastId=o,o=void 0)}}}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:{},o={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},s=r.code||o[e.status]||"INTERNAL_ERROR",c=new u(s,r.message||`HTTP ${e.status}`);throw S(s,r.message),c}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};f.REQUEST_TIMEOUT=6e4,f.MODEL_LOADING_TIMEOUT=18e4,f.STREAM_INACTIVITY_TIMEOUT=6e4,f.RECONNECT_MAX_ATTEMPTS=10,f.RECONNECT_BACKOFF_CAP=15e3;var H=f;var A=class{constructor(e,t,n,r,o=!1,s,c){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=r;this.isPreview=o;this.previewConfig=s,this.getModelName=c}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};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/chat",t,this.reqMeta())}async save(e){return this.isPreview?{id:`preview-${Date.now()}`}:this.http.post("/messages/save",{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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/generate",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/generate",t,this.reqMeta())}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={conversation_id:this.getConversationId(),model_id:this.getModelId(),topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/retry",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters,{conversationId:this.getConversationId(),topic:e.topic},e.onReconnecting);return}return this.http.post("/retry",t,this.reqMeta())}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})),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:W(e.onState),onThinking:e.onThinking,onCreatedCharacters:e.onCreatedCharacters,onReconnect:e.onReconnecting})}async sendPreview(e){let t={model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,history_messages:[]};this.previewConfig?t.prompt_config=this.previewConfig:t.game_id=this.getGameId();let n=this.previewConfig;if(n?.reply_length&&(t.reply_length=n.reply_length),n?.reply_language&&(t.reply_language=n.reply_language),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),W(e.onState),e.onThinking,e.onCreatedCharacters);return}let r="",o=null,s=null,c=[];await this.http.stream("/preview",t,a=>{r+=a},()=>{},this.reqMeta(),(a,h)=>{o=a,s=h,e.onState&&e.onState(o,s)},void 0,a=>{c=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:r};return o&&(d.delta=o,s&&(d.full=s)),c.length&&(d.createdNames=c),d}};function W(i){if(i)return(e,t)=>i(e,t)}var de=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})}},M=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(ye)),this.state=new de(e,t,n,o)}setInitial(e,t){this.mem=e?e.map(ye):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Ie):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?Ie(t):{name:e}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}`)}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 detail(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return{name:e,avatar:t?.avatar,description:t?.description,...t?.introduction!==void 0?{introduction:t.introduction}:{},...t?.visibleAtStart!==void 0?{visibleAtStart:t.visibleAtStart}:{},userDescription:t?.userDescription,...t?.gender?{gender:t.gender}:{},...t?.isPreset!==void 0?{isPreset:t.isPreset}:{},state:await this.state.get(e)}}return this.http.get(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/detail`)}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 ye(i){return{name:i.name,description:i.description,avatar:i.avatar,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.gender?{gender:i.gender}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}function Ie(i){return{name:i.name,avatar:i.avatar,description:i.description,...i.introduction!==void 0?{introduction:i.introduction}:{},...i.visibleAtStart!==void 0?{visibleAtStart:i.visibleAtStart}:{},...i.userDescription!==void 0?{userDescription:i.userDescription}:{},...i.gender?{gender:i.gender}:{},...i.isPreset!==void 0?{isPreset:i.isPreset}:{}}}var D=class{constructor(e,t,n=!1,r){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];r&&(this.mem=r.map(o=>({...o})))}setInitial(e){this.mem=e?e.map(t=>({...t})):[]}async list(){return this.isPreview?[...this.mem]:this.http.get(`/conversations/${this.getConversationId()}/relationships`)}async get(e,t){if(this.isPreview){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});return}await this.http.post(`/conversations/${this.getConversationId()}/relationships`,e)}async update(e,t,n){if(this.isPreview){let r=this.mem.find(o=>o.from===e&&o.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){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 Ce(i){let e={count:i.count};return i.desc!==void 0&&(e.desc=i.desc),i.icon_url!==void 0&&(e.iconUrl=i.icon_url),e}function ce(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i)){let r={};for(let[o,s]of Object.entries(n))r[o]=Ce(s);e[t]=r}return e}function $e(i){let e={};if(!i)return e;for(let[t,n]of Object.entries(i))e[t]=Ce(n);return e}var N=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,o]of Object.entries(this.mem))n[r]={...o};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return $e(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:o,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 d={count:r};o!==void 0&&(d.desc=o),s!==void 0&&(d.iconUrl=s),this.mem[t][n]=d;return}let c={group:t,name:n,count:r};o!==void 0&&(c.desc=o),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:o,iconUrl:s}=e;if(this.isPreview){let d=this.mem[t];if(!d||!(n in d))throw new Error(`Item "${t}/${n}" not found`);let a=d[n];r!==void 0&&(a.count=r),o!==void 0&&(a.desc=o),s!==void 0&&(a.iconUrl=s);return}let c={};r!==void 0&&(c.count=r),o!==void 0&&(c.desc=o),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 move(e){let{fromGroup:t,toGroup:n,name:r,newName:o}=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=o||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:o})}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 o=this.mem[e];if(o&&Object.keys(o).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 U=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 le=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})}},$=class{constructor(e,t,n=!1,r,o){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};r&&(this.memPersona={...r}),this.state=new le(e,t,n,o)}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 L(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var F=class{constructor(e,t,n,r=!1,o,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};this.memInject={};o&&(this.mem=Re(o)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Re(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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[r,o]of Object.entries(e))typeof o=="object"&&o!==null&&typeof this.mem[r]=="object"&&this.mem[r]!==null?this.mem[r]={...this.mem[r],...o}:this.mem[r]=o,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(L(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(L(`/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(L(`/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(L(`/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(L(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Re(i){let e={};for(let[t,n]of Object.entries(i))typeof n=="object"&&n!==null&&!Array.isArray(n)?e[t]={...n}:e[t]=n;return e}function Te(i,e){if(!e)return i;let t=i.includes("?")?"&":"?";return`${i}${t}game_id=${encodeURIComponent(e)}`}var G=class{constructor(e,t,n,r=!1,o){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=r;this.mem={};o&&(this.mem={...o})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()))}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(Te(`/conversations/${this.getConversationId()}/save`,this.getGameId()),e)}};var K=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 V=class{constructor(e,t,n=!1){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=null}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}};var Ee="/functions/v1/world-engine/v1",Le="https://api.storvia.ai";function Fe(){return window.__STORVIA__||{}}function Ge(i,e=3e4){let t=Fe();return t.apiBase?Promise.resolve(t):new Promise((n,r)=>{let o=setTimeout(()=>{s(),c(),r(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),s=i.on("init",a=>{a.payload?.apiBase&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,selectedModelId:a.payload.selectedModelId,debug:a.payload.debug})}),c=i.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(o),s(),c();let h=window;h.__STORVIA__=a,n(a)}i.send(C("ready",{}))})}var q=class{constructor(){this.baseUrl="";this.gameId="";this.conversationId="";this.modelId="";this.models=[];this.accessToken="";this.initialized=!1;this.isPreview=!1;this.previewConfig=void 0}async init(){if(this.initialized)return;let e=window.flutter_inappwebview,t=typeof e?.callHandler=="function";this.bus=new _({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?l=>l.source===null||l.source===window:l=>l.source===window.parent,customSend:t?l=>e.callHandler("storviaBus",l):void 0}),ge(l=>this.bus.send(l));let n=await Ge(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}${Ee}`,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,this.http=new H(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[l,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=l,this.modelId=(n.selectedModelId&&l.some(I=>I.id===n.selectedModelId)?n.selectedModelId:"")||l[0]?.id||"";let p=()=>this.gameId,g=()=>this.conversationId,b=()=>this.modelId,R=()=>this.models.find(I=>I.id===this.modelId)?.name;this.chat=new A(this.http,p,g,b,!0,this.previewConfig,R),this.characters=new M(this.http,g,!0,m?.characters,m?.characterStates),this.relationships=new D(this.http,g,!0,m?.relationships),this.inventory=new N(this.http,g,!0,m?.inventory),this.world=new U(this.http,g,!0,m?.world),this.player=new $(this.http,g,!0,m?.player,m?.playerState),this.custom=new F(this.http,g,p,!0,m?.custom,m?.custom_inject),this.save=new G(this.http,g,p,!0,m?.save_data),this.state=new K(this.http,g,!0),this.memory=new V(this.http,g,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[o,s]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=o.conversationId,this.models=s,this.modelId=(n.selectedModelId&&s.some(l=>l.id===n.selectedModelId)?n.selectedModelId:"")||s[0]?.id||"";let c=()=>this.gameId,d=()=>this.conversationId,a=()=>this.modelId,h=()=>this.models.find(l=>l.id===this.modelId)?.name;this.chat=new A(this.http,c,d,a,!1,void 0,h),this.characters=new M(this.http,d),this.relationships=new D(this.http,d),this.inventory=new N(this.http,d),this.world=new U(this.http,d),this.player=new $(this.http,d),this.custom=new F(this.http,d,c),this.save=new G(this.http,d,c),this.state=new K(this.http,d),this.memory=new V(this.http,d),this.listenForTokenUpdate(),this.listenForModelChange(),this.initialized=!0}listenForModelChange(){this.bus.on("set-model",e=>{let t=e.payload?.modelId||"";t&&(this.modelId=t)})}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("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 fetchPreviewSnapshot(){try{let e={game_id:this.gameId};return 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)),await this.http.post("/preview/initial-snapshot",e)}catch(e){return console.warn("[Storvia SDK] fetchPreviewSnapshot failed:",e),null}}async refreshPreviewSnapshot(){let e=await this.fetchPreviewSnapshot();e&&(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(){try{return await this.http.get("/models")}catch{}return[]}async authenticate(){let e={game_id:this.gameId};this.conversationId&&(e.conversation_id=this.conversationId);let t=await fetch(`${this.baseUrl}/auth`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`},body:JSON.stringify(e)});if(!t.ok)throw t.status===401?new u("UNAUTHORIZED","User not authenticated"):t.status===404?new u("GAME_NOT_FOUND","Game not found or not published"):new u("INTERNAL_ERROR",`Auth failed: HTTP ${t.status}`);let n=await t.json();return n.data??n}async initDev(e){if(this.initialized)return;this.baseUrl=`${Le}${Ee}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new H(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let r=e.model?t.find(a=>a.name===e.model)?.id??"":"";this.modelId=r||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000";let o=()=>this.gameId,s=()=>this.conversationId,c=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new A(this.http,o,s,c,!0,void 0,d),this.characters=new M(this.http,s,!0,n?.characters,n?.characterStates),this.relationships=new D(this.http,s,!0,n?.relationships),this.inventory=new N(this.http,s,!0,n?.inventory),this.world=new U(this.http,s,!0,n?.world),this.player=new $(this.http,s,!0,n?.player,n?.playerState),this.custom=new F(this.http,s,o,!0,n?.custom),this.save=new G(this.http,s,o,!0,n?.save_data),this.memory=new V(this.http,s,!0),this.initialized=!0}async getAssets(e,t){let n={asset_type:e};return t&&(n.category=t),(await this.http.get("/assets",n)).map(o=>({id:o.id,name:o.name,url:o.url,assetType:o.asset_type,category:o.category}))}};async function Se(i){let e=new q;return i?.dev?await e.initDev(i.dev):await e.init(),e}function he(i){return typeof i=="object"&&i!==null&&"value"in i&&"type"in i&&(i.type==="number"||i.type==="text")}function be(i){return he(i)?i.value:i}return Me(Ve);})();
240
240
  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.8.0",
3
+ "version": "0.8.1",
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",