@storvia/sdk 0.5.30 → 0.6.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 +11 -11
- package/dist/index.d.mts +30 -6
- package/dist/index.esm.js +11 -11
- package/dist/index.umd.js +11 -11
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
#${
|
|
1
|
+
"use strict";var se=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var De=Object.prototype.hasOwnProperty;var Ne=(o,e)=>{for(var t in e)se(o,t,{get:e[t],enumerable:!0})},Le=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!De.call(o,i)&&i!==t&&se(o,i,{get:()=>e[i],enumerable:!(n=_e(e,i))||n.enumerable});return o};var Ae=o=>Le(se({},"__esModule",{value:!0}),o);var Je={};Ne(Je,{PROTOCOL_VERSION:()=>D,StorviaBus:()=>M,StorviaError:()=>u,StorviaSDK:()=>X,createStorviaSDK:()=>Re,envelope:()=>I,extractFieldValue:()=>Pe,isProtocolEnvelope:()=>W,isRichFieldValue:()=>he,setToastEnabled:()=>be,showToast:()=>ae});module.exports=Ae(Je);var u=class extends Error{constructor(e,t){super(t),this.name="StorviaError",this.code=e}};var D=1;function W(o){if(!o||typeof o!="object")return!1;let e=o;return typeof e.protocol=="number"&&typeof e.type=="string"&&"payload"in e}function I(o,e,t){return{protocol:1,type:o,payload:e,...t?.id?{id:t.id}:{},...t?.ackId?{ackId:t.ackId}:{}}}var M=class{constructor(e){this.handlers=new Map;this.pendingAcks=new Map;this.listener=null;this.incoming=e.incoming,this.getOutgoing=e.outgoing,this.verifySource=e.verifySource??(()=>!0),this.validate=e.validate,this.debug=!!e.debug,this.getTransferables=e.transfer??(()=>{}),this.customSend=e.customSend,this.attach()}attach(){this.listener=e=>{if((this.incoming instanceof Window||this.incoming===window)&&!this.verifySource(e))return;let t=e.data;if(!W(t))return;if(t.protocol!==1){this.debug&&console.warn("[StorviaBus] protocol mismatch",{expected:1,got:t.protocol,type:t.type});return}if(this.validate&&!this.validate(t)){this.debug&&console.warn("[StorviaBus] validation failed",t);return}if(t.ackId){let i=this.pendingAcks.get(t.ackId);if(i){this.pendingAcks.delete(t.ackId),i(t);return}}let n=this.handlers.get(t.type);if(!n||n.size===0){this.debug&&console.debug("[StorviaBus] no handler for",t.type);return}n.forEach(i=>{try{i(t)}catch(s){console.error(`[StorviaBus] handler '${t.type}' threw:`,s)}})},this.incoming.addEventListener("message",this.listener),this.incoming instanceof MessagePort&&this.incoming.start()}on(e,t){let n=this.handlers.get(e);n||(n=new Set,this.handlers.set(e,n));let i=t;return n.add(i),()=>n.delete(i)}send(e){let t=e.protocol?e:I(e.type,e.payload,{id:e.id,ackId:e.ackId});if(this.customSend){try{this.customSend(t)}catch(s){console.error("[StorviaBus] customSend failed:",s,{type:e.type})}return}let n=this.getOutgoing();if(!n){this.debug&&console.warn("[StorviaBus] outgoing target unavailable, drop:",e.type);return}let i=this.getTransferables(t);try{n instanceof MessagePort?n.postMessage(t,i??[]):n.postMessage(t,"*",i??[])}catch(s){console.error("[StorviaBus] postMessage failed:",s,{type:e.type})}}request(e,t=1e4){return new Promise((n,i)=>{let s=e.id??$e(),r=I(e.type,e.payload,{id:s}),l=setTimeout(()=>{this.pendingAcks.delete(s),i(new Error(`[StorviaBus] request '${e.type}' timed out after ${t}ms`))},t);this.pendingAcks.set(s,d=>{clearTimeout(l),n(d)}),this.send(r)})}destroy(){if(this.listener&&(this.incoming.removeEventListener("message",this.listener),this.listener=null),this.incoming instanceof MessagePort)try{this.incoming.close()}catch{}this.handlers.clear(),this.pendingAcks.clear()}};function $e(){return`bus-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var oe=null;function fe(o){oe=o}var J="storvia-sdk-toast-style",ee="storvia-sdk-toast-stack",ve=`
|
|
2
|
+
#${ee} {
|
|
3
3
|
position: fixed;
|
|
4
4
|
top: max(20px, env(safe-area-inset-top, 0px) + 20px);
|
|
5
5
|
right: max(20px, env(safe-area-inset-right, 0px) + 20px);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
@media (max-width: 768px) {
|
|
15
|
-
#${
|
|
15
|
+
#${ee} {
|
|
16
16
|
top: max(10px, env(safe-area-inset-top, 0px) + 10px);
|
|
17
17
|
left: 10px;
|
|
18
18
|
right: 10px;
|
|
@@ -219,10 +219,10 @@
|
|
|
219
219
|
.storvia-sheet-msg { font-size: 13px; margin-bottom: 22px; }
|
|
220
220
|
.storvia-sheet-btn { height: 40px; font-size: 13px; }
|
|
221
221
|
}
|
|
222
|
-
`,
|
|
223
|
-
<span class="storvia-toast-icon">${
|
|
222
|
+
`,Ue={success:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',error:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',warning:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',info:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>'},re={UNAUTHORIZED:"\u767B\u5F55\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55",INSUFFICIENT_CREDITS:"\u82B1\u56ED\u5E01\u4E0D\u8DB3\uFF0C\u8BF7\u5145\u503C\u540E\u518D\u7EE7\u7EED\u6E38\u620F",VIOLATION_WORD_DETECTED:"\u5185\u5BB9\u542B\u6709\u8FDD\u7981\u8BCD\uFF0C\u8BF7\u4FEE\u6539\u540E\u91CD\u8BD5",CONTENT_FILTERED:"\u5185\u5BB9\u88AB\u5B89\u5168\u7B56\u7565\u62E6\u622A\uFF0C\u8BF7\u8C03\u6574\u540E\u91CD\u8BD5",MODEL_REFUSAL:"\u6A21\u578B\u62D2\u7EDD\u54CD\u5E94\uFF0C\u6362\u4E2A\u8BF4\u6CD5\u8BD5\u8BD5",STREAM_INTERRUPTED:"\u56DE\u590D\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u8BD5",RATE_LIMITED:"\u64CD\u4F5C\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",MODEL_NOT_FOUND:"\u6240\u9009\u6A21\u578B\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5207\u6362\u5176\u4ED6\u6A21\u578B",GAME_NOT_FOUND:"\u672A\u627E\u5230\u5BF9\u5E94\u6E38\u620F",INVALID_REQUEST:"\u8BF7\u6C42\u65E0\u6548\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",INTERNAL_ERROR:"\u670D\u52A1\u51FA\u4E86\u70B9\u5C0F\u95EE\u9898\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",NOT_INITIALIZED:"SDK \u5C1A\u672A\u521D\u59CB\u5316",NOT_SUPPORTED_IN_PREVIEW:"\u5F53\u524D\u63A5\u53E3\u5728\u9884\u89C8\u6A21\u5F0F\u4E0B\u4E0D\u53EF\u7528",NETWORK_ERROR:"\u7F51\u7EDC\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u8FDE\u63A5",REQUEST_TIMEOUT:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",MODEL_LOADING_TIMEOUT:"\u6A21\u578B\u54CD\u5E94\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",STREAM_INACTIVITY:"\u8FDE\u63A5\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u8BD5",DAISY_CARD_REQUIRED:"\u56DE\u6EAF\u6D88\u606F\u9700\u8981\u6709\u6548\u7684\u96CF\u83CA\u5361\u8BA2\u9605",MESSAGE_NOT_FOUND:"\u6D88\u606F\u4E0D\u5B58\u5728\u6216\u65E0\u6743\u64CD\u4F5C",MESSAGE_TOO_OLD:"\u4EC5\u53EF\u56DE\u6EAF 30 \u5929\u5185\u7684\u6D88\u606F",NO_MESSAGES_TO_DELETE:"\u8BE5\u6D88\u606F\u4E4B\u540E\u6CA1\u6709\u53EF\u56DE\u6EAF\u7684\u6D88\u606F"},ye=!0;function be(o){ye=o}function Be(){if(typeof document>"u")return null;let o=document.getElementById(ee);if(!o){if(!document.getElementById(J)){let e=document.createElement("style");e.id=J,e.textContent=ve,document.head.appendChild(e)}o=document.createElement("div"),o.id=ee,document.body.appendChild(o)}return o}function ae(o,e="info",t=3500,n){if(!ye)return;let i=Be();if(!i)return;let s=t<=0,r=document.createElement("div");r.className=`storvia-toast ${e}`,r.innerHTML=`
|
|
223
|
+
<span class="storvia-toast-icon">${Ue[e]}</span>
|
|
224
224
|
<span class="storvia-toast-msg"></span>
|
|
225
|
-
`;let
|
|
225
|
+
`;let l=r.querySelector(".storvia-toast-msg");l&&(l.textContent=o);let d=()=>{r.isConnected&&(r.classList.add("leaving"),r.classList.remove("show"),setTimeout(()=>r.remove(),320))};if(n){let a=document.createElement("button");a.type="button",a.className="storvia-toast-action",a.textContent=n.label,a.addEventListener("click",()=>{try{n.onClick()}catch(c){console.error("[Storvia toast] action error:",c)}d()}),r.appendChild(a)}if(s){let a=document.createElement("button");a.type="button",a.className="storvia-toast-close",a.setAttribute("aria-label","\u5173\u95ED"),a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.addEventListener("click",d),r.appendChild(a)}i.appendChild(r),requestAnimationFrame(()=>r.classList.add("show")),s||setTimeout(d,t)}function _(o,e){if(o==="INSUFFICIENT_CREDITS"){me({title:"\u82B1\u56ED\u5E01\u4E0D\u8DB3",msg:e||re.INSUFFICIENT_CREDITS,primaryLabel:"\u53BB\u5145\u503C"});return}if(o==="DAISY_CARD_REQUIRED"){me({title:"\u9700\u8981\u96CF\u83CA\u5361",msg:e||re.DAISY_CARD_REQUIRED,primaryLabel:"\u53BB\u5F00\u901A"});return}let t=re[o]||e||"\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";ae(t,o==="RATE_LIMITED"?"warning":"error")}var Z=null;function me(o){if(typeof document>"u"||Z)return;if(!document.getElementById(J)){let r=document.createElement("style");r.id=J,r.textContent=ve,document.head.appendChild(r)}let e=document.createElement("div");e.className="storvia-sheet-backdrop",e.innerHTML=`
|
|
226
226
|
<div class="storvia-sheet" role="dialog" aria-modal="true" aria-labelledby="storvia-sheet-title">
|
|
227
227
|
<div class="storvia-sheet-icon">
|
|
228
228
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
|
|
@@ -234,8 +234,8 @@
|
|
|
234
234
|
<button type="button" class="storvia-sheet-btn storvia-sheet-btn-primary" data-role="navigate"></button>
|
|
235
235
|
</div>
|
|
236
236
|
</div>
|
|
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 i=e.querySelector('[data-role="navigate"]');i&&(i.textContent=o.primaryLabel);let s=()=>{e.isConnected&&(e.classList.add("leaving"),e.classList.remove("show"),setTimeout(()=>{e.remove(),
|
|
238
|
-
`);for(let
|
|
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 i=e.querySelector('[data-role="navigate"]');i&&(i.textContent=o.primaryLabel);let s=()=>{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",s),e.addEventListener("click",r=>{r.target===e&&s()}),i?.addEventListener("click",()=>{if(oe)try{oe(I("navigate",{target:"wallet"})),console.log("[Storvia] navigate \u2192 wallet\uFF1A\u5DF2\u901A\u8FC7 bus \u901A\u77E5\u5BBF\u4E3B\u8DF3\u8F6C\u94B1\u5305\u9875")}catch(r){console.error("[Storvia] navigate \u2192 wallet \u901A\u8FC7 bus \u53D1\u9001\u5931\u8D25:",r)}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");s()}),document.body.appendChild(e),Z=e,requestAnimationFrame(()=>e.classList.add("show"))}var T=class T{constructor(e,t,n=!1,i=""){this.baseUrl=e,this.token=t,this.debug=n,this.devApiKey=i}setToken(e){this.token=e}setDebug(e){this.debug=e}maybeShowNetworkToast(e){e instanceof u||_("NETWORK_ERROR")}wrapAbortError(e){if(e instanceof DOMException&&e.name==="AbortError"){let t=new u("REQUEST_TIMEOUT","Request timed out");return _("REQUEST_TIMEOUT"),t}return e}createTimeoutController(){let e=new AbortController,t=setTimeout(()=>e.abort(),T.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:i,status:s,rawResponse:r,parsedData:l,error:d,durationMs:a,modelName:c}=e,p="%c[Storvia SDK]",y="color: #6366f1; font-weight: bold",m=a!==void 0?` (${a}ms)`:"",h=s!==void 0?` [${s}]`:"",g=c?` [model: ${c}]`:"";d?(console.groupCollapsed(`${p} %c${t} ${n}${h}${g}${m} %c\u2717`,y,"color: #e0e0e0","color: #ef4444"),i!==void 0&&console.log("Request:",i),r!==void 0&&console.log("Response (raw):",r),console.error("Error:",d),console.groupEnd()):(console.groupCollapsed(`${p} %c${t} ${n}${h}${g}${m} %c\u2713`,y,"color: #e0e0e0","color: #22c55e"),i!==void 0&&console.log("Request:",i),r!==void 0&&console.log("Response (raw):",r),l!==void 0&&l!==r&&console.log("Response (data):",l),console.groupEnd())}async get(e,t){let n=new URL(`${this.baseUrl}${e}`);t&&Object.entries(t).forEach(([a,c])=>n.searchParams.set(a,c));let i=Date.now(),s,r,{controller:l,clear:d}=this.createTimeoutController();try{let a=await fetch(n.toString(),{method:"GET",headers:this.buildHeaders(),signal:l.signal});d(),s=a.status;let{raw:c,data:p}=await this.handleResponseWithRaw(a);return r=c,this.log({method:"GET",path:e,body:t,status:s,rawResponse:r,parsedData:p,durationMs:Date.now()-i}),p}catch(a){d();let c=this.wrapAbortError(a);throw this.log({method:"GET",path:e,body:t,status:s,rawResponse:r,error:c,durationMs:Date.now()-i}),c===a&&this.maybeShowNetworkToast(a),c}}async post(e,t,n){let i=Date.now(),s,r,{controller:l,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:l.signal});d(),s=a.status;let{raw:c,data:p}=await this.handleResponseWithRaw(a);return r=c,this.log({method:"POST",path:e,body:t,status:s,rawResponse:r,parsedData:p,durationMs:Date.now()-i,modelName:n?.modelName}),p}catch(a){d();let c=this.wrapAbortError(a);throw this.log({method:"POST",path:e,body:t,status:s,rawResponse:r,error:c,durationMs:Date.now()-i,modelName:n?.modelName}),c===a&&this.maybeShowNetworkToast(a),c}}async patch(e,t){let n=Date.now(),i,s,{controller:r,clear:l}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PATCH",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:r.signal});l(),i=d.status;let{raw:a,data:c}=await this.handleResponseWithRaw(d);return s=a,this.log({method:"PATCH",path:e,body:t,status:i,rawResponse:s,parsedData:c,durationMs:Date.now()-n}),c}catch(d){l();let a=this.wrapAbortError(d);throw this.log({method:"PATCH",path:e,body:t,status:i,rawResponse:s,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async put(e,t){let n=Date.now(),i,s,{controller:r,clear:l}=this.createTimeoutController();try{let d=await fetch(`${this.baseUrl}${e}`,{method:"PUT",headers:this.buildHeaders(),body:t?JSON.stringify(t):void 0,signal:r.signal});l(),i=d.status;let{raw:a,data:c}=await this.handleResponseWithRaw(d);return s=a,this.log({method:"PUT",path:e,body:t,status:i,rawResponse:s,parsedData:c,durationMs:Date.now()-n}),c}catch(d){l();let a=this.wrapAbortError(d);throw this.log({method:"PUT",path:e,body:t,status:i,rawResponse:s,error:a,durationMs:Date.now()-n}),a===d&&this.maybeShowNetworkToast(d),a}}async delete(e){let t=Date.now(),n,i,{controller:s,clear:r}=this.createTimeoutController();try{let l=await fetch(`${this.baseUrl}${e}`,{method:"DELETE",headers:this.buildHeaders(),signal:s.signal});r(),n=l.status;let{raw:d,data:a}=await this.handleResponseWithRaw(l);return i=d,this.log({method:"DELETE",path:e,status:n,rawResponse:i,parsedData:a,durationMs:Date.now()-t}),a}catch(l){r();let d=this.wrapAbortError(l);throw this.log({method:"DELETE",path:e,status:n,rawResponse:i,error:d,durationMs:Date.now()-t}),d===l&&this.maybeShowNetworkToast(l),d}}async stream(e,t,n,i,s,r,l,d){let a=Date.now(),c=s?.modelName?` [model: ${s.modelName}]`:"",p=[],y=b=>{this.debug&&p.push({t:Date.now()-a,event:b})},m=new AbortController,h=null,g=null,x=null,w=null,f=()=>{h!==null&&(clearTimeout(h),h=null),g!==null&&(clearTimeout(g),g=null),x!==null&&(clearTimeout(x),x=null)},O=b=>{w=b,f(),m.abort()};h=setTimeout(()=>O("REQUEST_TIMEOUT"),T.REQUEST_TIMEOUT);let S;try{S=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(t),signal:m.signal})}catch(b){if(f(),w){let C=new u(w,"Request timed out");throw _(w),this.log({method:"STREAM",path:e,body:t,error:C,durationMs:Date.now()-a,modelName:s?.modelName}),C}throw this.maybeShowNetworkToast(b),b}if(h!==null&&(clearTimeout(h),h=null),!S.ok){f();let b=await S.text().catch(()=>""),C={};try{C=JSON.parse(b)}catch{}let ne=C.code||"INTERNAL_ERROR",Q=new u(ne,C.message||`HTTP ${S.status}`);throw _(ne,C.message),this.log({method:"STREAM",path:e,body:t,status:S.status,rawResponse:b,error:Q,durationMs:Date.now()-a,modelName:s?.modelName}),Q}let R=S.body?.getReader();if(!R)throw f(),new u("INTERNAL_ERROR","No response body for stream");g=setTimeout(()=>O("MODEL_LOADING_TIMEOUT"),T.MODEL_LOADING_TIMEOUT);let Me=new TextDecoder,z="",P="",ue=!1;try{for(;;){let{done:b,value:C}=await R.read();if(b)break;let Q=Me.decode(C,{stream:!0}).split(`
|
|
238
|
+
`);for(let ge of Q){if(!ge.startsWith("data: "))continue;let ie=ge.slice(6);if(ie==="[DONE]"){y("[DONE]"),f(),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${S.status}]${c} (${Date.now()-a}ms) %c\u2713`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #22c55e"),console.log("Request:",t),console.log(`Accumulated content (${P.length} chars):`,P),console.log("Message ID:",z),console.log(`SSE events (${p.length}):`,p),console.groupEnd()),i(z);return}try{let v=JSON.parse(ie);y(v),v.type==="done"&&v.id?z=v.id:v.type==="state"?(r&&r(v.delta,v.full??null),d&&Array.isArray(v.createdNames)&&v.createdNames.length&&d(v.createdNames)):v.type==="thinking"?l&&(v.status==="start"||v.status==="end")&&l(v.status):v.content&&(ue?(x!==null&&clearTimeout(x),x=setTimeout(()=>O("STREAM_INACTIVITY"),T.STREAM_INACTIVITY_TIMEOUT)):(ue=!0,g!==null&&(clearTimeout(g),g=null),x=setTimeout(()=>O("STREAM_INACTIVITY"),T.STREAM_INACTIVITY_TIMEOUT)),P+=v.content,n(v.content))}catch{y({raw:ie})}}}}catch(b){if(f(),w){let C=new u(w,w==="MODEL_LOADING_TIMEOUT"?"Model loading timed out":"Stream inactivity timed out");throw _(w),this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${S.status}]${c} (${Date.now()-a}ms) %c\u2717 ${w}`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${P.length} chars):`,P),console.log(`SSE events (${p.length}):`,p),console.error("Timeout:",C),console.groupEnd()),C}throw this.debug&&(console.groupCollapsed(`%c[Storvia SDK] %cSTREAM ${e} [${S.status}]${c} (${Date.now()-a}ms) %c\u2717`,"color: #6366f1; font-weight: bold","color: #e0e0e0","color: #ef4444"),console.log("Request:",t),console.log(`Accumulated content (${P.length} chars):`,P),console.log(`SSE events (${p.length}):`,p),console.error("Stream error:",b),console.groupEnd()),b}f(),z&&i(z)}async handleResponseWithRaw(e){let t=await e.text(),n;try{n=t?JSON.parse(t):null}catch{n=t}if(!e.ok){let i=n&&typeof n=="object"?n:{},s={401:"UNAUTHORIZED",402:"INSUFFICIENT_CREDITS",429:"RATE_LIMITED"},r=i.code||s[e.status]||"INTERNAL_ERROR",l=new u(r,i.message||`HTTP ${e.status}`);throw _(r,i.message),l}return n&&typeof n=="object"&&"data"in n?{raw:n,data:n.data}:{raw:n,data:n}}};T.REQUEST_TIMEOUT=6e4,T.MODEL_LOADING_TIMEOUT=18e4,T.STREAM_INACTIVITY_TIMEOUT=6e4;var Y=T;var le="storvia_selected_model_uuid",q=[{value:"zh-CN",label:"\u7B80\u4F53\u4E2D\u6587"},{value:"zh-TW",label:"\u7E41\u9AD4\u4E2D\u6587"},{value:"en",label:"English"},{value:"ja",label:"\u65E5\u672C\u8A9E"},{value:"ko",label:"\uD55C\uAD6D\uC5B4"}],we=[{value:"low",label:"\u7B80\u77ED"},{value:"medium",label:"\u9002\u4E2D"},{value:"high",label:"\u8BE6\u7EC6"}],He="https://cdn.storvia.ai/default/logo.png",Fe="https://api.storvia.ai/storage/v1/object/public/storvia/default/credits.png",Ge=`
|
|
239
239
|
:host {
|
|
240
240
|
position: fixed;
|
|
241
241
|
z-index: 2147483647;
|
|
@@ -1020,7 +1020,7 @@
|
|
|
1020
1020
|
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
|
|
1021
1021
|
}
|
|
1022
1022
|
}
|
|
1023
|
-
`,
|
|
1023
|
+
`,Ve='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>',je='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2v6h-6M3 12a9 9 0 0 1 15-6.7L21 8M3 22v-6h6M21 12a9 9 0 0 1-15 6.7L3 16"/></svg>',ze='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="spin"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>',We='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',Ye='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',Ce='<svg class="check" viewBox="0 0 24 24" fill="none" stroke="#8246FF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',E=48,k=16,qe=5,N=class{constructor(e){this.selectedModelId="";this.pendingModelId="";this.fabWrap=null;this.models=[];this.settings={temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""};this.activeTab="model";this.selectedCategory=null;this.hasWorldUpdate=!1;this.fabDot=null;this.syncHint=null;this.syncDot=null;this.fabX=0;this.fabY=0;this.fab=null;this.panel=null;this.modelTabBtn=null;this.settingsTabBtn=null;this.modelBody=null;this.settingsBody=null;this.footer=null;this.modelGrid=null;this.modelDetail=null;this.tempValueEl=null;this.segmentBtns=[];this.langDropdown=null;this.langOptions=[];this.langArrow=null;this.langDropdownOpen=!1;this.noteCounter=null;this.saveBtn=null;this.syncBtn=null;this.syncState="idle";this.dragStartX=0;this.dragStartY=0;this.dragOffsetX=0;this.dragOffsetY=0;this.dragMoved=!1;this.dragging=!1;this.updateDialogOpen=!1;this.handlePointerDown=e=>{this.fab&&(e.preventDefault(),this.dragStartX=e.clientX,this.dragStartY=e.clientY,this.dragOffsetX=e.clientX-this.fabX,this.dragOffsetY=e.clientY-this.fabY,this.dragMoved=!1,this.dragging=!0,this.fab.setPointerCapture(e.pointerId),this.fab.addEventListener("pointermove",this.handlePointerMove),this.fab.addEventListener("pointerup",this.handlePointerUp),this.fab.addEventListener("pointercancel",this.handlePointerUp))};this.handlePointerMove=e=>{if(!this.dragging)return;let t=e.clientX-this.dragStartX,n=e.clientY-this.dragStartY;!this.dragMoved&&Math.hypot(t,n)>qe&&(this.dragMoved=!0,this.fab?.classList.add("dragging"),this.closePanel()),this.dragMoved&&(this.fabX=e.clientX-this.dragOffsetX,this.fabY=e.clientY-this.dragOffsetY,this.applyHostPosition())};this.handlePointerUp=e=>{if(!this.fab)return;this.fab.removeEventListener("pointermove",this.handlePointerMove),this.fab.removeEventListener("pointerup",this.handlePointerUp),this.fab.removeEventListener("pointercancel",this.handlePointerUp);try{this.fab.releasePointerCapture(e.pointerId)}catch{}if(this.dragging=!1,!this.dragMoved){this.togglePanel();return}this.fab.classList.remove("dragging");let n=this.fabX+E/2<window.innerWidth/2;this.fabX=n?k:window.innerWidth-E-k,this.fabY=Math.max(k,Math.min(window.innerHeight-E-k,this.fabY)),this.fab&&(this.fab.style.transition="left 0.25s cubic-bezier(0.32, 0.72, 0, 1), top 0.25s cubic-bezier(0.32, 0.72, 0, 1), transform 0.2s, box-shadow 0.2s"),this.applyHostPosition(),setTimeout(()=>{this.fab&&(this.fab.style.transition="")},260)};this.handleResize=()=>{this.fabX=Math.max(k,Math.min(window.innerWidth-E-k,this.fabX)),this.fabY=Math.max(k,Math.min(window.innerHeight-E-k,this.fabY)),this.applyHostPosition()};this.handleDocClick=e=>{this.host.contains(e.target)||(this.closePanel(),this.closeLangDropdown())};this.savedBodyOverflow=null;this.callbacks=e,this.host=document.createElement("div"),this.host.id="storvia-settings",this.shadowRoot=this.host.attachShadow({mode:"closed"})}mount(e,t,n,i=!1){this.models=e,this.selectedModelId=t,this.pendingModelId=t,this.settings={...n},this.hasWorldUpdate=i,this.fabX=window.innerWidth-E-k,this.fabY=window.innerHeight-E-k,document.body.appendChild(this.host),this.render(),this.applyHostPosition(),window.addEventListener("resize",this.handleResize),document.addEventListener("click",this.handleDocClick),i&&setTimeout(()=>this.showUpdateDialog("prompt"),600)}unmount(){window.removeEventListener("resize",this.handleResize),document.removeEventListener("click",this.handleDocClick),this.host.remove()}getSelectedModelId(){return this.selectedModelId}getSettings(){return{...this.settings}}render(){let e=document.createElement("style");e.textContent=Ge;let t=document.createElement("div");t.className="fab-wrap",this.fabWrap=t;let n=document.createElement("div");n.className="fab",n.title="\u6E38\u620F\u8BBE\u7F6E";let i=document.createElement("img");i.src=He,i.alt="Storvia",n.appendChild(i),this.fab=n;let s=document.createElement("div");s.className=`fab-dot${this.hasWorldUpdate?" visible":""}`,this.fabDot=s,t.appendChild(n),t.appendChild(s);let r=document.createElement("div");r.className="panel",this.panel=r;let l=document.createElement("div");l.className="panel-header";let d=document.createElement("h2");d.className="panel-title",d.textContent="\u6E38\u620F\u8BBE\u7F6E";let a=document.createElement("button");a.className="close-btn",a.innerHTML=Ve,a.addEventListener("click",()=>this.closePanel()),l.appendChild(d),l.appendChild(a),r.appendChild(l);let c=document.createElement("div");c.className="tabs",this.modelTabBtn=this.createTabBtn("model","\u6A21\u578B\u9009\u62E9"),this.settingsTabBtn=this.createTabBtn("settings","\u6E38\u620F\u8BBE\u7F6E"),this.models.length===0&&(this.activeTab="settings",this.modelTabBtn.style.display="none"),c.appendChild(this.modelTabBtn),c.appendChild(this.settingsTabBtn),r.appendChild(c);let p=document.createElement("div");p.className="panel-body",this.modelBody=this.buildModelTab(),this.settingsBody=this.buildSettingsTab(),p.appendChild(this.modelBody),p.appendChild(this.settingsBody),r.appendChild(p);let y=document.createElement("div");y.className="panel-footer";let m=document.createElement("button");m.className="btn btn-save",m.textContent="\u4FDD\u5B58",this.saveBtn=m,m.addEventListener("click",()=>this.handleSave()),y.appendChild(m),this.footer=y,r.appendChild(y),n.addEventListener("pointerdown",this.handlePointerDown);let h=document.createElement("div");h.appendChild(r),h.appendChild(t),this.shadowRoot.appendChild(e),this.shadowRoot.appendChild(h),this.applyTab()}createTabBtn(e,t){let n=document.createElement("button");return n.className=`tab-btn${this.activeTab===e?" active":""}`,n.textContent=t,n.addEventListener("click",()=>{this.activeTab=e,this.applyTab()}),n}applyTab(){this.modelTabBtn&&this.modelTabBtn.classList.toggle("active",this.activeTab==="model"),this.settingsTabBtn&&this.settingsTabBtn.classList.toggle("active",this.activeTab==="settings"),this.modelBody&&(this.modelBody.style.display=this.activeTab==="model"?"block":"none"),this.settingsBody&&(this.settingsBody.style.display=this.activeTab==="settings"?"block":"none"),this.footer&&(this.footer.style.display="flex")}buildModelTab(){let e=document.createElement("div"),t=this.getCategories();if(t.length>0){let s=document.createElement("div");s.className="category-tabs";let r=(l,d)=>{let a=document.createElement("button");return a.className=`category-tab${this.selectedCategory===d?" active":""}`,a.textContent=l,a.addEventListener("click",()=>{this.selectedCategory=d,s.querySelectorAll(".category-tab").forEach(c=>c.classList.remove("active")),a.classList.add("active"),this.renderModelGrid()}),a};s.appendChild(r("\u5168\u90E8",null)),t.forEach(l=>s.appendChild(r(l,l))),e.appendChild(s)}let n=document.createElement("div");n.className="models-grid",this.modelGrid=n,e.appendChild(n);let i=document.createElement("div");return i.className="model-detail",i.style.display="none",this.modelDetail=i,e.appendChild(i),this.renderModelGrid(),this.renderModelDetail(),e}getCategories(){let e=new Set;return this.models.forEach(t=>{t.category&&e.add(t.category)}),Array.from(e)}getFilteredModels(){return this.selectedCategory?this.models.filter(e=>e.category===this.selectedCategory):this.models}renderModelGrid(){this.modelGrid&&(this.modelGrid.innerHTML="",this.getFilteredModels().forEach(e=>{let t=document.createElement("button"),n=e.is_active!==!1;t.className=`model-card${e.id===this.pendingModelId?" selected":""}${n?"":" disabled"}`;let i=this.getStatusDotColor(e);t.innerHTML=`<span class="status-dot" style="background:${i}"></span><span class="model-name">${this.escapeHtml(e.name)}</span>`,t.addEventListener("click",()=>this.handleSelectModel(e)),this.modelGrid.appendChild(t)}))}handleSelectModel(e){this.pendingModelId=e.id;let t=this.getFilteredModels();this.modelGrid&&this.modelGrid.querySelectorAll(".model-card").forEach((n,i)=>{n.classList.toggle("selected",t[i].id===this.pendingModelId)}),this.renderModelDetail()}renderModelDetail(){if(!this.modelDetail)return;let e=this.models.find(l=>l.id===this.pendingModelId);if(!e){this.modelDetail.style.display="none";return}this.modelDetail.style.display="block";let t=this.getStatusClass(e),n=this.getStatusText(e),i=this.getCreditsValue(e),s=this.getCreditsUnit(e),r=e.description||"";this.modelDetail.innerHTML=`
|
|
1024
1024
|
<div class="detail-header">
|
|
1025
1025
|
<span class="detail-title">${this.escapeHtml(e.name)}</span>
|
|
1026
1026
|
<span class="detail-status ${t}">${n}</span>
|
|
@@ -1028,8 +1028,8 @@
|
|
|
1028
1028
|
${i!==null?`<div class="detail-credits">
|
|
1029
1029
|
<span class="credits-label">\u6D88\u8017</span>
|
|
1030
1030
|
<span class="credits-value">${i}</span>
|
|
1031
|
-
<img class="credits-icon" src="${
|
|
1031
|
+
<img class="credits-icon" src="${Fe}" alt="credits" />
|
|
1032
1032
|
<span class="credits-unit">${s}</span>
|
|
1033
1033
|
</div>`:""}
|
|
1034
1034
|
${r?`<div class="detail-description">${this.escapeHtml(r)}</div>`:""}
|
|
1035
|
-
`}getStatusDotColor(e){if(e.is_active===!1)return"#6b7280";let t=e.success_rate??100;return t>=90?"#10b981":t>=80?"#3b82f6":t>=60?"#eab308":"#f97316"}getStatusClass(e){if(e.is_active===!1)return"inactive";let t=e.success_rate??100;return t>=90?"excellent":t>=80?"good":t>=60?"normal":"crowded"}getStatusText(e){if(e.is_active===!1)return"\u505C\u7528";let t=e.success_rate??100;return t>=90?"\u6D41\u7545":t>=80?"\u826F\u597D":t>=60?"\u4E00\u822C":"\u62E5\u6324"}getCreditsValue(e){let t=e.credits_config;return t?.billing_mode==="per_10k"&&typeof t.per_10k_tokens=="number"?String(t.per_10k_tokens):t?.billing_mode==="flat"&&typeof t.flat=="number"?String(t.flat):null}getCreditsUnit(e){return e.credits_config?.billing_mode==="per_10k"?"/ 10000 token":"/ 1 \u6B21"}buildSettingsTab(){let e=document.createElement("div"),t=document.createElement("div");return t.className="form-stack",t.appendChild(this.buildTemperatureSection()),t.appendChild(this.buildReplyLengthSection()),t.appendChild(this.buildReplyLanguageSection()),t.appendChild(this.buildNoteSection()),t.appendChild(this.buildSyncSection()),e.appendChild(t),e}buildTemperatureSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label";let n=document.createElement("span");n.textContent="\u6E29\u5EA6";let i=document.createElement("span");i.className="temperature-value",i.textContent=this.settings.temperature.toFixed(1),this.tempValueEl=i,t.appendChild(n),t.appendChild(i),e.appendChild(t);let s=document.createElement("p");s.className="form-hint",s.textContent="\u66F4\u4F4E\u8BA9 AI \u56DE\u590D\u66F4\u7A33\u5B9A\u7406\u667A\uFF0C\u66F4\u9AD8\u8BA9\u56DE\u590D\u66F4\u5177\u591A\u6837\u6027",e.appendChild(s);let r=document.createElement("input");r.type="range",r.className="slider",r.min="0",r.max="1",r.step="0.1",r.value=String(this.settings.temperature),r.addEventListener("input",()=>{let l=parseFloat(r.value);this.settings.temperature=l,this.tempValueEl&&(this.tempValueEl.textContent=l.toFixed(1))}),e.appendChild(r);let d=document.createElement("div");return d.className="slider-labels",d.innerHTML="<span>\u7CBE\u786E</span><span>\u521B\u610F</span>",e.appendChild(d),e}buildReplyLengthSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label",t.textContent="\u56DE\u590D\u957F\u5EA6",e.appendChild(t);let n=document.createElement("div");return n.className="segment-control",this.segmentBtns=[],ye.forEach(i=>{let s=document.createElement("button");s.className=`segment-button${i.value===this.settings.replyLength?" active":""}`,s.textContent=i.label,s.addEventListener("click",()=>{this.settings.replyLength=i.value,this.segmentBtns.forEach((r,d)=>{r.classList.toggle("active",ye[d].value===i.value)})}),this.segmentBtns.push(s),n.appendChild(s)}),e.appendChild(n),e}buildReplyLanguageSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label",t.textContent="\u56DE\u590D\u8BED\u8A00",e.appendChild(t);let n=document.createElement("div");n.className="custom-select";let i=document.createElement("button");i.className="select-trigger";let s=document.createElement("span");s.textContent=W.find(l=>l.value===this.settings.replyLanguage)?.label||"";let r=document.createElement("span");r.className="select-arrow",r.textContent="\u25BE",this.langArrow=r,i.appendChild(s),i.appendChild(r),i.addEventListener("click",l=>{l.stopPropagation(),this.toggleLangDropdown()}),n.appendChild(i);let d=document.createElement("div");return d.className="select-dropdown",this.langDropdown=d,this.langOptions=[],W.forEach(l=>{let a=document.createElement("button");a.className=`select-option${l.value===this.settings.replyLanguage?" active":""}`,a.innerHTML=`<span>${l.label}</span>${l.value===this.settings.replyLanguage?be:""}`,a.addEventListener("click",()=>{this.settings.replyLanguage=l.value,s.textContent=l.label,this.langOptions.forEach((c,h)=>{c.classList.toggle("active",W[h].value===l.value),c.innerHTML=`<span>${W[h].label}</span>${W[h].value===l.value?be:""}`}),this.closeLangDropdown()}),this.langOptions.push(a),d.appendChild(a)}),n.appendChild(d),e.appendChild(n),e}toggleLangDropdown(){this.langDropdownOpen?this.closeLangDropdown():this.openLangDropdown()}openLangDropdown(){this.langDropdownOpen=!0,this.langDropdown?.classList.add("open"),this.langArrow&&(this.langArrow.textContent="\u25B4")}closeLangDropdown(){this.langDropdownOpen=!1,this.langDropdown?.classList.remove("open"),this.langArrow&&(this.langArrow.textContent="\u25BE")}buildNoteSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label";let n=document.createElement("span");n.textContent="\u5907\u6CE8";let i=document.createElement("span");i.className="char-count",i.textContent=`${this.settings.playerNote.length}/50`,this.noteCounter=i,t.appendChild(n),t.appendChild(i),e.appendChild(t);let s=document.createElement("p");s.className="form-hint",s.textContent="\u5199\u4E0B\u4F60\u5BF9\u8FD9\u4E2A\u6E38\u620F\u7684\u5907\u6CE8\uFF0C\u4F1A\u663E\u793A\u5728\u5B58\u6863\u5217\u8868",e.appendChild(s);let r=document.createElement("textarea");return r.className="player-note-input",r.placeholder="\u5907\u6CE8",r.maxLength=50,r.rows=2,r.value=this.settings.playerNote,r.addEventListener("input",()=>{this.settings.playerNote=r.value,this.noteCounter&&(this.noteCounter.textContent=`${r.value.length}/50`)}),e.appendChild(r),e}buildSyncSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label sync-label-wrap";let n=document.createElement("span");n.textContent="\u540C\u6B65\u6E38\u620F\u8BBE\u5B9A";let i=document.createElement("span");i.className=`sync-label-dot${this.hasWorldUpdate?" visible":""}`,this.syncDot=i,t.appendChild(n),t.appendChild(i),e.appendChild(t);let s=document.createElement("p");s.className=`sync-hint${this.hasWorldUpdate?" visible":""}`,s.textContent="\u26A0 \u4F5C\u8005\u5DF2\u66F4\u65B0\u6E38\u620F\u5185\u5BB9\uFF0C\u5EFA\u8BAE\u70B9\u51FB\u540C\u6B65",this.syncHint=s,e.appendChild(s);let r=document.createElement("p");r.className="form-hint",r.textContent="\u5C06\u6700\u65B0\u6E38\u620F\u8BBE\u5B9A\u548C\u5F00\u5E55\u5C0F\u5267\u573A\u540C\u6B65\u5230\u5F53\u524D\u5BF9\u8BDD",e.appendChild(r);let d=document.createElement("button");return d.className="btn btn-sync",this.syncBtn=d,this.renderSyncBtn(),d.addEventListener("click",async()=>{if(this.syncState!=="loading"){this.setSyncState("loading");try{await this.callbacks.onSync(),this.setSyncState("success"),this.hasWorldUpdate=!1,this.fabDot&&this.fabDot.classList.remove("visible"),this.syncDot&&this.syncDot.classList.remove("visible"),this.syncHint&&(this.syncHint.textContent="\u2705 \u540C\u6B65\u6210\u529F\uFF0C\u8BF7\u9000\u51FA\u6E38\u620F\u540E\u91CD\u65B0\u6253\u5F00\uFF0C\u6700\u65B0\u8BBE\u5B9A\u5373\u53EF\u751F\u6548",this.syncHint.classList.add("visible")),setTimeout(()=>this.setSyncState("idle"),3e3),this.showUpdateDialog("success")}catch{this.setSyncState("error"),setTimeout(()=>this.setSyncState("idle"),4e3)}}}),e.appendChild(d),e}setSyncState(e){this.syncState=e,this.renderSyncBtn()}renderSyncBtn(){if(!this.syncBtn)return;let e=this.syncState,t={idle:He,loading:Fe,success:Ge,error:je},n={idle:"\u540C\u6B65\u6700\u65B0\u8BBE\u5B9A",loading:"\u540C\u6B65\u4E2D...",success:"\u5DF2\u540C\u6B65",error:"\u540C\u6B65\u5931\u8D25"};this.syncBtn.className=`btn btn-sync${e==="success"||e==="error"?` ${e}`:""}`,this.syncBtn.disabled=e==="loading",this.syncBtn.innerHTML=`${t[e]}<span>${n[e]}</span>`}showUpdateDialog(e="prompt"){if(this.updateDialogOpen)return;this.updateDialogOpen=!0;let t=document.createElement("div");t.className="confirm-overlay";let n=document.createElement("div");n.className="confirm-dialog";let i=document.createElement("h3");i.className="confirm-title";let s=document.createElement("p");s.className="confirm-message";let r=document.createElement("div");r.className="confirm-actions",n.appendChild(i),n.appendChild(s),n.appendChild(r),t.appendChild(n),this.shadowRoot.appendChild(t);let d=()=>{this.updateDialogOpen=!1,t.classList.remove("visible"),setTimeout(()=>t.remove(),200)},l=(c,h,v)=>{let g=document.createElement("button");return g.className=`btn ${h}`,g.textContent=c,g.addEventListener("click",v),g},a=c=>{r.innerHTML="",c==="prompt"?(i.textContent="\u68C0\u6D4B\u5230\u65B0\u7248\u672C",s.textContent="\u4F5C\u8005\u5DF2\u66F4\u65B0\u6E38\u620F\u5185\u5BB9\uFF0C\u662F\u5426\u7ACB\u5373\u540C\u6B65\u6700\u65B0\u8BBE\u5B9A\uFF1F",r.appendChild(l("\u7A0D\u540E","btn-confirm-cancel",d)),r.appendChild(l("\u7ACB\u5373\u66F4\u65B0","btn-confirm-ok",async()=>{a("syncing");try{await this.callbacks.onSync(),this.hasWorldUpdate=!1,this.fabDot&&this.fabDot.classList.remove("visible"),this.syncDot&&this.syncDot.classList.remove("visible"),this.syncHint&&this.syncHint.classList.remove("visible"),this.setSyncState("success"),setTimeout(()=>this.setSyncState("idle"),3e3),a("success")}catch{a("error")}}))):c==="syncing"?(i.textContent="\u6B63\u5728\u540C\u6B65",s.innerHTML='<span class="spinner"></span><span>\u540C\u6B65\u6700\u65B0\u8BBE\u5B9A\u4E2D\uFF0C\u8BF7\u7A0D\u5019...</span>'):c==="success"?(i.textContent="\u540C\u6B65\u6210\u529F",s.textContent="\u9700\u8981\u91CD\u65B0\u542F\u52A8\u6E38\u620F\u624D\u80FD\u5E94\u7528\u6700\u65B0\u8BBE\u5B9A\u3002",r.appendChild(l("\u91CD\u65B0\u542F\u52A8","btn-confirm-ok",()=>{d();try{window.parent.postMessage({type:"storvia-exit"},"*")}catch{}}))):(i.textContent="\u540C\u6B65\u5931\u8D25",s.textContent="\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF0C\u6216\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u3002",r.appendChild(l("\u5173\u95ED","btn-confirm-cancel",d)))};t.addEventListener("click",c=>{c.target===t&&e==="prompt"&&d()}),a(e),requestAnimationFrame(()=>t.classList.add("visible"))}async handleSave(){if(!(!this.saveBtn||this.saveBtn.disabled)){this.saveBtn.disabled=!0,this.saveBtn.innerHTML='<span class="spinner"></span>\u4FDD\u5B58\u4E2D...';try{if(this.pendingModelId&&this.pendingModelId!==this.selectedModelId){let e=this.models.find(t=>t.id===this.pendingModelId);if(e&&e.is_active!==!1){this.selectedModelId=this.pendingModelId,this.callbacks.onModelChange(this.pendingModelId);try{localStorage.setItem("storvia_model_id",this.pendingModelId)}catch{}}else this.pendingModelId=this.selectedModelId}await this.callbacks.onSettingsChange({temperature:this.settings.temperature,replyLength:this.settings.replyLength,replyLanguage:this.settings.replyLanguage,playerNote:this.settings.playerNote}),this.saveBtn&&(this.saveBtn.textContent="\u4FDD\u5B58",this.saveBtn.disabled=!1),this.closePanel()}catch{this.saveBtn&&(this.saveBtn.textContent="\u4FDD\u5B58\u5931\u8D25",setTimeout(()=>{this.saveBtn&&(this.saveBtn.textContent="\u4FDD\u5B58",this.saveBtn.disabled=!1)},2e3))}}}escapeHtml(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}applyHostPosition(){this.host.style.left=`${this.fabX}px`,this.host.style.top=`${this.fabY}px`,this.host.style.right="auto",this.host.style.bottom="auto",this.applyPanelPosition()}isMobile(){return window.innerWidth<=768}applyPanelPosition(){if(!this.panel)return;if(this.isMobile()){this.panel.style.left="",this.panel.style.right="",this.panel.style.top="",this.panel.style.bottom="";return}let e=this.fabX+S/2<window.innerWidth/2,t=380;e?(this.panel.style.left="0",this.panel.style.right="auto"):(this.panel.style.left=`${S-t}px`,this.panel.style.right="auto"),this.fabY>500?(this.panel.style.bottom=`${S+8}px`,this.panel.style.top="auto"):(this.panel.style.top=`${S+8}px`,this.panel.style.bottom="auto")}togglePanel(){this.panel&&(this.panel.classList.contains("open")?this.closePanel():(this.applyPanelPosition(),this.panel.classList.add("open"),requestAnimationFrame(()=>{this.panel?.classList.contains("open")&&(this.fab&&(this.fab.style.visibility="hidden"),this.fabDot&&(this.fabDot.style.visibility="hidden"),this.fabWrap&&(this.fabWrap.style.pointerEvents="none"))}),this.isMobile()&&this.lockBodyScroll()))}closePanel(){if(this.panel&&this.panel.classList.remove("open"),this.fab&&(this.fab.style.visibility="visible"),this.fabDot&&(this.fabDot.style.visibility="visible"),this.fabWrap&&(this.fabWrap.style.pointerEvents=""),this.unlockBodyScroll(),this.pendingModelId!==this.selectedModelId){if(this.pendingModelId=this.selectedModelId,this.modelGrid){let e=this.getFilteredModels();this.modelGrid.querySelectorAll(".model-card").forEach((t,n)=>{t.classList.toggle("selected",e[n].id===this.pendingModelId)})}this.renderModelDetail()}}lockBodyScroll(){this.savedBodyOverflow===null&&(this.savedBodyOverflow=document.body.style.overflow||"",document.body.style.overflow="hidden")}unlockBodyScroll(){this.savedBodyOverflow!==null&&(document.body.style.overflow=this.savedBodyOverflow,this.savedBodyOverflow=null)}};var N=class{constructor(e,t,n,i,s=!1,r,d,l){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=i;this.isPreview=s;this.previewConfig=r,this.getSettings=d,this.getModelName=l}reqMeta(){let e=this.getModelName?.();return e?{modelName:e}:void 0}updatePreviewConfig(e){this.previewConfig=e}async send(e){if(this.isPreview)return this.sendPreview(e);let t={game_id:this.getGameId(),conversation_id:this.getConversationId(),model_id:this.getModelId(),message:e.message,topic:e.topic,scene_key:e.sceneKey,extract:e.extract,stream:e.stream??!1};if(e.stream){await this.http.stream("/chat",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),ee(e.onState),e.onThinking);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});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(),ee(e.onState),e.onThinking);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(),ee(e.onState),e.onThinking);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(i=>({uuid:i.uuid,role:i.role,content:i.content,topic:i.topic,status:i.status,model:i.model,createdAt:i.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 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.getSettings?.();if(n&&(typeof n.temperature=="number"&&(t.temperature=n.temperature),n.replyLength&&(t.reply_length=n.replyLength),n.replyLanguage&&(t.reply_language=n.replyLanguage)),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),ee(e.onState),e.onThinking);return}let i="",s=null,r=null;await this.http.stream("/preview",t,l=>{i+=l},()=>{},this.reqMeta(),(l,a)=>{s=l,r=a,e.onState&&e.onState(s,r)});let d={id:"",content:i};return s&&(d.delta=s,r&&(d.full=r)),d}};function ee(o){if(o)return(e,t)=>o(e,t)}var ae=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let i=this.mem[e]||{};return t?{...i[t]||{}}:{...i}}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 i=this.mem[e]||(this.mem[e]={});i[t]={...i[t]||{},...n};return}await this.http.patch(`/conversations/${this.getConversationId()}/characters/${encodeURIComponent(e)}/state`,{group:t,values:n})}},L=class{constructor(e,t,n=!1,i,s){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];i&&(this.mem=i.map(we)),this.state=new ae(e,t,n,s)}setInitial(e,t){this.mem=e?e.map(we):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(xe):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?xe(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(i=>i.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 we(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 xe(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 A=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];i&&(this.mem=i.map(s=>({...s})))}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(i=>i.from===e&&i.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 i=this.mem.find(s=>s.from===e&&s.to===t);i?Object.assign(i,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(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 le(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let i={};for(let[s,r]of Object.entries(n))i[s]=Ce(r);e[t]=i}return e}function ze(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=Ce(n);return e}var $=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem=le(i))}setInitial(e){this.mem=e?le(e):{}}async list(e){if(this.isPreview){if(e!==void 0)return{...this.mem[e]||{}};let n={};for(let[i,s]of Object.entries(this.mem))n[i]={...s};return n}if(e!==void 0){let n=await this.http.get(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(e)}`);return ze(n)}let t=await this.http.get(`/conversations/${this.getConversationId()}/inventory`);return le(t)}async add(e){let{group:t,name:n,count:i=1,desc:s,iconUrl:r}=e;if(this.isPreview){if(!this.mem[t])throw new Error(`Group "${t}" does not exist`);if(n in this.mem[t])throw new Error(`Item "${n}" already exists in group "${t}"`);let l={count:i};s!==void 0&&(l.desc=s),r!==void 0&&(l.iconUrl=r),this.mem[t][n]=l;return}let d={group:t,name:n,count:i};s!==void 0&&(d.desc=s),r!==void 0&&(d.icon_url=r),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,d)}async update(e){let{group:t,name:n,count:i,desc:s,iconUrl:r}=e;if(this.isPreview){let l=this.mem[t];if(!l||!(n in l))throw new Error(`Item "${t}/${n}" not found`);let a=l[n];i!==void 0&&(a.count=i),s!==void 0&&(a.desc=s),r!==void 0&&(a.iconUrl=r);return}let d={};i!==void 0&&(d.count=i),s!==void 0&&(d.desc=s),r!==void 0&&(d.icon_url=r),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,d)}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:i,newName:s}=e;if(this.isPreview){let r=this.mem[t];if(!r||!(i in r))throw new Error(`Source item "${t}/${i}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let d=s||i;if(t===n&&d===i)return;if(d in this.mem[n])throw new Error(`Item "${d}" already exists in target group`);this.mem[n][d]=r[i],delete r[i];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:i,newName:s})}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 s=this.mem[e];if(s&&Object.keys(s).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let i=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${i}`)}};var U=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}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,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}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})}},B=class{constructor(e,t,n=!1,i,s){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};i&&(this.memPersona={...i}),this.state=new de(e,t,n,s)}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)}};var H=class{constructor(e,t,n=!1,i,s){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};this.memInject={};i&&(this.mem=Se(i)),s&&(this.memInject={...s})}setInitial(e,t){this.mem=e?Se(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`);return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[i,s]of Object.entries(e))typeof s=="object"&&s!==null&&typeof this.mem[i]=="object"&&this.mem[i]!==null?this.mem[i]={...this.mem[i],...s}:this.mem[i]=s,t?.inject!==void 0&&(this.memInject[i]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(`/conversations/${this.getConversationId()}/custom`,n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(`/conversations/${this.getConversationId()}/custom/inject/${encodeURIComponent(e)}`,{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)}`)}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)}`,{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)}`)}};function Se(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}var F=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(){return this.isPreview?{...this.mem}:await this.http.get(`/conversations/${this.getConversationId()}/save`)}async set(e){if(this.isPreview){this.mem={...e};return}await this.http.put(`/conversations/${this.getConversationId()}/save`,e)}};var Y=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 i={content:t,updated_at:new Date().toISOString()};return this.mem=i,{...i}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};var Ie="/functions/v1/world-engine/v1",We="https://api.storvia.ai";function Ye(){return window.__STORVIA__||{}}function qe(o,e=3e4){let t=Ye();return t.apiBase?Promise.resolve(t):new Promise((n,i)=>{let s=setTimeout(()=>{r(),d(),i(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),r=o.on("init",a=>{a.payload?.apiBase&&l({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,debug:a.payload.debug})}),d=o.on("preview-init",a=>{a.payload?.apiBase&&l(a.payload)});function l(a){clearTimeout(s),r(),d();let c=window;c.__STORVIA__=a,n(a)}o.send(I("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 M({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?p=>p.source===null||p.source===window:p=>p.source===window.parent,customSend:t?p=>e.callHandler("storviaBus",p):void 0}),ge(p=>this.bus.send(p));let n=await qe(this.bus),i=n.apiBase;if(!i)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${i}${Ie}`,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 z(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[p,m]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=p;let w=this.getSavedModelId();this.modelId=n.selectedModelId||(w&&p.some(R=>R.id===w)?w:"")||p[0]?.id||"",this.settingsSheet=new D({onModelChange:R=>{this.modelId=R},onSettingsChange:()=>Promise.resolve(),onSync:()=>Promise.resolve()}),p.length>0&&this.settingsSheet.mount(p,this.modelId,{temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""},!1);let k=()=>this.gameId,f=()=>this.conversationId,C=()=>this.modelId,K=()=>this.models.find(R=>R.id===this.modelId)?.name;this.chat=new N(this.http,k,f,C,!0,this.previewConfig,()=>this.settingsSheet?.getSettings()??null,K),this.characters=new L(this.http,f,!0,m?.characters,m?.characterStates),this.relationships=new A(this.http,f,!0,m?.relationships),this.inventory=new $(this.http,f,!0,m?.inventory),this.world=new U(this.http,f,!0,m?.world),this.player=new B(this.http,f,!0,m?.player,m?.playerState),this.custom=new H(this.http,f,!0,m?.custom,m?.custom_inject),this.save=new F(this.http,f,!0,m?.save_data),this.state=new Y(this.http,f,!0),this.memory=new G(this.http,f,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[s,r]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=s.conversationId,this.models=r;let d=this.getSavedModelId();this.modelId=d&&r.some(p=>p.id===d)?d:r[0]?.id||"";let l=s.settings,a=l?{temperature:l.temperature??1,replyLength:l.reply_length??"medium",replyLanguage:l.reply_language??"zh-CN",playerNote:l.player_note??""}:{temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""};this.settingsSheet=new D({onModelChange:p=>{this.modelId=p},onSettingsChange:p=>this.saveSettings(p),onSync:()=>this.syncSettings()}),this.settingsSheet.mount(r,this.modelId,a,s.hasWorldUpdate??!1);let c=()=>this.gameId,h=()=>this.conversationId,v=()=>this.modelId,g=()=>this.models.find(p=>p.id===this.modelId)?.name;this.chat=new N(this.http,c,h,v,!1,void 0,void 0,g),this.characters=new L(this.http,h),this.relationships=new A(this.http,h),this.inventory=new $(this.http,h),this.world=new U(this.http,h),this.player=new B(this.http,h),this.custom=new H(this.http,h),this.save=new F(this.http,h),this.state=new Y(this.http,h),this.memory=new G(this.http,h),this.listenForTokenUpdate(),this.initialized=!0}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 saveSettings(e){let t={conversation_id:this.conversationId};e.temperature!==void 0&&(t.temperature=e.temperature),e.replyLength!==void 0&&(t.reply_length=e.replyLength),e.replyLanguage!==void 0&&(t.reply_language=e.replyLanguage),e.playerNote!==void 0&&(t.player_note=e.playerNote),await this.http.patch("/settings",t)}async syncSettings(){await this.http.post("/sync",{conversation_id:this.conversationId})}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}getSavedModelId(){try{return localStorage.getItem("storvia_model_id")||""}catch{return""}}async initDev(e){if(this.initialized)return;this.baseUrl=`${We}${Ie}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new z(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let i=this.getSavedModelId();this.modelId=(i&&t.some(a=>a.id===i)?i:"")||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000",this.settingsSheet=new D({onModelChange:a=>{this.modelId=a},onSettingsChange:()=>Promise.resolve(),onSync:()=>Promise.resolve()}),t.length>0&&this.settingsSheet.mount(t,this.modelId,{temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""},!1);let s=()=>this.gameId,r=()=>this.conversationId,d=()=>this.modelId,l=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new N(this.http,s,r,d,!0,void 0,()=>this.settingsSheet?.getSettings()??null,l),this.characters=new L(this.http,r,!0,n?.characters,n?.characterStates),this.relationships=new A(this.http,r,!0,n?.relationships),this.inventory=new $(this.http,r,!0,n?.inventory),this.world=new U(this.http,r,!0,n?.world),this.player=new B(this.http,r,!0,n?.player,n?.playerState),this.custom=new H(this.http,r,!0,n?.custom),this.save=new F(this.http,r,!0,n?.save_data),this.memory=new G(this.http,r,!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(s=>({id:s.id,name:s.name,url:s.url,assetType:s.asset_type,category:s.category}))}};async function Ee(o){let e=new q;return o?.dev?await e.initDev(o.dev):await e.init(),e}function ce(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function Te(o){return ce(o)?o.value:o}0&&(module.exports={PROTOCOL_VERSION,StorviaBus,StorviaError,StorviaSDK,createStorviaSDK,envelope,extractFieldValue,isProtocolEnvelope,isRichFieldValue,setToastEnabled,showToast});
|
|
1035
|
+
`}getStatusDotColor(e){if(e.is_active===!1)return"#6b7280";let t=e.success_rate??100;return t>=90?"#10b981":t>=80?"#3b82f6":t>=60?"#eab308":"#f97316"}getStatusClass(e){if(e.is_active===!1)return"inactive";let t=e.success_rate??100;return t>=90?"excellent":t>=80?"good":t>=60?"normal":"crowded"}getStatusText(e){if(e.is_active===!1)return"\u505C\u7528";let t=e.success_rate??100;return t>=90?"\u6D41\u7545":t>=80?"\u826F\u597D":t>=60?"\u4E00\u822C":"\u62E5\u6324"}getCreditsValue(e){let t=e.credits_config;return t?.billing_mode==="per_10k"&&typeof t.per_10k_tokens=="number"?String(t.per_10k_tokens):t?.billing_mode==="flat"&&typeof t.flat=="number"?String(t.flat):null}getCreditsUnit(e){return e.credits_config?.billing_mode==="per_10k"?"/ 10000 token":"/ 1 \u6B21"}buildSettingsTab(){let e=document.createElement("div"),t=document.createElement("div");return t.className="form-stack",t.appendChild(this.buildTemperatureSection()),t.appendChild(this.buildReplyLengthSection()),t.appendChild(this.buildReplyLanguageSection()),t.appendChild(this.buildNoteSection()),t.appendChild(this.buildSyncSection()),e.appendChild(t),e}buildTemperatureSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label";let n=document.createElement("span");n.textContent="\u6E29\u5EA6";let i=document.createElement("span");i.className="temperature-value",i.textContent=this.settings.temperature.toFixed(1),this.tempValueEl=i,t.appendChild(n),t.appendChild(i),e.appendChild(t);let s=document.createElement("p");s.className="form-hint",s.textContent="\u66F4\u4F4E\u8BA9 AI \u56DE\u590D\u66F4\u7A33\u5B9A\u7406\u667A\uFF0C\u66F4\u9AD8\u8BA9\u56DE\u590D\u66F4\u5177\u591A\u6837\u6027",e.appendChild(s);let r=document.createElement("input");r.type="range",r.className="slider",r.min="0",r.max="1",r.step="0.1",r.value=String(this.settings.temperature),r.addEventListener("input",()=>{let d=parseFloat(r.value);this.settings.temperature=d,this.tempValueEl&&(this.tempValueEl.textContent=d.toFixed(1))}),e.appendChild(r);let l=document.createElement("div");return l.className="slider-labels",l.innerHTML="<span>\u7CBE\u786E</span><span>\u521B\u610F</span>",e.appendChild(l),e}buildReplyLengthSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label",t.textContent="\u56DE\u590D\u957F\u5EA6",e.appendChild(t);let n=document.createElement("div");return n.className="segment-control",this.segmentBtns=[],we.forEach(i=>{let s=document.createElement("button");s.className=`segment-button${i.value===this.settings.replyLength?" active":""}`,s.textContent=i.label,s.addEventListener("click",()=>{this.settings.replyLength=i.value,this.segmentBtns.forEach((r,l)=>{r.classList.toggle("active",we[l].value===i.value)})}),this.segmentBtns.push(s),n.appendChild(s)}),e.appendChild(n),e}buildReplyLanguageSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label",t.textContent="\u56DE\u590D\u8BED\u8A00",e.appendChild(t);let n=document.createElement("div");n.className="custom-select";let i=document.createElement("button");i.className="select-trigger";let s=document.createElement("span");s.textContent=q.find(d=>d.value===this.settings.replyLanguage)?.label||"";let r=document.createElement("span");r.className="select-arrow",r.textContent="\u25BE",this.langArrow=r,i.appendChild(s),i.appendChild(r),i.addEventListener("click",d=>{d.stopPropagation(),this.toggleLangDropdown()}),n.appendChild(i);let l=document.createElement("div");return l.className="select-dropdown",this.langDropdown=l,this.langOptions=[],q.forEach(d=>{let a=document.createElement("button");a.className=`select-option${d.value===this.settings.replyLanguage?" active":""}`,a.innerHTML=`<span>${d.label}</span>${d.value===this.settings.replyLanguage?Ce:""}`,a.addEventListener("click",()=>{this.settings.replyLanguage=d.value,s.textContent=d.label,this.langOptions.forEach((c,p)=>{c.classList.toggle("active",q[p].value===d.value),c.innerHTML=`<span>${q[p].label}</span>${q[p].value===d.value?Ce:""}`}),this.closeLangDropdown()}),this.langOptions.push(a),l.appendChild(a)}),n.appendChild(l),e.appendChild(n),e}toggleLangDropdown(){this.langDropdownOpen?this.closeLangDropdown():this.openLangDropdown()}openLangDropdown(){this.langDropdownOpen=!0,this.langDropdown?.classList.add("open"),this.langArrow&&(this.langArrow.textContent="\u25B4")}closeLangDropdown(){this.langDropdownOpen=!1,this.langDropdown?.classList.remove("open"),this.langArrow&&(this.langArrow.textContent="\u25BE")}buildNoteSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label";let n=document.createElement("span");n.textContent="\u5907\u6CE8";let i=document.createElement("span");i.className="char-count",i.textContent=`${this.settings.playerNote.length}/50`,this.noteCounter=i,t.appendChild(n),t.appendChild(i),e.appendChild(t);let s=document.createElement("p");s.className="form-hint",s.textContent="\u5199\u4E0B\u4F60\u5BF9\u8FD9\u4E2A\u6E38\u620F\u7684\u5907\u6CE8\uFF0C\u4F1A\u663E\u793A\u5728\u5B58\u6863\u5217\u8868",e.appendChild(s);let r=document.createElement("textarea");return r.className="player-note-input",r.placeholder="\u5907\u6CE8",r.maxLength=50,r.rows=2,r.value=this.settings.playerNote,r.addEventListener("input",()=>{this.settings.playerNote=r.value,this.noteCounter&&(this.noteCounter.textContent=`${r.value.length}/50`)}),e.appendChild(r),e}buildSyncSection(){let e=document.createElement("div");e.className="form-group";let t=document.createElement("label");t.className="form-label sync-label-wrap";let n=document.createElement("span");n.textContent="\u540C\u6B65\u6E38\u620F\u8BBE\u5B9A";let i=document.createElement("span");i.className=`sync-label-dot${this.hasWorldUpdate?" visible":""}`,this.syncDot=i,t.appendChild(n),t.appendChild(i),e.appendChild(t);let s=document.createElement("p");s.className=`sync-hint${this.hasWorldUpdate?" visible":""}`,s.textContent="\u26A0 \u4F5C\u8005\u5DF2\u66F4\u65B0\u6E38\u620F\u5185\u5BB9\uFF0C\u5EFA\u8BAE\u70B9\u51FB\u540C\u6B65",this.syncHint=s,e.appendChild(s);let r=document.createElement("p");r.className="form-hint",r.textContent="\u5C06\u6700\u65B0\u6E38\u620F\u8BBE\u5B9A\u548C\u5F00\u5E55\u5C0F\u5267\u573A\u540C\u6B65\u5230\u5F53\u524D\u5BF9\u8BDD",e.appendChild(r);let l=document.createElement("button");return l.className="btn btn-sync",this.syncBtn=l,this.renderSyncBtn(),l.addEventListener("click",async()=>{if(this.syncState!=="loading"){this.setSyncState("loading");try{await this.callbacks.onSync(),this.setSyncState("success"),this.hasWorldUpdate=!1,this.fabDot&&this.fabDot.classList.remove("visible"),this.syncDot&&this.syncDot.classList.remove("visible"),this.syncHint&&(this.syncHint.textContent="\u2705 \u540C\u6B65\u6210\u529F\uFF0C\u8BF7\u9000\u51FA\u6E38\u620F\u540E\u91CD\u65B0\u6253\u5F00\uFF0C\u6700\u65B0\u8BBE\u5B9A\u5373\u53EF\u751F\u6548",this.syncHint.classList.add("visible")),setTimeout(()=>this.setSyncState("idle"),3e3),this.showUpdateDialog("success")}catch{this.setSyncState("error"),setTimeout(()=>this.setSyncState("idle"),4e3)}}}),e.appendChild(l),e}setSyncState(e){this.syncState=e,this.renderSyncBtn()}renderSyncBtn(){if(!this.syncBtn)return;let e=this.syncState,t={idle:je,loading:ze,success:We,error:Ye},n={idle:"\u540C\u6B65\u6700\u65B0\u8BBE\u5B9A",loading:"\u540C\u6B65\u4E2D...",success:"\u5DF2\u540C\u6B65",error:"\u540C\u6B65\u5931\u8D25"};this.syncBtn.className=`btn btn-sync${e==="success"||e==="error"?` ${e}`:""}`,this.syncBtn.disabled=e==="loading",this.syncBtn.innerHTML=`${t[e]}<span>${n[e]}</span>`}showUpdateDialog(e="prompt"){if(this.updateDialogOpen)return;this.updateDialogOpen=!0;let t=document.createElement("div");t.className="confirm-overlay";let n=document.createElement("div");n.className="confirm-dialog";let i=document.createElement("h3");i.className="confirm-title";let s=document.createElement("p");s.className="confirm-message";let r=document.createElement("div");r.className="confirm-actions",n.appendChild(i),n.appendChild(s),n.appendChild(r),t.appendChild(n),this.shadowRoot.appendChild(t);let l=()=>{this.updateDialogOpen=!1,t.classList.remove("visible"),setTimeout(()=>t.remove(),200)},d=(c,p,y)=>{let m=document.createElement("button");return m.className=`btn ${p}`,m.textContent=c,m.addEventListener("click",y),m},a=c=>{r.innerHTML="",c==="prompt"?(i.textContent="\u68C0\u6D4B\u5230\u65B0\u7248\u672C",s.textContent="\u4F5C\u8005\u5DF2\u66F4\u65B0\u6E38\u620F\u5185\u5BB9\uFF0C\u662F\u5426\u7ACB\u5373\u540C\u6B65\u6700\u65B0\u8BBE\u5B9A\uFF1F",r.appendChild(d("\u7A0D\u540E","btn-confirm-cancel",l)),r.appendChild(d("\u7ACB\u5373\u66F4\u65B0","btn-confirm-ok",async()=>{a("syncing");try{await this.callbacks.onSync(),this.hasWorldUpdate=!1,this.fabDot&&this.fabDot.classList.remove("visible"),this.syncDot&&this.syncDot.classList.remove("visible"),this.syncHint&&this.syncHint.classList.remove("visible"),this.setSyncState("success"),setTimeout(()=>this.setSyncState("idle"),3e3),a("success")}catch{a("error")}}))):c==="syncing"?(i.textContent="\u6B63\u5728\u540C\u6B65",s.innerHTML='<span class="spinner"></span><span>\u540C\u6B65\u6700\u65B0\u8BBE\u5B9A\u4E2D\uFF0C\u8BF7\u7A0D\u5019...</span>'):c==="success"?(i.textContent="\u540C\u6B65\u6210\u529F",s.textContent="\u9700\u8981\u91CD\u65B0\u542F\u52A8\u6E38\u620F\u624D\u80FD\u5E94\u7528\u6700\u65B0\u8BBE\u5B9A\u3002",r.appendChild(d("\u91CD\u65B0\u542F\u52A8","btn-confirm-ok",()=>{l();try{window.parent.postMessage({type:"storvia-exit"},"*")}catch{}}))):(i.textContent="\u540C\u6B65\u5931\u8D25",s.textContent="\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF0C\u6216\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u3002",r.appendChild(d("\u5173\u95ED","btn-confirm-cancel",l)))};t.addEventListener("click",c=>{c.target===t&&e==="prompt"&&l()}),a(e),requestAnimationFrame(()=>t.classList.add("visible"))}async handleSave(){if(!(!this.saveBtn||this.saveBtn.disabled)){this.saveBtn.disabled=!0,this.saveBtn.innerHTML='<span class="spinner"></span>\u4FDD\u5B58\u4E2D...';try{if(this.pendingModelId&&this.pendingModelId!==this.selectedModelId){let e=this.models.find(t=>t.id===this.pendingModelId);if(e&&e.is_active!==!1){this.selectedModelId=this.pendingModelId,this.callbacks.onModelChange(this.pendingModelId);try{localStorage.setItem(le,this.pendingModelId)}catch{}}else this.pendingModelId=this.selectedModelId}await this.callbacks.onSettingsChange({temperature:this.settings.temperature,replyLength:this.settings.replyLength,replyLanguage:this.settings.replyLanguage,playerNote:this.settings.playerNote}),this.saveBtn&&(this.saveBtn.textContent="\u4FDD\u5B58",this.saveBtn.disabled=!1),this.closePanel()}catch{this.saveBtn&&(this.saveBtn.textContent="\u4FDD\u5B58\u5931\u8D25",setTimeout(()=>{this.saveBtn&&(this.saveBtn.textContent="\u4FDD\u5B58",this.saveBtn.disabled=!1)},2e3))}}}escapeHtml(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}applyHostPosition(){this.host.style.left=`${this.fabX}px`,this.host.style.top=`${this.fabY}px`,this.host.style.right="auto",this.host.style.bottom="auto",this.applyPanelPosition()}isMobile(){return window.innerWidth<=768}applyPanelPosition(){if(!this.panel)return;if(this.isMobile()){this.panel.style.left="",this.panel.style.right="",this.panel.style.top="",this.panel.style.bottom="";return}let e=this.fabX+E/2<window.innerWidth/2,t=380;e?(this.panel.style.left="0",this.panel.style.right="auto"):(this.panel.style.left=`${E-t}px`,this.panel.style.right="auto"),this.fabY>500?(this.panel.style.bottom=`${E+8}px`,this.panel.style.top="auto"):(this.panel.style.top=`${E+8}px`,this.panel.style.bottom="auto")}togglePanel(){this.panel&&(this.panel.classList.contains("open")?this.closePanel():(this.applyPanelPosition(),this.panel.classList.add("open"),requestAnimationFrame(()=>{this.panel?.classList.contains("open")&&(this.fab&&(this.fab.style.visibility="hidden"),this.fabDot&&(this.fabDot.style.visibility="hidden"),this.fabWrap&&(this.fabWrap.style.pointerEvents="none"))}),this.isMobile()&&this.lockBodyScroll()))}closePanel(){if(this.panel&&this.panel.classList.remove("open"),this.fab&&(this.fab.style.visibility="visible"),this.fabDot&&(this.fabDot.style.visibility="visible"),this.fabWrap&&(this.fabWrap.style.pointerEvents=""),this.unlockBodyScroll(),this.pendingModelId!==this.selectedModelId){if(this.pendingModelId=this.selectedModelId,this.modelGrid){let e=this.getFilteredModels();this.modelGrid.querySelectorAll(".model-card").forEach((t,n)=>{t.classList.toggle("selected",e[n].id===this.pendingModelId)})}this.renderModelDetail()}}lockBodyScroll(){this.savedBodyOverflow===null&&(this.savedBodyOverflow=document.body.style.overflow||"",document.body.style.overflow="hidden")}unlockBodyScroll(){this.savedBodyOverflow!==null&&(document.body.style.overflow=this.savedBodyOverflow,this.savedBodyOverflow=null)}};var L=class{constructor(e,t,n,i,s=!1,r,l,d){this.http=e;this.getGameId=t;this.getConversationId=n;this.getModelId=i;this.isPreview=s;this.previewConfig=r,this.getSettings=l,this.getModelName=d}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(),te(e.onState),e.onThinking,e.onCreatedCharacters);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(),te(e.onState),e.onThinking,e.onCreatedCharacters);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(),te(e.onState),e.onThinking,e.onCreatedCharacters);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(i=>({uuid:i.uuid,role:i.role,content:i.content,topic:i.topic,status:i.status,model:i.model,createdAt:i.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 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.getSettings?.();if(n&&(typeof n.temperature=="number"&&(t.temperature=n.temperature),n.replyLength&&(t.reply_length=n.replyLength),n.replyLanguage&&(t.reply_language=n.replyLanguage)),e.stream){await this.http.stream("/preview",t,e.onChunk??(()=>{}),e.onDone??(()=>{}),this.reqMeta(),te(e.onState),e.onThinking,e.onCreatedCharacters);return}let i="",s=null,r=null,l=[];await this.http.stream("/preview",t,a=>{i+=a},()=>{},this.reqMeta(),(a,c)=>{s=a,r=c,e.onState&&e.onState(s,r)},void 0,a=>{l=a,e.onCreatedCharacters&&e.onCreatedCharacters(a)});let d={id:"",content:i};return s&&(d.delta=s,r&&(d.full=r)),l.length&&(d.createdNames=l),d}};function te(o){if(o)return(e,t)=>o(e,t)}var de=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}setInitial(e){this.mem=e?{...e}:{}}async get(e,t){if(this.isPreview){let i=this.mem[e]||{};return t?{...i[t]||{}}:{...i}}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 i=this.mem[e]||(this.mem[e]={});i[t]={...i[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,i,s){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];i&&(this.mem=i.map(xe)),this.state=new de(e,t,n,s)}setInitial(e,t){this.mem=e?e.map(xe):[],this.state.setInitial(t)}async list(){return this.isPreview?this.mem.map(Se):this.http.get(`/conversations/${this.getConversationId()}/characters`)}async get(e){if(this.isPreview){let t=this.mem.find(n=>n.name===e);return t?Se(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(i=>i.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 xe(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 Se(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 $=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem=[];i&&(this.mem=i.map(s=>({...s})))}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(i=>i.from===e&&i.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 i=this.mem.find(s=>s.from===e&&s.to===t);i?Object.assign(i,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 Ie(o){let e={count:o.count};return o.desc!==void 0&&(e.desc=o.desc),o.icon_url!==void 0&&(e.iconUrl=o.icon_url),e}function ce(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o)){let i={};for(let[s,r]of Object.entries(n))i[s]=Ie(r);e[t]=i}return e}function Ke(o){let e={};if(!o)return e;for(let[t,n]of Object.entries(o))e[t]=Ie(n);return e}var U=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem=ce(i))}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[i,s]of Object.entries(this.mem))n[i]={...s};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 ce(t)}async add(e){let{group:t,name:n,count:i=1,desc:s,iconUrl:r}=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:i};s!==void 0&&(d.desc=s),r!==void 0&&(d.iconUrl=r),this.mem[t][n]=d;return}let l={group:t,name:n,count:i};s!==void 0&&(l.desc=s),r!==void 0&&(l.icon_url=r),await this.http.post(`/conversations/${this.getConversationId()}/inventory`,l)}async update(e){let{group:t,name:n,count:i,desc:s,iconUrl:r}=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];i!==void 0&&(a.count=i),s!==void 0&&(a.desc=s),r!==void 0&&(a.iconUrl=r);return}let l={};i!==void 0&&(l.count=i),s!==void 0&&(l.desc=s),r!==void 0&&(l.icon_url=r),await this.http.patch(`/conversations/${this.getConversationId()}/inventory/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,l)}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:i,newName:s}=e;if(this.isPreview){let r=this.mem[t];if(!r||!(i in r))throw new Error(`Source item "${t}/${i}" not found`);if(!this.mem[n])throw new Error(`Target group "${n}" does not exist`);let l=s||i;if(t===n&&l===i)return;if(l in this.mem[n])throw new Error(`Item "${l}" already exists in target group`);this.mem[n][l]=r[i],delete r[i];return}await this.http.post(`/conversations/${this.getConversationId()}/inventory/move`,{fromGroup:t,toGroup:n,name:i,newName:s})}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 s=this.mem[e];if(s&&Object.keys(s).length>0&&!n)throw new Error(`Group "${e}" is not empty, pass cascade: true to force delete`);delete this.mem[e];return}let i=n?"?cascade=true":"";await this.http.delete(`/conversations/${this.getConversationId()}/inventory/groups/${encodeURIComponent(e)}${i}`)}};var B=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}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 pe=class{constructor(e,t,n=!1,i){this.http=e;this.getConversationId=t;this.isPreview=n;this.mem={};i&&(this.mem={...i})}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})}},H=class{constructor(e,t,n=!1,i,s){this.http=e;this.getConversationId=t;this.isPreview=n;this.memPersona={name:""};i&&(this.memPersona={...i}),this.state=new pe(e,t,n,s)}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 F(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var G=class{constructor(e,t,n,i=!1,s,r){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=i;this.mem={};this.memInject={};s&&(this.mem=Ee(s)),r&&(this.memInject={...r})}setInitial(e,t){this.mem=e?Ee(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(F(`/conversations/${this.getConversationId()}/custom`,this.getGameId()));return e!==void 0?t[e]:t}async set(e,t){if(this.isPreview){for(let[i,s]of Object.entries(e))typeof s=="object"&&s!==null&&typeof this.mem[i]=="object"&&this.mem[i]!==null?this.mem[i]={...this.mem[i],...s}:this.mem[i]=s,t?.inject!==void 0&&(this.memInject[i]=t.inject);return}let n=t?.inject!==void 0?{data:e,inject:t.inject}:e;await this.http.patch(F(`/conversations/${this.getConversationId()}/custom`,this.getGameId()),n)}async setInject(e,t){if(this.isPreview){this.memInject[e]=t;return}await this.http.patch(F(`/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(F(`/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(F(`/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(F(`/conversations/${this.getConversationId()}/custom/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,this.getGameId()))}};function Ee(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 Te(o,e){if(!e)return o;let t=o.includes("?")?"&":"?";return`${o}${t}game_id=${encodeURIComponent(e)}`}var V=class{constructor(e,t,n,i=!1,s){this.http=e;this.getConversationId=t;this.getGameId=n;this.isPreview=i;this.mem={};s&&(this.mem={...s})}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 j=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 i={content:t,updated_at:new Date().toISOString()};return this.mem=i,{...i}}return(await this.http.patch(`/conversations/${this.getConversationId()}/summary`,{content:t})).ai_summary}};var ke="/functions/v1/world-engine/v1",Xe="https://api.storvia.ai";function Qe(){return window.__STORVIA__||{}}function Ze(o,e=3e4){let t=Qe();return t.apiBase?Promise.resolve(t):new Promise((n,i)=>{let s=setTimeout(()=>{r(),l(),i(new u("NOT_INITIALIZED","Timed out waiting for __STORVIA__ config from parent frame."))},e),r=o.on("init",a=>{a.payload?.apiBase&&d({apiBase:a.payload.apiBase,gameId:a.payload.gameId,conversationId:a.payload.conversationId,accessToken:a.payload.accessToken,debug:a.payload.debug})}),l=o.on("preview-init",a=>{a.payload?.apiBase&&d(a.payload)});function d(a){clearTimeout(s),r(),l();let c=window;c.__STORVIA__=a,n(a)}o.send(I("ready",{}))})}var X=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 M({incoming:window,outgoing:()=>t?null:window.parent,verifySource:t?h=>h.source===null||h.source===window:h=>h.source===window.parent,customSend:t?h=>e.callHandler("storviaBus",h):void 0}),fe(h=>this.bus.send(h));let n=await Ze(this.bus),i=n.apiBase;if(!i)throw new u("NOT_INITIALIZED","window.__STORVIA__.apiBase is not set. The platform must inject it before SDK init.");if(this.baseUrl=`${i}${ke}`,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 Y(this.baseUrl,this.accessToken,!!n.debug),this.isPreview){this.conversationId="00000000-0000-0000-0000-000000000000";let[h,g]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=h;let x=this.getSavedModelId();this.modelId=n.selectedModelId||(x&&h.some(R=>R.id===x)?x:"")||h[0]?.id||"",this.settingsSheet=new N({onModelChange:R=>this.handleLocalModelChange(R),onSettingsChange:()=>Promise.resolve(),onSync:()=>Promise.resolve()}),h.length>0&&this.settingsSheet.mount(h,this.modelId,{temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""},!1);let w=()=>this.gameId,f=()=>this.conversationId,O=()=>this.modelId,S=()=>this.models.find(R=>R.id===this.modelId)?.name;this.chat=new L(this.http,w,f,O,!0,this.previewConfig,()=>this.settingsSheet?.getSettings()??null,S),this.characters=new A(this.http,f,!0,g?.characters,g?.characterStates),this.relationships=new $(this.http,f,!0,g?.relationships),this.inventory=new U(this.http,f,!0,g?.inventory),this.world=new B(this.http,f,!0,g?.world),this.player=new H(this.http,f,!0,g?.player,g?.playerState),this.custom=new G(this.http,f,w,!0,g?.custom,g?.custom_inject),this.save=new V(this.http,f,w,!0,g?.save_data),this.state=new K(this.http,f,!0),this.memory=new j(this.http,f,!0),this.initialized=!0,this.listenForPreviewMessages(),this.listenForTokenUpdate();return}this.conversationId=n.conversationId??"";let[s,r]=await Promise.all([this.authenticate(),this.fetchModels()]);this.conversationId=s.conversationId,this.models=r;let l=this.getSavedModelId();this.modelId=l&&r.some(h=>h.id===l)?l:r[0]?.id||"";let d=s.settings,a=d?{temperature:d.temperature??1,replyLength:d.reply_length??"medium",replyLanguage:d.reply_language??"zh-CN",playerNote:d.player_note??""}:{temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""};this.settingsSheet=new N({onModelChange:h=>this.handleLocalModelChange(h),onSettingsChange:h=>this.saveSettings(h),onSync:()=>this.syncSettings()}),this.settingsSheet.mount(r,this.modelId,a,s.hasWorldUpdate??!1);let c=()=>this.gameId,p=()=>this.conversationId,y=()=>this.modelId,m=()=>this.models.find(h=>h.id===this.modelId)?.name;this.chat=new L(this.http,c,p,y,!1,void 0,void 0,m),this.characters=new A(this.http,p),this.relationships=new $(this.http,p),this.inventory=new U(this.http,p),this.world=new B(this.http,p),this.player=new H(this.http,p),this.custom=new G(this.http,p,c),this.save=new V(this.http,p,c),this.state=new K(this.http,p),this.memory=new j(this.http,p),this.listenForTokenUpdate(),this.initialized=!0}listenForTokenUpdate(){this.bus.on("token-update",e=>{let t=e.payload?.accessToken;typeof t!="string"||!t||(this.accessToken=t,this.http?.setToken(t))})}handleLocalModelChange(e){this.modelId=e,this.bus&&e&&this.bus.send(I("model-change",{modelId:e}))}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 saveSettings(e){let t={conversation_id:this.conversationId};e.temperature!==void 0&&(t.temperature=e.temperature),e.replyLength!==void 0&&(t.reply_length=e.replyLength),e.replyLanguage!==void 0&&(t.reply_language=e.replyLanguage),e.playerNote!==void 0&&(t.player_note=e.playerNote),await this.http.patch("/settings",t)}async syncSettings(){await this.http.post("/sync",{conversation_id:this.conversationId})}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}getSavedModelId(){try{return localStorage.getItem(le)||""}catch{return""}}async initDev(e){if(this.initialized)return;this.baseUrl=`${Xe}${ke}`,this.gameId=e.gameId,this.isPreview=!0,this.http=new Y(this.baseUrl,"",!1,e.apiKey);let[t,n]=await Promise.all([this.fetchModels(),this.fetchPreviewSnapshot()]);this.models=t;let i=this.getSavedModelId();this.modelId=(i&&t.some(a=>a.id===i)?i:"")||t[0]?.id||"",this.conversationId="00000000-0000-0000-0000-000000000000",this.settingsSheet=new N({onModelChange:a=>this.handleLocalModelChange(a),onSettingsChange:()=>Promise.resolve(),onSync:()=>Promise.resolve()}),t.length>0&&this.settingsSheet.mount(t,this.modelId,{temperature:1,replyLength:"medium",replyLanguage:"zh-CN",playerNote:""},!1);let s=()=>this.gameId,r=()=>this.conversationId,l=()=>this.modelId,d=()=>this.models.find(a=>a.id===this.modelId)?.name;this.chat=new L(this.http,s,r,l,!0,void 0,()=>this.settingsSheet?.getSettings()??null,d),this.characters=new A(this.http,r,!0,n?.characters,n?.characterStates),this.relationships=new $(this.http,r,!0,n?.relationships),this.inventory=new U(this.http,r,!0,n?.inventory),this.world=new B(this.http,r,!0,n?.world),this.player=new H(this.http,r,!0,n?.player,n?.playerState),this.custom=new G(this.http,r,s,!0,n?.custom),this.save=new V(this.http,r,s,!0,n?.save_data),this.memory=new j(this.http,r,!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(s=>({id:s.id,name:s.name,url:s.url,assetType:s.asset_type,category:s.category}))}};async function Re(o){let e=new X;return o?.dev?await e.initDev(o.dev):await e.init(),e}function he(o){return typeof o=="object"&&o!==null&&"value"in o&&"type"in o&&(o.type==="number"||o.type==="text")}function Pe(o){return he(o)?o.value:o}0&&(module.exports={PROTOCOL_VERSION,StorviaBus,StorviaError,StorviaSDK,createStorviaSDK,envelope,extractFieldValue,isProtocolEnvelope,isRichFieldValue,setToastEnabled,showToast});
|
package/dist/index.d.mts
CHANGED
|
@@ -31,7 +31,7 @@ declare class HttpClient {
|
|
|
31
31
|
delete<T>(path: string): Promise<T>;
|
|
32
32
|
stream(path: string, body: unknown, onChunk: (text: string) => void, onDone: (id: string) => void, meta?: {
|
|
33
33
|
modelName?: string;
|
|
34
|
-
}, onState?: (delta: unknown, full: unknown) => void, onThinking?: (status: 'start' | 'end') => void): Promise<void>;
|
|
34
|
+
}, onState?: (delta: unknown, full: unknown) => void, onThinking?: (status: 'start' | 'end') => void, onCreatedCharacters?: (names: string[]) => void): Promise<void>;
|
|
35
35
|
/**
|
|
36
36
|
* 读取完整响应文本,解析为 JSON 并返回 `{ raw, data }`:
|
|
37
37
|
* - `raw` 是后端返回的整体(用于 debug 完整打印,含 success/code/message 等包装字段)
|
|
@@ -97,6 +97,13 @@ interface StateChanges {
|
|
|
97
97
|
type ChatStateCallback = (delta: StateChanges, full: State | null) => void;
|
|
98
98
|
/** 模型 reasoning 状态回调:'start' 表示开始思考,'end' 表示思考结束、开始输出正文 */
|
|
99
99
|
type ChatThinkingCallback = (status: 'start' | 'end') => void;
|
|
100
|
+
/**
|
|
101
|
+
* 新角色出场回调:本轮 AI 创造了之前从未出现过的「真·新角色」时触发。
|
|
102
|
+
* @param names 新角色名字数组(apply 后 current 里、apply 前 current∪dormant 都没有的);
|
|
103
|
+
* 不含休眠恢复 / 被限额挤进 dormant 的角色。作者可据此弹「新角色出现」提示卡片。
|
|
104
|
+
* 非流式调用通过 ChatResponse.createdNames 获取,无需此回调。
|
|
105
|
+
*/
|
|
106
|
+
type ChatCreatedCharactersCallback = (names: string[]) => void;
|
|
100
107
|
/**
|
|
101
108
|
* 流式 + 入库内容过滤规则。提供后,服务端只保留 AI 回复中
|
|
102
109
|
* `start..end` 之间的内容(多段会自动拼接),其余被丢弃。
|
|
@@ -126,6 +133,8 @@ interface ChatSendOptions {
|
|
|
126
133
|
onState?: ChatStateCallback;
|
|
127
134
|
/** 模型 reasoning 状态变更('start' = 开始思考,'end' = 开始输出正文);仅支持思考型模型 */
|
|
128
135
|
onThinking?: ChatThinkingCallback;
|
|
136
|
+
/** 本轮出现「真·新角色」时触发;非流式调用通过 ChatResponse.createdNames 获取,无需此回调 */
|
|
137
|
+
onCreatedCharacters?: ChatCreatedCharactersCallback;
|
|
129
138
|
}
|
|
130
139
|
interface ChatSaveOptions {
|
|
131
140
|
role: 'user' | 'assistant';
|
|
@@ -144,6 +153,8 @@ interface ChatGenerateOptions {
|
|
|
144
153
|
onState?: ChatStateCallback;
|
|
145
154
|
/** 模型 reasoning 状态变更('start' = 开始思考,'end' = 开始输出正文);仅支持思考型模型 */
|
|
146
155
|
onThinking?: ChatThinkingCallback;
|
|
156
|
+
/** 本轮出现「真·新角色」时触发;非流式调用通过 ChatResponse.createdNames 获取,无需此回调 */
|
|
157
|
+
onCreatedCharacters?: ChatCreatedCharactersCallback;
|
|
147
158
|
}
|
|
148
159
|
interface ChatRetryOptions {
|
|
149
160
|
topic?: string;
|
|
@@ -157,6 +168,8 @@ interface ChatRetryOptions {
|
|
|
157
168
|
onState?: ChatStateCallback;
|
|
158
169
|
/** 模型 reasoning 状态变更('start' = 开始思考,'end' = 开始输出正文);仅支持思考型模型 */
|
|
159
170
|
onThinking?: ChatThinkingCallback;
|
|
171
|
+
/** 本轮出现「真·新角色」时触发;非流式调用通过 ChatResponse.createdNames 获取,无需此回调 */
|
|
172
|
+
onCreatedCharacters?: ChatCreatedCharactersCallback;
|
|
160
173
|
}
|
|
161
174
|
interface ChatResponse {
|
|
162
175
|
id: string;
|
|
@@ -165,6 +178,8 @@ interface ChatResponse {
|
|
|
165
178
|
delta?: StateChanges;
|
|
166
179
|
/** 合并后的完整状态快照,仅在有变更时出现;结构同 storvia.state.get() */
|
|
167
180
|
full?: State;
|
|
181
|
+
/** 本轮出现的「真·新角色」名字数组,仅在有新角色时出现 */
|
|
182
|
+
createdNames?: string[];
|
|
168
183
|
}
|
|
169
184
|
interface ChatMessageCursor {
|
|
170
185
|
uuid: string;
|
|
@@ -591,10 +606,11 @@ interface CustomSetOptions {
|
|
|
591
606
|
declare class CustomModule {
|
|
592
607
|
private http;
|
|
593
608
|
private getConversationId;
|
|
609
|
+
private getGameId;
|
|
594
610
|
private isPreview;
|
|
595
611
|
private mem;
|
|
596
612
|
private memInject;
|
|
597
|
-
constructor(http: HttpClient, getConversationId: () => string, isPreview?: boolean, initialCustom?: Record<string, unknown>, initialInject?: Record<string, boolean>);
|
|
613
|
+
constructor(http: HttpClient, getConversationId: () => string, getGameId: () => string, isPreview?: boolean, initialCustom?: Record<string, unknown>, initialInject?: Record<string, boolean>);
|
|
598
614
|
/** 预览模式下重新灌入初始数据(previewConfig 变更时调用) */
|
|
599
615
|
setInitial(initialCustom: Record<string, unknown> | undefined, initialInject?: Record<string, boolean>): void;
|
|
600
616
|
get(): Promise<Record<string, unknown>>;
|
|
@@ -611,17 +627,19 @@ declare class CustomModule {
|
|
|
611
627
|
|
|
612
628
|
/**
|
|
613
629
|
* 游戏存档:作者自由读写的任意 JSON
|
|
614
|
-
* - 独立于 custom
|
|
630
|
+
* - 独立于 custom 的字段配额
|
|
615
631
|
* - 永不注入 AI 提示词,AI 完全感知不到
|
|
616
632
|
* - 整体覆写语义(增量更新需自行 get → 修改 → set)
|
|
617
|
-
* - 序列化后上限
|
|
633
|
+
* - 序列化后上限 256KB
|
|
634
|
+
* - 小组件场景下自动隔离到自己的沙盒(不污染主线、不撞其他小组件)
|
|
618
635
|
*/
|
|
619
636
|
declare class SaveModule {
|
|
620
637
|
private http;
|
|
621
638
|
private getConversationId;
|
|
639
|
+
private getGameId;
|
|
622
640
|
private isPreview;
|
|
623
641
|
private mem;
|
|
624
|
-
constructor(http: HttpClient, getConversationId: () => string, isPreview?: boolean, initial?: Record<string, unknown>);
|
|
642
|
+
constructor(http: HttpClient, getConversationId: () => string, getGameId: () => string, isPreview?: boolean, initial?: Record<string, unknown>);
|
|
625
643
|
/** 预览模式下重新灌入初始数据(previewConfig 变更时调用) */
|
|
626
644
|
setInitial(initial: Record<string, unknown> | undefined): void;
|
|
627
645
|
get(): Promise<Record<string, unknown>>;
|
|
@@ -704,6 +722,12 @@ declare class StorviaSDK {
|
|
|
704
722
|
* 否则 SDK 会一直用旧 token 请求被服务端 401。
|
|
705
723
|
*/
|
|
706
724
|
private listenForTokenUpdate;
|
|
725
|
+
/**
|
|
726
|
+
* 用户在 SDK 内置选择器里切换模型时统一入口:
|
|
727
|
+
* 更新内部 modelId,并把选择回传给宿主(主站/App),实现双向同步与持久化。
|
|
728
|
+
* dev 模式没有 bus(无父页面),此时仅更新本地。
|
|
729
|
+
*/
|
|
730
|
+
private handleLocalModelChange;
|
|
707
731
|
/** 监听父页面发来的预览模式动态更新(envelope 'config-update' / 'set-model') */
|
|
708
732
|
private listenForPreviewMessages;
|
|
709
733
|
/**
|
|
@@ -827,7 +851,7 @@ interface AckPayload {
|
|
|
827
851
|
error?: string;
|
|
828
852
|
}
|
|
829
853
|
type DownstreamMsg = ProtocolEnvelope<'init', InitPayload> | ProtocolEnvelope<'preview-init', PreviewInitPayload> | ProtocolEnvelope<'token-update', TokenUpdatePayload> | ProtocolEnvelope<'config-update', ConfigUpdatePayload> | ProtocolEnvelope<'set-model', SetModelPayload> | ProtocolEnvelope<'orientation', OrientationPayload> | ProtocolEnvelope<'ack', AckPayload>;
|
|
830
|
-
type UpstreamMsg = ProtocolEnvelope<'ready', ReadyPayload> | ProtocolEnvelope<'exit', Record<string, never>> | ProtocolEnvelope<'request-orientation', OrientationPayload> | ProtocolEnvelope<'error', SdkErrorPayload> | ProtocolEnvelope<'navigate', NavigatePayload> | ProtocolEnvelope<'ack', AckPayload>;
|
|
854
|
+
type UpstreamMsg = ProtocolEnvelope<'ready', ReadyPayload> | ProtocolEnvelope<'exit', Record<string, never>> | ProtocolEnvelope<'request-orientation', OrientationPayload> | ProtocolEnvelope<'error', SdkErrorPayload> | ProtocolEnvelope<'navigate', NavigatePayload> | ProtocolEnvelope<'model-change', SetModelPayload> | ProtocolEnvelope<'ack', AckPayload>;
|
|
831
855
|
declare function isProtocolEnvelope(data: unknown): data is ProtocolEnvelope<string, unknown>;
|
|
832
856
|
declare function envelope<T extends string, P>(type: T, payload: P, opts?: {
|
|
833
857
|
id?: string;
|